Skip to content

Commit 93e3552

Browse files
committed
also normalize constants when comparing types
1 parent 50d7dea commit 93e3552

File tree

2 files changed

+36
-33
lines changed

2 files changed

+36
-33
lines changed

src/librustc_mir/interpret/eval_context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ pub(super) fn mir_assign_valid_types<'tcx>(
239239
// 2. Subtyping is used. While all normal lifetimes are erased, higher-ranked types
240240
// with their late-bound lifetimes are still around and can lead to type differences.
241241
// Normalize both of them away.
242+
// Also see the related but slightly different pre-monomorphization method in `transform/validate.rs`.
242243
let normalize = |ty: Ty<'tcx>| {
243244
ty.fold_with(&mut BottomUpFolder {
244245
tcx,

src/librustc_mir/transform/validate.rs

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -81,40 +81,42 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
8181
self.fail(location, format!("encountered jump to invalid basic block {:?}", bb))
8282
}
8383
}
84-
}
8584

86-
/// Check if src can be assigned into dest.
87-
/// This is not precise, it will accept some incorrect assignments.
88-
fn mir_assign_valid_types<'tcx>(tcx: TyCtxt<'tcx>, src: Ty<'tcx>, dest: Ty<'tcx>) -> bool {
89-
if src == dest {
90-
// Equal types, all is good.
91-
return true;
92-
}
85+
/// Check if src can be assigned into dest.
86+
/// This is not precise, it will accept some incorrect assignments.
87+
fn mir_assign_valid_types(&self, src: Ty<'tcx>, dest: Ty<'tcx>) -> bool {
88+
if src == dest {
89+
// Equal types, all is good.
90+
return true;
91+
}
9392

94-
// Type-changing assignments can happen for (at least) two reasons:
95-
// 1. `&mut T` -> `&T` gets optimized from a reborrow to a mere assignment.
96-
// 2. Subtyping is used. While all normal lifetimes are erased, higher-ranked types
97-
// with their late-bound lifetimes are still around and can lead to type differences.
98-
// Normalize both of them away.
99-
// FIXME: Share this code with `interpret/eval_context.rs`.
100-
let normalize = |ty: Ty<'tcx>| {
101-
ty.fold_with(&mut BottomUpFolder {
102-
tcx,
103-
// Normalize all references to immutable.
104-
ty_op: |ty| match ty.kind {
105-
ty::Ref(_, pointee, _) => tcx.mk_imm_ref(tcx.lifetimes.re_erased, pointee),
106-
_ => ty,
107-
},
108-
// We just erase all late-bound lifetimes, but this is not fully correct (FIXME):
109-
// lifetimes in invariant positions could matter (e.g. through associated types).
110-
// But that just means we miss some potential incompatible types, it will not
111-
// lead to wrong errors.
112-
lt_op: |_| tcx.lifetimes.re_erased,
113-
// Leave consts unchanged.
114-
ct_op: |ct| ct,
115-
})
116-
};
117-
normalize(src) == normalize(dest)
93+
// Type-changing assignments can happen for (at least) two reasons:
94+
// 1. `&mut T` -> `&T` gets optimized from a reborrow to a mere assignment.
95+
// 2. Subtyping is used. While all normal lifetimes are erased, higher-ranked types
96+
// with their late-bound lifetimes are still around and can lead to type differences.
97+
// Normalize both of them away.
98+
// Also see the related but slightly different post-monomorphization method in `interpret/eval_context.rs`.
99+
let normalize = |ty: Ty<'tcx>| {
100+
ty.fold_with(&mut BottomUpFolder {
101+
tcx: self.tcx,
102+
// Normalize all references to immutable.
103+
ty_op: |ty| match ty.kind {
104+
ty::Ref(_, pointee, _) => {
105+
self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, pointee)
106+
}
107+
_ => ty,
108+
},
109+
// We just erase all late-bound lifetimes, but this is not fully correct (FIXME):
110+
// lifetimes in invariant positions could matter (e.g. through associated types).
111+
// But that just means we miss some potential incompatible types, it will not
112+
// lead to wrong errors.
113+
lt_op: |_| self.tcx.lifetimes.re_erased,
114+
// Evaluate consts.
115+
ct_op: |ct| ct.eval(self.tcx, self.param_env),
116+
})
117+
};
118+
normalize(src) == normalize(dest)
119+
}
118120
}
119121

120122
impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
@@ -138,7 +140,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
138140
// LHS and RHS of the assignment must have the same type.
139141
let left_ty = dest.ty(&self.body.local_decls, self.tcx).ty;
140142
let right_ty = rvalue.ty(&self.body.local_decls, self.tcx);
141-
if !mir_assign_valid_types(self.tcx, right_ty, left_ty) {
143+
if !self.mir_assign_valid_types(right_ty, left_ty) {
142144
self.fail(
143145
location,
144146
format!(

0 commit comments

Comments
 (0)