about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-10-27 12:58:10 +0000
committerbors <bors@rust-lang.org>2019-10-27 12:58:10 +0000
commit0f677c65e867d93a47ccbaeaf6e6725cde8c5ff6 (patch)
tree7bab7c6cced461c05c36ce0c1490c52a3a50b844 /src
parentb7176b44a203322c834302f3b515f8c10a54f2c1 (diff)
parent1ca8da40366a417aef90415d8f745764cab5783b (diff)
downloadrust-0f677c65e867d93a47ccbaeaf6e6725cde8c5ff6.tar.gz
rust-0f677c65e867d93a47ccbaeaf6e6725cde8c5ff6.zip
Auto merge of #65541 - eddyb:spanned-inferred-outlives, r=nikomatsakis
rustc: add `Span`s to `inferred_outlives_of` predicates.

This would simplify #59789, and I suspect it has some potential in diagnostics (although we don't seem to use the predicate `Span`s much atm).
Diffstat (limited to 'src')
-rw-r--r--src/librustc/query/mod.rs2
-rw-r--r--src/librustc/ty/mod.rs2
-rw-r--r--src/librustc_lint/builtin.rs10
-rw-r--r--src/librustc_metadata/encoder.rs8
-rw-r--r--src/librustc_typeck/collect.rs15
-rw-r--r--src/librustc_typeck/outlives/explicit.rs13
-rw-r--r--src/librustc_typeck/outlives/implicit_infer.rs13
-rw-r--r--src/librustc_typeck/outlives/mod.rs19
-rw-r--r--src/librustc_typeck/outlives/utils.rs16
9 files changed, 62 insertions, 36 deletions
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index fdca6d0e17a..7cae74b59c7 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -191,7 +191,7 @@ rustc_queries! {
 
         /// Returns the inferred outlives predicates (e.g., for `struct
         /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
-        query inferred_outlives_of(_: DefId) -> &'tcx [ty::Predicate<'tcx>] {}
+        query inferred_outlives_of(_: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {}
 
         /// Maps from the `DefId` of a trait to the list of
         /// super-predicates. This is a subset of the full list of
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 260b525507e..eb673fcefcc 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1143,7 +1143,7 @@ pub struct CratePredicatesMap<'tcx> {
     /// For each struct with outlive bounds, maps to a vector of the
     /// predicate of its outlive bounds. If an item has no outlives
     /// bounds, it will have no entry.
-    pub predicates: FxHashMap<DefId, &'tcx [ty::Predicate<'tcx>]>,
+    pub predicates: FxHashMap<DefId, &'tcx [(ty::Predicate<'tcx>, Span)]>,
 }
 
 impl<'tcx> AsRef<Predicate<'tcx>> for Predicate<'tcx> {
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index ad674911e6f..7c19449f96b 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1497,10 +1497,10 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN
 
 impl ExplicitOutlivesRequirements {
     fn lifetimes_outliving_lifetime<'tcx>(
-        inferred_outlives: &'tcx [ty::Predicate<'tcx>],
+        inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)],
         index: u32,
     ) -> Vec<ty::Region<'tcx>> {
