From d62238d6a8ed57fecddfa9b97fd79cb0ac814791 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 27 Mar 2023 19:41:15 +0000 Subject: [PATCH] Do not consider elaborated projection predicates for objects in new solver --- .../src/solve/assembly.rs | 19 ++++++++++++++++--- .../dont-elaborate-for-projections.rs | 12 ++++++++++++ .../ui/traits/new-solver/more-object-bound.rs | 2 +- .../new-solver/more-object-bound.stderr | 13 ++++++++----- 4 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 tests/ui/traits/new-solver/dont-elaborate-for-projections.rs diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 0f7a0eb337b..856b1c08b72 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -6,6 +6,7 @@ use super::trait_goals::structural_traits::*; use super::{EvalCtxt, SolverMode}; use crate::traits::coherence; use itertools::Itertools; +use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::util::elaborate_predicates; @@ -489,9 +490,21 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { }; let tcx = self.tcx(); - for assumption in - elaborate_predicates(tcx, bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty))) - { + let own_bounds: FxIndexSet<_> = + bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty)).collect(); + for assumption in elaborate_predicates(tcx, own_bounds.iter().copied()) { + // FIXME: Predicates are fully elaborated in the object type's existential bounds + // list. We want to only consider these pre-elaborated projections, and not other + // projection predicates that we reach by elaborating the principal trait ref, + // since that'll cause ambiguity. + // + // We can remove this when we have implemented intersections in responses. + if assumption.to_opt_poly_projection_pred().is_some() + && !own_bounds.contains(&assumption) + { + continue; + } + match G::consider_object_bound_candidate(self, goal, assumption) { Ok(result) => { candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result }) diff --git a/tests/ui/traits/new-solver/dont-elaborate-for-projections.rs b/tests/ui/traits/new-solver/dont-elaborate-for-projections.rs new file mode 100644 index 00000000000..e608250063c --- /dev/null +++ b/tests/ui/traits/new-solver/dont-elaborate-for-projections.rs @@ -0,0 +1,12 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +trait Iter<'a, I: 'a>: Iterator {} + +fn needs_iter<'a, T: Iter<'a, I> + ?Sized, I: 'a>(_: &T) {} + +fn test(x: &dyn Iter<'_, ()>) { + needs_iter(x); +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/more-object-bound.rs b/tests/ui/traits/new-solver/more-object-bound.rs index 712759ef0e6..bb730b18ef7 100644 --- a/tests/ui/traits/new-solver/more-object-bound.rs +++ b/tests/ui/traits/new-solver/more-object-bound.rs @@ -10,7 +10,7 @@ trait Trait: SuperTrait::B> {} fn transmute(x: A) -> B { foo::>(x) - //~^ ERROR type annotations needed: cannot satisfy `dyn Trait: Trait` + //~^ ERROR the trait bound `dyn Trait: Trait` is not satisfied } fn foo(x: T::A) -> B diff --git a/tests/ui/traits/new-solver/more-object-bound.stderr b/tests/ui/traits/new-solver/more-object-bound.stderr index 208fdecb08f..4554b8c7473 100644 --- a/tests/ui/traits/new-solver/more-object-bound.stderr +++ b/tests/ui/traits/new-solver/more-object-bound.stderr @@ -1,10 +1,9 @@ -error[E0283]: type annotations needed: cannot satisfy `dyn Trait: Trait` - --> $DIR/more-object-bound.rs:12:5 +error[E0277]: the trait bound `dyn Trait: Trait` is not satisfied + --> $DIR/more-object-bound.rs:12:17 | LL | foo::>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Trait` | - = note: cannot satisfy `dyn Trait: Trait` note: required by a bound in `foo` --> $DIR/more-object-bound.rs:18:8 | @@ -13,7 +12,11 @@ LL | fn foo(x: T::A) -> B LL | where LL | T: Trait, | ^^^^^^^^^^^^ required by this bound in `foo` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn transmute(x: A) -> B where dyn Trait: Trait { + | ++++++++++++++++++++++++++++++++++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0277`.