@@ -31,7 +31,6 @@ use cairo_lang_syntax::node::kind::SyntaxKind;
31
31
use cairo_lang_syntax:: node:: { Terminal , TypedStablePtr , TypedSyntaxNode , ast} ;
32
32
use cairo_lang_utils as utils;
33
33
use cairo_lang_utils:: ordered_hash_map:: { Entry , OrderedHashMap } ;
34
- use cairo_lang_utils:: ordered_hash_set:: OrderedHashSet ;
35
34
use cairo_lang_utils:: unordered_hash_map:: UnorderedHashMap ;
36
35
use cairo_lang_utils:: unordered_hash_set:: UnorderedHashSet ;
37
36
use cairo_lang_utils:: { Intern , LookupIntern , OptionHelper , extract_matches, try_extract_matches} ;
@@ -51,9 +50,9 @@ use super::pattern::{
51
50
PatternOtherwise , PatternTuple , PatternVariable ,
52
51
} ;
53
52
use crate :: corelib:: {
54
- CoreTraitContext , core_binary_operator, core_bool_ty, core_unary_operator, deref_mut_trait ,
55
- deref_trait , false_literal_expr , get_core_trait, get_usize_ty, never_ty, numeric_literal_trait,
56
- true_literal_expr , try_get_core_ty_by_name, unit_expr, unit_ty, unwrap_error_propagation_type,
53
+ CoreTraitContext , core_binary_operator, core_bool_ty, core_unary_operator, false_literal_expr ,
54
+ get_core_trait, get_usize_ty, never_ty, numeric_literal_trait, true_literal_expr ,
55
+ try_get_core_ty_by_name, unit_expr, unit_ty, unwrap_error_propagation_type,
57
56
} ;
58
57
use crate :: db:: SemanticGroup ;
59
58
use crate :: diagnostic:: SemanticDiagnosticKind :: { self , * } ;
@@ -3040,12 +3039,13 @@ fn get_enriched_type_member_access(
3040
3039
accessed_member_name : & str ,
3041
3040
) -> Maybe < Option < EnrichedTypeMemberAccess > > {
3042
3041
let ( _, mut long_ty) = peel_snapshots ( ctx. db , expr. ty ( ) ) ;
3043
- if matches ! ( long_ty , TypeLongId :: Var ( _ ) ) {
3044
- // Save some work. ignore the result. The error, if any, will be reported later.
3045
- ctx . resolver . inference ( ) . solve ( ) . ok ( ) ;
3046
- long_ty = ctx. resolver . inference ( ) . rewrite ( long_ty ) . no_err ( ) ;
3047
- }
3042
+ // Run solver to get as much info on the type as possible.
3043
+ // Ignore the result of the `solve()` call - the error, if any, will be
3044
+ // reported later.
3045
+ ctx. resolver . inference ( ) . solve ( ) . ok ( ) ;
3046
+ ctx . resolver . inference ( ) . internal_rewrite ( & mut long_ty ) . no_err ( ) ;
3048
3047
let ( _, long_ty) = peel_snapshots_ex ( ctx. db , long_ty) ;
3048
+ let ty = long_ty. clone ( ) . intern ( ctx. db ) ;
3049
3049
let base_var = match & expr. expr {
3050
3050
Expr :: Var ( expr_var) => Some ( expr_var. var ) ,
3051
3051
Expr :: MemberAccess ( ExprMemberAccess { member_path : Some ( member_path) , .. } ) => {
@@ -3056,15 +3056,14 @@ fn get_enriched_type_member_access(
3056
3056
let is_mut_var = base_var
3057
3057
. filter ( |var_id| matches ! ( ctx. semantic_defs. get( var_id) , Some ( var) if var. is_mut( ) ) )
3058
3058
. is_some ( ) ;
3059
- let ty = long_ty. clone ( ) . intern ( ctx. db ) ;
3060
3059
let key = ( ty, is_mut_var) ;
3061
3060
let mut enriched_members = match ctx. resolver . type_enriched_members . entry ( key) {
3062
3061
Entry :: Occupied ( entry) => {
3063
3062
let e = entry. get ( ) ;
3064
3063
match e. get_member ( accessed_member_name) {
3065
3064
Some ( value) => return Ok ( Some ( value) ) ,
3066
3065
None => {
3067
- if e. exploration_tail . is_none ( ) {
3066
+ if e. exploration_done {
3068
3067
// There's no further exploration to be done, and member was not found.
3069
3068
return Ok ( None ) ;
3070
3069
}
@@ -3088,10 +3087,10 @@ fn get_enriched_type_member_access(
3088
3087
} else {
3089
3088
Default :: default ( )
3090
3089
} ;
3091
- EnrichedMembers { members, deref_functions : vec ! [ ] , exploration_tail : Some ( expr . id ) }
3090
+ EnrichedMembers { members, deref_functions : vec ! [ ] , exploration_done : false }
3092
3091
}
3093
3092
} ;
3094
- enrich_members ( ctx, & mut enriched_members, is_mut_var, stable_ptr, accessed_member_name) ?;
3093
+ enrich_members ( ctx, & mut enriched_members, ty , is_mut_var, stable_ptr, accessed_member_name) ?;
3095
3094
let e = ctx. resolver . type_enriched_members . entry ( key) . or_insert ( enriched_members) ;
3096
3095
Ok ( e. get_member ( accessed_member_name) )
3097
3096
}
@@ -3103,66 +3102,25 @@ fn get_enriched_type_member_access(
3103
3102
fn enrich_members (
3104
3103
ctx : & mut ComputationContext < ' _ > ,
3105
3104
enriched_members : & mut EnrichedMembers ,
3105
+ ty : TypeId ,
3106
3106
is_mut_var : bool ,
3107
3107
stable_ptr : ast:: ExprPtr ,
3108
3108
accessed_member_name : & str ,
3109
3109
) -> Maybe < ( ) > {
3110
- let EnrichedMembers { members : enriched, deref_functions, exploration_tail } = enriched_members;
3111
- let mut visited_types: OrderedHashSet < TypeId > = OrderedHashSet :: default ( ) ;
3112
-
3113
- let expr_id =
3114
- exploration_tail. expect ( "`enrich_members` should be called with a `calc_tail` value." ) ;
3115
- let mut expr = ExprAndId { expr : ctx. arenas . exprs [ expr_id] . clone ( ) , id : expr_id } ;
3116
-
3117
- let deref_mut_trait_id = deref_mut_trait ( ctx. db ) ;
3118
- let deref_trait_id = deref_trait ( ctx. db ) ;
3119
-
3120
- let compute_deref_method_function_call_data =
3121
- |ctx : & mut ComputationContext < ' _ > , expr : ExprAndId , use_deref_mut : bool | {
3122
- let deref_trait = if use_deref_mut { deref_mut_trait_id } else { deref_trait_id } ;
3123
- compute_method_function_call_data (
3124
- ctx,
3125
- & [ deref_trait] ,
3126
- if use_deref_mut { "deref_mut" . into ( ) } else { "deref" . into ( ) } ,
3127
- expr. clone ( ) ,
3128
- stable_ptr. 0 ,
3129
- None ,
3130
- |_, _, _| None ,
3131
- |_, _, _| None ,
3132
- )
3133
- } ;
3134
-
3135
- // If the variable is mutable, and implements DerefMut, we use DerefMut in the first iteration.
3136
- let mut use_deref_mut = deref_functions. is_empty ( )
3137
- && is_mut_var
3138
- && compute_deref_method_function_call_data ( ctx, expr. clone ( ) , true ) . is_ok ( ) ;
3110
+ let EnrichedMembers { members : enriched, deref_functions, exploration_done } = enriched_members;
3139
3111
3140
- // This function either finds a member and sets `exploration_tail` or finishes the exploration
3141
- // and leaves that exploration tail as `None`.
3142
- * exploration_tail = None ;
3112
+ let deref_chain = ctx. db . deref_chain ( ty, is_mut_var) ?;
3143
3113
3144
3114
// Add members of derefed types.
3145
- while let Ok ( ( function_id, _, cur_expr, mutability) ) =
3146
- compute_deref_method_function_call_data ( ctx, expr, use_deref_mut)
3147
- {
3148
- deref_functions. push ( ( function_id, mutability) ) ;
3149
- use_deref_mut = false ;
3115
+ for deref_info in deref_chain. derefs . iter ( ) . skip ( deref_functions. len ( ) ) . cloned ( ) {
3116
+ deref_functions. push ( ( deref_info. function_id , deref_info. self_mutability ) ) ;
3150
3117
let n_deref = deref_functions. len ( ) ;
3151
- expr = cur_expr;
3152
- let derefed_expr = expr_function_call (
3153
- ctx,
3154
- function_id,
3155
- vec ! [ NamedArg ( expr, None , mutability) ] ,
3156
- stable_ptr,
3157
- stable_ptr,
3158
- ) ?;
3159
- let ty = ctx. reduce_ty ( derefed_expr. ty ( ) ) ;
3160
- let ( _, long_ty) = finalized_snapshot_peeled_ty ( ctx, ty, stable_ptr) ?;
3118
+
3119
+ let ( _, long_ty) = finalized_snapshot_peeled_ty ( ctx, deref_info. target_ty , stable_ptr) ?;
3161
3120
// If the type is still a variable we stop looking for derefed members.
3162
3121
if let TypeLongId :: Var ( _) = long_ty {
3163
3122
break ;
3164
3123
}
3165
- expr = ExprAndId { expr : derefed_expr. clone ( ) , id : ctx. arenas . exprs . alloc ( derefed_expr) } ;
3166
3124
if let TypeLongId :: Concrete ( ConcreteTypeId :: Struct ( concrete_struct_id) ) = long_ty {
3167
3125
let members = ctx. db . concrete_struct_members ( concrete_struct_id) ?;
3168
3126
for ( member_name, member) in members. iter ( ) {
@@ -3171,17 +3129,12 @@ fn enrich_members(
3171
3129
}
3172
3130
// If member is contained we can stop the calculation post the lookup.
3173
3131
if members. contains_key ( accessed_member_name) {
3174
- // Found member, so exploration isn't done - setting up the tail.
3175
- * exploration_tail = Some ( expr. id ) ;
3176
- break ;
3132
+ // Found member, so exploration isn't done.
3133
+ return Ok ( ( ) ) ;
3177
3134
}
3178
3135
}
3179
- if !visited_types. insert ( long_ty. intern ( ctx. db ) ) {
3180
- // Break if we have a cycle. A diagnostic will be reported from the impl and not from
3181
- // member access.
3182
- break ;
3183
- }
3184
3136
}
3137
+ * exploration_done = true ;
3185
3138
Ok ( ( ) )
3186
3139
}
3187
3140
0 commit comments