Skip to content

Commit e916ea1

Browse files
committed
移除 ...: T 默认解析为 Tuple
1 parent f9275cf commit e916ea1

File tree

6 files changed

+39
-113
lines changed

6 files changed

+39
-113
lines changed

crates/emmylua_code_analysis/src/compilation/test/generic_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ mod test {
416416
417417
---@generic T
418418
---@param ... T...
419-
---@return UnwrapUnion<T>...
419+
---@return UnwrapUnion<[T...]>
420420
function unwrap(...) end
421421
"#,
422422
);

crates/emmylua_code_analysis/src/semantic/generic/instantiate_func_generic.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use emmylua_parser::{LuaAstNode, LuaCallExpr, LuaExpr};
44
use internment::ArcIntern;
55

66
use crate::{
7-
GenericTpl, GenericTplId, LuaFunctionType, LuaGenericType, LuaTupleStatus, LuaTupleType,
8-
TypeVisitTrait,
7+
GenericTpl, GenericTplId, LuaFunctionType, LuaGenericType, TypeVisitTrait,
98
db_index::{DbIndex, LuaType},
109
semantic::{
1110
LuaInferCache,
@@ -116,10 +115,6 @@ pub fn instantiate_func_generic(
116115
let arg_type = infer_expr(db, context.cache, arg_expr.clone())?;
117116
arg_types.push(constant_decay(arg_type));
118117
}
119-
// 剩余参数应该推断为元组类型
120-
arg_types = vec![LuaType::Tuple(
121-
LuaTupleType::new(arg_types, LuaTupleStatus::InferResolve).into(),
122-
)];
123118
variadic_tpl_pattern_match(&mut context, variadic, &arg_types)?;
124119
break;
125120
}
@@ -149,7 +144,6 @@ pub fn instantiate_func_generic(
149144
if contain_self && let Some(self_type) = infer_self_type(db, cache, &call_expr) {
150145
substitutor.add_self_type(self_type);
151146
}
152-
153147
if let LuaType::DocFunction(f) = instantiate_doc_function(db, func, &substitutor) {
154148
Ok(f.deref().clone())
155149
} else {

crates/emmylua_code_analysis/src/semantic/generic/instantiate_special_generic.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -134,29 +134,36 @@ fn instantiate_select_call(source: &LuaType, index: &LuaType) -> LuaType {
134134
_ => return LuaType::Unknown,
135135
};
136136

137+
let multi_return = if let LuaType::Variadic(multi) = source {
138+
multi.deref()
139+
} else {
140+
&VariadicType::Base(source.clone())
141+
};
142+
137143
match num_or_len {
138-
NumOrLen::Num(i) => match source {
139-
LuaType::Tuple(tuple) => {
140-
if let Some(first) = tuple.get_type(0) {
141-
if first.is_variadic() {
142-
return first.clone();
143-
}
144-
}
145-
// 返回元组中从 i 开始的所有类型
146-
let mut types = Vec::new();
147-
for ty in tuple.get_types().iter().skip(i as usize - 1) {
148-
types.push(ty.clone());
144+
NumOrLen::Num(i) => match multi_return {
145+
VariadicType::Base(_) => LuaType::Variadic(multi_return.clone().into()),
146+
VariadicType::Multi(_) => {
147+
let Some(total_len) = multi_return.get_min_len() else {
148+
return source.clone();
149+
};
150+
151+
let start = if i < 0 { total_len as i64 + i } else { i - 1 };
152+
if start < 0 || start >= (total_len as i64) {
153+
return source.clone();
149154
}
150155

151-
LuaType::Tuple(LuaTupleType::new(types, LuaTupleStatus::InferResolve).into())
156+
let multi = multi_return.get_new_variadic_from(start as usize);
157+
LuaType::Variadic(multi.into())
152158
}
153-
_ => LuaType::Unknown,
154159
},
155160
NumOrLen::Len => {
156-
if let LuaType::Tuple(tuple) = source {
157-
return LuaType::IntegerConst(tuple.get_types().len() as i64);
161+
let len = multi_return.get_min_len();
162+
if let Some(len) = len {
163+
LuaType::IntegerConst(len as i64)
164+
} else {
165+
LuaType::Integer
158166
}
159-
LuaType::Integer
160167
}
161168
NumOrLen::LenUnknown => LuaType::Integer,
162169
}

crates/emmylua_code_analysis/src/semantic/generic/instantiate_type_generic.rs

Lines changed: 5 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -153,14 +153,6 @@ pub fn instantiate_doc_function(
153153
new_params.push((param_name, Some(typ.clone())));
154154
}
155155
}
156-
// 剩余参数会被压制成元组, 我们需要展开他
157-
SubstitutorValue::Type(LuaType::Tuple(tuple)) => {
158-
for (i, typ) in tuple.get_types().iter().enumerate() {
159-
let param_name = format!("args_{}", i);
160-
new_params.push((param_name, Some(typ.clone())));
161-
}
162-
continue;
163-
}
164156
_ => {
165157
new_params.push((
166158
"...".to_string(),
@@ -196,71 +188,7 @@ pub fn instantiate_doc_function(
196188
// 将 substitutor 中存储的类型的 def 转为 ref
197189
let mut modified_substitutor = substitutor.clone();
198190
modified_substitutor.convert_def_to_ref();
199-
let mut inst_ret_type = instantiate_type_generic(db, tpl_ret, &modified_substitutor);
200-
// 如果返回值可变的, 且对应的实例化对应值是 tuple, 那么我们将其展开
201-
// TODO: 现在的实现过于复杂, 我们应该预处理可变参数
202-
match (tpl_ret, &inst_ret_type) {
203-
(LuaType::Variadic(tpl_ret), LuaType::Variadic(inst_ret)) => {
204-
match (tpl_ret.deref(), inst_ret.deref()) {
205-
(VariadicType::Base(tpl_base), VariadicType::Base(inst_base)) => {
206-
if tpl_base.is_variadic()
207-
&& let LuaType::Tuple(inst_tuple) = inst_base
208-
{
209-
inst_ret_type = LuaType::Variadic(
210-
VariadicType::Multi(inst_tuple.get_types().to_vec()).into(),
211-
);
212-
}
213-
}
214-
(VariadicType::Multi(tpl_multi), VariadicType::Multi(inst_multi)) => {
215-
let tpl_last = tpl_multi.last().unwrap_or(&LuaType::Unknown);
216-
let inst_last = inst_multi.last().unwrap_or(&LuaType::Unknown);
217-
if tpl_last.is_variadic()
218-
&& let LuaType::Tuple(inst_tuple) = inst_last
219-
{
220-
let mut new_types = Vec::new();
221-
for ty in inst_multi {
222-
new_types.push(ty.clone());
223-
}
224-
new_types.pop();
225-
new_types.extend_from_slice(inst_tuple.get_types());
226-
inst_ret_type = LuaType::Variadic(VariadicType::Multi(new_types).into());
227-
}
228-
}
229-
_ => {}
230-
}
231-
}
232-
(LuaType::Variadic(tpl_ret), LuaType::Tuple(inst_tuple)) => {
233-
if let VariadicType::Base(_) = tpl_ret.deref() {
234-
let mut new_types = Vec::new();
235-
new_types.extend_from_slice(inst_tuple.get_types());
236-
inst_ret_type = LuaType::Variadic(VariadicType::Multi(new_types).into());
237-
}
238-
}
239-
(_, LuaType::Variadic(inst_ret)) => {
240-
if let VariadicType::Base(base) = inst_ret.deref() {
241-
if let LuaType::Tuple(tuple) = base {
242-
match tuple.len() {
243-
0 => inst_ret_type = LuaType::Unknown,
244-
1 => inst_ret_type = tuple.get_types()[0].clone(),
245-
_ => {
246-
inst_ret_type = LuaType::Variadic(
247-
VariadicType::Multi(tuple.get_types().to_vec()).into(),
248-
)
249-
}
250-
}
251-
}
252-
}
253-
}
254-
(_, LuaType::Tuple(tuple)) => match tuple.len() {
255-
0 => inst_ret_type = LuaType::Unknown,
256-
1 => inst_ret_type = tuple.get_types()[0].clone(),
257-
_ => {
258-
inst_ret_type =
259-
LuaType::Variadic(VariadicType::Multi(tuple.get_types().to_vec()).into())
260-
}
261-
},
262-
_ => {}
263-
}
191+
let inst_ret_type = instantiate_type_generic(db, tpl_ret, &modified_substitutor);
264192
LuaType::DocFunction(
265193
LuaFunctionType::new(async_state, colon_define, new_params, inst_ret_type).into(),
266194
)
@@ -849,9 +777,10 @@ fn instantiate_mapped_type(
849777
if !fields.is_empty() || !index_access.is_empty() {
850778
if constraint.is_tuple() {
851779
let types = fields.into_iter().map(|(_, ty)| ty).collect();
852-
return LuaType::Tuple(
853-
LuaTupleType::new(types, LuaTupleStatus::InferResolve).into(),
854-
);
780+
return LuaType::Variadic(VariadicType::Multi(types).into());
781+
// return LuaType::Tuple(
782+
// LuaTupleType::new(types, LuaTupleStatus::InferResolve).into(),
783+
// );
855784
}
856785
let field_map: HashMap<LuaMemberKey, LuaType> = fields.into_iter().collect();
857786
return LuaType::Object(LuaObjectType::new_with_fields(field_map, index_access).into());

crates/emmylua_code_analysis/src/semantic/generic/test.rs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,7 @@ mod test {
3232

3333
#[test]
3434
fn test_select_type() {
35-
let mut ws = crate::VirtualWorkspace::new();
36-
ws.def(
37-
r#"
38-
---@alias std.Select<T, StartOrLen> unknown
39-
---@alias std.ConstTpl<T> unknown
40-
41-
---@generic T, Num: integer | '#'
42-
---@param index std.ConstTpl<Num>
43-
---@param ... T...
44-
---@return std.Select<T..., Num>
45-
function select(index, ...) end
46-
"#,
47-
);
35+
let mut ws = crate::VirtualWorkspace::new_with_init_std_lib();
4836
ws.def(
4937
r#"
5038
---@param ... string

crates/emmylua_parser/src/grammar/doc/test.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3147,4 +3147,12 @@ Syntax(Chunk)@0..110
31473147
"#;
31483148
assert_ast_eq!(code, result);
31493149
}
3150+
3151+
#[test]
3152+
fn test_alias_conditional_infer_dots() {
3153+
let code = r#"
3154+
---@alias ConstructorParameters<T> T extends (fun(infer: infer P): any) and P... or unknown
3155+
"#;
3156+
print_ast(code);
3157+
}
31503158
}

0 commit comments

Comments
 (0)