Skip to content

Commit 910ad35

Browse files
author
efve.zff
committed
test: add test cases for intersection type as table subtype and undefined-field access
1 parent 0f62fee commit 910ad35

2 files changed

Lines changed: 114 additions & 0 deletions

File tree

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
@@ -815,4 +815,30 @@ mod test {
815815
"#
816816
));
817817
}
818+
819+
#[test]
820+
fn test_intersection_array_index_access() {
821+
let mut ws = VirtualWorkspace::new_with_init_std_lib();
822+
823+
// Accessing [1] on an intersection type containing an array should not report undefined-field
824+
assert!(ws.check_code_for(
825+
DiagnosticCode::UndefinedField,
826+
r#"
827+
function test(...)
828+
local values = table.pack(...)
829+
local e = values[1]
830+
end
831+
"#
832+
));
833+
834+
// Explicit intersection type annotation
835+
assert!(ws.check_code_for(
836+
DiagnosticCode::UndefinedField,
837+
r#"
838+
---@type integer[] & { n: integer }
839+
local values
840+
local e = values[1]
841+
"#
842+
));
843+
}
818844
}

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

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,94 @@ mod test {
209209
));
210210
}
211211

212+
#[test]
213+
fn test_intersection_is_table_subtype() {
214+
let mut ws = VirtualWorkspace::new();
215+
216+
// [integer] & { n: integer } should be assignable to table
217+
let intersection_ty = ws.ty("integer[] & { n: integer }");
218+
let table_ty = ws.ty("table");
219+
assert!(
220+
ws.check_type(&table_ty, &intersection_ty),
221+
"integer[] & {{ n: integer }} should be a subtype of table"
222+
);
223+
224+
// Verify via diagnostic: passing intersection type to a table parameter should not error
225+
assert!(ws.check_code_for(
226+
DiagnosticCode::ParamTypeMismatch,
227+
r#"
228+
---@param t table
229+
local function foo(t) end
230+
231+
---@type integer[] & { n: integer }
232+
local packed
233+
foo(packed)
234+
"#
235+
));
236+
237+
// Also verify: assigning intersection to table should not error
238+
assert!(ws.check_code_for(
239+
DiagnosticCode::AssignTypeMismatch,
240+
r#"
241+
---@type integer[] & { n: integer }
242+
local packed
243+
244+
---@type table
245+
local t = packed
246+
"#
247+
));
248+
249+
// Intersection type should be assignable to an array type (non-generic)
250+
let array_ty = ws.ty("integer[]");
251+
assert!(
252+
ws.check_type(&array_ty, &intersection_ty),
253+
"integer[] & {{ n: integer }} should be assignable to integer[]"
254+
);
255+
256+
// Intersection type should be assignable to an array parameter (non-generic)
257+
assert!(ws.check_code_for(
258+
DiagnosticCode::ParamTypeMismatch,
259+
r#"
260+
---@param t integer[]
261+
local function foo2(t) end
262+
263+
---@type integer[] & { n: integer }
264+
local packed
265+
foo2(packed)
266+
"#
267+
));
268+
269+
// Intersection type should be assignable to a generic array parameter
270+
assert!(ws.check_code_for(
271+
DiagnosticCode::ParamTypeMismatch,
272+
r#"
273+
---@generic V
274+
---@param t V[]
275+
---@return fun(): integer, V
276+
local function my_ipairs(t) end
277+
278+
---@type integer[] & { n: integer }
279+
local packed
280+
my_ipairs(packed)
281+
"#
282+
));
283+
284+
// Intersection type should be assignable to table<int, V>
285+
assert!(ws.check_code_for(
286+
DiagnosticCode::ParamTypeMismatch,
287+
r#"
288+
---@generic V
289+
---@param t table<integer, V>
290+
---@return fun(): integer, V
291+
local function my_iter(t) end
292+
293+
---@type integer[] & { n: integer }
294+
local packed
295+
my_iter(packed)
296+
"#
297+
));
298+
}
299+
212300
#[test]
213301
fn test_set_index_expr_owner_prefers_declared_global_type() {
214302
let mut ws = VirtualWorkspace::new_with_init_std_lib();

0 commit comments

Comments
 (0)