rustc_typeck: compute better spans for inferred_outlives.
This commit is contained in:
parent
93cac9c3da
commit
1ca8da4036
5 changed files with 39 additions and 29 deletions
|
@ -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| {
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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(_) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue