// ^ expected lifetime parameter
struct Foo2<'a> { x: &'a bool } // correct
-impl Foo2 {}
- // ^^^^ expected lifetime parameter
-impl<'a> Foo2<'a> {} // correct
-
struct Bar1 { x: Foo2 }
// ^^^^ expected lifetime parameter
struct Bar2<'a> { x: Foo2<'a> } // correct
E0710, // an unknown tool name found in scoped lint
E0711, // a feature has been declared with conflicting stability attributes
// E0702, // replaced with a generic attribute input check
+ E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
}
.expect("already checked that type args or bindings exist");
(false, first_generic_span.shrink_to_lo(), format!("{}, ", anon_lt_suggestion))
};
- self.sess.buffer_lint_with_diagnostic(
- ELIDED_LIFETIMES_IN_PATHS,
- CRATE_NODE_ID,
- path_span,
- "hidden lifetime parameters in types are deprecated",
- builtin::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
- expected_lifetimes, path_span, incl_angl_brckt, insertion_span, suggestion
- )
- );
+ match self.anonymous_lifetime_mode {
+ // In create-parameter mode we error here because we don't want to support
+ // deprecated impl elision in new features like impl elision and `async fn`,
+ // both of which work using the `CreateParameter` mode:
+ //
+ // impl Foo for std::cell::Ref<u32> // note lack of '_
+ // async fn foo(_: std::cell::Ref<u32>) { ... }
+ AnonymousLifetimeMode::CreateParameter => {
+ let mut err = struct_span_err!(
+ self.sess,
+ path_span,
+ E0726,
+ "implicit elided lifetime not allowed here"
+ );
+ crate::lint::builtin::add_elided_lifetime_in_path_suggestion(
+ &self.sess,
+ &mut err,
+ expected_lifetimes,
+ path_span,
+ incl_angl_brckt,
+ insertion_span,
+ suggestion,
+ );
+ err.emit();
+ }
+ AnonymousLifetimeMode::PassThrough |
+ AnonymousLifetimeMode::ReportError |
+ AnonymousLifetimeMode::Replace(_) => {
+ self.sess.buffer_lint_with_diagnostic(
+ ELIDED_LIFETIMES_IN_PATHS,
+ CRATE_NODE_ID,
+ path_span,
+ "hidden lifetime parameters in types are deprecated",
+ builtin::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
+ expected_lifetimes,
+ path_span,
+ incl_angl_brckt,
+ insertion_span,
+ suggestion,
+ )
+ );
+ }
+ }
}
}
fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime {
match self.anonymous_lifetime_mode {
- // N.B., We intentionally ignore the create-parameter mode here
- // and instead "pass through" to resolve-lifetimes, which will then
- // report an error. This is because we don't want to support
- // impl elision for deprecated forms like
- //
- // impl Foo for std::cell::Ref<u32> // note lack of '_
- AnonymousLifetimeMode::CreateParameter |
+ AnonymousLifetimeMode::CreateParameter => {
+ // We should have emitted E0726 when processing this path above
+ self.sess.delay_span_bug(
+ span,
+ "expected 'implicit elided lifetime not allowed' error",
+ );
+ let id = self.sess.next_node_id();
+ self.new_named_lifetime(id, span, hir::LifetimeName::Error)
+ }
// This is the normal case.
AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
RedundantImport(Vec<(Span, bool)>, ast::Ident),
}
+pub(crate) fn add_elided_lifetime_in_path_suggestion(
+ sess: &Session,
+ db: &mut DiagnosticBuilder<'_>,
+ n: usize,
+ path_span: Span,
+ incl_angl_brckt: bool,
+ insertion_span: Span,
+ anon_lts: String,
+) {
+ let (replace_span, suggestion) = if incl_angl_brckt {
+ (insertion_span, anon_lts)
+ } else {
+ // When possible, prefer a suggestion that replaces the whole
+ // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
+ // at a point (which makes for an ugly/confusing label)
+ if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
+ // But our spans can get out of whack due to macros; if the place we think
+ // we want to insert `'_` isn't even within the path expression's span, we
+ // should bail out of making any suggestion rather than panicking on a
+ // subtract-with-overflow or string-slice-out-out-bounds (!)
+ // FIXME: can we do better?
+ if insertion_span.lo().0 < path_span.lo().0 {
+ return;
+ }
+ let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
+ if insertion_index > snippet.len() {
+ return;
+ }
+ let (before, after) = snippet.split_at(insertion_index);
+ (path_span, format!("{}{}{}", before, anon_lts, after))
+ } else {
+ (insertion_span, anon_lts)
+ }
+ };
+ db.span_suggestion(
+ replace_span,
+ &format!("indicate the anonymous lifetime{}", if n >= 2 { "s" } else { "" }),
+ suggestion,
+ Applicability::MachineApplicable
+ );
+}
+
impl BuiltinLintDiagnostics {
pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder<'_>) {
match self {
BuiltinLintDiagnostics::ElidedLifetimesInPaths(
n, path_span, incl_angl_brckt, insertion_span, anon_lts
) => {
- let (replace_span, suggestion) = if incl_angl_brckt {
- (insertion_span, anon_lts)
- } else {
- // When possible, prefer a suggestion that replaces the whole
- // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
- // at a point (which makes for an ugly/confusing label)
- if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
- // But our spans can get out of whack due to macros; if the place we think
- // we want to insert `'_` isn't even within the path expression's span, we
- // should bail out of making any suggestion rather than panicking on a
- // subtract-with-overflow or string-slice-out-out-bounds (!)
- // FIXME: can we do better?
- if insertion_span.lo().0 < path_span.lo().0 {
- return;
- }
- let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
- if insertion_index > snippet.len() {
- return;
- }
- let (before, after) = snippet.split_at(insertion_index);
- (path_span, format!("{}{}{}", before, anon_lts, after))
- } else {
- (insertion_span, anon_lts)
- }
- };
- db.span_suggestion(
- replace_span,
- &format!("indicate the anonymous lifetime{}", if n >= 2 { "s" } else { "" }),
- suggestion,
- Applicability::MachineApplicable
+ add_elided_lifetime_in_path_suggestion(
+ sess,
+ db,
+ n,
+ path_span,
+ incl_angl_brckt,
+ insertion_span,
+ anon_lts,
);
}
BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
--- /dev/null
+// edition:2018
+
+#![feature(async_await, await_macro)]
+#![allow(dead_code)]
+
+struct HasLifetime<'a>(&'a bool);
+
+async fn error(lt: HasLifetime) { //~ ERROR implicit elided lifetime not allowed here
+ if *lt.0 {}
+}
+
+fn no_error(lt: HasLifetime) {
+ if *lt.0 {}
+}
+
+fn main() {}
--- /dev/null
+error[E0726]: implicit elided lifetime not allowed here
+ --> $DIR/async-fn-path-elision.rs:8:20
+ |
+LL | async fn error(lt: HasLifetime) {
+ | ^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+
+error: aborting due to previous error
+
struct Foo<'a> { x: &'a u32 }
impl MyTrait for Foo {
- //~^ ERROR missing lifetime specifier
+ //~^ ERROR implicit elided lifetime not allowed here
}
fn main() {}
-error[E0106]: missing lifetime specifier
+error[E0726]: implicit elided lifetime not allowed here
--> $DIR/path-elided.rs:7:18
|
LL | impl MyTrait for Foo {
- | ^^^ expected lifetime parameter
+ | ^^^- help: indicate the anonymous lifetime: `<'_>`
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0106`.
trait MyTrait<'a> { }
impl MyTrait for u32 {
- //~^ ERROR missing lifetime specifier
+ //~^ ERROR implicit elided lifetime not allowed here
}
fn main() {}
-error[E0106]: missing lifetime specifier
+error[E0726]: implicit elided lifetime not allowed here
--> $DIR/trait-elided.rs:5:6
|
LL | impl MyTrait for u32 {
- | ^^^^^^^ expected lifetime parameter
+ | ^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0106`.
impl<'self> Serializable<str> for &'self str { //~ ERROR lifetimes cannot use keyword names
//~^ ERROR lifetimes cannot use keyword names
- //~| ERROR missing lifetime specifier
+ //~| ERROR implicit elided lifetime not allowed here
+ //~| ERROR the size for values of type `str` cannot be known at compilation time
fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR lifetimes cannot use keyword names
vec![1]
}
| ^^^^^
error: lifetimes cannot use keyword names
- --> $DIR/issue-10412.rs:9:25
+ --> $DIR/issue-10412.rs:10:25
|
LL | fn serialize(val : &'self str) -> Vec<u8> {
| ^^^^^
error: lifetimes cannot use keyword names
- --> $DIR/issue-10412.rs:12:37
+ --> $DIR/issue-10412.rs:13:37
|
LL | fn deserialize(repr: &[u8]) -> &'self str {
| ^^^^^
-error[E0106]: missing lifetime specifier
+error[E0726]: implicit elided lifetime not allowed here
--> $DIR/issue-10412.rs:6:13
|
LL | impl<'self> Serializable<str> for &'self str {
- | ^^^^^^^^^^^^^^^^^ expected lifetime parameter
+ | ^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Serializable<'_, str>`
-error: aborting due to 8 previous errors
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/issue-10412.rs:6:13
+ |
+LL | impl<'self> Serializable<str> for &'self str {
+ | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+
+error: aborting due to 9 previous errors
-For more information about this error, try `rustc --explain E0106`.
+For more information about this error, try `rustc --explain E0277`.