Skip to content

Commit

Permalink
Unrolled build for rust-lang#120277
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#120277 - compiler-errors:normalize-before-validating, r=oli-obk

Normalize field types before checking validity

I forgot to normalize field types when checking ADT-like aggregates in the MIR validator.

This normalization is needed due to a crude check for opaque types in `mir_assign_valid_types` which prevents opaque type cycles -- if we pass in an unnormalized type, we may not detect that the destination type is an opaque, and therefore will call `type_of(opaque)` later on, which causes a cycle error -> ICE.

Fixes rust-lang#120253
  • Loading branch information
rust-timer authored Jan 27, 2024
2 parents c073f56 + 866364c commit 41bc033
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 9 deletions.
23 changes: 14 additions & 9 deletions compiler/rustc_const_eval/src/transform/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,13 +810,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
let adt_def = self.tcx.adt_def(def_id);
assert!(adt_def.is_union());
assert_eq!(idx, FIRST_VARIANT);
let dest = adt_def.non_enum_variant().fields[field].ty(self.tcx, args);
if fields.len() != 1 {
let dest_ty = self.tcx.normalize_erasing_regions(
self.param_env,
adt_def.non_enum_variant().fields[field].ty(self.tcx, args),
);
if fields.len() == 1 {
let src_ty = fields.raw[0].ty(self.body, self.tcx);
if !self.mir_assign_valid_types(src_ty, dest_ty) {
self.fail(location, "union field has the wrong type");
}
} else {
self.fail(location, "unions should have one initialized field");
}
if !self.mir_assign_valid_types(fields.raw[0].ty(self.body, self.tcx), dest) {
self.fail(location, "union field has the wrong type");
}
}
AggregateKind::Adt(def_id, idx, args, _, None) => {
let adt_def = self.tcx.adt_def(def_id);
Expand All @@ -826,10 +831,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.fail(location, "adt has the wrong number of initialized fields");
}
for (src, dest) in std::iter::zip(fields, &variant.fields) {
if !self.mir_assign_valid_types(
src.ty(self.body, self.tcx),
dest.ty(self.tcx, args),
) {
let dest_ty = self
.tcx
.normalize_erasing_regions(self.param_env, dest.ty(self.tcx, args));
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest_ty) {
self.fail(location, "adt field has the wrong type");
}
}
Expand Down
31 changes: 31 additions & 0 deletions tests/ui/type-alias-impl-trait/struct-assignment-validity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// compile-flags: -Zvalidate-mir
// check-pass

// Check that we don't cause cycle errors when validating pre-`Reveal::All` MIR
// that assigns opaques through normalized projections.

#![feature(impl_trait_in_assoc_type)]

struct Bar;

trait Trait {
type Assoc;
fn foo() -> Foo;
}

impl Trait for Bar {
type Assoc = impl std::fmt::Debug;
fn foo() -> Foo
where
Self::Assoc:,
{
let x: <Bar as Trait>::Assoc = ();
Foo { field: () }
}
}

struct Foo {
field: <Bar as Trait>::Assoc,
}

fn main() {}

0 comments on commit 41bc033

Please sign in to comment.