diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-05-03 16:24:57 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-05-03 16:24:57 +0200 |
| commit | 3ca0d365386a640ba17b9b436a3dafff079cd71e (patch) | |
| tree | a008a7f1cadd673e80fe11d340cb8a1592584fbc /src/librustc | |
| parent | 9199bb5f81eae1f8ea47c9945fc3f4c4dded4989 (diff) | |
| parent | c6e13bc20b5664ba9a8bd4152412bcc497e4f041 (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.rs | 5 | ||||
| -rw-r--r-- | src/librustc/hir/lowering.rs | 68 | ||||
| -rw-r--r-- | src/librustc/lint/builtin.rs | 80 |
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) => { |
