Struct rustc_next_trait_solver::solve::eval_ctxt::EvalCtxt
source · pub struct EvalCtxt<'a, D, I = I>where
D: SolverDelegate<Interner = I>,
I: Interner,{
delegate: &'a D,
variables: I::CanonicalVars,
is_normalizes_to_goal: bool,
pub(super) var_values: CanonicalVarValues<I>,
predefined_opaques_in_body: I::PredefinedOpaques,
pub(super) max_input_universe: UniverseIndex,
pub(super) search_graph: &'a mut SearchGraph<SearchGraphDelegate<D>>,
nested_goals: NestedGoals<I>,
tainted: Result<(), NoSolution>,
pub(super) inspect: ProofTreeBuilder<D>,
}
Fields§
§delegate: &'a D
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 ObligationCause
s and Span
s 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.
variables: I::CanonicalVars
The variable info for the var_values
, only used to make an ambiguous response
with no constraints.
is_normalizes_to_goal: bool
Whether we’re currently computing a NormalizesTo
goal. Unlike other goals,
NormalizesTo
goals act like functions with the expected term always being
fully unconstrained. This would weaken inference however, as the nested goals
never get the inference constraints from the actual normalized-to type. Because
of this we return any ambiguous nested goals from NormalizesTo
to the caller
when then adds these to its own context. The caller is always an AliasRelate
goal so this never leaks out of the solver.
var_values: CanonicalVarValues<I>
§predefined_opaques_in_body: I::PredefinedOpaques
§max_input_universe: UniverseIndex
The 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<SearchGraphDelegate<D>>
§nested_goals: NestedGoals<I>
§tainted: Result<(), NoSolution>
§inspect: ProofTreeBuilder<D>
Implementations§
source§impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
pub(super) fn compute_alias_relate_goal( &mut self, goal: Goal<I, (I::Term, I::Term, AliasRelationDirection)>, ) -> QueryResult<I>
source§impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, ) -> Vec<Candidate<I>>
pub(super) fn forced_ambiguity( &mut self, cause: MaybeCause, ) -> Result<Candidate<I>, NoSolution>
fn assemble_impl_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, )
fn assemble_builtin_impl_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, )
fn assemble_param_env_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, )
fn assemble_alias_bound_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, )
sourcefn assemble_alias_bound_candidates_recur<G: GoalKind<D>>(
&mut self,
self_ty: I::Ty,
goal: Goal<I, G>,
candidates: &mut Vec<Candidate<I>>,
)
fn assemble_alias_bound_candidates_recur<G: GoalKind<D>>( &mut self, self_ty: I::Ty, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, )
For some deeply nested <T>::A::B::C::D
rigid associated type,
we should explore the item bounds for all levels, since the
associated_type_bounds
feature means that a parent associated
type may carry bounds for a nested associated type.
If we have a projection, check that its self type is a rigid projection. If so, continue searching by recursively calling after normalization.
fn assemble_object_bound_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, )
sourcefn assemble_coherence_unknowable_candidates<G: GoalKind<D>>(
&mut self,
goal: Goal<I, G>,
candidates: &mut Vec<Candidate<I>>,
)
fn assemble_coherence_unknowable_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, )
In coherence we have to not only care about all impls we know about, but also consider impls which may get added in a downstream or sibling crate or which an upstream impl may add in a minor release.
To do so we add an ambiguous candidate in case such an unknown impl could apply to the current goal.
sourcefn discard_impls_shadowed_by_env<G: GoalKind<D>>(
&mut self,
goal: Goal<I, G>,
candidates: &mut Vec<Candidate<I>>,
)
fn discard_impls_shadowed_by_env<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, )
If there’s a where-bound for the current goal, do not use any impl candidates to prove the current goal. Most importantly, if there is a where-bound which does not specify any associated types, we do not allow normalizing the associated type by using an impl, even if it would apply.
https://github.com/rust-lang/trait-system-refactor-initiative/issues/76
sourcepub(super) fn merge_candidates(
&mut self,
candidates: Vec<Candidate<I>>,
) -> QueryResult<I>
pub(super) fn merge_candidates( &mut self, candidates: Vec<Candidate<I>>, ) -> QueryResult<I>
If there are multiple ways to prove a trait or projection goal, we have to somehow try to merge the candidates into one. If that fails, we return ambiguity.
source§impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
sourcepub(super) fn canonicalize_goal<T: TypeFoldable<I>>(
&self,
goal: Goal<I, T>,
) -> (Vec<I::GenericArg>, CanonicalInput<I, T>)
pub(super) fn canonicalize_goal<T: TypeFoldable<I>>( &self, goal: Goal<I, T>, ) -> (Vec<I::GenericArg>, CanonicalInput<I, T>)
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<I>
pub(in solve) fn evaluate_added_goals_and_make_canonical_response( &mut self, certainty: Certainty, ) -> QueryResult<I>
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 expressible using simple unification of inference variables.
sourcepub(in solve) fn make_ambiguous_response_no_constraints(
&self,
maybe_cause: MaybeCause,
) -> CanonicalResponse<I>
pub(in solve) fn make_ambiguous_response_no_constraints( &self, maybe_cause: MaybeCause, ) -> CanonicalResponse<I>
Constructs a totally unconstrained, ambiguous response to a goal.
Take care when using this, since often it’s useful to respond with ambiguity but return constrained variables to guide inference.
sourcefn compute_external_query_constraints(
&self,
certainty: Certainty,
normalization_nested_goals: NestedNormalizationGoals<I>,
) -> ExternalConstraintsData<I>
fn compute_external_query_constraints( &self, certainty: Certainty, normalization_nested_goals: NestedNormalizationGoals<I>, ) -> ExternalConstraintsData<I>
Computes the region constraints and new opaque types registered when proving a goal.
If an opaque was already constrained before proving this goal, then the external constraints do not need to record that opaque, since if it is further constrained by inference, that will be passed back in the var values.
sourcepub(super) fn instantiate_and_apply_query_response(
&mut self,
param_env: I::ParamEnv,
original_values: Vec<I::GenericArg>,
response: CanonicalResponse<I>,
) -> (NestedNormalizationGoals<I>, Certainty)
pub(super) fn instantiate_and_apply_query_response( &mut self, param_env: I::ParamEnv, original_values: Vec<I::GenericArg>, response: CanonicalResponse<I>, ) -> (NestedNormalizationGoals<I>, Certainty)
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_values
of the response with theoriginal_values
- we apply the
external_constraints
returned by the query, returning thenormalization_nested_goals
sourcefn compute_query_response_instantiation_values<T: ResponseT<I>>(
delegate: &D,
original_values: &[I::GenericArg],
response: &Canonical<I, T>,
) -> CanonicalVarValues<I>
fn compute_query_response_instantiation_values<T: ResponseT<I>>( delegate: &D, original_values: &[I::GenericArg], response: &Canonical<I, T>, ) -> CanonicalVarValues<I>
This returns the canoncial variable values to instantiate the bound variables of
the canonical response. This depends on the original_values
for the
bound variables.
sourcefn unify_query_var_values(
delegate: &D,
param_env: I::ParamEnv,
original_values: &[I::GenericArg],
var_values: CanonicalVarValues<I>,
)
fn unify_query_var_values( delegate: &D, param_env: I::ParamEnv, original_values: &[I::GenericArg], var_values: CanonicalVarValues<I>, )
Unify the original_values
with the var_values
returned by the canonical query..
This assumes that this unification will always succeed. This is the case when applying a query response right away. However, calling a canonical query, doing any other kind of trait solving, and only then instantiating the result of the query can cause the instantiation to fail. This is not supported and we ICE in this case.
We always structurally instantiate aliases. Relating aliases needs to be different depending on whether the alias is rigid or not. We’re only really able to tell whether an alias is rigid by using the trait solver. When instantiating a response from the solver we assume that the solver correctly handled aliases and therefore always relate them structurally here.
fn register_region_constraints( &mut self, outlives: &[OutlivesPredicate<I, I::GenericArg>], )
fn register_new_opaque_types( &mut self, opaque_types: &[(OpaqueTypeKey<I>, I::Ty)], )
source§impl<'a, D, I> EvalCtxt<'a, D, I>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<'a, D, I> EvalCtxt<'a, D, I>where
D: SolverDelegate<Interner = I>,
I: Interner,
sourcepub(in solve) fn probe<F, T>(
&mut self,
probe_kind: F,
) -> ProbeCtxt<'_, 'a, D, I, F, T>
pub(in solve) fn probe<F, T>( &mut self, probe_kind: F, ) -> ProbeCtxt<'_, 'a, D, I, F, T>
probe_kind
is only called when proof tree building is enabled so it can be
as expensive as necessary to output the desired information.
pub(in solve) fn probe_builtin_trait_candidate( &mut self, source: BuiltinImplSource, ) -> TraitProbeCtxt<'_, 'a, D, I, impl FnOnce(&QueryResult<I>) -> ProbeKind<I>>
pub(in solve) fn probe_trait_candidate( &mut self, source: CandidateSource<I>, ) -> TraitProbeCtxt<'_, 'a, D, I, impl FnOnce(&QueryResult<I>) -> ProbeKind<I>>
source§impl<'a, D, I> EvalCtxt<'a, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<'a, D, I> EvalCtxt<'a, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
pub(super) fn solver_mode(&self) -> SolverMode
pub(super) fn set_is_normalizes_to_goal(&mut self)
sourcepub(super) fn enter_root<R>(
delegate: &D,
generate_proof_tree: GenerateProofTree,
f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R,
) -> (R, Option<GoalEvaluation<I>>)
pub(super) fn enter_root<R>( delegate: &D, generate_proof_tree: GenerateProofTree, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R, ) -> (R, Option<GoalEvaluation<I>>)
Creates a root evaluation context and search graph. This should only be
used from outside of any evaluation, and other methods should be preferred
over using this manually (such as SolverDelegateEvalExt::evaluate_root_goal
).
sourcefn enter_canonical<R>(
cx: I,
search_graph: &'a mut SearchGraph<SearchGraphDelegate<D>>,
canonical_input: CanonicalInput<I>,
canonical_goal_evaluation: &mut ProofTreeBuilder<D>,
f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R,
) -> R
fn enter_canonical<R>( cx: I, search_graph: &'a mut SearchGraph<SearchGraphDelegate<D>>, canonical_input: CanonicalInput<I>, canonical_goal_evaluation: &mut ProofTreeBuilder<D>, f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R, ) -> R
Creates a nested evaluation context that shares the same search graph as the
one passed in. This is suitable for evaluation, granted that the search graph
has had the nested goal recorded on its stack (SearchGraph::with_new_goal
),
but it’s preferable to use other methods that call this one rather than this
method directly.
This function takes care of setting up the inference context, setting the anchor, and registering opaques from the canonicalized input.
sourcefn evaluate_canonical_goal(
cx: I,
search_graph: &'a mut SearchGraph<SearchGraphDelegate<D>>,
canonical_input: CanonicalInput<I>,
goal_evaluation: &mut ProofTreeBuilder<D>,
) -> QueryResult<I>
fn evaluate_canonical_goal( cx: I, search_graph: &'a mut SearchGraph<SearchGraphDelegate<D>>, canonical_input: CanonicalInput<I>, goal_evaluation: &mut ProofTreeBuilder<D>, ) -> QueryResult<I>
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 SolverDelegateEvalExt::evaluate_root_goal if you’re outside of it.
sourcefn evaluate_goal(
&mut self,
goal_evaluation_kind: GoalEvaluationKind,
source: GoalSource,
goal: Goal<I, I::Predicate>,
) -> Result<(bool, Certainty), NoSolution>
fn evaluate_goal( &mut self, goal_evaluation_kind: GoalEvaluationKind, source: GoalSource, goal: Goal<I, I::Predicate>, ) -> Result<(bool, Certainty), NoSolution>
Recursively evaluates goal
, returning whether any inference vars have
been constrained and the certainty of the result.
sourcepub(super) fn evaluate_goal_raw(
&mut self,
goal_evaluation_kind: GoalEvaluationKind,
_source: GoalSource,
goal: Goal<I, I::Predicate>,
) -> Result<(NestedNormalizationGoals<I>, bool, Certainty), NoSolution>
pub(super) fn evaluate_goal_raw( &mut self, goal_evaluation_kind: GoalEvaluationKind, _source: GoalSource, goal: Goal<I, I::Predicate>, ) -> Result<(NestedNormalizationGoals<I>, bool, Certainty), NoSolution>
Recursively evaluates goal
, returning the nested goals in case
the nested goal is a NormalizesTo
goal.
As all other goal kinds do not return any nested goals and
NormalizesTo
is only used by AliasRelate
, all other callsites
should use EvalCtxt::evaluate_goal
which discards that empty
storage.
fn instantiate_response_discarding_overflow( &mut self, param_env: I::ParamEnv, original_values: Vec<I::GenericArg>, response: CanonicalResponse<I>, ) -> (NestedNormalizationGoals<I>, Certainty, bool)
fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I>
pub(super) fn try_evaluate_added_goals( &mut self, ) -> Result<Certainty, NoSolution>
sourcefn evaluate_added_goals_step(&mut self) -> Result<Option<Certainty>, NoSolution>
fn evaluate_added_goals_step(&mut self) -> Result<Option<Certainty>, NoSolution>
Iterate over all added goals: returning Ok(Some(_))
in case we can stop rerunning.
Goals for the next step get directly added to the nested goals of the EvalCtxt
.
sourcepub(crate) fn record_impl_args(&mut self, impl_args: I::GenericArgs)
pub(crate) fn record_impl_args(&mut self, impl_args: I::GenericArgs)
Record impl args in the proof tree for later access by InspectCandidate
.
pub(super) fn cx(&self) -> I
pub(super) fn add_normalizes_to_goal(&mut self, goal: Goal<I, NormalizesTo<I>>)
pub(super) fn add_goal( &mut self, source: GoalSource, goal: Goal<I, I::Predicate>, )
pub(super) fn add_goals( &mut self, source: GoalSource, goals: impl IntoIterator<Item = Goal<I, I::Predicate>>, )
pub(super) fn next_ty_infer(&mut self) -> I::Ty
pub(super) fn next_const_infer(&mut self) -> I::Const
sourcepub(super) fn next_term_infer_of_kind(&mut self, kind: I::Term) -> I::Term
pub(super) fn next_term_infer_of_kind(&mut self, kind: I::Term) -> I::Term
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<I, NormalizesTo<I>>,
) -> bool
pub(super) fn term_is_fully_unconstrained( &self, goal: Goal<I, NormalizesTo<I>>, ) -> bool
Is the projection predicate is of the form exists<T> <Ty as Trait>::Assoc = T
.
This is the case if the term
does not occur in any other part of the predicate
and is able to name all other placeholder and inference variables.
pub(super) fn eq<T: Relate<I>>( &mut self, param_env: I::ParamEnv, lhs: T, rhs: T, ) -> Result<(), NoSolution>
sourcepub(super) fn relate_rigid_alias_non_alias(
&mut self,
param_env: I::ParamEnv,
alias: AliasTerm<I>,
variance: Variance,
term: I::Term,
) -> Result<(), NoSolution>
pub(super) fn relate_rigid_alias_non_alias( &mut self, param_env: I::ParamEnv, alias: AliasTerm<I>, variance: Variance, term: I::Term, ) -> Result<(), NoSolution>
This should be used when relating a rigid alias with another type.
Normally we emit a nested AliasRelate
when equating an inference
variable and an alias. This causes us to instead constrain the inference
variable to the alias without emitting a nested alias relate goals.
sourcepub(super) fn eq_structurally_relating_aliases<T: Relate<I>>(
&mut self,
param_env: I::ParamEnv,
lhs: T,
rhs: T,
) -> Result<(), NoSolution>
pub(super) fn eq_structurally_relating_aliases<T: Relate<I>>( &mut self, param_env: I::ParamEnv, lhs: T, rhs: T, ) -> Result<(), NoSolution>
This sohuld only be used when we’re either instantiating a previously unconstrained “return value” or when we’re sure that all aliases in the types are rigid.
pub(super) fn sub<T: Relate<I>>( &mut self, param_env: I::ParamEnv, sub: T, sup: T, ) -> Result<(), NoSolution>
pub(super) fn relate<T: Relate<I>>( &mut self, param_env: I::ParamEnv, lhs: T, variance: Variance, rhs: T, ) -> Result<(), NoSolution>
sourcepub(super) fn eq_and_get_goals<T: Relate<I>>(
&self,
param_env: I::ParamEnv,
lhs: T,
rhs: T,
) -> Result<Vec<Goal<I, I::Predicate>>, NoSolution>
pub(super) fn eq_and_get_goals<T: Relate<I>>( &self, param_env: I::ParamEnv, lhs: T, rhs: T, ) -> Result<Vec<Goal<I, I::Predicate>>, 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<I> + Copy>( &self, value: Binder<I, T>, ) -> T
pub(super) fn enter_forall<T: TypeFoldable<I> + Copy, U>( &self, value: Binder<I, T>, f: impl FnOnce(T) -> U, ) -> U
pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> Twhere
T: TypeFoldable<I>,
pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs
pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region)
pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region)
sourcepub(super) fn well_formed_goals(
&self,
param_env: I::ParamEnv,
arg: I::GenericArg,
) -> Option<Vec<Goal<I, I::Predicate>>>
pub(super) fn well_formed_goals( &self, param_env: I::ParamEnv, arg: I::GenericArg, ) -> Option<Vec<Goal<I, I::Predicate>>>
Computes the list of goals required for arg
to be well-formed
pub(super) fn trait_ref_is_knowable( &mut self, param_env: I::ParamEnv, trait_ref: TraitRef<I>, ) -> Result<bool, NoSolution>
pub(super) fn fetch_eligible_assoc_item( &self, param_env: I::ParamEnv, goal_trait_ref: TraitRef<I>, trait_assoc_def_id: I::DefId, impl_def_id: I::DefId, ) -> Result<Option<I::DefId>, NoSolution>
pub(super) fn can_define_opaque_ty(&self, def_id: I::LocalDefId) -> bool
pub(super) fn unify_existing_opaque_tys( &mut self, param_env: I::ParamEnv, key: OpaqueTypeKey<I>, ty: I::Ty, ) -> Vec<CanonicalResponse<I>>
pub(super) fn try_const_eval_resolve( &self, param_env: I::ParamEnv, unevaluated: UnevaluatedConst<I>, ) -> Option<I::Const>
pub(super) fn is_transmutable( &mut self, param_env: I::ParamEnv, dst: I::Ty, src: I::Ty, assume: I::Const, ) -> Result<Certainty, NoSolution>
source§impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
pub(super) fn normalize_anon_const( &mut self, goal: Goal<I, NormalizesTo<I>>, ) -> QueryResult<I>
source§impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
pub(super) fn normalize_inherent_associated_type( &mut self, goal: Goal<I, NormalizesTo<I>>, ) -> QueryResult<I>
source§impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
pub(super) fn normalize_opaque_type( &mut self, goal: Goal<I, NormalizesTo<I>>, ) -> QueryResult<I>
source§impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
pub(super) fn normalize_weak_type( &mut self, goal: Goal<I, NormalizesTo<I>>, ) -> QueryResult<I>
source§impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
pub(super) fn compute_normalizes_to_goal( &mut self, goal: Goal<I, NormalizesTo<I>>, ) -> QueryResult<I>
sourcefn normalize_at_least_one_step(
&mut self,
goal: Goal<I, NormalizesTo<I>>,
) -> QueryResult<I>
fn normalize_at_least_one_step( &mut self, goal: Goal<I, NormalizesTo<I>>, ) -> QueryResult<I>
Normalize the given alias by at least one step. If the alias is rigid, this
returns NoSolution
.
sourcepub fn instantiate_normalizes_to_term(
&mut self,
goal: Goal<I, NormalizesTo<I>>,
term: I::Term,
)
pub fn instantiate_normalizes_to_term( &mut self, goal: Goal<I, NormalizesTo<I>>, term: I::Term, )
When normalizing an associated item, constrain the expected term to term
.
We know term
to always be a fully unconstrained inference variable, so
eq
should never fail here. However, in case term
contains aliases, we
emit nested AliasRelate
goals to structurally normalize the alias.
source§impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
fn translate_args( &mut self, goal: Goal<I, NormalizesTo<I>>, impl_def_id: I::DefId, impl_args: I::GenericArgs, impl_trait_ref: TraitRef<I>, target_container_def_id: I::DefId, ) -> Result<I::GenericArgs, NoSolution>
source§impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
pub(super) fn compute_projection_goal( &mut self, goal: Goal<I, ProjectionPredicate<I>>, ) -> QueryResult<I>
source§impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
sourcefn consider_builtin_dyn_upcast_candidates(
&mut self,
goal: Goal<I, (I::Ty, I::Ty)>,
a_data: I::BoundExistentialPredicates,
a_region: I::Region,
b_data: I::BoundExistentialPredicates,
b_region: I::Region,
) -> Vec<Candidate<I>>
fn consider_builtin_dyn_upcast_candidates( &mut self, goal: Goal<I, (I::Ty, I::Ty)>, a_data: I::BoundExistentialPredicates, a_region: I::Region, b_data: I::BoundExistentialPredicates, b_region: I::Region, ) -> Vec<Candidate<I>>
Trait upcasting allows for coercions between trait objects:
trait Super {}
trait Trait: Super {}
// results in builtin impls upcasting to a super trait
impl<'a, 'b: 'a> Unsize<dyn Super + 'a> for dyn Trait + 'b {}
// and impls removing auto trait bounds.
impl<'a, 'b: 'a> Unsize<dyn Trait + 'a> for dyn Trait + Send + 'b {}
fn consider_builtin_unsize_to_dyn_candidate( &mut self, goal: Goal<I, (I::Ty, I::Ty)>, b_data: I::BoundExistentialPredicates, b_region: I::Region, ) -> Result<Candidate<I>, NoSolution>
fn consider_builtin_upcast_to_principal( &mut self, goal: Goal<I, (I::Ty, I::Ty)>, source: CandidateSource<I>, a_data: I::BoundExistentialPredicates, a_region: I::Region, b_data: I::BoundExistentialPredicates, b_region: I::Region, upcast_principal: Option<Binder<I, ExistentialTraitRef<I>>>, ) -> Result<Candidate<I>, NoSolution>
sourcefn consider_builtin_array_unsize(
&mut self,
goal: Goal<I, (I::Ty, I::Ty)>,
a_elem_ty: I::Ty,
b_elem_ty: I::Ty,
) -> Result<Candidate<I>, NoSolution>
fn consider_builtin_array_unsize( &mut self, goal: Goal<I, (I::Ty, I::Ty)>, a_elem_ty: I::Ty, b_elem_ty: I::Ty, ) -> Result<Candidate<I>, NoSolution>
We have the following builtin impls for arrays:
impl<T: ?Sized, const N: usize> Unsize<[T]> for [T; N] {}
While the impl itself could theoretically not be builtin,
the actual unsizing behavior is builtin. Its also easier to
make all impls of Unsize
builtin as we’re able to use
#[rustc_deny_explicit_impl]
in this case.
sourcefn consider_builtin_struct_unsize(
&mut self,
goal: Goal<I, (I::Ty, I::Ty)>,
def: I::AdtDef,
a_args: I::GenericArgs,
b_args: I::GenericArgs,
) -> Result<Candidate<I>, NoSolution>
fn consider_builtin_struct_unsize( &mut self, goal: Goal<I, (I::Ty, I::Ty)>, def: I::AdtDef, a_args: I::GenericArgs, b_args: I::GenericArgs, ) -> Result<Candidate<I>, NoSolution>
We generate a builtin Unsize
impls for structs with generic parameters only
mentioned by the last field.
struct Foo<T, U: ?Sized> {
sized_field: Vec<T>,
unsizable: Box<U>,
}
// results in the following builtin impl
impl<T: ?Sized, U: ?Sized, V: ?Sized> Unsize<Foo<T, V>> for Foo<T, U>
where
Box<U>: Unsize<Box<V>>,
{}
sourcefn consider_builtin_tuple_unsize(
&mut self,
goal: Goal<I, (I::Ty, I::Ty)>,
a_tys: I::Tys,
b_tys: I::Tys,
) -> Result<Candidate<I>, NoSolution>
fn consider_builtin_tuple_unsize( &mut self, goal: Goal<I, (I::Ty, I::Ty)>, a_tys: I::Tys, b_tys: I::Tys, ) -> Result<Candidate<I>, NoSolution>
We generate the following builtin impl for tuples of all sizes.
This impl is still unstable and we emit a feature error when it when it is used by a coercion.
impl<T: ?Sized, U: ?Sized, V: ?Sized> Unsize<(T, V)> for (T, U)
where
U: Unsize<V>,
{}
fn disqualify_auto_trait_candidate_due_to_possible_impl( &mut self, goal: Goal<I, TraitPredicate<I>>, ) -> Option<Result<Candidate<I>, NoSolution>>
sourcefn probe_and_evaluate_goal_for_constituent_tys(
&mut self,
source: CandidateSource<I>,
goal: Goal<I, TraitPredicate<I>>,
constituent_tys: impl Fn(&EvalCtxt<'_, D>, I::Ty) -> Result<Vec<Binder<I, I::Ty>>, NoSolution>,
) -> Result<Candidate<I>, NoSolution>
fn probe_and_evaluate_goal_for_constituent_tys( &mut self, source: CandidateSource<I>, goal: Goal<I, TraitPredicate<I>>, constituent_tys: impl Fn(&EvalCtxt<'_, D>, I::Ty) -> Result<Vec<Binder<I, I::Ty>>, NoSolution>, ) -> Result<Candidate<I>, NoSolution>
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<I, TraitPredicate<I>>, ) -> QueryResult<I>
source§impl<'a, D, I> EvalCtxt<'a, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<'a, D, I> EvalCtxt<'a, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
fn compute_type_outlives_goal( &mut self, goal: Goal<I, OutlivesPredicate<I, I::Ty>>, ) -> QueryResult<I>
fn compute_region_outlives_goal( &mut self, goal: Goal<I, OutlivesPredicate<I, I::Region>>, ) -> QueryResult<I>
fn compute_coerce_goal( &mut self, goal: Goal<I, CoercePredicate<I>>, ) -> QueryResult<I>
fn compute_subtype_goal( &mut self, goal: Goal<I, SubtypePredicate<I>>, ) -> QueryResult<I>
fn compute_object_safe_goal(&mut self, trait_def_id: I::DefId) -> QueryResult<I>
fn compute_well_formed_goal( &mut self, goal: Goal<I, I::GenericArg>, ) -> QueryResult<I>
fn compute_const_evaluatable_goal( &mut self, _: Goal<I, I::Const>, ) -> QueryResult<I>
fn compute_const_arg_has_type_goal( &mut self, goal: Goal<I, (I::Const, I::Ty)>, ) -> QueryResult<I>
source§impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
impl<D, I> EvalCtxt<'_, D>where
D: SolverDelegate<Interner = I>,
I: Interner,
sourcefn try_merge_responses(
&mut self,
responses: &[CanonicalResponse<I>],
) -> Option<CanonicalResponse<I>>
fn try_merge_responses( &mut self, responses: &[CanonicalResponse<I>], ) -> Option<CanonicalResponse<I>>
Try to merge multiple possible ways to prove a goal, if that is not possible returns None
.
In this case we tend to flounder and return ambiguity by calling [EvalCtxt::flounder]
.
sourcefn flounder(&mut self, responses: &[CanonicalResponse<I>]) -> QueryResult<I>
fn flounder(&mut self, responses: &[CanonicalResponse<I>]) -> QueryResult<I>
If we fail to merge responses we flounder and return overflow or ambiguity.
sourcefn structurally_normalize_ty(
&mut self,
param_env: I::ParamEnv,
ty: I::Ty,
) -> Result<I::Ty, NoSolution>
fn structurally_normalize_ty( &mut self, param_env: I::ParamEnv, ty: I::Ty, ) -> Result<I::Ty, NoSolution>
Normalize a type for when it is structurally matched on.
This function is necessary in nearly all cases before matching on a type. Not doing so is likely to be incomplete and therefore unsound during coherence.
Auto Trait Implementations§
impl<'a, D, I> Freeze for EvalCtxt<'a, D, I>where
<D as Deref>::Target: Sized,
<I as Interner>::CanonicalVars: Freeze,
<I as Interner>::PredefinedOpaques: Freeze,
<I as Interner>::GenericArgs: Freeze,
impl<'a, D, I> RefUnwindSafe for EvalCtxt<'a, D, I>where
<D as Deref>::Target: Sized,
<I as Interner>::CanonicalVars: RefUnwindSafe,
<I as Interner>::PredefinedOpaques: RefUnwindSafe,
D: RefUnwindSafe,
<I as Interner>::GenericArgs: RefUnwindSafe,
<I as Interner>::ParamEnv: RefUnwindSafe,
<I as Interner>::Term: RefUnwindSafe,
<I as Interner>::Predicate: RefUnwindSafe,
<I as Interner>::DefId: RefUnwindSafe,
<I as Interner>::DefiningOpaqueTypes: RefUnwindSafe,
<I as Interner>::GenericArg: RefUnwindSafe,
<I as Interner>::ExternalConstraints: RefUnwindSafe,
impl<'a, D, I> Send for EvalCtxt<'a, D, I>where
<D as Deref>::Target: Sized,
<I as Interner>::CanonicalVars: Send,
<I as Interner>::PredefinedOpaques: Send,
D: Sync + Send,
<I as Interner>::GenericArgs: Send,
<I as Interner>::DefiningOpaqueTypes: Send,
<I as Interner>::ParamEnv: Send,
<I as Interner>::Term: Send,
<I as Interner>::Predicate: Send,
<I as Interner>::DefId: Send,
<I as Interner>::ExternalConstraints: Send,
<I as Interner>::GenericArg: Send,
impl<'a, D, I> Sync for EvalCtxt<'a, D, I>where
<D as Deref>::Target: Sized,
<I as Interner>::CanonicalVars: Sync,
<I as Interner>::PredefinedOpaques: Sync,
D: Sync,
<I as Interner>::GenericArgs: Sync,
<I as Interner>::ParamEnv: Sync,
<I as Interner>::Term: Sync,
<I as Interner>::Predicate: Sync,
<I as Interner>::DefiningOpaqueTypes: Sync,
<I as Interner>::DefId: Sync,
<I as Interner>::GenericArg: Sync,
<I as Interner>::ExternalConstraints: Sync,
impl<'a, D, I> Unpin for EvalCtxt<'a, D, I>
impl<'a, D, I = <D as SolverDelegate>::Interner> !UnwindSafe for EvalCtxt<'a, D, I>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T, R> CollectAndApply<T, R> for T
impl<T, R> CollectAndApply<T, R> for T
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§impl<I, T, U> Upcast<I, U> for Twhere
U: UpcastFrom<I, T>,
impl<I, T, U> Upcast<I, U> for Twhere
U: UpcastFrom<I, T>,
source§impl<I, T> UpcastFrom<I, T> for T
impl<I, T> UpcastFrom<I, T> for T
fn upcast_from(from: T, _tcx: I) -> T
source§impl<T> WithSubscriber for T
impl<T> WithSubscriber for T
source§fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
source§fn with_current_subscriber(self) -> WithDispatch<Self>
fn with_current_subscriber(self) -> WithDispatch<Self>
impl<'a, T> Captures<'a> for Twhere
T: ?Sized,
Layout§
Note: Unable to compute type layout, possibly due to this type having generic parameters. Layout can only be computed for concrete, fully-instantiated types.