Skip to content

Commit 643b173

Browse files
committed
Auto merge of #54401 - nikomatsakis:issue-54302-hrtb-fail, r=<try>
make evaluation track whether outlives relationships mattered Previously, evaluation ignored outlives relationships. Since we using evaluation to skip the "normal" trait selection (which enforces outlives relationships) this led to incorrect results in some cases. Fixes #54302 r? @arielb1
2 parents ae36663 + 563ba10 commit 643b173

File tree

9 files changed

+1466
-1143
lines changed

9 files changed

+1466
-1143
lines changed

src/librustc/infer/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1390,7 +1390,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
13901390
// rightly refuses to work with inference variables, but
13911391
// moves_by_default has a cache, which we want to use in other
13921392
// cases.
1393-
!traits::type_known_to_meet_bound(self, param_env, ty, copy_def_id, span)
1393+
!traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span)
13941394
}
13951395

13961396
/// Obtains the latest type of the given closure; this may be a

src/librustc/traits/fulfill.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -293,10 +293,10 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
293293
ty::Predicate::Trait(ref data) => {
294294
let trait_obligation = obligation.with(data.clone());
295295

296-
if data.is_global() && !data.has_late_bound_regions() {
296+
if data.is_global() {
297297
// no type variables present, can use evaluation for better caching.
298298
// FIXME: consider caching errors too.
299-
if self.selcx.infcx().predicate_must_hold(&obligation) {
299+
if self.selcx.infcx().predicate_must_hold_considering_regions(&obligation) {
300300
debug!("selecting trait `{:?}` at depth {} evaluated to holds",
301301
data, obligation.recursion_depth);
302302
return ProcessResult::Changed(vec![])

src/librustc/traits/mod.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -564,14 +564,14 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
564564
/// `bound` or is not known to meet bound (note that this is
565565
/// conservative towards *no impl*, which is the opposite of the
566566
/// `evaluate` methods).
567-
pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
568-
param_env: ty::ParamEnv<'tcx>,
569-
ty: Ty<'tcx>,
570-
def_id: DefId,
571-
span: Span)
572-
-> bool
573-
{
574-
debug!("type_known_to_meet_bound(ty={:?}, bound={:?})",
567+
pub fn type_known_to_meet_bound_modulo_regions<'a, 'gcx, 'tcx>(
568+
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
569+
param_env: ty::ParamEnv<'tcx>,
570+
ty: Ty<'tcx>,
571+
def_id: DefId,
572+
span: Span,
573+
) -> bool {
574+
debug!("type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})",
575575
ty,
576576
infcx.tcx.item_path_str(def_id));
577577

@@ -586,7 +586,7 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx
586586
predicate: trait_ref.to_predicate(),
587587
};
588588

589-
let result = infcx.predicate_must_hold(&obligation);
589+
let result = infcx.predicate_must_hold_modulo_regions(&obligation);
590590
debug!("type_known_to_meet_ty={:?} bound={} => {:?}",
591591
ty, infcx.tcx.item_path_str(def_id), result);
592592

@@ -613,13 +613,13 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx
613613
// assume it is move; linear is always ok.
614614
match fulfill_cx.select_all_or_error(infcx) {
615615
Ok(()) => {
616-
debug!("type_known_to_meet_bound: ty={:?} bound={} success",
616+
debug!("type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success",
617617
ty,
618618
infcx.tcx.item_path_str(def_id));
619619
true
620620
}
621621
Err(e) => {
622-
debug!("type_known_to_meet_bound: ty={:?} bound={} errors={:?}",
622+
debug!("type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}",
623623
ty,
624624
infcx.tcx.item_path_str(def_id),
625625
e);

src/librustc/traits/query/evaluate_obligation.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,26 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
2626
/// Evaluates whether the predicate can be satisfied in the given
2727
/// `ParamEnv`, and returns `false` if not certain. However, this is
2828
/// not entirely accurate if inference variables are involved.
29-
pub fn predicate_must_hold(
29+
///
30+
/// This version may conservatively fail when outlives obligations
31+
/// are required.
32+
pub fn predicate_must_hold_considering_regions(
3033
&self,
3134
obligation: &PredicateObligation<'tcx>,
3235
) -> bool {
33-
self.evaluate_obligation(obligation) == EvaluationResult::EvaluatedToOk
36+
self.evaluate_obligation(obligation).must_apply_considering_regions()
37+
}
38+
39+
/// Evaluates whether the predicate can be satisfied in the given
40+
/// `ParamEnv`, and returns `false` if not certain. However, this is
41+
/// not entirely accurate if inference variables are involved.
42+
///
43+
/// This version ignores all outlives constraints.
44+
pub fn predicate_must_hold_modulo_regions(
45+
&self,
46+
obligation: &PredicateObligation<'tcx>,
47+
) -> bool {
48+
self.evaluate_obligation(obligation).must_apply_modulo_regions()
3449
}
3550

3651
// Helper function that canonicalizes and runs the query, as well as handles

0 commit comments

Comments
 (0)