X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=inline;f=compiler%2Frustc_trait_selection%2Fsrc%2Fsolve%2Fmod.rs;h=dd16672cc7a0110fe6917dd9d73f45c7cbf925f4;hb=d117135f5a9b69ee3adfb1918aa25616758bf692;hp=f44648c95d742530298274dc3467dc6645e127e6;hpb=4b97f075342c0597cedd36d8d901c6ac84651f73;p=rust.git diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index f44648c95d7..dd16672cc7a 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -13,14 +13,12 @@ // preserves universes and creates a unique var (in the highest universe) for each // appearance of a region. -// FIXME: `CanonicalVarValues` should be interned and `Copy`. - // FIXME: uses of `infcx.at` need to enable deferred projection equality once that's implemented. use std::mem; use rustc_hir::def_id::DefId; -use rustc_infer::infer::canonical::{Canonical, CanonicalVarKind, CanonicalVarValues}; +use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse}; use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_infer::traits::query::NoSolution; @@ -141,17 +139,6 @@ pub struct ExternalConstraints<'tcx> { /// solver, merge the two responses again. pub type QueryResult<'tcx> = Result, NoSolution>; -pub trait TyCtxtExt<'tcx> { - fn evaluate_goal(self, goal: CanonicalGoal<'tcx>) -> QueryResult<'tcx>; -} - -impl<'tcx> TyCtxtExt<'tcx> for TyCtxt<'tcx> { - fn evaluate_goal(self, goal: CanonicalGoal<'tcx>) -> QueryResult<'tcx> { - let mut search_graph = search_graph::SearchGraph::new(self); - EvalCtxt::evaluate_canonical_goal(self, &mut search_graph, goal) - } -} - pub trait InferCtxtEvalExt<'tcx> { /// Evaluates a goal from **outside** of the trait solver. /// @@ -194,6 +181,15 @@ fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } + /// The entry point of the solver. + /// + /// This function deals with (coinductive) cycles, overflow, and caching + /// and then calls [`EvalCtxt::compute_goal`] which contains the actual + /// logic of the solver. + /// + /// Instead of calling this function directly, use either [EvalCtxt::evaluate_goal] + /// if you're inside of the solver or [InferCtxtEvalExt::evaluate_root_goal] if you're + /// outside of it. #[instrument(level = "debug", skip(tcx, search_graph), ret)] fn evaluate_canonical_goal( tcx: TyCtxt<'tcx>, @@ -227,7 +223,7 @@ fn make_canonical_response(&self, certainty: Certainty) -> QueryResult<'tcx> { let external_constraints = take_external_constraints(self.infcx)?; Ok(self.infcx.canonicalize_response(Response { - var_values: self.var_values.clone(), + var_values: self.var_values, external_constraints, certainty, })) @@ -337,15 +333,13 @@ fn compute_subtype_goal( // That won't actually reflect in the query response, so it seems moot. self.make_canonical_response(Certainty::AMBIGUOUS) } else { - self.infcx.probe(|_| { - let InferOk { value: (), obligations } = self - .infcx - .at(&ObligationCause::dummy(), goal.param_env) - .sub(goal.predicate.a, goal.predicate.b)?; - self.evaluate_all_and_make_canonical_response( - obligations.into_iter().map(|pred| pred.into()).collect(), - ) - }) + let InferOk { value: (), obligations } = self + .infcx + .at(&ObligationCause::dummy(), goal.param_env) + .sub(goal.predicate.a, goal.predicate.b)?; + self.evaluate_all_and_make_canonical_response( + obligations.into_iter().map(|pred| pred.into()).collect(), + ) } } @@ -367,7 +361,7 @@ fn compute_closure_kind_goal( } fn compute_object_safe_goal(&mut self, trait_def_id: DefId) -> QueryResult<'tcx> { - if self.tcx().is_object_safe(trait_def_id) { + if self.tcx().check_is_object_safe(trait_def_id) { self.make_canonical_response(Certainty::Yes) } else { Err(NoSolution) @@ -378,22 +372,22 @@ fn compute_well_formed_goal( &mut self, goal: Goal<'tcx, ty::GenericArg<'tcx>>, ) -> QueryResult<'tcx> { - self.infcx.probe(|_| { - match crate::traits::wf::unnormalized_obligations( - self.infcx, - goal.param_env, - goal.predicate, - ) { - Some(obligations) => self.evaluate_all_and_make_canonical_response( - obligations.into_iter().map(|o| o.into()).collect(), - ), - None => self.make_canonical_response(Certainty::AMBIGUOUS), - } - }) + match crate::traits::wf::unnormalized_obligations( + self.infcx, + goal.param_env, + goal.predicate, + ) { + Some(obligations) => self.evaluate_all_and_make_canonical_response( + obligations.into_iter().map(|o| o.into()).collect(), + ), + None => self.make_canonical_response(Certainty::AMBIGUOUS), + } } } impl<'tcx> EvalCtxt<'_, 'tcx> { + // Recursively evaluates a list of goals to completion, returning the certainty + // of all of the goals. fn evaluate_all( &mut self, mut goals: Vec>>, @@ -430,6 +424,10 @@ fn evaluate_all( }) } + // Recursively evaluates a list of goals to completion, making a query response. + // + // This is just a convenient way of calling [`EvalCtxt::evaluate_all`], + // then [`EvalCtxt::make_canonical_response`]. fn evaluate_all_and_make_canonical_response( &mut self, goals: Vec>>, @@ -483,32 +481,11 @@ pub(super) fn response_no_constraints<'tcx>( goal: Canonical<'tcx, impl Sized>, certainty: Certainty, ) -> QueryResult<'tcx> { - let var_values = goal - .variables - .iter() - .enumerate() - .map(|(i, info)| match info.kind { - CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => { - tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into())).into() - } - CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => { - let br = ty::BoundRegion { - var: ty::BoundVar::from_usize(i), - kind: ty::BrAnon(i as u32, None), - }; - tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into() - } - CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => tcx - .mk_const(ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)), ty) - .into(), - }) - .collect(); - Ok(Canonical { max_universe: goal.max_universe, variables: goal.variables, value: Response { - var_values: CanonicalVarValues { var_values }, + var_values: CanonicalVarValues::make_identity(tcx, goal.variables), external_constraints: Default::default(), certainty, },