summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/solve/mod.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /compiler/rustc_trait_selection/src/solve/mod.rs
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve/mod.rs')
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs166
1 files changed, 37 insertions, 129 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 56a254d9c..77809d8d2 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -20,17 +20,24 @@ use rustc_middle::ty::{
CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, TypeOutlivesPredicate,
};
+mod alias_relate;
mod assembly;
mod canonicalize;
mod eval_ctxt;
mod fulfill;
+pub mod inspect;
+mod normalize;
mod opaques;
mod project_goals;
mod search_graph;
mod trait_goals;
+mod weak_types;
-pub use eval_ctxt::{EvalCtxt, InferCtxtEvalExt};
+pub use eval_ctxt::{
+ EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt, UseGlobalCache,
+};
pub use fulfill::FulfillmentCtxt;
+pub(crate) use normalize::deeply_normalize;
#[derive(Debug, Clone, Copy)]
enum SolverMode {
@@ -154,139 +161,40 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
}
}
- #[instrument(level = "debug", skip(self), ret)]
- fn compute_alias_relate_goal(
+ #[instrument(level = "debug", skip(self))]
+ fn compute_const_evaluatable_goal(
&mut self,
- goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>, ty::AliasRelationDirection)>,
+ Goal { param_env, predicate: ct }: Goal<'tcx, ty::Const<'tcx>>,
) -> QueryResult<'tcx> {
- let tcx = self.tcx();
- // We may need to invert the alias relation direction if dealing an alias on the RHS.
- #[derive(Debug)]
- enum Invert {
- No,
- Yes,
- }
- let evaluate_normalizes_to =
- |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other, direction, invert| {
- let span = tracing::span!(
- tracing::Level::DEBUG,
- "compute_alias_relate_goal(evaluate_normalizes_to)",
- ?alias,
- ?other,
- ?direction,
- ?invert
- );
- let _enter = span.enter();
- let result = ecx.probe(|ecx| {
- let other = match direction {
- // This is purely an optimization.
- ty::AliasRelationDirection::Equate => other,
-
- ty::AliasRelationDirection::Subtype => {
- let fresh = ecx.next_term_infer_of_kind(other);
- let (sub, sup) = match invert {
- Invert::No => (fresh, other),
- Invert::Yes => (other, fresh),
- };
- ecx.sub(goal.param_env, sub, sup)?;
- fresh
- }
- };
- ecx.add_goal(goal.with(
- tcx,
- ty::Binder::dummy(ty::ProjectionPredicate {
- projection_ty: alias,
- term: other,
- }),
- ));
- ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
- });
- debug!(?result);
- result
- };
-
- let (lhs, rhs, direction) = goal.predicate;
-
- if lhs.is_infer() || rhs.is_infer() {
- bug!(
- "`AliasRelate` goal with an infer var on lhs or rhs which should have been instantiated"
- );
- }
-
- 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
- (Some(alias_lhs), None) => {
- evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No)
- }
-
- // LHS is not a projection, only way this is true is if RHS normalizes-to LHS
- (None, Some(alias_rhs)) => {
- evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes)
- }
-
- (Some(alias_lhs), Some(alias_rhs)) => {
- debug!("both sides are aliases");
-
- let mut candidates = Vec::new();
- // LHS normalizes-to RHS
- 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,
- ));
- // Relate via substs
- 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)
- });
- candidates.extend(subst_relate_response);
- debug!(?candidates);
-
- if let Some(merged) = self.try_merge_responses(&candidates) {
- Ok(merged)
+ match ct.kind() {
+ ty::ConstKind::Unevaluated(uv) => {
+ // We never return `NoSolution` here as `try_const_eval_resolve` emits an
+ // error itself when failing to evaluate, so emitting an additional fulfillment
+ // error in that case is unnecessary noise. This may change in the future once
+ // evaluation failures are allowed to impact selection, e.g. generic const
+ // expressions in impl headers or `where`-clauses.
+
+ // FIXME(generic_const_exprs): Implement handling for generic
+ // const expressions here.
+ if let Some(_normalized) = self.try_const_eval_resolve(param_env, uv, ct.ty()) {
+ self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
} else {
- // 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)
- }
- }
+ self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
}
+ ty::ConstKind::Infer(_) => {
+ self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
+ }
+ ty::ConstKind::Placeholder(_) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => {
+ self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ }
+ // We can freely ICE here as:
+ // - `Param` gets replaced with a placeholder during canonicalization
+ // - `Bound` cannot exist as we don't have a binder around the self Type
+ // - `Expr` is part of `feature(generic_const_exprs)` and is not implemented yet
+ ty::ConstKind::Param(_) | ty::ConstKind::Bound(_, _) | ty::ConstKind::Expr(_) => {
+ bug!("unexpect const kind: {:?}", ct)
+ }
}
}