Skip to content

Commit bc08b79

Browse files
committed
Fix bugs in evaluating WellFormed predicates
- List the nestsed obligations in an order that works with the single pass used by evaluation - Propagate recursion depth correctly
1 parent f52b2d8 commit bc08b79

File tree

8 files changed

+117
-42
lines changed

8 files changed

+117
-42
lines changed

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
449449
self.selcx.infcx(),
450450
obligation.param_env,
451451
obligation.cause.body_id,
452+
obligation.recursion_depth + 1,
452453
arg,
453454
obligation.cause.span,
454455
) {

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
139139
);
140140
});
141141
// Require that the projection is well-formed.
142-
let self_ty = obligation.predicate.skip_binder().self_ty();
143-
obligations.push(Obligation::new(
142+
let self_ty = self.infcx.replace_bound_vars_with_placeholders(&obligation.self_ty());
143+
let self_ty = normalize_with_depth_to(
144+
self,
145+
obligation.param_env,
144146
obligation.cause.clone(),
147+
obligation.recursion_depth + 1,
148+
&self_ty,
149+
&mut obligations,
150+
);
151+
obligations.push(Obligation::with_depth(
152+
obligation.cause.clone(),
153+
obligation.recursion_depth + 1,
145154
obligation.param_env,
146155
ty::PredicateKind::WellFormed(self_ty.into()).to_predicate(self.tcx()),
147156
));
@@ -333,9 +342,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
333342
// relying on projections in the impl-trait-ref.
334343
//
335344
// e.g., `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
336-
impl_obligations.append(&mut substs.obligations);
345+
substs.obligations.append(&mut impl_obligations);
337346

338-
ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: impl_obligations }
347+
ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: substs.obligations }
339348
}
340349

341350
fn confirm_object_candidate(

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
343343
Err(SelectionError::Overflow)
344344
}
345345
Err(e) => Err(e),
346-
Ok(candidate) => Ok(Some(candidate)),
346+
Ok(candidate) => {
347+
debug!("select: candidate = {:?}", candidate);
348+
Ok(Some(candidate))
349+
}
347350
}
348351
}
349352

@@ -413,9 +416,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
413416
predicates: I,
414417
) -> Result<EvaluationResult, OverflowError>
415418
where
416-
I: IntoIterator<Item = PredicateObligation<'tcx>>,
419+
I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,
417420
{
418421
let mut result = EvaluatedToOk;
422+
debug!("evaluate_predicates_recursively({:?})", predicates);
419423
for obligation in predicates {
420424
let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
421425
debug!("evaluate_predicate_recursively({:?}) = {:?}", obligation, eval);
@@ -436,7 +440,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
436440
obligation: PredicateObligation<'tcx>,
437441
) -> Result<EvaluationResult, OverflowError> {
438442
debug!(
439-
"evaluate_predicate_recursively(previous_stack={:?}, obligation={:?})",
443+
"evaluate_predicate_recursively(obligation={:?}, previous_stack={:?})",
440444
previous_stack.head(),
441445
obligation
442446
);
@@ -479,15 +483,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
479483
self.infcx,
480484
obligation.param_env,
481485
obligation.cause.body_id,
486+
obligation.recursion_depth + 1,
482487
arg,
483488
obligation.cause.span,
484489
) {
485490
Some(mut obligations) => {
486491
self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
487-
self.evaluate_predicates_recursively(
488-
previous_stack,
489-
obligations.into_iter(),
490-
)
492+
self.evaluate_predicates_recursively(previous_stack, obligations)
491493
}
492494
None => Ok(EvaluatedToAmbig),
493495
},
@@ -511,10 +513,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
511513
match project::poly_project_and_unify_type(self, &project_obligation) {
512514
Ok(Ok(Some(mut subobligations))) => {
513515
self.add_depth(subobligations.iter_mut(), obligation.recursion_depth);
514-
let result = self.evaluate_predicates_recursively(
515-
previous_stack,
516-
subobligations.into_iter(),
517-
);
516+
let result = self
517+
.evaluate_predicates_recursively(previous_stack, subobligations);
518518
if let Some(key) =
519519
ProjectionCacheKey::from_poly_projection_predicate(self, data)
520520
{
@@ -879,10 +879,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
879879
let result = self.evaluation_probe(|this| {
880880
let candidate = (*candidate).clone();
881881
match this.confirm_candidate(stack.obligation, candidate) {
882-
Ok(selection) => this.evaluate_predicates_recursively(
883-
stack.list(),
884-
selection.nested_obligations().into_iter(),
885-
),
882+
Ok(selection) => {
883+
debug!("evaluate_candidate: selection = {:?}", selection);
884+
this.evaluate_predicates_recursively(
885+
stack.list(),
886+
selection.nested_obligations().into_iter(),
887+
)
888+
}
886889
Err(..) => Ok(EvaluatedToErr),
887890
}
888891
})?;
@@ -1231,9 +1234,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12311234
) -> Result<EvaluationResult, OverflowError> {
12321235
self.evaluation_probe(|this| {
12331236
match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
1234-
Ok(obligations) => {
1235-
this.evaluate_predicates_recursively(stack.list(), obligations.into_iter())
1236-
}
1237+
Ok(obligations) => this.evaluate_predicates_recursively(stack.list(), obligations),
12371238
Err(()) => Ok(EvaluatedToErr),
12381239
}
12391240
})

compiler/rustc_trait_selection/src/traits/wf.rs

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub fn obligations<'a, 'tcx>(
2020
infcx: &InferCtxt<'a, 'tcx>,
2121
param_env: ty::ParamEnv<'tcx>,
2222
body_id: hir::HirId,
23+
recursion_depth: usize,
2324
arg: GenericArg<'tcx>,
2425
span: Span,
2526
) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
@@ -59,7 +60,8 @@ pub fn obligations<'a, 'tcx>(
5960
GenericArgKind::Lifetime(..) => return Some(Vec::new()),
6061
};
6162

62-
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
63+
let mut wf =
64+
WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth, item: None };
6365
wf.compute(arg);
6466
debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out);
6567

@@ -80,7 +82,8 @@ pub fn trait_obligations<'a, 'tcx>(
8082
span: Span,
8183
item: Option<&'tcx hir::Item<'tcx>>,
8284
) -> Vec<traits::PredicateObligation<'tcx>> {
83-
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item };
85+
let mut wf =
86+
WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth: 0, item };
8487
wf.compute_trait_ref(trait_ref, Elaborate::All);
8588
wf.normalize()
8689
}
@@ -92,7 +95,15 @@ pub fn predicate_obligations<'a, 'tcx>(
9295
predicate: ty::Predicate<'tcx>,
9396
span: Span,
9497
) -> Vec<traits::PredicateObligation<'tcx>> {
95-
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
98+
let mut wf = WfPredicates {
99+
infcx,
100+
param_env,
101+
body_id,
102+
span,
103+
out: vec![],
104+
recursion_depth: 0,
105+
item: None,
106+
};
96107

