@@ -41,9 +41,10 @@ use hir_def::{
41
41
resolver:: { HasResolver , ResolveValueResult , Resolver , TypeNs , ValueNs } ,
42
42
type_ref:: TypeRef ,
43
43
AdtId , AssocItemId , DefWithBodyId , EnumVariantId , FieldId , FunctionId , ItemContainerId , Lookup ,
44
- TraitId , TypeAliasId , VariantId ,
44
+ TraitId , TupleFieldId , TupleId , TypeAliasId , VariantId ,
45
45
} ;
46
46
use hir_expand:: name:: { name, Name } ;
47
+ use indexmap:: IndexSet ;
47
48
use la_arena:: { ArenaMap , Entry } ;
48
49
use rustc_hash:: { FxHashMap , FxHashSet } ;
49
50
use stdx:: { always, never} ;
@@ -403,11 +404,15 @@ pub struct InferenceResult {
403
404
/// For each method call expr, records the function it resolves to.
404
405
method_resolutions : FxHashMap < ExprId , ( FunctionId , Substitution ) > ,
405
406
/// 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 > > ,
407
408
/// For each struct literal or pattern, records the variant it resolves to.
408
409
variant_resolutions : FxHashMap < ExprOrPatId , VariantId > ,
409
410
/// For each associated item record what it resolves to
410
411
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 > ,
411
416
pub diagnostics : Vec < InferenceDiagnostic > ,
412
417
pub type_of_expr : ArenaMap < ExprId , Ty > ,
413
418
/// For each pattern record the type it resolves to.
@@ -447,7 +452,7 @@ impl InferenceResult {
447
452
pub fn method_resolution ( & self , expr : ExprId ) -> Option < ( FunctionId , Substitution ) > {
448
453
self . method_resolutions . get ( & expr) . cloned ( )
449
454
}
450
- pub fn field_resolution ( & self , expr : ExprId ) -> Option < FieldId > {
455
+ pub fn field_resolution ( & self , expr : ExprId ) -> Option < Either < FieldId , TupleFieldId > > {
451
456
self . field_resolutions . get ( & expr) . copied ( )
452
457
}
453
458
pub fn variant_resolution_for_expr ( & self , id : ExprId ) -> Option < VariantId > {
@@ -517,6 +522,8 @@ pub(crate) struct InferenceContext<'a> {
517
522
/// The traits in scope, disregarding block modules. This is used for caching purposes.
518
523
traits_in_scope : FxHashSet < TraitId > ,
519
524
pub ( crate ) result : InferenceResult ,
525
+ tuple_field_accesses_rev :
526
+ IndexSet < Substitution , std:: hash:: BuildHasherDefault < rustc_hash:: FxHasher > > ,
520
527
/// The return type of the function being inferred, the closure or async block if we're
521
528
/// currently within one.
522
529
///
@@ -598,6 +605,7 @@ impl<'a> InferenceContext<'a> {
598
605
InferenceContext {
599
606
result : InferenceResult :: default ( ) ,
600
607
table : unify:: InferenceTable :: new ( db, trait_env) ,
608
+ tuple_field_accesses_rev : Default :: default ( ) ,
601
609
return_ty : TyKind :: Error . intern ( Interner ) , // set in collect_* calls
602
610
resume_yield_tys : None ,
603
611
return_coercion : None ,
@@ -621,7 +629,13 @@ impl<'a> InferenceContext<'a> {
621
629
// used this function for another workaround, mention it here. If you really need this function and believe that
622
630
// there is no problem in it being `pub(crate)`, remove this comment.
623
631
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 ;
625
639
// Destructure every single field so whenever new fields are added to `InferenceResult` we
626
640
// don't forget to handle them here.
627
641
let InferenceResult {
@@ -645,6 +659,7 @@ impl<'a> InferenceContext<'a> {
645
659
// to resolve them here.
646
660
closure_info : _,
647
661
mutated_bindings_in_closure : _,
662
+ tuple_field_access_types : _,
648
663
} = & mut result;
649
664
650
665
table. fallback_if_possible ( ) ;
@@ -720,6 +735,11 @@ impl<'a> InferenceContext<'a> {
720
735
for adjustment in pat_adjustments. values_mut ( ) . flatten ( ) {
721
736
* adjustment = table. resolve_completely ( adjustment. clone ( ) ) ;
722
737
}
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 ( ) ;
723
743
result
724
744
}
725
745
0 commit comments