Skip to content

Commit 2394959

Browse files
committed
Auto merge of rust-lang#115751 - lcnr:inspect-cleanup, r=compiler-errors
some inspect improvements split from rust-lang#114810 because I still want to experiment a bunch with that PR and these changes are self-contained. r? `@compiler-errors`
2 parents c728bf3 + eac55ee commit 2394959

File tree

13 files changed

+349
-285
lines changed

13 files changed

+349
-285
lines changed

compiler/rustc_middle/src/traits/solve.rs

+63
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ use crate::ty::{
99
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable,
1010
TypeVisitor,
1111
};
12+
use rustc_span::def_id::DefId;
13+
14+
use super::BuiltinImplSource;
1215

1316
mod cache;
1417
pub mod inspect;
@@ -235,3 +238,63 @@ pub enum IsNormalizesToHack {
235238
Yes,
236239
No,
237240
}
241+
242+
/// Possible ways the given goal can be proven.
243+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
244+
pub enum CandidateSource {
245+
/// A user written impl.
246+
///
247+
/// ## Examples
248+
///
249+
/// ```rust
250+
/// fn main() {
251+
/// let x: Vec<u32> = Vec::new();
252+
/// // This uses the impl from the standard library to prove `Vec<T>: Clone`.
253+
/// let y = x.clone();
254+
/// }
255+
/// ```
256+
Impl(DefId),
257+
/// A builtin impl generated by the compiler. When adding a new special
258+
/// trait, try to use actual impls whenever possible. Builtin impls should
259+
/// only be used in cases where the impl cannot be manually be written.
260+
///
261+
/// Notable examples are auto traits, `Sized`, and `DiscriminantKind`.
262+
/// For a list of all traits with builtin impls, check out the
263+
/// `EvalCtxt::assemble_builtin_impl_candidates` method.
264+
BuiltinImpl(BuiltinImplSource),
265+
/// An assumption from the environment.
266+
///
267+
/// More precisely we've used the `n-th` assumption in the `param_env`.
268+
///
269+
/// ## Examples
270+
///
271+
/// ```rust
272+
/// fn is_clone<T: Clone>(x: T) -> (T, T) {
273+
/// // This uses the assumption `T: Clone` from the `where`-bounds
274+
/// // to prove `T: Clone`.
275+
/// (x.clone(), x)
276+
/// }
277+
/// ```
278+
ParamEnv(usize),
279+
/// If the self type is an alias type, e.g. an opaque type or a projection,
280+
/// we know the bounds on that alias to hold even without knowing its concrete
281+
/// underlying type.
282+
///
283+
/// More precisely this candidate is using the `n-th` bound in the `item_bounds` of
284+
/// the self type.
285+
///
286+
/// ## Examples
287+
///
288+
/// ```rust
289+
/// trait Trait {
290+
/// type Assoc: Clone;
291+
/// }
292+
///
293+
/// fn foo<T: Trait>(x: <T as Trait>::Assoc) {
294+
/// // We prove `<T as Trait>::Assoc` by looking at the bounds on `Assoc` in
295+
/// // in the trait definition.
296+
/// let _y = x.clone();
297+
/// }
298+
/// ```
299+
AliasBound,
300+
}
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,37 @@
11
use super::{
2-
CanonicalInput, Certainty, Goal, IsNormalizesToHack, NoSolution, QueryInput, QueryResult,
2+
CandidateSource, CanonicalInput, Certainty, Goal, IsNormalizesToHack, NoSolution, QueryInput,
3+
QueryResult,
34
};
45
use crate::ty;
56
use format::ProofTreeFormatter;
67
use std::fmt::{Debug, Write};
78

89
mod format;
910

10-
#[derive(Eq, PartialEq, Debug, Hash, HashStable)]
11+
#[derive(Debug, Eq, PartialEq)]
1112
pub enum CacheHit {
1213
Provisional,
1314
Global,
1415
}
1516

16-
#[derive(Eq, PartialEq, Hash, HashStable)]
17+
#[derive(Eq, PartialEq)]
1718
pub struct GoalEvaluation<'tcx> {
1819
pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>,
19-
pub canonicalized_goal: CanonicalInput<'tcx>,
20-
21-
pub kind: GoalEvaluationKind<'tcx>,
2220
pub is_normalizes_to_hack: IsNormalizesToHack,
21+
pub evaluation: CanonicalGoalEvaluation<'tcx>,
2322
pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
23+
}
2424

