Skip to content

Commit 1a0f7ac

Browse files
committed
inspect::CandidateKind -> ProbeKind
add `TraitCandidate` variant using `CandidateSource`
1 parent 121195a commit 1a0f7ac

File tree

11 files changed

+150
-123
lines changed

11 files changed

+150
-123
lines changed

compiler/rustc_middle/src/traits/solve.rs

+64-2
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
use std::ops::ControlFlow;
22

3-
use rustc_data_structures::intern::Interned;
4-
53
use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints};
64
use crate::traits::query::NoSolution;
75
use crate::traits::{Canonical, DefiningAnchor};
86
use crate::ty::{
97
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable,
108
TypeVisitor,
119
};
10+
use rustc_data_structures::intern::Interned;
11+
use rustc_span::def_id::DefId;
1212

1313
mod cache;
1414
pub mod inspect;
1515

1616
pub use cache::{CacheData, EvaluationCache};
1717

18+
use super::BuiltinImplSource;
19+
1820
/// A goal is a statement, i.e. `predicate`, we want to prove
1921
/// given some assumptions, i.e. `param_env`.
2022
///
@@ -229,3 +231,63 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
229231
self.opaque_types.visit_with(visitor)
230232
}
231233
}
234+
235+
/// Possible ways the given goal can be proven.
236+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
237+
pub enum CandidateSource {
238+
/// A user written impl.
239+
///
240+
/// ## Examples
241+
///
242+
/// ```rust
243+
/// fn main() {
244+
/// let x: Vec<u32> = Vec::new();
245+
/// // This uses the impl from the standard library to prove `Vec<T>: Clone`.
246+
/// let y = x.clone();
247+
/// }
248+
/// ```
249+
Impl(DefId),
250+
/// A builtin impl generated by the compiler. When adding a new special
251+
/// trait, try to use actual impls whenever possible. Builtin impls should
252+
/// only be used in cases where the impl cannot be manually be written.
253+
///
254+
/// Notable examples are auto traits, `Sized`, and `DiscriminantKind`.
255+
/// For a list of all traits with builtin impls, check out the
256+
/// [`EvalCtxt::assemble_builtin_impl_candidates`] method. Not
257+
BuiltinImpl(BuiltinImplSource),
258+
/// An assumption from the environment.
259+
///
260+
/// More precisely we've used the `n-th` assumption in the `param_env`.
261+
///
262+
/// ## Examples
263+
///
264+
/// ```rust
265+
/// fn is_clone<T: Clone>(x: T) -> (T, T) {
266+
/// // This uses the assumption `T: Clone` from the `where`-bounds
267+
/// // to prove `T: Clone`.
268+
/// (x.clone(), x)
269+
/// }
270+
/// ```
271+
ParamEnv(usize),
272+
/// If the self type is an alias type, e.g. an opaque type or a projection,
273+
/// we know the bounds on that alias to hold even without knowing its concrete
274+
/// underlying type.
275+
///
276+
/// More precisely this candidate is using the `n-th` bound in the `item_bounds` of
277+
/// the self type.
278+
///
279+
/// ## Examples
280+
///
281+
/// ```rust
282+
/// trait Trait {
283+
/// type Assoc: Clone;
284+
/// }
285+
///
286+
/// fn foo<T: Trait>(x: <T as Trait>::Assoc) {
287+
/// // We prove `<T as Trait>::Assoc` by looking at the bounds on `Assoc` in
288+
/// // in the trait definition.
289+
/// let _y = x.clone();
290+
/// }
291+
/// ```
292+
AliasBound,
293+
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{CanonicalInput, Certainty, Goal, NoSolution, QueryResult};
1+
use super::{CandidateSource, CanonicalInput, Certainty, Goal, NoSolution, QueryResult};
22
use crate::infer::canonical::{Canonical, CanonicalVarValues};
33
use crate::ty;
44
use format::ProofTreeFormatter;
@@ -13,27 +13,25 @@ pub struct State<'tcx, T> {
1313
}
1414
pub type CanonicalState<'tcx, T> = Canonical<'tcx, State<'tcx, T>>;
1515

16-
#[derive(Eq, PartialEq, Debug, Hash, HashStable)]
16+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1717
pub enum CacheHit {
1818
Provisional,
1919
Global,
2020
}
2121

22-
#[derive(Debug, PartialEq, Eq, Hash, HashStable)]
22+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2323
pub enum IsNormalizesToHack {
2424
Yes,
2525
No,
2626
}
2727

28-
#[derive(Eq, PartialEq, Hash, HashStable)]
2928
pub struct RootGoalEvaluation<'tcx> {
3029
pub goal: Goal<'tcx, ty::Predicate<'tcx>>,
3130
pub orig_values: Vec<ty::GenericArg<'tcx>>,
3231
pub evaluation: CanonicalGoalEvaluation<'tcx>,
3332
pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
3433
}
3534

