summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/solve/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve/mod.rs')
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs99
1 files changed, 58 insertions, 41 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 19bcbd461..56a254d9c 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -24,6 +24,7 @@ mod assembly;
mod canonicalize;
mod eval_ctxt;
mod fulfill;
+mod opaques;
mod project_goals;
mod search_graph;
mod trait_goals;
@@ -212,7 +213,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
);
}
- match (lhs.to_projection_term(tcx), rhs.to_projection_term(tcx)) {
+ match (lhs.to_alias_ty(tcx), rhs.to_alias_ty(tcx)) {
(None, None) => bug!("`AliasRelate` goal without an alias on either lhs or rhs"),
// RHS is not a projection, only way this is true is if LHS normalizes-to RHS
@@ -230,44 +231,60 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
let mut candidates = Vec::new();
// LHS normalizes-to RHS
- candidates.extend(
- evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No).ok(),
- );
+ candidates.extend(evaluate_normalizes_to(
+ self,
+ alias_lhs,
+ rhs,
+ direction,
+ Invert::No,
+ ));
// RHS normalizes-to RHS
- candidates.extend(
- evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes).ok(),
- );
+ candidates.extend(evaluate_normalizes_to(
+ self,
+ alias_rhs,
+ lhs,
+ direction,
+ Invert::Yes,
+ ));
// Relate via substs
- candidates.extend(
- self.probe(|ecx| {
- let span = tracing::span!(
- tracing::Level::DEBUG,
- "compute_alias_relate_goal(relate_via_substs)",
- ?alias_lhs,
- ?alias_rhs,
- ?direction
- );
- let _enter = span.enter();
-
- match direction {
- ty::AliasRelationDirection::Equate => {
- ecx.eq(goal.param_env, alias_lhs, alias_rhs)?;
- }
- ty::AliasRelationDirection::Subtype => {
- ecx.sub(goal.param_env, alias_lhs, alias_rhs)?;
- }
+ let subst_relate_response = self.probe(|ecx| {
+ let span = tracing::span!(
+ tracing::Level::DEBUG,
+ "compute_alias_relate_goal(relate_via_substs)",
+ ?alias_lhs,
+ ?alias_rhs,
+ ?direction
+ );
+ let _enter = span.enter();
+
+ match direction {
+ ty::AliasRelationDirection::Equate => {
+ ecx.eq(goal.param_env, alias_lhs, alias_rhs)?;
+ }
+ ty::AliasRelationDirection::Subtype => {
+ ecx.sub(goal.param_env, alias_lhs, alias_rhs)?;
}
+ }
- ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
- })
- .ok(),
- );
+ ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ });
+ candidates.extend(subst_relate_response);
debug!(?candidates);
if let Some(merged) = self.try_merge_responses(&candidates) {
Ok(merged)
} else {
- self.flounder(&candidates)
+ // When relating two aliases and we have ambiguity, we prefer
+ // relating the generic arguments of the aliases over normalizing
+ // them. This is necessary for inference during typeck.
+ //
+ // As this is incomplete, we must not do so during coherence.
+ match (self.solver_mode(), subst_relate_response) {
+ (SolverMode::Normal, Ok(response)) => Ok(response),
+ (SolverMode::Normal, Err(NoSolution)) | (SolverMode::Coherence, _) => {
+ self.flounder(&candidates)
+ }
+ }
}
}
}
@@ -340,17 +357,17 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
if responses.is_empty() {
return Err(NoSolution);
}
- let certainty = responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| {
- certainty.unify_with(response.value.certainty)
- });
-
- let response = self.evaluate_added_goals_and_make_canonical_response(certainty);
- if let Ok(response) = response {
- assert!(response.has_no_inference_or_external_constraints());
- Ok(response)
- } else {
- bug!("failed to make floundered response: {responses:?}");
- }
+
+ let Certainty::Maybe(maybe_cause) = responses.iter().fold(
+ Certainty::AMBIGUOUS,
+ |certainty, response| {
+ certainty.unify_with(response.value.certainty)
+ },
+ ) else {
+ bug!("expected flounder response to be ambiguous")
+ };
+
+ Ok(self.make_ambiguous_response_no_constraints(maybe_cause))
}
}