Skip to content

Commit 95d5a7f

Browse files
committed
fix rebase && fix generic param type match
1 parent fced8b5 commit 95d5a7f

File tree

7 files changed

+79
-31
lines changed

7 files changed

+79
-31
lines changed

crates/emmylua_code_analysis/src/compilation/analyzer/lua/for_range_stat.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ pub fn infer_for_range_iter_expr_func(
155155
cache,
156156
substitutor: &mut substitutor,
157157
root: root,
158+
call_expr: None,
158159
};
159160
let params = doc_function
160161
.get_params()

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,33 @@ mod test {
6767
let expected = ws.ty("fun(b:string, c:table)");
6868
assert_eq!(bar_ty, expected);
6969
}
70+
71+
#[test]
72+
fn test_generic_params() {
73+
let mut ws = VirtualWorkspace::new();
74+
ws.def(
75+
r#"
76+
---@class Observable<T>
77+
---@class Subject<T>: Observable<T>
78+
79+
---@generic T
80+
---@param ... Observable<T>
81+
---@return Observable<T>
82+
function concat(...)
83+
end
84+
"#,
85+
);
86+
87+
ws.def(
88+
r#"
89+
---@type Subject<number>
90+
local s1
91+
A = concat(s1)
92+
"#,
93+
);
94+
95+
let a_ty = ws.expr_ty("A");
96+
let expected = ws.ty("Observable<number>");
97+
assert_eq!(a_ty, expected);
98+
}
7099
}

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

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{collections::HashSet, ops::Deref};
1+
use std::{collections::HashSet, ops::Deref, sync::Arc};
22

33
use emmylua_parser::{LuaAstNode, LuaCallExpr, LuaExpr};
44
use internment::ArcIntern;
@@ -17,7 +17,7 @@ use crate::{
1717
infer::InferFailReason,
1818
infer_expr, LuaInferCache,
1919
},
20-
LuaFunctionType, TypeVisitTrait,
20+
GenericTpl, GenericTplId, LuaFunctionType, LuaGenericType, TypeVisitTrait,
2121
};
2222

