Skip to content

Commit 758bedc

Browse files
Make elaborator generic
1 parent de74dab commit 758bedc

File tree

21 files changed

+164
-156
lines changed

21 files changed

+164
-156
lines changed

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2034,7 +2034,7 @@ pub(super) fn check_type_bounds<'tcx>(
20342034
ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
20352035
};
20362036

2037-
let obligations = tcx
2037+
let obligations: Vec<_> = tcx
20382038
.bound_explicit_item_bounds(trait_ty.def_id)
20392039
.subst_iter_copied(tcx, rebased_substs)
20402040
.map(|(concrete_ty_bound, span)| {
@@ -2044,7 +2044,7 @@ pub(super) fn check_type_bounds<'tcx>(
20442044
.collect();
20452045
debug!("check_type_bounds: item_bounds={:?}", obligations);
20462046

2047-
for mut obligation in util::elaborate_obligations(tcx, obligations) {
2047+
for mut obligation in util::elaborate(tcx, obligations) {
20482048
let normalized_predicate =
20492049
ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate);
20502050
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1908,7 +1908,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
19081908

19091909
let predicates_with_span = tcx.predicates_of(self.body_def_id).predicates.iter().copied();
19101910
// Check elaborated bounds.
1911-
let implied_obligations = traits::elaborate_predicates_with_span(tcx, predicates_with_span);
1911+
let implied_obligations = traits::elaborate(tcx, predicates_with_span);
19121912

19131913
for (pred, obligation_span) in implied_obligations {
19141914
// We lower empty bounds like `Vec<dyn Copy>:` as

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ pub(super) fn item_bounds(
130130
tcx: TyCtxt<'_>,
131131
def_id: DefId,
132132
) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> {
133-
let bounds = tcx.mk_predicates_from_iter(util::elaborate_predicates(
133+
let bounds = tcx.mk_predicates_from_iter(util::elaborate(
134134
tcx,
135135
tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
136136
));

compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -318,15 +318,14 @@ fn check_predicates<'tcx>(
318318
span: Span,
319319
) {
320320
let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
321-
let impl1_predicates: Vec<_> =
322-
traits::elaborate_predicates_with_span(tcx, instantiated.into_iter()).collect();
321+
let impl1_predicates: Vec<_> = traits::elaborate(tcx, instantiated.into_iter()).collect();
323322

324323
let mut impl2_predicates = if impl2_node.is_from_trait() {
325324
// Always applicable traits have to be always applicable without any
326325
// assumptions.
327326
Vec::new()
328327
} else {
329-
traits::elaborate_predicates(
328+
traits::elaborate(
330329
tcx,
331330
tcx.predicates_of(impl2_node.def_id())
332331
.instantiate(tcx, impl2_substs)
@@ -371,11 +370,10 @@ fn check_predicates<'tcx>(
371370
.unwrap();
372371

373372
assert!(!obligations.needs_infer());
374-
impl2_predicates.extend(
375-
traits::elaborate_obligations(tcx, obligations).map(|obligation| obligation.predicate),
376-
)
373+
impl2_predicates
374+
.extend(traits::elaborate(tcx, obligations).map(|obligation| obligation.predicate))
377375
}
378-
impl2_predicates.extend(traits::elaborate_predicates(tcx, always_applicable_traits));
376+
impl2_predicates.extend(traits::elaborate(tcx, always_applicable_traits));
379377

380378
for (predicate, span) in impl1_predicates {
381379
if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(tcx, predicate, *pred2, span)) {

compiler/rustc_hir_typeck/src/closure.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
204204
let mut expected_sig = None;
205205
let mut expected_kind = None;
206206

207-
for (pred, span) in traits::elaborate_predicates_with_span(
207+
for (pred, span) in traits::elaborate(
208208
self.tcx,
209209
// Reverse the obligations here, since `elaborate_*` uses a stack,
210210
// and we want to keep inference generally in the same order of

compiler/rustc_hir_typeck/src/method/confirm.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
574574
) -> Option<Span> {
575575
let sized_def_id = self.tcx.lang_items().sized_trait()?;
576576

577-
traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied())
577+
traits::elaborate(self.tcx, predicates.predicates.iter().copied())
578578
// We don't care about regions here.
579579
.filter_map(|pred| match pred.kind().skip_binder() {
580580
ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred))

compiler/rustc_hir_typeck/src/method/probe.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1555,8 +1555,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
15551555
if !self.predicate_may_hold(&o) {
15561556
result = ProbeResult::NoMatch;
15571557
let parent_o = o.clone();
1558-
let implied_obligations =
1559-
traits::elaborate_obligations(self.tcx, vec![o]);
1558+
let implied_obligations = traits::elaborate(self.tcx, vec![o]);
15601559
for o in implied_obligations {
15611560
let parent = if o == parent_o {
15621561
None

compiler/rustc_infer/src/traits/util.rs

+117-92
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use smallvec::smallvec;
22

33
use crate::infer::outlives::components::{push_outlives_components, Component};
4-
use crate::traits::{self, Obligation, ObligationCause, PredicateObligation};
4+
use crate::traits::{self, Obligation, PredicateObligation};
55
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
66
use rustc_middle::ty::{self, ToPredicate, TyCtxt};
77
use rustc_span::symbol::Ident;
@@ -66,99 +66,143 @@ impl<'tcx> Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
6666
/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd`
6767
/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
6868
/// `T: Foo`, then we know that `T: 'static`.
69-
pub struct Elaborator<'tcx> {
70-
stack: Vec<PredicateObligation<'tcx>>,
69+
pub struct Elaborator<'tcx, O> {
70+
stack: Vec<O>,
7171
visited: PredicateSet<'tcx>,
7272
}
7373

74-
pub fn elaborate_trait_ref<'tcx>(
75-
tcx: TyCtxt<'tcx>,
76-
trait_ref: ty::PolyTraitRef<'tcx>,
77-
) -> impl Iterator<Item = ty::Predicate<'tcx>> {
78-
elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx)))
74+
/// Describes how to elaborate an obligation into a sub-obligation.
75+
///
76+
/// For [`Obligation`], a sub-obligation is combined with the current obligation's
77+
/// param-env and cause code. For [`ty::Predicate`], none of this is needed, since
78+
/// there is no param-env or cause code to copy over.
79+
pub trait Elaboratable<'tcx> {
80+
fn predicate(&self) -> ty::Predicate<'tcx>;
81+
82+
// Makes a new `Self` but with a different predicate.
83+
fn child(&self, predicate: ty::Predicate<'tcx>) -> Self;
84+
85+
// Makes a new `Self` but with a different predicate and a different cause
86+
// code (if `Self` has one).
87+
fn child_with_derived_cause(
88+
&self,
89+
predicate: ty::Predicate<'tcx>,
90+
span: Span,
91+
parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
92+
index: usize,
93+
) -> Self;
7994
}
8095

81-
pub fn elaborate_trait_refs<'tcx>(
82-
tcx: TyCtxt<'tcx>,
83-
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
84-
) -> impl Iterator<Item = ty::Predicate<'tcx>> {
85-
let predicates = trait_refs.map(move |trait_ref| trait_ref.without_const().to_predicate(tcx));
86-
elaborate_predicates(tcx, predicates)
96+
impl<'tcx> Elaboratable<'tcx> for PredicateObligation<'tcx> {
97+
fn predicate(&self) -> ty::Predicate<'tcx> {
98+
self.predicate
99+
}
100+
101+
fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
102+
Obligation {
103+
cause: self.cause.clone(),
104+
param_env: self.param_env,
105+
recursion_depth: 0,
106+
predicate,
107+
}
108+
}
109+
110+
fn child_with_derived_cause(
111+
&self,
112+
predicate: ty::Predicate<'tcx>,
113+
span: Span,
114+
parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
115+
index: usize,
116+
) -> Self {
117+
let cause = self.cause.clone().derived_cause(parent_trait_pred, |derived| {
118+
traits::ImplDerivedObligation(Box::new(traits::ImplDerivedObligationCause {
119+
derived,
120+
impl_or_alias_def_id: parent_trait_pred.def_id(),
121+
impl_def_predicate_index: Some(index),
122+
span,
123+
}))
124+
});
125+
Obligation { cause, param_env: self.param_env, recursion_depth: 0, predicate }
126+
}
87127
}
88128

89-
pub fn elaborate_predicates<'tcx>(
129+
impl<'tcx> Elaboratable<'tcx> for ty::Predicate<'tcx> {
130+
fn predicate(&self) -> ty::Predicate<'tcx> {
131+
*self
132+
}
133+
134+
fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
135+
predicate
136+
}
137+
138+
fn child_with_derived_cause(
139+
&self,
140+
predicate: ty::Predicate<'tcx>,
141+
_span: Span,
142+
_parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
143+
_index: usize,
144+
) -> Self {
145+
predicate
146+
}
147+
}
148+
149+
impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) {
150+
fn predicate(&self) -> ty::Predicate<'tcx> {
151+
self.0
152+
}
153+
154+
fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
155+
(predicate, self.1)
156+
}
157+
158+
fn child_with_derived_cause(
159+
&self,
160+
predicate: ty::Predicate<'tcx>,
161+
_span: Span,
162+
_parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
163+
_index: usize,
164+
) -> Self {
165+
(predicate, self.1)
166+
}
167+
}
168+
169+
pub fn elaborate_trait_ref<'tcx>(
90170
tcx: TyCtxt<'tcx>,
91-
predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
92-
) -> impl Iterator<Item = ty::Predicate<'tcx>> {
93-
elaborate_obligations(
94-
tcx,
95-
predicates
96-
.map(|predicate| {
97-
Obligation::new(
98-
tcx,
99-
// We'll dump the cause/param-env later
100-
ObligationCause::dummy(),
101-
ty::ParamEnv::empty(),
102-
predicate,
103-
)
104-
})
105-
.collect(),
106-
)
107-
.map(|obl| obl.predicate)
171+
trait_ref: ty::PolyTraitRef<'tcx>,
172+
) -> Elaborator<'tcx, ty::Predicate<'tcx>> {
173+
elaborate(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx)))
108174
}
109175

