diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 69681930be657..d75f250275bce 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -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> for abi::Abi { diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 644fca7c5fee9..be91249a25f8d 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -37,7 +37,11 @@ pub struct Predicate<'tcx>( pub(super) Interned<'tcx, WithCachedTypeInfo>>>, ); -impl<'tcx> rustc_type_ir::inherent::Predicate> for Predicate<'tcx> {} +impl<'tcx> rustc_type_ir::inherent::Predicate> 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 { diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs index 65cc0a4585732..43e61de955af7 100644 --- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs +++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs @@ -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, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index b1dd6ae6611e0..1152441069280 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -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, 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, 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, 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, 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, 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, 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, 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, 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, NoSolution>; /// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn` /// 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, NoSolution>; @@ -172,7 +174,7 @@ pub(super) trait GoalKind<'tcx>: /// An async closure is known to implement the `AsyncFn` 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, 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, 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, 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, NoSolution>; @@ -205,7 +207,7 @@ pub(super) trait GoalKind<'tcx>: /// `Future`, 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, NoSolution>; @@ -213,19 +215,19 @@ pub(super) trait GoalKind<'tcx>: /// `Iterator`, 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, 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, NoSolution>; fn consider_builtin_async_iterator_candidate( - ecx: &mut EvalCtxt<'_, 'tcx>, + ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, goal: Goal<'tcx, Self>, ) -> Result, NoSolution>; @@ -233,27 +235,27 @@ pub(super) trait GoalKind<'tcx>: /// implement `Coroutine`, 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, NoSolution>; fn consider_builtin_discriminant_kind_candidate( - ecx: &mut EvalCtxt<'_, 'tcx>, + ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, goal: Goal<'tcx, Self>, ) -> Result, NoSolution>; fn consider_builtin_async_destruct_candidate( - ecx: &mut EvalCtxt<'_, 'tcx>, + ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, goal: Goal<'tcx, Self>, ) -> Result, NoSolution>; fn consider_builtin_destruct_candidate( - ecx: &mut EvalCtxt<'_, 'tcx>, + ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, goal: Goal<'tcx, Self>, ) -> Result, NoSolution>; fn consider_builtin_transmute_candidate( - ecx: &mut EvalCtxt<'_, 'tcx>, + ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, goal: Goal<'tcx, Self>, ) -> Result, 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>; } -impl<'tcx> EvalCtxt<'_, 'tcx> { +impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { pub(super) fn assemble_and_evaluate_candidates>( &mut self, goal: Goal<'tcx, G>, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index cf826596392ce..930ae5af811b4 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -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>>, 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>>, 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>>, 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>, @@ -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>, nested: Vec>>, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 52deb22098f4b..a642d0c40fc9d 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -52,7 +52,7 @@ impl<'tcx, T> ResponseT<'tcx> for inspect::State, 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>>( diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 70308d4359d22..7e1d7d73e0b3f 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -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, + I: Interner = ::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, - 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, - nested_goals: NestedGoals>, + nested_goals: NestedGoals, // 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>, + pub(super) inspect: ProofTreeBuilder, } #[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( infcx: &InferCtxt<'tcx>, generate_proof_tree: GenerateProofTree, - f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> R, + f: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> R, ) -> (R, Option>>) { 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( tcx: TyCtxt<'tcx>, - search_graph: &'a mut search_graph::SearchGraph<'tcx>, + search_graph: &'a mut search_graph::SearchGraph>, canonical_input: CanonicalInput<'tcx>, canonical_goal_evaluation: &mut ProofTreeBuilder>, - 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>, canonical_input: CanonicalInput<'tcx>, goal_evaluation: &mut ProofTreeBuilder>, ) -> 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 } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs index 9edc489754ca9..1748c9be9275e 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs @@ -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, } @@ -17,7 +18,10 @@ impl<'tcx, F, T> ProbeCtxt<'_, '_, 'tcx, F, T> where F: FnOnce(&T) -> inspect::ProbeKind>, { - 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, 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(&mut self, probe_kind: F) -> ProbeCtxt<'_, 'a, 'tcx, F, T> diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index b085d009d75af..60722d3618f9a 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -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>> { } } -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, diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs index 94e078f56159e..c9621e705e575 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs @@ -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, diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs index 353bdb9caff8f..2146a2c2f0819 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs @@ -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>>, diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 8c492b62c1ade..7ef8373663ba5 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -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, 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, 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, NoSolution> { Err(NoSolution) } fn consider_auto_trait_candidate( - ecx: &mut EvalCtxt<'_, 'tcx>, + ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, goal: Goal<'tcx, Self>, ) -> Result, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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> { 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, 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, 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, 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, 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, diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs index 9fdb280cdc6da..3b83d347276f7 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs @@ -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>>, diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs index 13af5068b6c99..109a9e9671f08 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs @@ -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>>, diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 0f1be1072a8f1..8fa78e49dc6e6 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -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, diff --git a/compiler/rustc_trait_selection/src/solve/search_graph.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs index 0164d44667c3f..5a5df439a7888 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs @@ -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 { + input: CanonicalInput, 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>, + provisional_result: Option>, } /// The provisional result for a goal which is not on the stack. -struct DetachedEntry<'tcx> { +struct DetachedEntry { /// 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, } /// 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 { stack_depth: Option, - with_inductive_stack: Option>, - with_coinductive_stack: Option>, + with_inductive_stack: Option>, + with_coinductive_stack: Option>, } -impl<'tcx> ProvisionalCacheEntry<'tcx> { +impl ProvisionalCacheEntry { 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 { mode: SolverMode, /// The stack of goals currently being computed. /// /// An element is *deeper* in the stack if its index is *lower*. - stack: IndexVec>, - provisional_cache: FxHashMap, ProvisionalCacheEntry<'tcx>>, + stack: IndexVec>, + provisional_cache: FxHashMap, ProvisionalCacheEntry>, /// 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>, + cycle_participants: FxHashSet>, } -impl<'tcx> SearchGraph<'tcx> { - pub(super) fn new(mode: SolverMode) -> SearchGraph<'tcx> { +impl SearchGraph { + pub(super) fn new(mode: SolverMode) -> SearchGraph { 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 { 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>, + tcx: I, + stack: &IndexVec>, ) -> Option { 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>, + tcx: I, + stack: &IndexVec>, 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>, - cycle_participants: &mut FxHashSet>, + stack: &mut IndexVec>, + cycle_participants: &mut FxHashSet>, usage_kind: HasBeenUsed, head: StackDepth, ) { @@ -234,7 +228,7 @@ impl<'tcx> SearchGraph<'tcx> { } fn clear_dependent_provisional_results( - provisional_cache: &mut FxHashMap, ProvisionalCacheEntry<'tcx>>, + provisional_cache: &mut FxHashMap, ProvisionalCacheEntry>, head: StackDepth, ) { #[allow(rustc::potential_query_instability)] @@ -244,6 +238,19 @@ impl<'tcx> SearchGraph<'tcx> { !entry.is_empty() }); } +} + +impl<'tcx> SearchGraph> { + /// 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>, inspect: &mut ProofTreeBuilder>, - mut prove_goal: impl FnMut(&mut Self, &mut ProofTreeBuilder>) -> QueryResult<'tcx>, - ) -> QueryResult<'tcx> { + mut prove_goal: impl FnMut( + &mut Self, + &mut ProofTreeBuilder>, + ) -> QueryResult>, + ) -> QueryResult> { // 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>, certainty: Certainty, - ) -> QueryResult<'tcx> { + ) -> QueryResult> { Ok(super::response_no_constraints_raw(tcx, goal.max_universe, goal.variables, certainty)) } } diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 9139c75d3999a..e59eef22f4111 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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 for T {} /// ``` fn consider_structural_builtin_unsize_candidates( - ecx: &mut EvalCtxt<'_, 'tcx>, + ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, goal: Goal<'tcx, Self>, ) -> Vec> { 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>>, NoSolution>, ) -> Result, NoSolution> { diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 5289dfd932f90..19c76fb165a03 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -96,6 +96,7 @@ pub trait GenericArgs>: pub trait Predicate>: Copy + Debug + Hash + Eq + TypeSuperVisitable + TypeSuperFoldable + Flags { + fn is_coinductive(self, interner: I) -> bool; } /// Common capabilities of placeholder kinds diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 9acf7c04dd61c..0b51d2e75f457 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -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` diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 09739698a65c0..7dcaa59dcd1c7 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2496,6 +2496,14 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Arc { // [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 { 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 Default for Arc { } } +/// Struct to hold the static `ArcInner` used for empty `Arc` as +/// returned by `Default::default`. +/// +/// Layout notes: +/// * `repr(align(16))` so we can use it for `[T]` with `align_of::() <= 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`. +#[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 { @@ -3391,15 +3430,12 @@ impl Default for Arc { #[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> = NonNull::from(&STATIC_INNER_CSTR); - let inner: NonNull> = NonNull::new(inner.as_ptr() as *mut ArcInner).unwrap(); + let inner: NonNull> = NonNull::from(&STATIC_INNER_SLICE.inner); + let inner: NonNull> = + NonNull::new(inner.as_ptr() as *mut ArcInner).unwrap(); // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. - let this: mem::ManuallyDrop> = unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; + let this: mem::ManuallyDrop> = + unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; (*this).clone() } } @@ -3412,31 +3448,20 @@ impl 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::(); - // 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 = ArcInner { - strong: atomic::AtomicUsize::new(1), - weak: atomic::AtomicUsize::new(1), - data: Aligned, - }; - let inner: NonNull> = NonNull::from(&ALIGNED_STATIC_INNER); - let inner: NonNull> = inner.cast(); - // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. - let this: mem::ManuallyDrop> = unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; - return (*this).clone(); - })* - }; + if mem::align_of::() <= 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 = NonNull::from(&STATIC_INNER_SLICE); + let inner: NonNull> = inner.cast(); + // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. + let this: mem::ManuallyDrop> = + 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) } diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs index 848cbd5ed99fc..ac7d422ec800f 100644 --- a/src/librustdoc/passes/strip_aliased_non_local.rs +++ b/src/librustdoc/passes/strip_aliased_non_local.rs @@ -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)); } } diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index 48d40d167bad8..4a6adc2fc5331 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -7,7 +7,7 @@ // gdb-command:run // gdb-command:print plain_string -// gdbr-check:$1 = alloc::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {ptr: core::ptr::unique::Unique {pointer: core::ptr::non_null::NonNull {pointer: 0x55555555ab80}, _marker: core::marker::PhantomData}, cap: alloc::raw_vec::Cap (5), alloc: alloc::alloc::Global}, len: 5}} +// gdbr-check:$1 = alloc::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {ptr: core::ptr::unique::Unique {pointer: core::ptr::non_null::NonNull {pointer: 0x[...]}, _marker: core::marker::PhantomData}, 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> {pointer: 0x55555555aae0}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} +// gdbr-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull> {pointer: 0x[...]}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} // === LLDB TESTS ================================================================================== diff --git a/tests/rustdoc/auxiliary/cross_crate_generic_typedef.rs b/tests/rustdoc/auxiliary/cross_crate_generic_typedef.rs index f4e020b3b9599..d85129a69fc6e 100644 --- a/tests/rustdoc/auxiliary/cross_crate_generic_typedef.rs +++ b/tests/rustdoc/auxiliary/cross_crate_generic_typedef.rs @@ -3,3 +3,8 @@ pub struct InlineOne { } pub type InlineU64 = InlineOne; + +pub enum GenericEnum { + Variant(T), + Variant2(T, T), +} diff --git a/tests/rustdoc/typedef-inner-variants.rs b/tests/rustdoc/typedef-inner-variants.rs index d87a1cb6facbf..0e65fdaf2afdc 100644 --- a/tests/rustdoc/typedef-inner-variants.rs +++ b/tests/rustdoc/typedef-inner-variants.rs @@ -117,3 +117,10 @@ pub type HighlyGenericAABB = HighlyGenericStruct; // @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;