Skip to content

Commit 809f55d

Browse files
committed
TypeVerifier: stop computing types for later use
1 parent c54e815 commit 809f55d

File tree

1 file changed

+74
-172
lines changed
  • compiler/rustc_borrowck/src/type_check

1 file changed

+74
-172
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 74 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,6 @@ macro_rules! span_mirbug {
7575
})
7676
}
7777

78-
macro_rules! span_mirbug_and_err {
79-
($context:expr, $elem:expr, $($message:tt)*) => ({
80-
{
81-
span_mirbug!($context, $elem, $($message)*);
82-
$context.error()
83-
}
84-
})
85-
}
86-
8778
mod canonical;
8879
mod constraint_conversion;
8980
pub(crate) mod free_region_relations;
@@ -263,6 +254,74 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
263254
self.sanitize_place(place, location, context);
264255
}
265256

257+
fn visit_projection_elem(
258+
&mut self,
259+
place: PlaceRef<'tcx>,
260+
elem: PlaceElem<'tcx>,
261+
context: PlaceContext,
262+
location: Location,
263+
) {
264+
let tcx = self.tcx();
265+
let base_ty = place.ty(self.body(), tcx);
266+
match elem {
267+
// All these projections don't add any constraints, so there's nothing to
268+
// do here. We check their invariants in the MIR validator after all.
269+
ProjectionElem::Deref
270+
| ProjectionElem::Index(_)
271+
| ProjectionElem::ConstantIndex { .. }
272+
| ProjectionElem::Subslice { .. }
273+
| ProjectionElem::Downcast(..) => {}
274+
ProjectionElem::Field(field, fty) => {
275+
let fty = self.typeck.normalize(fty, location);
276+
match self.expected_field_ty(base_ty, field, location) {
277+
Ok(ty) => {
278+
let ty = self.typeck.normalize(ty, location);
279+
debug!(?fty, ?ty);
280+
281+
if let Err(terr) = self.typeck.relate_types(
282+
ty,
283+
context.ambient_variance(),
284+
fty,
285+
location.to_locations(),
286+
ConstraintCategory::Boring,
287+
) {
288+
span_mirbug!(
289+
self,
290+
place,
291+
"bad field access ({:?}: {:?}): {:?}",
292+
ty,
293+
fty,
294+
terr
295+
);
296+
}
297+
}
298+
Err(FieldAccessError::OutOfRange { field_count }) => span_mirbug!(
299+
self,
300+
place,
301+
"accessed field #{} but variant only has {}",
302+
field.index(),
303+
field_count
304+
),
305+
}
306+
}
307+
ProjectionElem::OpaqueCast(ty) => {
308+
let ty = self.typeck.normalize(ty, location);
309+
self.typeck
310+
.relate_types(
311+
ty,
312+
context.ambient_variance(),
313+
base_ty.ty,
314+
location.to_locations(),
315+
ConstraintCategory::TypeAnnotation,
316+
)
317+
.unwrap();
318+
}
319+
ProjectionElem::Subtype(_) => {
320+
bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
321+
}
322+
}
323+
}
324+
266325
fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
267326
debug!(?constant, ?location, "visit_const_operand");
268327

@@ -444,25 +503,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
444503
/// Checks that the types internal to the `place` match up with
445504
/// what would be expected.
446505
#[instrument(level = "debug", skip(self, location), ret)]
447-
fn sanitize_place(
448-
&mut self,
449-
place: &Place<'tcx>,
450-
location: Location,
451-
context: PlaceContext,
452-
) -> PlaceTy<'tcx> {
453-
let mut place_ty = PlaceTy::from_ty(self.body().local_decls[place.local].ty);
454-
455-
for elem in place.projection.iter() {
456-
if place_ty.variant_index.is_none() {
457-
if let Err(guar) = place_ty.ty.error_reported() {
458-
return PlaceTy::from_ty(Ty::new_error(self.tcx(), guar));
459-
}
460-
}
461-
place_ty = self.sanitize_projection(place_ty, elem, place, location, context);
462-
}
463-
506+
fn sanitize_place(&mut self, place: &Place<'tcx>, location: Location, context: PlaceContext) {
507+
self.super_place(place, context, location);
508+
let tcx = self.tcx();
509+
let place_ty = place.ty(self.body(), tcx);
464510
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
465-
let tcx = self.tcx();
466511
let trait_ref = ty::TraitRef::new(
467512
tcx,
468513
tcx.require_lang_item(LangItem::Copy, Some(self.last_span)),
@@ -486,8 +531,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
486531
ConstraintCategory::CopyBound,
487532
);
488533
}
489-
490-
place_ty
491534
}
492535

493536
fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Location) {
@@ -547,144 +590,8 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
547590
}
548591
}
549592