36-
#[derive(Eq, PartialEq, Hash, HashStable)]
3735
pub struct NestedGoalEvaluation<'tcx> {
3836
pub goal: CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>,
3937
pub orig_values: CanonicalState<'tcx, Vec<ty::GenericArg<'tcx>>>,
@@ -42,14 +40,12 @@ pub struct NestedGoalEvaluation<'tcx> {
4240
pub returned_goals: Vec<CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>,
4341
}
4442

45-
#[derive(Eq, PartialEq, Hash, HashStable)]
4643
pub struct CanonicalGoalEvaluation<'tcx> {
4744
pub goal: CanonicalInput<'tcx>,
4845
pub data: GoalEvaluationData<'tcx>,
4946
pub result: QueryResult<'tcx>,
5047
}
5148

52-
#[derive(Eq, PartialEq, Hash, HashStable)]
5349
pub enum GoalEvaluationData<'tcx> {
5450
CacheHit(CacheHit),
5551
Uncached { revisions: Vec<GoalEvaluationStep<'tcx>> },
@@ -60,38 +56,39 @@ impl Debug for RootGoalEvaluation<'_> {
6056
}
6157
}
6258

63-
#[derive(Eq, PartialEq, Hash, HashStable)]
6459
pub struct AddedGoalsEvaluation<'tcx> {
6560
pub evaluations: Vec<Vec<NestedGoalEvaluation<'tcx>>>,
6661
pub result: Result<Certainty, NoSolution>,
6762
}
6863

69-
#[derive(Eq, PartialEq, Hash, HashStable)]
7064
pub struct GoalEvaluationStep<'tcx> {
7165
pub added_goals_evaluations: Vec<AddedGoalsEvaluation<'tcx>>,
7266
pub candidates: Vec<GoalCandidate<'tcx>>,
7367

7468
pub result: QueryResult<'tcx>,
7569
}
7670

77-
#[derive(Eq, PartialEq, Hash, HashStable)]
7871
pub struct GoalCandidate<'tcx> {
7972
pub added_goals_evaluations: Vec<AddedGoalsEvaluation<'tcx>>,
8073
pub candidates: Vec<GoalCandidate<'tcx>>,
81-
pub kind: CandidateKind<'tcx>,
74+
pub kind: ProbeKind<'tcx>,
8275
}
8376

