@@ -7,7 +7,11 @@ use rustc_middle::{
77 BasicBlock , Body , Location , Operand , Rvalue , Statement , StatementKind , Terminator ,
88 TerminatorKind ,
99 } ,
10- ty:: { self , fold:: BottomUpFolder , ParamEnv , Ty , TyCtxt , TypeFoldable } ,
10+ ty:: {
11+ self ,
12+ relate:: { Relate , RelateResult , TypeRelation } ,
13+ ParamEnv , Ty , TyCtxt ,
14+ } ,
1115} ;
1216
1317#[ derive( Copy , Clone , Debug ) ]
@@ -103,23 +107,81 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
103107 // Type-changing assignments can happen when subtyping is used. While
104108 // all normal lifetimes are erased, higher-ranked types with their
105109 // 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 ( )
123185 }
124186}
125187
0 commit comments