diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
commit | d1b2d29528b7794b41e66fc2136e395a02f8529b (patch) | |
tree | a4a17504b260206dec3cf55b2dca82929a348ac2 /compiler/rustc_middle/src/traits | |
parent | Releasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip |
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_middle/src/traits')
-rw-r--r-- | compiler/rustc_middle/src/traits/mod.rs | 124 | ||||
-rw-r--r-- | compiler/rustc_middle/src/traits/query.rs | 4 | ||||
-rw-r--r-- | compiler/rustc_middle/src/traits/select.rs | 5 | ||||
-rw-r--r-- | compiler/rustc_middle/src/traits/solve.rs | 9 | ||||
-rw-r--r-- | compiler/rustc_middle/src/traits/solve/cache.rs | 100 | ||||
-rw-r--r-- | compiler/rustc_middle/src/traits/solve/inspect.rs | 15 | ||||
-rw-r--r-- | compiler/rustc_middle/src/traits/solve/inspect/format.rs | 122 | ||||
-rw-r--r-- | compiler/rustc_middle/src/traits/specialization_graph.rs | 6 | ||||
-rw-r--r-- | compiler/rustc_middle/src/traits/structural_impls.rs | 40 |
9 files changed, 251 insertions, 174 deletions
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index c7d2e4c22..3465759b9 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -12,7 +12,7 @@ pub mod util; use crate::infer::canonical::Canonical; use crate::mir::ConstraintCategory; use crate::ty::abstract_const::NotConstEvaluatable; -use crate::ty::subst::SubstsRef; +use crate::ty::GenericArgsRef; use crate::ty::{self, AdtKind, Ty, TyCtxt}; use rustc_data_structures::sync::Lrc; @@ -199,7 +199,7 @@ impl<'tcx> ObligationCause<'tcx> { pub struct UnifyReceiverContext<'tcx> { pub assoc_item: ty::AssocItem, pub param_env: ty::ParamEnv<'tcx>, - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, } #[derive(Clone, PartialEq, Eq, Lift, Default, HashStable)] @@ -402,7 +402,7 @@ pub enum ObligationCauseCode<'tcx> { OpaqueReturnType(Option<(Ty<'tcx>, Span)>), /// Block implicit return - BlockTailExpression(hir::HirId), + BlockTailExpression(hir::HirId, hir::MatchSource), /// #[feature(trivial_bounds)] is not enabled TrivialBound, @@ -543,7 +543,6 @@ pub struct MatchExpressionArmCause<'tcx> { pub scrut_span: Span, pub source: hir::MatchSource, pub prior_arms: Vec<Span>, - pub scrut_hir_id: hir::HirId, pub opt_suggest_box_span: Option<Span>, } @@ -649,43 +648,31 @@ pub enum ImplSource<'tcx, N> { /// for some type parameter. The `Vec<N>` represents the /// obligations incurred from normalizing the where-clause (if /// any). - Param(Vec<N>, ty::BoundConstness), + Param(Vec<N>), - /// Virtual calls through an object. - Object(ImplSourceObjectData<N>), - - /// Successful resolution for a builtin trait. - Builtin(Vec<N>), - - /// ImplSource for trait upcasting coercion - TraitUpcasting(ImplSourceTraitUpcastingData<N>), + /// Successful resolution for a builtin impl. + Builtin(BuiltinImplSource, Vec<N>), } impl<'tcx, N> ImplSource<'tcx, N> { pub fn nested_obligations(self) -> Vec<N> { match self { ImplSource::UserDefined(i) => i.nested, - ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, - ImplSource::Object(d) => d.nested, - ImplSource::TraitUpcasting(d) => d.nested, + ImplSource::Param(n) | ImplSource::Builtin(_, n) => n, } } pub fn borrow_nested_obligations(&self) -> &[N] { match self { ImplSource::UserDefined(i) => &i.nested, - ImplSource::Param(n, _) | ImplSource::Builtin(n) => &n, - ImplSource::Object(d) => &d.nested, - ImplSource::TraitUpcasting(d) => &d.nested, + ImplSource::Param(n) | ImplSource::Builtin(_, n) => &n, } } pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] { match self { ImplSource::UserDefined(i) => &mut i.nested, - ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, - ImplSource::Object(d) => &mut d.nested, - ImplSource::TraitUpcasting(d) => &mut d.nested, + ImplSource::Param(n) | ImplSource::Builtin(_, n) => n, } } @@ -696,20 +683,12 @@ impl<'tcx, N> ImplSource<'tcx, N> { match self { ImplSource::UserDefined(i) => ImplSource::UserDefined(ImplSourceUserDefinedData { impl_def_id: i.impl_def_id, - substs: i.substs, + args: i.args, nested: i.nested.into_iter().map(f).collect(), }), - ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct), - ImplSource::Builtin(n) => ImplSource::Builtin(n.into_iter().map(f).collect()), - ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData { - vtable_base: o.vtable_base, - nested: o.nested.into_iter().map(f).collect(), - }), - ImplSource::TraitUpcasting(d) => { - ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData { - vtable_vptr_slot: d.vtable_vptr_slot, - nested: d.nested.into_iter().map(f).collect(), - }) + ImplSource::Param(n) => ImplSource::Param(n.into_iter().map(f).collect()), + ImplSource::Builtin(source, n) => { + ImplSource::Builtin(source, n.into_iter().map(f).collect()) } } } @@ -729,33 +708,35 @@ impl<'tcx, N> ImplSource<'tcx, N> { #[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceUserDefinedData<'tcx, N> { pub impl_def_id: DefId, - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, pub nested: Vec<N>, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceTraitUpcastingData<N> { +#[derive(Copy, Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Debug)] +pub enum BuiltinImplSource { + /// Some builtin impl we don't need to differentiate. This should be used + /// unless more specific information is necessary. + Misc, + /// A builtin impl for trait objects. + /// + /// The vtable is formed by concatenating together the method lists of + /// the base object trait and all supertraits, pointers to supertrait vtable will + /// be provided when necessary; this is the start of `upcast_trait_ref`'s methods + /// in that vtable. + Object { vtable_base: usize }, /// The vtable is formed by concatenating together the method lists of /// the base object trait and all supertraits, pointers to supertrait vtable will /// be provided when necessary; this is the position of `upcast_trait_ref`'s vtable /// within that vtable. - pub vtable_vptr_slot: Option<usize>, - - pub nested: Vec<N>, + TraitUpcasting { vtable_vptr_slot: Option<usize> }, + /// Unsizing a tuple like `(A, B, ..., X)` to `(A, B, ..., Y)` if `X` unsizes to `Y`. + /// + /// This needs to be a separate variant as it is still unstable and we need to emit + /// a feature error when using it on stable. + TupleUnsizing, } -#[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceObjectData<N> { - /// The vtable is formed by concatenating together the method lists of - /// the base object trait and all supertraits, pointers to supertrait vtable will - /// be provided when necessary; this is the start of `upcast_trait_ref`'s methods - /// in that vtable. - pub vtable_base: usize, - - pub nested: Vec<N>, -} +TrivialTypeTraversalAndLiftImpls! { BuiltinImplSource } #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] pub enum ObjectSafetyViolation { @@ -795,49 +776,48 @@ impl ObjectSafetyViolation { "where clause cannot reference non-lifetime `for<...>` variables".into() } ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => { - format!("associated function `{}` has no `self` parameter", name).into() + format!("associated function `{name}` has no `self` parameter").into() } ObjectSafetyViolation::Method( name, MethodViolationCode::ReferencesSelfInput(_), DUMMY_SP, - ) => format!("method `{}` references the `Self` type in its parameters", name).into(), + ) => format!("method `{name}` references the `Self` type in its parameters").into(), ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfInput(_), _) => { - format!("method `{}` references the `Self` type in this parameter", name).into() + format!("method `{name}` references the `Self` type in this parameter").into() } ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfOutput, _) => { - format!("method `{}` references the `Self` type in its return type", name).into() + format!("method `{name}` references the `Self` type in its return type").into() } ObjectSafetyViolation::Method( name, MethodViolationCode::ReferencesImplTraitInTrait(_), _, - ) => format!("method `{}` references an `impl Trait` type in its return type", name) - .into(), + ) => { + format!("method `{name}` references an `impl Trait` type in its return type").into() + } ObjectSafetyViolation::Method(name, MethodViolationCode::AsyncFn, _) => { - format!("method `{}` is `async`", name).into() + format!("method `{name}` is `async`").into() } ObjectSafetyViolation::Method( name, MethodViolationCode::WhereClauseReferencesSelf, _, - ) => { - format!("method `{}` references the `Self` type in its `where` clause", name).into() - } + ) => format!("method `{name}` references the `Self` type in its `where` clause").into(), ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => { - format!("method `{}` has generic type parameters", name).into() + format!("method `{name}` has generic type parameters").into() } ObjectSafetyViolation::Method( name, MethodViolationCode::UndispatchableReceiver(_), _, - ) => format!("method `{}`'s `self` parameter cannot be dispatched on", name).into(), + ) => format!("method `{name}`'s `self` parameter cannot be dispatched on").into(), ObjectSafetyViolation::AssocConst(name, DUMMY_SP) => { - format!("it contains associated `const` `{}`", name).into() + format!("it contains associated `const` `{name}`").into() } ObjectSafetyViolation::AssocConst(..) => "it contains this associated `const`".into(), ObjectSafetyViolation::GAT(name, _) => { - format!("it contains the generic associated type `{}`", name).into() + format!("it contains the generic associated type `{name}`").into() } } } @@ -855,8 +835,7 @@ impl ObjectSafetyViolation { err.span_suggestion( add_self_sugg.1, format!( - "consider turning `{}` into a method by giving it a `&self` argument", - name + "consider turning `{name}` into a method by giving it a `&self` argument" ), add_self_sugg.0.to_string(), Applicability::MaybeIncorrect, @@ -864,9 +843,8 @@ impl ObjectSafetyViolation { err.span_suggestion( make_sized_sugg.1, format!( - "alternatively, consider constraining `{}` so it does not apply to \ - trait objects", - name + "alternatively, consider constraining `{name}` so it does not apply to \ + trait objects" ), make_sized_sugg.0.to_string(), Applicability::MaybeIncorrect, @@ -879,7 +857,7 @@ impl ObjectSafetyViolation { ) => { err.span_suggestion( *span, - format!("consider changing method `{}`'s `self` parameter to be `&self`", name), + format!("consider changing method `{name}`'s `self` parameter to be `&self`"), "&Self", Applicability::MachineApplicable, ); @@ -887,7 +865,7 @@ impl ObjectSafetyViolation { ObjectSafetyViolation::AssocConst(name, _) | ObjectSafetyViolation::GAT(name, _) | ObjectSafetyViolation::Method(name, ..) => { - err.help(format!("consider moving `{}` to another trait", name)); + err.help(format!("consider moving `{name}` to another trait")); } } } diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 60a38747f..950a59e96 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -8,7 +8,7 @@ use crate::error::DropCheckOverflow; use crate::infer::canonical::{Canonical, QueryResponse}; use crate::ty::error::TypeError; -use crate::ty::subst::GenericArg; +use crate::ty::GenericArg; use crate::ty::{self, Ty, TyCtxt}; use rustc_span::source_map::Span; @@ -132,7 +132,7 @@ impl<'tcx> DropckOutlivesResult<'tcx> { pub struct DropckConstraint<'tcx> { /// Types that are required to be alive in order for this /// type to be valid for destruction. - pub outlives: Vec<ty::subst::GenericArg<'tcx>>, + pub outlives: Vec<ty::GenericArg<'tcx>>, /// Types that could not be resolved: projections and params. pub dtorck_types: Vec<Ty<'tcx>>, diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index f2dda003b..ffae35798 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -127,6 +127,7 @@ pub enum SelectionCandidate<'tcx> { /// an applicable bound in the trait definition. The `usize` is an index /// into the list returned by `tcx.item_bounds`. The constness is the /// constness of the bound in the trait. + // FIXME(effects) do we need this constness ProjectionCandidate(usize, ty::BoundConstness), /// Implementation of a `Fn`-family trait by one of the anonymous types @@ -304,9 +305,7 @@ impl From<ErrorGuaranteed> for OverflowError { } } -TrivialTypeTraversalAndLiftImpls! { - OverflowError, -} +TrivialTypeTraversalAndLiftImpls! { OverflowError } impl<'tcx> From<OverflowError> for SelectionError<'tcx> { fn from(overflow_error: OverflowError) -> SelectionError<'tcx> { diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 73b332fd8..9d63d2918 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -1,7 +1,6 @@ use std::ops::ControlFlow; use rustc_data_structures::intern::Interned; -use rustc_query_system::cache::Cache; use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints}; use crate::traits::query::NoSolution; @@ -11,9 +10,10 @@ use crate::ty::{ TypeVisitor, }; +mod cache; pub mod inspect; -pub type EvaluationCache<'tcx> = Cache<CanonicalInput<'tcx>, QueryResult<'tcx>>; +pub use cache::{CacheData, EvaluationCache}; /// A goal is a statement, i.e. `predicate`, we want to prove /// given some assumptions, i.e. `param_env`. @@ -57,6 +57,7 @@ pub enum Certainty { impl Certainty { pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity); + pub const OVERFLOW: Certainty = Certainty::Maybe(MaybeCause::Overflow); /// Use this function to merge the certainty of multiple nested subgoals. /// @@ -66,7 +67,7 @@ impl Certainty { /// success, we merge these two responses. This results in ambiguity. /// /// If we unify ambiguity with overflow, we return overflow. This doesn't matter - /// inside of the solver as we distinguish ambiguity from overflow. It does + /// inside of the solver as we do not distinguish ambiguity from overflow. It does /// however matter for diagnostics. If `T: Foo` resulted in overflow and `T: Bar` /// in ambiguity without changing the inference state, we still want to tell the /// user that `T: Baz` results in overflow. @@ -146,7 +147,7 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> { } /// Additional constraints returned on success. -#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default)] +#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default, TypeVisitable, TypeFoldable)] pub struct ExternalConstraintsData<'tcx> { // FIXME: implement this. pub region_constraints: QueryRegionConstraints<'tcx>, diff --git a/compiler/rustc_middle/src/traits/solve/cache.rs b/compiler/rustc_middle/src/traits/solve/cache.rs new file mode 100644 index 000000000..9898b0019 --- /dev/null +++ b/compiler/rustc_middle/src/traits/solve/cache.rs @@ -0,0 +1,100 @@ +use super::{CanonicalInput, QueryResult}; +use crate::ty::TyCtxt; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::sync::Lock; +use rustc_query_system::cache::WithDepNode; +use rustc_query_system::dep_graph::DepNodeIndex; +use rustc_session::Limit; +/// The trait solver cache used by `-Ztrait-solver=next`. +/// +/// FIXME(@lcnr): link to some official documentation of how +/// this works. +#[derive(Default)] +pub struct EvaluationCache<'tcx> { + map: Lock<FxHashMap<CanonicalInput<'tcx>, CacheEntry<'tcx>>>, +} + +pub struct CacheData<'tcx> { + pub result: QueryResult<'tcx>, + pub reached_depth: usize, + pub encountered_overflow: bool, +} + +impl<'tcx> EvaluationCache<'tcx> { + /// Insert a final result into the global cache. + pub fn insert( + &self, + key: CanonicalInput<'tcx>, + reached_depth: usize, + did_overflow: bool, + cycle_participants: FxHashSet<CanonicalInput<'tcx>>, + dep_node: DepNodeIndex, + result: QueryResult<'tcx>, + ) { + let mut map = self.map.borrow_mut(); + let entry = map.entry(key).or_default(); + let data = WithDepNode::new(dep_node, result); + entry.cycle_participants.extend(cycle_participants); + if did_overflow { + entry.with_overflow.insert(reached_depth, data); + } else { + entry.success = Some(Success { data, reached_depth }); + } + } + + /// Try to fetch a cached result, checking the recursion limit + /// and handling root goals of coinductive cycles. + /// + /// If this returns `Some` the cache result can be used. + pub fn get( + &self, + tcx: TyCtxt<'tcx>, + key: CanonicalInput<'tcx>, + cycle_participant_in_stack: impl FnOnce(&FxHashSet<CanonicalInput<'tcx>>) -> bool, + available_depth: Limit, + ) -> Option<CacheData<'tcx>> { + let map = self.map.borrow(); + let entry = map.get(&key)?; + + if cycle_participant_in_stack(&entry.cycle_participants) { + return None; + } + + if let Some(ref success) = entry.success { + if available_depth.value_within_limit(success.reached_depth) { + return Some(CacheData { + result: success.data.get(tcx), + reached_depth: success.reached_depth, + encountered_overflow: false, + }); + } + } + + entry.with_overflow.get(&available_depth.0).map(|e| CacheData { + result: e.get(tcx), + reached_depth: available_depth.0, + encountered_overflow: true, + }) + } +} + +struct Success<'tcx> { + data: WithDepNode<QueryResult<'tcx>>, + reached_depth: usize, +} + +/// The cache entry for a goal `CanonicalInput`. +/// +/// This contains results whose computation never hit the +/// recursion limit in `success`, and all results which hit +/// the recursion limit in `with_overflow`. +#[derive(Default)] +struct CacheEntry<'tcx> { + success: Option<Success<'tcx>>, + /// We have to be careful when caching roots of cycles. + /// + /// See the doc comment of `StackEntry::cycle_participants` for more + /// details. + cycle_participants: FxHashSet<CanonicalInput<'tcx>>, + with_overflow: FxHashMap<usize, WithDepNode<QueryResult<'tcx>>>, +} diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs index 527afa005..4e2af3816 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect.rs @@ -32,7 +32,7 @@ pub enum GoalEvaluationKind<'tcx> { } impl Debug for GoalEvaluation<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ProofTreeFormatter { f, on_newline: true }.format_goal_evaluation(self) + ProofTreeFormatter::new(f).format_goal_evaluation(self) } } @@ -43,7 +43,7 @@ pub struct AddedGoalsEvaluation<'tcx> { } impl Debug for AddedGoalsEvaluation<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ProofTreeFormatter { f, on_newline: true }.format_nested_goal_evaluation(self) + ProofTreeFormatter::new(f).format_nested_goal_evaluation(self) } } @@ -58,7 +58,7 @@ pub struct GoalEvaluationStep<'tcx> { } impl Debug for GoalEvaluationStep<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ProofTreeFormatter { f, on_newline: true }.format_evaluation_step(self) + ProofTreeFormatter::new(f).format_evaluation_step(self) } } @@ -75,9 +75,16 @@ pub enum CandidateKind<'tcx> { NormalizedSelfTyAssembly, /// A normal candidate for proving a goal Candidate { name: String, result: QueryResult<'tcx> }, + /// Used in the probe that wraps normalizing the non-self type for the unsize + /// trait, which is also structurally matched on. + UnsizeAssembly, + /// During upcasting from some source object to target object type, used to + /// do a probe to find out what projection type(s) may be used to prove that + /// the source type upholds all of the target type's object bounds. + UpcastProbe, } impl Debug for GoalCandidate<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ProofTreeFormatter { f, on_newline: true }.format_candidate(self) + ProofTreeFormatter::new(f).format_candidate(self) } } diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs index 2ee625674..8759fecb0 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -1,17 +1,25 @@ use super::*; pub(super) struct ProofTreeFormatter<'a, 'b> { - pub(super) f: &'a mut (dyn Write + 'b), - pub(super) on_newline: bool, + f: &'a mut (dyn Write + 'b), } -impl Write for ProofTreeFormatter<'_, '_> { +/// A formatter which adds 4 spaces of indentation to its input before +/// passing it on to its nested formatter. +/// +/// We can use this for arbitrary levels of indentation by nesting it. +struct Indentor<'a, 'b> { + f: &'a mut (dyn Write + 'b), + on_newline: bool, +} + +impl Write for Indentor<'_, '_> { fn write_str(&mut self, s: &str) -> std::fmt::Result { - for line in s.split_inclusive("\n") { + for line in s.split_inclusive('\n') { if self.on_newline { self.f.write_str(" ")?; } - self.on_newline = line.ends_with("\n"); + self.on_newline = line.ends_with('\n'); self.f.write_str(line)?; } @@ -19,49 +27,52 @@ impl Write for ProofTreeFormatter<'_, '_> { } } -impl ProofTreeFormatter<'_, '_> { - fn nested(&mut self) -> ProofTreeFormatter<'_, '_> { - ProofTreeFormatter { f: self, on_newline: true } +impl<'a, 'b> ProofTreeFormatter<'a, 'b> { + pub(super) fn new(f: &'a mut (dyn Write + 'b)) -> Self { + ProofTreeFormatter { f } } - pub(super) fn format_goal_evaluation(&mut self, goal: &GoalEvaluation<'_>) -> std::fmt::Result { - let f = &mut *self.f; + fn nested<F, R>(&mut self, func: F) -> R + where + F: FnOnce(&mut ProofTreeFormatter<'_, '_>) -> R, + { + func(&mut ProofTreeFormatter { f: &mut Indentor { f: self.f, on_newline: true } }) + } + pub(super) fn format_goal_evaluation(&mut self, goal: &GoalEvaluation<'_>) -> std::fmt::Result { let goal_text = match goal.is_normalizes_to_hack { IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL", IsNormalizesToHack::No => "GOAL", }; - writeln!(f, "{}: {:?}", goal_text, goal.uncanonicalized_goal,)?; - writeln!(f, "CANONICALIZED: {:?}", goal.canonicalized_goal)?; + writeln!(self.f, "{}: {:?}", goal_text, goal.uncanonicalized_goal)?; + writeln!(self.f, "CANONICALIZED: {:?}", goal.canonicalized_goal)?; match &goal.kind { GoalEvaluationKind::CacheHit(CacheHit::Global) => { - writeln!(f, "GLOBAL CACHE HIT: {:?}", goal.result) + writeln!(self.f, "GLOBAL CACHE HIT: {:?}", goal.result) } GoalEvaluationKind::CacheHit(CacheHit::Provisional) => { - writeln!(f, "PROVISIONAL CACHE HIT: {:?}", goal.result) + writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", goal.result) } GoalEvaluationKind::Uncached { revisions } => { for (n, step) in revisions.iter().enumerate() { - let f = &mut *self.f; - writeln!(f, "REVISION {n}: {:?}", step.result)?; - let mut f = self.nested(); - f.format_evaluation_step(step)?; + writeln!(self.f, "REVISION {n}: {:?}", step.result)?; + self.nested(|this| this.format_evaluation_step(step))?; } - - let f = &mut *self.f; - writeln!(f, "RESULT: {:?}", goal.result) + writeln!(self.f, "RESULT: {:?}", goal.result) } }?; if goal.returned_goals.len() > 0 { - let f = &mut *self.f; - writeln!(f, "NESTED GOALS ADDED TO CALLER: [")?; - let mut f = self.nested(); - for goal in goal.returned_goals.iter() { - writeln!(f, "ADDED GOAL: {:?},", goal)?; - } + writeln!(self.f, "NESTED GOALS ADDED TO CALLER: [")?; + self.nested(|this| { + for goal in goal.returned_goals.iter() { + writeln!(this.f, "ADDED GOAL: {goal:?},")?; + } + Ok(()) + })?; + writeln!(self.f, "]")?; } @@ -72,58 +83,59 @@ impl ProofTreeFormatter<'_, '_> { &mut self, evaluation_step: &GoalEvaluationStep<'_>, ) -> std::fmt::Result { - let f = &mut *self.f; - writeln!(f, "INSTANTIATED: {:?}", evaluation_step.instantiated_goal)?; + writeln!(self.f, "INSTANTIATED: {:?}", evaluation_step.instantiated_goal)?; for candidate in &evaluation_step.candidates { - let mut f = self.nested(); - f.format_candidate(candidate)?; + self.nested(|this| this.format_candidate(candidate))?; } - for nested_goal_evaluation in &evaluation_step.nested_goal_evaluations { - let mut f = self.nested(); - f.format_nested_goal_evaluation(nested_goal_evaluation)?; + for nested in &evaluation_step.nested_goal_evaluations { + self.nested(|this| this.format_nested_goal_evaluation(nested))?; } Ok(()) } pub(super) fn format_candidate(&mut self, candidate: &GoalCandidate<'_>) -> std::fmt::Result { - let f = &mut *self.f; - match &candidate.kind { CandidateKind::NormalizedSelfTyAssembly => { - writeln!(f, "NORMALIZING SELF TY FOR ASSEMBLY:") + writeln!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:") + } + CandidateKind::UnsizeAssembly => { + writeln!(self.f, "ASSEMBLING CANDIDATES FOR UNSIZING:") + } + CandidateKind::UpcastProbe => { + writeln!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:") } CandidateKind::Candidate { name, result } => { - writeln!(f, "CANDIDATE {}: {:?}", name, result) + writeln!(self.f, "CANDIDATE {name}: {result:?}") } }?; - let mut f = self.nested(); - for candidate in &candidate.candidates { - f.format_candidate(candidate)?; - } - for nested_evaluations in &candidate.nested_goal_evaluations { - f.format_nested_goal_evaluation(nested_evaluations)?; - } - - Ok(()) + self.nested(|this| { + for candidate in &candidate.candidates { + this.format_candidate(candidate)?; + } + for nested in &candidate.nested_goal_evaluations { + this.format_nested_goal_evaluation(nested)?; + } + Ok(()) + }) } pub(super) fn format_nested_goal_evaluation( &mut self, nested_goal_evaluation: &AddedGoalsEvaluation<'_>, ) -> std::fmt::Result { - let f = &mut *self.f; - writeln!(f, "TRY_EVALUATE_ADDED_GOALS: {:?}", nested_goal_evaluation.result)?; + writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", nested_goal_evaluation.result)?; for (n, revision) in nested_goal_evaluation.evaluations.iter().enumerate() { - let f = &mut *self.f; - writeln!(f, "REVISION {n}")?; - let mut f = self.nested(); - for goal_evaluation in revision { - f.format_goal_evaluation(goal_evaluation)?; - } + writeln!(self.f, "REVISION {n}")?; + self.nested(|this| { + for goal_evaluation in revision { + this.format_goal_evaluation(goal_evaluation)?; + } + Ok(()) + })?; } Ok(()) diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index dc2cd2035..e48b46d12 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -43,7 +43,7 @@ impl Graph { /// The parent of a given impl, which is the `DefId` of the trait when the /// impl is a "specialization root". pub fn parent(&self, child: DefId) -> DefId { - *self.parent.get(&child).unwrap_or_else(|| panic!("Failed to get parent for {:?}", child)) + *self.parent.get(&child).unwrap_or_else(|| panic!("Failed to get parent for {child:?}")) } } @@ -259,7 +259,9 @@ pub fn ancestors( if let Some(reported) = specialization_graph.has_errored { Err(reported) - } else if let Err(reported) = tcx.type_of(start_from_impl).subst_identity().error_reported() { + } else if let Err(reported) = + tcx.type_of(start_from_impl).instantiate_identity().error_reported() + { Err(reported) } else { Ok(Ancestors { diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index a703e3c95..ec450cf55 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -6,18 +6,16 @@ use std::fmt; impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - super::ImplSource::UserDefined(ref v) => write!(f, "{:?}", v), + match self { + super::ImplSource::UserDefined(v) => write!(f, "{v:?}"), - super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d), - - super::ImplSource::Object(ref d) => write!(f, "{:?}", d), - - super::ImplSource::Param(ref n, ct) => { - write!(f, "ImplSourceParamData({:?}, {:?})", n, ct) + super::ImplSource::Builtin(source, d) => { + write!(f, "Builtin({source:?}, {d:?})") } - super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d), + super::ImplSource::Param(n) => { + write!(f, "ImplSourceParamData({n:?})") + } } } } @@ -26,28 +24,8 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceUserDefinedData<'tcx, fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "ImplSourceUserDefinedData(impl_def_id={:?}, substs={:?}, nested={:?})", - self.impl_def_id, self.substs, self.nested - ) - } -} - -impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitUpcastingData<N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceTraitUpcastingData(vtable_vptr_slot={:?}, nested={:?})", - self.vtable_vptr_slot, self.nested - ) - } -} - -impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceObjectData<N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceObjectData(vtable_base={}, nested={:?})", - self.vtable_base, self.nested + "ImplSourceUserDefinedData(impl_def_id={:?}, args={:?}, nested={:?})", + self.impl_def_id, self.args, self.nested ) } } |