25+
#[derive(Eq, PartialEq)]
26+
pub struct CanonicalGoalEvaluation<'tcx> {
27+
pub goal: CanonicalInput<'tcx>,
28+
pub kind: GoalEvaluationKind<'tcx>,
2529
pub result: QueryResult<'tcx>,
2630
}
2731

28-
#[derive(Eq, PartialEq, Hash, HashStable)]
32+
#[derive(Eq, PartialEq)]
2933
pub enum GoalEvaluationKind<'tcx> {
34+
Overflow,
3035
CacheHit(CacheHit),
3136
Uncached { revisions: Vec<GoalEvaluationStep<'tcx>> },
3237
}
@@ -36,55 +41,50 @@ impl Debug for GoalEvaluation<'_> {
3641
}
3742
}
3843

39-
#[derive(Eq, PartialEq, Hash, HashStable)]
44+
#[derive(Eq, PartialEq)]
4045
pub struct AddedGoalsEvaluation<'tcx> {
4146
pub evaluations: Vec<Vec<GoalEvaluation<'tcx>>>,
4247
pub result: Result<Certainty, NoSolution>,
4348
}
44-
impl Debug for AddedGoalsEvaluation<'_> {
45-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46-
ProofTreeFormatter::new(f).format_nested_goal_evaluation(self)
47-
}
48-
}
4949

50-
#[derive(Eq, PartialEq, Hash, HashStable)]
50+
#[derive(Eq, PartialEq)]
5151
pub struct GoalEvaluationStep<'tcx> {
5252
pub instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>,
5353

54-
pub nested_goal_evaluations: Vec<AddedGoalsEvaluation<'tcx>>,
55-
pub candidates: Vec<GoalCandidate<'tcx>>,
56-
57-
pub result: QueryResult<'tcx>,
58-
}
59-
impl Debug for GoalEvaluationStep<'_> {
60-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61-
ProofTreeFormatter::new(f).format_evaluation_step(self)
62-
}
54+
/// The actual evaluation of the goal, always `ProbeKind::Root`.
55+
pub evaluation: GoalCandidate<'tcx>,
6356
}
6457

65-
#[derive(Eq, PartialEq, Hash, HashStable)]
58+
#[derive(Eq, PartialEq)]
6659
pub struct GoalCandidate<'tcx> {
67-
pub nested_goal_evaluations: Vec<AddedGoalsEvaluation<'tcx>>,
60+
pub added_goals_evaluations: Vec<AddedGoalsEvaluation<'tcx>>,
6861
pub candidates: Vec<GoalCandidate<'tcx>>,
69-
pub kind: CandidateKind<'tcx>,
62+
pub kind: ProbeKind<'tcx>,
63+
}
64+
65+
impl Debug for GoalCandidate<'_> {
66+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67+
ProofTreeFormatter::new(f).format_candidate(self)
68+
}
7069
}
7170

72-
#[derive(Eq, PartialEq, Debug, Hash, HashStable)]
73-
pub enum CandidateKind<'tcx> {
71+
#[derive(Debug, PartialEq, Eq)]
72+
pub enum ProbeKind<'tcx> {
73+
/// The root inference context while proving a goal.
74+
Root { result: QueryResult<'tcx> },
7475
/// Probe entered when normalizing the self ty during candidate assembly
7576
NormalizedSelfTyAssembly,
76-
/// A normal candidate for proving a goal
77-
Candidate { name: String, result: QueryResult<'tcx> },
77+
/// Some candidate to prove the current goal.
78+
///
79+
/// FIXME: Remove this in favor of always using more strongly typed variants.
80+
MiscCandidate { name: &'static str, result: QueryResult<'tcx> },
81+
/// A candidate for proving a trait or alias-relate goal.
82+
TraitCandidate { source: CandidateSource, result: QueryResult<'tcx> },
7883
/// Used in the probe that wraps normalizing the non-self type for the unsize
7984
/// trait, which is also structurally matched on.
8085
UnsizeAssembly,
8186
/// During upcasting from some source object to target object type, used to
8287
/// do a probe to find out what projection type(s) may be used to prove that
8388
/// the source type upholds all of the target type's object bounds.
84-
UpcastProbe,
85-
}
86-
impl Debug for GoalCandidate<'_> {
87-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88-
ProofTreeFormatter::new(f).format_candidate(self)
89-
}
89+
UpcastProjectionCompatibility,
9090
}

