Skip to content

Commit b21c5cd

Browse files
authored
Rollup merge of #139798 - lcnr:where-bounds-gt-alias-bound, r=compiler-errors
normalize: prefer `ParamEnv` over `AliasBound` candidates cc rust-lang/trait-system-refactor-initiative#175 not the only issue affecting bevy sadly r? ``@compiler-errors``
2 parents e8c9dcc + 9c88eb6 commit b21c5cd

File tree

2 files changed

+59
-21
lines changed

2 files changed

+59
-21
lines changed

compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs

+30-21
Original file line numberDiff line numberDiff line change
@@ -792,37 +792,46 @@ where
792792
};
793793

794794
match proven_via {
795-
// Even when a trait bound has been proven using a where-bound, we
796-
// still need to consider alias-bounds for normalization, see
797-
// tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
798-
//
799-
// FIXME(const_trait_impl): should this behavior also be used by
800-
// constness checking. Doing so is *at least theoretically* breaking,
801-
// see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
802795
TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => {
803-
let mut candidates_from_env_and_bounds: Vec<_> = candidates
804-
.iter()
805-
.filter(|c| {
806-
matches!(
807-
c.source,
808-
CandidateSource::AliasBound | CandidateSource::ParamEnv(_)
809-
)
810-
})
811-
.map(|c| c.result)
812-
.collect();
796+
let mut considered_candidates = Vec::new();
797+
considered_candidates.extend(
798+
candidates
799+
.iter()
800+
.filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
801+
.map(|c| c.result),
802+
);
803+
804+
// Even when a trait bound has been proven using a where-bound, we
805+
// still need to consider alias-bounds for normalization, see
806+
// tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
807+
//
808+
// We still need to prefer where-bounds over alias-bounds however.
809+
// See tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs.
810+
//
811+
// FIXME(const_trait_impl): should this behavior also be used by
812+
// constness checking. Doing so is *at least theoretically* breaking,
813+
// see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
814+
if considered_candidates.is_empty() {
815+
considered_candidates.extend(
816+
candidates
817+
.iter()
818+
.filter(|c| matches!(c.source, CandidateSource::AliasBound))
819+
.map(|c| c.result),
820+
);
821+
}
813822

814823
// If the trait goal has been proven by using the environment, we want to treat
815824
// aliases as rigid if there are no applicable projection bounds in the environment.
816-
if candidates_from_env_and_bounds.is_empty() {
825+
if considered_candidates.is_empty() {
817826
if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
818-
candidates_from_env_and_bounds.push(response);
827+
considered_candidates.push(response);
819828
}
820829
}
821830

822-
if let Some(response) = self.try_merge_responses(&candidates_from_env_and_bounds) {
831+
if let Some(response) = self.try_merge_responses(&considered_candidates) {
823832
Ok(response)
824833
} else {
825-
self.flounder(&candidates_from_env_and_bounds)
834+
self.flounder(&considered_candidates)
826835
}
827836
}
828837
TraitGoalProvenVia::Misc => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//@ revisions: current next
2+
//@ ignore-compare-mode-next-solver (explicit revisions)
3+
//@[next] compile-flags: -Znext-solver
4+
//@ check-pass
5+
6+
// Make sure we prefer the `I::IntoIterator: Iterator<Item = ()>`
7+
// where-bound over the `I::Intoiterator: Iterator<Item = I::Item>`
8+
// alias-bound.
9+
10+
trait Iterator {
11+
type Item;
12+
}
13+
14+
trait IntoIterator {
15+
type Item;
16+
type IntoIter: Iterator<Item = Self::Item>;
17+
}
18+
19+
fn normalize<I: Iterator<Item = ()>>() {}
20+
21+
fn foo<I>()
22+
where
23+
I: IntoIterator,
24+
I::IntoIter: Iterator<Item = ()>,
25+
{
26+
normalize::<I::IntoIter>();
27+
}
28+
29+
fn main() {}

0 commit comments

Comments
 (0)