@@ -3760,35 +3760,48 @@ fn try_extract_identifier_from_path<'a>(
37603760 }
37613761}
37623762
3763- /// Given an expression syntax, if it's an identifier, returns it. Otherwise, returns the proper
3764- /// error.
3765- fn expr_as_identifier < ' db > (
3766- ctx : & mut ComputationContext < ' db , ' _ > ,
3767- path : & ast:: ExprPath < ' db > ,
3768- db : & ' db dyn Database ,
3769- ) -> Maybe < SmolStrId < ' db > > {
3770- let segments_var = path. segments ( db) ;
3771- let mut segments = segments_var. elements ( db) ;
3772- if segments. len ( ) == 1 {
3773- Ok ( segments. next ( ) . unwrap ( ) . identifier ( db) )
3774- } else {
3775- Err ( ctx. diagnostics . report ( path. stable_ptr ( db) , InvalidMemberExpression ) )
3776- }
3777- }
3778-
3779- // TODO(spapini): Consider moving some checks here to the responsibility of the parser.
37803763/// Computes the semantic expression for a dot expression.
37813764fn dot_expr < ' db > (
37823765 ctx : & mut ComputationContext < ' db , ' _ > ,
37833766 lexpr : ExprAndId < ' db > ,
37843767 rhs_syntax : ast:: Expr < ' db > ,
37853768 stable_ptr : ast:: ExprPtr < ' db > ,
37863769) -> Maybe < Expr < ' db > > {
3787- // Find MemberId.
3788- match rhs_syntax {
3789- ast:: Expr :: Path ( expr) => member_access_expr ( ctx, lexpr, expr, stable_ptr) ,
3790- ast:: Expr :: FunctionCall ( expr) => method_call_expr ( ctx, lexpr, expr, stable_ptr) ,
3791- _ => Err ( ctx. diagnostics . report ( rhs_syntax. stable_ptr ( ctx. db ) , InvalidMemberExpression ) ) ,
3770+ if let Some ( member_name) = match rhs_syntax {
3771+ ast:: Expr :: FunctionCall ( expr) => return method_call_expr ( ctx, lexpr, expr, stable_ptr) ,
3772+ ast:: Expr :: Path ( ref expr) => path_as_identifier ( ctx. db , & expr) ,
3773+ ast:: Expr :: Literal ( ref literal) => literal_as_identifier ( ctx. db , & literal) ,
3774+ _ => None ,
3775+ } {
3776+ member_access_expr_by_name (
3777+ ctx,
3778+ lexpr,
3779+ member_name,
3780+ rhs_syntax. stable_ptr ( ctx. db ) . untyped ( ) ,
3781+ stable_ptr,
3782+ )
3783+ } else {
3784+ Err ( ctx. diagnostics . report ( rhs_syntax. stable_ptr ( ctx. db ) , InvalidMemberExpression ) )
3785+ }
3786+ }
3787+
3788+ /// Given a path syntax, return it as an identifier if possible, otherwise, return None.
3789+ fn path_as_identifier < ' db > (
3790+ db : & ' db dyn Database ,
3791+ path : & ast:: ExprPath < ' db > ,
3792+ ) -> Option < SmolStrId < ' db > > {
3793+ Some ( path. segments ( db) . elements ( db) . exactly_one ( ) . ok ( ) ?. identifier ( db) )
3794+ }
3795+
3796+ /// Given a literal syntax, return it as an identifier if possible, otherwise, return None.
3797+ fn literal_as_identifier < ' db > (
3798+ db : & ' db dyn Database ,
3799+ literal : & ast:: TerminalLiteralNumber < ' db > ,
3800+ ) -> Option < SmolStrId < ' db > > {
3801+ if let ( value, None ) = literal. numeric_value_and_suffix ( db) ? {
3802+ Some ( SmolStrId :: from ( db, value. to_usize ( ) ?. to_string ( ) ) )
3803+ } else {
3804+ None
37923805 }
37933806}
37943807
@@ -3933,55 +3946,46 @@ fn method_call_expr<'db>(
39333946 expr_function_call ( ctx, function_id, named_args, expr. stable_ptr ( db) , stable_ptr)
39343947}
39353948
3936- /// Computes the semantic model of a member access expression (e.g. "expr. member") .
3937- fn member_access_expr < ' db > (
3949+ /// Computes the semantic model of a member access expression for a given member name .
3950+ fn member_access_expr_by_name < ' db > (
39383951 ctx : & mut ComputationContext < ' db , ' _ > ,
39393952 lexpr : ExprAndId < ' db > ,
3940- rhs_syntax : ast:: ExprPath < ' db > ,
3953+ member_name : SmolStrId < ' db > ,
3954+ name_stable_ptr : SyntaxStablePtrId < ' db > ,
39413955 stable_ptr : ast:: ExprPtr < ' db > ,
39423956) -> Maybe < Expr < ' db > > {
39433957 let db = ctx. db ;
3944-
3945- // Find MemberId.
3946- let member_name = expr_as_identifier ( ctx, & rhs_syntax, db) ?;
3947- let ( n_snapshots, long_ty) =
3948- finalized_snapshot_peeled_ty ( ctx, lexpr. ty ( ) , rhs_syntax. stable_ptr ( db) ) ?;
3958+ let ( n_snapshots, long_ty) = finalized_snapshot_peeled_ty ( ctx, lexpr. ty ( ) , name_stable_ptr) ?;
39493959
39503960 match & long_ty {
39513961 TypeLongId :: Concrete ( _) | TypeLongId :: Tuple ( _) | TypeLongId :: FixedSizeArray { .. } => {
39523962 let Some ( EnrichedTypeMemberAccess { type_member, deref_functions } ) =
39533963 get_enriched_type_member_access ( ctx, lexpr. clone ( ) , stable_ptr, member_name) ?
39543964 else {
39553965 return Err ( ctx. diagnostics . report (
3956- rhs_syntax . stable_ptr ( db ) ,
3966+ name_stable_ptr ,
39573967 NoSuchTypeMember { ty : long_ty. intern ( ctx. db ) , member_name } ,
39583968 ) ) ;
39593969 } ;
3960- // TODO(#7608): handle TypeMemberKind::TupleElement here.
3961- let TypeMemberKind :: StructMember ( member_id) = type_member. kind else {
3962- return Err ( ctx. diagnostics . report ( rhs_syntax. stable_ptr ( db) , Unsupported ) ) ;
3963- } ;
3964- let member = semantic:: Member {
3965- id : member_id,
3966- ty : type_member. ty ,
3967- visibility : type_member. visibility ,
3968- } ;
3969- check_struct_member_is_visible (
3970- ctx,
3971- & member,
3972- rhs_syntax. stable_ptr ( db) . untyped ( ) ,
3973- member_name,
3974- ) ;
3975- let member_path = match & long_ty {
3976- TypeLongId :: Concrete ( ConcreteTypeId :: Struct ( concrete_struct_id) )
3977- if n_snapshots == 0 && deref_functions. is_empty ( ) =>
3978- {
3970+ if let TypeMemberKind :: StructMember ( member_id) = type_member. kind {
3971+ let member = semantic:: Member {
3972+ id : member_id,
3973+ ty : type_member. ty ,
3974+ visibility : type_member. visibility ,
3975+ } ;
3976+ check_struct_member_is_visible ( ctx, & member, name_stable_ptr, member_name) ;
3977+ }
3978+ let member_path = match ( & type_member. kind , & long_ty) {
3979+ (
3980+ TypeMemberKind :: StructMember ( member_id) ,
3981+ TypeLongId :: Concrete ( ConcreteTypeId :: Struct ( concrete_struct_id) ) ,
3982+ ) if n_snapshots == 0 && deref_functions. is_empty ( ) => {
39793983 lexpr. as_member_path ( ) . map ( |parent| ExprVarMemberPath :: Member {
39803984 parent : Box :: new ( parent) ,
3981- member_id : member . id ,
3985+ member_id : * member_id ,
39823986 stable_ptr,
39833987 concrete_struct_id : * concrete_struct_id,
3984- ty : member . ty ,
3988+ ty : type_member . ty ,
39853989 } )
39863990 }
39873991 _ => None ,
@@ -4000,19 +4004,12 @@ fn member_access_expr<'db>(
40004004 derefed_expr =
40014005 ExprAndId { expr : cur_expr. clone ( ) , id : ctx. arenas . exprs . alloc ( cur_expr) } ;
40024006 }
4003- let ( n_snapshots, long_ty) =
4004- finalized_snapshot_peeled_ty ( ctx, derefed_expr. ty ( ) , rhs_syntax. stable_ptr ( db) ) ?;
4005- let derefed_expr_concrete_struct_id = match long_ty {
4006- TypeLongId :: Concrete ( ConcreteTypeId :: Struct ( concrete_struct_id) ) => {
4007- concrete_struct_id
4008- }
4009- _ => unreachable ! ( ) ,
4010- } ;
4011- let ty = wrap_in_snapshots ( ctx. db , member. ty , n_snapshots) ;
4007+ let ( n_snapshots, _) =
4008+ finalized_snapshot_peeled_ty ( ctx, derefed_expr. ty ( ) , name_stable_ptr) ?;
4009+ let ty = wrap_in_snapshots ( ctx. db , type_member. ty , n_snapshots) ;
40124010 let mut final_expr = Expr :: MemberAccess ( ExprMemberAccess {
40134011 expr : derefed_expr. id ,
4014- concrete_struct_id : derefed_expr_concrete_struct_id,
4015- member : member. id ,
4012+ type_member,
40164013 ty,
40174014 member_path,
40184015 n_snapshots,
@@ -4031,20 +4028,15 @@ fn member_access_expr<'db>(
40314028 Ok ( final_expr)
40324029 }
40334030
4034- TypeLongId :: Snapshot ( _) => {
4035- // TODO(spapini): Handle snapshot members.
4036- Err ( ctx. diagnostics . report ( rhs_syntax. stable_ptr ( db) , Unsupported ) )
4037- }
4038- TypeLongId :: Closure ( _) => {
4039- Err ( ctx. diagnostics . report ( rhs_syntax. stable_ptr ( db) , Unsupported ) )
4040- }
4031+ TypeLongId :: Snapshot ( _) => Err ( ctx. diagnostics . report ( name_stable_ptr, Unsupported ) ) ,
4032+ TypeLongId :: Closure ( _) => Err ( ctx. diagnostics . report ( name_stable_ptr, Unsupported ) ) ,
40414033 TypeLongId :: Var ( _) => Err ( ctx. diagnostics . report (
4042- rhs_syntax . stable_ptr ( db ) ,
4034+ name_stable_ptr ,
40434035 InternalInferenceError ( InferenceError :: TypeNotInferred ( long_ty. intern ( ctx. db ) ) ) ,
40444036 ) ) ,
40454037 TypeLongId :: ImplType ( _) | TypeLongId :: GenericParameter ( _) | TypeLongId :: Coupon ( _) => {
40464038 Err ( ctx. diagnostics . report (
4047- rhs_syntax . stable_ptr ( db ) ,
4039+ name_stable_ptr ,
40484040 TypeHasNoMembers { ty : long_ty. intern ( ctx. db ) , member_name } ,
40494041 ) )
40504042 }
@@ -4090,18 +4082,19 @@ fn get_enriched_type_member_access<'db>(
40904082 }
40914083 Entry :: Vacant ( _) => {
40924084 let ( _, long_ty) = finalized_snapshot_peeled_ty ( ctx, ty, stable_ptr) ?;
4093- let members = if let Some ( type_members_map) = ctx. db . type_members ( long_ty. intern ( ctx. db ) ) ? {
4094- if let Some ( type_member) = type_members_map. get ( & accessed_member_name) {
4095- // Found direct member access - so directly returning it.
4096- return Ok ( Some ( EnrichedTypeMemberAccess {
4097- type_member : type_member. clone ( ) ,
4098- deref_functions : vec ! [ ] ,
4099- } ) ) ;
4100- }
4101- type_members_map. iter ( ) . map ( |( k, v) | ( * k, ( v. clone ( ) , 0 ) ) ) . collect ( )
4102- } else {
4103- Default :: default ( )
4104- } ;
4085+ let members =
4086+ if let Some ( type_members_map) = ctx. db . type_members ( long_ty. intern ( ctx. db ) ) ? {
4087+ if let Some ( type_member) = type_members_map. get ( & accessed_member_name) {
4088+ // Found direct member access - so directly returning it.
4089+ return Ok ( Some ( EnrichedTypeMemberAccess {
4090+ type_member : type_member. clone ( ) ,
4091+ deref_functions : vec ! [ ] ,
4092+ } ) ) ;
4093+ }
4094+ type_members_map. iter ( ) . map ( |( k, v) | ( * k, ( v. clone ( ) , 0 ) ) ) . collect ( )
4095+ } else {
4096+ Default :: default ( )
4097+ } ;
41054098
41064099 EnrichedMembers {
41074100 members,
0 commit comments