Skip to content

Commit 0f677c6

Browse files
committed
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).
2 parents b7176b4 + 1ca8da4 commit 0f677c6

File tree

9 files changed

+62
-36
lines changed

9 files changed

+62
-36
lines changed

src/librustc/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ rustc_queries! {
191191

192192
/// Returns the inferred outlives predicates (e.g., for `struct
193193
/// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
194-
query inferred_outlives_of(_: DefId) -> &'tcx [ty::Predicate<'tcx>] {}
194+
query inferred_outlives_of(_: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {}
195195

196196
/// Maps from the `DefId` of a trait to the list of
197197
/// super-predicates. This is a subset of the full list of

src/librustc/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1143,7 +1143,7 @@ pub struct CratePredicatesMap<'tcx> {
11431143
/// For each struct with outlive bounds, maps to a vector of the
11441144
/// predicate of its outlive bounds. If an item has no outlives
11451145
/// bounds, it will have no entry.
1146-
pub predicates: FxHashMap<DefId, &'tcx [ty::Predicate<'tcx>]>,
1146+
pub predicates: FxHashMap<DefId, &'tcx [(ty::Predicate<'tcx>, Span)]>,
11471147
}
11481148

11491149
impl<'tcx> AsRef<Predicate<'tcx>> for Predicate<'tcx> {

src/librustc_lint/builtin.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1497,10 +1497,10 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN
14971497

