Skip to content

Commit 29b2090

Browse files
author
efve.zff
committed
fix: handle intersection type in undefined-field check, to avoid false positives on index access like values[1] for types such as Tuple & Object
1 parent 48ff02c commit 29b2090

2 files changed

Lines changed: 48 additions & 0 deletions

File tree

crates/emmylua_code_analysis/src/diagnostic/checker/check_field.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ fn is_invalid_prefix_type(typ: &LuaType) -> bool {
116116
LuaType::Instance(instance_typ) => {
117117
current_typ = instance_typ.get_base();
118118
}
119+
LuaType::Intersection(intersection) => {
120+
return intersection.get_types().iter().any(is_invalid_prefix_type);
121+
}
119122
_ => return false,
120123
}
121124
}
@@ -141,6 +144,25 @@ pub(super) fn is_valid_member(
141144
return None;
142145
}
143146
}
147+
LuaType::Intersection(intersection) => {
148+
// If any component of the intersection would pass the member check on its own,
149+
// the intersection should also pass (e.g. unknown[] & { n: integer }).
150+
for component in intersection.get_types() {
151+
if is_valid_member(semantic_model, component, index_expr, index_key, code).is_some()
152+
{
153+
return Some(());
154+
}
155+
}
156+
// Even if no single component passes the early checks, the intersection's
157+
// member lookup may still succeed (e.g. Tuple([Unknown]) & Object).
158+
// Try inferring the index expression type directly.
159+
if semantic_model
160+
.get_index_decl_type(index_expr.clone())
161+
.is_some()
162+
{
163+
return Some(());
164+
}
165+
}
144166
_ => {}
145167
}
146168

crates/emmylua_code_analysis/src/diagnostic/test/undefined_field_test.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,4 +818,30 @@ mod test {
818818
"#
819819
));
820820
}
821+
822+
#[test]
823+
fn test_intersection_array_index_access() {
824+
let mut ws = VirtualWorkspace::new_with_init_std_lib();
825+
826+
// Accessing [1] on an intersection type containing an array should not report undefined-field
827+
assert!(ws.check_code_for(
828+
DiagnosticCode::UndefinedField,
829+
r#"
830+
function test(...)
831+
local values = table.pack(...)
832+
local e = values[1]
833+
end
834+
"#
835+
));
836+
837+
// Explicit intersection type annotation
838+
assert!(ws.check_code_for(
839+
DiagnosticCode::UndefinedField,
840+
r#"
841+
---@type integer[] & { n: integer }
842+
local values
843+
local e = values[1]
844+
"#
845+
));
846+
}
821847
}

0 commit comments

Comments
 (0)