Skip to content

Commit d5f80c8

Browse files
committedJun 18, 2019
Improve the explicit_outlives_requirements lint
* Don't use Strings to compare parameters * Extend the lint to lifetime bounds * Extend the lint to enums and unions * Use the correct span for where clauses in tuple structs * Try to early-out where possible
1 parent 36960a5 commit d5f80c8

6 files changed

+3404
-514
lines changed
 

‎src/librustc_lint/builtin.rs

Lines changed: 210 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
2424
use rustc::hir::def::{Res, DefKind};
2525
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
26-
use rustc::ty::{self, Ty};
26+
use rustc::ty::{self, Ty, TyCtxt};
2727
use rustc::{lint, util};
2828
use hir::Node;
2929
use util::nodemap::HirIdSet;
@@ -1494,58 +1494,107 @@ impl EarlyLintPass for KeywordIdents {
14941494
declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMENTS]);
14951495

14961496
impl ExplicitOutlivesRequirements {
1497-
fn collect_outlives_bound_spans(
1498-
&self,
1499-
cx: &LateContext<'_, '_>,
1500-
item_def_id: DefId,
1501-
param_name: &str,
1502-
bounds: &hir::GenericBounds,
1503-
infer_static: bool
1504-
) -> Vec<(usize, Span)> {
1505-
// For lack of a more elegant strategy for comparing the `ty::Predicate`s
1506-
// returned by this query with the params/bounds grabbed from the HIR—and
1507-
// with some regrets—we're going to covert the param/lifetime names to
1508-
// strings
1509-
let inferred_outlives = cx.tcx.inferred_outlives_of(item_def_id);
1510-
1511-
let ty_lt_names = inferred_outlives.iter().filter_map(|pred| {
1512-
let binder = match pred {
1513-
ty::Predicate::TypeOutlives(binder) => binder,
1514-
_ => { return None; }
1515-
};
1516-
let ty_outlives_pred = binder.skip_binder();
1517-
let ty_name = match ty_outlives_pred.0.sty {
1518-
ty::Param(param) => param.name.to_string(),
1519-
_ => { return None; }
1520-
};
1521-
let lt_name = match ty_outlives_pred.1 {
1522-
ty::RegionKind::ReEarlyBound(region) => {
1523-
region.name.to_string()
1524-
},
1525-
_ => { return None; }
1526-
};
1527-
Some((ty_name, lt_name))
1528-
}).collect::<Vec<_>>();
1529-
1530-
let mut bound_spans = Vec::new();
1531-
for (i, bound) in bounds.iter().enumerate() {
1532-
if let hir::GenericBound::Outlives(lifetime) = bound {
1533-
let is_static = match lifetime.name {
1534-
hir::LifetimeName::Static => true,
1535-
_ => false
1536-
};
1537-
if is_static && !infer_static {
1538-
// infer-outlives for 'static is still feature-gated (tracking issue #44493)
1539-
continue;
1497+
fn lifetimes_outliving_lifetime<'tcx>(
1498+
inferred_outlives: &'tcx [ty::Predicate<'tcx>],
1499+
index: u32,
1500+
) -> Vec<ty::Region<'tcx>> {
1501+
inferred_outlives.iter().filter_map(|pred| {
1502+
match pred {
1503+
ty::Predicate::RegionOutlives(outlives) => {
1504+
let outlives = outlives.skip_binder();
1505+
match outlives.0 {
1506+
ty::ReEarlyBound(ebr) if ebr.index == index => {
1507+
Some(outlives.1)
1508+
}
1509+
_ => None,
1510+
}
15401511
}
1512+
_ => None
1513+
}
1514+
}).collect()
1515+
}
15411516

1542-
let lt_name = &lifetime.name.ident().to_string();
1543-
if ty_lt_names.contains(&(param_name.to_owned(), lt_name.to_owned())) {
1544-
bound_spans.push((i, bound.span()));
1517+
fn lifetimes_outliving_type<'tcx>(
1518+
inferred_outlives: &'tcx [ty::Predicate<'tcx>],
1519+
index: u32,
1520+
) -> Vec<ty::Region<'tcx>> {
1521+
inferred_outlives.iter().filter_map(|pred| {
1522+
match pred {
1523+
ty::Predicate::TypeOutlives(outlives) => {
1524+
let outlives = outlives.skip_binder();
1525+
if outlives.0.is_param(index) {
1526+
Some(outlives.1)
1527+
} else {
1528+
None
1529+
}
15451530
}
1531+
_ => None
1532+
}
1533+
}).collect()
1534+
}
1535+
1536+
fn collect_outlived_lifetimes<'tcx>(
1537+
&self,
1538+
param: &'tcx hir::GenericParam,
1539+
tcx: TyCtxt<'tcx>,
1540+
inferred_outlives: &'tcx [ty::Predicate<'tcx>],
1541+
ty_generics: &'tcx ty::Generics,
1542+
) -> Vec<ty::Region<'tcx>> {
1543+
let index = ty_generics.param_def_id_to_index[
1544+
&tcx.hir().local_def_id_from_hir_id(param.hir_id)];
1545+
1546+
match param.kind {
1547+
hir::GenericParamKind::Lifetime { .. } => {
1548+
Self::lifetimes_outliving_lifetime(inferred_outlives, index)
1549+
}
1550+
hir::GenericParamKind::Type { .. } => {
1551+
Self::lifetimes_outliving_type(inferred_outlives, index)
15461552
}
1553+
hir::GenericParamKind::Const { .. } => Vec::new(),
15471554
}
1548-
bound_spans
1555+
}
1556+
1557+
1558+
fn collect_outlives_bound_spans<'tcx>(
1559+
&self,
1560+
tcx: TyCtxt<'tcx>,
1561+
bounds: &hir::GenericBounds,
1562+
inferred_outlives: &[ty::Region<'tcx>],
1563+
infer_static: bool,
1564+
) -> Vec<(usize, Span)> {
1565+
use rustc::middle::resolve_lifetime::Region;
1566+
1567+
bounds
1568+
.iter()
1569+
.enumerate()
1570+
.filter_map(|(i, bound)| {
1571+
if let hir::GenericBound::Outlives(lifetime) = bound {
1572+
let is_inferred = match tcx.named_region(lifetime.hir_id) {
1573+
Some(Region::Static) if infer_static => {
1574+
inferred_outlives.iter()
1575+
.any(|r| if let ty::ReStatic = r { true } else { false })
1576+
}
1577+
Some(Region::EarlyBound(index, ..)) => inferred_outlives
1578+
.iter()
1579+
.any(|r| {
1580+
if let ty::ReEarlyBound(ebr) = r {
1581+
ebr.index == index
1582+
} else {
1583+
false
1584+
}
1585+
}),
1586+
_ => false,
1587+
};
1588+
if is_inferred {
1589+
Some((i, bound.span()))
1590+
} else {
1591+
None
1592+
}
1593+
} else {
1594+
None
1595+
}
1596+
})
1597+
.collect()
15491598
}
15501599