84-
#[derive(Eq, PartialEq, Debug, Hash, HashStable)]
85-
pub enum CandidateKind<'tcx> {
77+
#[derive(Debug, PartialEq, Eq)]
78+
pub enum ProbeKind<'tcx> {
8679
/// Probe entered when normalizing the self ty during candidate assembly
8780
NormalizedSelfTyAssembly,
88-
/// A normal candidate for proving a goal
89-
Candidate { name: String, result: QueryResult<'tcx> },
81+
/// Some candidate to prove the current goal.
82+
///
83+
/// FIXME: Remove this in favor of always using more strongly typed variants.
84+
MiscCandidate { name: String, result: QueryResult<'tcx> },
85+
/// A candidate for proving a trait or alias-relate goal.
86+
TraitCandidate { source: CandidateSource, result: QueryResult<'tcx> },
9087
/// Used in the probe that wraps normalizing the non-self type for the unsize
9188
/// trait, which is also structurally matched on.
9289
UnsizeAssembly,
9390
/// During upcasting from some source object to target object type, used to
9491
/// do a probe to find out what projection type(s) may be used to prove that
9592
/// the source type upholds all of the target type's object bounds.
96-
UpcastProbe,
93+
UpcastProjectionCompatibility,
9794
}

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

+7-4
Original file line numberDiff line numberDiff line change
@@ -124,18 +124,21 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
124124

125125
pub(super) fn format_candidate(&mut self, candidate: &GoalCandidate<'_>) -> std::fmt::Result {
126126
match &candidate.kind {
127-
CandidateKind::NormalizedSelfTyAssembly => {
127+
ProbeKind::NormalizedSelfTyAssembly => {
128128
writeln!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:")
129129
}
130-
CandidateKind::UnsizeAssembly => {
130+
ProbeKind::UnsizeAssembly => {
131131
writeln!(self.f, "ASSEMBLING CANDIDATES FOR UNSIZING:")
132132
}
133-
CandidateKind::UpcastProbe => {
133+
ProbeKind::UpcastProjectionCompatibility => {
134134
writeln!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:")
135135
}
136-
CandidateKind::Candidate { name, result } => {
136+
ProbeKind::MiscCandidate { name, result } => {
137137
writeln!(self.f, "CANDIDATE {name}: {result:?}")
138138
}
139+
ProbeKind::TraitCandidate { source, result } => {
140+
writeln!(self.f, "CANDIDATE {source:?}: {result:?}")
141+
}
139142
}?;
140143

141144
self.nested(|this| {

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(),

compiler/rustc_trait_selection/src/solve/assembly/mod.rs

+6-64
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ use crate::traits::coherence;
55
use rustc_hir::def_id::DefId;
66
use rustc_infer::traits::query::NoSolution;
77
use rustc_infer::traits::Reveal;
8-
use rustc_middle::traits::solve::inspect::CandidateKind;
9-
use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult};
8+
use rustc_middle::traits::solve::inspect::ProbeKind;
9+
use rustc_middle::traits::solve::{
10+
CandidateSource, CanonicalResponse, Certainty, Goal, QueryResult,
11+
};
1012
use rustc_middle::traits::BuiltinImplSource;
1113
use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams};
1214
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -27,66 +29,6 @@ pub(super) struct Candidate<'tcx> {
2729
pub(super) result: CanonicalResponse<'tcx>,
2830
}
2931

30-
/// Possible ways the given goal can be proven.
31-
#[derive(Debug, Clone, Copy)]
32-
pub(super) enum CandidateSource {
33-
/// A user written impl.
34-
///
35-
/// ## Examples
36-
///
37-
/// ```rust
38-
/// fn main() {
39-
/// let x: Vec<u32> = Vec::new();
40-
/// // This uses the impl from the standard library to prove `Vec<T>: Clone`.
41-
/// let y = x.clone();
42-
/// }
43-
/// ```
44-
Impl(DefId),
45-
/// A builtin impl generated by the compiler. When adding a new special
46-
/// trait, try to use actual impls whenever possible. Builtin impls should
47-
/// only be used in cases where the impl cannot be manually be written.
48-
///
49-
/// Notable examples are auto traits, `Sized`, and `DiscriminantKind`.
50-
/// For a list of all traits with builtin impls, check out the
51-
/// [`EvalCtxt::assemble_builtin_impl_candidates`] method. Not
52-
BuiltinImpl(BuiltinImplSource),
53-
/// An assumption from the environment.
54-
///
55-
/// More precisely we've used the `n-th` assumption in the `param_env`.
56-
///
57-
/// ## Examples
58-
///
59-
/// ```rust
60-
/// fn is_clone<T: Clone>(x: T) -> (T, T) {
61-
/// // This uses the assumption `T: Clone` from the `where`-bounds
62-
/// // to prove `T: Clone`.
63-
/// (x.clone(), x)
64-
/// }
65-
/// ```
66-
ParamEnv(usize),
67-
/// If the self type is an alias type, e.g. an opaque type or a projection,
68-
/// we know the bounds on that alias to hold even without knowing its concrete
69-
/// underlying type.
70-
///
71-
/// More precisely this candidate is using the `n-th` bound in the `item_bounds` of
72-
/// the self type.
73-
///
74-
/// ## Examples
75-
///
76-
/// ```rust
77-
/// trait Trait {
78-
/// type Assoc: Clone;
79-
/// }
80-
///
81-
/// fn foo<T: Trait>(x: <T as Trait>::Assoc) {
82-
/// // We prove `<T as Trait>::Assoc` by looking at the bounds on `Assoc` in
83-
/// // in the trait definition.
84-
/// let _y = x.clone();
85-
/// }
86-
/// ```
87-
AliasBound,
88-
}
89-
9032
/// Methods used to assemble candidates for either trait or projection goals.
9133
pub(super) trait GoalKind<'tcx>:
9234
TypeFoldable<TyCtxt<'tcx>> + Copy + Eq + std::fmt::Display
@@ -393,7 +335,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
393335
let tcx = self.tcx();
394336
let &ty::Alias(_, projection_ty) = goal.predicate.self_ty().kind() else { return };
395337

396-
candidates.extend(self.probe(|_| CandidateKind::NormalizedSelfTyAssembly).enter(|ecx| {
338+
candidates.extend(self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| {
397339
if num_steps < ecx.local_overflow_limit() {
398340
let normalized_ty = ecx.next_ty_infer();
399341
let normalizes_to_goal = goal.with(
@@ -882,7 +824,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
882824
SolverMode::Coherence => {}
883825
};
884826

885-
let result = self.probe_candidate("coherence unknowable").enter(|ecx| {
827+
let result = self.probe_misc_candidate("coherence unknowable").enter(|ecx| {
886828
let trait_ref = goal.predicate.trait_ref(tcx);
887829

888830
#[derive(Debug)]

compiler/rustc_trait_selection/src/solve/eval_ctxt.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -921,7 +921,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
921921
if candidate_key.def_id != key.def_id {
922922
continue;
923923
}
924-
values.extend(self.probe_candidate("opaque type storage").enter(|ecx| {
924+
values.extend(self.probe_misc_candidate("opaque type storage").enter(|ecx| {
925925
for (a, b) in std::iter::zip(candidate_key.args, key.args) {
926926
ecx.eq(param_env, a, b)?;
927927
}

0 commit comments

Comments
 (0)