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 42dde96

Browse files
committedOct 19, 2018
Auto merge of #55162 - nikomatsakis:issue-54902-underscore-bound, r=tmandry
handle underscore bounds in unexpected places Per the discussion on #54902, I made it a hard error to use lifetime bounds in various places where they used to be permitted: - `where Foo: Bar<'_>` for example I also moved error reporting to HIR lowering and added `Error` variants to let us suppress downstream errors that result. I (imo) improved the error message wording to be clearer, as well. In the process, I fixed the ICE in #52098. Fixes #54902 Fixes #52098
2 parents 78ff609 + c294ec6 commit 42dde96

36 files changed

+910
-362
lines changed
 

‎src/librustc/hir/intravisit.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,9 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime
436436
visitor.visit_ident(ident);
437437
}
438438
LifetimeName::Param(ParamName::Fresh(_)) |
439+
LifetimeName::Param(ParamName::Error) |
439440
LifetimeName::Static |
441+
LifetimeName::Error |
440442
LifetimeName::Implicit |
441443
LifetimeName::Underscore => {}
442444
}
@@ -747,7 +749,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi
747749
walk_list!(visitor, visit_attribute, &param.attrs);
748750
match param.name {
749751
ParamName::Plain(ident) => visitor.visit_ident(ident),
750-
ParamName::Fresh(_) => {}
752+
ParamName::Error | ParamName::Fresh(_) => {}
751753
}
752754
match param.kind {
753755
GenericParamKind::Lifetime { .. } => {}

‎src/librustc/hir/lowering.rs

Lines changed: 83 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,11 @@ enum AnonymousLifetimeMode {
315315
/// For **Deprecated** cases, report an error.
316316
CreateParameter,
317317

318+
/// Give a hard error when either `&` or `'_` is written. Used to
319+
/// rule out things like `where T: Foo<'_>`. Does not imply an
320+
/// error on default object bounds (e.g., `Box<dyn Foo>`).
321+
ReportError,
322+
318323
/// Pass responsibility to `resolve_lifetime` code for all cases.
319324
PassThrough,
320325
}
@@ -735,6 +740,10 @@ impl<'a> LoweringContext<'a> {
735740
keywords::UnderscoreLifetime.name().as_interned_str(),
736741
hir::LifetimeParamKind::Elided,
737742
),
743+
ParamName::Error => (
744+
keywords::UnderscoreLifetime.name().as_interned_str(),
745+
hir::LifetimeParamKind::Error,
746+
),
738747
};
739748

740749
// Add a definition for the in-band lifetime def
@@ -791,7 +800,7 @@ impl<'a> LoweringContext<'a> {
791800
}
792801

793802
/// When we have either an elided or `'_` lifetime in an impl
794-
/// header, we convert it to
803+
/// header, we convert it to an in-band lifetime.
795804
fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName {
796805
assert!(self.is_collecting_in_band_lifetimes);
797806
let index = self.lifetimes_to_define.len();
@@ -1474,7 +1483,7 @@ impl<'a> LoweringContext<'a> {
14741483
}
14751484
}
14761485
hir::LifetimeName::Param(_) => lifetime.name,
1477-
hir::LifetimeName::Static => return,
1486+
hir::LifetimeName::Error | hir::LifetimeName::Static => return,
14781487
};
14791488

14801489
if !self.currently_bound_lifetimes.contains(&name)
@@ -2162,7 +2171,7 @@ impl<'a> LoweringContext<'a> {
21622171
}
21632172
}
21642173
hir::LifetimeName::Param(_) => lifetime.name,
2165-
hir::LifetimeName::Static => return,
2174+
hir::LifetimeName::Error | hir::LifetimeName::Static => return,
21662175
};
21672176

