@@ -7,7 +7,7 @@ use smol_str::SmolStr;
77use crate :: {
88 check_type_compact,
99 db_index:: { DbIndex , LuaOperatorMetaMethod , LuaType } ,
10- LuaInferCache , TypeOps ,
10+ get_real_type , LuaInferCache , TypeOps ,
1111} ;
1212
1313use super :: { get_custom_type_operator, infer_expr, InferFailReason , InferResult } ;
@@ -21,18 +21,29 @@ pub fn infer_binary_expr(
2121 let ( left, right) = expr. get_exprs ( ) . ok_or ( InferFailReason :: None ) ?;
2222 let left_type = infer_expr ( db, cache, left. clone ( ) ) ?;
2323 let right_type = infer_expr ( db, cache, right. clone ( ) ) ?;
24+ let real_left_type = get_real_type ( db, & left_type) ;
25+ let real_right_type = get_real_type ( db, & right_type) ;
26+ let left_type_ref = real_left_type. unwrap_or ( & left_type) ;
27+ let right_type_ref = real_right_type. unwrap_or ( & right_type) ;
2428
2529 if op == BinaryOperator :: OpOr {
26- if let Some ( ty) = special_or_rule ( db, & left_type , & right_type , left, right) {
30+ if let Some ( ty) = special_or_rule ( db, left_type_ref , right_type_ref , left, right) {
2731 return Ok ( ty) ;
2832 }
2933 } else if !matches ! ( op, BinaryOperator :: OpAnd | BinaryOperator :: OpOr ) {
30- if let Some ( ty) = infer_union_binary_expr ( db, op, & left_type , & right_type ) {
34+ if let Some ( ty) = infer_union_binary_expr ( db, op, left_type_ref , right_type_ref ) {
3135 return Ok ( ty) ;
3236 }
3337 }
3438
35- infer_binary_expr_type ( db, left_type, right_type, op)
39+ match ( real_left_type. is_some ( ) , real_right_type. is_some ( ) ) {
40+ ( false , false ) => infer_binary_expr_type ( db, left_type, right_type, op) ,
41+ ( true , false ) => infer_binary_expr_type ( db, left_type_ref. clone ( ) , right_type, op) ,
42+ ( false , true ) => infer_binary_expr_type ( db, left_type, right_type_ref. clone ( ) , op) ,
43+ ( true , true ) => {
44+ infer_binary_expr_type ( db, left_type_ref. clone ( ) , right_type_ref. clone ( ) , op)
45+ }
46+ }
3647}
3748
3849fn infer_union_binary_expr (
@@ -52,11 +63,14 @@ fn infer_union_binary_expr(
5263 let mut result = LuaType :: Unknown ;
5364 let types = u. get_types ( ) ;
5465 for ty in types. iter ( ) {
55- if let Ok ( ty) = if is_left_union {
66+ // 只在实际调用时才 clone,而不是预先 clone
67+ let ty_result = if is_left_union {
5668 infer_binary_expr_type ( db, ty. clone ( ) , other. clone ( ) , op)
5769 } else {
5870 infer_binary_expr_type ( db, other. clone ( ) , ty. clone ( ) , op)
59- } {
71+ } ;
72+
73+ if let Ok ( ty) = ty_result {
6074 result = TypeOps :: Union . apply ( db, & result, & ty) ;
6175 }
6276 }
@@ -101,22 +115,26 @@ fn infer_binary_custom_operator(
101115 right : & LuaType ,
102116 op : LuaOperatorMetaMethod ,
103117) -> InferResult {
104- let operators = get_custom_type_operator ( db, left. clone ( ) , op) ;
105- if let Some ( operators) = operators {
106- for operator in operators {
107- let operand = operator. get_operand ( db) ;
108- if check_type_compact ( db, & operand, right) . is_ok ( ) {
109- return operator. get_result ( db) ;
118+ // 先检查 left 是否是自定义类型,避免不必要的 clone
119+ if left. is_custom_type ( ) {
120+ if let Some ( operators) = get_custom_type_operator ( db, left. clone ( ) , op) {
121+ for operator in operators {
122+ let operand = operator. get_operand ( db) ;
123+ if check_type_compact ( db, & operand, right) . is_ok ( ) {
124+ return operator. get_result ( db) ;
125+ }
110126 }
111127 }
112128 }
113129
114- let operators = get_custom_type_operator ( db, right. clone ( ) , op) ;
115- if let Some ( operators) = operators {
116- for operator in operators {
117- let operand = operator. get_operand ( db) ;
118- if check_type_compact ( db, & operand, left) . is_ok ( ) {
119- return operator. get_result ( db) ;
130+ // 再检查 right 是否是自定义类型,只在需要时 clone
131+ if right. is_custom_type ( ) {
132+ if let Some ( operators) = get_custom_type_operator ( db, right. clone ( ) , op) {
133+ for operator in operators {
134+ let operand = operator. get_operand ( db) ;
135+ if check_type_compact ( db, & operand, left) . is_ok ( ) {
136+ return operator. get_result ( db) ;
137+ }
120138 }
121139 }
122140 }
0 commit comments