diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0dc9f91ae00e1..08554c83ed5bf 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -197,6 +197,13 @@ impl<'tcx> SpecializedEncoder 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/outlives/explicit.rs b/src/librustc_typeck/outlives/explicit.rs index 83194144216ee..21e529f33cfd0 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 433d04ffa64ff..74048b8d20c82 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>, 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 b2699fffc2c17..6b861656d7e2d 100644 --- a/src/librustc_typeck/outlives/mod.rs +++ b/src/librustc_typeck/outlives/mod.rs @@ -97,32 +97,16 @@ fn inferred_outlives_crate( let predicates = global_inferred_outlives .iter() .map(|(&def_id, set)| { - let def_span = tcx.def_span(def_id); - let generics = tcx.generics_of(def_id); 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) => { - // FIXME(eddyb) compute `Span`s in `implicit_infer`. - let span = match &ty1.kind { - ty::Param(p) => { - tcx.def_span(generics.type_param(p, tcx).def_id) - } - _ => def_span, - }; Some((ty::Predicate::TypeOutlives(ty::Binder::bind( ty::OutlivesPredicate(ty1, region2) )), span)) } GenericArgKind::Lifetime(region1) => { - // FIXME(eddyb) compute `Span`s in `implicit_infer`. - let span = match region1 { - ty::RegionKind::ReEarlyBound(p) => { - tcx.def_span(generics.region_param(p, tcx).def_id) - } - _ => def_span, - }; Some((ty::Predicate::RegionOutlives( ty::Binder::bind(ty::OutlivesPredicate(region1, region2)) ), span)) diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs index d34605dc482a3..361116e96d0bf 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::Region<'tcx>>>; + BTreeMap, 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 ::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(_) => {