2323
use super::{instantiate_type_generic::instantiate_doc_function, TypeSubstitutor};
@@ -58,14 +58,15 @@ pub fn instantiate_func_generic(
5858
.get_args()
5959
.collect::<Vec<_>>();
6060
let mut substitutor = TypeSubstitutor::new();
61+
let mut context = TplContext {
62+
db,
63+
cache,
64+
substitutor: &mut substitutor,
65+
root: call_expr.get_root(),
66+
call_expr: Some(call_expr.clone()),
67+
};
6168
if !generic_tpls.is_empty() {
62-
substitutor.add_need_infer_tpls(generic_tpls);
63-
let mut context = TplContext {
64-
db,
65-
cache,
66-
substitutor: &mut substitutor,
67-
root: call_expr.get_root(),
68-
};
69+
context.substitutor.add_need_infer_tpls(generic_tpls);
6970

7071
let colon_call = call_expr.is_colon_call();
7172
let colon_define = func.is_colon_define();
@@ -141,9 +142,10 @@ pub fn instantiate_func_generic(
141142
}
142143
}
143144

144-
substitutor.set_call_expr(call_expr.clone());
145145
if contain_self {
146-
infer_self_type(db, cache, &call_expr, &mut substitutor)?;
146+
if let Some(self_type) = infer_self_type(db, cache, &call_expr) {
147+
substitutor.add_self_type(self_type);
148+
}
147149
}
148150

149151
if let LuaType::DocFunction(f) = instantiate_doc_function(db, func, &substitutor) {
@@ -153,7 +155,31 @@ pub fn instantiate_func_generic(
153155
}
154156
}
155157

156-
fn infer_self_type(
158+
pub fn build_self_type(db: &DbIndex, self_type: &LuaType) -> LuaType {
159+
match self_type {
160+
LuaType::Def(id) | LuaType::Ref(id) => {
161+
if let Some(generic) = db.get_type_index().get_generic_params(id) {
162+
let mut params = Vec::new();
163+
for (i, ty) in generic.iter().enumerate() {
164+
if let Some(t) = &ty.1 {
165+
params.push(t.clone());
166+
} else {
167+
params.push(LuaType::TplRef(Arc::new(GenericTpl::new(
168+
GenericTplId::Type(i as u32),
169+
ArcIntern::new(SmolStr::from(ty.0.clone())),
170+
))));
171+
}
172+
}
173+
let generic = LuaGenericType::new(id.clone(), params);
174+
return LuaType::Generic(Arc::new(generic));
175+
}
176+
}
177+
_ => {}
178+
};
179+
self_type.clone()
180+
}
181+
182+
pub fn infer_self_type(
157183
db: &DbIndex,
158184
cache: &mut LuaInferCache,
159185
call_expr: &LuaCallExpr,

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use emmylua_parser::LuaSyntaxNode;
1+
use emmylua_parser::{LuaCallExpr, LuaSyntaxNode};
22

33
use crate::{DbIndex, LuaInferCache, TypeSubstitutor};
44

@@ -8,4 +8,5 @@ pub struct TplContext<'a> {
88
pub cache: &'a mut LuaInferCache,
99
pub substitutor: &'a mut TypeSubstitutor,
1010
pub root: LuaSyntaxNode,
11+
pub call_expr: Option<LuaCallExpr>,
1112
}

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{
1212
semantic::{
1313
generic::{tpl_context::TplContext, type_substitutor::SubstitutorValue},
1414
member::{find_index_operations, get_member_map},
15+
type_check::is_sub_type_of,
1516
},
1617
InferFailReason, LuaFunctionType, LuaMemberInfo, LuaMemberKey, LuaMemberOwner, LuaObjectType,
1718
LuaSemanticDeclId, LuaTupleType, LuaUnionType, SemanticDeclLevel, VariadicType,
@@ -480,9 +481,10 @@ fn generic_tpl_pattern_match(
480481
) -> TplPatternMatchResult {
481482
match target {
482483
LuaType::Generic(target_generic) => {
483-
let base = generic.get_base_type();
484-
let target_base = target_generic.get_base_type();
485-
if target_base != base {
484+
let base = generic.get_base_type_id_ref();
485+
let target_base = target_generic.get_base_type_id_ref();
486+
487+
if !is_sub_type_of(context.db, &target_base, &base) {
486488
return Err(InferFailReason::None);
487489
}
488490

@@ -872,7 +874,7 @@ fn escape_alias(db: &DbIndex, may_alias: &LuaType) -> LuaType {
872874
}
873875

874876
fn is_pairs_call(context: &mut TplContext) -> Option<bool> {
875-
let call_expr = context.substitutor.get_call_expr()?;
877+
let call_expr = context.call_expr.as_ref()?;
876878
let prefix_expr = call_expr.get_prefix_expr()?;
877879
let semantic_decl = match prefix_expr.syntax().clone().into() {
878880
NodeOrToken::Node(node) => infer_node_semantic_decl(

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

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
use std::collections::{HashMap, HashSet};
22

3-
use emmylua_parser::LuaCallExpr;
4-
53
use crate::{GenericTplId, LuaType, LuaTypeDeclId};
64

75
#[derive(Debug, Clone)]
86
pub struct TypeSubstitutor {
97
tpl_replace_map: HashMap<GenericTplId, SubstitutorValue>,
108
alias_type_id: Option<LuaTypeDeclId>,
119
self_type: Option<LuaType>,
12-
call_expr: Option<LuaCallExpr>,
1310
}
1411

1512
impl TypeSubstitutor {
@@ -18,7 +15,6 @@ impl TypeSubstitutor {
1815
tpl_replace_map: HashMap::new(),
1916
alias_type_id: None,
2017
self_type: None,
21-
call_expr: None,
2218
}
2319
}
2420

@@ -31,7 +27,6 @@ impl TypeSubstitutor {
3127
tpl_replace_map,
3228
alias_type_id: None,
3329
self_type: None,
34-
call_expr: None,
3530
}
3631
}
3732

@@ -44,7 +39,6 @@ impl TypeSubstitutor {
4439
tpl_replace_map,
4540
alias_type_id: Some(alias_type_id),
4641
self_type: None,
47-
call_expr: None,
4842
}
4943
}
5044

@@ -148,14 +142,6 @@ impl TypeSubstitutor {
148142
}
149143
}
150144
}
151-
152-
pub fn set_call_expr(&mut self, call_expr: LuaCallExpr) {
153-
self.call_expr = Some(call_expr);
154-
}
155-
156-
pub fn get_call_expr(&self) -> Option<&LuaCallExpr> {
157-
self.call_expr.as_ref()
158-
}
159145
}
160146

161147
fn convert_type_def_to_ref(ty: &LuaType) -> LuaType {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ use std::collections::HashSet;
22

33
use crate::{DbIndex, LuaType, LuaTypeDeclId};
44

5+
/// 检查子类型关系.
6+
///
7+
/// 假设现在有一个类型定义`---@class C: A, B`, 那么`sub_type_ref_id`为`C`, `super_type_ref_id`可以为`A`或`B`.
58
pub fn is_sub_type_of(
69
db: &DbIndex,
710
sub_type_ref_id: &LuaTypeDeclId,

0 commit comments

Comments
 (0)