3 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
4 use rustc::ty::query::Providers;
5 use rustc::ty::subst::UnpackedKind;
6 use rustc::ty::{self, CratePredicatesMap, TyCtxt};
7 use rustc_data_structures::sync::Lrc;
8 use syntax::symbol::sym;
12 /// Code to write unit test for outlives.
16 pub fn provide(providers: &mut Providers<'_>) {
17 *providers = Providers {
19 inferred_outlives_crate,
24 fn inferred_outlives_of<'a, 'tcx>(
25 tcx: TyCtxt<'a, 'tcx, 'tcx>,
27 ) -> &'tcx [ty::Predicate<'tcx>] {
30 .as_local_hir_id(item_def_id)
31 .expect("expected local def-id");
33 match tcx.hir().get_by_hir_id(id) {
34 Node::Item(item) => match item.node {
35 hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => {
36 let crate_map = tcx.inferred_outlives_crate(LOCAL_CRATE);
38 let predicates = crate_map
44 if tcx.has_attr(item_def_id, sym::rustc_outlives) {
45 let mut pred: Vec<String> = predicates
47 .map(|out_pred| match out_pred {
48 ty::Predicate::RegionOutlives(p) => p.to_string(),
49 ty::Predicate::TypeOutlives(p) => p.to_string(),
50 err => bug!("unexpected predicate {:?}", err),
54 let span = tcx.def_span(item_def_id);
55 let mut err = tcx.sess.struct_span_err(span, "rustc_outlives");
62 debug!("inferred_outlives_of({:?}) = {:?}", item_def_id, predicates);
74 fn inferred_outlives_crate<'tcx>(
75 tcx: TyCtxt<'_, 'tcx, 'tcx>,
77 ) -> Lrc<CratePredicatesMap<'tcx>> {
78 assert_eq!(crate_num, LOCAL_CRATE);
80 // Compute a map from each struct/enum/union S to the **explicit**
81 // outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote.
82 // Typically there won't be many of these, except in older code where
83 // they were mandatory. Nonetheless, we have to ensure that every such
84 // predicate is satisfied, so they form a kind of base set of requirements
87 // Compute the inferred predicates
88 let mut exp_map = explicit::ExplicitPredicatesMap::new();
90 let global_inferred_outlives = implicit_infer::infer_predicates(tcx, &mut exp_map);
92 // Convert the inferred predicates into the "collected" form the
93 // global data structure expects.
95 // FIXME -- consider correcting impedance mismatch in some way,
96 // probably by updating the global data structure.
97 let predicates = global_inferred_outlives
99 .map(|(&def_id, set)| {
100 let predicates = tcx.arena.alloc_from_iter(set
103 |ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() {
104 UnpackedKind::Type(ty1) => {
105 Some(ty::Predicate::TypeOutlives(ty::Binder::bind(
106 ty::OutlivesPredicate(ty1, region2)
109 UnpackedKind::Lifetime(region1) => {
110 Some(ty::Predicate::RegionOutlives(
111 ty::Binder::bind(ty::OutlivesPredicate(region1, region2))
114 UnpackedKind::Const(_) => {
115 // Generic consts don't impose any constraints.
120 (def_id, &*predicates)
123 Lrc::new(ty::CratePredicatesMap {