mirror of https://github.com/rust-lang/rust.git
MIR validation: ensure that downcast projection is followed by field projection
This commit is contained in:
parent
cdc509f7c0
commit
7d24f87068
|
@ -1008,8 +1008,8 @@ pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
|
|||
/// element:
|
||||
///
|
||||
/// - [`Downcast`](ProjectionElem::Downcast): This projection sets the place's variant index to the
|
||||
/// given one, and makes no other changes. A `Downcast` projection on a place with its variant
|
||||
/// index already set is not well-formed.
|
||||
/// given one, and makes no other changes. A `Downcast` projection must always be followed
|
||||
/// immediately by a `Field` projection.
|
||||
/// - [`Field`](ProjectionElem::Field): `Field` projections take their parent place and create a
|
||||
/// place referring to one of the fields of the type. The resulting address is the parent
|
||||
/// address, plus the offset of the field. The type becomes the type of the field. If the parent
|
||||
|
|
|
@ -689,8 +689,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
if Some(adt_def.did()) == self.tcx.lang_items().dyn_metadata() {
|
||||
self.fail(
|
||||
location,
|
||||
format!("You can't project to field {f:?} of `DynMetadata` because \
|
||||
layout is weird and thinks it doesn't have fields."),
|
||||
format!(
|
||||
"You can't project to field {f:?} of `DynMetadata` because \
|
||||
layout is weird and thinks it doesn't have fields."
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -839,7 +841,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
&& cntxt != PlaceContext::NonUse(NonUseContext::VarDebugInfo)
|
||||
&& place.projection[1..].contains(&ProjectionElem::Deref)
|
||||
{
|
||||
self.fail(location, format!("{place:?}, has deref at the wrong place"));
|
||||
self.fail(
|
||||
location,
|
||||
format!("place {place:?} has deref as a later projection (it is only permitted as the first projection)"),
|
||||
);
|
||||
}
|
||||
|
||||
// Ensure all downcast projections are followed by field projections.
|
||||
let mut projections_iter = place.projection.iter();
|
||||
while let Some(proj) = projections_iter.next() {
|
||||
if matches!(proj, ProjectionElem::Downcast(..)) {
|
||||
if !matches!(projections_iter.next(), Some(ProjectionElem::Field(..))) {
|
||||
self.fail(
|
||||
location,
|
||||
format!(
|
||||
"place {place:?} has `Downcast` projection not followed by `Field`"
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.super_place(place, cntxt, location);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
thread 'rustc' panicked at compiler/rustc_mir_transform/src/validate.rs:LL:CC:
|
||||
broken MIR in Item(DefId) (after phase change to runtime-optimized) at bb0[1]:
|
||||
(*(_2.0: *mut i32)), has deref at the wrong place
|
||||
place (*(_2.0: *mut i32)) has deref as a later projection (it is only permitted as the first projection)
|
||||
stack backtrace:
|
||||
|
||||
error: the compiler unexpectedly panicked. this is a bug.
|
||||
|
|
Loading…
Reference in New Issue