110-
pub fn elaborate_predicates_with_span<'tcx>(
176+
pub fn elaborate_trait_refs<'tcx>(
111177
tcx: TyCtxt<'tcx>,
112-
predicates: impl Iterator<Item = (ty::Predicate<'tcx>, Span)>,
113-
) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> {
114-
elaborate_obligations(
115-
tcx,
116-
predicates
117-
.map(|(predicate, span)| {
118-
Obligation::new(
119-
tcx,
120-
// We'll dump the cause/param-env later
121-
ObligationCause::dummy_with_span(span),
122-
ty::ParamEnv::empty(),
123-
predicate,
124-
)
125-
})
126-
.collect(),
127-
)
128-
.map(|obl| (obl.predicate, obl.cause.span))
178+
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
179+
) -> Elaborator<'tcx, ty::Predicate<'tcx>> {
180+
elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.to_predicate(tcx)))
129181
}
130182

131-
pub fn elaborate_obligations<'tcx>(
183+
pub fn elaborate<'tcx, O: Elaboratable<'tcx>>(
132184
tcx: TyCtxt<'tcx>,
133-
obligations: Vec<PredicateObligation<'tcx>>,
134-
) -> Elaborator<'tcx> {
185+
obligations: impl IntoIterator<Item = O>,
186+
) -> Elaborator<'tcx, O> {
135187
let mut elaborator = Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx) };
136188
elaborator.extend_deduped(obligations);
137189
elaborator
138190
}
139191

