Skip to content

Commit d7ef208

Browse files
committed
feat: move fulfillment into rustc_next_trait_solver
Signed-off-by: Amirhossein Akhlaghpour <m9.akhlaghpoor@gmail.com>
1 parent 0913b18 commit d7ef208

17 files changed

Lines changed: 610 additions & 490 deletions

File tree

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,10 +1172,9 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> {
11721172
let ocx = ObligationCtxt::new(&self.infcx);
11731173
ocx.register_obligations(clauses.iter().map(|(clause, span)| {
11741174
trace!(?clause);
1175-
Obligation::misc(
1175+
Obligation::new(
11761176
tcx,
1177-
span,
1178-
self.mir_def_id(),
1177+
rustc_middle::traits::ObligationCause::misc(span, self.mir_def_id()),
11791178
self.infcx.param_env,
11801179
clause.skip_norm_wip(),
11811180
)

compiler/rustc_infer/src/traits/mod.rs

Lines changed: 4 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,10 @@ mod project;
77
mod structural_impls;
88
pub mod util;
99

10-
use std::cmp;
11-
use std::hash::{Hash, Hasher};
12-
13-
use hir::def_id::LocalDefId;
14-
use rustc_hir as hir;
15-
use rustc_macros::{TypeFoldable, TypeVisitable};
1610
use rustc_middle::traits::query::NoSolution;
1711
use rustc_middle::traits::solve::Certainty;
1812
pub use rustc_middle::traits::*;
19-
use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
20-
use rustc_span::Span;
13+
use rustc_middle::ty::{self, TyCtxt};
2114
use thin_vec::ThinVec;
2215

2316
pub use self::engine::{FromSolverError, ScrubbedTraitError, TraitEngine, TraitErrors};
@@ -28,93 +21,16 @@ pub use self::project::{
2821
};
2922
use crate::infer::InferCtxt;
3023

31-
/// An `Obligation` represents some trait reference (e.g., `i32: Eq`) for
32-
/// which the "impl_source" must be found. The process of finding an "impl_source" is
33-
/// called "resolving" the `Obligation`. This process consists of
34-
/// either identifying an `impl` (e.g., `impl Eq for i32`) that
35-
/// satisfies the obligation, or else finding a bound that is in
36-
/// scope. The eventual result is usually a `Selection` (defined below).
37-
#[derive(Clone, TypeFoldable, TypeVisitable)]
38-
pub struct Obligation<'tcx, T> {
39-
/// The reason we have to prove this thing.
40-
/// FIXME: we shouldn't ignore the cause but instead change the affected visitors
41-
/// to only visit predicates manually.
42-
#[type_foldable(identity)]
43-
#[type_visitable(ignore)]
44-
pub cause: ObligationCause<'tcx>,
45-
46-
/// The environment in which we should prove this thing.
47-
pub param_env: ty::ParamEnv<'tcx>,
48-
49-
/// The thing we are trying to prove.
50-
pub predicate: T,
51-
52-
/// If we started proving this as a result of trying to prove
53-
/// something else, track the total depth to ensure termination.
54-
/// If this goes over a certain threshold, we abort compilation --
55-
/// in such cases, we can not say whether or not the predicate
56-
/// holds for certain. Stupid halting problem; such a drag.
57-
#[type_foldable(identity)]
58-
#[type_visitable(ignore)]
59-
pub recursion_depth: usize,
60-
}
61-
62-
impl<'tcx, T: Copy> Obligation<'tcx, T> {
63-
pub fn as_goal(&self) -> solve::Goal<'tcx, T> {
64-
solve::Goal { param_env: self.param_env, predicate: self.predicate }
65-
}
66-
}
67-
68-
impl<'tcx, T: PartialEq> PartialEq<Obligation<'tcx, T>> for Obligation<'tcx, T> {
69-
#[inline]
70-
fn eq(&self, other: &Obligation<'tcx, T>) -> bool {
71-
// Ignore `cause` and `recursion_depth`. This is a small performance
72-
// win for a few crates, and a huge performance win for the crate in
73-
// https://github.com/rust-lang/rustc-perf/pull/1680, which greatly
74-
// stresses the trait system.
75-
self.param_env == other.param_env && self.predicate == other.predicate
76-
}
77-
}
78-
79-
impl<T: Eq> Eq for Obligation<'_, T> {}
80-
81-
impl<T: Hash> Hash for Obligation<'_, T> {
82-
fn hash<H: Hasher>(&self, state: &mut H) -> () {
83-
// See the comment on `Obligation::eq`.
84-
self.param_env.hash(state);
85-
self.predicate.hash(state);
86-
}
87-
}
24+
/// An obligation represents a predicate which must be proven in a
25+
/// particular parameter environment.
26+
pub type Obligation<'tcx, T> = rustc_type_ir::solve::Obligation<TyCtxt<'tcx>, T>;
8827

8928
pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
9029
pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>;
9130
pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
9231

9332
pub type PredicateObligations<'tcx> = ThinVec<PredicateObligation<'tcx>>;
9433

95-
impl<'tcx> PredicateObligation<'tcx> {
96-
/// Flips the polarity of the inner predicate.
97-
///
98-
/// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`.
99-
pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option<PredicateObligation<'tcx>> {
100-
Some(PredicateObligation {
101-
cause: self.cause.clone(),
102-
param_env: self.param_env,
103-
predicate: self.predicate.flip_polarity(tcx)?,
104-
recursion_depth: self.recursion_depth,
105-
})
106-
}
107-
}
108-
109-
impl<'tcx> PolyTraitObligation<'tcx> {
110-
pub fn derived_cause(
111-
&self,
112-
variant: impl FnOnce(DerivedCause<'tcx>) -> ObligationCauseCode<'tcx>,
113-
) -> ObligationCause<'tcx> {
114-
self.cause.clone().derived_cause(self.predicate, variant)
115-
}
116-
}
117-
11834
// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
11935
#[cfg(target_pointer_width = "64")]
12036
rustc_data_structures::static_assert_size!(PredicateObligation<'_>, 48);
@@ -125,61 +41,3 @@ pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>;
12541
/// of root obligations.
12642
pub type ObligationInspector<'tcx> =
12743
fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result<Certainty, NoSolution>);
128-
129-
impl<'tcx, O> Obligation<'tcx, O> {
130-
pub fn new(
131-
tcx: TyCtxt<'tcx>,
132-
cause: ObligationCause<'tcx>,
133-
param_env: ty::ParamEnv<'tcx>,
134-
predicate: impl Upcast<TyCtxt<'tcx>, O>,
135-
) -> Obligation<'tcx, O> {
136-
Self::with_depth(tcx, cause, 0, param_env, predicate)
137-
}
138-
139-
/// We often create nested obligations without setting the correct depth.
140-
///
141-
/// To deal with this evaluate and fulfill explicitly update the depth
142-
/// of nested obligations using this function.
143-
pub fn set_depth_from_parent(&mut self, parent_depth: usize) {
144-
self.recursion_depth = cmp::max(parent_depth + 1, self.recursion_depth);
145-
}
146-
147-
pub fn with_depth(
148-
tcx: TyCtxt<'tcx>,
149-
cause: ObligationCause<'tcx>,
150-
recursion_depth: usize,
151-
param_env: ty::ParamEnv<'tcx>,
152-
predicate: impl Upcast<TyCtxt<'tcx>, O>,
153-
) -> Obligation<'tcx, O> {
154-
let predicate = predicate.upcast(tcx);
155-
Obligation { cause, param_env, recursion_depth, predicate }
156-
}
157-
158-
pub fn misc(
159-
tcx: TyCtxt<'tcx>,
160-
span: Span,
161-
body_def_id: LocalDefId,
162-
param_env: ty::ParamEnv<'tcx>,
163-
trait_ref: impl Upcast<TyCtxt<'tcx>, O>,
164-
) -> Obligation<'tcx, O> {
165-
Obligation::new(tcx, ObligationCause::misc(span, body_def_id), param_env, trait_ref)
166-
}
167-
168-
pub fn with<P>(
169-
&self,
170-
tcx: TyCtxt<'tcx>,
171-
value: impl Upcast<TyCtxt<'tcx>, P>,
172-
) -> Obligation<'tcx, P> {
173-
Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value)
174-
}
175-
}
176-
177-
impl<'tcx> PolyTraitObligation<'tcx> {
178-
pub fn polarity(&self) -> ty::PredicatePolarity {
179-
self.predicate.skip_binder().polarity
180-
}
181-
182-
pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> {
183-
self.predicate.map_bound(|p| p.self_ty())
184-
}
185-
}

compiler/rustc_infer/src/traits/structural_impls.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use std::fmt;
22

3-
use rustc_middle::ty;
4-
53
use crate::traits;
64
use crate::traits::project::Normalized;
75

@@ -13,20 +11,6 @@ impl<'tcx, T: fmt::Debug> fmt::Debug for Normalized<'tcx, T> {
1311
}
1412
}
1513

16-
impl<'tcx, O: fmt::Debug> fmt::Debug for traits::Obligation<'tcx, O> {
17-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18-
if ty::tls::with(|tcx| tcx.sess.verbose_internals()) {
19-
write!(
20-
f,
21-
"Obligation(predicate={:?}, cause={:?}, param_env={:?}, depth={})",
22-
self.predicate, self.cause, self.param_env, self.recursion_depth
23-
)
24-
} else {
25-
write!(f, "Obligation(predicate={:?}, depth={})", self.predicate, self.recursion_depth)
26-
}
27-
}
28-
}
29-
3014
impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> {
3115
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3216
write!(f, "MismatchedProjectionTypes({:?})", self.err)

compiler/rustc_infer/src/traits/util.rs

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
use rustc_data_structures::fx::FxHashSet;
22
pub use rustc_middle::ty::elaborate::*;
33
use rustc_middle::ty::{self, TyCtxt, Unnormalized};
4-
use rustc_span::{Ident, Span};
5-
6-
use crate::traits::{self, Obligation, ObligationCauseCode, PredicateObligation};
4+
use rustc_span::Ident;
75

86
pub fn anonymize_predicate<'tcx>(
97
tcx: TyCtxt<'tcx>,
@@ -61,46 +59,6 @@ impl<'tcx> Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
6159
}
6260
}
6361

