From ed30efff3b2d9e4636d3b1b9e9dc275362b64a62 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 22 Feb 2023 01:39:41 +0000 Subject: [PATCH] Comments, another test --- .../solve/trait_goals/structural_traits.rs | 43 ++++++++++++++++++- .../ui/traits/new-solver/more-object-bound.rs | 27 ++++++++++++ .../new-solver/more-object-bound.stderr | 19 ++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/new-solver/more-object-bound.rs create mode 100644 tests/ui/traits/new-solver/more-object-bound.stderr diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs index bd4950d8067..9b6cce86fff 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs @@ -235,6 +235,40 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>( } } +/// Assemble a list of predicates that would be present on a theoretical +/// user impl for an object type. These predicates must be checked any time +/// we assemble a built-in object candidate for an object type, since they +/// are not implied by the well-formedness of the type. +/// +/// For example, given the following traits: +/// +/// ```rust,ignore (theoretical code) +/// trait Foo: Baz { +/// type Bar: Copy; +/// } +/// +/// trait Baz {} +/// ``` +/// +/// For the dyn type `dyn Foo`, we can imagine there being a +/// pair of theoretical impls: +/// +/// ```rust,ignore (theoretical code) +/// impl Foo for dyn Foo +/// where +/// Self: Baz, +/// ::Bar: Copy, +/// { +/// type Bar = Ty; +/// } +/// +/// impl Baz for dyn Foo {} +/// ``` +/// +/// However, in order to make such impls well-formed, we need to do an +/// additional step of eagerly folding the associated types in the where +/// clauses of the impl. In this example, that means replacing +/// `::Bar` with `Ty` in the first impl. pub(crate) fn predicates_for_object_candidate<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -247,6 +281,8 @@ pub(crate) fn predicates_for_object_candidate<'tcx>( tcx.super_predicates_of(trait_ref.def_id).instantiate(tcx, trait_ref.substs).predicates, ); for item in tcx.associated_items(trait_ref.def_id).in_definition_order() { + // FIXME(associated_const_equality): Also add associated consts to + // the requirements here. if item.kind == ty::AssocKind::Type { requirements.extend(tcx.item_bounds(item.def_id).subst(tcx, trait_ref.substs)); } @@ -290,13 +326,16 @@ impl<'tcx> TypeFolder> for ReplaceProjectionWith<'_, 'tcx> { if let ty::Alias(ty::Projection, alias_ty) = *ty.kind() && let Some(replacement) = self.mapping.get(&alias_ty.def_id) { + // We may have a case where our object type's projection bound is higher-ranked, + // but the where clauses we instantiated are not. We can solve this by instantiating + // the binder at the usage site. let proj = self.ecx.instantiate_binder_with_infer(*replacement); - // Technically this folder could be fallible? + // FIXME: Technically this folder could be fallible? let nested = self .ecx .eq(self.param_env, alias_ty, proj.projection_ty) .expect("expected to be able to unify goal projection with dyn's projection"); - // Technically we could register these too.. + // FIXME: Technically we could register these too.. assert!(nested.is_empty(), "did not expect unification to have any nested goals"); proj.term.ty().unwrap() } else { diff --git a/tests/ui/traits/new-solver/more-object-bound.rs b/tests/ui/traits/new-solver/more-object-bound.rs new file mode 100644 index 00000000000..712759ef0e6 --- /dev/null +++ b/tests/ui/traits/new-solver/more-object-bound.rs @@ -0,0 +1,27 @@ +// compile-flags: -Ztrait-solver=next +// From #80800 + +trait SuperTrait { + type A; + type B; +} + +trait Trait: SuperTrait::B> {} + +fn transmute(x: A) -> B { + foo::>(x) + //~^ ERROR type annotations needed: cannot satisfy `dyn Trait: Trait` +} + +fn foo(x: T::A) -> B +where + T: Trait, +{ + x +} + +static X: u8 = 0; +fn main() { + let x = transmute::<&u8, &[u8; 1_000_000]>(&X); + println!("{:?}", x[100_000]); +} diff --git a/tests/ui/traits/new-solver/more-object-bound.stderr b/tests/ui/traits/new-solver/more-object-bound.stderr new file mode 100644 index 00000000000..208fdecb08f --- /dev/null +++ b/tests/ui/traits/new-solver/more-object-bound.stderr @@ -0,0 +1,19 @@ +error[E0283]: type annotations needed: cannot satisfy `dyn Trait: Trait` + --> $DIR/more-object-bound.rs:12:5 + | +LL | foo::>(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: cannot satisfy `dyn Trait: Trait` +note: required by a bound in `foo` + --> $DIR/more-object-bound.rs:18:8 + | +LL | fn foo(x: T::A) -> B + | --- required by a bound in this function +LL | where +LL | T: Trait, + | ^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`.