drop global where-bounds before merging candidates
This commit is contained in:
parent
092a284ba0
commit
2c2c9df653
5 changed files with 93 additions and 6 deletions
|
@ -1238,10 +1238,11 @@ where
|
||||||
D: SolverDelegate<Interner = I>,
|
D: SolverDelegate<Interner = I>,
|
||||||
I: Interner,
|
I: Interner,
|
||||||
{
|
{
|
||||||
|
#[instrument(level = "debug", skip(self, goal), ret)]
|
||||||
pub(super) fn merge_trait_candidates(
|
pub(super) fn merge_trait_candidates(
|
||||||
&mut self,
|
&mut self,
|
||||||
goal: Goal<I, TraitPredicate<I>>,
|
goal: Goal<I, TraitPredicate<I>>,
|
||||||
candidates: Vec<Candidate<I>>,
|
mut candidates: Vec<Candidate<I>>,
|
||||||
) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
|
) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
|
||||||
if let TypingMode::Coherence = self.typing_mode() {
|
if let TypingMode::Coherence = self.typing_mode() {
|
||||||
let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect();
|
let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect();
|
||||||
|
@ -1323,13 +1324,16 @@ where
|
||||||
|
|
||||||
// If there are *only* global where bounds, then make sure to return that this
|
// If there are *only* global where bounds, then make sure to return that this
|
||||||
// is still reported as being proven-via the param-env so that rigid projections
|
// is still reported as being proven-via the param-env so that rigid projections
|
||||||
// operate correctly.
|
// operate correctly. Otherwise, drop all global where-bounds before merging the
|
||||||
|
// remaining candidates.
|
||||||
let proven_via =
|
let proven_via =
|
||||||
if candidates.iter().all(|c| matches!(c.source, CandidateSource::ParamEnv(_))) {
|
if candidates.iter().all(|c| matches!(c.source, CandidateSource::ParamEnv(_))) {
|
||||||
TraitGoalProvenVia::ParamEnv
|
TraitGoalProvenVia::ParamEnv
|
||||||
} else {
|
} else {
|
||||||
|
candidates.retain(|c| !matches!(c.source, CandidateSource::ParamEnv(_)));
|
||||||
TraitGoalProvenVia::Misc
|
TraitGoalProvenVia::Misc
|
||||||
};
|
};
|
||||||
|
|
||||||
let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect();
|
let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect();
|
||||||
if let Some(response) = self.try_merge_responses(&all_candidates) {
|
if let Some(response) = self.try_merge_responses(&all_candidates) {
|
||||||
Ok((response, Some(proven_via)))
|
Ok((response, Some(proven_via)))
|
||||||
|
|
|
@ -34,9 +34,17 @@ where
|
||||||
MultipleNested: Trait,
|
MultipleNested: Trait,
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
// We ignore the trivially true global where-bounds when checking that this
|
||||||
|
// impl is well-formed, meaning that we depend on `MultipleNested: Trait` when
|
||||||
|
// recursively proving `MultipleCandidates: Trait`.
|
||||||
|
//
|
||||||
|
// These overflow errors will disappear once we treat these cycles as either
|
||||||
|
// productive or an error.
|
||||||
impl Trait for MultipleNested
|
impl Trait for MultipleNested
|
||||||
|
//~^ ERROR overflow evaluating the requirement `MultipleNested: Trait`
|
||||||
where
|
where
|
||||||
MultipleCandidates: Trait,
|
MultipleCandidates: Trait,
|
||||||
|
//~^ ERROR overflow evaluating the requirement `MultipleCandidates: Trait`
|
||||||
DoesNotImpl: Trait,
|
DoesNotImpl: Trait,
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,29 @@
|
||||||
|
error[E0275]: overflow evaluating the requirement `MultipleNested: Trait`
|
||||||
|
--> $DIR/inductive-cycle-but-err.rs:43:16
|
||||||
|
|
|
||||||
|
LL | impl Trait for MultipleNested
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0275]: overflow evaluating the requirement `MultipleCandidates: Trait`
|
||||||
|
--> $DIR/inductive-cycle-but-err.rs:46:25
|
||||||
|
|
|
||||||
|
LL | MultipleCandidates: Trait,
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
error[E0277]: the trait bound `MultipleCandidates: Trait` is not satisfied
|
error[E0277]: the trait bound `MultipleCandidates: Trait` is not satisfied
|
||||||
--> $DIR/inductive-cycle-but-err.rs:46:19
|
--> $DIR/inductive-cycle-but-err.rs:54:19
|
||||||
|
|
|
|
||||||
LL | impls_trait::<MultipleCandidates>();
|
LL | impls_trait::<MultipleCandidates>();
|
||||||
| ^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `MultipleCandidates`
|
| ^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `MultipleCandidates`
|
||||||
|
|
|
|
||||||
= help: the trait `Trait` is implemented for `MultipleCandidates`
|
= help: the trait `Trait` is implemented for `MultipleCandidates`
|
||||||
note: required by a bound in `impls_trait`
|
note: required by a bound in `impls_trait`
|
||||||
--> $DIR/inductive-cycle-but-err.rs:43:19
|
--> $DIR/inductive-cycle-but-err.rs:51:19
|
||||||
|
|
|
|
||||||
LL | fn impls_trait<T: Trait>() {}
|
LL | fn impls_trait<T: Trait>() {}
|
||||||
| ^^^^^ required by this bound in `impls_trait`
|
| ^^^^^ required by this bound in `impls_trait`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
Some errors have detailed explanations: E0275, E0277.
|
||||||
|
For more information about an error, try `rustc --explain E0275`.
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
//@ revisions: current next
|
||||||
|
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
// Regression test for trait-system-refactor-initiative#172.
|
||||||
|
//
|
||||||
|
// In this test the global where-bound simply constrains the
|
||||||
|
// object lifetime bound to 'static while the builtin impl
|
||||||
|
// ends up also emitting a `dyn Any: 'static` type outlives
|
||||||
|
// constraint. This previously resulted in ambiguity. We now
|
||||||
|
// always prefer the impl.
|
||||||
|
|
||||||
|
pub trait Any: 'static {}
|
||||||
|
|
||||||
|
pub trait Downcast<T>: Any
|
||||||
|
where
|
||||||
|
T: Any,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// elided object lifetime: `dyn Any + 'static`
|
||||||
|
impl dyn Any {
|
||||||
|
pub fn is<T>(&self)
|
||||||
|
where
|
||||||
|
T: Any,
|
||||||
|
// elaboration adds global where-clause `dyn Any + 'static: Any`
|
||||||
|
Self: Downcast<T>,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,29 @@
|
||||||
|
//@ revisions: current next
|
||||||
|
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
// Regression test for trait-system-refactor-initiative#172.
|
||||||
|
//
|
||||||
|
// The next-generation trait solver previously simply tried
|
||||||
|
// to merge the global where-bounds with the impl candidates.
|
||||||
|
// This caused ambiguity in case the where-bound had stricter
|
||||||
|
// region requirements than the impl.
|
||||||
|
|
||||||
|
trait Trait {}
|
||||||
|
struct Foo<'a, 'b>(&'a (), &'b ());
|
||||||
|
impl<'a> Trait for Foo<'a, 'static> {}
|
||||||
|
|
||||||
|
fn impls_trait<T: Trait>() {}
|
||||||
|
fn foo()
|
||||||
|
where
|
||||||
|
Foo<'static, 'static>: Trait,
|
||||||
|
{
|
||||||
|
// impl requires `'1 to be 'static
|
||||||
|
// global where-bound requires both '0 and '1 to be 'static
|
||||||
|
//
|
||||||
|
// we always prefer the impl here.
|
||||||
|
impls_trait::<Foo<'_, '_>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue