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.rs82
1 files changed, 60 insertions, 22 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 77809d8d2..75a99f799 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -1,21 +1,27 @@
-//! The new trait solver, currently still WIP.
+//! The next-generation trait solver, currently still WIP.
//!
-//! As a user of the trait system, you can use `TyCtxt::evaluate_goal` to
-//! interact with this solver.
+//! As a user of rust, you can use `-Ztrait-solver=next` or `next-coherence`
+//! to enable the new trait solver always, or just within coherence, respectively.
+//!
+//! As a developer of rustc, you shouldn't be using the new trait
+//! solver without asking the trait-system-refactor-initiative, but it can
+//! be enabled with `InferCtxtBuilder::with_next_trait_solver`. This will
+//! ensure that trait solving using that inference context will be routed
+//! to the new trait solver.
//!
//! For a high-level overview of how this solver works, check out the relevant
//! section of the rustc-dev-guide.
//!
//! FIXME(@lcnr): Write that section. If you read this before then ask me
//! about it on zulip.
-
use rustc_hir::def_id::DefId;
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
use rustc_infer::traits::query::NoSolution;
+use rustc_middle::infer::canonical::CanonicalVarInfos;
use rustc_middle::traits::solve::{
CanonicalResponse, Certainty, ExternalConstraintsData, Goal, QueryResult, Response,
};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex};
use rustc_middle::ty::{
CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, TypeOutlivesPredicate,
};
@@ -25,6 +31,7 @@ mod assembly;
mod canonicalize;
mod eval_ctxt;
mod fulfill;
+mod inherent_projection;
pub mod inspect;
mod normalize;
mod opaques;
@@ -37,7 +44,7 @@ pub use eval_ctxt::{
EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt, UseGlobalCache,
};
pub use fulfill::FulfillmentCtxt;
-pub(crate) use normalize::deeply_normalize;
+pub(crate) use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
#[derive(Debug, Clone, Copy)]
enum SolverMode {
@@ -123,10 +130,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn compute_closure_kind_goal(
&mut self,
- goal: Goal<'tcx, (DefId, ty::SubstsRef<'tcx>, ty::ClosureKind)>,
+ goal: Goal<'tcx, (DefId, ty::GenericArgsRef<'tcx>, ty::ClosureKind)>,
) -> QueryResult<'tcx> {
- let (_, substs, expected_kind) = goal.predicate;
- let found_kind = substs.as_closure().kind_ty().to_opt_closure_kind();
+ let (_, args, expected_kind) = goal.predicate;
+ let found_kind = args.as_closure().kind_ty().to_opt_closure_kind();
let Some(found_kind) = found_kind else {
return self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
@@ -266,33 +273,64 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
return Err(NoSolution);
}
- let Certainty::Maybe(maybe_cause) = responses.iter().fold(
- Certainty::AMBIGUOUS,
- |certainty, response| {
+ let Certainty::Maybe(maybe_cause) =
+ responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| {
certainty.unify_with(response.value.certainty)
- },
- ) else {
+ })
+ else {
bug!("expected flounder response to be ambiguous")
};
Ok(self.make_ambiguous_response_no_constraints(maybe_cause))
}
+
+ /// Normalize a type when it is structually matched on.
+ ///
+ /// For self types this is generally already handled through
+ /// `assemble_candidates_after_normalizing_self_ty`, so anything happening
+ /// in [`EvalCtxt::assemble_candidates_via_self_ty`] does not have to normalize
+ /// the self type. It is required when structurally matching on any other
+ /// arguments of a trait goal, e.g. when assembling builtin unsize candidates.
+ fn try_normalize_ty(
+ &mut self,
+ param_env: ty::ParamEnv<'tcx>,
+ mut ty: Ty<'tcx>,
+ ) -> Result<Option<Ty<'tcx>>, NoSolution> {
+ for _ in 0..self.local_overflow_limit() {
+ let ty::Alias(_, projection_ty) = *ty.kind() else {
+ return Ok(Some(ty));
+ };
+
+ let normalized_ty = self.next_ty_infer();
+ let normalizes_to_goal = Goal::new(
+ self.tcx(),
+ param_env,
+ ty::ProjectionPredicate { projection_ty, term: normalized_ty.into() },
+ );
+ self.add_goal(normalizes_to_goal);
+ self.try_evaluate_added_goals()?;
+ ty = self.resolve_vars_if_possible(normalized_ty);
+ }
+
+ Ok(None)
+ }
}
-pub(super) fn response_no_constraints<'tcx>(
+fn response_no_constraints_raw<'tcx>(
tcx: TyCtxt<'tcx>,
- goal: Canonical<'tcx, impl Sized>,
+ max_universe: UniverseIndex,
+ variables: CanonicalVarInfos<'tcx>,
certainty: Certainty,
-) -> QueryResult<'tcx> {
- Ok(Canonical {
- max_universe: goal.max_universe,
- variables: goal.variables,
+) -> CanonicalResponse<'tcx> {
+ Canonical {
+ max_universe,
+ variables,
value: Response {
- var_values: CanonicalVarValues::make_identity(tcx, goal.variables),
+ var_values: CanonicalVarValues::make_identity(tcx, variables),
// FIXME: maybe we should store the "no response" version in tcx, like
// we do for tcx.types and stuff.
external_constraints: tcx.mk_external_constraints(ExternalConstraintsData::default()),
certainty,
},
- })
+ }
}