diff --git a/crates/emmylua_code_analysis/src/diagnostic/test/generic_constraint_mismatch_test.rs b/crates/emmylua_code_analysis/src/diagnostic/test/generic_constraint_mismatch_test.rs index 055a48e4e..1e85409b1 100644 --- a/crates/emmylua_code_analysis/src/diagnostic/test/generic_constraint_mismatch_test.rs +++ b/crates/emmylua_code_analysis/src/diagnostic/test/generic_constraint_mismatch_test.rs @@ -300,6 +300,47 @@ mod test { )); } + #[test] + fn test_object_constraint_with_class_duck_typing() { + let mut ws = VirtualWorkspace::new(); + // A @class whose inferred Def type (e.g. from `return self`) should satisfy + // an object constraint via structural duck typing, same as Ref types do. + assert!(ws.check_code_for( + DiagnosticCode::GenericConstraintMismatch, + r#" + ---@class MyPos + ---@field x number + ---@field y number + ---@field z number + ---@overload fun(x: number, y: number, z: number): MyPos + MyPos = {} + MyPos.__index = MyPos + + setmetatable(MyPos, { + __call = function(x, y, z) + return setmetatable({ x = x, y = y, z = z }, MyPos) + end + }) + + function MyPos:next() + self.x = self.x + 1 + self.y = self.y + 1 + return self + end + + ---@generic T: { x: number, y: number, z: number } + ---@param pos T + local function getTile(pos) end + + local p = MyPos(0, 0, 0):next() + getTile(p) + + local p2 = MyPos(1, 1, 1) + getTile(p2:next()) + "# + )); + } + #[test] fn test_generic_keyof_param_scope() { let mut ws = VirtualWorkspace::new(); diff --git a/crates/emmylua_code_analysis/src/semantic/type_check/complex_type/object_type_check.rs b/crates/emmylua_code_analysis/src/semantic/type_check/complex_type/object_type_check.rs index 371c017b5..d1184b52b 100644 --- a/crates/emmylua_code_analysis/src/semantic/type_check/complex_type/object_type_check.rs +++ b/crates/emmylua_code_analysis/src/semantic/type_check/complex_type/object_type_check.rs @@ -35,7 +35,7 @@ pub fn check_object_type_compact( check_guard.next_level()?, ); } - LuaType::Ref(type_id) => { + LuaType::Ref(type_id) | LuaType::Def(type_id) => { return check_object_type_compact_type_ref( context, source_object,