Skip to content

Commit 91f73fb

Browse files
committed
use a TypeRelation to compare the types
1 parent 978470f commit 91f73fb

File tree

1 file changed

+80
-18
lines changed

1 file changed

+80
-18
lines changed

src/librustc_mir/transform/validate.rs

Lines changed: 80 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)