Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a0a6e43

Browse files
committedSep 29, 2018
Auto merge of #53013 - zackmdavis:infer_outlints, r=nikomatsakis
in which inferable outlives-requirements are linted RFC 2093 (tracking issue #44493) lets us leave off these commonsensically inferable `T: 'a` outlives requirements. (A separate feature-gate was split off for the case of 'static lifetimes, for which questions still remain.) Detecting these was requested as an idioms-2018 lint. Resolves #52042, an item under the fabulous metaïssue #52047. It's plausible that this shouldn't land until after `infer_outlives_requirements` has been stabilized ([final comment period started](#44493 (comment)) 4 days ago), but I think there's also a strong case to not-wait in order to maximize the time that [Edition Preview 2](https://internals.rust-lang.org/t/rust-2018-release-schedule-and-extended-beta/8076) users have to kick at it. (It's allow by default, so there's no impact unless you explicitly turn it or the rust-2018-idioms group up to `warn` or higher.) Questions— * Is `explicit-outlives-requirements` a good name? (I chose it as an [RFC 344](https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#lints)-compliant "inversion" of the feature-gate name, `infer_outlives_requirements`, but I could imagine someone arguing that the word `struct` should be part of the name somewhere, for specificity.) * Are there any false-positives or false-negatives? @nikomatsakis [said that](#52042 (comment)) getting this right would be "fairly hard", which makes me nervous that I'm missing something. The UI test in the initial submission of this pull request just exercises the examples [given in the Edition Guide](https://rust-lang-nursery.github.io/edition-guide/2018/transitioning/ownership-and-lifetimes/struct-inference.html). ![infer_outlints](https://user-images.githubusercontent.com/1076988/43625740-6bf43dca-96a3-11e8-9dcf-793ac83d424d.png) r? @alexcrichton
2 parents 63d51e8 + 032d97f commit a0a6e43

9 files changed

+1095
-1
lines changed
 

‎src/librustc/lint/builtin.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,12 @@ declare_lint! {
338338
cannot be referred to by absolute paths"
339339
}
340340

341+
declare_lint! {
342+
pub EXPLICIT_OUTLIVES_REQUIREMENTS,
343+
Allow,
344+
"outlives requirements can be inferred"
345+
}
346+
341347
/// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`.
342348
pub mod parser {
343349
declare_lint! {

‎src/librustc_lint/builtin.rs

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,3 +1999,233 @@ impl EarlyLintPass for KeywordIdents {
19991999
lint.emit()
20002000
}
20012001
}
2002+
2003+
2004+
pub struct ExplicitOutlivesRequirements;
2005+
2006+
impl LintPass for ExplicitOutlivesRequirements {
2007+
fn get_lints(&self) -> LintArray {
2008+
lint_array![EXPLICIT_OUTLIVES_REQUIREMENTS]
2009+
}
2010+
}
2011+
2012+
impl ExplicitOutlivesRequirements {
2013+
fn collect_outlives_bound_spans(
2014+
&self,
2015+
cx: &LateContext,
2016+
item_def_id: DefId,
2017+
param_name: &str,
2018+
bounds: &hir::GenericBounds,
2019+
infer_static: bool
2020+
) -> Vec<(usize, Span)> {
2021+
// For lack of a more elegant strategy for comparing the `ty::Predicate`s
2022+
// returned by this query with the params/bounds grabbed from the HIR—and
2023+
// with some regrets—we're going to covert the param/lifetime names to
2024+
// strings
2025+
let inferred_outlives = cx.tcx.inferred_outlives_of(item_def_id);
2026+
2027+
let ty_lt_names = inferred_outlives.iter().filter_map(|pred| {
2028+
let binder = match pred {
2029+
ty::Predicate::TypeOutlives(binder) => binder,
2030+
_ => { return None; }
2031+
};
2032+
let ty_outlives_pred = binder.skip_binder();
2033+
let ty_name = match ty_outlives_pred.0.sty {
2034+
ty::Param(param) => param.name.to_string(),
2035+
_ => { return None; }
2036+
};
2037+
let lt_name = match ty_outlives_pred.1 {
2038+
ty::RegionKind::ReEarlyBound(region) => {
2039+
region.name.to_string()
2040+
},
2041+
_ => { return None; }
2042+
};
2043+
Some((ty_name, lt_name))
2044+
}).collect::<Vec<_>>();
2045+
2046+
let mut bound_spans = Vec::new();
2047+
for (i, bound) in bounds.iter().enumerate() {
2048+
if let hir::GenericBound::Outlives(lifetime) = bound {
2049+
let is_static = match lifetime.name {
2050+
hir::LifetimeName::Static => true,
2051+
_ => false
2052+
};
2053+
if is_static && !infer_static {
2054+
// infer-outlives for 'static is still feature-gated (tracking issue #44493)
2055+
continue;
2056+
}
2057+
2058+
let lt_name = &lifetime.name.ident().to_string();
2059+
if ty_lt_names.contains(&(param_name.to_owned(), lt_name.to_owned())) {
2060+
bound_spans.push((i, bound.span()));
2061+
}
2062+
}
2063+
}
2064+
bound_spans
2065+
}
2066+
2067+
fn consolidate_outlives_bound_spans(
2068+
&self,
2069+
lo: Span,
2070+
bounds: &hir::GenericBounds,
2071+
bound_spans: Vec<(usize, Span)>
2072+
) -> Vec<Span> {
2073+
if bounds.is_empty() {
2074+
return Vec::new();
2075+
}
2076+
if bound_spans.len() == bounds.len() {
2077+
let (_, last_bound_span) = bound_spans[bound_spans.len()-1];
2078+
// If all bounds are inferable, we want to delete the colon, so
2079+
// start from just after the parameter (span passed as argument)
2080+
vec![lo.to(last_bound_span)]
2081+
} else {
2082+
let mut merged = Vec::new();
2083+
let mut last_merged_i = None;
2084+
2085+
let mut from_start = true;
2086+
for (i, bound_span) in bound_spans {
2087+
match last_merged_i {
2088+
// If the first bound is inferable, our span should also eat the trailing `+`
2089+
None if i == 0 => {
2090+
merged.push(bound_span.to(bounds[1].span().shrink_to_lo()));
2091+
last_merged_i = Some(0);
2092+
},
2093+
// If consecutive bounds are inferable, merge their spans
2094+
Some(h) if i == h+1 => {
2095+
if let Some(tail) = merged.last_mut() {
2096+
// Also eat the trailing `+` if the first
2097+
// more-than-one bound is inferable
2098+
let to_span = if from_start && i < bounds.len() {
2099+
bounds[i+1].span().shrink_to_lo()
2100+
} else {
2101+
bound_span
2102+
};
2103+
*tail = tail.to(to_span);
2104+
last_merged_i = Some(i);
2105+
} else {
2106+
bug!("another bound-span visited earlier");
2107+
}
2108+
},
2109+
_ => {
2110+
// When we find a non-inferable bound, subsequent inferable bounds
2111+
// won't be consecutive from the start (and we'll eat the leading
2112+
// `+` rather than the trailing one)
2113+
from_start = false;
2114+
merged.push(bounds[i-1].span().shrink_to_hi().to(bound_span));
2115+
last_merged_i = Some(i);
2116+
}
2117+
}
2118+
}
2119+
merged
2120+
}
2121+
}
2122+
}
2123+
2124+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitOutlivesRequirements {
2125+
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) {
2126+
let infer_static = cx.tcx.features().infer_static_outlives_requirements;
2127+
let def_id = cx.tcx.hir.local_def_id(item.id);
2128+
if let hir::ItemKind::Struct(_, ref generics) = item.node {
2129+
let mut bound_count = 0;
2130+
let mut lint_spans = Vec::new();
2131+
2132+
for param in &generics.params {
2133+
let param_name = match param.kind {
2134+
hir::GenericParamKind::Lifetime { .. } => { continue; },
2135+
hir::GenericParamKind::Type { .. } => {
2136+
match param.name {
2137+
hir::ParamName::Fresh(_) => { continue; },
2138+
hir::ParamName::Plain(name) => name.to_string()
2139+
}
2140+
}
2141+
};
2142+
let bound_spans = self.collect_outlives_bound_spans(
2143+
cx, def_id, &param_name, &param.bounds, infer_static
2144+
);
2145+
bound_count += bound_spans.len();
2146+
lint_spans.extend(
2147+
self.consolidate_outlives_bound_spans(
2148+
param.span.shrink_to_hi(), &param.bounds, bound_spans
2149+
)
2150+
);
2151+
}
2152+
2153+
let mut where_lint_spans = Vec::new();
2154+
let mut dropped_predicate_count = 0;
2155+
let num_predicates = generics.where_clause.predicates.len();
2156+
for (i, where_predicate) in generics.where_clause.predicates.iter().enumerate() {
2157+
if let hir::WherePredicate::BoundPredicate(predicate) = where_predicate {
2158+
let param_name = match predicate.bounded_ty.node {
2159+
hir::TyKind::Path(ref qpath) => {
2160+
if let hir::QPath::Resolved(None, ty_param_path) = qpath {
2161+
ty_param_path.segments[0].ident.to_string()
2162+
} else {
2163+
continue;
2164+
}
2165+
},
2166+
_ => { continue; }
2167+
};
2168+
let bound_spans = self.collect_outlives_bound_spans(
2169+
cx, def_id, &param_name, &predicate.bounds, infer_static
2170+
);
2171+
bound_count += bound_spans.len();
2172+
2173+
let drop_predicate = bound_spans.len() == predicate.bounds.len();
2174+
if drop_predicate {
2175+
dropped_predicate_count += 1;
2176+
}
2177+
2178+
// If all the bounds on a predicate were inferable and there are
2179+
// further predicates, we want to eat the trailing comma
2180+
if drop_predicate && i + 1 < num_predicates {
2181+
let next_predicate_span = generics.where_clause.predicates[i+1].span();
2182+
where_lint_spans.push(
2183+
predicate.span.to(next_predicate_span.shrink_to_lo())
2184+
);
2185+
} else {
2186+
where_lint_spans.extend(
2187+
self.consolidate_outlives_bound_spans(
2188+
predicate.span.shrink_to_lo(),
2189+
&predicate.bounds,
2190+
bound_spans
2191+
)
2192+
);
2193+
}
2194+
}
2195+
}
2196+
2197+
// If all predicates are inferable, drop the entire clause
2198+
// (including the `where`)
2199+
if num_predicates > 0 && dropped_predicate_count == num_predicates {
2200+
let full_where_span = generics.span.shrink_to_hi()
2201+
.to(generics.where_clause.span()
2202+
.expect("span of (nonempty) where clause should exist"));
2203+
lint_spans.push(
2204+
full_where_span
2205+
);
2206+
} else {
2207+
lint_spans.extend(where_lint_spans);
2208+
}
2209+
2210+
if !lint_spans.is_empty() {
2211+
let mut err = cx.struct_span_lint(
2212+
EXPLICIT_OUTLIVES_REQUIREMENTS,
2213+
lint_spans.clone(),
2214+
"outlives requirements can be inferred"
2215+
);
2216+
err.multipart_suggestion_with_applicability(
2217+
if bound_count == 1 {
2218+
"remove this bound"
2219+
} else {
2220+
"remove these bounds"
2221+
},
2222+
lint_spans.into_iter().map(|span| (span, "".to_owned())).collect::<Vec<_>>(),
2223+
Applicability::MachineApplicable
2224+
);
2225+
err.emit();
2226+
}
2227+
2228+
}
2229+
}
2230+
2231+
}

‎src/librustc_lint/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use rustc::lint::builtin::{
4848
BARE_TRAIT_OBJECTS,
4949
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
5050
ELIDED_LIFETIMES_IN_PATHS,
51+
EXPLICIT_OUTLIVES_REQUIREMENTS,
5152
parser::QUESTION_MARK_MACRO_SEP
5253
};
5354
use rustc::session;
@@ -157,6 +158,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
157158
TypeLimits: TypeLimits::new(),
158159
MissingDoc: MissingDoc::new(),
159160
MissingDebugImplementations: MissingDebugImplementations::new(),
161+
ExplicitOutlivesRequirements: ExplicitOutlivesRequirements,
160162
]], ['tcx]);
161163

162164
store.register_late_pass(sess, false, box BuiltinCombinedLateLintPass::new());
@@ -199,7 +201,8 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
199201
BARE_TRAIT_OBJECTS,
200202
UNUSED_EXTERN_CRATES,
201203
ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
202-
ELIDED_LIFETIMES_IN_PATHS
204+
ELIDED_LIFETIMES_IN_PATHS,
205+
EXPLICIT_OUTLIVES_REQUIREMENTS
203206

204207
// FIXME(#52665, #47816) not always applicable and not all
205208
// macros are ready for this yet.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(unused)]
12+
#![deny(explicit_outlives_requirements)]
13+
14+
use std::fmt::{Debug, Display};
15+
16+
// These examples should live in edition-lint-infer-outlives.rs, but are split
17+
// into this separate file because they can't be `rustfix`'d (and thus, can't
18+
// be part of a `run-rustfix` test file) until rust-lang-nursery/rustfix#141
19+
// is solved
20+
21+
struct TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> {
22+
//~^ ERROR outlives requirements can be inferred
23+
tee: &'a &'b T
24+
}
25+
26+
struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b {
27+
//~^ ERROR outlives requirements can be inferred
28+
tee: &'a &'b T
29+
}
30+
31+
struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> {
32+
//~^ ERROR outlives requirements can be inferred
33+
tee: T,
34+
yoo: &'a &'b U
35+
}
36+
37+
struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> {
38+
//~^ ERROR outlives requirements can be inferred
39+
tee: &'a T,
40+
yoo: &'b U
41+
}
42+
43+
struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> {
44+
//~^ ERROR outlives requirements can be inferred
45+
tee: &'a T,
46+
yoo: &'b U
47+
}
48+
49+
struct TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b {
50+
//~^ ERROR outlives requirements can be inferred
51+
tee: &'a T,
52+
yoo: &'b U
53+
}
54+
55+
struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b {
56+
//~^ ERROR outlives requirements can be inferred
57+
tee: T,
58+
yoo: &'a &'b U
59+
}
60+
61+
struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug {
62+
//~^ ERROR outlives requirements can be inferred
63+
tee: &'a T,
64+
yoo: &'b U
65+
}
66+
67+
struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b {
68+
//~^ ERROR outlives requirements can be inferred
69+
tee: &'a T,
70+
yoo: &'b U
71+
}
72+
73+
struct TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug {
74+
//~^ ERROR outlives requirements can be inferred
75+
tee: &'a T,
76+
yoo: &'b U
77+
}
78+
79+
struct TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b {
80+
//~^ ERROR outlives requirements can be inferred
81+
tee: &'a T,
82+
yoo: &'b U
83+
}
84+
85+
fn main() {}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
error: outlives requirements can be inferred
2+
--> $DIR/edition-lint-infer-outlives-multispan.rs:21:43
3+
|
4+
LL | struct TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> {
5+
| ^^^^^ ^^^^^
6+
|
7+
note: lint level defined here
8+
--> $DIR/edition-lint-infer-outlives-multispan.rs:12:9
9+
|
10+
LL | #![deny(explicit_outlives_requirements)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
help: remove these bounds
13+
|
14+
LL | struct TeeOutlivesAyIsDebugBee<'a, 'b, T: Debug> {
15+
| -- --
16+
17+
error: outlives requirements can be inferred
18+
--> $DIR/edition-lint-infer-outlives-multispan.rs:26:57
19+
|
20+
LL | struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b {
21+
| ^^^^^ ^^^^^
22+
help: remove these bounds
23+
|
24+
LL | struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: Debug {
25+
| -- --
26+
27+
error: outlives requirements can be inferred
28+
--> $DIR/edition-lint-infer-outlives-multispan.rs:31:49
29+
|
30+
LL | struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> {
31+
| ^^^^^ ^^^^^
32+
help: remove these bounds
33+
|
34+
LL | struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: Debug> {
35+
| -- --
36+
37+
error: outlives requirements can be inferred
38+
--> $DIR/edition-lint-infer-outlives-multispan.rs:37:44
39+
|
40+
LL | struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> {
41+
| ^^^^ ^^^^^
42+
help: remove these bounds
43+
|
44+
LL | struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T, U: Debug> {
45+
| -- --
46+
47+
error: outlives requirements can be inferred
48+
--> $DIR/edition-lint-infer-outlives-multispan.rs:43:44
49+
|
50+
LL | struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> {
51+
| ^^^^ ^^^^^
52+
help: remove these bounds
53+
|
54+
LL | struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T, U: Debug> {
55+
| -- --
56+
57+
error: outlives requirements can be inferred
58+
--> $DIR/edition-lint-infer-outlives-multispan.rs:49:42
59+
|
60+
LL | struct TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b {
61+
| ^^^^ ^^^^^^^^^^^^
62+
help: remove these bounds
63+
|
64+
LL | struct TeeOutlivesAyYooWhereBee<'a, 'b, T, U> {
65+
| -- --
66+
67+
error: outlives requirements can be inferred
68+
--> $DIR/edition-lint-infer-outlives-multispan.rs:55:63
69+
|
70+
LL | struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b {
71+
| ^^^^^ ^^^^^
72+
help: remove these bounds
73+
|
74+
LL | struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: Debug {
75+
| -- --
76+
77+
error: outlives requirements can be inferred
78+
--> $DIR/edition-lint-infer-outlives-multispan.rs:61:49
79+
|
80+
LL | struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug {
81+
| ^^^^ ^^^^^
82+
help: remove these bounds
83+
|
84+
LL | struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where U: Debug {
85+
| -- --
86+
87+
error: outlives requirements can be inferred
88+
--> $DIR/edition-lint-infer-outlives-multispan.rs:67:49
89+
|
90+
LL | struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b {
91+
| ^^^^ ^^^^^
92+
help: remove these bounds
93+
|
94+
LL | struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where U: Debug {
95+
| -- --
96+
97+
error: outlives requirements can be inferred
98+
--> $DIR/edition-lint-infer-outlives-multispan.rs:73:65
99+
|
100+
LL | struct TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug {
101+
| ^^^^^^^ ^^^^^
102+
help: remove these bounds
103+
|
104+
LL | struct TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where U: Debug {
105+
| -- --
106+
107+
error: outlives requirements can be inferred
108+
--> $DIR/edition-lint-infer-outlives-multispan.rs:79:65
109+
|
110+
LL | struct TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b {
111+
| ^^^^^^^ ^^^^^
112+
help: remove these bounds
113+
|
114+
LL | struct TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where U: Debug {
115+
| -- --
116+
117+
error: aborting due to 11 previous errors
118+
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// run-rustfix
12+
13+
#![allow(unused)]
14+
#![deny(explicit_outlives_requirements)]
15+
16+
use std::fmt::{Debug, Display};
17+
18+
19+
// Programmatically generated examples!
20+
//
21+
// Exercise outlives bounds for each of the following parameter/position
22+
// combinations—
23+
//
24+
// • one generic parameter (T) bound inline
25+
// • one parameter (T) with a where clause
26+
// • two parameters (T and U), both bound inline
27+
// • two paramters (T and U), one bound inline, one with a where clause
28+
// • two parameters (T and U), both with where clauses
29+
//
30+
// —and for every permutation of 0, 1, or 2 lifetimes to outlive and 0 or 1
31+
// trait bounds distributed among said parameters (subject to no where clause
32+
// being empty and the struct having at least one lifetime).
33+
34+
35+
struct TeeOutlivesAy<'a, T> {
36+
//~^ ERROR outlives requirements can be inferred
37+
tee: &'a T
38+
}
39+
40+
struct TeeOutlivesAyIsDebug<'a, T: Debug> {
41+
//~^ ERROR outlives requirements can be inferred
42+
tee: &'a T
43+
}
44+
45+
struct TeeIsDebugOutlivesAy<'a, T: Debug> {
46+
//~^ ERROR outlives requirements can be inferred
47+
tee: &'a T
48+
}
49+
50+
struct TeeOutlivesAyBee<'a, 'b, T> {
51+
//~^ ERROR outlives requirements can be inferred
52+
tee: &'a &'b T
53+
}
54+
55+
struct TeeOutlivesAyBeeIsDebug<'a, 'b, T: Debug> {
56+
//~^ ERROR outlives requirements can be inferred
57+
tee: &'a &'b T
58+
}
59+
60+
struct TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug> {
61+
//~^ ERROR outlives requirements can be inferred
62+
tee: &'a &'b T
63+
}
64+
65+
struct TeeWhereOutlivesAy<'a, T> {
66+
//~^ ERROR outlives requirements can be inferred
67+
tee: &'a T
68+
}
69+
70+
struct TeeWhereOutlivesAyIsDebug<'a, T> where T: Debug {
71+
//~^ ERROR outlives requirements can be inferred
72+
tee: &'a T
73+
}
74+
75+
struct TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug {
76+
//~^ ERROR outlives requirements can be inferred
77+
tee: &'a T
78+
}
79+
80+
struct TeeWhereOutlivesAyBee<'a, 'b, T> {
81+
//~^ ERROR outlives requirements can be inferred
82+
tee: &'a &'b T
83+
}
84+
85+
struct TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: Debug {
86+
//~^ ERROR outlives requirements can be inferred
87+
tee: &'a &'b T
88+
}
89+
90+
struct TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug {
91+
//~^ ERROR outlives requirements can be inferred
92+
tee: &'a &'b T
93+
}
94+
95+
struct TeeYooOutlivesAy<'a, T, U> {
96+
//~^ ERROR outlives requirements can be inferred
97+
tee: T,
98+
yoo: &'a U
99+
}
100+
101+
struct TeeYooOutlivesAyIsDebug<'a, T, U: Debug> {
102+
//~^ ERROR outlives requirements can be inferred
103+
tee: T,
104+
yoo: &'a U
105+
}
106+
107+
struct TeeYooIsDebugOutlivesAy<'a, T, U: Debug> {
108+
//~^ ERROR outlives requirements can be inferred
109+
tee: T,
110+
yoo: &'a U
111+
}
112+
113+
struct TeeOutlivesAyYooIsDebug<'a, T, U: Debug> {
114+
//~^ ERROR outlives requirements can be inferred
115+
tee: &'a T,
116+
yoo: U
117+
}
118+
119+
struct TeeYooOutlivesAyBee<'a, 'b, T, U> {
120+
//~^ ERROR outlives requirements can be inferred
121+
tee: T,
122+
yoo: &'a &'b U
123+
}
124+
125+
struct TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: Debug> {
126+
//~^ ERROR outlives requirements can be inferred
127+
tee: T,
128+
yoo: &'a &'b U
129+
}
130+
131+
struct TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug> {
132+
//~^ ERROR outlives requirements can be inferred
133+
tee: T,
134+
yoo: &'a &'b U
135+
}
136+
137+
struct TeeOutlivesAyBeeYooIsDebug<'a, 'b, T, U: Debug> {
138+
//~^ ERROR outlives requirements can be inferred
139+
tee: &'a &'b T,
140+
yoo: U
141+
}
142+
143+
struct TeeYooWhereOutlivesAy<'a, T, U> {
144+
//~^ ERROR outlives requirements can be inferred
145+
tee: T,
146+
yoo: &'a U
147+
}
148+
149+
struct TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: Debug {
150+
//~^ ERROR outlives requirements can be inferred
151+
tee: T,
152+
yoo: &'a U
153+
}
154+
155+
struct TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug {
156+
//~^ ERROR outlives requirements can be inferred
157+
tee: T,
158+
yoo: &'a U
159+
}
160+
161+
struct TeeOutlivesAyYooWhereIsDebug<'a, T, U> where U: Debug {
162+
//~^ ERROR outlives requirements can be inferred
163+
tee: &'a T,
164+
yoo: U
165+
}
166+
167+
struct TeeYooWhereOutlivesAyBee<'a, 'b, T, U> {
168+
//~^ ERROR outlives requirements can be inferred
169+
tee: T,
170+
yoo: &'a &'b U
171+
}
172+
173+
struct TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: Debug {
174+
//~^ ERROR outlives requirements can be inferred
175+
tee: T,
176+
yoo: &'a &'b U
177+
}
178+
179+
struct TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug {
180+
//~^ ERROR outlives requirements can be inferred
181+
tee: T,
182+
yoo: &'a &'b U
183+
}
184+
185+
struct TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where U: Debug {
186+
//~^ ERROR outlives requirements can be inferred
187+
tee: &'a &'b T,
188+
yoo: U
189+
}
190+
191+
struct TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where U: Debug {
192+
//~^ ERROR outlives requirements can be inferred
193+
tee: &'a T,
194+
yoo: U
195+
}
196+
197+
struct TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where U: Debug {
198+
//~^ ERROR outlives requirements can be inferred
199+
tee: &'a &'b T,
200+
yoo: U
201+
}
202+
203+
204+
// But outlives inference for 'static lifetimes is under a separate
205+
// feature-gate for now
206+
// (https://github.com/rust-lang/rust/issues/44493#issuecomment-407846046).
207+
struct StaticRef<T: 'static> {
208+
field: &'static T
209+
}
210+
211+
212+
fn main() {}
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// run-rustfix
12+
13+
#![allow(unused)]
14+
#![deny(explicit_outlives_requirements)]
15+
16+
use std::fmt::{Debug, Display};
17+
18+
19+
// Programmatically generated examples!
20+
//
21+
// Exercise outlives bounds for each of the following parameter/position
22+
// combinations—
23+
//
24+
// • one generic parameter (T) bound inline
25+
// • one parameter (T) with a where clause
26+
// • two parameters (T and U), both bound inline
27+
// • two paramters (T and U), one bound inline, one with a where clause
28+
// • two parameters (T and U), both with where clauses
29+
//
30+
// —and for every permutation of 0, 1, or 2 lifetimes to outlive and 0 or 1
31+
// trait bounds distributed among said parameters (subject to no where clause
32+
// being empty and the struct having at least one lifetime).
33+
34+
35+
struct TeeOutlivesAy<'a, T: 'a> {
36+
//~^ ERROR outlives requirements can be inferred
37+
tee: &'a T
38+
}
39+
40+
struct TeeOutlivesAyIsDebug<'a, T: 'a + Debug> {
41+
//~^ ERROR outlives requirements can be inferred
42+
tee: &'a T
43+
}
44+
45+
struct TeeIsDebugOutlivesAy<'a, T: Debug + 'a> {
46+
//~^ ERROR outlives requirements can be inferred
47+
tee: &'a T
48+
}
49+
50+
struct TeeOutlivesAyBee<'a, 'b, T: 'a + 'b> {
51+
//~^ ERROR outlives requirements can be inferred
52+
tee: &'a &'b T
53+
}
54+
55+
struct TeeOutlivesAyBeeIsDebug<'a, 'b, T: 'a + 'b + Debug> {
56+
//~^ ERROR outlives requirements can be inferred
57+
tee: &'a &'b T
58+
}
59+
60+
struct TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug + 'a + 'b> {
61+
//~^ ERROR outlives requirements can be inferred
62+
tee: &'a &'b T
63+
}
64+
65+
struct TeeWhereOutlivesAy<'a, T> where T: 'a {
66+
//~^ ERROR outlives requirements can be inferred
67+
tee: &'a T
68+
}
69+
70+
struct TeeWhereOutlivesAyIsDebug<'a, T> where T: 'a + Debug {
71+
//~^ ERROR outlives requirements can be inferred
72+
tee: &'a T
73+
}
74+
75+
struct TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug + 'a {
76+
//~^ ERROR outlives requirements can be inferred
77+
tee: &'a T
78+
}
79+
80+
struct TeeWhereOutlivesAyBee<'a, 'b, T> where T: 'a + 'b {
81+
//~^ ERROR outlives requirements can be inferred
82+
tee: &'a &'b T
83+
}
84+
85+
struct TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: 'a + 'b + Debug {
86+
//~^ ERROR outlives requirements can be inferred
87+
tee: &'a &'b T
88+
}
89+
90+
struct TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug + 'a + 'b {
91+
//~^ ERROR outlives requirements can be inferred
92+
tee: &'a &'b T
93+
}
94+
95+
struct TeeYooOutlivesAy<'a, T, U: 'a> {
96+
//~^ ERROR outlives requirements can be inferred
97+
tee: T,
98+
yoo: &'a U
99+
}
100+
101+
struct TeeYooOutlivesAyIsDebug<'a, T, U: 'a + Debug> {
102+
//~^ ERROR outlives requirements can be inferred
103+
tee: T,
104+
yoo: &'a U
105+
}
106+
107+
struct TeeYooIsDebugOutlivesAy<'a, T, U: Debug + 'a> {
108+
//~^ ERROR outlives requirements can be inferred
109+
tee: T,
110+
yoo: &'a U
111+
}
112+
113+
struct TeeOutlivesAyYooIsDebug<'a, T: 'a, U: Debug> {
114+
//~^ ERROR outlives requirements can be inferred
115+
tee: &'a T,
116+
yoo: U
117+
}
118+
119+
struct TeeYooOutlivesAyBee<'a, 'b, T, U: 'a + 'b> {
120+
//~^ ERROR outlives requirements can be inferred
121+
tee: T,
122+
yoo: &'a &'b U
123+
}
124+
125+
struct TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: 'a + 'b + Debug> {
126+
//~^ ERROR outlives requirements can be inferred
127+
tee: T,
128+
yoo: &'a &'b U
129+
}
130+
131+
struct TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug + 'a + 'b> {
132+
//~^ ERROR outlives requirements can be inferred
133+
tee: T,
134+
yoo: &'a &'b U
135+
}
136+
137+
struct TeeOutlivesAyBeeYooIsDebug<'a, 'b, T: 'a + 'b, U: Debug> {
138+
//~^ ERROR outlives requirements can be inferred
139+
tee: &'a &'b T,
140+
yoo: U
141+
}
142+
143+
struct TeeYooWhereOutlivesAy<'a, T, U> where U: 'a {
144+
//~^ ERROR outlives requirements can be inferred
145+
tee: T,
146+
yoo: &'a U
147+
}
148+
149+
struct TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: 'a + Debug {
150+
//~^ ERROR outlives requirements can be inferred
151+
tee: T,
152+
yoo: &'a U
153+
}
154+
155+
struct TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug + 'a {
156+
//~^ ERROR outlives requirements can be inferred
157+
tee: T,
158+
yoo: &'a U
159+
}
160+
161+
struct TeeOutlivesAyYooWhereIsDebug<'a, T: 'a, U> where U: Debug {
162+
//~^ ERROR outlives requirements can be inferred
163+
tee: &'a T,
164+
yoo: U
165+
}
166+
167+
struct TeeYooWhereOutlivesAyBee<'a, 'b, T, U> where U: 'a + 'b {
168+
//~^ ERROR outlives requirements can be inferred
169+
tee: T,
170+
yoo: &'a &'b U
171+
}
172+
173+
struct TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: 'a + 'b + Debug {
174+
//~^ ERROR outlives requirements can be inferred
175+
tee: T,
176+
yoo: &'a &'b U
177+
}
178+
179+
struct TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug + 'a + 'b {
180+
//~^ ERROR outlives requirements can be inferred
181+
tee: T,
182+
yoo: &'a &'b U
183+
}
184+
185+
struct TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T: 'a + 'b, U> where U: Debug {
186+
//~^ ERROR outlives requirements can be inferred
187+
tee: &'a &'b T,
188+
yoo: U
189+
}
190+
191+
struct TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where T: 'a, U: Debug {
192+
//~^ ERROR outlives requirements can be inferred
193+
tee: &'a T,
194+
yoo: U
195+
}
196+
197+
struct TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where T: 'a + 'b, U: Debug {
198+
//~^ ERROR outlives requirements can be inferred
199+
tee: &'a &'b T,
200+
yoo: U
201+
}
202+
203+
204+
// But outlives inference for 'static lifetimes is under a separate
205+
// feature-gate for now
206+
// (https://github.com/rust-lang/rust/issues/44493#issuecomment-407846046).
207+
struct StaticRef<T: 'static> {
208+
field: &'static T
209+
}
210+
211+
212+
fn main() {}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
error: outlives requirements can be inferred
2+
--> $DIR/edition-lint-infer-outlives.rs:35:27
3+
|
4+
LL | struct TeeOutlivesAy<'a, T: 'a> {
5+
| ^^^^ help: remove this bound
6+
|
7+
note: lint level defined here
8+
--> $DIR/edition-lint-infer-outlives.rs:14:9
9+
|
10+
LL | #![deny(explicit_outlives_requirements)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: outlives requirements can be inferred
14+
--> $DIR/edition-lint-infer-outlives.rs:40:36
15+
|
16+
LL | struct TeeOutlivesAyIsDebug<'a, T: 'a + Debug> {
17+
| ^^^^^ help: remove this bound
18+
19+
error: outlives requirements can be inferred
20+
--> $DIR/edition-lint-infer-outlives.rs:45:41
21+
|
22+
LL | struct TeeIsDebugOutlivesAy<'a, T: Debug + 'a> {
23+
| ^^^^^ help: remove this bound
24+
25+
error: outlives requirements can be inferred
26+
--> $DIR/edition-lint-infer-outlives.rs:50:34
27+
|
28+
LL | struct TeeOutlivesAyBee<'a, 'b, T: 'a + 'b> {
29+
| ^^^^^^^^^ help: remove these bounds
30+
31+
error: outlives requirements can be inferred
32+
--> $DIR/edition-lint-infer-outlives.rs:55:43
33+
|
34+
LL | struct TeeOutlivesAyBeeIsDebug<'a, 'b, T: 'a + 'b + Debug> {
35+
| ^^^^^^^^^^ help: remove these bounds
36+
37+
error: outlives requirements can be inferred
38+
--> $DIR/edition-lint-infer-outlives.rs:60:48
39+
|
40+
LL | struct TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug + 'a + 'b> {
41+
| ^^^^^^^^^^ help: remove these bounds
42+
43+
error: outlives requirements can be inferred
44+
--> $DIR/edition-lint-infer-outlives.rs:65:33
45+
|
46+
LL | struct TeeWhereOutlivesAy<'a, T> where T: 'a {
47+
| ^^^^^^^^^^^^ help: remove this bound
48+
49+
error: outlives requirements can be inferred
50+
--> $DIR/edition-lint-infer-outlives.rs:70:50
51+
|
52+
LL | struct TeeWhereOutlivesAyIsDebug<'a, T> where T: 'a + Debug {
53+
| ^^^^^ help: remove this bound
54+
55+
error: outlives requirements can be inferred
56+
--> $DIR/edition-lint-infer-outlives.rs:75:55
57+
|
58+
LL | struct TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug + 'a {
59+
| ^^^^^ help: remove this bound
60+
61+
error: outlives requirements can be inferred
62+
--> $DIR/edition-lint-infer-outlives.rs:80:40
63+
|
64+
LL | struct TeeWhereOutlivesAyBee<'a, 'b, T> where T: 'a + 'b {
65+
| ^^^^^^^^^^^^^^^^^ help: remove these bounds
66+
67+
error: outlives requirements can be inferred
68+
--> $DIR/edition-lint-infer-outlives.rs:85:57
69+
|
70+
LL | struct TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: 'a + 'b + Debug {
71+
| ^^^^^^^^^^ help: remove these bounds
72+
73+
error: outlives requirements can be inferred
74+
--> $DIR/edition-lint-infer-outlives.rs:90:62
75+
|
76+
LL | struct TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug + 'a + 'b {
77+
| ^^^^^^^^^^ help: remove these bounds
78+
79+
error: outlives requirements can be inferred
80+
--> $DIR/edition-lint-infer-outlives.rs:95:33
81+
|
82+
LL | struct TeeYooOutlivesAy<'a, T, U: 'a> {
83+
| ^^^^ help: remove this bound
84+
85+
error: outlives requirements can be inferred
86+
--> $DIR/edition-lint-infer-outlives.rs:101:42
87+
|
88+
LL | struct TeeYooOutlivesAyIsDebug<'a, T, U: 'a + Debug> {
89+
| ^^^^^ help: remove this bound
90+
91+
error: outlives requirements can be inferred
92+
--> $DIR/edition-lint-infer-outlives.rs:107:47
93+
|
94+
LL | struct TeeYooIsDebugOutlivesAy<'a, T, U: Debug + 'a> {
95+
| ^^^^^ help: remove this bound
96+
97+
error: outlives requirements can be inferred
98+
--> $DIR/edition-lint-infer-outlives.rs:113:37
99+
|
100+
LL | struct TeeOutlivesAyYooIsDebug<'a, T: 'a, U: Debug> {
101+
| ^^^^ help: remove this bound
102+
103+
error: outlives requirements can be inferred
104+
--> $DIR/edition-lint-infer-outlives.rs:119:40
105+
|
106+
LL | struct TeeYooOutlivesAyBee<'a, 'b, T, U: 'a + 'b> {
107+
| ^^^^^^^^^ help: remove these bounds
108+
109+
error: outlives requirements can be inferred
110+
--> $DIR/edition-lint-infer-outlives.rs:125:49
111+
|
112+
LL | struct TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: 'a + 'b + Debug> {
113+
| ^^^^^^^^^^ help: remove these bounds
114+
115+
error: outlives requirements can be inferred
116+
--> $DIR/edition-lint-infer-outlives.rs:131:54
117+
|
118+
LL | struct TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug + 'a + 'b> {
119+
| ^^^^^^^^^^ help: remove these bounds
120+
121+
error: outlives requirements can be inferred
122+
--> $DIR/edition-lint-infer-outlives.rs:137:44
123+
|
124+
LL | struct TeeOutlivesAyBeeYooIsDebug<'a, 'b, T: 'a + 'b, U: Debug> {
125+
| ^^^^^^^^^ help: remove these bounds
126+
127+
error: outlives requirements can be inferred
128+
--> $DIR/edition-lint-infer-outlives.rs:143:39
129+
|
130+
LL | struct TeeYooWhereOutlivesAy<'a, T, U> where U: 'a {
131+
| ^^^^^^^^^^^^ help: remove this bound
132+
133+
error: outlives requirements can be inferred
134+
--> $DIR/edition-lint-infer-outlives.rs:149:56
135+
|
136+
LL | struct TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: 'a + Debug {
137+
| ^^^^^ help: remove this bound
138+
139+
error: outlives requirements can be inferred
140+
--> $DIR/edition-lint-infer-outlives.rs:155:61
141+
|
142+
LL | struct TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug + 'a {
143+
| ^^^^^ help: remove this bound
144+
145+
error: outlives requirements can be inferred
146+
--> $DIR/edition-lint-infer-outlives.rs:161:42
147+
|
148+
LL | struct TeeOutlivesAyYooWhereIsDebug<'a, T: 'a, U> where U: Debug {
149+
| ^^^^ help: remove this bound
150+
151+
error: outlives requirements can be inferred
152+
--> $DIR/edition-lint-infer-outlives.rs:167:46
153+
|
154+
LL | struct TeeYooWhereOutlivesAyBee<'a, 'b, T, U> where U: 'a + 'b {
155+
| ^^^^^^^^^^^^^^^^^ help: remove these bounds
156+
157+
error: outlives requirements can be inferred
158+
--> $DIR/edition-lint-infer-outlives.rs:173:63
159+
|
160+
LL | struct TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: 'a + 'b + Debug {
161+
| ^^^^^^^^^^ help: remove these bounds
162+
163+
error: outlives requirements can be inferred
164+
--> $DIR/edition-lint-infer-outlives.rs:179:68
165+
|
166+
LL | struct TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug + 'a + 'b {
167+
| ^^^^^^^^^^ help: remove these bounds
168+
169+
error: outlives requirements can be inferred
170+
--> $DIR/edition-lint-infer-outlives.rs:185:49
171+
|
172+
LL | struct TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T: 'a + 'b, U> where U: Debug {
173+
| ^^^^^^^^^ help: remove these bounds
174+
175+
error: outlives requirements can be inferred
176+
--> $DIR/edition-lint-infer-outlives.rs:191:58
177+
|
178+
LL | struct TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where T: 'a, U: Debug {
179+
| ^^^^^^^ help: remove this bound
180+
181+
error: outlives requirements can be inferred
182+
--> $DIR/edition-lint-infer-outlives.rs:197:65
183+
|
184+
LL | struct TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where T: 'a + 'b, U: Debug {
185+
| ^^^^^^^^^^^^ help: remove these bounds
186+
187+
error: aborting due to 30 previous errors
188+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-pass
12+
13+
#![allow(unused)]
14+
#![deny(explicit_outlives_requirements)]
15+
16+
// A case where we can't infer the outlives requirement. Example copied from
17+
// RFC 2093.
18+
// (https://rust-lang.github.io/rfcs/2093-infer-outlives.html
19+
// #where-explicit-annotations-would-still-be-required)
20+
21+
22+
trait MakeRef<'a> {
23+
type Type;
24+
}
25+
26+
impl<'a, T> MakeRef<'a> for Vec<T>
27+
where T: 'a // still required
28+
{
29+
type Type = &'a T;
30+
}
31+
32+
33+
struct Foo<'a, T>
34+
where T: 'a // still required, not inferred from `field`
35+
{
36+
field: <Vec<T> as MakeRef<'a>>::Type
37+
}
38+
39+
40+
fn main() {}

0 commit comments

Comments
 (0)
Please sign in to comment.