about summary refs log tree commit diff
path: root/src/librustc
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-05-03 16:24:57 +0200
committerGitHub <noreply@github.com>2019-05-03 16:24:57 +0200
commit3ca0d365386a640ba17b9b436a3dafff079cd71e (patch)
treea008a7f1cadd673e80fe11d340cb8a1592584fbc /src/librustc
parent9199bb5f81eae1f8ea47c9945fc3f4c4dded4989 (diff)
parentc6e13bc20b5664ba9a8bd4152412bcc497e4f041 (diff)
Rollup merge of #60388 - cramertj:elided-lifetime-async, r=nikomatsakis
Disallow non-explicit elided lifetimes in async fn

Fix https://github.com/rust-lang/rust/issues/60203

r? @nikomatsakis
Diffstat (limited to 'src/librustc')
-rw-r--r--src/librustc/error_codes.rs5
-rw-r--r--src/librustc/hir/lowering.rs68
-rw-r--r--src/librustc/lint/builtin.rs80
3 files changed, 103 insertions, 50 deletions
diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs
index 7f68b35d014..fd089fc688e 100644
--- a/src/librustc/error_codes.rs
+++ b/src/librustc/error_codes.rs
@@ -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 @@ register_diagnostics! {
     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
 }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 6d57882976e..ad26e05bf80 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -2110,15 +2110,49 @@ impl<'a> LoweringContext<'a> {
                         .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,
+                            )
+                        );
+                    }
+                }
             }
         }
 
@@ -5335,13 +5369,15 @@ impl<'a> LoweringContext<'a> {
 
     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),
 
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index ef487242866..993e1aacb4e 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -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 @@ impl BuiltinLintDiagnostics {
             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) => {