summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/traits
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
commitd1b2d29528b7794b41e66fc2136e395a02f8529b (patch)
treea4a17504b260206dec3cf55b2dca82929a348ac2 /compiler/rustc_middle/src/traits
parentReleasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-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.rs124
-rw-r--r--compiler/rustc_middle/src/traits/query.rs4
-rw-r--r--compiler/rustc_middle/src/traits/select.rs5
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs9
-rw-r--r--compiler/rustc_middle/src/traits/solve/cache.rs100
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect.rs15
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect/format.rs122
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs6
-rw-r--r--compiler/rustc_middle/src/traits/structural_impls.rs40
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
)
}
}