Struct rustc_trait_selection::solve::EvalCtxt
source · pub struct EvalCtxt<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
pub(super) var_values: CanonicalVarValues<'tcx>,
pub(super) max_input_universe: UniverseIndex,
pub(super) search_graph: &'a mut SearchGraph<'tcx>,
pub(super) nested_goals: NestedGoals<'tcx>,
}Fields§
§infcx: &'a InferCtxt<'tcx>The inference context that backs (mostly) inference and placeholder terms instantiated while solving goals.
NOTE: The InferCtxt that backs the EvalCtxt is intentionally private,
because the InferCtxt is much more general than EvalCtxt. Methods such
as take_registered_region_obligations can mess up query responses,
using At::normalize is totally wrong, calling evaluate_root_goal can
cause coinductive unsoundness, etc.
Methods that are generally of use for trait solving are intentionally
re-declared through the EvalCtxt below, often with cleaner signatures
since we don’t care about things like ObligationCauses and Spans here.
If some InferCtxt method is missing, please first think defensively about
the method’s compatibility with this solver, or if an existing one does
the job already.
var_values: CanonicalVarValues<'tcx>§max_input_universe: UniverseIndexThe highest universe index nameable by the caller.
When we enter a new binder inside of the query we create new universes which the caller cannot name. We have to be careful with variables from these new universes when creating the query response.
Both because these new universes can prevent us from reaching a fixpoint if we have a coinductive cycle and because that’s the only way we can return new placeholders to the caller.
search_graph: &'a mut SearchGraph<'tcx>§nested_goals: NestedGoals<'tcx>Implementations§
source§impl<'tcx> EvalCtxt<'_, 'tcx>
impl<'tcx> EvalCtxt<'_, 'tcx>
pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'tcx>>( &mut self, goal: Goal<'tcx, G> ) -> Vec<Candidate<'tcx>>
sourcefn assemble_candidates_after_normalizing_self_ty<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>
)
fn assemble_candidates_after_normalizing_self_ty<G: GoalKind<'tcx>>( &mut self, goal: Goal<'tcx, G>, candidates: &mut Vec<Candidate<'tcx>> )
If the self type of a goal is a projection, computing the relevant candidates is difficult.
To deal with this, we first try to normalize the self type and add the candidates for the normalized self type to the list of candidates in case that succeeds. We also have to consider candidates with the projection as a self type as well
fn assemble_impl_candidates<G: GoalKind<'tcx>>( &mut self, goal: Goal<'tcx, G>, candidates: &mut Vec<Candidate<'tcx>> )
fn assemble_builtin_impl_candidates<G: GoalKind<'tcx>>( &mut self, goal: Goal<'tcx, G>, candidates: &mut Vec<Candidate<'tcx>> )
fn assemble_param_env_candidates<G: GoalKind<'tcx>>( &mut self, goal: Goal<'tcx, G>, candidates: &mut Vec<Candidate<'tcx>> )
fn assemble_alias_bound_candidates<G: GoalKind<'tcx>>( &mut self, goal: Goal<'tcx, G>, candidates: &mut Vec<Candidate<'tcx>> )
fn assemble_object_bound_candidates<G: GoalKind<'tcx>>( &mut self, goal: Goal<'tcx, G>, candidates: &mut Vec<Candidate<'tcx>> )
fn assemble_coherence_unknowable_candidates<G: GoalKind<'tcx>>( &mut self, goal: Goal<'tcx, G>, candidates: &mut Vec<Candidate<'tcx>> )
pub(super) fn merge_candidates( &mut self, candidates: Vec<Candidate<'tcx>> ) -> QueryResult<'tcx>
fn candidate_should_be_dropped_in_favor_of( &self, candidate: &Candidate<'tcx>, other: &Candidate<'tcx> ) -> bool
source§impl<'tcx> EvalCtxt<'_, 'tcx>
impl<'tcx> EvalCtxt<'_, 'tcx>
sourcepub(super) fn canonicalize_goal(
&self,
goal: Goal<'tcx, Predicate<'tcx>>
) -> (Vec<GenericArg<'tcx>>, CanonicalGoal<'tcx>)
pub(super) fn canonicalize_goal( &self, goal: Goal<'tcx, Predicate<'tcx>> ) -> (Vec<GenericArg<'tcx>>, CanonicalGoal<'tcx>)
Canonicalizes the goal remembering the original values for each bound variable.
sourcepub(in solve) fn evaluate_added_goals_and_make_canonical_response(
&mut self,
certainty: Certainty
) -> QueryResult<'tcx>
pub(in solve) fn evaluate_added_goals_and_make_canonical_response( &mut self, certainty: Certainty ) -> QueryResult<'tcx>
To return the constraints of a canonical query to the caller, we canonicalize:
var_values: a map from bound variables in the canonical goal to the values inferred while solving the instantiated goal.external_constraints: additional constraints which aren’t expressable using simple unification of inference variables.
fn compute_external_query_constraints( &self ) -> Result<ExternalConstraints<'tcx>, NoSolution>
sourcepub(super) fn instantiate_and_apply_query_response(
&mut self,
param_env: ParamEnv<'tcx>,
original_values: Vec<GenericArg<'tcx>>,
response: CanonicalResponse<'tcx>
) -> Result<(Certainty, Vec<Goal<'tcx, Predicate<'tcx>>>), NoSolution>
pub(super) fn instantiate_and_apply_query_response( &mut self, param_env: ParamEnv<'tcx>, original_values: Vec<GenericArg<'tcx>>, response: CanonicalResponse<'tcx> ) -> Result<(Certainty, Vec<Goal<'tcx, Predicate<'tcx>>>), NoSolution>
After calling a canonical query, we apply the constraints returned by the query using this function.
This happens in three steps:
- we instantiate the bound variables of the query response
- we unify the
var_valuesof the response with theoriginal_values - we apply the
external_constraintsreturned by the query
sourcefn compute_query_response_substitution(
&self,
original_values: &[GenericArg<'tcx>],
response: &CanonicalResponse<'tcx>
) -> CanonicalVarValues<'tcx>
fn compute_query_response_substitution( &self, original_values: &[GenericArg<'tcx>], response: &CanonicalResponse<'tcx> ) -> CanonicalVarValues<'tcx>
This returns the substitutions to instantiate the bound variables of
the canonical reponse. This depends on the original_values for the
bound variables.
fn unify_query_var_values( &self, param_env: ParamEnv<'tcx>, original_values: &[GenericArg<'tcx>], var_values: CanonicalVarValues<'tcx> ) -> Result<Vec<Goal<'tcx, Predicate<'tcx>>>, NoSolution>
fn register_region_constraints( &mut self, region_constraints: &QueryRegionConstraints<'tcx> )
source§impl<'a, 'tcx> EvalCtxt<'a, 'tcx>
impl<'a, 'tcx> EvalCtxt<'a, 'tcx>
pub(super) fn solver_mode(&self) -> SolverMode
sourcefn evaluate_canonical_goal(
tcx: TyCtxt<'tcx>,
search_graph: &'a mut SearchGraph<'tcx>,
canonical_goal: CanonicalGoal<'tcx>
) -> QueryResult<'tcx>
fn evaluate_canonical_goal( tcx: TyCtxt<'tcx>, search_graph: &'a mut SearchGraph<'tcx>, canonical_goal: CanonicalGoal<'tcx> ) -> QueryResult<'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.
sourcefn evaluate_goal(
&mut self,
is_normalizes_to_hack: IsNormalizesToHack,
goal: Goal<'tcx, Predicate<'tcx>>
) -> Result<(bool, Certainty, Vec<Goal<'tcx, Predicate<'tcx>>>), NoSolution>
fn evaluate_goal( &mut self, is_normalizes_to_hack: IsNormalizesToHack, goal: Goal<'tcx, Predicate<'tcx>> ) -> Result<(bool, Certainty, Vec<Goal<'tcx, Predicate<'tcx>>>), NoSolution>
Recursively evaluates goal, returning whether any inference vars have
been constrained and the certainty of the result.
fn compute_goal( &mut self, goal: Goal<'tcx, Predicate<'tcx>> ) -> QueryResult<'tcx>
pub(super) fn try_evaluate_added_goals( &mut self ) -> Result<Certainty, NoSolution>
source§impl<'tcx> EvalCtxt<'_, 'tcx>
impl<'tcx> EvalCtxt<'_, 'tcx>
pub(super) fn probe<T>( &mut self, f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> T ) -> T
pub(super) fn tcx(&self) -> TyCtxt<'tcx>
pub(super) fn next_ty_infer(&self) -> Ty<'tcx>
pub(super) fn next_const_infer(&self, ty: Ty<'tcx>) -> Const<'tcx>
sourcepub(super) fn next_term_infer_of_kind(&self, kind: Term<'tcx>) -> Term<'tcx>
pub(super) fn next_term_infer_of_kind(&self, kind: Term<'tcx>) -> Term<'tcx>
Returns a ty infer or a const infer depending on whether kind is a Ty or Const.
If kind is an integer inference variable this will still return a ty infer var.
sourcepub(super) fn term_is_fully_unconstrained(
&self,
goal: Goal<'tcx, ProjectionPredicate<'tcx>>
) -> bool
pub(super) fn term_is_fully_unconstrained( &self, goal: Goal<'tcx, ProjectionPredicate<'tcx>> ) -> bool
Is the projection predicate is of the form exists<T> <Ty as Trait>::Assoc = T.
This is the case if the term is an inference variable in the innermost universe
and does not occur in any other part of the predicate.
pub(super) fn eq<T: ToTrace<'tcx>>( &mut self, param_env: ParamEnv<'tcx>, lhs: T, rhs: T ) -> Result<(), NoSolution>
pub(super) fn sub<T: ToTrace<'tcx>>( &mut self, param_env: ParamEnv<'tcx>, sub: T, sup: T ) -> Result<(), NoSolution>
sourcepub(super) fn eq_and_get_goals<T: ToTrace<'tcx>>(
&self,
param_env: ParamEnv<'tcx>,
lhs: T,
rhs: T
) -> Result<Vec<Goal<'tcx, Predicate<'tcx>>>, NoSolution>
pub(super) fn eq_and_get_goals<T: ToTrace<'tcx>>( &self, param_env: ParamEnv<'tcx>, lhs: T, rhs: T ) -> Result<Vec<Goal<'tcx, Predicate<'tcx>>>, NoSolution>
Equates two values returning the nested goals without adding them
to the nested goals of the EvalCtxt.
If possible, try using eq instead which automatically handles nested
goals correctly.
pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<TyCtxt<'tcx>> + Copy>( &self, value: Binder<'tcx, T> ) -> T
pub(super) fn instantiate_binder_with_placeholders<T: TypeFoldable<TyCtxt<'tcx>> + Copy>( &self, value: Binder<'tcx, T> ) -> T
pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> Twhere T: TypeFoldable<TyCtxt<'tcx>>,
pub(super) fn fresh_substs_for_item(&self, def_id: DefId) -> SubstsRef<'tcx>
pub(super) fn translate_substs( &self, param_env: ParamEnv<'tcx>, source_impl: DefId, source_substs: SubstsRef<'tcx>, target_node: Node ) -> SubstsRef<'tcx>
pub(super) fn register_ty_outlives(&self, ty: Ty<'tcx>, lt: Region<'tcx>)
pub(super) fn register_region_outlives(&self, a: Region<'tcx>, b: Region<'tcx>)
sourcepub(super) fn well_formed_goals(
&self,
param_env: ParamEnv<'tcx>,
arg: GenericArg<'tcx>
) -> Option<impl Iterator<Item = Goal<'tcx, Predicate<'tcx>>>>
pub(super) fn well_formed_goals( &self, param_env: ParamEnv<'tcx>, arg: GenericArg<'tcx> ) -> Option<impl Iterator<Item = Goal<'tcx, Predicate<'tcx>>>>
Computes the list of goals required for arg to be well-formed
source§impl<'tcx> EvalCtxt<'_, 'tcx>
impl<'tcx> EvalCtxt<'_, 'tcx>
pub(super) fn compute_projection_goal( &mut self, goal: Goal<'tcx, ProjectionPredicate<'tcx>> ) -> QueryResult<'tcx>
source§impl<'tcx> EvalCtxt<'_, 'tcx>
impl<'tcx> EvalCtxt<'_, 'tcx>
sourcefn probe_and_evaluate_goal_for_constituent_tys(
&mut self,
goal: Goal<'tcx, TraitPredicate<'tcx>>,
constituent_tys: impl Fn(&EvalCtxt<'_, 'tcx>, Ty<'tcx>) -> Result<Vec<Ty<'tcx>>, NoSolution>
) -> QueryResult<'tcx>
fn probe_and_evaluate_goal_for_constituent_tys( &mut self, goal: Goal<'tcx, TraitPredicate<'tcx>>, constituent_tys: impl Fn(&EvalCtxt<'_, 'tcx>, Ty<'tcx>) -> Result<Vec<Ty<'tcx>>, NoSolution> ) -> QueryResult<'tcx>
Convenience function for traits that are structural, i.e. that only have nested subgoals that only change the self type. Unlike other evaluate-like helpers, this does a probe, so it doesn’t need to be wrapped in one.
pub(super) fn compute_trait_goal( &mut self, goal: Goal<'tcx, TraitPredicate<'tcx>> ) -> QueryResult<'tcx>
source§impl<'a, 'tcx> EvalCtxt<'a, 'tcx>
impl<'a, 'tcx> EvalCtxt<'a, 'tcx>
fn compute_type_outlives_goal( &mut self, goal: Goal<'tcx, TypeOutlivesPredicate<'tcx>> ) -> QueryResult<'tcx>
fn compute_region_outlives_goal( &mut self, goal: Goal<'tcx, RegionOutlivesPredicate<'tcx>> ) -> QueryResult<'tcx>
fn compute_coerce_goal( &mut self, goal: Goal<'tcx, CoercePredicate<'tcx>> ) -> QueryResult<'tcx>
fn compute_subtype_goal( &mut self, goal: Goal<'tcx, SubtypePredicate<'tcx>> ) -> QueryResult<'tcx>
fn compute_closure_kind_goal( &mut self, goal: Goal<'tcx, (DefId, SubstsRef<'tcx>, ClosureKind)> ) -> QueryResult<'tcx>
fn compute_object_safe_goal(&mut self, trait_def_id: DefId) -> QueryResult<'tcx>
fn compute_well_formed_goal( &mut self, goal: Goal<'tcx, GenericArg<'tcx>> ) -> QueryResult<'tcx>
fn compute_alias_relate_goal( &mut self, goal: Goal<'tcx, (Term<'tcx>, Term<'tcx>, AliasRelationDirection)> ) -> QueryResult<'tcx>
fn compute_const_arg_has_type_goal( &mut self, goal: Goal<'tcx, (Const<'tcx>, Ty<'tcx>)> ) -> QueryResult<'tcx>
source§impl<'tcx> EvalCtxt<'_, 'tcx>
impl<'tcx> EvalCtxt<'_, 'tcx>
fn set_normalizes_to_hack_goal( &mut self, goal: Goal<'tcx, ProjectionPredicate<'tcx>> )
fn add_goal(&mut self, goal: Goal<'tcx, Predicate<'tcx>>)
fn add_goals( &mut self, goals: impl IntoIterator<Item = Goal<'tcx, Predicate<'tcx>>> )
fn try_merge_responses( &mut self, responses: impl Iterator<Item = QueryResult<'tcx>> ) -> QueryResult<'tcx>
Trait Implementations§
source§impl<'tcx> OverflowHandler<'tcx> for EvalCtxt<'_, 'tcx>
impl<'tcx> OverflowHandler<'tcx> for EvalCtxt<'_, 'tcx>
fn search_graph(&mut self) -> &mut SearchGraph<'tcx>
fn repeat_while_none<T>( &mut self, on_overflow: impl FnOnce(&mut Self) -> Result<T, NoSolution>, loop_body: impl FnMut(&mut Self) -> Option<Result<T, NoSolution>> ) -> Result<T, NoSolution>
fn with_incremented_depth<T>( &mut self, on_overflow: impl FnOnce(&mut Self) -> T, body: impl FnOnce(&mut Self) -> T ) -> T
Auto Trait Implementations§
impl<'a, 'tcx> !RefUnwindSafe for EvalCtxt<'a, 'tcx>
impl<'a, 'tcx> !Send for EvalCtxt<'a, 'tcx>
impl<'a, 'tcx> !Sync for EvalCtxt<'a, 'tcx>
impl<'a, 'tcx> Unpin for EvalCtxt<'a, 'tcx>where 'tcx: 'a,
impl<'a, 'tcx> !UnwindSafe for EvalCtxt<'a, 'tcx>
Blanket Implementations§
Layout§
Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...) attributes. Please see the Rust Reference’s “Type Layout” chapter for details on type layout guarantees.
Size: 88 bytes