rustc_next_trait_solver::solve

Struct 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 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.

§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,

Source

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,

Source

pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, ) -> Vec<Candidate<I>>

Source

pub(super) fn forced_ambiguity( &mut self, cause: MaybeCause, ) -> Result<Candidate<I>, NoSolution>

Source

fn assemble_impl_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, )

Source

fn assemble_builtin_impl_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, )

Source

fn assemble_param_env_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, )

Source

fn assemble_alias_bound_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, )

Source

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.

Source

fn assemble_object_bound_candidates<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, candidates: &mut Vec<Candidate<I>>, )

Source

fn consider_coherence_unknowable_candidate<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, ) -> Result<Candidate<I>, NoSolution>

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 return a single ambiguous candidate in case such an unknown impl could apply to the current goal.

Source

pub(super) fn merge_candidates( &mut self, proven_via: Option<TraitGoalProvenVia>, candidates: Vec<Candidate<I>>, ) -> QueryResult<I>

We sadly can’t simply take all possible candidates for normalization goals and check whether they result in the same constraints. We want to make sure that trying to normalize an alias doesn’t result in constraints which aren’t otherwise required.

Most notably, when proving a trait goal by via a where-bound, we should not normalize via impls which have stricter region constraints than the where-bound:

trait Trait<'a> {
    type Assoc;
}

impl<'a, T: 'a> Trait<'a> for T {
    type Assoc = u32;
}

fn with_bound<'a, T: Trait<'a>>(_value: T::Assoc) {}

The where-bound of with_bound doesn’t specify the associated type, so we would only be able to normalize <T as Trait<'a>>::Assoc by using the impl. This impl adds a T: 'a bound however, which would result in a region error. Given that the user explicitly wrote that T: Trait<'a> holds, this is undesirable and we instead treat the alias as rigid.

See trait-system-refactor-initiative#124 for more details.

Source§

impl<D, I> EvalCtxt<'_, D>
where D: SolverDelegate<Interner = I>, I: Interner,

Source

pub(super) fn compute_host_effect_goal( &mut self, goal: Goal<I, HostEffectPredicate<I>>, ) -> QueryResult<I>

Source§

impl<D, I> EvalCtxt<'_, D>
where D: SolverDelegate<Interner = I>, I: Interner,

Source

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.

Source

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.
Source

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.

Source

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.

Source

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 the original_values
  • we apply the external_constraints returned by the query, returning the normalization_nested_goals
Source

fn compute_query_response_instantiation_values<T: ResponseT<I>>( delegate: &D, original_values: &[I::GenericArg], response: &Canonical<I, T>, ) -> CanonicalVarValues<I>

This returns the canonical variable values to instantiate the bound variables of the canonical response. This depends on the original_values for the bound variables.

Source

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.

Source

fn register_region_constraints( &mut self, outlives: &[OutlivesPredicate<I, I::GenericArg>], )

Source

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,

Source

pub(in solve) fn probe<F, T>( &mut self, probe_kind: F, ) -> ProbeCtxt<'_, 'a, D, I, F, T>
where F: FnOnce(&T) -> ProbeKind<I>,

probe_kind is only called when proof tree building is enabled so it can be as expensive as necessary to output the desired information.

Source

pub(in solve) fn probe_builtin_trait_candidate( &mut self, source: BuiltinImplSource, ) -> TraitProbeCtxt<'_, 'a, D, I, impl FnOnce(&QueryResult<I>) -> ProbeKind<I>>

Source

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,

Source

pub(super) fn typing_mode(&self) -> TypingMode<I>

Source

pub(super) fn set_is_normalizes_to_goal(&mut self)

Source

pub(super) fn enter_root<R>( delegate: &D, root_depth: usize, 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).

Source

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.

Source

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.

Source

fn evaluate_goal( &mut self, goal_evaluation_kind: GoalEvaluationKind, source: GoalSource, goal: Goal<I, I::Predicate>, ) -> Result<(HasChanged, Certainty), NoSolution>

Recursively evaluates goal, returning whether any inference vars have been constrained and the certainty of the result.