-        inferred_outlives.iter().filter_map(|pred| {
+        inferred_outlives.iter().filter_map(|(pred, _)| {
             match pred {
                 ty::Predicate::RegionOutlives(outlives) => {
                     let outlives = outlives.skip_binder();
@@ -1517,10 +1517,10 @@ impl ExplicitOutlivesRequirements {
     }
 
     fn lifetimes_outliving_type<'tcx>(
-        inferred_outlives: &'tcx [ty::Predicate<'tcx>],
+        inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)],
         index: u32,
     ) -> Vec<ty::Region<'tcx>> {
-        inferred_outlives.iter().filter_map(|pred| {
+        inferred_outlives.iter().filter_map(|(pred, _)| {
             match pred {
                 ty::Predicate::TypeOutlives(outlives) => {
                     let outlives = outlives.skip_binder();
@@ -1539,7 +1539,7 @@ impl ExplicitOutlivesRequirements {
         &self,
         param: &'tcx hir::GenericParam,
         tcx: TyCtxt<'tcx>,
-        inferred_outlives: &'tcx [ty::Predicate<'tcx>],
+        inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)],
         ty_generics: &'tcx ty::Generics,
     ) -> Vec<ty::Region<'tcx>> {
         let index = ty_generics.param_def_id_to_index[
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 0dc9f91ae00..08554c83ed5 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -197,6 +197,13 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> {
             return TAG_INVALID_SPAN.encode(self)
         }
 
+        // HACK(eddyb) there's no way to indicate which crate a Span is coming
+        // from right now, so decoding would fail to find the SourceFile if
+        // it's not local to the crate the Span is found in.
+        if self.source_file_cache.is_imported() {
+            return TAG_INVALID_SPAN.encode(self)
+        }
+
         TAG_VALID_SPAN.encode(self)?;
         span.lo.encode(self)?;
 
@@ -379,6 +386,7 @@ impl<'tcx> EncodeContext<'tcx> {
             .filter(|source_file| {
                 // No need to re-export imported source_files, as any downstream
                 // crate will import them from their original source.
+                // FIXME(eddyb) the `Span` encoding should take that into account.
                 !source_file.is_imported()
             })
             .map(|source_file| {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 2395cb7495d..a0550b5126a 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1983,19 +1983,18 @@ fn predicates_defined_on(
     );
     let inferred_outlives = tcx.inferred_outlives_of(def_id);
     if !inferred_outlives.is_empty() {
-        let span = tcx.def_span(def_id);
         debug!(
             "predicates_defined_on: inferred_outlives_of({:?}) = {:?}",
             def_id,
             inferred_outlives,
         );
-        result.predicates = tcx.arena.alloc_from_iter(
-            result.predicates.iter().copied().chain(
-                // FIXME(eddyb) use better spans - maybe add `Span`s
-                // to `inferred_outlives_of` predicates as well?
-                inferred_outlives.iter().map(|&p| (p, span)),
-            ),
-        );
+        if result.predicates.is_empty() {
+            result.predicates = inferred_outlives;
+        } else {
+            result.predicates = tcx.arena.alloc_from_iter(
+                result.predicates.iter().chain(inferred_outlives).copied(),
+            );
+        }
     }
     debug!("predicates_defined_on({:?}) = {:?}", def_id, result);
     result
diff --git a/src/librustc_typeck/outlives/explicit.rs b/src/librustc_typeck/outlives/explicit.rs
index 83194144216..21e529f33cf 100644
--- a/src/librustc_typeck/outlives/explicit.rs
+++ b/src/librustc_typeck/outlives/explicit.rs
@@ -30,11 +30,17 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
             let mut required_predicates = RequiredPredicates::default();
 
             // process predicates and convert to `RequiredPredicates` entry, see below
-            for (pred, _) in predicates.predicates {
-                match pred {
+            for &(predicate, span) in predicates.predicates {
+                match predicate {
                     ty::Predicate::TypeOutlives(predicate) => {
                         let OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder();
-                        insert_outlives_predicate(tcx, (*ty).into(), reg, &mut required_predicates)
+                        insert_outlives_predicate(
+                            tcx,
+                            (*ty).into(),
+                            reg,
+                            span,
+                            &mut required_predicates,
+                        )
                     }
 
                     ty::Predicate::RegionOutlives(predicate) => {
@@ -43,6 +49,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
                             tcx,
                             (*reg1).into(),
                             reg2,
+                            span,
                             &mut required_predicates,
                         )
                     }
diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs
index 433d04ffa64..74048b8d20c 100644
--- a/src/librustc_typeck/outlives/implicit_infer.rs
+++ b/src/librustc_typeck/outlives/implicit_infer.rs
@@ -4,6 +4,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::subst::{GenericArg, Subst, GenericArgKind};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::util::nodemap::FxHashMap;
+use syntax_pos::Span;
 
 use super::explicit::ExplicitPredicatesMap;
 use super::utils::*;
@@ -79,9 +80,11 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
                     // (struct/enum/union) there will be outlive
                     // requirements for adt_def.
                     let field_ty = self.tcx.type_of(field_def.did);
+                    let field_span = self.tcx.def_span(field_def.did);
                     insert_required_predicates_to_be_wf(
                         self.tcx,
                         field_ty,
+                        field_span,
                         self.global_inferred_outlives,
                         &mut item_required_predicates,
                         &mut self.explicit_map,
@@ -118,6 +121,7 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
 fn insert_required_predicates_to_be_wf<'tcx>(
     tcx: TyCtxt<'tcx>,
     field_ty: Ty<'tcx>,
+    field_span: Span,
     global_inferred_outlives: &FxHashMap<DefId, RequiredPredicates<'tcx>>,
     required_predicates: &mut RequiredPredicates<'tcx>,
     explicit_map: &mut ExplicitPredicatesMap<'tcx>,
@@ -130,7 +134,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
             // We also want to calculate potential predicates for the T
             ty::Ref(region, rty, _) => {
                 debug!("Ref");
-                insert_outlives_predicate(tcx, rty.into(), region, required_predicates);
+                insert_outlives_predicate(tcx, rty.into(), region, field_span, required_predicates);
             }
 
             // For each Adt (struct/enum/union) type `Foo<'a, T>`, we
@@ -158,7 +162,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                 // 'a` holds for `Foo`.
                 debug!("Adt");
                 if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did) {
-                    for unsubstituted_predicate in unsubstituted_predicates {
+                    for (unsubstituted_predicate, &span) in unsubstituted_predicates {
                         // `unsubstituted_predicate` is `U: 'b` in the
                         // example above.  So apply the substitution to
                         // get `T: 'a` (or `predicate`):
@@ -167,6 +171,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                             tcx,
                             predicate.0,
                             predicate.1,
+                            span,
                             required_predicates,
                         );
                     }
@@ -272,7 +277,7 @@ pub fn check_explicit_predicates<'tcx>(
     );
     let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id);
 
-    for outlives_predicate in explicit_predicates.iter() {
+    for (outlives_predicate, &span) in explicit_predicates {
         debug!("outlives_predicate = {:?}", &outlives_predicate);
 
         // Careful: If we are inferring the effects of a `dyn Trait<..>`
@@ -320,6 +325,6 @@ pub fn check_explicit_predicates<'tcx>(
 
         let predicate = outlives_predicate.subst(tcx, substs);
         debug!("predicate = {:?}", &predicate);
-        insert_outlives_predicate(tcx, predicate.0.into(), predicate.1, required_predicates);
+        insert_outlives_predicate(tcx, predicate.0.into(), predicate.1, span, required_predicates);
     }
 }
diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs
index cdb83eb328a..6b861656d7e 100644
--- a/src/librustc_typeck/outlives/mod.rs
+++ b/src/librustc_typeck/outlives/mod.rs
@@ -5,6 +5,7 @@ use rustc::ty::query::Providers;
 use rustc::ty::subst::GenericArgKind;
 use rustc::ty::{self, CratePredicatesMap, TyCtxt};
 use syntax::symbol::sym;
+use syntax_pos::Span;
 
 mod explicit;
 mod implicit_infer;
@@ -23,7 +24,7 @@ pub fn provide(providers: &mut Providers<'_>) {
 fn inferred_outlives_of(
     tcx: TyCtxt<'_>,
     item_def_id: DefId,
-) -> &[ty::Predicate<'_>] {
+) -> &[(ty::Predicate<'_>, Span)] {
     let id = tcx
         .hir()
         .as_local_hir_id(item_def_id)
@@ -43,7 +44,7 @@ fn inferred_outlives_of(
                 if tcx.has_attr(item_def_id, sym::rustc_outlives) {
                     let mut pred: Vec<String> = predicates
                         .iter()
-                        .map(|out_pred| match out_pred {
+                        .map(|(out_pred, _)| match out_pred {
                             ty::Predicate::RegionOutlives(p) => p.to_string(),
                             ty::Predicate::TypeOutlives(p) => p.to_string(),
                             err => bug!("unexpected predicate {:?}", err),
@@ -96,19 +97,19 @@ fn inferred_outlives_crate(
     let predicates = global_inferred_outlives
         .iter()
         .map(|(&def_id, set)| {
-            let predicates = tcx.arena.alloc_from_iter(set
+            let predicates = &*tcx.arena.alloc_from_iter(set
                 .iter()
                 .filter_map(
-                    |ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() {
+                    |(ty::OutlivesPredicate(kind1, region2), &span)| match kind1.unpack() {
                         GenericArgKind::Type(ty1) => {
-                            Some(ty::Predicate::TypeOutlives(ty::Binder::bind(
+                            Some((ty::Predicate::TypeOutlives(ty::Binder::bind(
                                 ty::OutlivesPredicate(ty1, region2)
-                            )))
+                            )), span))
                         }
                         GenericArgKind::Lifetime(region1) => {
-                            Some(ty::Predicate::RegionOutlives(
+                            Some((ty::Predicate::RegionOutlives(
                                 ty::Binder::bind(ty::OutlivesPredicate(region1, region2))
-                            ))
+                            ), span))
                         }
                         GenericArgKind::Const(_) => {
                             // Generic consts don't impose any constraints.
@@ -116,7 +117,7 @@ fn inferred_outlives_crate(
                         }
                     },
                 ));
-            (def_id, &*predicates)
+            (def_id, predicates)
         }).collect();
 
     tcx.arena.alloc(ty::CratePredicatesMap {
diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs
index d34605dc482..361116e96d0 100644
--- a/src/librustc_typeck/outlives/utils.rs
+++ b/src/librustc_typeck/outlives/utils.rs
@@ -2,12 +2,13 @@ use rustc::ty::outlives::Component;
 use rustc::ty::subst::{GenericArg, GenericArgKind};
 use rustc::ty::{self, Region, RegionKind, Ty, TyCtxt};
 use smallvec::smallvec;
-use std::collections::BTreeSet;
+use std::collections::BTreeMap;
+use syntax_pos::Span;
 
 /// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
 /// must be added to the struct header.
 pub type RequiredPredicates<'tcx> =
-    BTreeSet<ty::OutlivesPredicate<GenericArg<'tcx>, ty::Region<'tcx>>>;
+    BTreeMap<ty::OutlivesPredicate<GenericArg<'tcx>, ty::Region<'tcx>>, Span>;
 
 /// Given a requirement `T: 'a` or `'b: 'a`, deduce the
 /// outlives_component and add it to `required_predicates`
@@ -15,6 +16,7 @@ pub fn insert_outlives_predicate<'tcx>(
     tcx: TyCtxt<'tcx>,
     kind: GenericArg<'tcx>,
     outlived_region: Region<'tcx>,
+    span: Span,
     required_predicates: &mut RequiredPredicates<'tcx>,
 ) {
     // If the `'a` region is bound within the field type itself, we
@@ -53,6 +55,7 @@ pub fn insert_outlives_predicate<'tcx>(
                             tcx,
                             r.into(),
                             outlived_region,
+                            span,
                             required_predicates,
                         );
                     }
@@ -73,7 +76,8 @@ pub fn insert_outlives_predicate<'tcx>(
                         // where clause that `U: 'a`.
                         let ty: Ty<'tcx> = param_ty.to_ty(tcx);
                         required_predicates
-                            .insert(ty::OutlivesPredicate(ty.into(), outlived_region));
+                            .entry(ty::OutlivesPredicate(ty.into(), outlived_region))
+                            .or_insert(span);
                     }
 
                     Component::Projection(proj_ty) => {
@@ -88,7 +92,8 @@ pub fn insert_outlives_predicate<'tcx>(
                         // Here we want to add an explicit `where <T as Iterator>::Item: 'a`.
                         let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.item_def_id, proj_ty.substs);
                         required_predicates
-                            .insert(ty::OutlivesPredicate(ty.into(), outlived_region));
+                            .entry(ty::OutlivesPredicate(ty.into(), outlived_region))
+                            .or_insert(span);
                     }
 
                     Component::EscapingProjection(_) => {
@@ -117,7 +122,8 @@ pub fn insert_outlives_predicate<'tcx>(
             if !is_free_region(tcx, r) {
                 return;
             }
-            required_predicates.insert(ty::OutlivesPredicate(kind, outlived_region));
+            required_predicates.entry(ty::OutlivesPredicate(kind, outlived_region))
+                .or_insert(span);
         }
 
         GenericArgKind::Const(_) => {