140-
fn predicate_obligation<'tcx>(
141-
predicate: ty::Predicate<'tcx>,
142-
param_env: ty::ParamEnv<'tcx>,
143-
cause: ObligationCause<'tcx>,
144-
) -> PredicateObligation<'tcx> {
145-
Obligation { cause, param_env, recursion_depth: 0, predicate }
146-
}
147-
148-
impl<'tcx> Elaborator<'tcx> {
149-
fn extend_deduped(&mut self, obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>) {
192+
impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
193+
fn extend_deduped(&mut self, obligations: impl IntoIterator<Item = O>) {
150194
// Only keep those bounds that we haven't already seen.
151195
// This is necessary to prevent infinite recursion in some
152196
// cases. One common case is when people define
153197
// `trait Sized: Sized { }` rather than `trait Sized { }`.
154198
// let visited = &mut self.visited;
155-
self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate)));
199+
self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate())));
156200
}
157201

158-
fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
202+
fn elaborate(&mut self, elaboratable: &O) {
159203
let tcx = self.visited.tcx;
160204

161-
let bound_predicate = obligation.predicate.kind();
205+
let bound_predicate = elaboratable.predicate().kind();
162206
match bound_predicate.skip_binder() {
163207
ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
164208
// Get predicates declared on the trait.
@@ -170,24 +214,11 @@ impl<'tcx> Elaborator<'tcx> {
170214
if data.constness == ty::BoundConstness::NotConst {
171215
pred = pred.without_const(tcx);
172216
}
173-
174-
let cause = obligation.cause.clone().derived_cause(
175-
bound_predicate.rebind(data),
176-
|derived| {
177-
traits::ImplDerivedObligation(Box::new(
178-
traits::ImplDerivedObligationCause {
179-
derived,
180-
impl_or_alias_def_id: data.def_id(),
181-
impl_def_predicate_index: Some(index),
182-
span,
183-
},
184-
))
185-
},
186-
);
187-
predicate_obligation(
217+
elaboratable.child_with_derived_cause(
188218
pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
189-
obligation.param_env,
190-
cause,
219+
span,
220+
bound_predicate.rebind(data),
221+
index,
191222
)
192223
});
193224
debug!(?data, ?obligations, "super_predicates");
@@ -290,13 +321,7 @@ impl<'tcx> Elaborator<'tcx> {
290321
.map(|predicate_kind| {
291322
bound_predicate.rebind(predicate_kind).to_predicate(tcx)
292323
})
293-
.map(|predicate| {
294-
predicate_obligation(
295-
predicate,
296-
obligation.param_env,
297-
obligation.cause.clone(),
298-
)
299-
}),
324+
.map(|predicate| elaboratable.child(predicate)),
300325
);
301326
}
302327
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
@@ -313,8 +338,8 @@ impl<'tcx> Elaborator<'tcx> {
313338
}
314339
}
315340

316-
impl<'tcx> Iterator for Elaborator<'tcx> {
317-
type Item = PredicateObligation<'tcx>;
341+
impl<'tcx, O: Elaboratable<'tcx>> Iterator for Elaborator<'tcx, O> {
342+
type Item = O;
318343

319344
fn size_hint(&self) -> (usize, Option<usize>) {
320345
(self.stack.len(), None)

0 commit comments

Comments
 (0)