64-
/// For [`Obligation`], a sub-obligation is combined with the current obligation's
65-
/// param-env and cause code.
66-
impl<'tcx> Elaboratable<TyCtxt<'tcx>> for PredicateObligation<'tcx> {
67-
fn predicate(&self) -> ty::Predicate<'tcx> {
68-
self.predicate
69-
}
70-
71-
fn child(&self, clause: ty::Clause<'tcx>) -> Self {
72-
Obligation {
73-
cause: self.cause.clone(),
74-
param_env: self.param_env,
75-
recursion_depth: 0,
76-
predicate: clause.as_predicate(),
77-
}
78-
}
79-
80-
fn child_with_derived_cause(
81-
&self,
82-
clause: ty::Clause<'tcx>,
83-
span: Span,
84-
parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
85-
index: usize,
86-
) -> Self {
87-
let cause = self.cause.clone().derived_cause(parent_trait_pred, |derived| {
88-
ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause {
89-
derived,
90-
impl_or_alias_def_id: parent_trait_pred.def_id(),
91-
impl_def_clause_index: Some(index),
92-
span,
93-
}))
94-
});
95-
Obligation {
96-
cause,
97-
param_env: self.param_env,
98-
recursion_depth: 0,
99-
predicate: clause.as_predicate(),
100-
}
101-
}
102-
}
103-
10462
/// A specialized variant of `elaborate` that only elaborates trait references that may
10563
/// define the given associated item with the name `assoc_name`. It uses the
10664
/// `explicit_supertraits_containing_assoc_item` query to avoid enumerating super-predicates that

compiler/rustc_middle/src/ty/context/impl_interner.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ use crate::ty::{
2929
Region, RegionKind, Ty, TyCtxt,
3030
};
3131

32+
impl<'tcx> rustc_type_ir::inherent::ObligationCause<TyCtxt<'tcx>>
33+
for crate::traits::ObligationCause<'tcx>
34+
{
35+
fn span(&self) -> Span {
36+
self.span
37+
}
38+
}
39+
3240
#[allow(rustc::usage_of_ty_tykind)]
3341
impl<'tcx> Interner for TyCtxt<'tcx> {
3442
fn next_trait_solver_globally(self) -> bool {
@@ -61,6 +69,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
6169
type InherentAssocConstId = DefId;
6270
type InherentAssocTermId = DefId;
6371
type Span = Span;
72+
type ObligationCause = crate::traits::ObligationCause<'tcx>;
6473

6574
type GenericArgs = ty::GenericArgsRef<'tcx>;
6675

compiler/rustc_middle/src/ty/elaborate_impl.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,53 @@
11
use rustc_span::Span;
22
use rustc_type_ir::elaborate::Elaboratable;
3+
use rustc_type_ir::solve::Obligation;
34

5+
use crate::traits::{ImplDerivedCause, ObligationCauseCode};
46
use crate::ty::{self, TyCtxt};
57

8+
type PredicateObligation<'tcx> = Obligation<TyCtxt<'tcx>, ty::Predicate<'tcx>>;
9+
10+
/// For `Obligation`, a sub-obligation is combined with the current
11+
/// obligation's param-env and cause code.
12+
impl<'tcx> Elaboratable<TyCtxt<'tcx>> for PredicateObligation<'tcx> {
13+
fn predicate(&self) -> ty::Predicate<'tcx> {
14+
self.predicate
15+
}
16+
17+
fn child(&self, clause: ty::Clause<'tcx>) -> Self {
18+
Obligation {
19+
cause: self.cause.clone(),
20+
param_env: self.param_env,
21+
recursion_depth: 0,
22+
predicate: clause.as_predicate(),
23+
}
24+
}
25+
26+
fn child_with_derived_cause(
27+
&self,
28+
clause: ty::Clause<'tcx>,
29+
span: Span,
30+
parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
31+
index: usize,
32+
) -> Self {
33+
let cause = self.cause.clone().derived_cause(parent_trait_pred, |derived| {
34+
ObligationCauseCode::ImplDerived(Box::new(ImplDerivedCause {
35+
derived,
36+
impl_or_alias_def_id: parent_trait_pred.def_id(),
37+
impl_def_clause_index: Some(index),
38+
span,
39+
}))
40+
});
41+
42+
Obligation {
43+
cause,
44+
param_env: self.param_env,
45+
recursion_depth: 0,
46+
predicate: clause.as_predicate(),
47+
}
48+
}
49+
}
50+
651
impl<'tcx> Elaboratable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
752
fn predicate(&self) -> ty::Predicate<'tcx> {
853
self.as_predicate()

0 commit comments

Comments
 (0)