@@ -2,14 +2,114 @@ use rustc_errors::ErrorReported;
2
2
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
3
3
use rustc_infer:: infer:: TyCtxtInferExt ;
4
4
use 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 } ;
6
6
use rustc_span:: { sym, DUMMY_SP } ;
7
7
use rustc_target:: spec:: abi:: Abi ;
8
8
use rustc_trait_selection:: traits;
9
9
use traits:: { translate_substs, Reveal } ;
10
10
11
+ use rustc_data_structures:: sso:: SsoHashSet ;
12
+ use std:: collections:: btree_map:: Entry ;
13
+ use std:: collections:: BTreeMap ;
14
+ use std:: ops:: ControlFlow ;
15
+
11
16
use tracing:: debug;
12
17
18
+ // FIXME(#86795): `BoundVarsCollector` here should **NOT** be used
19
+ // outside of `resolve_associated_item`. It's just to address #64494,
20
+ // #83765, and #85848 which are creating bound types/regions that lose
21
+ // their `Binder` *unintentionally*.
22
+ // It's ideal to remove `BoundVarsCollector` and just use
23
+ // `ty::Binder::*` methods but we use this stopgap until we figure out
24
+ // the "real" fix.
25
+ struct BoundVarsCollector < ' tcx > {
26
+ binder_index : ty:: DebruijnIndex ,
27
+ vars : BTreeMap < u32 , ty:: BoundVariableKind > ,
28
+ // We may encounter the same variable at different levels of binding, so
29
+ // this can't just be `Ty`
30
+ visited : SsoHashSet < ( ty:: DebruijnIndex , Ty < ' tcx > ) > ,
31
+ }
32
+
33
+ impl < ' tcx > BoundVarsCollector < ' tcx > {
34
+ fn new ( ) -> Self {
35
+ BoundVarsCollector {
36
+ binder_index : ty:: INNERMOST ,
37
+ vars : BTreeMap :: new ( ) ,
38
+ visited : SsoHashSet :: default ( ) ,
39
+ }
40
+ }
41
+
42
+ fn into_vars ( self , tcx : TyCtxt < ' tcx > ) -> & ' tcx ty:: List < ty:: BoundVariableKind > {
43
+ let max = self . vars . iter ( ) . map ( |( k, _) | * k) . max ( ) . unwrap_or ( 0 ) ;
44
+ for i in 0 ..max {
45
+ if let None = self . vars . get ( & i) {
46
+ panic ! ( "Unknown variable: {:?}" , i) ;
47
+ }
48
+ }
49
+
50
+ tcx. mk_bound_variable_kinds ( self . vars . into_iter ( ) . map ( |( _, v) | v) )
51
+ }
52
+ }
53
+
54
+ impl < ' tcx > TypeVisitor < ' tcx > for BoundVarsCollector < ' tcx > {
55
+ type BreakTy = ( ) ;
56
+
57
+ fn visit_binder < T : TypeFoldable < ' tcx > > (
58
+ & mut self ,
59
+ t : & Binder < ' tcx , T > ,
60
+ ) -> ControlFlow < Self :: BreakTy > {
61
+ self . binder_index . shift_in ( 1 ) ;
62
+ let result = t. super_visit_with ( self ) ;
63
+ self . binder_index . shift_out ( 1 ) ;
64
+ result
65
+ }
66
+
67
+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
68
+ if t. outer_exclusive_binder ( ) < self . binder_index
69
+ || !self . visited . insert ( ( self . binder_index , t) )
70
+ {
71
+ return ControlFlow :: CONTINUE ;
72
+ }
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
+ match r {
94
+ ty:: ReLateBound ( index, br) if * index == self . binder_index => {
95
+ match self . vars . entry ( br. var . as_u32 ( ) ) {
96
+ Entry :: Vacant ( entry) => {
97
+ entry. insert ( ty:: BoundVariableKind :: Region ( br. kind ) ) ;
98
+ }
99
+ Entry :: Occupied ( entry) => match entry. get ( ) {
100
+ ty:: BoundVariableKind :: Region ( _) => { }
101
+ _ => bug ! ( "Conflicting bound vars" ) ,
102
+ } ,
103
+ }
104
+ }
105
+
106
+ _ => ( ) ,
107
+ } ;
108
+
109
+ r. super_visit_with ( self )
110
+ }
111
+ }
112
+
13
113
#[ instrument( level = "debug" , skip( tcx) ) ]
14
114
fn resolve_instance < ' tcx > (
15
115
tcx : TyCtxt < ' tcx > ,
@@ -115,7 +215,12 @@ fn resolve_associated_item<'tcx>(
115
215
) ;
116
216
117
217
let trait_ref = ty:: TraitRef :: from_method ( tcx, trait_id, rcvr_substs) ;
118
- let vtbl = tcx. codegen_fulfill_obligation ( ( param_env, ty:: Binder :: bind ( trait_ref, tcx) ) ) ?;
218
+
219
+ // See FIXME on `BoundVarsCollector`.
220
+ let mut bound_vars_collector = BoundVarsCollector :: new ( ) ;
221
+ trait_ref. visit_with ( & mut bound_vars_collector) ;
222
+ let trait_binder = ty:: Binder :: bind_with_vars ( trait_ref, bound_vars_collector. into_vars ( tcx) ) ;
223
+ let vtbl = tcx. codegen_fulfill_obligation ( ( param_env, trait_binder) ) ?;
119
224
120
225
// Now that we know which impl is being used, we can dispatch to
121
226
// the actual function:
0 commit comments