Skip to content

Commit a6ffe9c

Browse files
committed
调整泛型规范
1 parent 34d8afe commit a6ffe9c

File tree

3 files changed

+92
-2
lines changed

3 files changed

+92
-2
lines changed

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

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,4 +470,86 @@ mod test {
470470
"#,
471471
));
472472
}
473+
474+
#[test]
475+
fn test_variadic_base() {
476+
let mut ws = VirtualWorkspace::new();
477+
{
478+
ws.def(
479+
r#"
480+
---@generic T
481+
---@param ... T... # 所有传入参数合并为一个`可变序列`, 即(T1, T2, ...)
482+
---@return T # 返回可变序列
483+
function f1(...) end
484+
"#,
485+
);
486+
assert!(ws.check_code_for(
487+
DiagnosticCode::ParamTypeNotMatch,
488+
r#"
489+
A, B, C = f1(1, "2", true)
490+
"#,
491+
));
492+
assert_eq!(ws.expr_ty("A"), ws.ty("integer"));
493+
assert_eq!(ws.expr_ty("B"), ws.ty("string"));
494+
assert_eq!(ws.expr_ty("C"), ws.ty("boolean"));
495+
}
496+
{
497+
ws.def(
498+
r#"
499+
---@generic T
500+
---@param ... T...
501+
---@return T... # `...`的作用是转换类型为序列, 此时 T 为序列, 那么 T... = T
502+
function f2(...) end
503+
"#,
504+
);
505+
assert!(ws.check_code_for(
506+
DiagnosticCode::ParamTypeNotMatch,
507+
r#"
508+
D, E, F = f2(1, "2", true)
509+
"#,
510+
));
511+
assert_eq!(ws.expr_ty("D"), ws.ty("integer"));
512+
assert_eq!(ws.expr_ty("E"), ws.ty("string"));
513+
assert_eq!(ws.expr_ty("F"), ws.ty("boolean"));
514+
}
515+
516+
{
517+
ws.def(
518+
r#"
519+
---@generic T
520+
---@param ... T # T为单类型, `@param ... T`在语义上等同于 TS 的 T[]
521+
---@return T # 返回一个单类型
522+
function f3(...) end
523+
"#,
524+
);
525+
assert!(!ws.check_code_for(
526+
DiagnosticCode::ParamTypeNotMatch,
527+
r#"
528+
G, H = f3(1, "2")
529+
"#,
530+
));
531+
assert_eq!(ws.expr_ty("G"), ws.ty("integer"));
532+
assert_eq!(ws.expr_ty("H"), ws.ty("any"));
533+
}
534+
535+
{
536+
ws.def(
537+
r#"
538+
---@generic T
539+
---@param ... T # T为单类型
540+
---@return T... # 将单类型转为可变序列返回, 即返回了(T, T, T, ...)
541+
function f4(...) end
542+
"#,
543+
);
544+
assert!(!ws.check_code_for(
545+
DiagnosticCode::ParamTypeNotMatch,
546+
r#"
547+
I, J, K = f4(1, "2")
548+
"#,
549+
));
550+
assert_eq!(ws.expr_ty("I"), ws.ty("integer"));
551+
assert_eq!(ws.expr_ty("J"), ws.ty("integer"));
552+
assert_eq!(ws.expr_ty("K"), ws.ty("integer"));
553+
}
554+
}
473555
}

crates/emmylua_code_analysis/src/semantic/generic/instantiate_type/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,15 @@ fn instantiate_variadic_type(
424424
SubstitutorValue::None => {
425425
return LuaType::Never;
426426
}
427-
SubstitutorValue::Type(ty) => return ty.clone(),
427+
SubstitutorValue::Type(ty) => {
428+
if matches!(
429+
ty,
430+
LuaType::Nil | LuaType::Any | LuaType::Unknown | LuaType::Never
431+
) {
432+
return ty.clone();
433+
}
434+
return LuaType::Variadic(VariadicType::Base(ty.clone()).into());
435+
}
428436
SubstitutorValue::MultiTypes(types) => {
429437
return LuaType::Variadic(VariadicType::Multi(types.clone()).into());
430438
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ mod test {
2626
);
2727

2828
let ty = ws.expr_ty("async_create(locaf)");
29-
let expected = ws.ty("async fun(a: number, b: string, c:boolean): number");
29+
let expected = ws.ty("async fun(a: number, b: string, c:boolean): number...");
3030
assert_eq!(ty, expected);
3131
}
3232

0 commit comments

Comments
 (0)