-
Notifications
You must be signed in to change notification settings - Fork 12.8k
/
mod.rs
180 lines (154 loc) · 6.33 KB
/
mod.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
//! Trait Resolution. See the [rustc-dev-guide] for more information on how this works.
//!
//! [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
mod engine;
mod project;
mod structural_impls;
pub mod util;
use std::cmp;
use std::hash::{Hash, Hasher};
use hir::def_id::LocalDefId;
use rustc_hir as hir;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::Certainty;
pub use rustc_middle::traits::*;
use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
use rustc_span::Span;
use thin_vec::ThinVec;
pub use self::ImplSource::*;
pub use self::SelectionError::*;
pub use self::engine::{FromSolverError, ScrubbedTraitError, TraitEngine};
pub(crate) use self::project::UndoLog;
pub use self::project::{
MismatchedProjectionTypes, Normalized, NormalizedTerm, ProjectionCache, ProjectionCacheEntry,
ProjectionCacheKey, ProjectionCacheStorage,
};
use crate::infer::InferCtxt;
/// An `Obligation` represents some trait reference (e.g., `i32: Eq`) for
/// which the "impl_source" must be found. The process of finding an "impl_source" is
/// called "resolving" the `Obligation`. This process consists of
/// either identifying an `impl` (e.g., `impl Eq for i32`) that
/// satisfies the obligation, or else finding a bound that is in
/// scope. The eventual result is usually a `Selection` (defined below).
#[derive(Clone)]
pub struct Obligation<'tcx, T> {
/// The reason we have to prove this thing.
pub cause: ObligationCause<'tcx>,
/// The environment in which we should prove this thing.
pub param_env: ty::ParamEnv<'tcx>,
/// The thing we are trying to prove.
pub predicate: T,
/// If we started proving this as a result of trying to prove
/// something else, track the total depth to ensure termination.
/// If this goes over a certain threshold, we abort compilation --
/// in such cases, we can not say whether or not the predicate
/// holds for certain. Stupid halting problem; such a drag.
pub recursion_depth: usize,
}
impl<'tcx, T: PartialEq> PartialEq<Obligation<'tcx, T>> for Obligation<'tcx, T> {
#[inline]
fn eq(&self, other: &Obligation<'tcx, T>) -> bool {
// Ignore `cause` and `recursion_depth`. This is a small performance
// win for a few crates, and a huge performance win for the crate in
// https://github.com/rust-lang/rustc-perf/pull/1680, which greatly
// stresses the trait system.
self.param_env == other.param_env && self.predicate == other.predicate
}
}
impl<T: Eq> Eq for Obligation<'_, T> {}
impl<T: Hash> Hash for Obligation<'_, T> {
fn hash<H: Hasher>(&self, state: &mut H) -> () {
// See the comment on `Obligation::eq`.
self.param_env.hash(state);
self.predicate.hash(state);
}
}
impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> {
fn from(value: Obligation<'tcx, P>) -> Self {
solve::Goal { param_env: value.param_env, predicate: value.predicate }
}
}
pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>;
pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
pub type PredicateObligations<'tcx> = ThinVec<PredicateObligation<'tcx>>;
impl<'tcx> PredicateObligation<'tcx> {
/// Flips the polarity of the inner predicate.
///
/// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`.
pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option<PredicateObligation<'tcx>> {
Some(PredicateObligation {
cause: self.cause.clone(),
param_env: self.param_env,
predicate: self.predicate.flip_polarity(tcx)?,
recursion_depth: self.recursion_depth,
})
}
}
impl<'tcx> PolyTraitObligation<'tcx> {
pub fn derived_cause(
&self,
variant: impl FnOnce(DerivedCause<'tcx>) -> ObligationCauseCode<'tcx>,
) -> ObligationCause<'tcx> {
self.cause.clone().derived_cause(self.predicate, variant)
}
}
// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(PredicateObligation<'_>, 48);
pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>;
/// A callback that can be provided to `inspect_typeck`. Invoked on evaluation
/// of root obligations.
pub type ObligationInspector<'tcx> =
fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result<Certainty, NoSolution>);
impl<'tcx, O> Obligation<'tcx, O> {
pub fn new(
tcx: TyCtxt<'tcx>,
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
predicate: impl Upcast<TyCtxt<'tcx>, O>,
) -> Obligation<'tcx, O> {
Self::with_depth(tcx, cause, 0, param_env, predicate)
}
/// We often create nested obligations without setting the correct depth.
///
/// To deal with this evaluate and fulfill explicitly update the depth
/// of nested obligations using this function.
pub fn set_depth_from_parent(&mut self, parent_depth: usize) {
self.recursion_depth = cmp::max(parent_depth + 1, self.recursion_depth);
}
pub fn with_depth(
tcx: TyCtxt<'tcx>,
cause: ObligationCause<'tcx>,
recursion_depth: usize,
param_env: ty::ParamEnv<'tcx>,
predicate: impl Upcast<TyCtxt<'tcx>, O>,
) -> Obligation<'tcx, O> {
let predicate = predicate.upcast(tcx);
Obligation { cause, param_env, recursion_depth, predicate }
}
pub fn misc(
tcx: TyCtxt<'tcx>,
span: Span,
body_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
trait_ref: impl Upcast<TyCtxt<'tcx>, O>,
) -> Obligation<'tcx, O> {
Obligation::new(tcx, ObligationCause::misc(span, body_id), param_env, trait_ref)
}
pub fn with<P>(
&self,
tcx: TyCtxt<'tcx>,
value: impl Upcast<TyCtxt<'tcx>, P>,
) -> Obligation<'tcx, P> {
Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value)
}
}
impl<'tcx> PolyTraitObligation<'tcx> {
pub fn polarity(&self) -> ty::PredicatePolarity {
self.predicate.skip_binder().polarity
}
pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> {
self.predicate.map_bound(|p| p.self_ty())
}
}