Skip to content

Commit 98f0d50

Browse files
committed
fix infer generic
1 parent d7a7c56 commit 98f0d50

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ pub fn instantiate_func_generic(
7272
if !generic_tpls.is_empty() {
7373
context.substitutor.add_need_infer_tpls(generic_tpls);
7474

75-
// 判断是否指定了泛型
7675
if let Some(type_list) = call_expr.get_call_generic_type_list() {
76+
// 如果使用了`obj:abc--[[@<string>]]("abc")`强制指定了泛型, 那么我们只需要直接应用
7777
apply_call_generic_type_list(db, file_id, &mut context, &type_list);
7878
} else {
79-
// 没有指定泛型, 从调用参数中推断
79+
// 如果没有指定泛型, 则需要从调用参数中推断
8080
infer_generic_types_from_call(
8181
db,
8282
&mut context,
@@ -155,12 +155,16 @@ fn infer_generic_types_from_call(
155155
if !func_param_type.is_variadic()
156156
&& check_expr_can_later_infer(context, func_param_type, call_arg_expr)?
157157
{
158-
// If the argument cannot be inferred later, we will handle it later.
158+
// 如果参数不能被后续推断, 那么我们先不处理
159159
unresolve_tpls.push((func_param_type.clone(), call_arg_expr.clone()));
160160
continue;
161161
}
162162

163-
let arg_type = infer_expr(db, context.cache, call_arg_expr.clone())?;
163+
let arg_type = match infer_expr(db, context.cache, call_arg_expr.clone()) {
164+
Ok(t) => t,
165+
Err(InferFailReason::FieldNotFound) => LuaType::Nil, // 对于未找到的字段, 我们认为是 nil 以执行后续推断
166+
Err(e) => return Err(e),
167+
};
164168
match (func_param_type, &arg_type) {
165169
(LuaType::Variadic(variadic), _) => {
166170
let mut arg_types = vec![];

crates/emmylua_ls/src/handlers/test/completion_test.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2339,4 +2339,38 @@ mod tests {
23392339

23402340
Ok(())
23412341
}
2342+
2343+
#[gtest]
2344+
fn test_function_generic_value_is_nil() -> Result<()> {
2345+
let mut ws = ProviderVirtualWorkspace::new();
2346+
ws.def(
2347+
r#"
2348+
---@class Expect
2349+
---@overload fun<T>(actual: T): Assertion<T>
2350+
2351+
---@class Assertion<T>
2352+
---@field toBe fun(self: self)
2353+
2354+
---@type table
2355+
GTable = {}
2356+
"#,
2357+
);
2358+
2359+
check!(ws.check_completion_with_kind(
2360+
r#"
2361+
---@type Expect
2362+
local expect = {}
2363+
2364+
expect(GTable["a"]):<??>
2365+
"#,
2366+
vec![VirtualCompletionItem {
2367+
label: "toBe".to_string(),
2368+
kind: CompletionItemKind::FUNCTION,
2369+
label_detail: Some("()".to_string()),
2370+
},],
2371+
CompletionTriggerKind::TRIGGER_CHARACTER
2372+
));
2373+
2374+
Ok(())
2375+
}
23422376
}

0 commit comments

Comments
 (0)