550-
#[instrument(skip(self, location), ret, level = "debug")]
551-
fn sanitize_projection(
552-
&mut self,
553-
base: PlaceTy<'tcx>,
554-
pi: PlaceElem<'tcx>,
555-
place: &Place<'tcx>,
556-
location: Location,
557-
context: PlaceContext,
558-
) -> PlaceTy<'tcx> {
559-
let tcx = self.tcx();
560-
let base_ty = base.ty;
561-
match pi {
562-
ProjectionElem::Deref => {
563-
let deref_ty = base_ty.builtin_deref(true);
564-
PlaceTy::from_ty(deref_ty.unwrap_or_else(|| {
565-
span_mirbug_and_err!(self, place, "deref of non-pointer {:?}", base_ty)
566-
}))
567-
}
568-
ProjectionElem::Index(i) => {
569-
let index_ty = Place::from(i).ty(self.body(), tcx).ty;
570-
if index_ty != tcx.types.usize {
571-
PlaceTy::from_ty(span_mirbug_and_err!(self, i, "index by non-usize {:?}", i))
572-
} else {
573-
PlaceTy::from_ty(base_ty.builtin_index().unwrap_or_else(|| {
574-
span_mirbug_and_err!(self, place, "index of non-array {:?}", base_ty)
575-
}))
576-
}
577-
}
578-
ProjectionElem::ConstantIndex { .. } => {
579-
// consider verifying in-bounds
580-
PlaceTy::from_ty(base_ty.builtin_index().unwrap_or_else(|| {
581-
span_mirbug_and_err!(self, place, "index of non-array {:?}", base_ty)
582-
}))
583-
}
584-
ProjectionElem::Subslice { from, to, from_end } => {
585-
PlaceTy::from_ty(match base_ty.kind() {
586-
ty::Array(inner, _) => {
587-
assert!(!from_end, "array subslices should not use from_end");
588-
Ty::new_array(tcx, *inner, to - from)
589-
}
590-
ty::Slice(..) => {
591-
assert!(from_end, "slice subslices should use from_end");
592-
base_ty
593-
}
594-
_ => span_mirbug_and_err!(self, place, "slice of non-array {:?}", base_ty),
595-
})
596-
}
597-
ProjectionElem::Downcast(maybe_name, index) => match base_ty.kind() {
598-
ty::Adt(adt_def, _args) if adt_def.is_enum() => {
599-
if index.as_usize() >= adt_def.variants().len() {
600-
PlaceTy::from_ty(span_mirbug_and_err!(
601-
self,
602-
place,
603-
"cast to variant #{:?} but enum only has {:?}",
604-
index,
605-
adt_def.variants().len()
606-
))
607-
} else {
608-
PlaceTy { ty: base_ty, variant_index: Some(index) }
609-
}
610-
}
611-
// We do not need to handle coroutines here, because this runs
612-
// before the coroutine transform stage.
613-
_ => {
614-
let ty = if let Some(name) = maybe_name {
615-
span_mirbug_and_err!(
616-
self,
617-
place,
618-
"can't downcast {:?} as {:?}",
619-
base_ty,
620-
name
621-
)
622-
} else {
623-
span_mirbug_and_err!(self, place, "can't downcast {:?}", base_ty)
624-
};
625-
PlaceTy::from_ty(ty)
626-
}
627-
},
628-
ProjectionElem::Field(field, fty) => {
629-
let fty = self.typeck.normalize(fty, location);
630-
match self.field_ty(place, base, field, location) {
631-
Ok(ty) => {
632-
let ty = self.typeck.normalize(ty, location);
633-
debug!(?fty, ?ty);
634-
635-
if let Err(terr) = self.typeck.relate_types(
636-
ty,
637-
context.ambient_variance(),
638-
fty,
639-
location.to_locations(),
640-
ConstraintCategory::Boring,
641-
) {
642-
span_mirbug!(
643-
self,
644-
place,
645-
"bad field access ({:?}: {:?}): {:?}",
646-
ty,
647-
fty,
648-
terr
649-
);
650-
}
651-
}
652-
Err(FieldAccessError::OutOfRange { field_count }) => span_mirbug!(
653-
self,
654-
place,
655-
"accessed field #{} but variant only has {}",
656-
field.index(),
657-
field_count
658-
),
659-
}
660-
PlaceTy::from_ty(fty)
661-
}
662-
ProjectionElem::Subtype(_) => {
663-
bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
664-
}
665-
ProjectionElem::OpaqueCast(ty) => {
666-
let ty = self.typeck.normalize(ty, location);
667-
self.typeck
668-
.relate_types(
669-
ty,
670-
context.ambient_variance(),
671-
base.ty,
672-
location.to_locations(),
673-
ConstraintCategory::TypeAnnotation,
674-
)
675-
.unwrap();
676-
PlaceTy::from_ty(ty)
677-
}
678-
}
679-
}
680-
681-
fn error(&mut self) -> Ty<'tcx> {
682-
Ty::new_misc_error(self.tcx())
683-
}
684-
685-
fn field_ty(
593+
fn expected_field_ty(
686594
&mut self,
687-
parent: &dyn fmt::Debug,
688595
base_ty: PlaceTy<'tcx>,
689596
field: FieldIdx,
690597
location: Location,
@@ -747,12 +654,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
747654
};
748655
}
749656
_ => {
750-
return Ok(span_mirbug_and_err!(
751-
self,
752-
parent,
753-
"can't project out of {:?}",
754-
base_ty
755-
));
657+
span_bug!(self.last_span, "can't project out of {:?}", base_ty);
756658
}
757659
},
758660
};

0 commit comments

Comments
 (0)