From e2eddfc0c217c2fc84c5f43bd55c73e2971df699 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 30 Jan 2026 13:56:13 +0000 Subject: [PATCH] fix(flow): narrow to assigned function signatures treat signature targets as compatible when source is function-typed --- .../src/compilation/test/flow.rs | 21 +++++++++++++++++++ .../semantic/infer/narrow/narrow_type/mod.rs | 7 +++++++ 2 files changed, 28 insertions(+) diff --git a/crates/emmylua_code_analysis/src/compilation/test/flow.rs b/crates/emmylua_code_analysis/src/compilation/test/flow.rs index a5f068d79..336a44413 100644 --- a/crates/emmylua_code_analysis/src/compilation/test/flow.rs +++ b/crates/emmylua_code_analysis/src/compilation/test/flow.rs @@ -258,6 +258,27 @@ print(a.field) )); } + #[test] + fn test_doc_function_assignment_narrowing() { + let mut ws = VirtualWorkspace::new(); + + let code = r#" + local i --- @type integer|fun():string + i = function() end + _ = i() + A = i + "#; + + ws.def(code); + + assert!(ws.check_code_for(DiagnosticCode::CallNonCallable, code)); + assert!(ws.check_code_for(DiagnosticCode::NeedCheckNil, code)); + + let a = ws.expr_ty("A"); + let a_desc = ws.humanize_type_detailed(a); + assert_eq!(a_desc, "fun()"); + } + #[test] fn test_issue_224() { let mut ws = VirtualWorkspace::new(); diff --git a/crates/emmylua_code_analysis/src/semantic/infer/narrow/narrow_type/mod.rs b/crates/emmylua_code_analysis/src/semantic/infer/narrow/narrow_type/mod.rs index 15a719325..88872141a 100644 --- a/crates/emmylua_code_analysis/src/semantic/infer/narrow/narrow_type/mod.rs +++ b/crates/emmylua_code_analysis/src/semantic/infer/narrow/narrow_type/mod.rs @@ -4,6 +4,7 @@ use crate::{DbIndex, LuaType, TypeOps, get_real_type, semantic::type_check::is_s pub use false_or_nil_type::{narrow_false_or_nil, remove_false_or_nil}; // need to be optimized +// `source` is the current/antecedent type, `target` is the narrowing candidate (e.g. assignment RHS). pub fn narrow_down_type(db: &DbIndex, source: LuaType, target: LuaType) -> Option { if source == target { return Some(source); @@ -73,6 +74,12 @@ pub fn narrow_down_type(db: &DbIndex, source: LuaType, target: LuaType) -> Optio return Some(source); } } + LuaType::Signature(_) => { + if real_source_ref.is_function() { + // Prefer the assigned closure signature, even when the antecedent is a doc function. + return Some(target.clone()); + } + } LuaType::Thread => { if real_source_ref.is_thread() { return Some(source);