Rollup merge of #139798 - lcnr:where-bounds-gt-alias-bound, r=compiler-errors
normalize: prefer `ParamEnv` over `AliasBound` candidates cc https://github.com/rust-lang/trait-system-refactor-initiative/issues/175 not the only issue affecting bevy sadly r? ``@compiler-errors``
This commit is contained in:
commit
b21c5cd025
2 changed files with 59 additions and 21 deletions
|
@ -792,37 +792,46 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
match proven_via {
|
match proven_via {
|
||||||
// Even when a trait bound has been proven using a where-bound, we
|
|
||||||
// still need to consider alias-bounds for normalization, see
|
|
||||||
// tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
|
|
||||||
//
|
|
||||||
// FIXME(const_trait_impl): should this behavior also be used by
|
|
||||||
// constness checking. Doing so is *at least theoretically* breaking,
|
|
||||||
// see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
|
|
||||||
TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => {
|
TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => {
|
||||||
let mut candidates_from_env_and_bounds: Vec<_> = candidates
|
let mut considered_candidates = Vec::new();
|
||||||
.iter()
|
considered_candidates.extend(
|
||||||
.filter(|c| {
|
candidates
|
||||||
matches!(
|
.iter()
|
||||||
c.source,
|
.filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
|
||||||
CandidateSource::AliasBound | CandidateSource::ParamEnv(_)
|
.map(|c| c.result),
|
||||||
)
|
);
|
||||||
})
|
|
||||||
.map(|c| c.result)
|
// Even when a trait bound has been proven using a where-bound, we
|
||||||
.collect();
|
// still need to consider alias-bounds for normalization, see
|
||||||
|
// tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
|
||||||
|
//
|
||||||
|
// We still need to prefer where-bounds over alias-bounds however.
|
||||||
|
// See tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs.
|
||||||
|
//
|
||||||
|
// FIXME(const_trait_impl): should this behavior also be used by
|
||||||
|
// constness checking. Doing so is *at least theoretically* breaking,
|
||||||
|
// see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
|
||||||
|
if considered_candidates.is_empty() {
|
||||||
|
considered_candidates.extend(
|
||||||
|
candidates
|
||||||
|
.iter()
|
||||||
|
.filter(|c| matches!(c.source, CandidateSource::AliasBound))
|
||||||
|
.map(|c| c.result),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// If the trait goal has been proven by using the environment, we want to treat
|
// If the trait goal has been proven by using the environment, we want to treat
|
||||||
// aliases as rigid if there are no applicable projection bounds in the environment.
|
// aliases as rigid if there are no applicable projection bounds in the environment.
|
||||||
if candidates_from_env_and_bounds.is_empty() {
|
if considered_candidates.is_empty() {
|
||||||
if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
|
if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
|
||||||
candidates_from_env_and_bounds.push(response);
|
considered_candidates.push(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(response) = self.try_merge_responses(&candidates_from_env_and_bounds) {
|
if let Some(response) = self.try_merge_responses(&considered_candidates) {
|
||||||
Ok(response)
|
Ok(response)
|
||||||
} else {
|
} else {
|
||||||
self.flounder(&candidates_from_env_and_bounds)
|
self.flounder(&considered_candidates)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TraitGoalProvenVia::Misc => {
|
TraitGoalProvenVia::Misc => {
|
||||||
|
|
29
tests/ui/traits/winnowing/norm-where-bound-gt-alias-bound.rs
Normal file
29
tests/ui/traits/winnowing/norm-where-bound-gt-alias-bound.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
//@ revisions: current next
|
||||||
|
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
// Make sure we prefer the `I::IntoIterator: Iterator<Item = ()>`
|
||||||
|
// where-bound over the `I::Intoiterator: Iterator<Item = I::Item>`
|
||||||
|
// alias-bound.
|
||||||
|
|
||||||
|
trait Iterator {
|
||||||
|
type Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait IntoIterator {
|
||||||
|
type Item;
|
||||||
|
type IntoIter: Iterator<Item = Self::Item>;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn normalize<I: Iterator<Item = ()>>() {}
|
||||||
|
|
||||||
|
fn foo<I>()
|
||||||
|
where
|
||||||
|
I: IntoIterator,
|
||||||
|
I::IntoIter: Iterator<Item = ()>,
|
||||||
|
{
|
||||||
|
normalize::<I::IntoIter>();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue