From 866364cc5d79b26ec1ab58eca0cc4c3416b5a1bc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 23 Jan 2024 19:09:12 +0000 Subject: [PATCH] Normalize field types before checking validity --- .../src/transform/validate.rs | 23 ++++++++------ .../struct-assignment-validity.rs | 31 +++++++++++++++++++ 2 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 tests/ui/type-alias-impl-trait/struct-assignment-validity.rs diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 5564902396e..21bdb66a276 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -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); @@ -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"); } } diff --git a/tests/ui/type-alias-impl-trait/struct-assignment-validity.rs b/tests/ui/type-alias-impl-trait/struct-assignment-validity.rs new file mode 100644 index 00000000000..39f0b9a02ee --- /dev/null +++ b/tests/ui/type-alias-impl-trait/struct-assignment-validity.rs @@ -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: ::Assoc = (); + Foo { field: () } + } +} + +struct Foo { + field: ::Assoc, +} + +fn main() {}