@@ -2,14 +2,98 @@ use rustc_errors::ErrorReported;
22use rustc_hir:: def_id:: { DefId , LocalDefId } ;
33use rustc_infer:: infer:: TyCtxtInferExt ;
44use rustc_middle:: ty:: subst:: SubstsRef ;
5- use rustc_middle:: ty:: { self , Instance , TyCtxt , TypeFoldable } ;
5+ use rustc_middle:: ty:: { self , Binder , Instance , Ty , TyCtxt , TypeFoldable , TypeVisitor } ;
66use rustc_span:: { sym, DUMMY_SP } ;
77use rustc_target:: spec:: abi:: Abi ;
88use rustc_trait_selection:: traits;
99use traits:: { translate_substs, Reveal } ;
1010
11+ use rustc_data_structures:: sso:: SsoHashSet ;
12+ use std:: collections:: BTreeMap ;
13+ use std:: ops:: ControlFlow ;
14+
1115use tracing:: debug;
1216
17+ // FIXME(#86795): `BoundVarsCollector` here should **NOT** be used
18+ // outside of `resolve_associated_item`. It's just to address #64494,
19+ // #83765, and #85848 which are creating bound types/regions that lose
20+ // their `Binder` *unintentionally*.
21+ // It's ideal to remove `BoundVarsCollector` and just use
22+ // `ty::Binder::*` methods but we use this stopgap until we figure out
23+ // the "real" fix.
24+ struct BoundVarsCollector < ' tcx > {
25+ binder_index : ty:: DebruijnIndex ,
26+ vars : BTreeMap < u32 , ty:: BoundVariableKind > ,
27+ // We may encounter the same variable at different levels of binding, so
28+ // this can't just be `Ty`
29+ visited : SsoHashSet < ( ty:: DebruijnIndex , Ty < ' tcx > ) > ,
30+ }
31+
32+ impl < ' tcx > BoundVarsCollector < ' tcx > {
33+ fn new ( ) -> Self {
34+ BoundVarsCollector {
35+ binder_index : ty:: INNERMOST ,
36+ vars : BTreeMap :: new ( ) ,
37+ visited : SsoHashSet :: default ( ) ,
38+ }
39+ }
40+
41+ fn into_vars ( self , tcx : TyCtxt < ' tcx > ) -> & ' tcx ty:: List < ty:: BoundVariableKind > {
42+ let max = self . vars . iter ( ) . map ( |( k, _) | * k) . max ( ) . unwrap_or_else ( || 0 ) ;
43+ for i in 0 ..max {
44+ if let None = self . vars . get ( & i) {
45+ panic ! ( "Unknown variable: {:?}" , i) ;
46+ }
47+ }
48+
49+ tcx. mk_bound_variable_kinds ( self . vars . into_iter ( ) . map ( |( _, v) | v) )
50+ }
51+ }
52+
53+ impl < ' tcx > TypeVisitor < ' tcx > for BoundVarsCollector < ' tcx > {
54+ type BreakTy = ( ) ;
55+
56+ fn visit_binder < T : TypeFoldable < ' tcx > > (
57+ & mut self ,
58+ t : & Binder < ' tcx , T > ,
59+ ) -> ControlFlow < Self :: BreakTy > {
60+ self . binder_index . shift_in ( 1 ) ;
61+ let result = t. super_visit_with ( self ) ;
62+ self . binder_index . shift_out ( 1 ) ;
63+ result
64+ }
65+
66+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
67+ if t. outer_exclusive_binder ( ) < self . binder_index
68+ || !self . visited . insert ( ( self . binder_index , t) )
69+ {
70+ return ControlFlow :: CONTINUE ;
71+ }
72+ use std:: collections:: btree_map:: Entry ;
73+ match * t. kind ( ) {
74+ ty:: Bound ( debruijn, bound_ty) if debruijn == self . binder_index => {
75+ match self . vars . entry ( bound_ty. var . as_u32 ( ) ) {
76+ Entry :: Vacant ( entry) => {
77+ entry. insert ( ty:: BoundVariableKind :: Ty ( bound_ty. kind ) ) ;
78+ }
79+ Entry :: Occupied ( entry) => match entry. get ( ) {
80+ ty:: BoundVariableKind :: Ty ( _) => { }
81+ _ => bug ! ( "Conflicting bound vars" ) ,
82+ } ,
83+ }
84+ }
85+
86+ _ => ( ) ,
87+ } ;
88+
89+ t. super_visit_with ( self )
90+ }
91+
92+ fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
93+ r. super_visit_with ( self )
94+ }
95+ }
96+
1397#[ instrument( level = "debug" , skip( tcx) ) ]
1498fn resolve_instance < ' tcx > (
1599 tcx : TyCtxt < ' tcx > ,
@@ -115,14 +199,12 @@ fn resolve_associated_item<'tcx>(
115199 ) ;
116200
117201 let trait_ref = ty:: TraitRef :: from_method ( tcx, trait_id, rcvr_substs) ;
118- let vtbl = if trait_item. kind == ty:: AssocKind :: Const {
119- let bound_vars = tcx
120- . mk_bound_variable_kinds ( std:: iter:: once ( ty:: BoundVariableKind :: Region ( ty:: BrAnon ( 0 ) ) ) ) ;
121- let bind = ty:: Binder :: bind_with_vars ( trait_ref, bound_vars) ;
122- tcx. codegen_fulfill_obligation ( ( param_env, bind) ) ?
123- } else {
124- tcx. codegen_fulfill_obligation ( ( param_env, ty:: Binder :: bind ( trait_ref, tcx) ) ) ?
125- } ;
202+
203+ // See FIXME on `BoundVarsCollector`.
204+ let mut bound_vars_collector = BoundVarsCollector :: new ( ) ;
205+ trait_ref. visit_with ( & mut bound_vars_collector) ;
206+ let trait_binder = ty:: Binder :: bind_with_vars ( trait_ref, bound_vars_collector. into_vars ( tcx) ) ;
207+ let vtbl = tcx. codegen_fulfill_obligation ( ( param_env, trait_binder) ) ?;
126208
127209 // Now that we know which impl is being used, we can dispatch to
128210 // the actual function:
0 commit comments