diff --git a/crates/emmylua_code_analysis/src/diagnostic/checker/check_field.rs b/crates/emmylua_code_analysis/src/diagnostic/checker/check_field.rs index 47d22a516..df25bc6ad 100644 --- a/crates/emmylua_code_analysis/src/diagnostic/checker/check_field.rs +++ b/crates/emmylua_code_analysis/src/diagnostic/checker/check_field.rs @@ -274,6 +274,8 @@ pub(super) fn is_valid_member( } } else if typ.is_integer() && key_types.iter().any(|typ| typ.is_integer()) { return Some(()); + } else if key_types.iter().any(|kt| kt == typ) { + return Some(()); } } LuaMemberKey::Name(_) => { @@ -378,6 +380,9 @@ fn get_key_types(db: &DbIndex, typ: &LuaType) -> HashSet { LuaType::DocStringConst(_) | LuaType::DocIntegerConst(_) => { type_set.insert(current_type); } + LuaType::Boolean | LuaType::Thread | LuaType::Number | LuaType::Userdata => { + type_set.insert(current_type); + } LuaType::Call(alias_call) => { if let Some(key_types) = get_keyof_keys(db, alias_call) { for t in key_types { diff --git a/crates/emmylua_code_analysis/src/diagnostic/test/undefined_field_test.rs b/crates/emmylua_code_analysis/src/diagnostic/test/undefined_field_test.rs index cfefece06..b380f6d2d 100644 --- a/crates/emmylua_code_analysis/src/diagnostic/test/undefined_field_test.rs +++ b/crates/emmylua_code_analysis/src/diagnostic/test/undefined_field_test.rs @@ -900,4 +900,48 @@ mod test { assert_eq!(ws.expr_ty("alias_result"), ws.ty("string?")); assert_eq!(ws.expr_ty("numeric_result"), ws.ty("string?")); } + + #[test] + fn test_table_generic_value_with_thread_key() { + let mut ws = VirtualWorkspace::new(); + assert!(ws.has_no_diagnostic( + DiagnosticCode::UndefinedField, + r#" + ---@class Box + ---@field value T + + ---@class Container + ---@field items table?> + local Container = {} + + ---@param co thread + function Container:get(co) + local item = self.items[co] + return item + end + "# + )); + } + + #[test] + fn test_table_generic_value_with_boolean_key() { + let mut ws = VirtualWorkspace::new(); + assert!(ws.has_no_diagnostic( + DiagnosticCode::UndefinedField, + r#" + ---@class Box + ---@field value T + + ---@class Container + ---@field items table?> + local Container = {} + + ---@param key boolean + function Container:get(key) + local item = self.items[key] + return item + end + "# + )); + } }