3 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
4 use rustc_middle::ty::query::Providers;
5 use rustc_middle::ty::subst::GenericArgKind;
6 use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
7 use rustc_span::symbol::sym;
12 /// Code to write unit test for outlives.
16 pub fn provide(providers: &mut Providers) {
17 *providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers };
20 fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate<'_>, Span)] {
21 let id = tcx.hir().as_local_hir_id(item_def_id.expect_local());
23 match tcx.hir().get(id) {
24 Node::Item(item) => match item.kind {
25 hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => {
26 let crate_map = tcx.inferred_outlives_crate(LOCAL_CRATE);
28 let predicates = crate_map.predicates.get(&item_def_id).copied().unwrap_or(&[]);
30 if tcx.has_attr(item_def_id, sym::rustc_outlives) {
31 let mut pred: Vec<String> = predicates
33 .map(|(out_pred, _)| match out_pred.kind() {
34 ty::PredicateKind::Atom(ty::PredicateAtom::RegionOutlives(p)) => {
37 ty::PredicateKind::Atom(ty::PredicateAtom::TypeOutlives(p)) => {
40 err => bug!("unexpected predicate {:?}", err),
45 let span = tcx.def_span(item_def_id);
46 let mut err = tcx.sess.struct_span_err(span, "rustc_outlives");
53 debug!("inferred_outlives_of({:?}) = {:?}", item_def_id, predicates);
65 fn inferred_outlives_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CratePredicatesMap<'_> {
66 assert_eq!(crate_num, LOCAL_CRATE);
68 // Compute a map from each struct/enum/union S to the **explicit**
69 // outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote.
70 // Typically there won't be many of these, except in older code where
71 // they were mandatory. Nonetheless, we have to ensure that every such
72 // predicate is satisfied, so they form a kind of base set of requirements
75 // Compute the inferred predicates
76 let mut exp_map = explicit::ExplicitPredicatesMap::new();
78 let global_inferred_outlives = implicit_infer::infer_predicates(tcx, &mut exp_map);
80 // Convert the inferred predicates into the "collected" form the
81 // global data structure expects.
83 // FIXME -- consider correcting impedance mismatch in some way,
84 // probably by updating the global data structure.
85 let predicates = global_inferred_outlives
87 .map(|(&def_id, set)| {
88 let predicates = &*tcx.arena.alloc_from_iter(set.iter().filter_map(
89 |(ty::OutlivesPredicate(kind1, region2), &span)| {
90 match kind1.unpack() {
91 GenericArgKind::Type(ty1) => Some((
92 ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty1, region2))
93 .potentially_quantified(tcx, ty::PredicateKind::ForAll),
96 GenericArgKind::Lifetime(region1) => Some((
97 ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(
100 .potentially_quantified(tcx, ty::PredicateKind::ForAll),
103 GenericArgKind::Const(_) => {
104 // Generic consts don't impose any constraints.
114 ty::CratePredicatesMap { predicates }