15511600
fn consolidate_outlives_bound_spans(
@@ -1569,7 +1618,7 @@ impl ExplicitOutlivesRequirements {
15691618
let mut from_start = true;
15701619
for (i, bound_span) in bound_spans {
15711620
match last_merged_i {
1572-
// If the first bound is inferable, our span should also eat the trailing `+`
1621+
// If the first bound is inferable, our span should also eat the leading `+`
15731622
None if i == 0 => {
15741623
merged.push(bound_span.to(bounds[1].span().shrink_to_lo()));
15751624
last_merged_i = Some(0);
@@ -1607,26 +1656,48 @@ impl ExplicitOutlivesRequirements {
16071656

16081657
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitOutlivesRequirements {
16091658
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) {
1659+
use rustc::middle::resolve_lifetime::Region;
1660+
16101661
let infer_static = cx.tcx.features().infer_static_outlives_requirements;
16111662
let def_id = cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
1612-
if let hir::ItemKind::Struct(_, ref generics) = item.node {
1663+
if let hir::ItemKind::Struct(_, ref hir_generics)
1664+
| hir::ItemKind::Enum(_, ref hir_generics)
1665+
| hir::ItemKind::Union(_, ref hir_generics) = item.node
1666+
{
1667+
let inferred_outlives = cx.tcx.inferred_outlives_of(def_id);
1668+
if inferred_outlives.is_empty() {
1669+
return;
1670+
}
1671+
1672+
let ty_generics = cx.tcx.generics_of(def_id);
1673+
16131674
let mut bound_count = 0;
16141675
let mut lint_spans = Vec::new();
16151676

1616-
for param in &generics.params {
1617-
let param_name = match param.kind {
1618-
hir::GenericParamKind::Lifetime { .. } => continue,
1619-
hir::GenericParamKind::Type { .. } => {
1620-
match param.name {
1621-
hir::ParamName::Fresh(_) => continue,
1622-
hir::ParamName::Error => continue,
1623-
hir::ParamName::Plain(name) => name.to_string(),
1624-
}
1677+
for param in &hir_generics.params {
1678+
let has_lifetime_bounds = param.bounds.iter().any(|bound| {
1679+
if let hir::GenericBound::Outlives(_) = bound {
1680+
true
1681+
} else {
1682+
false
16251683
}
1626-
hir::GenericParamKind::Const { .. } => continue,
1627-
};
1684+
});
1685+
if !has_lifetime_bounds {
1686+
continue;
1687+
}
1688+
1689+
let relevant_lifetimes = self.collect_outlived_lifetimes(
1690+
param,
1691+
cx.tcx,
1692+
inferred_outlives,
1693+
ty_generics,
1694+
);
1695+
if relevant_lifetimes.is_empty() {
1696+
continue;
1697+
}
1698+
16281699
let bound_spans = self.collect_outlives_bound_spans(
1629-
cx, def_id, &param_name, &param.bounds, infer_static
1700+
cx.tcx, &param.bounds, &relevant_lifetimes, infer_static,
16301701
);
16311702
bound_count += bound_spans.len();
16321703
lint_spans.extend(
@@ -1638,54 +1709,92 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitOutlivesRequirements {
16381709

16391710
let mut where_lint_spans = Vec::new();
16401711
let mut dropped_predicate_count = 0;
1641-
let num_predicates = generics.where_clause.predicates.len();
1642-
for (i, where_predicate) in generics.where_clause.predicates.iter().enumerate() {
1643-
if let hir::WherePredicate::BoundPredicate(predicate) = where_predicate {
1644-
let param_name = match predicate.bounded_ty.node {
1645-
hir::TyKind::Path(ref qpath) => {
1646-
if let hir::QPath::Resolved(None, ty_param_path) = qpath {
1647-
ty_param_path.segments[0].ident.to_string()
1648-
} else {
1649-
continue;
1650-
}
1651-
},
1652-
_ => { continue; }
1653-
};
1654-
let bound_spans = self.collect_outlives_bound_spans(
1655-
cx, def_id, &param_name, &predicate.bounds, infer_static
1656-
);
1657-
bound_count += bound_spans.len();
1658-
1659-
let drop_predicate = bound_spans.len() == predicate.bounds.len();
1660-
if drop_predicate {
1661-
dropped_predicate_count += 1;
1662-
}
1663-
1664-
// If all the bounds on a predicate were inferable and there are
1665-
// further predicates, we want to eat the trailing comma
1666-
if drop_predicate && i + 1 < num_predicates {
1667-
let next_predicate_span = generics.where_clause.predicates[i+1].span();
1668-
where_lint_spans.push(
1669-
predicate.span.to(next_predicate_span.shrink_to_lo())
1670-
);
1671-
} else {
1672-
where_lint_spans.extend(
1673-
self.consolidate_outlives_bound_spans(
1674-
predicate.span.shrink_to_lo(),
1712+
let num_predicates = hir_generics.where_clause.predicates.len();
1713+
for (i, where_predicate) in hir_generics.where_clause.predicates.iter().enumerate() {
1714+
let (relevant_lifetimes, bounds, span) = match where_predicate {
1715+
hir::WherePredicate::RegionPredicate(predicate) => {
1716+
if let Some(Region::EarlyBound(index, ..))
1717+
= cx.tcx.named_region(predicate.lifetime.hir_id)
1718+
{
1719+
(
1720+
Self::lifetimes_outliving_lifetime(inferred_outlives, index),
16751721
&predicate.bounds,
1676-
bound_spans
1722+
predicate.span,
16771723
)
1678-
);
1724+
} else {
1725+
continue;
1726+
}
16791727
}
1728+
hir::WherePredicate::BoundPredicate(predicate) => {
1729+
// FIXME we can also infer bounds on associated types,
1730+
// and should check for them here.
1731+
match predicate.bounded_ty.node {
1732+
hir::TyKind::Path(hir::QPath::Resolved(
1733+
None,
1734+
ref path,
1735+
)) => if let Res::Def(DefKind::TyParam, def_id) = path.res {
1736+
let index = ty_generics.param_def_id_to_index[&def_id];
1737+
(
1738+
Self::lifetimes_outliving_type(inferred_outlives, index),
1739+
&predicate.bounds,
1740+
predicate.span,
1741+
)
1742+
} else {
1743+
continue
1744+
},
1745+
_ => { continue; }
1746+
}
1747+
}
1748+
_ => continue,
1749+
};
1750+
if relevant_lifetimes.is_empty() {
1751+
continue;
1752+
}
1753+
1754+
let bound_spans = self.collect_outlives_bound_spans(
1755+
cx.tcx, bounds, &relevant_lifetimes, infer_static,
1756+
);
1757+
bound_count += bound_spans.len();
1758+
1759+
let drop_predicate = bound_spans.len() == bounds.len();
1760+
if drop_predicate {
1761+
dropped_predicate_count += 1;
1762+
}
1763+
1764+
// If all the bounds on a predicate were inferable and there are
1765+
// further predicates, we want to eat the trailing comma
1766+
if drop_predicate && i + 1 < num_predicates {
1767+
let next_predicate_span = hir_generics.where_clause.predicates[i+1].span();
1768+
where_lint_spans.push(
1769+
span.to(next_predicate_span.shrink_to_lo())
1770+
);
1771+
} else {
1772+
where_lint_spans.extend(
1773+
self.consolidate_outlives_bound_spans(
1774+
span.shrink_to_lo(),
1775+
bounds,
1776+
bound_spans
1777+
)
1778+
);
16801779
}
16811780
}
16821781

16831782
// If all predicates are inferable, drop the entire clause
16841783
// (including the `where`)
16851784
if num_predicates > 0 && dropped_predicate_count == num_predicates {
1686-
let full_where_span = generics.span.shrink_to_hi()
1687-
.to(generics.where_clause.span()
1688-
.expect("span of (nonempty) where clause should exist"));
1785+
let where_span = hir_generics.where_clause.span()
1786+
.expect("span of (nonempty) where clause should exist");
1787+
// Extend the where clause back to the closing `>` of the
1788+
// generics, except for tuple struct, which have the `where`
1789+
// after the fields of the struct.
1790+
let full_where_span = match item.node {
1791+
hir::ItemKind::Struct(hir::VariantData::Tuple(..), _) => {
1792+
where_span
1793+
}
1794+
_ => {
1795+
hir_generics.span.shrink_to_hi().to(where_span)
1796+
}
1797+
};
16891798
lint_spans.push(
16901799
full_where_span
16911800
);
Lines changed: 335 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,368 @@
11
#![allow(unused)]
22
#![deny(explicit_outlives_requirements)]
33

4-
use std::fmt::{Debug, Display};
54

65
// These examples should live in edition-lint-infer-outlives.rs, but are split
76
// into this separate file because they can't be `rustfix`'d (and thus, can't
87
// be part of a `run-rustfix` test file) until rust-lang-nursery/rustfix#141
98
// is solved
109

11-
struct TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> {
12-
//~^ ERROR outlives requirements can be inferred
13-
tee: &'a &'b T
10+
mod structs {
11+
use std::fmt::Debug;
12+
13+
struct TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> {
14+
//~^ ERROR outlives requirements can be inferred
15+
tee: &'a &'b T
16+
}
17+
18+
struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b {
19+
//~^ ERROR outlives requirements can be inferred
20+
tee: &'a &'b T
21+
}
22+
23+
struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> {
24+
//~^ ERROR outlives requirements can be inferred
25+
tee: T,
26+
yoo: &'a &'b U
27+
}
28+
29+
struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> {
30+
//~^ ERROR outlives requirements can be inferred
31+
tee: &'a T,
32+
yoo: &'b U
33+
}
34+
35+
struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> {
36+
//~^ ERROR outlives requirements can be inferred
37+
tee: &'a T,
38+
yoo: &'b U
39+
}
40+
41+
struct TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b {
42+
//~^ ERROR outlives requirements can be inferred
43+
tee: &'a T,
44+
yoo: &'b U
45+
}
46+
47+
struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b {
48+
//~^ ERROR outlives requirements can be inferred
49+
tee: T,
50+
yoo: &'a &'b U
51+
}
52+
53+
struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug {
54+
//~^ ERROR outlives requirements can be inferred
55+
tee: &'a T,
56+
yoo: &'b U
57+
}
58+
59+
struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b {
60+
//~^ ERROR outlives requirements can be inferred
61+
tee: &'a T,
62+
yoo: &'b U
63+
}
64+
65+
struct TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug {
66+
//~^ ERROR outlives requirements can be inferred
67+
tee: &'a T,
68+
yoo: &'b U
69+
}
70+
71+
struct TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b {
72+
//~^ ERROR outlives requirements can be inferred
73+
tee: &'a T,
74+
yoo: &'b U
75+
}
76+
77+
struct BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b> {
78+
//~^ ERROR outlives requirements can be inferred
79+
tee: &'a &'b T,
80+
}
81+
82+
struct BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b> {
83+
//~^ ERROR outlives requirements can be inferred
84+
tee: &'a &'b T,
85+
}
86+
87+
struct BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b> {
88+
//~^ ERROR outlives requirements can be inferred
89+
tee: &'a &'b T
90+
}
91+
92+
struct BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where 'b: 'a, T: 'a + Debug + 'b {
93+
//~^ ERROR outlives requirements can be inferred
94+
tee: &'a &'b T
95+
}
96+
97+
struct BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b> {
98+
//~^ ERROR outlives requirements can be inferred
99+
tee: T,
100+
yoo: &'a &'b U
101+
}
102+
103+
struct BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U>
104+
where U: 'a + Debug + 'b, 'b: 'a
105+
//~^ ERROR outlives requirements can be inferred
106+
{
107+
tee: T,
108+
yoo: &'a &'b U
109+
}
14110
}
15111

16-
struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b {
112+
mod tuple_structs {
113+
use std::fmt::Debug;
114+
115+
struct TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b>(&'a &'b T);
17116
//~^ ERROR outlives requirements can be inferred
18-
tee: &'a &'b T
19-
}
20117

21-
struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> {
118+
struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T>(&'a &'b T) where T: 'a + Debug + 'b;
22119
//~^ ERROR outlives requirements can be inferred
23-
tee: T,
24-
yoo: &'a &'b U
25-
}
26120

27-
struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> {
121+
struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b>(T, &'a &'b U);
28122
//~^ ERROR outlives requirements can be inferred
29-
tee: &'a T,
30-
yoo: &'b U
31-
}
32123

33-
struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> {
124+
struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug>(&'a T, &'b U);
34125
//~^ ERROR outlives requirements can be inferred
35-
tee: &'a T,
36-
yoo: &'b U
37-
}
38126

39-
struct TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b {
127+
struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b>(&'a T, &'b U);
40128
//~^ ERROR outlives requirements can be inferred
41-
tee: &'a T,
42-
yoo: &'b U
43-
}
44129

45-
struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b {
130+
struct TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U>(&'a T, &'b U) where U: 'b;
46131
//~^ ERROR outlives requirements can be inferred
47-
tee: T,
48-
yoo: &'a &'b U
49-
}
50132

51-
struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug {
133+
struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U>(T, &'a &'b U) where U: 'a + Debug + 'b;
52134
//~^ ERROR outlives requirements can be inferred
53-
tee: &'a T,
54-
yoo: &'b U
55-
}
56135

57-
struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b {
136+
struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U>(&'a T, &'b U) where U: 'b + Debug;
58137
//~^ ERROR outlives requirements can be inferred
59-
tee: &'a T,
60-
yoo: &'b U
61-
}
62138

63-
struct TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug {
139+
struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U>(&'a T, &'b U) where U: Debug + 'b;
140+
//~^ ERROR outlives requirements can be inferred
141+
142+
struct TeeWhereAyYooWhereBeeIsDebug<'a, 'b, T, U>(&'a T, &'b U) where T: 'a, U: 'b + Debug;
143+
//~^ ERROR outlives requirements can be inferred
144+
145+
struct TeeWhereAyYooWhereIsDebugBee<'a, 'b, T, U>(&'a T, &'b U) where T: 'a, U: Debug + 'b;
146+
//~^ ERROR outlives requirements can be inferred
147+
148+
struct BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b>(&'a &'b T);
149+
//~^ ERROR outlives requirements can be inferred
150+
151+
struct BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b>(&'a &'b T);
152+
//~^ ERROR outlives requirements can be inferred
153+
154+
struct BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b>(&'a &'b T);
155+
//~^ ERROR outlives requirements can be inferred
156+
157+
struct BeeWhereAyTeeWhereAyIsDebugBee<'a, 'b, T>(&'a &'b T) where 'b: 'a, T: 'a + Debug + 'b;
64158
//~^ ERROR outlives requirements can be inferred
65-
tee: &'a T,
66-
yoo: &'b U
67-
}
68159

69-
struct TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b {
160+
struct BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b>(T, &'a &'b U);
70161
//~^ ERROR outlives requirements can be inferred
71-
tee: &'a T,
72-
yoo: &'b U
162+
163+
struct BeeWhereAyTeeYooWhereAyIsDebugBee<'a, 'b, T, U>(T, &'a &'b U)
164+
where U: 'a + Debug + 'b, 'b: 'a;
165+
//~^ ERROR outlives requirements can be inferred
166+
}
167+
168+
mod enums {
169+
use std::fmt::Debug;
170+
171+
enum TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> {
172+
//~^ ERROR outlives requirements can be inferred
173+
V { tee: &'a &'b T },
174+
}
175+
176+
enum TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b {
177+
//~^ ERROR outlives requirements can be inferred
178+
V(&'a &'b T),
179+
}
180+
181+
enum TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> {
182+
//~^ ERROR outlives requirements can be inferred
183+
V { tee: T, },
184+
W(&'a &'b U),
185+
}
186+
187+
enum TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> {
188+
//~^ ERROR outlives requirements can be inferred
189+
V { tee: &'a T, yoo: &'b U },
190+
W,
191+
}
192+
193+
enum TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> {
194+
//~^ ERROR outlives requirements can be inferred
195+
V(&'a T, &'b U),
196+
W,
197+
}
198+
199+
enum TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b {
200+
//~^ ERROR outlives requirements can be inferred
201+
V { tee: &'a T },
202+
W(&'b U),
203+
}
204+
205+
enum TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b {
206+
//~^ ERROR outlives requirements can be inferred
207+
V { tee: T, yoo: &'a &'b U },
208+
W,
209+
}
210+
211+
enum TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug {
212+
//~^ ERROR outlives requirements can be inferred
213+
V(&'a T, &'b U),
214+
W,
215+
}
216+
217+
enum TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b {
218+
//~^ ERROR outlives requirements can be inferred
219+
V { tee: &'a T },
220+
W(&'b U)
221+
}
222+
223+
enum TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug {
224+
//~^ ERROR outlives requirements can be inferred
225+
V { tee: &'a T, yoo: &'b U },
226+
W,
227+
}
228+
229+
enum TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b {
230+
//~^ ERROR outlives requirements can be inferred
231+
V(&'a T, &'b U),
232+
W,
233+
}
234+
235+
enum BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b> {
236+
//~^ ERROR outlives requirements can be inferred
237+
V { tee: &'a &'b T },
238+
}
239+
240+
enum BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b> {
241+
//~^ ERROR outlives requirements can be inferred
242+
V { tee: &'a &'b T },
243+
W,
244+
}
245+
246+
enum BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b> {
247+
//~^ ERROR outlives requirements can be inferred
248+
V { tee: &'a &'b T },
249+
}
250+
251+
enum BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where 'b: 'a, T: 'a + Debug + 'b {
252+
//~^ ERROR outlives requirements can be inferred
253+
V(&'a &'b T),
254+
}
255+
256+
enum BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b> {
257+
//~^ ERROR outlives requirements can be inferred
258+
V { tee: T },
259+
W(&'a &'b U),
260+
}
261+
262+
enum BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b, 'b: 'a {
263+
//~^ ERROR outlives requirements can be inferred
264+
V { tee: T, yoo: &'a &'b U },
265+
}
266+
}
267+
268+
mod unions {
269+
use std::fmt::Debug;
270+
271+
union TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> {
272+
//~^ ERROR outlives requirements can be inferred
273+
tee: &'a &'b T
274+
}
275+
276+
union TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b {
277+
//~^ ERROR outlives requirements can be inferred
278+
tee: &'a &'b T
279+
}
280+
281+
union TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> {
282+
//~^ ERROR outlives requirements can be inferred
283+
tee: *const T,
284+
yoo: &'a &'b U
285+
}
286+
287+
union TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> {
288+
//~^ ERROR outlives requirements can be inferred
289+
tee: &'a T,
290+
yoo: &'b U
291+
}
292+
293+
union TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> {
294+
//~^ ERROR outlives requirements can be inferred
295+
tee: &'a T,
296+
yoo: &'b U
297+
}
298+
299+
union TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b {
300+
//~^ ERROR outlives requirements can be inferred
301+
tee: &'a T,
302+
yoo: &'b U
303+
}
304+
305+
union TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b {
306+
//~^ ERROR outlives requirements can be inferred
307+
tee: *const T,
308+
yoo: &'a &'b U
309+
}
310+
311+
union TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug {
312+
//~^ ERROR outlives requirements can be inferred
313+
tee: &'a T,
314+
yoo: &'b U
315+
}
316+
317+
union TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b {
318+
//~^ ERROR outlives requirements can be inferred
319+
tee: &'a T,
320+
yoo: &'b U
321+
}
322+
323+
union TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug {
324+
//~^ ERROR outlives requirements can be inferred
325+
tee: &'a T,
326+
yoo: &'b U
327+
}
328+
329+
union TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b {
330+
//~^ ERROR outlives requirements can be inferred
331+
tee: &'a T,
332+
yoo: &'b U
333+
}
334+
335+
union BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b> {
336+
//~^ ERROR outlives requirements can be inferred
337+
tee: &'a &'b T,
338+
}
339+
340+
union BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b> {
341+
//~^ ERROR outlives requirements can be inferred
342+
tee: &'a &'b T,
343+
}
344+
345+
union BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b> {
346+
//~^ ERROR outlives requirements can be inferred
347+
tee: &'a &'b T
348+
}
349+
350+
union BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where 'b: 'a, T: 'a + Debug + 'b {
351+
//~^ ERROR outlives requirements can be inferred
352+
tee: &'a &'b T
353+
}
354+
355+
union BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b> {
356+
//~^ ERROR outlives requirements can be inferred
357+
tee: *const T,
358+
yoo: &'a &'b U
359+
}
360+
361+
union BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b, 'b: 'a {
362+
//~^ ERROR outlives requirements can be inferred
363+
tee: *const T,
364+
yoo: &'a &'b U
365+
}
73366
}
74367

75368
fn main() {}

‎src/test/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr

Lines changed: 626 additions & 56 deletions
Large diffs are not rendered by default.

‎src/test/ui/rust-2018/edition-lint-infer-outlives.fixed

Lines changed: 706 additions & 113 deletions
Large diffs are not rendered by default.

‎src/test/ui/rust-2018/edition-lint-infer-outlives.rs

Lines changed: 706 additions & 113 deletions
Large diffs are not rendered by default.

‎src/test/ui/rust-2018/edition-lint-infer-outlives.stderr

Lines changed: 821 additions & 89 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.