MIR validation: ensure that downcast projection is followed by field … · rust-lang/rust@7d24f87

Original file line numberDiff line numberDiff line change

@@ -689,8 +689,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {

689689

if Some(adt_def.did()) == self.tcx.lang_items().dyn_metadata() {

690690

self.fail(

691691

location,

692-

format!("You can't project to field {f:?} of `DynMetadata` because \

693-

layout is weird and thinks it doesn't have fields."),

692+

format!(

693+

"You can't project to field {f:?} of `DynMetadata` because \

694+

layout is weird and thinks it doesn't have fields."

695+

),

694696

);

695697

}

696698

@@ -839,7 +841,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {

839841

&& cntxt != PlaceContext::NonUse(NonUseContext::VarDebugInfo)

840842

&& place.projection[1..].contains(&ProjectionElem::Deref)

841843

{

842-

self.fail(location, format!("{place:?}, has deref at the wrong place"));

844+

self.fail(

845+

location,

846+

format!("place {place:?} has deref as a later projection (it is only permitted as the first projection)"),

847+

);

848+

}

849+
850+

// Ensure all downcast projections are followed by field projections.

851+

let mut projections_iter = place.projection.iter();

852+

while let Some(proj) = projections_iter.next() {

853+

if matches!(proj, ProjectionElem::Downcast(..)) {

854+

if !matches!(projections_iter.next(), Some(ProjectionElem::Field(..))) {

855+

self.fail(

856+

location,

857+

format!(

858+

"place {place:?} has `Downcast` projection not followed by `Field`"

859+

),

860+

);

861+

}

862+

}

843863

}

844864
845865

self.super_place(place, cntxt, location);