97108
// It's ok to skip the binder here because wf code is prepared for it
98109
match predicate.skip_binders() {
@@ -142,6 +153,7 @@ struct WfPredicates<'a, 'tcx> {
142153
body_id: hir::HirId,
143154
span: Span,
144155
out: Vec<traits::PredicateObligation<'tcx>>,
156+
recursion_depth: usize,
145157
item: Option<&'tcx hir::Item<'tcx>>,
146158
}
147159

@@ -249,19 +261,19 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
249261
for mut obligation in self.out {
250262
assert!(!obligation.has_escaping_bound_vars());
251263
let mut selcx = traits::SelectionContext::new(infcx);
252-
let i = obligations.len();
253264
// Don't normalize the whole obligation, the param env is either
254265
// already normalized, or we're currently normalizing the
255266
// param_env. Either way we should only normalize the predicate.
256-
let normalized_predicate = traits::normalize_to(
267+
let normalized_predicate = traits::project::normalize_with_depth_to(
257268
&mut selcx,
258269
param_env,
259270
cause.clone(),
271+
self.recursion_depth,
260272
&obligation.predicate,
261273
&mut obligations,
262274
);
263275
obligation.predicate = normalized_predicate;
264-
obligations.insert(i, obligation);
276+
obligations.push(obligation);
265277
}
266278
obligations
267279
}
@@ -274,6 +286,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
274286
debug!("compute_trait_ref obligations {:?}", obligations);
275287
let cause = self.cause(traits::MiscObligation);
276288
let param_env = self.param_env;
289+
let depth = self.recursion_depth;
277290

278291
let item = self.item;
279292

@@ -295,7 +308,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
295308
&obligation.predicate,
296309
tcx.associated_items(trait_ref.def_id).in_definition_order(),
297310
);
298-
traits::Obligation::new(cause, param_env, obligation.predicate)
311+
traits::Obligation::with_depth(cause, depth, param_env, obligation.predicate)
299312
};
300313

