Skip to content

Commit 2cdb7fa

Browse files
Prefer param-env candidates even when alias's trait bound isn't proven via param-env
1 parent 2162e9d commit 2cdb7fa

File tree

1 file changed

+29
-8
lines changed
  • compiler/rustc_next_trait_solver/src/solve/assembly

1 file changed

+29
-8
lines changed

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

+29-8
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,7 @@ where
791791
return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Ambiguity));
792792
};
793793

794-
let responses: Vec<_> = match proven_via {
794+
match proven_via {
795795
// Even when a trait bound has been proven using a where-bound, we
796796
// still need to consider alias-bounds for normalization, see
797797
// tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
@@ -800,7 +800,7 @@ where
800800
// constness checking. Doing so is *at least theoretically* breaking,
801801
// see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
802802
TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => {
803-
let mut candidates_from_env: Vec<_> = candidates
803+
let mut candidates_from_env_and_bounds: Vec<_> = candidates
804804
.iter()
805805
.filter(|c| {
806806
matches!(
@@ -813,16 +813,37 @@ where
813813

814814
// If the trait goal has been proven by using the environment, we want to treat
815815
// aliases as rigid if there are no applicable projection bounds in the environment.
816-
if candidates_from_env.is_empty() {
816+
if candidates_from_env_and_bounds.is_empty() {
817817
if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
818-
candidates_from_env.push(response);
818+
candidates_from_env_and_bounds.push(response);
819819
}
820820
}
821-
candidates_from_env
821+
822+
if let Some(response) = self.try_merge_responses(&candidates_from_env_and_bounds) {
823+
Ok(response)
824+
} else {
825+
self.flounder(&candidates_from_env_and_bounds)
826+
}
822827
}
823-
TraitGoalProvenVia::Misc => candidates.iter().map(|c| c.result).collect(),
824-
};
828+
TraitGoalProvenVia::Misc => {
829+
// Prefer "orphaned" param-env normalization predicates, which are used
830+
// (for example, and ideally only) when proving item bounds for an impl.
831+
let candidates_from_env: Vec<_> = candidates
832+
.iter()
833+
.filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
834+
.map(|c| c.result)
835+
.collect();
836+
if let Some(response) = self.try_merge_responses(&candidates_from_env) {
837+
return Ok(response);
838+
}
825839

826-
self.try_merge_responses(&responses).map_or_else(|| self.flounder(&responses), Ok)
840+
let responses: Vec<_> = candidates.iter().map(|c| c.result).collect();
841+
if let Some(response) = self.try_merge_responses(&responses) {
842+
Ok(response)
843+
} else {
844+
self.flounder(&responses)
845+
}
846+
}
847+
}
827848
}
828849
}

0 commit comments

Comments
 (0)