Skip to content

Commit c6e13bc

Browse files
committed
Disallow non-explicit elided lifetimes in async fn
1 parent 00859e3 commit c6e13bc

11 files changed

+150
-65
lines changed

src/librustc/error_codes.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,6 @@ struct Foo1 { x: &bool }
362362
// ^ expected lifetime parameter
363363
struct Foo2<'a> { x: &'a bool } // correct
364364
365-
impl Foo2 {}
366-
// ^^^^ expected lifetime parameter
367-
impl<'a> Foo2<'a> {} // correct
368-
369365
struct Bar1 { x: Foo2 }
370366
// ^^^^ expected lifetime parameter
371367
struct Bar2<'a> { x: Foo2<'a> } // correct
@@ -2208,4 +2204,5 @@ register_diagnostics! {
22082204
E0710, // an unknown tool name found in scoped lint
22092205
E0711, // a feature has been declared with conflicting stability attributes
22102206
// E0702, // replaced with a generic attribute input check
2207+
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
22112208
}

src/librustc/hir/lowering.rs

+52-16
Original file line numberDiff line numberDiff line change
@@ -2110,15 +2110,49 @@ impl<'a> LoweringContext<'a> {
21102110
.expect("already checked that type args or bindings exist");
21112111
(false, first_generic_span.shrink_to_lo(), format!("{}, ", anon_lt_suggestion))
21122112
};
2113-
self.sess.buffer_lint_with_diagnostic(
2114-
ELIDED_LIFETIMES_IN_PATHS,
2115-
CRATE_NODE_ID,
2116-
path_span,
2117-
"hidden lifetime parameters in types are deprecated",
2118-
builtin::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
2119-
expected_lifetimes, path_span, incl_angl_brckt, insertion_span, suggestion
2120-
)
2121-
);
2113+
match self.anonymous_lifetime_mode {
2114+
// In create-parameter mode we error here because we don't want to support
2115+
// deprecated impl elision in new features like impl elision and `async fn`,
2116+
// both of which work using the `CreateParameter` mode:
2117+
//
2118+
// impl Foo for std::cell::Ref<u32> // note lack of '_
2119+
// async fn foo(_: std::cell::Ref<u32>) { ... }
2120+
AnonymousLifetimeMode::CreateParameter => {
2121+
let mut err = struct_span_err!(
2122+
self.sess,
2123+
path_span,
2124+
E0726,
2125+
"implicit elided lifetime not allowed here"
2126+
);
2127+
crate::lint::builtin::add_elided_lifetime_in_path_suggestion(
2128+
&self.sess,
2129+
&mut err,
2130+
expected_lifetimes,
2131+
path_span,
2132+
incl_angl_brckt,
2133+
insertion_span,
2134+
suggestion,
2135+
);
2136+
err.emit();
2137+
}
2138+
AnonymousLifetimeMode::PassThrough |
2139+
AnonymousLifetimeMode::ReportError |
2140+
AnonymousLifetimeMode::Replace(_) => {
2141+
self.sess.buffer_lint_with_diagnostic(
2142+
ELIDED_LIFETIMES_IN_PATHS,
2143+
CRATE_NODE_ID,
2144+
path_span,
2145+
"hidden lifetime parameters in types are deprecated",
2146+
builtin::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
2147+
expected_lifetimes,
2148+
path_span,
2149+
incl_angl_brckt,
2150+
insertion_span,
2151+
suggestion,
2152+
)
2153+
);
2154+
}
2155+
}
21222156
}
21232157
}
21242158

@@ -5298,13 +5332,15 @@ impl<'a> LoweringContext<'a> {
52985332

52995333
fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime {
53005334
match self.anonymous_lifetime_mode {
5301-
// N.B., We intentionally ignore the create-parameter mode here
5302-
// and instead "pass through" to resolve-lifetimes, which will then
5303-
// report an error. This is because we don't want to support
5304-
// impl elision for deprecated forms like
5305-
//
5306-
// impl Foo for std::cell::Ref<u32> // note lack of '_
5307-
AnonymousLifetimeMode::CreateParameter |
5335+
AnonymousLifetimeMode::CreateParameter => {
5336+
// We should have emitted E0726 when processing this path above
5337+
self.sess.delay_span_bug(
5338+
span,
5339+
"expected 'implicit elided lifetime not allowed' error",
5340+
);
5341+
let id = self.sess.next_node_id();
5342+
self.new_named_lifetime(id, span, hir::LifetimeName::Error)
5343+
}
53085344
// This is the normal case.
53095345
AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
53105346

src/librustc/lint/builtin.rs

+50-30
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,48 @@ pub enum BuiltinLintDiagnostics {
477477
RedundantImport(Vec<(Span, bool)>, ast::Ident),
478478
}
479479

480+
pub(crate) fn add_elided_lifetime_in_path_suggestion(
481+
sess: &Session,
482+
db: &mut DiagnosticBuilder<'_>,
483+
n: usize,
484+
path_span: Span,
485+
incl_angl_brckt: bool,
486+
insertion_span: Span,
487+
anon_lts: String,
488+
) {
489+
let (replace_span, suggestion) = if incl_angl_brckt {
490+
(insertion_span, anon_lts)
491+
} else {
492+
// When possible, prefer a suggestion that replaces the whole
493+
// `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
494+
// at a point (which makes for an ugly/confusing label)
495+
if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
496+
// But our spans can get out of whack due to macros; if the place we think
497+
// we want to insert `'_` isn't even within the path expression's span, we
498+
// should bail out of making any suggestion rather than panicking on a
499+
// subtract-with-overflow or string-slice-out-out-bounds (!)
500+
// FIXME: can we do better?
501+
if insertion_span.lo().0 < path_span.lo().0 {
502+
return;
503+
}
504+
let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
505+
if insertion_index > snippet.len() {
506+
return;
507+
}
508+
let (before, after) = snippet.split_at(insertion_index);
509+
(path_span, format!("{}{}{}", before, anon_lts, after))
510+
} else {
511+
(insertion_span, anon_lts)
512+
}
513+
};
514+
db.span_suggestion(
515+
replace_span,
516+
&format!("indicate the anonymous lifetime{}", if n >= 2 { "s" } else { "" }),
517+
suggestion,
518+
Applicability::MachineApplicable
519+
);
520+
}
521+
480522
impl BuiltinLintDiagnostics {
481523
pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder<'_>) {
482524
match self {
@@ -521,36 +563,14 @@ impl BuiltinLintDiagnostics {
521563
BuiltinLintDiagnostics::ElidedLifetimesInPaths(
522564
n, path_span, incl_angl_brckt, insertion_span, anon_lts
523565
) => {
524-
let (replace_span, suggestion) = if incl_angl_brckt {
525-
(insertion_span, anon_lts)
526-
} else {
527-
// When possible, prefer a suggestion that replaces the whole
528-
// `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
529-
// at a point (which makes for an ugly/confusing label)
530-
if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
531-
// But our spans can get out of whack due to macros; if the place we think
532-
// we want to insert `'_` isn't even within the path expression's span, we
533-
// should bail out of making any suggestion rather than panicking on a
534-
// subtract-with-overflow or string-slice-out-out-bounds (!)
535-
// FIXME: can we do better?
536-
if insertion_span.lo().0 < path_span.lo().0 {
537-
return;
538-
}
539-
let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
540-
if insertion_index > snippet.len() {
541-
return;
542-
}
543-
let (before, after) = snippet.split_at(insertion_index);
544-
(path_span, format!("{}{}{}", before, anon_lts, after))
545-
} else {
546-
(insertion_span, anon_lts)
547-
}
548-
};
549-
db.span_suggestion(
550-
replace_span,
551-
&format!("indicate the anonymous lifetime{}", if n >= 2 { "s" } else { "" }),
552-
suggestion,
553-
Applicability::MachineApplicable
566+
add_elided_lifetime_in_path_suggestion(
567+
sess,
568+
db,
569+
n,
570+
path_span,
571+
incl_angl_brckt,
572+
insertion_span,
573+
anon_lts,
554574
);
555575
}
556576
BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {

src/test/ui/async-fn-path-elision.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// edition:2018
2+
3+
#![feature(async_await, await_macro)]
4+
#![allow(dead_code)]
5+
6+
struct HasLifetime<'a>(&'a bool);
7+
8+
async fn error(lt: HasLifetime) { //~ ERROR implicit elided lifetime not allowed here
9+
if *lt.0 {}
10+
}
11+
12+
fn no_error(lt: HasLifetime) {
13+
if *lt.0 {}
14+
}
15+
16+
fn main() {}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error[E0726]: implicit elided lifetime not allowed here
2+
--> $DIR/async-fn-path-elision.rs:8:20
3+
|
4+
LL | async fn error(lt: HasLifetime) {
5+
| ^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
6+
7+
error: aborting due to previous error
8+

src/test/ui/impl-header-lifetime-elision/path-elided.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ trait MyTrait { }
55
struct Foo<'a> { x: &'a u32 }
66

77
impl MyTrait for Foo {
8-
//~^ ERROR missing lifetime specifier
8+
//~^ ERROR implicit elided lifetime not allowed here
99
}
1010

1111
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
error[E0106]: missing lifetime specifier
1+
error[E0726]: implicit elided lifetime not allowed here
22
--> $DIR/path-elided.rs:7:18
33
|
44
LL | impl MyTrait for Foo {
5-
| ^^^ expected lifetime parameter
5+
| ^^^- help: indicate the anonymous lifetime: `<'_>`
66

77
error: aborting due to previous error
88

9-
For more information about this error, try `rustc --explain E0106`.

src/test/ui/impl-header-lifetime-elision/trait-elided.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
trait MyTrait<'a> { }
44

55
impl MyTrait for u32 {
6-
//~^ ERROR missing lifetime specifier
6+
//~^ ERROR implicit elided lifetime not allowed here
77
}
88

99
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
error[E0106]: missing lifetime specifier
1+
error[E0726]: implicit elided lifetime not allowed here
22
--> $DIR/trait-elided.rs:5:6
33
|
44
LL | impl MyTrait for u32 {
5-
| ^^^^^^^ expected lifetime parameter
5+
| ^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
66

77
error: aborting due to previous error
88

9-
For more information about this error, try `rustc --explain E0106`.

src/test/ui/issues/issue-10412.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ trait Serializable<'self, T> { //~ ERROR lifetimes cannot use keyword names
55

66
impl<'self> Serializable<str> for &'self str { //~ ERROR lifetimes cannot use keyword names
77
//~^ ERROR lifetimes cannot use keyword names
8-
//~| ERROR missing lifetime specifier
8+
//~| ERROR implicit elided lifetime not allowed here
9+
//~| ERROR the size for values of type `str` cannot be known at compilation time
910
fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR lifetimes cannot use keyword names
1011
vec![1]
1112
}

src/test/ui/issues/issue-10412.stderr

+15-6
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,32 @@ LL | impl<'self> Serializable<str> for &'self str {
2929
| ^^^^^
3030

3131
error: lifetimes cannot use keyword names
32-
--> $DIR/issue-10412.rs:9:25
32+
--> $DIR/issue-10412.rs:10:25
3333
|
3434
LL | fn serialize(val : &'self str) -> Vec<u8> {
3535
| ^^^^^
3636

3737
error: lifetimes cannot use keyword names
38-
--> $DIR/issue-10412.rs:12:37
38+
--> $DIR/issue-10412.rs:13:37
3939
|
4040
LL | fn deserialize(repr: &[u8]) -> &'self str {
4141
| ^^^^^
4242

43-
error[E0106]: missing lifetime specifier
43+
error[E0726]: implicit elided lifetime not allowed here
4444
--> $DIR/issue-10412.rs:6:13
4545
|
4646
LL | impl<'self> Serializable<str> for &'self str {
47-
| ^^^^^^^^^^^^^^^^^ expected lifetime parameter
47+
| ^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Serializable<'_, str>`
4848

49-
error: aborting due to 8 previous errors
49+
error[E0277]: the size for values of type `str` cannot be known at compilation time
50+
--> $DIR/issue-10412.rs:6:13
51+
|
52+
LL | impl<'self> Serializable<str> for &'self str {
53+
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
54+
|
55+
= help: the trait `std::marker::Sized` is not implemented for `str`
56+
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
57+
58+
error: aborting due to 9 previous errors
5059

51-
For more information about this error, try `rustc --explain E0106`.
60+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)