From 7893ca74e53b76068a2afae17ddf752f21a160ff Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Sep 2022 01:13:46 +0000 Subject: [PATCH] Normalize struct types in confirm_builtin_unsize_candidate --- .../src/traits/select/confirmation.rs | 22 ++++++++++++++++--- src/test/ui/unsized/issue-75899-but-gats.rs | 21 ++++++++++++++++++ src/test/ui/unsized/issue-75899.rs | 18 +++++++++++++++ 3 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/unsized/issue-75899-but-gats.rs create mode 100644 src/test/ui/unsized/issue-75899.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 43c4ddd3f6faf..d1deef7840710 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1039,9 +1039,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(Unimplemented); } - // Extract `TailField` and `TailField` from `Struct` and `Struct`. - let source_tail = tail_field_ty.subst(tcx, substs_a); - let target_tail = tail_field_ty.subst(tcx, substs_b); + // Extract `TailField` and `TailField` from `Struct` and `Struct`, + // normalizing in the process, since `type_of` returns something directly from + // astconv (which means it's un-normalized). + let source_tail = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + tail_field_ty.subst(tcx, substs_a), + &mut nested, + ); + let target_tail = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + tail_field_ty.subst(tcx, substs_b), + &mut nested, + ); // Check that the source struct with the target's // unsizing parameters is equal to the target. diff --git a/src/test/ui/unsized/issue-75899-but-gats.rs b/src/test/ui/unsized/issue-75899-but-gats.rs new file mode 100644 index 0000000000000..5716817f43ded --- /dev/null +++ b/src/test/ui/unsized/issue-75899-but-gats.rs @@ -0,0 +1,21 @@ +// check-pass + +use std::fmt::Debug; +use std::marker::PhantomData; + +trait Foo { + type Gat<'a>: ?Sized where Self: 'a; +} + +struct Bar<'a, T: Foo + 'a>(T::Gat<'a>); + +struct Baz(PhantomData); + +impl Foo for Baz { + type Gat<'a> = T where Self: 'a; +} + +fn main() { + let x = Bar::<'_, Baz<()>>(()); + let y: &Bar<'_, Baz> = &x; +} diff --git a/src/test/ui/unsized/issue-75899.rs b/src/test/ui/unsized/issue-75899.rs new file mode 100644 index 0000000000000..abff17e11b54a --- /dev/null +++ b/src/test/ui/unsized/issue-75899.rs @@ -0,0 +1,18 @@ +// check-pass + +trait Trait {} +impl Trait for T {} + +trait Noop { + type Assoc: ?Sized; +} +impl Noop for T { + type Assoc = T; +} + +struct NoopNewtype(T::Assoc); +fn coerce_newtype(x: &NoopNewtype) -> &NoopNewtype { + x +} + +fn main() {}