Skip to content

Commit 6bb21f7

Browse files
committed
generic match will decay const type
1 parent 55399c1 commit 6bb21f7

File tree

9 files changed

+58
-7
lines changed

9 files changed

+58
-7
lines changed

crates/emmylua_code_analysis/resources/std/builtin.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@
123123
--- built-in type for Rawget
124124
---@alias std.Rawget<T, K> unknown
125125

126+
---
127+
--- built-in type for generic template, for match integer const and true/false
128+
---@alias std.ConstTpl<T> unknown
129+
126130
--- compact luals
127131

128132
---@alias type std.type
@@ -132,3 +136,4 @@
132136
---@alias metatable std.metatable
133137

134138
---@alias TypeGuard<T> boolean
139+

crates/emmylua_code_analysis/resources/std/global.lua

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ function rawequal(v1, v2) end
271271
--- must be a table; `index` may be any value.
272272
---@generic T, K
273273
---@param table T
274-
---@param index K
274+
---@param index std.ConstTpl<K>
275275
---@return std.RawGet<T, K>
276276
function rawget(table, index) end
277277

@@ -332,7 +332,7 @@ function require(modname) end
332332
--- Otherwise, `index` must be the string "#", and `select` returns
333333
--- the total number of extra arguments it received.
334334
---@generic T, Num: integer | '#'
335-
---@param index Num
335+
---@param index std.ConstTpl<Num>
336336
---@param ... T...
337337
---@return std.Select<T..., Num>
338338
function select(index, ...) end
@@ -451,8 +451,8 @@ function xpcall(f, msgh, ...) end
451451

452452
---@version 5.1, JIT
453453
---@generic T, Start: integer, End: integer
454-
---@param i? Start
455-
---@param j? End
454+
---@param i? std.ConstTpl<Start>
455+
---@param j? std.ConstTpl<End>
456456
---@param list T
457457
---@return std.Unpack<T, Start, End>
458458
function unpack(list, i, j) end

crates/emmylua_code_analysis/resources/std/table.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ function table.sort(list, comp) end
108108
--- return `list[i]`, `list[i+1]`, `···`, `list[j]`
109109
--- By default, i is 1 and j is #list.
110110
---@generic T, Start: integer, End: integer
111-
---@param i? Start
112-
---@param j? End
111+
---@param i? std.ConstTpl<Start>
112+
---@param j? std.ConstTpl<End>
113113
---@param list T
114114
---@return std.Unpack<T, Start, End>
115115
function table.unpack(list, i, j) end

crates/emmylua_code_analysis/src/compilation/analyzer/doc/infer_type.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,13 @@ fn infer_special_generic_type(
310310

311311
return Some(LuaType::TypeGuard(first_param.into()));
312312
}
313+
"std.ConstTpl" => {
314+
let first_doc_param_type = generic_type.get_generic_types()?.get_types().next()?;
315+
let first_param = infer_type(analyzer, first_doc_param_type);
316+
if let LuaType::TplRef(tpl) = first_param {
317+
return Some(LuaType::ConstTplRef(tpl));
318+
}
319+
}
313320
_ => {}
314321
}
315322

crates/emmylua_code_analysis/src/compilation/test/array_test.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,24 @@ mod test {
3030
"#,
3131
));
3232
}
33+
34+
#[test]
35+
fn test_create_array() {
36+
let mut ws = VirtualWorkspace::new();
37+
ws.def(
38+
r#"
39+
---@generic T
40+
---@param ... T
41+
---@return T[]
42+
local function new_array(...)
43+
end
44+
45+
t = new_array(1, 2, 3, 4, 5)
46+
"#,
47+
);
48+
49+
let t = ws.expr_ty("t");
50+
let t_expected = ws.ty("integer[]");
51+
assert_eq!(t, t_expected)
52+
}
3353
}

crates/emmylua_code_analysis/src/db_index/type/types.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pub enum LuaType {
6060
Call(Arc<LuaAliasCallType>),
6161
MultiLineUnion(Arc<LuaMultiLineUnion>),
6262
TypeGuard(Arc<LuaType>),
63+
ConstTplRef(Arc<GenericTpl>),
6364
}
6465

6566
impl PartialEq for LuaType {
@@ -107,6 +108,7 @@ impl PartialEq for LuaType {
107108
(LuaType::MultiLineUnion(a), LuaType::MultiLineUnion(b)) => a == b,
108109
(LuaType::TypeGuard(a), LuaType::TypeGuard(b)) => a == b,
109110
(LuaType::Never, LuaType::Never) => true,
111+
(LuaType::ConstTplRef(a), LuaType::ConstTplRef(b)) => a == b,
110112
_ => false, // 不同变体之间不相等
111113
}
112114
}
@@ -183,6 +185,7 @@ impl Hash for LuaType {
183185
(44, ptr).hash(state)
184186
}
185187
LuaType::Never => 45.hash(state),
188+
LuaType::ConstTplRef(a) => (46, a).hash(state),
186189
}
187190
}
188191
}

crates/emmylua_code_analysis/src/semantic/generic/tpl_pattern.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ fn tpl_pattern_match(
132132

133133
match pattern {
134134
LuaType::TplRef(tpl) => {
135+
if tpl.get_tpl_id().is_func() {
136+
substitutor.insert_type(tpl.get_tpl_id(), constant_decay(target));
137+
}
138+
}
139+
LuaType::ConstTplRef(tpl) => {
135140
if tpl.get_tpl_id().is_func() {
136141
substitutor.insert_type(tpl.get_tpl_id(), target);
137142
}
@@ -179,6 +184,16 @@ fn tpl_pattern_match(
179184
Ok(())
180185
}
181186

187+
fn constant_decay(typ: LuaType) -> LuaType {
188+
match &typ {
189+
LuaType::FloatConst(_) => LuaType::Number,
190+
LuaType::DocIntegerConst(_) | LuaType::IntegerConst(_) => LuaType::Integer,
191+
LuaType::DocStringConst(_) | LuaType::StringConst(_) => LuaType::String,
192+
LuaType::DocBooleanConst(_) | LuaType::BooleanConst(_) => LuaType::Boolean,
193+
_ => typ,
194+
}
195+
}
196+
182197
fn object_tpl_pattern_match(
183198
db: &DbIndex,
184199
cache: &mut LuaInferCache,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ fn check_general_type_compact(
6666
| LuaType::DocBooleanConst(_)
6767
| LuaType::TplRef(_)
6868
| LuaType::StrTplRef(_)
69+
| LuaType::ConstTplRef(_)
6970
| LuaType::Namespace(_)
7071
| LuaType::Variadic(_) => check_simple_type_compact(db, source, compact_type, check_guard),
7172

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ pub fn check_simple_type_compact(
204204
return Ok(());
205205
}
206206
}
207-
LuaType::TplRef(_) => return Ok(()),
207+
LuaType::TplRef(_) | LuaType::ConstTplRef(_) => return Ok(()),
208208
LuaType::Namespace(source_namespace) => {
209209
if let LuaType::Namespace(compact_namespace) = compact_type {
210210
if source_namespace == compact_namespace {

0 commit comments

Comments
 (0)