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:
bors 2024-05-20 13:37:35 +00:00
commit 75cb5c51cd
24 changed files with 289 additions and 209 deletions

View File

@ -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 {

View File

@ -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 {

View File

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

View File

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

View File

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

View File

@ -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>>>(

View File

@ -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
}

View File

@ -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>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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))
}
}

View File

@ -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> {

View File

@ -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

View File

@ -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`

View File

@ -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)
}

View File

@ -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));
}
}

View File

@ -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 ==================================================================================

View File

@ -3,3 +3,8 @@ pub struct InlineOne<A> {
}
pub type InlineU64 = InlineOne<u64>;
pub enum GenericEnum<T> {
Variant(T),
Variant2(T, T),
}

View File

@ -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>;