301314
if let Elaborate::All = elaborate {
@@ -324,8 +337,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
324337
new_cause.make_mut().span = self_ty.span;
325338
}
326339
}
327-
traits::Obligation::new(
340+
traits::Obligation::with_depth(
328341
new_cause,
342+
depth,
329343
param_env,
330344
ty::PredicateAtom::WellFormed(arg).to_predicate(tcx),
331345
)
@@ -363,6 +377,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
363377
let tcx = self.tcx();
364378
let cause = self.cause(traits::MiscObligation);
365379
let param_env = self.param_env;
380+
let depth = self.recursion_depth;
366381

367382
self.out.extend(
368383
data.substs
@@ -372,8 +387,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
372387
})
373388
.filter(|arg| !arg.has_escaping_bound_vars())
374389
.map(|arg| {
375-
traits::Obligation::new(
390+
traits::Obligation::with_depth(
376391
cause.clone(),
392+
depth,
377393
param_env,
378394
ty::PredicateKind::WellFormed(arg).to_predicate(tcx),
379395
)
@@ -388,8 +404,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
388404
def_id: self.infcx.tcx.require_lang_item(LangItem::Sized, None),
389405
substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
390406
};
391-
self.out.push(traits::Obligation::new(
407+
self.out.push(traits::Obligation::with_depth(
392408
cause,
409+
self.recursion_depth,
393410
self.param_env,
394411
trait_ref.without_const().to_predicate(self.infcx.tcx),
395412
));
@@ -400,6 +417,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
400417
fn compute(&mut self, arg: GenericArg<'tcx>) {
401418
let mut walker = arg.walk();
402419
let param_env = self.param_env;
420+
let depth = self.recursion_depth;
403421
while let Some(arg) = walker.next() {
404422
let ty = match arg.unpack() {
405423
GenericArgKind::Type(ty) => ty,
@@ -419,8 +437,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
419437
let predicate = ty::PredicateAtom::ConstEvaluatable(def, substs)
420438
.to_predicate(self.tcx());
421439
let cause = self.cause(traits::MiscObligation);
422-
self.out.push(traits::Obligation::new(
440+
self.out.push(traits::Obligation::with_depth(
423441
cause,
442+
self.recursion_depth,
424443
self.param_env,
425444
predicate,
426445
));
@@ -435,8 +454,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
435454
val: ty::ConstKind::Infer(resolved),
436455
..*constant
437456
});
438-
self.out.push(traits::Obligation::new(
457+
self.out.push(traits::Obligation::with_depth(
439458
cause,
459+
self.recursion_depth,
440460
self.param_env,
441461
ty::PredicateAtom::WellFormed(resolved_constant.into())
442462
.to_predicate(self.tcx()),
@@ -521,8 +541,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
521541
// WfReference
522542
if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
523543
let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
524-
self.out.push(traits::Obligation::new(
544+
self.out.push(traits::Obligation::with_depth(
525545
cause,
546+
depth,
526547
param_env,
527548
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(rty, r))
528549
.to_predicate(self.tcx()),
@@ -612,8 +633,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
612633
let component_traits = data.auto_traits().chain(data.principal_def_id());
613634
let tcx = self.tcx();
614635
self.out.extend(component_traits.map(|did| {
615-
traits::Obligation::new(
636+
traits::Obligation::with_depth(
616637
cause.clone(),
638+
depth,
617639
param_env,
618640
ty::PredicateAtom::ObjectSafe(did).to_predicate(tcx),
619641
)
@@ -638,8 +660,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
638660
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
639661
// Not yet resolved, but we've made progress.
640662
let cause = self.cause(traits::MiscObligation);
641-
self.out.push(traits::Obligation::new(
663+
self.out.push(traits::Obligation::with_depth(
642664
cause,
665+
self.recursion_depth,
643666
param_env,
644667
ty::PredicateAtom::WellFormed(ty.into()).to_predicate(self.tcx()),
645668
));
@@ -676,7 +699,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
676699
.zip(origins.into_iter().rev())
677700
.map(|((pred, span), origin_def_id)| {
678701
let cause = self.cause(traits::BindingObligation(origin_def_id, span));
679-
traits::Obligation::new(cause, self.param_env, pred)
702+
traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred)
680703
})
681704
.filter(|pred| !pred.has_escaping_bound_vars())
682705
.collect()
@@ -729,8 +752,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
729752
let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
730753
let outlives =
731754
ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound));
732-
self.out.push(traits::Obligation::new(
755+
self.out.push(traits::Obligation::with_depth(
733756
cause,
757+
self.recursion_depth,
734758
self.param_env,
735759
outlives.to_predicate(self.infcx.tcx),
736760
));

compiler/rustc_traits/src/implied_outlives_bounds.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ fn compute_implied_outlives_bounds<'tcx>(
6161
// than the ultimate set. (Note: normally there won't be
6262
// unresolved inference variables here anyway, but there might be
6363
// during typeck under some circumstances.)
64-
let obligations =
65-
wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, arg, DUMMY_SP).unwrap_or(vec![]);
64+
let obligations = wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP)
65+
.unwrap_or(vec![]);
6666

6767
// N.B., all of these predicates *ought* to be easily proven
6868
// true. In fact, their correctness is (mostly) implied by

compiler/rustc_typeck/src/check/check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ fn check_opaque_meets_bounds<'tcx>(
561561
let misc_cause = traits::ObligationCause::misc(span, hir_id);
562562

563563
let (_, opaque_type_map) = inh.register_infer_ok_obligations(
564-
infcx.instantiate_opaque_types(def_id.to_def_id(), hir_id, param_env, &opaque_ty, span),
564+
infcx.instantiate_opaque_types(def_id, hir_id, param_env, &opaque_ty, span),
565565
);
566566

567567
for (def_id, opaque_defn) in opaque_type_map {

compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ fn check_predicates<'tcx>(
337337
infcx,
338338
tcx.param_env(impl1_def_id),
339339
tcx.hir().local_def_id_to_hir_id(impl1_def_id),
340+
0,
340341
arg,
341342
span,
342343
) {

0 commit comments

Comments
 (0)