Skip to content

Commit c8ecf09

Browse files
committed
Generalize projection_must_outlive
1 parent 4d4cc4f commit c8ecf09

File tree

1 file changed

+29
-14
lines changed

1 file changed

+29
-14
lines changed

compiler/rustc_infer/src/infer/outlives/obligations.rs

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ use crate::infer::{
6868
};
6969
use crate::traits::{ObligationCause, ObligationCauseCode};
7070
use rustc_data_structures::undo_log::UndoLogs;
71+
use rustc_hir::def_id::DefId;
7172
use rustc_hir::def_id::LocalDefId;
7273
use rustc_middle::mir::ConstraintCategory;
7374
use rustc_middle::ty::subst::GenericArgKind;
@@ -324,6 +325,29 @@ where
324325
origin: infer::SubregionOrigin<'tcx>,
325326
region: ty::Region<'tcx>,
326327
projection_ty: ty::ProjectionTy<'tcx>,
328+
) {
329+
self.generic_must_outlive(
330+
origin,
331+
region,
332+
GenericKind::Projection(projection_ty),
333+
projection_ty.item_def_id,
334+
projection_ty.substs,
335+
|ty| match ty.kind() {
336+
ty::Projection(projection_ty) => (projection_ty.item_def_id, projection_ty.substs),
337+
_ => bug!("expected only projection types from env, not {:?}", ty),
338+
},
339+
);
340+
}
341+
342+
#[instrument(level = "debug", skip(self, filter))]
343+
fn generic_must_outlive(
344+
&mut self,
345+
origin: infer::SubregionOrigin<'tcx>,
346+
region: ty::Region<'tcx>,
347+
generic: GenericKind<'tcx>,
348+
def_id: DefId,
349+
substs: SubstsRef<'tcx>,
350+
filter: impl Fn(Ty<'tcx>) -> (DefId, SubstsRef<'tcx>),
327351
) {
328352
// This case is thorny for inference. The fundamental problem is
329353
// that there are many cases where we have choice, and inference
@@ -342,13 +366,10 @@ where
342366
// Compute the bounds we can derive from the trait definition.
343367
// These are guaranteed to apply, no matter the inference
344368
// results.
345-
let trait_bounds: Vec<_> =
346-
self.verify_bound.bounds(projection_ty.item_def_id, projection_ty.substs).collect();
369+
let trait_bounds: Vec<_> = self.verify_bound.bounds(def_id, substs).collect();
347370

348371
debug!(?trait_bounds);
349372

350-
let generic = GenericKind::Projection(projection_ty);
351-
352373
// Compute the bounds we can derive from the environment. This
353374
// is an "approximate" match -- in some cases, these bounds
354375
// may not apply.
@@ -367,14 +388,8 @@ where
367388
// If the declaration is `trait Trait<'b> { type Item: 'b; }`, then `projection_declared_bounds_from_trait`
368389
// will be invoked with `['b => ^1]` and so we will get `^1` returned.
369390
let bound = bound_outlives.skip_binder();
370-
match *bound.0.kind() {
371-
ty::Projection(projection_ty) => self
372-
.verify_bound
373-
.bounds(projection_ty.item_def_id, projection_ty.substs)
374-
.all(|r| r != bound.1),
375-
376-
_ => panic!("expected only projection types from env, not {:?}", bound.0),
377-
}
391+
let (def_id, substs) = filter(bound.0);
392+
self.verify_bound.bounds(def_id, substs).all(|r| r != bound.1)
378393
});
379394

380395
// If declared bounds list is empty, the only applicable rule is
@@ -391,11 +406,11 @@ where
391406
// the problem is to add `T: 'r`, which isn't true. So, if there are no
392407
// inference variables, we use a verify constraint instead of adding
393408
// edges, which winds up enforcing the same condition.
394-
let needs_infer = projection_ty.needs_infer();
409+
let needs_infer = substs.needs_infer();
395410
if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer {
396411
debug!("no declared bounds");
397412

398-
self.substs_must_outlive(projection_ty.substs, origin, region);
413+
self.substs_must_outlive(substs, origin, region);
399414

400415
return;
401416
}

0 commit comments

Comments
 (0)