]> git.lizzy.rs Git - rust.git/commitdiff
Disallow non-explicit elided lifetimes in async fn
authorTaylor Cramer <cramertj@google.com>
Tue, 30 Apr 2019 00:45:22 +0000 (17:45 -0700)
committerTaylor Cramer <cramertj@google.com>
Thu, 2 May 2019 01:34:49 +0000 (18:34 -0700)
src/librustc/error_codes.rs
src/librustc/hir/lowering.rs
src/librustc/lint/builtin.rs
src/test/ui/async-fn-path-elision.rs [new file with mode: 0644]
src/test/ui/async-fn-path-elision.stderr [new file with mode: 0644]
src/test/ui/impl-header-lifetime-elision/path-elided.rs
src/test/ui/impl-header-lifetime-elision/path-elided.stderr
src/test/ui/impl-header-lifetime-elision/trait-elided.rs
src/test/ui/impl-header-lifetime-elision/trait-elided.stderr
src/test/ui/issues/issue-10412.rs
src/test/ui/issues/issue-10412.stderr

index 7f68b35d014cba72237797858644b332305fb062..fd089fc688e32d5db01a66650e90a1dfe0a6bbce 100644 (file)
@@ -362,10 +362,6 @@ struct Foo1 { x: &bool }
               // ^ 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
@@ -2208,4 +2204,5 @@ trait Foo { }
     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
 }
index df455a725c5baa9acde46f5c72292c5b8a252344..0587b978105d74ba51e00a05071448dab58be8f4 100644 (file)
@@ -2110,15 +2110,49 @@ fn lower_path_segment(
                         .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,
+                            )
+                        );
+                    }
+                }
             }
         }
 
@@ -5298,13 +5332,15 @@ fn elided_path_lifetimes(&mut self, span: Span, count: usize) -> P<[hir::Lifetim
 
     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),
 
index 28a2a1eaf6b492e8f44e6871f3dc69e33a6a290e..a9481cb32a16b5267f93b3f9af4cf79668c84593 100644 (file)
@@ -477,6 +477,48 @@ pub enum BuiltinLintDiagnostics {
     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 {
@@ -521,36 +563,14 @@ pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder<'_>) {
             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) => {
diff --git a/src/test/ui/async-fn-path-elision.rs b/src/test/ui/async-fn-path-elision.rs
new file mode 100644 (file)
index 0000000..8db7631
--- /dev/null
@@ -0,0 +1,16 @@
+// 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() {}
diff --git a/src/test/ui/async-fn-path-elision.stderr b/src/test/ui/async-fn-path-elision.stderr
new file mode 100644 (file)
index 0000000..3b311ba
--- /dev/null
@@ -0,0 +1,8 @@
+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
+
index 6532b0aebe74ab79881ebece697554fe605b6ca6..40a52efc7f9fc0860dc774477c5a9c13832f8266 100644 (file)
@@ -5,7 +5,7 @@ trait MyTrait { }
 struct Foo<'a> { x: &'a u32 }
 
 impl MyTrait for Foo {
-    //~^ ERROR missing lifetime specifier
+    //~^ ERROR implicit elided lifetime not allowed here
 }
 
 fn main() {}
index c9287ffba96d3c8d36dcc14b430a3832babcbeae..6500a2a55f6677d807922ec67f2cff89d53f6fe3 100644 (file)
@@ -1,9 +1,8 @@
-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`.
index 3979eda740a824e377472287e4cca9ba0ae615a7..102d259b0c87ab5e9976df924dce3951c6448e77 100644 (file)
@@ -3,7 +3,7 @@
 trait MyTrait<'a> { }
 
 impl MyTrait for u32 {
-    //~^ ERROR missing lifetime specifier
+    //~^ ERROR implicit elided lifetime not allowed here
 }
 
 fn main() {}
index b742db1c75c19cca614aec1cae53816f2facbe2e..ad97cb0abd6239bc34ba3c0f04e0034a0ad0e8e8 100644 (file)
@@ -1,9 +1,8 @@
-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`.
index a0bc2fc2f3c79c69fb350b0d2e808be3945469e0..020585136856bd35070624c7a0e54bcb44a019fe 100644 (file)
@@ -5,7 +5,8 @@ trait Serializable<'self, T> { //~ ERROR lifetimes cannot use keyword names
 
 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]
     }
index 48920813ae10d2f0a79e00ffaf924d85a2ae39fa..0793dd99b4d12578d71987cb9770af50e6468e2e 100644 (file)
@@ -29,23 +29,32 @@ LL | impl<'self> Serializable<str> for &'self str {
    |                                    ^^^^^
 
 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`.