rustc: add Spans to inferred_outlives_of predicates.

This commit is contained in:
Eduard-Mihai Burtescu 2019-10-18 04:24:22 +03:00
parent 8e0007f829
commit 93cac9c3da
5 changed files with 39 additions and 23 deletions

View File

@ -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

View File

@ -1136,7 +1136,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> {

View File

@ -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[

View File

@ -1970,19 +1970,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

View File

@ -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,35 @@ fn inferred_outlives_crate(
let predicates = global_inferred_outlives
.iter()
.map(|(&def_id, set)| {
let predicates = tcx.arena.alloc_from_iter(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() {
GenericArgKind::Type(ty1) => {
Some(ty::Predicate::TypeOutlives(ty::Binder::bind(
// 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) => {
Some(ty::Predicate::RegionOutlives(
// 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))
}
GenericArgKind::Const(_) => {
// Generic consts don't impose any constraints.
@ -116,7 +133,7 @@ fn inferred_outlives_crate(
}
},
));
(def_id, &*predicates)
(def_id, predicates)
}).collect();
tcx.arena.alloc(ty::CratePredicatesMap {