compiler/rustc_middle/src/traits/solve/inspect/format.rs

+50-44
Original file line numberDiff line numberDiff line change
@@ -39,99 +39,105 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
3939
func(&mut ProofTreeFormatter { f: &mut Indentor { f: self.f, on_newline: true } })
4040
}
4141

42-
pub(super) fn format_goal_evaluation(&mut self, goal: &GoalEvaluation<'_>) -> std::fmt::Result {
43-
let goal_text = match goal.is_normalizes_to_hack {
42+
pub(super) fn format_goal_evaluation(&mut self, eval: &GoalEvaluation<'_>) -> std::fmt::Result {
43+
let goal_text = match eval.is_normalizes_to_hack {
4444
IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL",
4545
IsNormalizesToHack::No => "GOAL",
4646
};
47+
writeln!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?;
48+
self.nested(|this| this.format_canonical_goal_evaluation(&eval.evaluation))?;
49+
if eval.returned_goals.len() > 0 {
50+
writeln!(self.f, "NESTED GOALS ADDED TO CALLER: [")?;
51+
self.nested(|this| {
52+
for goal in eval.returned_goals.iter() {
53+
writeln!(this.f, "ADDED GOAL: {goal:?},")?;
54+
}
55+
Ok(())
56+
})?;
57+
58+
writeln!(self.f, "]")
59+
} else {
60+
Ok(())
61+
}
62+
}
4763

48-
writeln!(self.f, "{}: {:?}", goal_text, goal.uncanonicalized_goal)?;
49-
writeln!(self.f, "CANONICALIZED: {:?}", goal.canonicalized_goal)?;
64+
pub(super) fn format_canonical_goal_evaluation(
65+
&mut self,
66+
eval: &CanonicalGoalEvaluation<'_>,
67+
) -> std::fmt::Result {
68+
writeln!(self.f, "GOAL: {:?}", eval.goal)?;
5069

51-
match &goal.kind {
70+
match &eval.kind {
71+
GoalEvaluationKind::Overflow => {
72+
writeln!(self.f, "OVERFLOW: {:?}", eval.result)
73+
}
5274
GoalEvaluationKind::CacheHit(CacheHit::Global) => {
53-
writeln!(self.f, "GLOBAL CACHE HIT: {:?}", goal.result)
75+
writeln!(self.f, "GLOBAL CACHE HIT: {:?}", eval.result)
5476
}
5577
GoalEvaluationKind::CacheHit(CacheHit::Provisional) => {
56-
writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", goal.result)
78+
writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", eval.result)
5779
}
5880
GoalEvaluationKind::Uncached { revisions } => {
5981
for (n, step) in revisions.iter().enumerate() {
60-
writeln!(self.f, "REVISION {n}: {:?}", step.result)?;
82+
writeln!(self.f, "REVISION {n}")?;
6183
self.nested(|this| this.format_evaluation_step(step))?;
6284
}
63-
writeln!(self.f, "RESULT: {:?}", goal.result)
85+
writeln!(self.f, "RESULT: {:?}", eval.result)
6486
}
65-
}?;
66-
67-
if goal.returned_goals.len() > 0 {
68-
writeln!(self.f, "NESTED GOALS ADDED TO CALLER: [")?;
69-
self.nested(|this| {
70-
for goal in goal.returned_goals.iter() {
71-
writeln!(this.f, "ADDED GOAL: {goal:?},")?;
72-
}
73-
Ok(())
74-
})?;
75-
76-
writeln!(self.f, "]")?;
7787
}
78-
79-
Ok(())
8088
}
8189

8290
pub(super) fn format_evaluation_step(
8391
&mut self,
8492
evaluation_step: &GoalEvaluationStep<'_>,
8593
) -> std::fmt::Result {
8694
writeln!(self.f, "INSTANTIATED: {:?}", evaluation_step.instantiated_goal)?;
87-
88-
for candidate in &evaluation_step.candidates {
89-
self.nested(|this| this.format_candidate(candidate))?;
90-
}
91-
for nested in &evaluation_step.nested_goal_evaluations {
92-
self.nested(|this| this.format_nested_goal_evaluation(nested))?;
93-
}
94-
95-
Ok(())
95+
self.format_candidate(&evaluation_step.evaluation)
9696
}
9797

9898
pub(super) fn format_candidate(&mut self, candidate: &GoalCandidate<'_>) -> std::fmt::Result {
9999
match &candidate.kind {
100-
CandidateKind::NormalizedSelfTyAssembly => {
100+
ProbeKind::Root { result } => {
101+
writeln!(self.f, "ROOT RESULT: {result:?}")
102+
}
103+
ProbeKind::NormalizedSelfTyAssembly => {
101104
writeln!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:")
102105
}
103-
CandidateKind::UnsizeAssembly => {
106+
ProbeKind::UnsizeAssembly => {
104107
writeln!(self.f, "ASSEMBLING CANDIDATES FOR UNSIZING:")
105108
}
106-
CandidateKind::UpcastProbe => {
109+
ProbeKind::UpcastProjectionCompatibility => {
107110
writeln!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:")
108111
}
109-
CandidateKind::Candidate { name, result } => {
112+
ProbeKind::MiscCandidate { name, result } => {
110113
writeln!(self.f, "CANDIDATE {name}: {result:?}")
111114
}
115+
ProbeKind::TraitCandidate { source, result } => {
116+
writeln!(self.f, "CANDIDATE {source:?}: {result:?}")
117+
}
112118
}?;
113119

114120
self.nested(|this| {
115121
for candidate in &candidate.candidates {
116122
this.format_candidate(candidate)?;
117123
}
118-
for nested in &candidate.nested_goal_evaluations {
119-
this.format_nested_goal_evaluation(nested)?;
124+
for nested in &candidate.added_goals_evaluations {
125+
this.format_added_goals_evaluation(nested)?;
120126
}
121127
Ok(())
122128
})
123129
}
124130

125-
pub(super) fn format_nested_goal_evaluation(
131+
pub(super) fn format_added_goals_evaluation(
126132
&mut self,
127-
nested_goal_evaluation: &AddedGoalsEvaluation<'_>,
133+
added_goals_evaluation: &AddedGoalsEvaluation<'_>,
128134
) -> std::fmt::Result {
129-
writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", nested_goal_evaluation.result)?;
135+
writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", added_goals_evaluation.result)?;
130136

131-
for (n, revision) in nested_goal_evaluation.evaluations.iter().enumerate() {
132-
writeln!(self.f, "REVISION {n}")?;
137+
for (n, iterations) in added_goals_evaluation.evaluations.iter().enumerate() {
138+
writeln!(self.f, "ITERATION {n}")?;
133139
self.nested(|this| {
134-
for goal_evaluation in revision {
140+
for goal_evaluation in iterations {
135141
this.format_goal_evaluation(goal_evaluation)?;
136142
}
137143
Ok(())

compiler/rustc_trait_selection/src/solve/alias_relate.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
125125
direction: ty::AliasRelationDirection,
126126
invert: Invert,
127127
) -> QueryResult<'tcx> {
128-
self.probe_candidate("normalizes-to").enter(|ecx| {
128+
self.probe_misc_candidate("normalizes-to").enter(|ecx| {
129129
ecx.normalizes_to_inner(param_env, alias, other, direction, invert)?;
130130
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
131131
})
@@ -175,7 +175,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
175175
alias_rhs: ty::AliasTy<'tcx>,
176176
direction: ty::AliasRelationDirection,
177177
) -> QueryResult<'tcx> {
178-
self.probe_candidate("args relate").enter(|ecx| {
178+
self.probe_misc_candidate("args relate").enter(|ecx| {
179179
match direction {
180180
ty::AliasRelationDirection::Equate => {
181181
ecx.eq(param_env, alias_lhs, alias_rhs)?;
@@ -196,7 +196,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
196196
rhs: ty::Term<'tcx>,
197197
direction: ty::AliasRelationDirection,
198198
) -> QueryResult<'tcx> {
199-
self.probe_candidate("bidir normalizes-to").enter(|ecx| {
199+
self.probe_misc_candidate("bidir normalizes-to").enter(|ecx| {
200200
ecx.normalizes_to_inner(
201201
param_env,
202202
lhs.to_alias_ty(ecx.tcx()).unwrap(),

0 commit comments

Comments
 (0)