mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Auto merge of #125324 - matthiaskrgr:rollup-5vcgjtq, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #125255 (Make `EvalCtxt` generic over `InferCtxtLike`) - #125283 (Use a single static for all default slice Arcs.) - #125300 (rustdoc: Don't strip items with inherited visibility in `AliasedNonLocalStripper`) - #125309 (Fix `tests/debuginfo/strings-and-strs`.) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
75cb5c51cd
@ -233,6 +233,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
fn parent(self, def_id: Self::DefId) -> Self::DefId {
|
||||
self.parent(def_id)
|
||||
}
|
||||
|
||||
fn recursion_limit(self) -> usize {
|
||||
self.recursion_limit().0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for abi::Abi {
|
||||
|
@ -37,7 +37,11 @@ pub struct Predicate<'tcx>(
|
||||
pub(super) Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
|
||||
);
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::Predicate<TyCtxt<'tcx>> for Predicate<'tcx> {}
|
||||
impl<'tcx> rustc_type_ir::inherent::Predicate<TyCtxt<'tcx>> for Predicate<'tcx> {
|
||||
fn is_coinductive(self, interner: TyCtxt<'tcx>) -> bool {
|
||||
self.is_coinductive(interner)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::visit::Flags for Predicate<'tcx> {
|
||||
fn flags(&self) -> TypeFlags {
|
||||
|
@ -16,10 +16,11 @@
|
||||
//! relate them structurally.
|
||||
|
||||
use super::EvalCtxt;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
||||
use rustc_middle::ty;
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
pub(super) fn compute_alias_relate_goal(
|
||||
&mut self,
|
||||
|
@ -1,8 +1,7 @@
|
||||
//! Code shared by trait and projection goals for candidate assembly.
|
||||
|
||||
use crate::solve::GoalSource;
|
||||
use crate::solve::{EvalCtxt, SolverMode};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::traits::solve::inspect::ProbeKind;
|
||||
@ -17,6 +16,9 @@ use rustc_middle::ty::{TypeVisitableExt, Upcast};
|
||||
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::solve::GoalSource;
|
||||
use crate::solve::{EvalCtxt, SolverMode};
|
||||
|
||||
pub(super) mod structural_traits;
|
||||
|
||||
/// A candidate is a possible way to prove a goal.
|
||||
@ -46,18 +48,18 @@ pub(super) trait GoalKind<'tcx>:
|
||||
/// work, then produce a response (typically by executing
|
||||
/// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]).
|
||||
fn probe_and_match_goal_against_assumption(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
source: CandidateSource<'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
assumption: ty::Clause<'tcx>,
|
||||
then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
|
||||
then: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> QueryResult<'tcx>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
/// Consider a clause, which consists of a "assumption" and some "requirements",
|
||||
/// to satisfy a goal. If the requirements hold, then attempt to satisfy our
|
||||
/// goal by equating it with the assumption.
|
||||
fn probe_and_consider_implied_clause(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
parent_source: CandidateSource<'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
assumption: ty::Clause<'tcx>,
|
||||
@ -75,7 +77,7 @@ pub(super) trait GoalKind<'tcx>:
|
||||
/// additionally checking all of the supertraits and object bounds to hold,
|
||||
/// since they're not implied by the well-formedness of the object type.
|
||||
fn probe_and_consider_object_bound_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
source: CandidateSource<'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
assumption: ty::Clause<'tcx>,
|
||||
@ -99,7 +101,7 @@ pub(super) trait GoalKind<'tcx>:
|
||||
}
|
||||
|
||||
fn consider_impl_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
impl_def_id: DefId,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
@ -111,7 +113,7 @@ pub(super) trait GoalKind<'tcx>:
|
||||
/// Trait goals always hold while projection goals never do. This is a bit arbitrary
|
||||
/// but prevents incorrect normalization while hiding any trait errors.
|
||||
fn consider_error_guaranteed_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
guar: ErrorGuaranteed,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
@ -120,13 +122,13 @@ pub(super) trait GoalKind<'tcx>:
|
||||
/// These components are given by built-in rules from
|
||||
/// [`structural_traits::instantiate_constituent_tys_for_auto_trait`].
|
||||
fn consider_auto_trait_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
/// A trait alias holds if the RHS traits and `where` clauses hold.
|
||||
fn consider_trait_alias_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
@ -135,7 +137,7 @@ pub(super) trait GoalKind<'tcx>:
|
||||
/// These components are given by built-in rules from
|
||||
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
|
||||
fn consider_builtin_sized_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
@ -144,27 +146,27 @@ pub(super) trait GoalKind<'tcx>:
|
||||
/// These components are given by built-in rules from
|
||||
/// [`structural_traits::instantiate_constituent_tys_for_copy_clone_trait`].
|
||||
fn consider_builtin_copy_clone_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
/// A type is `PointerLike` if we can compute its layout, and that layout
|
||||
/// matches the layout of `usize`.
|
||||
fn consider_builtin_pointer_like_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
/// A type is a `FnPtr` if it is of `FnPtr` type.
|
||||
fn consider_builtin_fn_ptr_trait_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
/// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>`
|
||||
/// family of traits where `A` is given by the signature of the type.
|
||||
fn consider_builtin_fn_trait_candidates(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
kind: ty::ClosureKind,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
@ -172,7 +174,7 @@ pub(super) trait GoalKind<'tcx>:
|
||||
/// An async closure is known to implement the `AsyncFn<A>` family of traits
|
||||
/// where `A` is given by the signature of the type.
|
||||
fn consider_builtin_async_fn_trait_candidates(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
kind: ty::ClosureKind,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
@ -181,13 +183,13 @@ pub(super) trait GoalKind<'tcx>:
|
||||
/// is used internally to delay computation for async closures until after
|
||||
/// upvar analysis is performed in HIR typeck.
|
||||
fn consider_builtin_async_fn_kind_helper_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
/// `Tuple` is implemented if the `Self` type is a tuple.
|
||||
fn consider_builtin_tuple_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
@ -197,7 +199,7 @@ pub(super) trait GoalKind<'tcx>:
|
||||
/// the built-in types. For structs, the metadata type is given by the struct
|
||||
/// tail.
|
||||
fn consider_builtin_pointee_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
@ -205,7 +207,7 @@ pub(super) trait GoalKind<'tcx>:
|
||||
/// `Future<Output = O>`, where `O` is given by the coroutine's return type
|
||||
/// that was computed during type-checking.
|
||||
fn consider_builtin_future_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
@ -213,19 +215,19 @@ pub(super) trait GoalKind<'tcx>:
|
||||
/// `Iterator<Item = O>`, where `O` is given by the generator's yield type
|
||||
/// that was computed during type-checking.
|
||||
fn consider_builtin_iterator_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
/// A coroutine (that comes from a `gen` desugaring) is known to implement
|
||||
/// `FusedIterator`
|
||||
fn consider_builtin_fused_iterator_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
fn consider_builtin_async_iterator_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
@ -233,27 +235,27 @@ pub(super) trait GoalKind<'tcx>:
|
||||
/// implement `Coroutine<R, Yield = Y, Return = O>`, given the resume, yield,
|
||||
/// and return types of the coroutine computed during type-checking.
|
||||
fn consider_builtin_coroutine_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
fn consider_builtin_discriminant_kind_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
fn consider_builtin_async_destruct_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
fn consider_builtin_destruct_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
fn consider_builtin_transmute_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution>;
|
||||
|
||||
@ -265,12 +267,12 @@ pub(super) trait GoalKind<'tcx>:
|
||||
/// otherwise recompute this for codegen. This is a bit of a mess but the
|
||||
/// easiest way to maintain the existing behavior for now.
|
||||
fn consider_structural_builtin_unsize_candidates(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Vec<Candidate<'tcx>>;
|
||||
}
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||
pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'tcx>>(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, G>,
|
||||
|
@ -3,6 +3,7 @@
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_hir::{def_id::DefId, Movability, Mutability};
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
use rustc_middle::bug;
|
||||
@ -18,7 +19,7 @@ use crate::solve::EvalCtxt;
|
||||
// instantiate the binder with placeholders eagerly.
|
||||
#[instrument(level = "trace", skip(ecx), ret)]
|
||||
pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
|
||||
ecx: &EvalCtxt<'_, 'tcx>,
|
||||
ecx: &EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution> {
|
||||
let tcx = ecx.tcx();
|
||||
@ -97,7 +98,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
|
||||
|
||||
#[instrument(level = "trace", skip(ecx), ret)]
|
||||
pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
|
||||
ecx: &EvalCtxt<'_, 'tcx>,
|
||||
ecx: &EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution> {
|
||||
match *ty.kind() {
|
||||
@ -161,7 +162,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
|
||||
|
||||
#[instrument(level = "trace", skip(ecx), ret)]
|
||||
pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
|
||||
ecx: &EvalCtxt<'_, 'tcx>,
|
||||
ecx: &EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution> {
|
||||
match *ty.kind() {
|
||||
@ -663,7 +664,7 @@ fn coroutine_closure_to_ambiguous_coroutine<'tcx>(
|
||||
// normalize eagerly here. See https://github.com/lcnr/solver-woes/issues/9
|
||||
// for more details.
|
||||
pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
|
||||
ecx: &EvalCtxt<'_, 'tcx>,
|
||||
ecx: &EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
trait_ref: ty::TraitRef<'tcx>,
|
||||
object_bound: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
@ -716,7 +717,7 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
|
||||
}
|
||||
|
||||
struct ReplaceProjectionWith<'a, 'tcx> {
|
||||
ecx: &'a EvalCtxt<'a, 'tcx>,
|
||||
ecx: &'a EvalCtxt<'a, InferCtxt<'tcx>>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
mapping: FxHashMap<DefId, ty::PolyProjectionPredicate<'tcx>>,
|
||||
nested: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
|
||||
|
@ -52,7 +52,7 @@ impl<'tcx, T> ResponseT<'tcx> for inspect::State<TyCtxt<'tcx>, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||
/// Canonicalizes the goal remembering the original values
|
||||
/// for each bound variable.
|
||||
pub(super) fn canonicalize_goal<T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
|
@ -4,7 +4,6 @@ use std::ops::ControlFlow;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::at::ToTrace;
|
||||
use rustc_infer::infer::canonical::CanonicalVarValues;
|
||||
use rustc_infer::infer::{
|
||||
BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk, TyCtxtInferExt,
|
||||
};
|
||||
@ -13,10 +12,8 @@ use rustc_infer::traits::solve::{MaybeCause, NestedNormalizationGoals};
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_macros::{extension, HashStable, HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::infer::canonical::CanonicalVarInfos;
|
||||
use rustc_middle::traits::solve::{
|
||||
inspect, CanonicalInput, CanonicalResponse, Certainty, PredefinedOpaques,
|
||||
PredefinedOpaquesData, QueryResult,
|
||||
inspect, CanonicalInput, CanonicalResponse, Certainty, PredefinedOpaquesData, QueryResult,
|
||||
};
|
||||
use rustc_middle::traits::specialization_graph;
|
||||
use rustc_middle::ty::{
|
||||
@ -25,7 +22,7 @@ use rustc_middle::ty::{
|
||||
};
|
||||
use rustc_session::config::DumpSolverProofTree;
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_type_ir::{self as ir, Interner};
|
||||
use rustc_type_ir::{self as ir, CanonicalVarValues, Interner};
|
||||
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
|
||||
use crate::traits::coherence;
|
||||
@ -41,7 +38,11 @@ pub(super) mod canonical;
|
||||
mod probe;
|
||||
mod select;
|
||||
|
||||
pub struct EvalCtxt<'a, 'tcx> {
|
||||
pub struct EvalCtxt<
|
||||
'a,
|
||||
Infcx: InferCtxtLike<Interner = I>,
|
||||
I: Interner = <Infcx as InferCtxtLike>::Interner,
|
||||
> {
|
||||
/// The inference context that backs (mostly) inference and placeholder terms
|
||||
/// instantiated while solving goals.
|
||||
///
|
||||
@ -57,11 +58,11 @@ pub struct EvalCtxt<'a, 'tcx> {
|
||||
/// 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.
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
infcx: &'a Infcx,
|
||||
|
||||
/// The variable info for the `var_values`, only used to make an ambiguous response
|
||||
/// with no constraints.
|
||||
variables: CanonicalVarInfos<'tcx>,
|
||||
variables: I::CanonicalVars,
|
||||
/// 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
|
||||
@ -70,9 +71,9 @@ pub struct EvalCtxt<'a, 'tcx> {
|
||||
/// when then adds these to its own context. The caller is always an `AliasRelate`
|
||||
/// goal so this never leaks out of the solver.
|
||||
is_normalizes_to_goal: bool,
|
||||
pub(super) var_values: CanonicalVarValues<'tcx>,
|
||||
pub(super) var_values: CanonicalVarValues<I>,
|
||||
|
||||
predefined_opaques_in_body: PredefinedOpaques<'tcx>,
|
||||
predefined_opaques_in_body: I::PredefinedOpaques,
|
||||
|
||||
/// The highest universe index nameable by the caller.
|
||||
///
|
||||
@ -85,9 +86,9 @@ pub struct EvalCtxt<'a, 'tcx> {
|
||||
/// new placeholders to the caller.
|
||||
pub(super) max_input_universe: ty::UniverseIndex,
|
||||
|
||||
pub(super) search_graph: &'a mut SearchGraph<'tcx>,
|
||||
pub(super) search_graph: &'a mut SearchGraph<I>,
|
||||
|
||||
nested_goals: NestedGoals<TyCtxt<'tcx>>,
|
||||
nested_goals: NestedGoals<I>,
|
||||
|
||||
// Has this `EvalCtxt` errored out with `NoSolution` in `try_evaluate_added_goals`?
|
||||
//
|
||||
@ -97,7 +98,7 @@ pub struct EvalCtxt<'a, 'tcx> {
|
||||
// evaluation code.
|
||||
tainted: Result<(), NoSolution>,
|
||||
|
||||
pub(super) inspect: ProofTreeBuilder<TyCtxt<'tcx>>,
|
||||
pub(super) inspect: ProofTreeBuilder<I>,
|
||||
}
|
||||
|
||||
#[derive(derivative::Derivative)]
|
||||
@ -157,7 +158,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||
impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
|
||||
pub(super) fn solver_mode(&self) -> SolverMode {
|
||||
self.search_graph.solver_mode()
|
||||
}
|
||||
@ -172,7 +173,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||
pub(super) fn enter_root<R>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
generate_proof_tree: GenerateProofTree,
|
||||
f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> R,
|
||||
f: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> R,
|
||||
) -> (R, Option<inspect::GoalEvaluation<TyCtxt<'tcx>>>) {
|
||||
let mode = if infcx.intercrate { SolverMode::Coherence } else { SolverMode::Normal };
|
||||
let mut search_graph = search_graph::SearchGraph::new(mode);
|
||||
@ -225,10 +226,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||
/// and registering opaques from the canonicalized input.
|
||||
fn enter_canonical<R>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
search_graph: &'a mut search_graph::SearchGraph<'tcx>,
|
||||
search_graph: &'a mut search_graph::SearchGraph<TyCtxt<'tcx>>,
|
||||
canonical_input: CanonicalInput<'tcx>,
|
||||
canonical_goal_evaluation: &mut ProofTreeBuilder<TyCtxt<'tcx>>,
|
||||
f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>, Goal<'tcx, ty::Predicate<'tcx>>) -> R,
|
||||
f: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>, Goal<'tcx, ty::Predicate<'tcx>>) -> R,
|
||||
) -> R {
|
||||
let intercrate = match search_graph.solver_mode() {
|
||||
SolverMode::Normal => false,
|
||||
@ -287,7 +288,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||
#[instrument(level = "debug", skip(tcx, search_graph, goal_evaluation), ret)]
|
||||
fn evaluate_canonical_goal(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
search_graph: &'a mut search_graph::SearchGraph<'tcx>,
|
||||
search_graph: &'a mut search_graph::SearchGraph<TyCtxt<'tcx>>,
|
||||
canonical_input: CanonicalInput<'tcx>,
|
||||
goal_evaluation: &mut ProofTreeBuilder<TyCtxt<'tcx>>,
|
||||
) -> QueryResult<'tcx> {
|
||||
@ -600,7 +601,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||
pub(super) fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::solve::assembly::Candidate;
|
||||
|
||||
use super::EvalCtxt;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::traits::BuiltinImplSource;
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::traits::solve::{inspect, CandidateSource, QueryResult};
|
||||
@ -8,7 +9,7 @@ use rustc_middle::ty::TyCtxt;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub(in crate::solve) struct ProbeCtxt<'me, 'a, 'tcx, F, T> {
|
||||
ecx: &'me mut EvalCtxt<'a, 'tcx>,
|
||||
ecx: &'me mut EvalCtxt<'a, InferCtxt<'tcx>>,
|
||||
probe_kind: F,
|
||||
_result: PhantomData<T>,
|
||||
}
|
||||
@ -17,7 +18,10 @@ impl<'tcx, F, T> ProbeCtxt<'_, '_, 'tcx, F, T>
|
||||
where
|
||||
F: FnOnce(&T) -> inspect::ProbeKind<TyCtxt<'tcx>>,
|
||||
{
|
||||
pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> T) -> T {
|
||||
pub(in crate::solve) fn enter(
|
||||
self,
|
||||
f: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> T,
|
||||
) -> T {
|
||||
let ProbeCtxt { ecx: outer_ecx, probe_kind, _result } = self;
|
||||
|
||||
let infcx = outer_ecx.infcx;
|
||||
@ -60,13 +64,13 @@ where
|
||||
#[instrument(level = "debug", skip_all, fields(source = ?self.source))]
|
||||
pub(in crate::solve) fn enter(
|
||||
self,
|
||||
f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
|
||||
f: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> QueryResult<'tcx>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
self.cx.enter(|ecx| f(ecx)).map(|result| Candidate { source: self.source, result })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||
impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
|
||||
/// `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 crate::solve) fn probe<F, T>(&mut self, probe_kind: F) -> ProbeCtxt<'_, 'a, 'tcx, F, T>
|
||||
|
@ -15,6 +15,7 @@
|
||||
//! about it on zulip.
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_macros::extension;
|
||||
use rustc_middle::bug;
|
||||
@ -82,7 +83,7 @@ impl<'tcx> Canonical<'tcx, Response<TyCtxt<'tcx>>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||
impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn compute_type_outlives_goal(
|
||||
&mut self,
|
||||
@ -201,7 +202,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||
#[instrument(level = "trace", skip(self, goals))]
|
||||
fn add_goals(
|
||||
&mut self,
|
||||
|
@ -1,8 +1,9 @@
|
||||
use crate::solve::EvalCtxt;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
||||
use rustc_middle::ty;
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
pub(super) fn normalize_anon_const(
|
||||
&mut self,
|
||||
|
@ -4,12 +4,13 @@
|
||||
//! 1. instantiate generic parameters,
|
||||
//! 2. equate the self type, and
|
||||
//! 3. instantiate and register where clauses.
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, QueryResult};
|
||||
use rustc_middle::ty;
|
||||
|
||||
use crate::solve::EvalCtxt;
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||
pub(super) fn normalize_inherent_associated_type(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
|
||||
|
@ -5,6 +5,7 @@ use super::assembly::{self, structural_traits, Candidate};
|
||||
use super::{EvalCtxt, GoalSource};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_infer::traits::solve::inspect::ProbeKind;
|
||||
use rustc_infer::traits::solve::MaybeCause;
|
||||
@ -24,7 +25,7 @@ mod inherent;
|
||||
mod opaque_types;
|
||||
mod weak_types;
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
pub(super) fn compute_normalizes_to_goal(
|
||||
&mut self,
|
||||
@ -98,11 +99,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
}
|
||||
|
||||
fn probe_and_match_goal_against_assumption(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
source: CandidateSource<'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
assumption: ty::Clause<'tcx>,
|
||||
then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
|
||||
then: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> QueryResult<'tcx>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if let Some(projection_pred) = assumption.as_projection_clause() {
|
||||
if projection_pred.projection_def_id() == goal.predicate.def_id() {
|
||||
@ -137,7 +138,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_impl_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, NormalizesTo<'tcx>>,
|
||||
impl_def_id: DefId,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
@ -199,7 +200,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
|
||||
};
|
||||
|
||||
let error_response = |ecx: &mut EvalCtxt<'_, 'tcx>, reason| {
|
||||
let error_response = |ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, reason| {
|
||||
let guar = tcx.dcx().span_delayed_bug(tcx.def_span(assoc_def.item.def_id), reason);
|
||||
let error_term = match assoc_def.item.kind {
|
||||
ty::AssocKind::Const => ty::Const::new_error(
|
||||
@ -279,14 +280,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
/// Fail to normalize if the predicate contains an error, alternatively, we could normalize to `ty::Error`
|
||||
/// and succeed. Can experiment with this to figure out what results in better error messages.
|
||||
fn consider_error_guaranteed_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
_ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
_guar: ErrorGuaranteed,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
Err(NoSolution)
|
||||
}
|
||||
|
||||
fn consider_auto_trait_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
ecx.tcx().dcx().span_delayed_bug(
|
||||
@ -297,42 +298,42 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_trait_alias_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
_ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
bug!("trait aliases do not have associated types: {:?}", goal);
|
||||
}
|
||||
|
||||
fn consider_builtin_sized_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
_ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
bug!("`Sized` does not have an associated type: {:?}", goal);
|
||||
}
|
||||
|
||||
fn consider_builtin_copy_clone_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
_ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
bug!("`Copy`/`Clone` does not have an associated type: {:?}", goal);
|
||||
}
|
||||
|
||||
fn consider_builtin_pointer_like_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
_ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
bug!("`PointerLike` does not have an associated type: {:?}", goal);
|
||||
}
|
||||
|
||||
fn consider_builtin_fn_ptr_trait_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
_ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
bug!("`FnPtr` does not have an associated type: {:?}", goal);
|
||||
}
|
||||
|
||||
fn consider_builtin_fn_trait_candidates(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
goal_kind: ty::ClosureKind,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
@ -375,7 +376,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_async_fn_trait_candidates(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
goal_kind: ty::ClosureKind,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
@ -460,7 +461,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_async_fn_kind_helper_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
let [
|
||||
@ -507,14 +508,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_tuple_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
_ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
bug!("`Tuple` does not have an associated type: {:?}", goal);
|
||||
}
|
||||
|
||||
fn consider_builtin_pointee_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
let tcx = ecx.tcx();
|
||||
@ -596,7 +597,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_future_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
let self_ty = goal.predicate.self_ty();
|
||||
@ -628,7 +629,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_iterator_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
let self_ty = goal.predicate.self_ty();
|
||||
@ -660,14 +661,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_fused_iterator_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
_ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
bug!("`FusedIterator` does not have an associated type: {:?}", goal);
|
||||
}
|
||||
|
||||
fn consider_builtin_async_iterator_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
let self_ty = goal.predicate.self_ty();
|
||||
@ -703,7 +704,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_coroutine_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
let self_ty = goal.predicate.self_ty();
|
||||
@ -748,14 +749,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_structural_builtin_unsize_candidates(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
_ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Vec<Candidate<'tcx>> {
|
||||
bug!("`Unsize` does not have an associated type: {:?}", goal);
|
||||
}
|
||||
|
||||
fn consider_builtin_discriminant_kind_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
let self_ty = goal.predicate.self_ty();
|
||||
@ -807,7 +808,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_async_destruct_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
let self_ty = goal.predicate.self_ty();
|
||||
@ -860,14 +861,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_destruct_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
_ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
bug!("`Destruct` does not have an associated type: {:?}", goal);
|
||||
}
|
||||
|
||||
fn consider_builtin_transmute_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
_ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
bug!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal)
|
||||
@ -880,7 +881,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||
/// diverge.
|
||||
#[instrument(level = "trace", skip(ecx, param_env), ret)]
|
||||
fn fetch_eligible_assoc_item_def<'tcx>(
|
||||
ecx: &EvalCtxt<'_, 'tcx>,
|
||||
ecx: &EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
goal_trait_ref: ty::TraitRef<'tcx>,
|
||||
trait_assoc_def_id: DefId,
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Computes a normalizes-to (projection) goal for opaque types. This goal
|
||||
//! behaves differently depending on the param-env's reveal mode and whether
|
||||
//! the opaque is in a defining scope.
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
||||
use rustc_middle::traits::Reveal;
|
||||
@ -9,7 +10,7 @@ use rustc_middle::ty::util::NotUniqueParam;
|
||||
|
||||
use crate::solve::{EvalCtxt, SolverMode};
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||
pub(super) fn normalize_opaque_type(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
|
||||
|
@ -3,12 +3,13 @@
|
||||
//!
|
||||
//! Since a weak alias is never ambiguous, this just computes the `type_of` of
|
||||
//! the alias and registers the where-clauses of the type alias.
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, QueryResult};
|
||||
use rustc_middle::ty;
|
||||
|
||||
use crate::solve::EvalCtxt;
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||
pub(super) fn normalize_weak_type(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
|
||||
|
@ -1,10 +1,11 @@
|
||||
use crate::solve::GoalSource;
|
||||
|
||||
use super::EvalCtxt;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
||||
use rustc_middle::ty::{self, ProjectionPredicate};
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
pub(super) fn compute_projection_goal(
|
||||
&mut self,
|
||||
|
@ -1,18 +1,21 @@
|
||||
use crate::solve::FIXPOINT_STEP_LIMIT;
|
||||
use std::mem;
|
||||
|
||||
use super::inspect;
|
||||
use super::inspect::ProofTreeBuilder;
|
||||
use super::SolverMode;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_index::Idx;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::dep_graph::dep_kinds;
|
||||
use rustc_middle::traits::solve::CacheData;
|
||||
use rustc_middle::traits::solve::{CanonicalInput, Certainty, EvaluationCache, QueryResult};
|
||||
use rustc_middle::traits::solve::EvaluationCache;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_next_trait_solver::solve::{CanonicalInput, Certainty, QueryResult};
|
||||
use rustc_session::Limit;
|
||||
use std::mem;
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::Interner;
|
||||
|
||||
use super::inspect;
|
||||
use super::inspect::ProofTreeBuilder;
|
||||
use super::SolverMode;
|
||||
use crate::solve::FIXPOINT_STEP_LIMIT;
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
#[orderable]
|
||||
@ -30,9 +33,10 @@ bitflags::bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct StackEntry<'tcx> {
|
||||
input: CanonicalInput<'tcx>,
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Debug(bound = ""))]
|
||||
struct StackEntry<I: Interner> {
|
||||
input: CanonicalInput<I>,
|
||||
|
||||
available_depth: Limit,
|
||||
|
||||
@ -53,11 +57,11 @@ struct StackEntry<'tcx> {
|
||||
has_been_used: HasBeenUsed,
|
||||
/// Starts out as `None` and gets set when rerunning this
|
||||
/// goal in case we encounter a cycle.
|
||||
provisional_result: Option<QueryResult<'tcx>>,
|
||||
provisional_result: Option<QueryResult<I>>,
|
||||
}
|
||||
|
||||
/// The provisional result for a goal which is not on the stack.
|
||||
struct DetachedEntry<'tcx> {
|
||||
struct DetachedEntry<I: Interner> {
|
||||
/// The head of the smallest non-trivial cycle involving this entry.
|
||||
///
|
||||
/// Given the following rules, when proving `A` the head for
|
||||
@ -68,7 +72,7 @@ struct DetachedEntry<'tcx> {
|
||||
/// C :- A + B + C
|
||||
/// ```
|
||||
head: StackDepth,
|
||||
result: QueryResult<'tcx>,
|
||||
result: QueryResult<I>,
|
||||
}
|
||||
|
||||
/// Stores the stack depth of a currently evaluated goal *and* already
|
||||
@ -83,14 +87,15 @@ struct DetachedEntry<'tcx> {
|
||||
///
|
||||
/// The provisional cache can theoretically result in changes to the observable behavior,
|
||||
/// see tests/ui/traits/next-solver/cycles/provisional-cache-impacts-behavior.rs.
|
||||
#[derive(Default)]
|
||||
struct ProvisionalCacheEntry<'tcx> {
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Default(bound = ""))]
|
||||
struct ProvisionalCacheEntry<I: Interner> {
|
||||
stack_depth: Option<StackDepth>,
|
||||
with_inductive_stack: Option<DetachedEntry<'tcx>>,
|
||||
with_coinductive_stack: Option<DetachedEntry<'tcx>>,
|
||||
with_inductive_stack: Option<DetachedEntry<I>>,
|
||||
with_coinductive_stack: Option<DetachedEntry<I>>,
|
||||
}
|
||||
|
||||
impl<'tcx> ProvisionalCacheEntry<'tcx> {
|
||||
impl<I: Interner> ProvisionalCacheEntry<I> {
|
||||
fn is_empty(&self) -> bool {
|
||||
self.stack_depth.is_none()
|
||||
&& self.with_inductive_stack.is_none()
|
||||
@ -98,13 +103,13 @@ impl<'tcx> ProvisionalCacheEntry<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SearchGraph<'tcx> {
|
||||
pub(super) struct SearchGraph<I: Interner> {
|
||||
mode: SolverMode,
|
||||
/// The stack of goals currently being computed.
|
||||
///
|
||||
/// An element is *deeper* in the stack if its index is *lower*.
|
||||
stack: IndexVec<StackDepth, StackEntry<'tcx>>,
|
||||
provisional_cache: FxHashMap<CanonicalInput<'tcx>, ProvisionalCacheEntry<'tcx>>,
|
||||
stack: IndexVec<StackDepth, StackEntry<I>>,
|
||||
provisional_cache: FxHashMap<CanonicalInput<I>, ProvisionalCacheEntry<I>>,
|
||||
/// We put only the root goal of a coinductive cycle into the global cache.
|
||||
///
|
||||
/// If we were to use that result when later trying to prove another cycle
|
||||
@ -112,11 +117,11 @@ pub(super) struct SearchGraph<'tcx> {
|
||||
///
|
||||
/// See tests/ui/next-solver/coinduction/incompleteness-unstable-result.rs for
|
||||
/// an example of where this is needed.
|
||||
cycle_participants: FxHashSet<CanonicalInput<'tcx>>,
|
||||
cycle_participants: FxHashSet<CanonicalInput<I>>,
|
||||
}
|
||||
|
||||
impl<'tcx> SearchGraph<'tcx> {
|
||||
pub(super) fn new(mode: SolverMode) -> SearchGraph<'tcx> {
|
||||
impl<I: Interner> SearchGraph<I> {
|
||||
pub(super) fn new(mode: SolverMode) -> SearchGraph<I> {
|
||||
Self {
|
||||
mode,
|
||||
stack: Default::default(),
|
||||
@ -144,7 +149,7 @@ impl<'tcx> SearchGraph<'tcx> {
|
||||
///
|
||||
/// Directly popping from the stack instead of using this method
|
||||
/// would cause us to not track overflow and recursion depth correctly.
|
||||
fn pop_stack(&mut self) -> StackEntry<'tcx> {
|
||||
fn pop_stack(&mut self) -> StackEntry<I> {
|
||||
let elem = self.stack.pop().unwrap();
|
||||
if let Some(last) = self.stack.raw.last_mut() {
|
||||
last.reached_depth = last.reached_depth.max(elem.reached_depth);
|
||||
@ -153,17 +158,6 @@ impl<'tcx> SearchGraph<'tcx> {
|
||||
elem
|
||||
}
|
||||
|
||||
/// The trait solver behavior is different for coherence
|
||||
/// so we use a separate cache. Alternatively we could use
|
||||
/// a single cache and share it between coherence and ordinary
|
||||
/// trait solving.
|
||||
pub(super) fn global_cache(&self, tcx: TyCtxt<'tcx>) -> &'tcx EvaluationCache<'tcx> {
|
||||
match self.mode {
|
||||
SolverMode::Normal => &tcx.new_solver_evaluation_cache,
|
||||
SolverMode::Coherence => &tcx.new_solver_coherence_evaluation_cache,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn is_empty(&self) -> bool {
|
||||
if self.stack.is_empty() {
|
||||
debug_assert!(self.provisional_cache.is_empty());
|
||||
@ -181,8 +175,8 @@ impl<'tcx> SearchGraph<'tcx> {
|
||||
/// the remaining depth of all nested goals to prevent hangs
|
||||
/// in case there is exponential blowup.
|
||||
fn allowed_depth_for_nested(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
stack: &IndexVec<StackDepth, StackEntry<'tcx>>,
|
||||
tcx: I,
|
||||
stack: &IndexVec<StackDepth, StackEntry<I>>,
|
||||
) -> Option<Limit> {
|
||||
if let Some(last) = stack.raw.last() {
|
||||
if last.available_depth.0 == 0 {
|
||||
@ -195,13 +189,13 @@ impl<'tcx> SearchGraph<'tcx> {
|
||||
Limit(last.available_depth.0 - 1)
|
||||
})
|
||||
} else {
|
||||
Some(tcx.recursion_limit())
|
||||
Some(Limit(tcx.recursion_limit()))
|
||||
}
|
||||
}
|
||||
|
||||
fn stack_coinductive_from(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
stack: &IndexVec<StackDepth, StackEntry<'tcx>>,
|
||||
tcx: I,
|
||||
stack: &IndexVec<StackDepth, StackEntry<I>>,
|
||||
head: StackDepth,
|
||||
) -> bool {
|
||||
stack.raw[head.index()..]
|
||||
@ -220,8 +214,8 @@ impl<'tcx> SearchGraph<'tcx> {
|
||||
// we reach a fixpoint and all other cycle participants to make sure that
|
||||
// their result does not get moved to the global cache.
|
||||
fn tag_cycle_participants(
|
||||
stack: &mut IndexVec<StackDepth, StackEntry<'tcx>>,
|
||||
cycle_participants: &mut FxHashSet<CanonicalInput<'tcx>>,
|
||||
stack: &mut IndexVec<StackDepth, StackEntry<I>>,
|
||||
cycle_participants: &mut FxHashSet<CanonicalInput<I>>,
|
||||
usage_kind: HasBeenUsed,
|
||||
head: StackDepth,
|
||||
) {
|
||||
@ -234,7 +228,7 @@ impl<'tcx> SearchGraph<'tcx> {
|
||||
}
|
||||
|
||||
fn clear_dependent_provisional_results(
|
||||
provisional_cache: &mut FxHashMap<CanonicalInput<'tcx>, ProvisionalCacheEntry<'tcx>>,
|
||||
provisional_cache: &mut FxHashMap<CanonicalInput<I>, ProvisionalCacheEntry<I>>,
|
||||
head: StackDepth,
|
||||
) {
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
@ -244,6 +238,19 @@ impl<'tcx> SearchGraph<'tcx> {
|
||||
!entry.is_empty()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
|
||||
/// The trait solver behavior is different for coherence
|
||||
/// so we use a separate cache. Alternatively we could use
|
||||
/// a single cache and share it between coherence and ordinary
|
||||
/// trait solving.
|
||||
pub(super) fn global_cache(&self, tcx: TyCtxt<'tcx>) -> &'tcx EvaluationCache<'tcx> {
|
||||
match self.mode {
|
||||
SolverMode::Normal => &tcx.new_solver_evaluation_cache,
|
||||
SolverMode::Coherence => &tcx.new_solver_coherence_evaluation_cache,
|
||||
}
|
||||
}
|
||||
|
||||
/// Probably the most involved method of the whole solver.
|
||||
///
|
||||
@ -252,10 +259,13 @@ impl<'tcx> SearchGraph<'tcx> {
|
||||
pub(super) fn with_new_goal(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
input: CanonicalInput<'tcx>,
|
||||
input: CanonicalInput<TyCtxt<'tcx>>,
|
||||
inspect: &mut ProofTreeBuilder<TyCtxt<'tcx>>,
|
||||
mut prove_goal: impl FnMut(&mut Self, &mut ProofTreeBuilder<TyCtxt<'tcx>>) -> QueryResult<'tcx>,
|
||||
) -> QueryResult<'tcx> {
|
||||
mut prove_goal: impl FnMut(
|
||||
&mut Self,
|
||||
&mut ProofTreeBuilder<TyCtxt<'tcx>>,
|
||||
) -> QueryResult<TyCtxt<'tcx>>,
|
||||
) -> QueryResult<TyCtxt<'tcx>> {
|
||||
// Check for overflow.
|
||||
let Some(available_depth) = Self::allowed_depth_for_nested(tcx, &self.stack) else {
|
||||
if let Some(last) = self.stack.raw.last_mut() {
|
||||
@ -489,9 +499,9 @@ impl<'tcx> SearchGraph<'tcx> {
|
||||
|
||||
fn response_no_constraints(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
goal: CanonicalInput<'tcx>,
|
||||
goal: CanonicalInput<TyCtxt<'tcx>>,
|
||||
certainty: Certainty,
|
||||
) -> QueryResult<'tcx> {
|
||||
) -> QueryResult<TyCtxt<'tcx>> {
|
||||
Ok(super::response_no_constraints_raw(tcx, goal.max_universe, goal.variables, certainty))
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use super::{EvalCtxt, GoalSource, SolverMode};
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{LangItem, Movability};
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_infer::traits::solve::MaybeCause;
|
||||
use rustc_middle::bug;
|
||||
@ -37,7 +38,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_impl_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, TraitPredicate<'tcx>>,
|
||||
impl_def_id: DefId,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
@ -93,7 +94,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_error_guaranteed_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
_guar: ErrorGuaranteed,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
// FIXME: don't need to enter a probe here.
|
||||
@ -102,11 +103,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn probe_and_match_goal_against_assumption(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
source: CandidateSource<'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
assumption: ty::Clause<'tcx>,
|
||||
then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
|
||||
then: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> QueryResult<'tcx>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if let Some(trait_clause) = assumption.as_trait_clause() {
|
||||
if trait_clause.def_id() == goal.predicate.def_id()
|
||||
@ -130,7 +131,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_auto_trait_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -173,7 +174,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_trait_alias_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -196,7 +197,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_sized_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -211,7 +212,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_copy_clone_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -226,7 +227,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_pointer_like_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -256,7 +257,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_fn_ptr_trait_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
let self_ty = goal.predicate.self_ty();
|
||||
@ -287,7 +288,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_fn_trait_candidates(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
goal_kind: ty::ClosureKind,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
@ -328,7 +329,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_async_fn_trait_candidates(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
goal_kind: ty::ClosureKind,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
@ -379,7 +380,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_async_fn_kind_helper_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
let [closure_fn_kind_ty, goal_kind_ty] = **goal.predicate.trait_ref.args else {
|
||||
@ -406,7 +407,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
/// impl Tuple for (T1, .., Tn) {}
|
||||
/// ```
|
||||
fn consider_builtin_tuple_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -422,7 +423,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_pointee_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -434,7 +435,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_future_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -460,7 +461,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_iterator_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -486,7 +487,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_fused_iterator_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -510,7 +511,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_async_iterator_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -536,7 +537,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_coroutine_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -568,7 +569,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_discriminant_kind_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -581,7 +582,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_async_destruct_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -594,7 +595,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_destruct_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -610,7 +611,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
fn consider_builtin_transmute_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -651,7 +652,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
/// impl<'a, T: Trait + 'a> Unsize<dyn Trait + 'a> for T {}
|
||||
/// ```
|
||||
fn consider_structural_builtin_unsize_candidates(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Vec<Candidate<'tcx>> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
@ -722,7 +723,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||
/// Trait upcasting allows for coercions between trait objects:
|
||||
/// ```ignore (builtin impl example)
|
||||
/// trait Super {}
|
||||
@ -846,7 +847,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
// having any inference side-effects. We process obligations because
|
||||
// unification may initially succeed due to deferred projection equality.
|
||||
let projection_may_match =
|
||||
|ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
|ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
source_projection: ty::PolyExistentialProjection<'tcx>,
|
||||
target_projection: ty::PolyExistentialProjection<'tcx>| {
|
||||
source_projection.item_def_id() == target_projection.item_def_id()
|
||||
@ -1152,7 +1153,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
source: CandidateSource<'tcx>,
|
||||
goal: Goal<'tcx, TraitPredicate<'tcx>>,
|
||||
constituent_tys: impl Fn(
|
||||
&EvalCtxt<'_, 'tcx>,
|
||||
&EvalCtxt<'_, InferCtxt<'tcx>>,
|
||||
Ty<'tcx>,
|
||||
) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution>,
|
||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||
|
@ -96,6 +96,7 @@ pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
|
||||
pub trait Predicate<I: Interner<Predicate = Self>>:
|
||||
Copy + Debug + Hash + Eq + TypeSuperVisitable<I> + TypeSuperFoldable<I> + Flags
|
||||
{
|
||||
fn is_coinductive(self, interner: I) -> bool;
|
||||
}
|
||||
|
||||
/// Common capabilities of placeholder kinds
|
||||
|
@ -124,6 +124,8 @@ pub trait Interner:
|
||||
) -> Self::GenericArgs;
|
||||
|
||||
fn parent(self, def_id: Self::DefId) -> Self::DefId;
|
||||
|
||||
fn recursion_limit(self) -> usize;
|
||||
}
|
||||
|
||||
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
|
||||
|
@ -2496,6 +2496,14 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Arc<T, A> {
|
||||
// [2]: (https://github.com/rust-lang/rust/pull/41714)
|
||||
acquire!(self.inner().strong);
|
||||
|
||||
// Make sure we aren't trying to "drop" the shared static for empty slices
|
||||
// used by Default::default.
|
||||
debug_assert!(
|
||||
!ptr::addr_eq(self.ptr.as_ptr(), &STATIC_INNER_SLICE.inner),
|
||||
"Arcs backed by a static should never reach a strong count of 0. \
|
||||
Likely decrement_strong_count or from_raw were called too many times.",
|
||||
);
|
||||
|
||||
unsafe {
|
||||
self.drop_slow();
|
||||
}
|
||||
@ -3126,6 +3134,15 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Weak<T, A> {
|
||||
|
||||
if inner.weak.fetch_sub(1, Release) == 1 {
|
||||
acquire!(inner.weak);
|
||||
|
||||
// Make sure we aren't trying to "deallocate" the shared static for empty slices
|
||||
// used by Default::default.
|
||||
debug_assert!(
|
||||
!ptr::addr_eq(self.ptr.as_ptr(), &STATIC_INNER_SLICE.inner),
|
||||
"Arc/Weaks backed by a static should never be deallocated. \
|
||||
Likely decrement_strong_count or from_raw were called too many times.",
|
||||
);
|
||||
|
||||
unsafe {
|
||||
self.alloc.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr()))
|
||||
}
|
||||
@ -3367,6 +3384,28 @@ impl<T: Default> Default for Arc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Struct to hold the static `ArcInner` used for empty `Arc<str/CStr/[T]>` as
|
||||
/// returned by `Default::default`.
|
||||
///
|
||||
/// Layout notes:
|
||||
/// * `repr(align(16))` so we can use it for `[T]` with `align_of::<T>() <= 16`.
|
||||
/// * `repr(C)` so `inner` is at offset 0 (and thus guaranteed to actually be aligned to 16).
|
||||
/// * `[u8; 1]` (to be initialized with 0) so it can be used for `Arc<CStr>`.
|
||||
#[repr(C, align(16))]
|
||||
struct SliceArcInnerForStatic {
|
||||
inner: ArcInner<[u8; 1]>,
|
||||
}
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
const MAX_STATIC_INNER_SLICE_ALIGNMENT: usize = 16;
|
||||
|
||||
static STATIC_INNER_SLICE: SliceArcInnerForStatic = SliceArcInnerForStatic {
|
||||
inner: ArcInner {
|
||||
strong: atomic::AtomicUsize::new(1),
|
||||
weak: atomic::AtomicUsize::new(1),
|
||||
data: [0],
|
||||
},
|
||||
};
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Default for Arc<str> {
|
||||
@ -3391,15 +3430,12 @@ impl Default for Arc<core::ffi::CStr> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
use core::ffi::CStr;
|
||||
static STATIC_INNER_CSTR: ArcInner<[u8; 1]> = ArcInner {
|
||||
strong: atomic::AtomicUsize::new(1),
|
||||
weak: atomic::AtomicUsize::new(1),
|
||||
data: [0],
|
||||
};
|
||||
let inner: NonNull<ArcInner<[u8]>> = NonNull::from(&STATIC_INNER_CSTR);
|
||||
let inner: NonNull<ArcInner<CStr>> = NonNull::new(inner.as_ptr() as *mut ArcInner<CStr>).unwrap();
|
||||
let inner: NonNull<ArcInner<[u8]>> = NonNull::from(&STATIC_INNER_SLICE.inner);
|
||||
let inner: NonNull<ArcInner<CStr>> =
|
||||
NonNull::new(inner.as_ptr() as *mut ArcInner<CStr>).unwrap();
|
||||
// `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
|
||||
let this: mem::ManuallyDrop<Arc<CStr>> = unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) };
|
||||
let this: mem::ManuallyDrop<Arc<CStr>> =
|
||||
unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) };
|
||||
(*this).clone()
|
||||
}
|
||||
}
|
||||
@ -3412,31 +3448,20 @@ impl<T> Default for Arc<[T]> {
|
||||
/// This may or may not share an allocation with other Arcs.
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
let alignment_of_t: usize = mem::align_of::<T>();
|
||||
// We only make statics for the lowest five alignments.
|
||||
// Alignments greater than that will use dynamic allocation.
|
||||
macro_rules! use_static_inner_for_alignments {
|
||||
($($alignment:literal),*) => {
|
||||
$(if alignment_of_t == $alignment {
|
||||
// Note: this must be in a new scope because static and type names are unhygenic.
|
||||
#[repr(align($alignment))]
|
||||
struct Aligned;
|
||||
static ALIGNED_STATIC_INNER: ArcInner<Aligned> = ArcInner {
|
||||
strong: atomic::AtomicUsize::new(1),
|
||||
weak: atomic::AtomicUsize::new(1),
|
||||
data: Aligned,
|
||||
};
|
||||
let inner: NonNull<ArcInner<Aligned>> = NonNull::from(&ALIGNED_STATIC_INNER);
|
||||
let inner: NonNull<ArcInner<[T; 0]>> = inner.cast();
|
||||
// `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
|
||||
let this: mem::ManuallyDrop<Arc<[T; 0]>> = unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) };
|
||||
return (*this).clone();
|
||||
})*
|
||||
};
|
||||
if mem::align_of::<T>() <= MAX_STATIC_INNER_SLICE_ALIGNMENT {
|
||||
// We take a reference to the whole struct instead of the ArcInner<[u8; 1]> inside it so
|
||||
// we don't shrink the range of bytes the ptr is allowed to access under Stacked Borrows.
|
||||
// (Miri complains on 32-bit targets with Arc<[Align16]> otherwise.)
|
||||
// (Note that NonNull::from(&STATIC_INNER_SLICE.inner) is fine under Tree Borrows.)
|
||||
let inner: NonNull<SliceArcInnerForStatic> = NonNull::from(&STATIC_INNER_SLICE);
|
||||
let inner: NonNull<ArcInner<[T; 0]>> = inner.cast();
|
||||
// `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
|
||||
let this: mem::ManuallyDrop<Arc<[T; 0]>> =
|
||||
unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) };
|
||||
return (*this).clone();
|
||||
}
|
||||
use_static_inner_for_alignments!(1, 2, 4, 8, 16);
|
||||
|
||||
// If T's alignment is not one of the ones we have a static for, make a new unique allocation.
|
||||
// If T's alignment is too large for the static, make a new unique allocation.
|
||||
let arr: [T; 0] = [];
|
||||
Arc::from(arr)
|
||||
}
|
||||
|
@ -46,8 +46,13 @@ impl<'tcx> DocFolder for NonLocalStripper<'tcx> {
|
||||
// the field and not the one given by the user for the currrent crate.
|
||||
//
|
||||
// FIXME(#125009): Not-local should probably consider same Cargo workspace
|
||||
if !i.def_id().map_or(true, |did| did.is_local()) {
|
||||
if i.visibility(self.tcx) != Some(Visibility::Public) || i.is_doc_hidden() {
|
||||
if let Some(def_id) = i.def_id()
|
||||
&& !def_id.is_local()
|
||||
{
|
||||
if i.is_doc_hidden()
|
||||
// Default to *not* stripping items with inherited visibility.
|
||||
|| i.visibility(self.tcx).map_or(false, |viz| viz != Visibility::Public)
|
||||
{
|
||||
return Some(strip_item(i));
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
// gdb-command:run
|
||||
|
||||
// gdb-command:print plain_string
|
||||
// gdbr-check:$1 = alloc::string::String {vec: alloc::vec::Vec<u8, alloc::alloc::Global> {buf: alloc::raw_vec::RawVec<u8, alloc::alloc::Global> {ptr: core::ptr::unique::Unique<u8> {pointer: core::ptr::non_null::NonNull<u8> {pointer: 0x55555555ab80}, _marker: core::marker::PhantomData<u8>}, cap: alloc::raw_vec::Cap (5), alloc: alloc::alloc::Global}, len: 5}}
|
||||
// gdbr-check:$1 = alloc::string::String {vec: alloc::vec::Vec<u8, alloc::alloc::Global> {buf: alloc::raw_vec::RawVec<u8, alloc::alloc::Global> {ptr: core::ptr::unique::Unique<u8> {pointer: core::ptr::non_null::NonNull<u8> {pointer: 0x[...]}, _marker: core::marker::PhantomData<u8>}, cap: alloc::raw_vec::Cap (5), alloc: alloc::alloc::Global}, len: 5}}
|
||||
|
||||
// gdb-command:print plain_str
|
||||
// gdbr-check:$2 = "Hello"
|
||||
@ -19,7 +19,7 @@
|
||||
// gdbr-check:$4 = ("Hello", "World")
|
||||
|
||||
// gdb-command:print str_in_rc
|
||||
// gdbr-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull<alloc::rc::RcBox<&str>> {pointer: 0x55555555aae0}, phantom: core::marker::PhantomData<alloc::rc::RcBox<&str>>, alloc: alloc::alloc::Global}
|
||||
// gdbr-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull<alloc::rc::RcBox<&str>> {pointer: 0x[...]}, phantom: core::marker::PhantomData<alloc::rc::RcBox<&str>>, alloc: alloc::alloc::Global}
|
||||
|
||||
|
||||
// === LLDB TESTS ==================================================================================
|
||||
|
@ -3,3 +3,8 @@ pub struct InlineOne<A> {
|
||||
}
|
||||
|
||||
pub type InlineU64 = InlineOne<u64>;
|
||||
|
||||
pub enum GenericEnum<T> {
|
||||
Variant(T),
|
||||
Variant2(T, T),
|
||||
}
|
||||
|
@ -117,3 +117,10 @@ pub type HighlyGenericAABB<A, B> = HighlyGenericStruct<A, A, B, B>;
|
||||
// @count - '//*[@id="variants"]' 0
|
||||
// @count - '//*[@id="fields"]' 1
|
||||
pub use cross_crate_generic_typedef::InlineU64;
|
||||
|
||||
// @has 'inner_variants/type.InlineEnum.html'
|
||||
// @count - '//*[@id="aliased-type"]' 1
|
||||
// @count - '//*[@id="variants"]' 1
|
||||
// @count - '//*[@id="fields"]' 0
|
||||
// @count - '//*[@class="variant"]' 2
|
||||
pub type InlineEnum = cross_crate_generic_typedef::GenericEnum<i32>;
|
||||
|
Loading…
Reference in New Issue
Block a user