21682177
if !self.currently_bound_lifetimes.contains(&name) {
@@ -2293,10 +2302,12 @@ impl<'a> LoweringContext<'a> {
22932302
itctx: ImplTraitContext<'_>,
22942303
) -> hir::GenericBound {
22952304
match *tpb {
2296-
GenericBound::Trait(ref ty, modifier) => hir::GenericBound::Trait(
2297-
self.lower_poly_trait_ref(ty, itctx),
2298-
self.lower_trait_bound_modifier(modifier),
2299-
),
2305+
GenericBound::Trait(ref ty, modifier) => {
2306+
hir::GenericBound::Trait(
2307+
self.lower_poly_trait_ref(ty, itctx),
2308+
self.lower_trait_bound_modifier(modifier),
2309+
)
2310+
}
23002311
GenericBound::Outlives(ref lifetime) => {
23012312
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
23022313
}
@@ -2318,6 +2329,8 @@ impl<'a> LoweringContext<'a> {
23182329
AnonymousLifetimeMode::PassThrough => {
23192330
self.new_named_lifetime(l.id, span, hir::LifetimeName::Underscore)
23202331
}
2332+
2333+
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(Some(l.id), span),
23212334
},
23222335
ident => {
23232336
self.maybe_collect_in_band_lifetime(ident);
@@ -2356,16 +2369,26 @@ impl<'a> LoweringContext<'a> {
23562369
add_bounds: &NodeMap<Vec<GenericBound>>,
23572370
mut itctx: ImplTraitContext<'_>)
23582371
-> hir::GenericParam {
2359-
let mut bounds = self.lower_param_bounds(&param.bounds, itctx.reborrow());
2372+
let mut bounds = self.with_anonymous_lifetime_mode(
2373+
AnonymousLifetimeMode::ReportError,
2374+
|this| this.lower_param_bounds(&param.bounds, itctx.reborrow()),
2375+
);
2376+
23602377
match param.kind {
23612378
GenericParamKind::Lifetime => {
23622379
let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
23632380
self.is_collecting_in_band_lifetimes = false;
23642381

2365-
let lt = self.lower_lifetime(&Lifetime { id: param.id, ident: param.ident });
2382+
let lt = self.with_anonymous_lifetime_mode(
2383+
AnonymousLifetimeMode::ReportError,
2384+
|this| this.lower_lifetime(&Lifetime { id: param.id, ident: param.ident }),
2385+
);
23662386
let param_name = match lt.name {
23672387
hir::LifetimeName::Param(param_name) => param_name,
2368-
_ => hir::ParamName::Plain(lt.name.ident()),
2388+
hir::LifetimeName::Implicit
2389+
| hir::LifetimeName::Underscore
2390+
| hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()),
2391+
hir::LifetimeName::Error => ParamName::Error,
23692392
};
23702393
let param = hir::GenericParam {
23712394
id: lt.id,
@@ -2489,13 +2512,18 @@ impl<'a> LoweringContext<'a> {
24892512
}
24902513

24912514
fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause {
2492-
hir::WhereClause {
2493-
id: self.lower_node_id(wc.id).node_id,
2494-
predicates: wc.predicates
2495-
.iter()
2496-
.map(|predicate| self.lower_where_predicate(predicate))
2497-
.collect(),
2498-
}
2515+
self.with_anonymous_lifetime_mode(
2516+
AnonymousLifetimeMode::ReportError,
2517+
|this| {
2518+
hir::WhereClause {
2519+
id: this.lower_node_id(wc.id).node_id,
2520+
predicates: wc.predicates
2521+
.iter()
2522+
.map(|predicate| this.lower_where_predicate(predicate))
2523+
.collect(),
2524+
}
2525+
},
2526+
)
24992527
}
25002528

25012529
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate {
@@ -4837,10 +4865,38 @@ impl<'a> LoweringContext<'a> {
48374865
}
48384866
}
48394867

4868+
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
4869+
48404870
AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
48414871
}
48424872
}
48434873

4874+
/// Report an error on illegal use of `'_` or a `&T` with no explicit lifetime;
4875+
/// return a "error lifetime".
4876+
fn new_error_lifetime(&mut self, id: Option<NodeId>, span: Span) -> hir::Lifetime {
4877+
let (id, msg, label) = match id {
4878+
Some(id) => (id, "`'_` cannot be used here", "`'_` is a reserved lifetime name"),
4879+
4880+
None => (
4881+
self.next_id().node_id,
4882+
"`&` without an explicit lifetime name cannot be used here",
4883+
"explicit lifetime name needed here",
4884+
),
4885+
};
4886+
4887+
let mut err = struct_span_err!(
4888+
self.sess,
4889+
span,
4890+
E0637,
4891+
"{}",
4892+
msg,
4893+
);
4894+
err.span_label(span, label);
4895+
err.emit();
4896+
4897+
self.new_named_lifetime(id, span, hir::LifetimeName::Error)
4898+
}
4899+
48444900
/// Invoked to create the lifetime argument(s) for a path like
48454901
/// `std::cell::Ref<T>`; note that implicit lifetimes in these
48464902
/// sorts of cases are deprecated. This may therefore report a warning or an
@@ -4855,6 +4911,12 @@ impl<'a> LoweringContext<'a> {
48554911
// impl Foo for std::cell::Ref<u32> // note lack of '_
48564912
AnonymousLifetimeMode::CreateParameter => {}
48574913

4914+
AnonymousLifetimeMode::ReportError => {
4915+
return (0..count)
4916+
.map(|_| self.new_error_lifetime(None, span))
4917+
.collect();
4918+
}
4919+
48584920
// This is the normal case.
48594921
AnonymousLifetimeMode::PassThrough => {}
48604922
}
@@ -4885,6 +4947,10 @@ impl<'a> LoweringContext<'a> {
48854947
// `resolve_lifetime` has the code to make that happen.
48864948
AnonymousLifetimeMode::CreateParameter => {}
48874949

4950+
AnonymousLifetimeMode::ReportError => {
4951+
// ReportError applies to explicit use of `'_`.
4952+
}
4953+
48884954
// This is the normal case.
48894955
AnonymousLifetimeMode::PassThrough => {}
48904956
}

‎src/librustc/hir/mod.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,18 @@ pub enum ParamName {
208208
/// where `'f` is something like `Fresh(0)`. The indices are
209209
/// unique per impl, but not necessarily continuous.
210210
Fresh(usize),
211+
212+
/// Indicates an illegal name was given and an error has been
213+
/// repored (so we should squelch other derived errors). Occurs
214+
/// when e.g. `'_` is used in the wrong place.
215+
Error,
211216
}
212217

213218
impl ParamName {
214219
pub fn ident(&self) -> Ident {
215220
match *self {
216221
ParamName::Plain(ident) => ident,
217-
ParamName::Fresh(_) => keywords::UnderscoreLifetime.ident(),
222+
ParamName::Error | ParamName::Fresh(_) => keywords::UnderscoreLifetime.ident(),
218223
}
219224
}
220225

@@ -234,6 +239,10 @@ pub enum LifetimeName {
234239
/// User typed nothing. e.g. the lifetime in `&u32`.
235240
Implicit,
236241

242+
/// Indicates an error during lowering (usually `'_` in wrong place)
243+
/// that was already reported.
244+
Error,
245+
237246
/// User typed `'_`.
238247
Underscore,
239248

@@ -245,6 +254,7 @@ impl LifetimeName {
245254
pub fn ident(&self) -> Ident {
246255
match *self {
247256
LifetimeName::Implicit => keywords::Invalid.ident(),
257+
LifetimeName::Error => keywords::Invalid.ident(),
248258
LifetimeName::Underscore => keywords::UnderscoreLifetime.ident(),
249259
LifetimeName::Static => keywords::StaticLifetime.ident(),
250260
LifetimeName::Param(param_name) => param_name.ident(),
@@ -260,7 +270,7 @@ impl LifetimeName {
260270
// in the compiler is concerned -- `Fresh(_)` variants act
261271
// equivalently to "some fresh name". They correspond to
262272
// early-bound regions on an impl, in other words.
263-
LifetimeName::Param(_) | LifetimeName::Static => false,
273+
LifetimeName::Error | LifetimeName::Param(_) | LifetimeName::Static => false,
264274
}
265275
}
266276

@@ -513,6 +523,9 @@ pub enum LifetimeParamKind {
513523
// Indication that the lifetime was elided like both cases here:
514524
// `fn foo(x: &u8) -> &'_ u8 { x }`
515525
Elided,
526+
527+
// Indication that the lifetime name was somehow in error.
528+
Error,
516529
}
517530

518531
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]

‎src/librustc/ich/impls_hir.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,16 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItemId {
144144

145145
impl_stable_hash_for!(enum hir::ParamName {
146146
Plain(name),
147-
Fresh(index)
147+
Fresh(index),
148+
Error,
148149
});
149150

150151
impl_stable_hash_for!(enum hir::LifetimeName {
151152
Param(param_name),
152153
Implicit,
153154
Underscore,
154155
Static,
156+
Error,
155157
});
156158

157159
impl_stable_hash_for!(struct hir::Label {
@@ -210,7 +212,8 @@ impl_stable_hash_for!(struct hir::GenericParam {
210212
impl_stable_hash_for!(enum hir::LifetimeParamKind {
211213
Explicit,
212214
InBand,
213-
Elided
215+
Elided,
216+
Error,
214217
});
215218

216219
impl<'a> HashStable<StableHashingContext<'a>> for hir::GenericParamKind {

‎src/librustc/ich/impls_ty.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -755,8 +755,9 @@ for ::middle::resolve_lifetime::Set1<T>
755755
}
756756

757757
impl_stable_hash_for!(enum ::middle::resolve_lifetime::LifetimeDefOrigin {
758-
Explicit,
759-
InBand
758+
ExplicitOrElided,
759+
InBand,
760+
Error,
760761
});
761762

762763
impl_stable_hash_for!(enum ::middle::resolve_lifetime::Region {

‎src/librustc/middle/resolve_lifetime.rs

Lines changed: 395 additions & 312 deletions
Large diffs are not rendered by default.

‎src/librustc_lint/builtin.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2074,6 +2074,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitOutlivesRequirements {
20742074
hir::GenericParamKind::Type { .. } => {
20752075
match param.name {
20762076
hir::ParamName::Fresh(_) => { continue; },
2077+
hir::ParamName::Error => { continue; },
20772078
hir::ParamName::Plain(name) => name.to_string()
20782079
}
20792080
}

‎src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
562562
let lifetime = self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
563563
match lifetime.name {
564564
hir::LifetimeName::Param(_)
565+
| hir::LifetimeName::Error
565566
| hir::LifetimeName::Static
566567
| hir::LifetimeName::Underscore => {
567568
let region_name = self.synthesize_region_name(counter);

‎src/librustc_typeck/check/wfcheck.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,10 @@ fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
830830
}
831831

832832
let param = &hir_generics.params[index];
833-
report_bivariance(tcx, param.span, param.name.ident().name);
833+
match param.name {
834+
hir::ParamName::Error => { }
835+
_ => report_bivariance(tcx, param.span, param.name.ident().name),
836+
}
834837
}
835838
}
836839

‎src/test/ui/error-codes/E0637.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
struct Foo<'a: '_>(&'a u8); //~ ERROR invalid lifetime bound name: `'_`
12-
fn foo<'a: '_>(_: &'a u8) {} //~ ERROR invalid lifetime bound name: `'_`
11+
struct Foo<'a: '_>(&'a u8); //~ ERROR cannot be used here
12+
fn foo<'a: '_>(_: &'a u8) {} //~ ERROR cannot be used here
1313

1414
struct Bar<'a>(&'a u8);
15-
impl<'a: '_> Bar<'a> { //~ ERROR invalid lifetime bound name: `'_`
15+
impl<'a: '_> Bar<'a> { //~ ERROR cannot be used here
1616
fn bar() {}
1717
}
1818

‎src/test/ui/error-codes/E0637.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
error[E0637]: invalid lifetime bound name: `'_`
1+
error[E0637]: `'_` cannot be used here
22
--> $DIR/E0637.rs:11:16
33
|
4-
LL | struct Foo<'a: '_>(&'a u8); //~ ERROR invalid lifetime bound name: `'_`
4+
LL | struct Foo<'a: '_>(&'a u8); //~ ERROR cannot be used here
55
| ^^ `'_` is a reserved lifetime name
66

7-
error[E0637]: invalid lifetime bound name: `'_`
7+
error[E0637]: `'_` cannot be used here
88
--> $DIR/E0637.rs:12:12
99
|
10-
LL | fn foo<'a: '_>(_: &'a u8) {} //~ ERROR invalid lifetime bound name: `'_`
10+
LL | fn foo<'a: '_>(_: &'a u8) {} //~ ERROR cannot be used here
1111
| ^^ `'_` is a reserved lifetime name
1212

13-
error[E0637]: invalid lifetime bound name: `'_`
13+
error[E0637]: `'_` cannot be used here
1414
--> $DIR/E0637.rs:15:10
1515
|
16-
LL | impl<'a: '_> Bar<'a> { //~ ERROR invalid lifetime bound name: `'_`
16+
LL | impl<'a: '_> Bar<'a> { //~ ERROR cannot be used here
1717
| ^^ `'_` is a reserved lifetime name
1818

1919
error: aborting due to 3 previous errors
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
error[E0637]: `'_` cannot be used here
2+
--> $DIR/in-binder.rs:12:6
3+
|
4+
LL | impl<'_> IceCube<'_> {}
5+
| ^^ `'_` is a reserved lifetime name
6+
7+
error[E0637]: `'_` cannot be used here
8+
--> $DIR/in-binder.rs:17:15
9+
|
10+
LL | struct Struct<'_> {
11+
| ^^ `'_` is a reserved lifetime name
12+
13+
error[E0637]: `'_` cannot be used here
14+
--> $DIR/in-binder.rs:23:11
15+
|
16+
LL | enum Enum<'_> {
17+
| ^^ `'_` is a reserved lifetime name
18+
19+
error[E0637]: `'_` cannot be used here
20+
--> $DIR/in-binder.rs:29:13
21+
|
22+
LL | union Union<'_> {
23+
| ^^ `'_` is a reserved lifetime name
24+
25+
error[E0637]: `'_` cannot be used here
26+
--> $DIR/in-binder.rs:35:13
27+
|
28+
LL | trait Trait<'_> {
29+
| ^^ `'_` is a reserved lifetime name
30+
31+
error[E0637]: `'_` cannot be used here
32+
--> $DIR/in-binder.rs:40:8
33+
|
34+
LL | fn foo<'_>() {
35+
| ^^ `'_` is a reserved lifetime name
36+
37+
error[E0106]: missing lifetime specifier
38+
--> $DIR/in-binder.rs:12:18
39+
|
40+
LL | impl<'_> IceCube<'_> {}
41+
| ^^ expected lifetime parameter
42+
43+
error: aborting due to 7 previous errors
44+
45+
Some errors occurred: E0106, E0637.
46+
For more information about an error, try `rustc --explain E0106`.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0637]: `'_` cannot be used here
2+
--> $DIR/in-binder.rs:12:6
3+
|
4+
LL | impl<'_> IceCube<'_> {}
5+
| ^^ `'_` is a reserved lifetime name
6+
7+
error[E0637]: `'_` cannot be used here
8+
--> $DIR/in-binder.rs:17:15
9+
|
10+
LL | struct Struct<'_> {
11+
| ^^ `'_` is a reserved lifetime name
12+
13+
error[E0637]: `'_` cannot be used here
14+
--> $DIR/in-binder.rs:23:11
15+
|
16+
LL | enum Enum<'_> {
17+
| ^^ `'_` is a reserved lifetime name
18+
19+
error[E0637]: `'_` cannot be used here
20+
--> $DIR/in-binder.rs:29:13
21+
|
22+
LL | union Union<'_> {
23+
| ^^ `'_` is a reserved lifetime name
24+
25+
error[E0637]: `'_` cannot be used here
26+
--> $DIR/in-binder.rs:35:13
27+
|
28+
LL | trait Trait<'_> {
29+
| ^^ `'_` is a reserved lifetime name
30+
31+
error[E0637]: `'_` cannot be used here
32+
--> $DIR/in-binder.rs:40:8
33+
|
34+
LL | fn foo<'_>() {
35+
| ^^ `'_` is a reserved lifetime name
36+
37+
error: aborting due to 6 previous errors
38+
39+
For more information about this error, try `rustc --explain E0637`.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Check that we error when `'_` appears as the name of a lifetime parameter.
2+
//
3+
// Regression test for #52098.
4+
5+
// revisions: Rust2015 Rust2018
6+
//[Rust2018] edition:2018
7+
8+
struct IceCube<'a> {
9+
v: Vec<&'a char>
10+
}
11+
12+
impl<'_> IceCube<'_> {}
13+
//[Rust2015]~^ ERROR `'_` cannot be used here
14+
//[Rust2015]~| ERROR missing lifetime specifier
15+
//[Rust2018]~^^^ ERROR `'_` cannot be used here
16+
17+
struct Struct<'_> {
18+
//[Rust2015]~^ ERROR `'_` cannot be used here
19+
//[Rust2018]~^^ ERROR `'_` cannot be used here
20+
v: Vec<&'static char>
21+
}
22+
23+
enum Enum<'_> {
24+
//[Rust2015]~^ ERROR `'_` cannot be used here
25+
//[Rust2018]~^^ ERROR `'_` cannot be used here
26+
Variant
27+
}
28+
29+
union Union<'_> {
30+
//[Rust2015]~^ ERROR `'_` cannot be used here
31+
//[Rust2018]~^^ ERROR `'_` cannot be used here
32+
a: u32
33+
}
34+
35+
trait Trait<'_> {
36+
//[Rust2015]~^ ERROR `'_` cannot be used here
37+
//[Rust2018]~^^ ERROR `'_` cannot be used here
38+
}
39+
40+
fn foo<'_>() {
41+
//[Rust2015]~^ ERROR `'_` cannot be used here
42+
//[Rust2018]~^^ ERROR `'_` cannot be used here
43+
}
44+
45+
fn main() {}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2015 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+
// Check that the `'_` used in structs/enums gives an error.
12+
13+
use std::fmt::Debug;
14+
15+
fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } } //~ ERROR missing lifetime specifier
16+
17+
fn main() { }
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/in-fn-return-illegal.rs:15:30
3+
|
4+
LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } } //~ ERROR missing lifetime specifier
5+
| ^^ expected lifetime parameter
6+
|
7+
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0106`.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2015 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+
// Check that the `'_` used in structs/enums gives an error.
12+
13+
use std::fmt::Debug;
14+
15+
struct Foo {
16+
x: &'_ u32, //~ ERROR missing lifetime specifier
17+
}
18+
19+
enum Bar {
20+
Variant(&'_ u32), //~ ERROR missing lifetime specifier
21+
}
22+
23+
fn main() { }
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/in-struct.rs:16:9
3+
|
4+
LL | x: &'_ u32, //~ ERROR missing lifetime specifier
5+
| ^^ expected lifetime parameter
6+
7+
error[E0106]: missing lifetime specifier
8+
--> $DIR/in-struct.rs:20:14
9+
|
10+
LL | Variant(&'_ u32), //~ ERROR missing lifetime specifier
11+
| ^^ expected lifetime parameter
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0106`.

‎src/test/ui/underscore-lifetime/underscore-lifetime-binders.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ impl Foo<'_> { //~ ERROR missing lifetime specifier
1515
fn x() {}
1616
}
1717

18-
fn foo<'_> //~ ERROR invalid lifetime parameter name: `'_`
18+
fn foo<'_> //~ ERROR cannot be used here
1919
(_: Foo<'_>) {}
2020

2121
trait Meh<'a> {}
2222
impl<'a> Meh<'a> for u8 {}
2323

24-
fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR invalid lifetime parameter name: `'_`
24+
fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR cannot be used here
2525
//~^ ERROR missing lifetime specifier
2626
{
2727
Box::new(5u8)
Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
error[E0637]: `'_` cannot be used here
2+
--> $DIR/underscore-lifetime-binders.rs:18:8
3+
|
4+
LL | fn foo<'_> //~ ERROR cannot be used here
5+
| ^^ `'_` is a reserved lifetime name
6+
7+
error[E0637]: `'_` cannot be used here
8+
--> $DIR/underscore-lifetime-binders.rs:24:21
9+
|
10+
LL | fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR cannot be used here
11+
| ^^ `'_` is a reserved lifetime name
12+
113
error[E0106]: missing lifetime specifier
214
--> $DIR/underscore-lifetime-binders.rs:12:17
315
|
@@ -10,22 +22,10 @@ error[E0106]: missing lifetime specifier
1022
LL | impl Foo<'_> { //~ ERROR missing lifetime specifier
1123
| ^^ expected lifetime parameter
1224

13-
error[E0262]: invalid lifetime parameter name: `'_`
14-
--> $DIR/underscore-lifetime-binders.rs:18:8
15-
|
16-
LL | fn foo<'_> //~ ERROR invalid lifetime parameter name: `'_`
17-
| ^^ '_ is a reserved lifetime name
18-
19-
error[E0262]: invalid lifetime parameter name: `'_`
20-
--> $DIR/underscore-lifetime-binders.rs:24:21
21-
|
22-
LL | fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR invalid lifetime parameter name: `'_`
23-
| ^^ '_ is a reserved lifetime name
24-
2525
error[E0106]: missing lifetime specifier
2626
--> $DIR/underscore-lifetime-binders.rs:24:29
2727
|
28-
LL | fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR invalid lifetime parameter name: `'_`
28+
LL | fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR cannot be used here
2929
| ^^ expected lifetime parameter
3030
|
3131
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
@@ -41,5 +41,5 @@ LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } //~ ERROR missing lifetime sp
4141

4242
error: aborting due to 6 previous errors
4343

44-
Some errors occurred: E0106, E0262.
44+
Some errors occurred: E0106, E0637.
4545
For more information about an error, try `rustc --explain E0106`.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Regression test to check that `'b: '_` gets an error, because it's
2+
// basically useless.
3+
//
4+
// #54902
5+
6+
trait Foo<'a> {}
7+
impl<'b: '_> Foo<'b> for i32 {}
8+
fn main() { }
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0637]: `'_` cannot be used here
2+
--> $DIR/underscore-outlives-bounds.rs:7:10
3+
|
4+
LL | impl<'b: '_> Foo<'b> for i32 {}
5+
| ^^ `'_` is a reserved lifetime name
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0637`.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// revisions: rust2015 rust2018
2+
//[rust2018] edition:2018
3+
4+
trait WithType<T> {}
5+
trait WithRegion<'a> { }
6+
7+
struct Foo<T> {
8+
t: T
9+
}
10+
11+
impl<T> Foo<T>
12+
where
13+
T: WithType<&u32>
14+
//[rust2015]~^ ERROR `&` without an explicit lifetime name cannot be used here
15+
//[rust2018]~^^ ERROR `&` without an explicit lifetime name cannot be used here
16+
{ }
17+
18+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0637]: `&` without an explicit lifetime name cannot be used here
2+
--> $DIR/where-clause-inherent-impl-ampersand.rs:13:17
3+
|
4+
LL | T: WithType<&u32>
5+
| ^ explicit lifetime name needed here
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0637`.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0637]: `&` without an explicit lifetime name cannot be used here
2+
--> $DIR/where-clause-inherent-impl-ampersand.rs:13:17
3+
|
4+
LL | T: WithType<&u32>
5+
| ^ explicit lifetime name needed here
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0637`.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// revisions: rust2015 rust2018
2+
//[rust2018] edition:2018
3+
4+
trait WithType<T> {}
5+
trait WithRegion<'a> { }
6+
7+
struct Foo<T> {
8+
t: T
9+
}
10+
11+
impl<T> Foo<T>
12+
where
13+
T: WithRegion<'_>
14+
//[rust2015]~^ ERROR `'_` cannot be used here
15+
//[rust2018]~^^ ERROR `'_` cannot be used here
16+
{ }
17+
18+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0637]: `'_` cannot be used here
2+
--> $DIR/where-clause-inherent-impl-underscore.rs:13:19
3+
|
4+
LL | T: WithRegion<'_>
5+
| ^^ `'_` is a reserved lifetime name
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0637`.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0637]: `'_` cannot be used here
2+
--> $DIR/where-clause-inherent-impl-underscore.rs:13:19
3+
|
4+
LL | T: WithRegion<'_>
5+
| ^^ `'_` is a reserved lifetime name
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0637`.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// revisions: rust2015 rust2018
2+
//[rust2018] edition:2018
3+
4+
trait WithType<T> {}
5+
trait WithRegion<'a> { }
6+
7+
trait Foo { }
8+
9+
impl<T> Foo for Vec<T>
10+
where
11+
T: WithType<&u32>
12+
//[rust2015]~^ ERROR `&` without an explicit lifetime name cannot be used here
13+
//[rust2018]~^^ ERROR `&` without an explicit lifetime name cannot be used here
14+
{ }
15+
16+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0637]: `&` without an explicit lifetime name cannot be used here
2+
--> $DIR/where-clause-trait-impl-region.rs:11:17
3+
|
4+
LL | T: WithType<&u32>
5+
| ^ explicit lifetime name needed here
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0637`.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0637]: `&` without an explicit lifetime name cannot be used here
2+
--> $DIR/where-clause-trait-impl-region.rs:11:17
3+
|
4+
LL | T: WithType<&u32>
5+
| ^ explicit lifetime name needed here
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0637`.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// revisions: rust2015 rust2018
2+
//[rust2018] edition:2018
3+
4+
trait WithType<T> {}
5+
trait WithRegion<'a> { }
6+
7+
trait Foo { }
8+
9+
impl<T> Foo for Vec<T>
10+
where
11+
T: WithRegion<'_>
12+
//[rust2015]~^ ERROR `'_` cannot be used here
13+
//[rust2018]~^^ ERROR `'_` cannot be used here
14+
{ }
15+
16+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0637]: `'_` cannot be used here
2+
--> $DIR/where-clause-trait-impl-underscore.rs:11:19
3+
|
4+
LL | T: WithRegion<'_>
5+
| ^^ `'_` is a reserved lifetime name
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0637`.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0637]: `'_` cannot be used here
2+
--> $DIR/where-clause-trait-impl-underscore.rs:11:19
3+
|
4+
LL | T: WithRegion<'_>
5+
| ^^ `'_` is a reserved lifetime name
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0637`.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
trait Foo<'a> {}
2+
3+
impl<'b: '_> Foo<'b> for i32 {} //~ ERROR `'_` cannot be used here
4+
5+
impl<T: '_> Foo<'static> for Vec<T> {} //~ ERROR `'_` cannot be used here
6+
7+
fn main() { }
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0637]: `'_` cannot be used here
2+
--> $DIR/where-clauses.rs:3:10
3+
|
4+
LL | impl<'b: '_> Foo<'b> for i32 {} //~ ERROR `'_` cannot be used here
5+
| ^^ `'_` is a reserved lifetime name
6+
7+
error[E0637]: `'_` cannot be used here
8+
--> $DIR/where-clauses.rs:5:9
9+
|
10+
LL | impl<T: '_> Foo<'static> for Vec<T> {} //~ ERROR `'_` cannot be used here
11+
| ^^ `'_` is a reserved lifetime name
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0637`.

0 commit comments

Comments
 (0)
Please sign in to comment.