@@ -41,9 +41,10 @@ use hir_def::{
4141 resolver:: { HasResolver , ResolveValueResult , Resolver , TypeNs , ValueNs } ,
4242 type_ref:: TypeRef ,
4343 AdtId , AssocItemId , DefWithBodyId , EnumVariantId , FieldId , FunctionId , ItemContainerId , Lookup ,
44- TraitId , TypeAliasId , VariantId ,
44+ TraitId , TupleFieldId , TupleId , TypeAliasId , VariantId ,
4545} ;
4646use hir_expand:: name:: { name, Name } ;
47+ use indexmap:: IndexSet ;
4748use la_arena:: { ArenaMap , Entry } ;
4849use rustc_hash:: { FxHashMap , FxHashSet } ;
4950use stdx:: { always, never} ;
@@ -403,11 +404,15 @@ pub struct InferenceResult {
403404 /// For each method call expr, records the function it resolves to.
404405 method_resolutions : FxHashMap < ExprId , ( FunctionId , Substitution ) > ,
405406 /// For each field access expr, records the field it resolves to.
406- field_resolutions : FxHashMap < ExprId , FieldId > ,
407+ field_resolutions : FxHashMap < ExprId , Either < FieldId , TupleFieldId > > ,
407408 /// For each struct literal or pattern, records the variant it resolves to.
408409 variant_resolutions : FxHashMap < ExprOrPatId , VariantId > ,
409410 /// For each associated item record what it resolves to
410411 assoc_resolutions : FxHashMap < ExprOrPatId , ( AssocItemId , Substitution ) > ,
412+ /// Whenever a tuple field expression access a tuple field, we allocate a tuple id in
413+ /// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of
414+ /// that which allows us to resolve a [`TupleFieldId`]s type.
415+ pub tuple_field_access_types : FxHashMap < TupleId , Substitution > ,
411416 pub diagnostics : Vec < InferenceDiagnostic > ,
412417 pub type_of_expr : ArenaMap < ExprId , Ty > ,
413418 /// For each pattern record the type it resolves to.
@@ -447,7 +452,7 @@ impl InferenceResult {
447452 pub fn method_resolution ( & self , expr : ExprId ) -> Option < ( FunctionId , Substitution ) > {
448453 self . method_resolutions . get ( & expr) . cloned ( )
449454 }
450- pub fn field_resolution ( & self , expr : ExprId ) -> Option < FieldId > {
455+ pub fn field_resolution ( & self , expr : ExprId ) -> Option < Either < FieldId , TupleFieldId > > {
451456 self . field_resolutions . get ( & expr) . copied ( )
452457 }
453458 pub fn variant_resolution_for_expr ( & self , id : ExprId ) -> Option < VariantId > {
@@ -517,6 +522,8 @@ pub(crate) struct InferenceContext<'a> {
517522 /// The traits in scope, disregarding block modules. This is used for caching purposes.
518523 traits_in_scope : FxHashSet < TraitId > ,
519524 pub ( crate ) result : InferenceResult ,
525+ tuple_field_accesses_rev :
526+ IndexSet < Substitution , std:: hash:: BuildHasherDefault < rustc_hash:: FxHasher > > ,
520527 /// The return type of the function being inferred, the closure or async block if we're
521528 /// currently within one.
522529 ///
@@ -598,6 +605,7 @@ impl<'a> InferenceContext<'a> {
598605 InferenceContext {
599606 result : InferenceResult :: default ( ) ,
600607 table : unify:: InferenceTable :: new ( db, trait_env) ,
608+ tuple_field_accesses_rev : Default :: default ( ) ,
601609 return_ty : TyKind :: Error . intern ( Interner ) , // set in collect_* calls
602610 resume_yield_tys : None ,
603611 return_coercion : None ,
@@ -621,7 +629,13 @@ impl<'a> InferenceContext<'a> {
621629 // used this function for another workaround, mention it here. If you really need this function and believe that
622630 // there is no problem in it being `pub(crate)`, remove this comment.
623631 pub ( crate ) fn resolve_all ( self ) -> InferenceResult {
624- let InferenceContext { mut table, mut result, deferred_cast_checks, .. } = self ;
632+ let InferenceContext {
633+ mut table,
634+ mut result,
635+ deferred_cast_checks,
636+ tuple_field_accesses_rev,
637+ ..
638+ } = self ;
625639 // Destructure every single field so whenever new fields are added to `InferenceResult` we
626640 // don't forget to handle them here.
627641 let InferenceResult {
@@ -645,6 +659,7 @@ impl<'a> InferenceContext<'a> {
645659 // to resolve them here.
646660 closure_info : _,
647661 mutated_bindings_in_closure : _,
662+ tuple_field_access_types : _,
648663 } = & mut result;
649664
650665 table. fallback_if_possible ( ) ;
@@ -720,6 +735,11 @@ impl<'a> InferenceContext<'a> {
720735 for adjustment in pat_adjustments. values_mut ( ) . flatten ( ) {
721736 * adjustment = table. resolve_completely ( adjustment. clone ( ) ) ;
722737 }
738+ result. tuple_field_access_types = tuple_field_accesses_rev
739+ . into_iter ( )
740+ . enumerate ( )
741+ . map ( |( idx, subst) | ( TupleId ( idx as u32 ) , table. resolve_completely ( subst. clone ( ) ) ) )
742+ . collect ( ) ;
723743 result
724744 }
725745
0 commit comments