14981498
impl ExplicitOutlivesRequirements {
14991499
fn lifetimes_outliving_lifetime<'tcx>(
1500-
inferred_outlives: &'tcx [ty::Predicate<'tcx>],
1500+
inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)],
15011501
index: u32,
15021502
) -> Vec<ty::Region<'tcx>> {
1503-
inferred_outlives.iter().filter_map(|pred| {
1503+
inferred_outlives.iter().filter_map(|(pred, _)| {
15041504
match pred {
15051505
ty::Predicate::RegionOutlives(outlives) => {
15061506
let outlives = outlives.skip_binder();
@@ -1517,10 +1517,10 @@ impl ExplicitOutlivesRequirements {
15171517
}
15181518

15191519
fn lifetimes_outliving_type<'tcx>(
1520-
inferred_outlives: &'tcx [ty::Predicate<'tcx>],
1520+
inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)],
15211521
index: u32,
15221522
) -> Vec<ty::Region<'tcx>> {
1523-
inferred_outlives.iter().filter_map(|pred| {
1523+
inferred_outlives.iter().filter_map(|(pred, _)| {
15241524
match pred {
15251525
ty::Predicate::TypeOutlives(outlives) => {
15261526
let outlives = outlives.skip_binder();
@@ -1539,7 +1539,7 @@ impl ExplicitOutlivesRequirements {
15391539
&self,
15401540
param: &'tcx hir::GenericParam,
15411541
tcx: TyCtxt<'tcx>,
1542-
inferred_outlives: &'tcx [ty::Predicate<'tcx>],
1542+
inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)],
15431543
ty_generics: &'tcx ty::Generics,
15441544
) -> Vec<ty::Region<'tcx>> {
15451545
let index = ty_generics.param_def_id_to_index[

src/librustc_metadata/encoder.rs

+8
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,13 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> {
197197
return TAG_INVALID_SPAN.encode(self)
198198
}
199199

200+
// HACK(eddyb) there's no way to indicate which crate a Span is coming
201+
// from right now, so decoding would fail to find the SourceFile if
202+
// it's not local to the crate the Span is found in.
203+
if self.source_file_cache.is_imported() {
204+
return TAG_INVALID_SPAN.encode(self)
205+
}
206+
200207
TAG_VALID_SPAN.encode(self)?;
201208
span.lo.encode(self)?;
202209

@@ -379,6 +386,7 @@ impl<'tcx> EncodeContext<'tcx> {
379386
.filter(|source_file| {
380387
// No need to re-export imported source_files, as any downstream
381388
// crate will import them from their original source.
389+
// FIXME(eddyb) the `Span` encoding should take that into account.
382390
!source_file.is_imported()
383391
})
384392
.map(|source_file| {

src/librustc_typeck/collect.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -1983,19 +1983,18 @@ fn predicates_defined_on(
19831983
);
19841984
let inferred_outlives = tcx.inferred_outlives_of(def_id);
19851985
if !inferred_outlives.is_empty() {
1986-
let span = tcx.def_span(def_id);
19871986
debug!(
19881987
"predicates_defined_on: inferred_outlives_of({:?}) = {:?}",
19891988
def_id,
19901989
inferred_outlives,
19911990
);
1992-
result.predicates = tcx.arena.alloc_from_iter(
1993-
result.predicates.iter().copied().chain(
1994-
// FIXME(eddyb) use better spans - maybe add `Span`s
1995-
// to `inferred_outlives_of` predicates as well?
1996-
inferred_outlives.iter().map(|&p| (p, span)),
1997-
),
1998-
);
1991+
if result.predicates.is_empty() {
1992+
result.predicates = inferred_outlives;
1993+
} else {
1994+
result.predicates = tcx.arena.alloc_from_iter(
1995+
result.predicates.iter().chain(inferred_outlives).copied(),
1996+
);
1997+
}
19991998
}
20001999
debug!("predicates_defined_on({:?}) = {:?}", def_id, result);
20012000
result

src/librustc_typeck/outlives/explicit.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,17 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
3030
let mut required_predicates = RequiredPredicates::default();
3131

3232
// process predicates and convert to `RequiredPredicates` entry, see below
33-
for (pred, _) in predicates.predicates {
34-
match pred {
33+
for &(predicate, span) in predicates.predicates {
34+
match predicate {
3535
ty::Predicate::TypeOutlives(predicate) => {
3636
let OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder();
37-
insert_outlives_predicate(tcx, (*ty).into(), reg, &mut required_predicates)
37+
insert_outlives_predicate(
38+
tcx,
39+
(*ty).into(),
40+
reg,
41+
span,
42+
&mut required_predicates,
43+
)
3844
}
3945

4046
ty::Predicate::RegionOutlives(predicate) => {
@@ -43,6 +49,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
4349
tcx,
4450
(*reg1).into(),
4551
reg2,
52+
span,
4653
&mut required_predicates,
4754
)
4855
}

src/librustc_typeck/outlives/implicit_infer.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
44
use rustc::ty::subst::{GenericArg, Subst, GenericArgKind};
55
use rustc::ty::{self, Ty, TyCtxt};
66
use rustc::util::nodemap::FxHashMap;
7+
use syntax_pos::Span;
78

89
use super::explicit::ExplicitPredicatesMap;
910
use super::utils::*;
@@ -79,9 +80,11 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
7980
// (struct/enum/union) there will be outlive
8081
// requirements for adt_def.
8182
let field_ty = self.tcx.type_of(field_def.did);
83+
let field_span = self.tcx.def_span(field_def.did);
8284
insert_required_predicates_to_be_wf(
8385
self.tcx,
8486
field_ty,
87+
field_span,
8588
self.global_inferred_outlives,
8689
&mut item_required_predicates,
8790
&mut self.explicit_map,
@@ -118,6 +121,7 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
118121
fn insert_required_predicates_to_be_wf<'tcx>(
119122
tcx: TyCtxt<'tcx>,
120123
field_ty: Ty<'tcx>,
124+
field_span: Span,
121125
global_inferred_outlives: &FxHashMap<DefId, RequiredPredicates<'tcx>>,
122126
required_predicates: &mut RequiredPredicates<'tcx>,
123127
explicit_map: &mut ExplicitPredicatesMap<'tcx>,
@@ -130,7 +134,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
130134
// We also want to calculate potential predicates for the T
131135
ty::Ref(region, rty, _) => {
132136
debug!("Ref");
133-
insert_outlives_predicate(tcx, rty.into(), region, required_predicates);
137+
insert_outlives_predicate(tcx, rty.into(), region, field_span, required_predicates);
134138
}
135139

136140
// For each Adt (struct/enum/union) type `Foo<'a, T>`, we
@@ -158,7 +162,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
158162
// 'a` holds for `Foo`.
159163
debug!("Adt");
160164
if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did) {
161-
for unsubstituted_predicate in unsubstituted_predicates {
165+
for (unsubstituted_predicate, &span) in unsubstituted_predicates {
162166
// `unsubstituted_predicate` is `U: 'b` in the
163167
// example above. So apply the substitution to
164168
// get `T: 'a` (or `predicate`):
@@ -167,6 +171,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
167171
tcx,
168172
predicate.0,
169173
predicate.1,
174+
span,
170175
required_predicates,
171176
);
172177
}
@@ -272,7 +277,7 @@ pub fn check_explicit_predicates<'tcx>(
272277
);
273278
let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id);
274279

275-
for outlives_predicate in explicit_predicates.iter() {
280+
for (outlives_predicate, &span) in explicit_predicates {
276281
debug!("outlives_predicate = {:?}", &outlives_predicate);
277282

278283
// Careful: If we are inferring the effects of a `dyn Trait<..>`
@@ -320,6 +325,6 @@ pub fn check_explicit_predicates<'tcx>(
320325

321326
let predicate = outlives_predicate.subst(tcx, substs);
322327
debug!("predicate = {:?}", &predicate);
323-
insert_outlives_predicate(tcx, predicate.0.into(), predicate.1, required_predicates);
328+
insert_outlives_predicate(tcx, predicate.0.into(), predicate.1, span, required_predicates);
324329
}
325330
}

src/librustc_typeck/outlives/mod.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc::ty::query::Providers;
55
use rustc::ty::subst::GenericArgKind;
66
use rustc::ty::{self, CratePredicatesMap, TyCtxt};
77
use syntax::symbol::sym;
8+
use syntax_pos::Span;
89

910
mod explicit;
1011
mod implicit_infer;
@@ -23,7 +24,7 @@ pub fn provide(providers: &mut Providers<'_>) {
2324
fn inferred_outlives_of(
2425
tcx: TyCtxt<'_>,
2526
item_def_id: DefId,
26-
) -> &[ty::Predicate<'_>] {
27+
) -> &[(ty::Predicate<'_>, Span)] {
2728
let id = tcx
2829
.hir()
2930
.as_local_hir_id(item_def_id)
@@ -43,7 +44,7 @@ fn inferred_outlives_of(
4344
if tcx.has_attr(item_def_id, sym::rustc_outlives) {
4445
let mut pred: Vec<String> = predicates
4546
.iter()
46-
.map(|out_pred| match out_pred {
47+
.map(|(out_pred, _)| match out_pred {
4748
ty::Predicate::RegionOutlives(p) => p.to_string(),
4849
ty::Predicate::TypeOutlives(p) => p.to_string(),
4950
err => bug!("unexpected predicate {:?}", err),
@@ -96,27 +97,27 @@ fn inferred_outlives_crate(
9697
let predicates = global_inferred_outlives
9798
.iter()
9899
.map(|(&def_id, set)| {
99-
let predicates = tcx.arena.alloc_from_iter(set
100+
let predicates = &*tcx.arena.alloc_from_iter(set
100101
.iter()
101102
.filter_map(
102-
|ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() {
103+
|(ty::OutlivesPredicate(kind1, region2), &span)| match kind1.unpack() {
103104
GenericArgKind::Type(ty1) => {
104-
Some(ty::Predicate::TypeOutlives(ty::Binder::bind(
105+
Some((ty::Predicate::TypeOutlives(ty::Binder::bind(
105106
ty::OutlivesPredicate(ty1, region2)
106-
)))
107+
)), span))
107108
}
108109
GenericArgKind::Lifetime(region1) => {
109-
Some(ty::Predicate::RegionOutlives(
110+
Some((ty::Predicate::RegionOutlives(
110111
ty::Binder::bind(ty::OutlivesPredicate(region1, region2))
111-
))
112+
), span))
112113
}
113114
GenericArgKind::Const(_) => {
114115
// Generic consts don't impose any constraints.
115116
None
116117
}
117118
},
118119
));
119-
(def_id, &*predicates)
120+
(def_id, predicates)
120121
}).collect();
121122

122123
tcx.arena.alloc(ty::CratePredicatesMap {

src/librustc_typeck/outlives/utils.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,21 @@ use rustc::ty::outlives::Component;
22
use rustc::ty::subst::{GenericArg, GenericArgKind};
33
use rustc::ty::{self, Region, RegionKind, Ty, TyCtxt};
44
use smallvec::smallvec;
5-
use std::collections::BTreeSet;
5+
use std::collections::BTreeMap;
6+
use syntax_pos::Span;
67

78
/// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
89
/// must be added to the struct header.
910
pub type RequiredPredicates<'tcx> =
10-
BTreeSet<ty::OutlivesPredicate<GenericArg<'tcx>, ty::Region<'tcx>>>;
11+
BTreeMap<ty::OutlivesPredicate<GenericArg<'tcx>, ty::Region<'tcx>>, Span>;
1112

1213
/// Given a requirement `T: 'a` or `'b: 'a`, deduce the
1314
/// outlives_component and add it to `required_predicates`
1415
pub fn insert_outlives_predicate<'tcx>(
1516
tcx: TyCtxt<'tcx>,
1617
kind: GenericArg<'tcx>,
1718
outlived_region: Region<'tcx>,
19+
span: Span,
1820
required_predicates: &mut RequiredPredicates<'tcx>,
1921
) {
2022
// If the `'a` region is bound within the field type itself, we
@@ -53,6 +55,7 @@ pub fn insert_outlives_predicate<'tcx>(
5355
tcx,
5456
r.into(),
5557
outlived_region,
58+
span,
5659
required_predicates,
5760
);
5861
}
@@ -73,7 +76,8 @@ pub fn insert_outlives_predicate<'tcx>(
7376
// where clause that `U: 'a`.
7477
let ty: Ty<'tcx> = param_ty.to_ty(tcx);
7578
required_predicates
76-
.insert(ty::OutlivesPredicate(ty.into(), outlived_region));
79+
.entry(ty::OutlivesPredicate(ty.into(), outlived_region))
80+
.or_insert(span);
7781
}
7882

7983
Component::Projection(proj_ty) => {
@@ -88,7 +92,8 @@ pub fn insert_outlives_predicate<'tcx>(
8892
// Here we want to add an explicit `where <T as Iterator>::Item: 'a`.
8993
let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.item_def_id, proj_ty.substs);
9094
required_predicates
91-
.insert(ty::OutlivesPredicate(ty.into(), outlived_region));
95+
.entry(ty::OutlivesPredicate(ty.into(), outlived_region))
96+
.or_insert(span);
9297
}
9398

9499
Component::EscapingProjection(_) => {
@@ -117,7 +122,8 @@ pub fn insert_outlives_predicate<'tcx>(
117122
if !is_free_region(tcx, r) {
118123
return;
119124
}
120-
required_predicates.insert(ty::OutlivesPredicate(kind, outlived_region));
125+
required_predicates.entry(ty::OutlivesPredicate(kind, outlived_region))
126+
.or_insert(span);
121127
}
122128

123129
GenericArgKind::Const(_) => {

0 commit comments

Comments
 (0)