Source

pub(super) fn evaluate_goal_raw( &mut self, goal_evaluation_kind: GoalEvaluationKind, _source: GoalSource, goal: Goal<I, I::Predicate>, ) -> Result<(NestedNormalizationGoals<I>, HasChanged, 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.

Source

fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I>

Source

pub(super) fn try_evaluate_added_goals( &mut self, ) -> Result<Certainty, NoSolution>

Source

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.

Source

pub(crate) fn record_impl_args(&mut self, impl_args: I::GenericArgs)

Record impl args in the proof tree for later access by InspectCandidate.

Source

pub(super) fn cx(&self) -> I

Source

pub(super) fn add_normalizes_to_goal(&mut self, goal: Goal<I, NormalizesTo<I>>)

Source

pub(super) fn add_goal( &mut self, source: GoalSource, goal: Goal<I, I::Predicate>, )

Source

pub(super) fn add_goals( &mut self, source: GoalSource, goals: impl IntoIterator<Item = Goal<I, I::Predicate>>, )

Source

pub(super) fn next_region_var(&mut self) -> I::Region

Source

pub(super) fn next_ty_infer(&mut self) -> I::Ty

Source

pub(super) fn next_const_infer(&mut self) -> I::Const

Source

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.

Source

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.

Source

pub(super) fn eq<T: Relate<I>>( &mut self, param_env: I::ParamEnv, lhs: T, rhs: T, ) -> Result<(), NoSolution>

Source

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.

Source

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.

Source

pub(super) fn sub<T: Relate<I>>( &mut self, param_env: I::ParamEnv, sub: T, sup: T, ) -> Result<(), NoSolution>

Source

pub(super) fn relate<T: Relate<I>>( &mut self, param_env: I::ParamEnv, lhs: T, variance: Variance, rhs: T, ) -> Result<(), NoSolution>

Source

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.

Source

pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>( &self, value: Binder<I, T>, ) -> T

Source

pub(super) fn enter_forall<T: TypeFoldable<I> + Copy, U>( &mut self, value: Binder<I, T>, f: impl FnOnce(&mut Self, T) -> U, ) -> U

enter_forall, but takes &mut self and passes it back through the callback since it can’t be aliased during the call.

Source

pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T
where T: TypeFoldable<I>,

Source

pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs

Source

pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region)

Source

pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region)

Source

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

Source

pub(super) fn trait_ref_is_knowable( &mut self, param_env: I::ParamEnv, trait_ref: TraitRef<I>, ) -> Result<bool, NoSolution>

Source

pub(super) fn fetch_eligible_assoc_item( &self, goal_trait_ref: TraitRef<I>, trait_assoc_def_id: I::DefId, impl_def_id: I::DefId, ) -> Result<Option<I::DefId>, NoSolution>

Source

pub(super) fn insert_hidden_type( &mut self, opaque_type_key: OpaqueTypeKey<I>, param_env: I::ParamEnv, hidden_ty: I::Ty, ) -> Result<(), NoSolution>

Source

pub(super) fn add_item_bounds_for_hidden_type( &mut self, opaque_def_id: I::DefId, opaque_args: I::GenericArgs, param_env: I::ParamEnv, hidden_ty: I::Ty, )

Source

pub(super) fn probe_existing_opaque_ty( &mut self, key: OpaqueTypeKey<I>, ) -> Option<(OpaqueTypeKey<I>, I::Ty)>

Source

pub(super) fn evaluate_const( &self, param_env: I::ParamEnv, uv: UnevaluatedConst<I>, ) -> Option<I::Const>

Source

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,

Source

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,

Source

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,

Source

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,

Source

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,

Source

pub(super) fn compute_normalizes_to_goal( &mut self, goal: Goal<I, NormalizesTo<I>>, ) -> QueryResult<I>

Source

fn add_rigid_constraints( &mut self, param_env: I::ParamEnv, rigid_alias: AliasTerm<I>, ) -> Result<(), NoSolution>

Register any obligations that are used to validate that an alias should be treated as rigid.

An alias may be considered rigid if it fails normalization, but we also don’t want to consider aliases that are not well-formed to be rigid simply because they fail normalization.

For example, some <T as Trait>::Assoc where T: Trait does not hold, or an opaque type whose hidden type doesn’t actually satisfy the opaque item bounds.

Source

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.

Source

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,

Source

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,

Source

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,

Source

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 {}
Source

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>

Source

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>

Source

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.

Source

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>>,
{}
Source

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>,
{}
Source

fn disqualify_auto_trait_candidate_due_to_possible_impl( &mut self, goal: Goal<I, TraitPredicate<I>>, ) -> Option<Result<Candidate<I>, NoSolution>>

Source

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.

Source§

impl<D, I> EvalCtxt<'_, D>
where D: SolverDelegate<Interner = I>, I: Interner,

Source§

impl<'a, D, I> EvalCtxt<'a, D>
where D: SolverDelegate<Interner = I>, I: Interner,

Source

fn compute_type_outlives_goal( &mut self, goal: Goal<I, OutlivesPredicate<I, I::Ty>>, ) -> QueryResult<I>

Source

fn compute_region_outlives_goal( &mut self, goal: Goal<I, OutlivesPredicate<I, I::Region>>, ) -> QueryResult<I>

Source

fn compute_coerce_goal( &mut self, goal: Goal<I, CoercePredicate<I>>, ) -> QueryResult<I>

Source

fn compute_subtype_goal( &mut self, goal: Goal<I, SubtypePredicate<I>>, ) -> QueryResult<I>

Source

fn compute_dyn_compatible_goal( &mut self, trait_def_id: I::DefId, ) -> QueryResult<I>

Source

fn compute_well_formed_goal( &mut self, goal: Goal<I, I::GenericArg>, ) -> QueryResult<I>

Source

fn compute_const_evaluatable_goal( &mut self, _: Goal<I, I::Const>, ) -> QueryResult<I>

Source

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,

Source

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].

Source

fn bail_with_ambiguity( &mut self, responses: &[CanonicalResponse<I>], ) -> CanonicalResponse<I>

Source

fn flounder(&mut self, responses: &[CanonicalResponse<I>]) -> QueryResult<I>

If we fail to merge responses we flounder and return overflow or ambiguity.

Source

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.

Source

fn structurally_normalize_const( &mut self, param_env: I::ParamEnv, ct: I::Const, ) -> Result<I::Const, NoSolution>

Normalize a const for when it is structurally matched on, or more likely when it needs .try_to_* called on it (e.g. to turn it into a usize).

This function is necessary in nearly all cases before matching on a const. Not doing so is likely to be incomplete and therefore unsound during coherence.

Source

fn opaque_type_is_rigid(&self, def_id: I::DefId) -> bool

Auto Trait Implementations§

§

impl<'a, D, I> DynSend for EvalCtxt<'a, D, I>

§

impl<'a, D, I> DynSync for EvalCtxt<'a, D, I>

§

impl<'a, D, I> Freeze for EvalCtxt<'a, D, I>

§

impl<'a, D, I> RefUnwindSafe for EvalCtxt<'a, D, I>

§

impl<'a, D, I> Send for EvalCtxt<'a, D, I>

§

impl<'a, D, I> Sync for EvalCtxt<'a, D, I>

§

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> Aligned for T

Source§

const ALIGN: Alignment

Alignment of Self.
Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T, R> CollectAndApply<T, R> for T

Source§

fn collect_and_apply<I, F>(iter: I, f: F) -> R
where I: Iterator<Item = T>, F: FnOnce(&[T]) -> R,

Equivalent to f(&iter.collect::<Vec<_>>()).

Source§

type Output = R

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<I, T, U> Upcast<I, U> for T
where U: UpcastFrom<I, T>,

Source§

fn upcast(self, interner: I) -> U

Source§

impl<I, T> UpcastFrom<I, T> for T

Source§

fn upcast_from(from: T, _tcx: I) -> T

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<'a, T> Captures<'a> for T
where 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.