@@ -7,7 +7,11 @@ use rustc_middle::{
7
7
BasicBlock , Body , Location , Operand , Rvalue , Statement , StatementKind , Terminator ,
8
8
TerminatorKind ,
9
9
} ,
10
- ty:: { self , fold:: BottomUpFolder , ParamEnv , Ty , TyCtxt , TypeFoldable } ,
10
+ ty:: {
11
+ self ,
12
+ relate:: { Relate , RelateResult , TypeRelation } ,
13
+ ParamEnv , Ty , TyCtxt ,
14
+ } ,
11
15
} ;
12
16
13
17
#[ derive( Copy , Clone , Debug ) ]
@@ -103,23 +107,81 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
103
107
// Type-changing assignments can happen when subtyping is used. While
104
108
// all normal lifetimes are erased, higher-ranked types with their
105
109
// late-bound lifetimes are still around and can lead to type
106
- // differences. Normalize both of them away.
107
- // Also see the related but slightly different post-monomorphization
108
- // method in `interpret/eval_context.rs`.
109
- let normalize = |ty : Ty < ' tcx > | {
110
- ty. fold_with ( & mut BottomUpFolder {
111
- tcx : self . tcx ,
112
- ty_op : |ty| ty,
113
- // We just erase all late-bound lifetimes, but this is not fully correct (FIXME):
114
- // lifetimes in invariant positions could matter (e.g. through associated types).
115
- // But that just means we miss some potential incompatible types, it will not
116
- // lead to wrong errors.
117
- lt_op : |_| self . tcx . lifetimes . re_erased ,
118
- // Evaluate consts.
119
- ct_op : |ct| ct. eval ( self . tcx , param_env) ,
120
- } )
121
- } ;
122
- normalize ( src) == normalize ( dest)
110
+ // differences. So we compare ignoring lifetimes.
111
+ struct LifetimeIgnoreRelation < ' tcx > {
112
+ tcx : TyCtxt < ' tcx > ,
113
+ param_env : ty:: ParamEnv < ' tcx > ,
114
+ }
115
+
116
+ impl TypeRelation < ' tcx > for LifetimeIgnoreRelation < ' tcx > {
117
+ fn tcx ( & self ) -> TyCtxt < ' tcx > {
118
+ self . tcx
119
+ }
120
+
121
+ fn param_env ( & self ) -> ty:: ParamEnv < ' tcx > {
122
+ self . param_env
123
+ }
124
+
125
+ fn tag ( & self ) -> & ' static str {
126
+ "librustc_mir::transform::validate"
127
+ }
128
+
129
+ fn a_is_expected ( & self ) -> bool {
130
+ true
131
+ }
132
+
133
+ fn relate_with_variance < T : Relate < ' tcx > > (
134
+ & mut self ,
135
+ _: ty:: Variance ,
136
+ a : & T ,
137
+ b : & T ,
138
+ ) -> RelateResult < ' tcx , T > {
139
+ // Ignore variance, require types to be exactly the same.
140
+ self . relate ( a, b)
141
+ }
142
+
143
+ fn tys ( & mut self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> RelateResult < ' tcx , Ty < ' tcx > > {
144
+ if a == b {
145
+ // Short-circuit.
146
+ return Ok ( a) ;
147
+ }
148
+ ty:: relate:: super_relate_tys ( self , a, b)
149
+ }
150
+
151
+ fn regions (
152
+ & mut self ,
153
+ a : ty:: Region < ' tcx > ,
154
+ _b : ty:: Region < ' tcx > ,
155
+ ) -> RelateResult < ' tcx , ty:: Region < ' tcx > > {
156
+ // Ignore regions.
157
+ Ok ( a)
158
+ }
159
+
160
+ fn consts (
161
+ & mut self ,
162
+ a : & ' tcx ty:: Const < ' tcx > ,
163
+ b : & ' tcx ty:: Const < ' tcx > ,
164
+ ) -> RelateResult < ' tcx , & ' tcx ty:: Const < ' tcx > > {
165
+ ty:: relate:: super_relate_consts ( self , a, b)
166
+ }
167
+
168
+ fn binders < T > (
169
+ & mut self ,
170
+ a : & ty:: Binder < T > ,
171
+ b : & ty:: Binder < T > ,
172
+ ) -> RelateResult < ' tcx , ty:: Binder < T > >
173
+ where
174
+ T : Relate < ' tcx > ,
175
+ {
176
+ self . relate ( a. skip_binder ( ) , b. skip_binder ( ) ) ?;
177
+ Ok ( a. clone ( ) )
178
+ }
179
+ }
180
+
181
+ // Instantiate and run relation.
182
+ let mut relator: LifetimeIgnoreRelation < ' tcx > =
183
+ LifetimeIgnoreRelation { tcx : self . tcx , param_env } ;
184
+ relator. relate ( & src, & dest) . is_ok ( )
123
185
}
124
186
}
125
187
0 commit comments