Auto merge of #95779 - cjgillot:ast-lifetimes-undeclared, r=petrochenkov

Report undeclared lifetimes during late resolution.

First step in https://github.com/rust-lang/rust/pull/91557

We reuse the rib design of the current resolution framework. Specific `LifetimeRib` and `LifetimeRibKind` types are introduced. The most important variant is `LifetimeRibKind::Generics`, which happens each time we encounter something which may introduce generic lifetime parameters. It can be an item or a `for<...>` binder. The `LifetimeBinderKind` specifies how this rib behaves with respect to in-band lifetimes.

r? `@petrochenkov`
This commit is contained in:
bors 2022-04-17 12:56:19 +00:00
commit 1ec2c136b3
54 changed files with 1855 additions and 778 deletions

View File

@ -35,7 +35,7 @@ pub enum FnCtxt {
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum FnKind<'a> { pub enum FnKind<'a> {
/// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, Option<&'a Block>), Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>),
/// E.g., `|x, y| body`. /// E.g., `|x, y| body`.
Closure(&'a FnDecl, &'a Expr), Closure(&'a FnDecl, &'a Expr),
@ -44,7 +44,7 @@ pub enum FnKind<'a> {
impl<'a> FnKind<'a> { impl<'a> FnKind<'a> {
pub fn header(&self) -> Option<&'a FnHeader> { pub fn header(&self) -> Option<&'a FnHeader> {
match *self { match *self {
FnKind::Fn(_, _, sig, _, _) => Some(&sig.header), FnKind::Fn(_, _, sig, _, _, _) => Some(&sig.header),
FnKind::Closure(_, _) => None, FnKind::Closure(_, _) => None,
} }
} }
@ -58,7 +58,7 @@ impl<'a> FnKind<'a> {
pub fn decl(&self) -> &'a FnDecl { pub fn decl(&self) -> &'a FnDecl {
match self { match self {
FnKind::Fn(_, _, sig, _, _) => &sig.decl, FnKind::Fn(_, _, sig, _, _, _) => &sig.decl,
FnKind::Closure(decl, _) => decl, FnKind::Closure(decl, _) => decl,
} }
} }
@ -295,8 +295,8 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
walk_list!(visitor, visit_expr, expr); walk_list!(visitor, visit_expr, expr);
} }
ItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => { ItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
visitor.visit_generics(generics); let kind =
let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref()); FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
visitor.visit_fn(kind, item.span, item.id) visitor.visit_fn(kind, item.span, item.id)
} }
ItemKind::Mod(_unsafety, ref mod_kind) => match mod_kind { ItemKind::Mod(_unsafety, ref mod_kind) => match mod_kind {
@ -561,8 +561,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
walk_list!(visitor, visit_expr, expr); walk_list!(visitor, visit_expr, expr);
} }
ForeignItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => { ForeignItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
visitor.visit_generics(generics); let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref());
let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
visitor.visit_fn(kind, span, id); visitor.visit_fn(kind, span, id);
} }
ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => { ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
@ -644,7 +643,8 @@ pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &
pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Span) { pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Span) {
match kind { match kind {
FnKind::Fn(_, _, sig, _, body) => { FnKind::Fn(_, _, sig, _, generics, body) => {
visitor.visit_generics(generics);
visitor.visit_fn_header(&sig.header); visitor.visit_fn_header(&sig.header);
walk_fn_decl(visitor, &sig.decl); walk_fn_decl(visitor, &sig.decl);
walk_list!(visitor, visit_block, body); walk_list!(visitor, visit_block, body);
@ -667,8 +667,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
walk_list!(visitor, visit_expr, expr); walk_list!(visitor, visit_expr, expr);
} }
AssocItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => { AssocItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
visitor.visit_generics(generics); let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref());
let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref());
visitor.visit_fn(kind, span, id); visitor.visit_fn(kind, span, id);
} }
AssocItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => { AssocItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {

View File

@ -484,7 +484,7 @@ enum ParenthesizedGenericArgs {
/// an "elided" or "underscore" lifetime name. In the future, we probably want to move /// an "elided" or "underscore" lifetime name. In the future, we probably want to move
/// everything into HIR lowering. /// everything into HIR lowering.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
enum AnonymousLifetimeMode { pub enum AnonymousLifetimeMode {
/// For **Modern** cases, create a new anonymous region parameter /// For **Modern** cases, create a new anonymous region parameter
/// and reference that. /// and reference that.
/// ///
@ -1835,7 +1835,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Output lifetime like `'_`: // Output lifetime like `'_`:
for (span, node_id) in lifetimes_to_define { for (span, node_id) in lifetimes_to_define {
let param = this.fresh_lifetime_to_generic_param(span, node_id); let param = this.fresh_lifetime_to_generic_param(span, node_id);
lifetime_params.push((span, hir::LifetimeName::Implicit(false))); lifetime_params.push((span, hir::LifetimeName::Implicit));
generic_params.push(param); generic_params.push(param);
} }
let generic_params = this.arena.alloc_from_iter(generic_params); let generic_params = this.arena.alloc_from_iter(generic_params);
@ -2017,16 +2017,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}); });
let param_name = match lt.name { let param_name = match lt.name {
hir::LifetimeName::Param(param_name) => param_name, hir::LifetimeName::Param(param_name) => param_name,
hir::LifetimeName::Implicit(_) hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
| hir::LifetimeName::Underscore hir::ParamName::Plain(lt.name.ident())
| hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()), }
hir::LifetimeName::ImplicitObjectLifetimeDefault => { hir::LifetimeName::ImplicitObjectLifetimeDefault => {
self.sess.diagnostic().span_bug( self.sess.diagnostic().span_bug(
param.ident.span, param.ident.span,
"object-lifetime-default should not occur here", "object-lifetime-default should not occur here",
); );
} }
hir::LifetimeName::Error => ParamName::Error, hir::LifetimeName::Static | hir::LifetimeName::Error => ParamName::Error,
}; };
let kind = let kind =
@ -2397,27 +2397,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span), AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span, false), AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
} }
} }
/// Report an error on illegal use of `'_` or a `&T` with no explicit lifetime; /// Report an error on illegal use of `'_` or a `&T` with no explicit lifetime;
/// return an "error lifetime". /// return an "error lifetime".
fn new_error_lifetime(&mut self, id: Option<NodeId>, span: Span) -> hir::Lifetime { fn new_error_lifetime(&mut self, id: Option<NodeId>, span: Span) -> hir::Lifetime {
let (id, msg, label) = match id { let id = id.unwrap_or_else(|| self.resolver.next_node_id());
Some(id) => (id, "`'_` cannot be used here", "`'_` is a reserved lifetime name"),
None => (
self.resolver.next_node_id(),
"`&` without an explicit lifetime name cannot be used here",
"explicit lifetime name needed here",
),
};
let mut err = struct_span_err!(self.sess, span, E0637, "{}", msg,);
err.span_label(span, label);
err.emit();
self.new_named_lifetime(id, span, hir::LifetimeName::Error) self.new_named_lifetime(id, span, hir::LifetimeName::Error)
} }
@ -2429,12 +2416,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&'s mut self, &'s mut self,
span: Span, span: Span,
count: usize, count: usize,
param_mode: ParamMode,
) -> impl Iterator<Item = hir::Lifetime> + Captures<'a> + Captures<'s> + Captures<'hir> { ) -> impl Iterator<Item = hir::Lifetime> + Captures<'a> + Captures<'s> + Captures<'hir> {
(0..count).map(move |_| self.elided_path_lifetime(span, param_mode)) (0..count).map(move |_| self.elided_path_lifetime(span))
} }
fn elided_path_lifetime(&mut self, span: Span, param_mode: ParamMode) -> hir::Lifetime { fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime {
match self.anonymous_lifetime_mode { match self.anonymous_lifetime_mode {
AnonymousLifetimeMode::CreateParameter => { AnonymousLifetimeMode::CreateParameter => {
// We should have emitted E0726 when processing this path above // We should have emitted E0726 when processing this path above
@ -2450,7 +2436,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// lifetime. Instead, we simply create an implicit lifetime, which will be checked // lifetime. Instead, we simply create an implicit lifetime, which will be checked
// later, at which point a suitable error will be emitted. // later, at which point a suitable error will be emitted.
AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => { AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => {
self.new_implicit_lifetime(span, param_mode == ParamMode::Explicit) self.new_implicit_lifetime(span)
} }
} }
} }
@ -2493,11 +2479,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
r r
} }
fn new_implicit_lifetime(&mut self, span: Span, missing: bool) -> hir::Lifetime { fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime {
hir::Lifetime { hir::Lifetime {
hir_id: self.next_id(), hir_id: self.next_id(),
span: self.lower_span(span), span: self.lower_span(span),
name: hir::LifetimeName::Implicit(missing), name: hir::LifetimeName::Implicit,
} }
} }
} }
@ -2600,7 +2586,7 @@ fn lifetimes_from_impl_trait_bounds(
fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) { fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
let name = match lifetime.name { let name = match lifetime.name {
hir::LifetimeName::Implicit(_) | hir::LifetimeName::Underscore => { hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
if self.collect_elided_lifetimes { if self.collect_elided_lifetimes {
// Use `'_` for both implicit and underscore lifetimes in // Use `'_` for both implicit and underscore lifetimes in
// `type Foo<'_> = impl SomeTrait<'_>;`. // `type Foo<'_> = impl SomeTrait<'_>;`.

View File

@ -290,47 +290,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo() generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo()
}; };
generic_args.args = self generic_args.args = self
.elided_path_lifetimes(elided_lifetime_span, expected_lifetimes, param_mode) .elided_path_lifetimes(elided_lifetime_span, expected_lifetimes)
.map(GenericArg::Lifetime) .map(GenericArg::Lifetime)
.chain(generic_args.args.into_iter()) .chain(generic_args.args.into_iter())
.collect(); .collect();
// 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>) { ... }
if let (ParamMode::Explicit, AnonymousLifetimeMode::CreateParameter) = if let (ParamMode::Explicit, AnonymousLifetimeMode::CreateParameter) =
(param_mode, self.anonymous_lifetime_mode) (param_mode, self.anonymous_lifetime_mode)
{ {
let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", "); // Late resolver should have issued the error.
let no_non_lt_args = generic_args.args.len() == expected_lifetimes; self.sess
let no_bindings = generic_args.bindings.is_empty(); .delay_span_bug(elided_lifetime_span, "implicit lifetime not allowed here");
let (incl_angl_brckt, suggestion) = if no_non_lt_args && no_bindings {
// If there are no generic args, our suggestion can include the angle brackets.
(true, format!("<{}>", anon_lt_suggestion))
} else {
// Otherwise we'll insert a `'_, ` right after the opening bracket.
(false, format!("{}, ", anon_lt_suggestion))
};
let insertion_sp = elided_lifetime_span.shrink_to_hi();
let mut err = struct_span_err!(
self.sess,
path_span,
E0726,
"implicit elided lifetime not allowed here"
);
rustc_errors::add_elided_lifetime_in_path_suggestion(
&self.sess.source_map(),
&mut err,
expected_lifetimes,
path_span,
incl_angl_brckt,
insertion_sp,
suggestion,
);
err.note("assuming a `'static` lifetime...");
err.emit();
} }
} }

View File

@ -91,16 +91,18 @@ impl<'a> AstValidator<'a> {
self.is_impl_trait_banned = old; self.is_impl_trait_banned = old;
} }
fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) { fn with_tilde_const(&mut self, allowed: bool, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.is_tilde_const_allowed, true); let old = mem::replace(&mut self.is_tilde_const_allowed, allowed);
f(self); f(self);
self.is_tilde_const_allowed = old; self.is_tilde_const_allowed = old;
} }
fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
self.with_tilde_const(true, f)
}
fn with_banned_tilde_const(&mut self, f: impl FnOnce(&mut Self)) { fn with_banned_tilde_const(&mut self, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.is_tilde_const_allowed, false); self.with_tilde_const(false, f)
f(self);
self.is_tilde_const_allowed = old;
} }
fn with_let_management( fn with_let_management(
@ -1202,12 +1204,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
} }
self.visit_vis(&item.vis); self.visit_vis(&item.vis);
self.visit_ident(item.ident); self.visit_ident(item.ident);
if let Const::Yes(_) = sig.header.constness { let kind =
self.with_tilde_const_allowed(|this| this.visit_generics(generics)); FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
} else {
self.visit_generics(generics);
}
let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
self.visit_fn(kind, item.span, item.id); self.visit_fn(kind, item.span, item.id);
walk_list!(self, visit_attribute, &item.attrs); walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again. return; // Avoid visiting again.
@ -1555,13 +1553,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
FnSig { span: sig_span, header: FnHeader { ext: Extern::Implicit, .. }, .. }, FnSig { span: sig_span, header: FnHeader { ext: Extern::Implicit, .. }, .. },
_, _,
_, _,
_,
) = fk ) = fk
{ {
self.maybe_lint_missing_abi(*sig_span, id); self.maybe_lint_missing_abi(*sig_span, id);
} }
// Functions without bodies cannot have patterns. // Functions without bodies cannot have patterns.
if let FnKind::Fn(ctxt, _, sig, _, None) = fk { if let FnKind::Fn(ctxt, _, sig, _, _, None) = fk {
Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| { Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
let (code, msg, label) = match ctxt { let (code, msg, label) = match ctxt {
FnCtxt::Foreign => ( FnCtxt::Foreign => (
@ -1596,7 +1595,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}); });
} }
visit::walk_fn(self, fk, span); let tilde_const_allowed =
matches!(fk.header(), Some(FnHeader { constness: Const::Yes(_), .. }))
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk, span));
} }
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
@ -1670,9 +1673,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
{ {
self.visit_vis(&item.vis); self.visit_vis(&item.vis);
self.visit_ident(item.ident); self.visit_ident(item.ident);
self.with_tilde_const_allowed(|this| this.visit_generics(generics)); let kind = FnKind::Fn(
let kind = FnCtxt::Assoc(ctxt),
FnKind::Fn(FnCtxt::Assoc(ctxt), item.ident, sig, &item.vis, body.as_deref()); item.ident,
sig,
&item.vis,
generics,
body.as_deref(),
);
self.visit_fn(kind, item.span, item.id); self.visit_fn(kind, item.span, item.id);
} }
_ => self _ => self

View File

@ -575,7 +575,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span)) Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span))
} }
hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit(_) => { hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit => {
// In this case, the user left off the lifetime; so // In this case, the user left off the lifetime; so
// they wrote something like: // they wrote something like:
// //

View File

@ -1511,35 +1511,17 @@ pub fn add_elided_lifetime_in_path_suggestion(
path_span: Span, path_span: Span,
incl_angl_brckt: bool, incl_angl_brckt: bool,
insertion_span: Span, insertion_span: Span,
anon_lts: String,
) { ) {
let (replace_span, suggestion) = if incl_angl_brckt { diag.span_label(path_span, format!("expected lifetime parameter{}", pluralize!(n)));
(insertion_span, anon_lts) if source_map.span_to_snippet(insertion_span).is_err() {
} else { // Do not try to suggest anything if generated by a proc-macro.
// When possible, prefer a suggestion that replaces the whole return;
// `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, ` }
// at a point (which makes for an ugly/confusing label) let anon_lts = vec!["'_"; n].join(", ");
if let Ok(snippet) = source_map.span_to_snippet(path_span) { let suggestion =
// But our spans can get out of whack due to macros; if the place we think if incl_angl_brckt { format!("<{}>", anon_lts) } else { format!("{}, ", anon_lts) };
// we want to insert `'_` isn't even within the path expression's span, we diag.span_suggestion_verbose(
// should bail out of making any suggestion rather than panicking on a insertion_span.shrink_to_hi(),
// 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)
}
};
diag.span_suggestion(
replace_span,
&format!("indicate the anonymous lifetime{}", pluralize!(n)), &format!("indicate the anonymous lifetime{}", pluralize!(n)),
suggestion, suggestion,
Applicability::MachineApplicable, Applicability::MachineApplicable,

View File

@ -95,7 +95,7 @@ pub enum LifetimeName {
/// User wrote nothing (e.g., the lifetime in `&u32`). /// User wrote nothing (e.g., the lifetime in `&u32`).
/// ///
/// The bool indicates whether the user should have written something. /// The bool indicates whether the user should have written something.
Implicit(bool), Implicit,
/// Implicit lifetime in a context like `dyn Foo`. This is /// Implicit lifetime in a context like `dyn Foo`. This is
/// distinguished from implicit lifetimes elsewhere because the /// distinguished from implicit lifetimes elsewhere because the
@ -125,7 +125,7 @@ impl LifetimeName {
pub fn ident(&self) -> Ident { pub fn ident(&self) -> Ident {
match *self { match *self {
LifetimeName::ImplicitObjectLifetimeDefault LifetimeName::ImplicitObjectLifetimeDefault
| LifetimeName::Implicit(_) | LifetimeName::Implicit
| LifetimeName::Error => Ident::empty(), | LifetimeName::Error => Ident::empty(),
LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime), LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime),
LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime), LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
@ -136,7 +136,7 @@ impl LifetimeName {
pub fn is_elided(&self) -> bool { pub fn is_elided(&self) -> bool {
match self { match self {
LifetimeName::ImplicitObjectLifetimeDefault LifetimeName::ImplicitObjectLifetimeDefault
| LifetimeName::Implicit(_) | LifetimeName::Implicit
| LifetimeName::Underscore => true, | LifetimeName::Underscore => true,
// It might seem surprising that `Fresh(_)` counts as // It might seem surprising that `Fresh(_)` counts as

View File

@ -528,7 +528,7 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime
| LifetimeName::Param(ParamName::Error) | LifetimeName::Param(ParamName::Error)
| LifetimeName::Static | LifetimeName::Static
| LifetimeName::Error | LifetimeName::Error
| LifetimeName::Implicit(_) | LifetimeName::Implicit
| LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::ImplicitObjectLifetimeDefault
| LifetimeName::Underscore => {} | LifetimeName::Underscore => {}
} }

View File

@ -441,6 +441,7 @@ impl EarlyLintPass for UnsafeCode {
_, _,
ast::FnSig { header: ast::FnHeader { unsafety: ast::Unsafe::Yes(_), .. }, .. }, ast::FnSig { header: ast::FnHeader { unsafety: ast::Unsafe::Yes(_), .. }, .. },
_, _,
_,
body, body,
) = fk ) = fk
{ {

View File

@ -21,7 +21,8 @@ use crate::passes::{EarlyLintPassObject, LateLintPassObject};
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync; use rustc_data_structures::sync;
use rustc_errors::{struct_span_err, Applicability, MultiSpan, SuggestionStyle}; use rustc_errors::{add_elided_lifetime_in_path_suggestion, struct_span_err};
use rustc_errors::{Applicability, MultiSpan, SuggestionStyle};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::def_id::{CrateNum, DefId};
@ -665,6 +666,21 @@ pub trait LintContext: Sized {
) => { ) => {
db.span_note(span_def, "the macro is defined here"); db.span_note(span_def, "the macro is defined here");
} }
BuiltinLintDiagnostics::ElidedLifetimesInPaths(
n,
path_span,
incl_angl_brckt,
insertion_span,
) => {
add_elided_lifetime_in_path_suggestion(
sess.source_map(),
&mut db,
n,
path_span,
incl_angl_brckt,
insertion_span,
);
}
BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => { BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
db.span_suggestion(span, &note, sugg, Applicability::MaybeIncorrect); db.span_suggestion(span, &note, sugg, Applicability::MaybeIncorrect);
} }

View File

@ -158,7 +158,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
// Explicitly check for lints associated with 'closure_id', since // Explicitly check for lints associated with 'closure_id', since
// it does not have a corresponding AST node // it does not have a corresponding AST node
if let ast_visit::FnKind::Fn(_, _, sig, _, _) = fk { if let ast_visit::FnKind::Fn(_, _, sig, _, _, _) = fk {
if let ast::Async::Yes { closure_id, .. } = sig.header.asyncness { if let ast::Async::Yes { closure_id, .. } = sig.header.asyncness {
self.check_id(closure_id); self.check_id(closure_id);
} }
@ -284,6 +284,11 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
ast_visit::walk_path(self, p); ast_visit::walk_path(self, p);
} }
fn visit_path_segment(&mut self, path_span: Span, s: &'a ast::PathSegment) {
self.check_id(s.id);
ast_visit::walk_path_segment(self, path_span, s);
}
fn visit_attribute(&mut self, attr: &'a ast::Attribute) { fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
run_early_pass!(self, check_attribute, attr); run_early_pass!(self, check_attribute, attr);
} }

View File

@ -418,6 +418,7 @@ pub enum BuiltinLintDiagnostics {
AbsPathWithModule(Span), AbsPathWithModule(Span),
ProcMacroDeriveResolutionFallback(Span), ProcMacroDeriveResolutionFallback(Span),
MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
ElidedLifetimesInPaths(usize, Span, bool, Span),
UnknownCrateTypes(Span, String, String), UnknownCrateTypes(Span, String, String),
UnusedImports(String, Vec<(Span, String)>, Option<Span>), UnusedImports(String, Vec<(Span, String)>, Option<Span>),
RedundantImport(Vec<(Span, bool)>, Ident), RedundantImport(Vec<(Span, bool)>, Ident),

View File

@ -521,11 +521,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
// while the current crate doesn't have a valid `crate_name`. // while the current crate doesn't have a valid `crate_name`.
if crate_name != kw::Empty { if crate_name != kw::Empty {
// `crate_name` should not be interpreted as relative. // `crate_name` should not be interpreted as relative.
module_path.push(Segment { module_path.push(Segment::from_ident_and_id(
ident: Ident { name: kw::PathRoot, span: source.ident.span }, Ident { name: kw::PathRoot, span: source.ident.span },
id: Some(self.r.next_node_id()), self.r.next_node_id(),
has_generic_args: false, ));
});
source.ident.name = crate_name; source.ident.name = crate_name;
} }
if rename.is_none() { if rename.is_none() {

View File

@ -133,8 +133,10 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
} }
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
if let FnKind::Fn(_, _, sig, _, body) = fn_kind { if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind {
if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness { if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness {
self.visit_generics(generics);
let return_impl_trait_id = let return_impl_trait_id =
self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span);

View File

@ -1402,7 +1402,7 @@ impl<'a> Resolver<'a> {
let mut allow_super = true; let mut allow_super = true;
let mut second_binding = None; let mut second_binding = None;
for (i, &Segment { ident, id, has_generic_args: _ }) in path.iter().enumerate() { for (i, &Segment { ident, id, .. }) in path.iter().enumerate() {
debug!("resolve_path ident {} {:?} {:?}", i, ident, id); debug!("resolve_path ident {} {:?} {:?}", i, ident, id);
let record_segment_res = |this: &mut Self, res| { let record_segment_res = |this: &mut Self, res| {
if finalize.is_some() { if finalize.is_some() {

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion}; use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion};
use crate::late::lifetimes::{ElisionFailureInfo, LifetimeContext}; use crate::late::lifetimes::{ElisionFailureInfo, LifetimeContext};
use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind}; use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind};
use crate::late::{LifetimeBinderKind, LifetimeRibKind};
use crate::path_names_to_string; use crate::path_names_to_string;
use crate::{Finalize, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{Finalize, Module, ModuleKind, ModuleOrUniformRoot};
use crate::{PathResult, PathSource, Segment}; use crate::{PathResult, PathSource, Segment};
@ -1793,6 +1794,102 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
(*ident, within_scope) (*ident, within_scope)
}) })
} }
crate fn emit_undeclared_lifetime_error(
&self,
lifetime_ref: &ast::Lifetime,
outer_lifetime_ref: Option<Ident>,
) {
debug_assert_ne!(lifetime_ref.ident.name, kw::UnderscoreLifetime);
let mut err = if let Some(outer) = outer_lifetime_ref {
let mut err = struct_span_err!(
self.r.session,
lifetime_ref.ident.span,
E0401,
"can't use generic parameters from outer item",
);
err.span_label(lifetime_ref.ident.span, "use of generic parameter from outer item");
err.span_label(outer.span, "lifetime parameter from outer item");
err
} else {
let mut err = struct_span_err!(
self.r.session,
lifetime_ref.ident.span,
E0261,
"use of undeclared lifetime name `{}`",
lifetime_ref.ident
);
err.span_label(lifetime_ref.ident.span, "undeclared lifetime");
err
};
let mut suggest_note = true;
for rib in self.lifetime_ribs.iter().rev() {
match rib.kind {
LifetimeRibKind::Generics { span, kind } => {
if !span.can_be_used_for_suggestions() && suggest_note {
suggest_note = false; // Avoid displaying the same help multiple times.
err.span_label(
span,
&format!(
"lifetime `{}` is missing in item created through this procedural macro",
lifetime_ref.ident,
),
);
continue;
}
let higher_ranked = matches!(
kind,
LifetimeBinderKind::BareFnType
| LifetimeBinderKind::PolyTrait
| LifetimeBinderKind::WhereBound
);
let (span, sugg) = if span.is_empty() {
let sugg = format!(
"{}<{}>{}",
if higher_ranked { "for" } else { "" },
lifetime_ref.ident,
if higher_ranked { " " } else { "" },
);
(span, sugg)
} else {
let span =
self.r.session.source_map().span_through_char(span, '<').shrink_to_hi();
let sugg = format!("{}, ", lifetime_ref.ident);
(span, sugg)
};
if higher_ranked {
err.span_suggestion(
span,
&format!(
"consider making the {} lifetime-generic with a new `{}` lifetime",
kind.descr(),
lifetime_ref
),
sugg,
Applicability::MaybeIncorrect,
);
err.note_once(
"for more information on higher-ranked polymorphism, visit \
https://doc.rust-lang.org/nomicon/hrtb.html",
);
} else {
err.span_suggestion(
span,
&format!("consider introducing lifetime `{}` here", lifetime_ref.ident),
sugg,
Applicability::MaybeIncorrect,
);
}
}
LifetimeRibKind::Item => break,
_ => {}
}
}
err.emit();
}
} }
impl<'tcx> LifetimeContext<'_, 'tcx> { impl<'tcx> LifetimeContext<'_, 'tcx> {
@ -1810,67 +1907,6 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
) )
} }
crate fn emit_undeclared_lifetime_error(&self, lifetime_ref: &hir::Lifetime) {
let mut err = struct_span_err!(
self.tcx.sess,
lifetime_ref.span,
E0261,
"use of undeclared lifetime name `{}`",
lifetime_ref
);
err.span_label(lifetime_ref.span, "undeclared lifetime");
let mut suggested_spans = vec![];
for missing in &self.missing_named_lifetime_spots {
match missing {
MissingLifetimeSpot::Generics(generics) => {
let (span, sugg) = if let Some(param) = generics.params.iter().find(|p| {
!matches!(
p.kind,
hir::GenericParamKind::Type { synthetic: true, .. }
| hir::GenericParamKind::Lifetime {
kind: hir::LifetimeParamKind::Elided,
}
)
}) {
(param.span.shrink_to_lo(), format!("{}, ", lifetime_ref))
} else {
(generics.span, format!("<{}>", lifetime_ref))
};
if suggested_spans.contains(&span) {
continue;
}
suggested_spans.push(span);
if span.can_be_used_for_suggestions() {
err.span_suggestion(
span,
&format!("consider introducing lifetime `{}` here", lifetime_ref),
sugg,
Applicability::MaybeIncorrect,
);
}
}
MissingLifetimeSpot::HigherRanked { span, span_type } => {
err.span_suggestion(
*span,
&format!(
"consider making the {} lifetime-generic with a new `{}` lifetime",
span_type.descr(),
lifetime_ref
),
span_type.suggestion(&lifetime_ref.to_string()),
Applicability::MaybeIncorrect,
);
err.note(
"for more information on higher-ranked polymorphism, visit \
https://doc.rust-lang.org/nomicon/hrtb.html",
);
}
_ => {}
}
}
err.emit();
}
/// Returns whether to add `'static` lifetime to the suggested lifetime list. /// Returns whether to add `'static` lifetime to the suggested lifetime list.
crate fn report_elision_failure( crate fn report_elision_failure(
&mut self, &mut self,
@ -1950,38 +1986,6 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
} }
} }
crate fn report_elided_lifetime_in_ty(&self, lifetime_refs: &[&hir::Lifetime]) {
let Some(missing_lifetime) = lifetime_refs.iter().find(|lt| {
lt.name == hir::LifetimeName::Implicit(true)
}) else { return };
let mut spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect();
spans.sort();
let mut spans_dedup = spans.clone();
spans_dedup.dedup();
let spans_with_counts: Vec<_> = spans_dedup
.into_iter()
.map(|sp| (sp, spans.iter().filter(|nsp| *nsp == &sp).count()))
.collect();
self.tcx.struct_span_lint_hir(
rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
missing_lifetime.hir_id,
spans,
|lint| {
let mut db = lint.build("hidden lifetime parameters in types are deprecated");
self.add_missing_lifetime_specifiers_label(
&mut db,
spans_with_counts,
&FxHashSet::from_iter([kw::UnderscoreLifetime]),
Vec::new(),
&[],
);
db.emit();
},
);
}
// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const // FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
// generics. We are disallowing this until we can decide on how we want to handle non-'static // generics. We are disallowing this until we can decide on how we want to handle non-'static
// lifetimes in const generics. See issue #74052 for discussion. // lifetimes in const generics. See issue #74052 for discussion.
@ -2416,9 +2420,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
); );
let is_allowed_lifetime = matches!( let is_allowed_lifetime = matches!(
lifetime_ref.name, lifetime_ref.name,
hir::LifetimeName::Implicit(_) hir::LifetimeName::Implicit | hir::LifetimeName::Static | hir::LifetimeName::Underscore
| hir::LifetimeName::Static
| hir::LifetimeName::Underscore
); );
if !self.tcx.lazy_normalization() && is_anon_const && !is_allowed_lifetime { if !self.tcx.lazy_normalization() && is_anon_const && !is_allowed_lifetime {

View File

@ -164,9 +164,6 @@ crate struct LifetimeContext<'a, 'tcx> {
map: &'a mut NamedRegionMap, map: &'a mut NamedRegionMap,
scope: ScopeRef<'a>, scope: ScopeRef<'a>,
/// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax.
is_in_fn_syntax: bool,
is_in_const_generic: bool, is_in_const_generic: bool,
/// Indicates that we only care about the definition of a trait. This should /// Indicates that we only care about the definition of a trait. This should
@ -455,7 +452,6 @@ fn do_resolve(
tcx, tcx,
map: &mut named_region_map, map: &mut named_region_map,
scope: ROOT_SCOPE, scope: ROOT_SCOPE,
is_in_fn_syntax: false,
is_in_const_generic: false, is_in_const_generic: false,
trait_definition_only, trait_definition_only,
labels_in_fn: vec![], labels_in_fn: vec![],
@ -874,8 +870,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
match ty.kind { match ty.kind {
hir::TyKind::BareFn(ref c) => { hir::TyKind::BareFn(ref c) => {
let next_early_index = self.next_early_index(); let next_early_index = self.next_early_index();
let was_in_fn_syntax = self.is_in_fn_syntax;
self.is_in_fn_syntax = true;
let lifetime_span: Option<Span> = let lifetime_span: Option<Span> =
c.generic_params.iter().rev().find_map(|param| match param.kind { c.generic_params.iter().rev().find_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => Some(param.span), GenericParamKind::Lifetime { .. } => Some(param.span),
@ -917,7 +911,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
intravisit::walk_ty(this, ty); intravisit::walk_ty(this, ty);
}); });
self.missing_named_lifetime_spots.pop(); self.missing_named_lifetime_spots.pop();
self.is_in_fn_syntax = was_in_fn_syntax;
} }
hir::TyKind::TraitObject(bounds, ref lifetime, _) => { hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
debug!(?bounds, ?lifetime, "TraitObject"); debug!(?bounds, ?lifetime, "TraitObject");
@ -928,7 +921,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
} }
}); });
match lifetime.name { match lifetime.name {
LifetimeName::Implicit(_) => { LifetimeName::Implicit => {
// For types like `dyn Foo`, we should // For types like `dyn Foo`, we should
// generate a special form of elided. // generate a special form of elided.
span_bug!(ty.span, "object-lifetime-default expected, not implicit",); span_bug!(ty.span, "object-lifetime-default expected, not implicit",);
@ -1805,7 +1798,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
tcx: *tcx, tcx: *tcx,
map, map,
scope: &wrap_scope, scope: &wrap_scope,
is_in_fn_syntax: self.is_in_fn_syntax,
is_in_const_generic: self.is_in_const_generic, is_in_const_generic: self.is_in_const_generic,
trait_definition_only: self.trait_definition_only, trait_definition_only: self.trait_definition_only,
labels_in_fn, labels_in_fn,
@ -2320,7 +2312,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
self.insert_lifetime(lifetime_ref, def); self.insert_lifetime(lifetime_ref, def);
} else { } else {
self.emit_undeclared_lifetime_error(lifetime_ref); self.tcx.sess.delay_span_bug(
lifetime_ref.span,
&format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
);
} }
} }
@ -2336,10 +2331,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
); );
if generic_args.parenthesized { if generic_args.parenthesized {
let was_in_fn_syntax = self.is_in_fn_syntax;
self.is_in_fn_syntax = true;
self.visit_fn_like_elision(generic_args.inputs(), Some(generic_args.bindings[0].ty())); self.visit_fn_like_elision(generic_args.inputs(), Some(generic_args.bindings[0].ty()));
self.is_in_fn_syntax = was_in_fn_syntax;
return; return;
} }
@ -2963,9 +2955,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
let error = loop { let error = loop {
match *scope { match *scope {
// Do not assign any resolution, it will be inferred. // Do not assign any resolution, it will be inferred.
Scope::Body { .. } => break Ok(()), Scope::Body { .. } => return,
Scope::Root => break Err(None), Scope::Root => break None,
Scope::Binder { s, ref lifetimes, scope_type, .. } => { Scope::Binder { s, ref lifetimes, scope_type, .. } => {
// collect named lifetimes for suggestions // collect named lifetimes for suggestions
@ -2992,7 +2984,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
self.insert_lifetime(lifetime_ref, lifetime); self.insert_lifetime(lifetime_ref, lifetime);
} }
break Ok(()); return;
} }
Scope::Elision { elide: Elide::Exact(l), .. } => { Scope::Elision { elide: Elide::Exact(l), .. } => {
@ -3000,7 +2992,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
for lifetime_ref in lifetime_refs { for lifetime_ref in lifetime_refs {
self.insert_lifetime(lifetime_ref, lifetime); self.insert_lifetime(lifetime_ref, lifetime);
} }
break Ok(()); return;
} }
Scope::Elision { elide: Elide::Error(ref e), ref s, .. } => { Scope::Elision { elide: Elide::Error(ref e), ref s, .. } => {
@ -3025,10 +3017,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
_ => break, _ => break,
} }
} }
break Err(Some(&e[..])); break Some(&e[..]);
} }
Scope::Elision { elide: Elide::Forbid, .. } => break Err(None), Scope::Elision { elide: Elide::Forbid, .. } => break None,
Scope::ObjectLifetimeDefault { s, .. } Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. } | Scope::Supertrait { s, .. }
@ -3038,14 +3030,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
} }
}; };
let error = match error {
Ok(()) => {
self.report_elided_lifetime_in_ty(lifetime_refs);
return;
}
Err(error) => error,
};
// If we specifically need the `scope_for_path` map, then we're in the // If we specifically need the `scope_for_path` map, then we're in the
// diagnostic pass and we don't want to emit more errors. // diagnostic pass and we don't want to emit more errors.
if self.map.scope_for_path.is_some() { if self.map.scope_for_path.is_some() {
@ -3130,18 +3114,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
if let hir::ParamName::Plain(_) = lifetime_i_name { if let hir::ParamName::Plain(_) = lifetime_i_name {
let name = lifetime_i_name.ident().name; let name = lifetime_i_name.ident().name;
if name == kw::UnderscoreLifetime || name == kw::StaticLifetime { if name == kw::UnderscoreLifetime || name == kw::StaticLifetime {
let mut err = struct_span_err!( self.tcx.sess.delay_span_bug(
self.tcx.sess,
lifetime_i.span, lifetime_i.span,
E0262, &format!("invalid lifetime parameter name: `{}`", lifetime_i.name.ident()),
"invalid lifetime parameter name: `{}`",
lifetime_i.name.ident(),
); );
err.span_label(
lifetime_i.span,
format!("{} is a reserved lifetime name", name),
);
err.emit();
} }
} }
@ -3190,7 +3166,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
)) ))
.emit(); .emit();
} }
hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit(_) => { hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => {
self.resolve_lifetime_ref(lt); self.resolve_lifetime_ref(lt);
} }
hir::LifetimeName::ImplicitObjectLifetimeDefault => { hir::LifetimeName::ImplicitObjectLifetimeDefault => {

View File

@ -11,6 +11,7 @@
#![feature(drain_filter)] #![feature(drain_filter)]
#![feature(bool_to_option)] #![feature(bool_to_option)]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(if_let_guard)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(let_else)] #![feature(let_else)]
#![feature(never_type)] #![feature(never_type)]
@ -27,7 +28,7 @@ pub use rustc_hir::def::{Namespace, PerNS};
use rustc_arena::{DroplessArena, TypedArena}; use rustc_arena::{DroplessArena, TypedArena};
use rustc_ast::node_id::NodeMap; use rustc_ast::node_id::NodeMap;
use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID}; use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID};
use rustc_ast::{Crate, Expr, ExprKind, LitKind, Path}; use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path};
use rustc_ast_lowering::ResolverAstLowering; use rustc_ast_lowering::ResolverAstLowering;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::intern::Interned; use rustc_data_structures::intern::Interned;
@ -282,6 +283,9 @@ pub struct Segment {
/// Signals whether this `PathSegment` has generic arguments. Used to avoid providing /// Signals whether this `PathSegment` has generic arguments. Used to avoid providing
/// nonsensical suggestions. /// nonsensical suggestions.
has_generic_args: bool, has_generic_args: bool,
/// Signals whether this `PathSegment` has lifetime arguments.
has_lifetime_args: bool,
args_span: Span,
} }
impl Segment { impl Segment {
@ -290,7 +294,23 @@ impl Segment {
} }
fn from_ident(ident: Ident) -> Segment { fn from_ident(ident: Ident) -> Segment {
Segment { ident, id: None, has_generic_args: false } Segment {
ident,
id: None,
has_generic_args: false,
has_lifetime_args: false,
args_span: DUMMY_SP,
}
}
fn from_ident_and_id(ident: Ident, id: NodeId) -> Segment {
Segment {
ident,
id: Some(id),
has_generic_args: false,
has_lifetime_args: false,
args_span: DUMMY_SP,
}
} }
fn names_to_string(segments: &[Segment]) -> String { fn names_to_string(segments: &[Segment]) -> String {
@ -300,7 +320,28 @@ impl Segment {
impl<'a> From<&'a ast::PathSegment> for Segment { impl<'a> From<&'a ast::PathSegment> for Segment {
fn from(seg: &'a ast::PathSegment) -> Segment { fn from(seg: &'a ast::PathSegment) -> Segment {
Segment { ident: seg.ident, id: Some(seg.id), has_generic_args: seg.args.is_some() } let has_generic_args = seg.args.is_some();
let (args_span, has_lifetime_args) = if let Some(args) = seg.args.as_deref() {
match args {
GenericArgs::AngleBracketed(args) => {
let found_lifetimes = args
.args
.iter()
.any(|arg| matches!(arg, AngleBracketedArg::Arg(GenericArg::Lifetime(_))));
(args.span, found_lifetimes)
}
GenericArgs::Parenthesized(args) => (args.span, true),
}
} else {
(DUMMY_SP, false)
};
Segment {
ident: seg.ident,
id: Some(seg.id),
has_generic_args,
has_lifetime_args,
args_span,
}
} }
} }
@ -1358,9 +1399,17 @@ impl<'a> Resolver<'a> {
} }
pub fn next_node_id(&mut self) -> NodeId { pub fn next_node_id(&mut self) -> NodeId {
let next = let start = self.next_node_id;
self.next_node_id.as_u32().checked_add(1).expect("input too large; ran out of NodeIds"); let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
mem::replace(&mut self.next_node_id, ast::NodeId::from_u32(next)) self.next_node_id = ast::NodeId::from_u32(next);
start
}
pub fn next_node_ids(&mut self, count: usize) -> std::ops::Range<NodeId> {
let start = self.next_node_id;
let end = start.as_usize().checked_add(count).expect("input too large; ran out of NodeIds");
self.next_node_id = ast::NodeId::from_usize(end);
start..self.next_node_id
} }
pub fn lint_buffer(&mut self) -> &mut LintBuffer { pub fn lint_buffer(&mut self) -> &mut LintBuffer {

View File

@ -2,9 +2,13 @@ error[E0726]: implicit elided lifetime not allowed here
--> $DIR/async-fn-path-elision.rs:5:20 --> $DIR/async-fn-path-elision.rs:5:20
| |
LL | async fn error(lt: HasLifetime) { LL | async fn error(lt: HasLifetime) {
| ^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>` | ^^^^^^^^^^^ expected lifetime parameter
| |
= note: assuming a `'static` lifetime... = note: assuming a `'static` lifetime...
help: indicate the anonymous lifetime
|
LL | async fn error(lt: HasLifetime<'_>) {
| ++++
error: aborting due to previous error error: aborting due to previous error

View File

@ -2,9 +2,17 @@ error[E0261]: use of undeclared lifetime name `'x`
--> $DIR/gat-in-trait-path-undeclared-lifetime.rs:8:35 --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:8:35
| |
LL | fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {} LL | fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
| - ^^ undeclared lifetime | ^^ undeclared lifetime
| | |
| help: consider introducing lifetime `'x` here: `<'x>` = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the bound lifetime-generic with a new `'x` lifetime
|
LL | fn _f(arg : Box<dyn for<'x, 'a> X<Y<'x> = &'a [u32]>>) {}
| +++
help: consider introducing lifetime `'x` here
|
LL | fn _f<'x>(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
| ++++
error[E0582]: binding for associated type `Y` references lifetime `'a`, which does not appear in the trait input types error[E0582]: binding for associated type `Y` references lifetime `'a`, which does not appear in the trait input types
--> $DIR/gat-in-trait-path-undeclared-lifetime.rs:8:33 --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:8:33

View File

@ -4,14 +4,19 @@ error[E0261]: use of undeclared lifetime name `'b`
LL | + Deref<Target = Self::Item<'b>>; LL | + Deref<Target = Self::Item<'b>>;
| ^^ undeclared lifetime | ^^ undeclared lifetime
| |
help: consider introducing lifetime `'b` here = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the bound lifetime-generic with a new `'b` lifetime
| |
LL | trait Iterable<'b> { LL | + for<'b> Deref<Target = Self::Item<'b>>;
| ++++ | +++++++
help: consider introducing lifetime `'b` here help: consider introducing lifetime `'b` here
| |
LL | type Iter<'b, 'a>: Iterator<Item = Self::Item<'a>> LL | type Iter<'b, 'a>: Iterator<Item = Self::Item<'a>>
| +++ | +++
help: consider introducing lifetime `'b` here
|
LL | trait Iterable<'b> {
| ++++
error[E0261]: use of undeclared lifetime name `'undeclared` error[E0261]: use of undeclared lifetime name `'undeclared`
--> $DIR/generic_associated_type_undeclared_lifetimes.rs:11:41 --> $DIR/generic_associated_type_undeclared_lifetimes.rs:11:41
@ -21,12 +26,12 @@ LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
| |
help: consider introducing lifetime `'undeclared` here help: consider introducing lifetime `'undeclared` here
| |
LL | trait Iterable<'undeclared> {
| +++++++++++++
help: consider introducing lifetime `'undeclared` here
|
LL | fn iter<'undeclared, 'a>(&'a self) -> Self::Iter<'undeclared>; LL | fn iter<'undeclared, 'a>(&'a self) -> Self::Iter<'undeclared>;
| ++++++++++++ | ++++++++++++
help: consider introducing lifetime `'undeclared` here
|
LL | trait Iterable<'undeclared> {
| +++++++++++++
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -4,9 +4,9 @@ trait X {
type Y<'a>; type Y<'a>;
} }
fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {} fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
//~^ ERROR: use of undeclared lifetime name `'a` //~^ ERROR: use of undeclared lifetime name `'a`
//~| ERROR: use of undeclared lifetime name `'a` //~| ERROR: use of undeclared lifetime name `'a`
//~| ERROR: the trait `X` cannot be made into an object [E0038]
fn main() {} fn main() {}

View File

@ -1,19 +1,50 @@
error[E0261]: use of undeclared lifetime name `'a` error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/issue-67510.rs:7:21 --> $DIR/issue-67510.rs:7:21
| |
LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {} LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
| - ^^ undeclared lifetime | ^^ undeclared lifetime
| | |
| help: consider introducing lifetime `'a` here: `<'a>` = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the bound lifetime-generic with a new `'a` lifetime
|
LL | fn f(x: Box<dyn for<'a> X<Y<'a> = &'a ()>>) {}
| +++++++
help: consider introducing lifetime `'a` here
|
LL | fn f<'a>(x: Box<dyn X<Y<'a> = &'a ()>>) {}
| ++++
error[E0261]: use of undeclared lifetime name `'a` error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/issue-67510.rs:7:26 --> $DIR/issue-67510.rs:7:28
| |
LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {} LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
| - ^^ undeclared lifetime | ^^ undeclared lifetime
| | |
| help: consider introducing lifetime `'a` here: `<'a>` help: consider making the bound lifetime-generic with a new `'a` lifetime
|
LL | fn f(x: Box<dyn for<'a> X<Y<'a> = &'a ()>>) {}
| +++++++
help: consider introducing lifetime `'a` here
|
LL | fn f<'a>(x: Box<dyn X<Y<'a> = &'a ()>>) {}
| ++++
error: aborting due to 2 previous errors error[E0038]: the trait `X` cannot be made into an object
--> $DIR/issue-67510.rs:7:13
|
LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
| ^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-67510.rs:4:10
|
LL | trait X {
| - this trait cannot be made into an object...
LL | type Y<'a>;
| ^ ...because it contains the generic associated type `Y`
= help: consider moving `Y` to another trait
For more information about this error, try `rustc --explain E0261`. error: aborting due to 3 previous errors
Some errors have detailed explanations: E0038, E0261.
For more information about an error, try `rustc --explain E0038`.

View File

@ -12,13 +12,10 @@ impl Document for DocumentImpl {
type Cursor<'a> = DocCursorImpl<'a>; type Cursor<'a> = DocCursorImpl<'a>;
fn cursor(&self) -> Self::Cursor<'_> { fn cursor(&self) -> Self::Cursor<'_> {
DocCursorImpl { DocCursorImpl { document: &self }
document: &self,
}
} }
} }
trait DocCursor<'a> {} trait DocCursor<'a> {}
struct DocCursorImpl<'a> { struct DocCursorImpl<'a> {
@ -35,7 +32,6 @@ where
_phantom: std::marker::PhantomData<&'d ()>, _phantom: std::marker::PhantomData<&'d ()>,
} }
impl<'d, Cursor> Lexer<'d, Cursor> impl<'d, Cursor> Lexer<'d, Cursor>
where where
Cursor: DocCursor<'d>, Cursor: DocCursor<'d>,
@ -44,15 +40,12 @@ where
where where
Doc: Document<Cursor<'d> = Cursor>, Doc: Document<Cursor<'d> = Cursor>,
{ {
Lexer { Lexer { cursor: document.cursor(), _phantom: std::marker::PhantomData }
cursor: document.cursor(),
_phantom: std::marker::PhantomData,
}
} }
} }
fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> { fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
//~^ ERROR: missing lifetime specifier //~^ ERROR: missing lifetime specifier
DocumentImpl {} DocumentImpl {}
} }

View File

@ -1,5 +1,5 @@
error[E0106]: missing lifetime specifier error[E0106]: missing lifetime specifier
--> $DIR/issue-70304.rs:54:41 --> $DIR/issue-70304.rs:47:41
| |
LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> { LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
| ^^ expected named lifetime parameter | ^^ expected named lifetime parameter

View File

@ -2,7 +2,9 @@ error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/generic-extern-lifetime.rs:6:26 --> $DIR/generic-extern-lifetime.rs:6:26
| |
LL | pub fn life2<'b>(x: &'a i32, y: &'b i32); LL | pub fn life2<'b>(x: &'a i32, y: &'b i32);
| ^^ undeclared lifetime | - ^^ undeclared lifetime
| |
| help: consider introducing lifetime `'a` here: `'a,`
error[E0261]: use of undeclared lifetime name `'a` error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/generic-extern-lifetime.rs:8:37 --> $DIR/generic-extern-lifetime.rs:8:37
@ -13,8 +15,12 @@ LL | pub fn life4<'b>(x: for<'c> fn(&'a i32));
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the type lifetime-generic with a new `'a` lifetime help: consider making the type lifetime-generic with a new `'a` lifetime
| |
LL | pub fn life4<'b>(x: for<'c, 'a> fn(&'a i32)); LL | pub fn life4<'b>(x: for<'a, 'c> fn(&'a i32));
| ++++ | +++
help: consider introducing lifetime `'a` here
|
LL | pub fn life4<'a, 'b>(x: for<'c> fn(&'a i32));
| +++
error[E0261]: use of undeclared lifetime name `'a` error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/generic-extern-lifetime.rs:11:39 --> $DIR/generic-extern-lifetime.rs:11:39
@ -22,11 +28,14 @@ error[E0261]: use of undeclared lifetime name `'a`
LL | pub fn life7<'b>() -> for<'c> fn(&'a i32); LL | pub fn life7<'b>() -> for<'c> fn(&'a i32);
| ^^ undeclared lifetime | ^^ undeclared lifetime
| |
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the type lifetime-generic with a new `'a` lifetime help: consider making the type lifetime-generic with a new `'a` lifetime
| |
LL | pub fn life7<'b>() -> for<'c, 'a> fn(&'a i32); LL | pub fn life7<'b>() -> for<'a, 'c> fn(&'a i32);
| ++++ | +++
help: consider introducing lifetime `'a` here
|
LL | pub fn life7<'a, 'b>() -> for<'c> fn(&'a i32);
| +++
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View File

@ -2,9 +2,13 @@ error[E0726]: implicit elided lifetime not allowed here
--> $DIR/path-elided.rs:7:18 --> $DIR/path-elided.rs:7:18
| |
LL | impl MyTrait for Foo { LL | impl MyTrait for Foo {
| ^^^- help: indicate the anonymous lifetime: `<'_>` | ^^^ expected lifetime parameter
| |
= note: assuming a `'static` lifetime... = note: assuming a `'static` lifetime...
help: indicate the anonymous lifetime
|
LL | impl MyTrait for Foo<'_> {
| ++++
error: aborting due to previous error error: aborting due to previous error

View File

@ -1,9 +1,8 @@
#![allow(warnings)] #![allow(warnings)]
trait MyTrait<'a> { } trait MyTrait<'a> {}
impl MyTrait for u32 { impl MyTrait for u32 {}
//~^ ERROR implicit elided lifetime not allowed here //~^ ERROR implicit elided lifetime not allowed here
}
fn main() {} fn main() {}

View File

@ -1,10 +1,14 @@
error[E0726]: implicit elided lifetime not allowed here error[E0726]: implicit elided lifetime not allowed here
--> $DIR/trait-elided.rs:5:6 --> $DIR/trait-elided.rs:5:6
| |
LL | impl MyTrait for u32 { LL | impl MyTrait for u32 {}
| ^^^^^^^- help: indicate the anonymous lifetime: `<'_>` | ^^^^^^^ expected lifetime parameter
| |
= note: assuming a `'static` lifetime... = note: assuming a `'static` lifetime...
help: indicate the anonymous lifetime
|
LL | impl MyTrait<'_> for u32 {}
| ++++
error: aborting due to previous error error: aborting due to previous error

View File

@ -1,16 +1,20 @@
trait Serializable<'self, T> { //~ ERROR lifetimes cannot use keyword names trait Serializable<'self, T> {
fn serialize(val : &'self T) -> Vec<u8>; //~ ERROR lifetimes cannot use keyword names //~^ ERROR lifetimes cannot use keyword names
fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR lifetimes cannot use keyword names fn serialize(val: &'self T) -> Vec<u8>; //~ ERROR lifetimes cannot use keyword names
fn deserialize(repr: &[u8]) -> &'self T; //~ ERROR lifetimes cannot use keyword names
} }
impl<'self> Serializable<str> for &'self str { //~ 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 lifetimes cannot use keyword names
//~| ERROR implicit elided lifetime not allowed here //~| ERROR implicit elided lifetime not allowed here
//~| ERROR the size for values of type `str` cannot be known at compilation time //~| ERROR the size for values of type `str` cannot be known at compilation time [E0277]
fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR lifetimes cannot use keyword names fn serialize(val: &'self str) -> Vec<u8> {
//~^ ERROR lifetimes cannot use keyword names
vec![1] vec![1]
} }
fn deserialize(repr: &[u8]) -> &'self str { //~ ERROR lifetimes cannot use keyword names fn deserialize(repr: &[u8]) -> &'self str {
//~^ ERROR lifetimes cannot use keyword names
"hi" "hi"
} }
} }

View File

@ -5,51 +5,55 @@ LL | trait Serializable<'self, T> {
| ^^^^^ | ^^^^^
error: lifetimes cannot use keyword names error: lifetimes cannot use keyword names
--> $DIR/issue-10412.rs:2:25 --> $DIR/issue-10412.rs:3:24
| |
LL | fn serialize(val : &'self T) -> Vec<u8>; LL | fn serialize(val: &'self T) -> Vec<u8>;
| ^^^^^ | ^^^^^
error: lifetimes cannot use keyword names error: lifetimes cannot use keyword names
--> $DIR/issue-10412.rs:3:38 --> $DIR/issue-10412.rs:4:37
| |
LL | fn deserialize(repr : &[u8]) -> &'self T; LL | fn deserialize(repr: &[u8]) -> &'self T;
| ^^^^^ | ^^^^^
error: lifetimes cannot use keyword names error: lifetimes cannot use keyword names
--> $DIR/issue-10412.rs:6:6 --> $DIR/issue-10412.rs:7:6
| |
LL | impl<'self> Serializable<str> for &'self str { LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^ | ^^^^^
error: lifetimes cannot use keyword names error: lifetimes cannot use keyword names
--> $DIR/issue-10412.rs:6:36 --> $DIR/issue-10412.rs:7:36
| |
LL | impl<'self> Serializable<str> for &'self str { LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^ | ^^^^^
error: lifetimes cannot use keyword names error: lifetimes cannot use keyword names
--> $DIR/issue-10412.rs:10:25 --> $DIR/issue-10412.rs:12:24
| |
LL | fn serialize(val : &'self str) -> Vec<u8> { LL | fn serialize(val: &'self str) -> Vec<u8> {
| ^^^^^ | ^^^^^
error: lifetimes cannot use keyword names error: lifetimes cannot use keyword names
--> $DIR/issue-10412.rs:13:37 --> $DIR/issue-10412.rs:16:37
| |
LL | fn deserialize(repr: &[u8]) -> &'self str { LL | fn deserialize(repr: &[u8]) -> &'self str {
| ^^^^^ | ^^^^^
error[E0726]: implicit elided lifetime not allowed here error[E0726]: implicit elided lifetime not allowed here
--> $DIR/issue-10412.rs:6:13 --> $DIR/issue-10412.rs:7:13
| |
LL | impl<'self> Serializable<str> for &'self str { LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Serializable<'_, str>` | ^^^^^^^^^^^^^^^^^ expected lifetime parameter
| |
= note: assuming a `'static` lifetime... = note: assuming a `'static` lifetime...
help: indicate the anonymous lifetime
|
LL | impl<'self> Serializable<'_, str> for &'self str {
| +++
error[E0277]: the size for values of type `str` cannot be known at compilation time error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/issue-10412.rs:6:13 --> $DIR/issue-10412.rs:7:13
| |
LL | impl<'self> Serializable<str> for &'self str { LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time

View File

@ -2,13 +2,17 @@ error: hidden lifetime parameters in types are deprecated
--> $DIR/issue-91763.rs:8:20 --> $DIR/issue-91763.rs:8:20
| |
LL | fn f() -> Ptr<Thing>; LL | fn f() -> Ptr<Thing>;
| ^ expected named lifetime parameter | ^ expected lifetime parameter
| |
note: the lint level is defined here note: the lint level is defined here
--> $DIR/issue-91763.rs:3:9 --> $DIR/issue-91763.rs:3:9
| |
LL | #![deny(elided_lifetimes_in_paths)] LL | #![deny(elided_lifetimes_in_paths)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
help: indicate the anonymous lifetime
|
LL | fn f() -> Ptr<Thing><'_>;
| ++++
error: aborting due to previous error error: aborting due to previous error

View File

@ -9,6 +9,8 @@ LL | a: &'b str,
error[E0261]: use of undeclared lifetime name `'b` error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9 --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
| |
LL | #[derive(Eq, PartialEq)]
| -- lifetime `'b` is missing in item created through this procedural macro
LL | struct Test { LL | struct Test {
| - help: consider introducing lifetime `'b` here: `<'b>` | - help: consider introducing lifetime `'b` here: `<'b>`
LL | a: &'b str, LL | a: &'b str,
@ -22,12 +24,12 @@ LL | fn foo(&'b self) {}
| |
help: consider introducing lifetime `'b` here help: consider introducing lifetime `'b` here
| |
LL | impl<'b> T for Test {
| ++++
help: consider introducing lifetime `'b` here
|
LL | fn foo<'b>(&'b self) {} LL | fn foo<'b>(&'b self) {}
| ++++ | ++++
help: consider introducing lifetime `'b` here
|
LL | impl<'b> T for Test {
| ++++
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View File

@ -2,13 +2,13 @@ warning: hidden lifetime parameters in types are deprecated
--> $DIR/allowed-by-default-lint.rs:9:12 --> $DIR/allowed-by-default-lint.rs:9:12
| |
LL | fn foo(x: &Foo) {} LL | fn foo(x: &Foo) {}
| ^^^ expected named lifetime parameter | ^^^ expected lifetime parameter
| |
= note: requested on the command line with `--force-warn elided-lifetimes-in-paths` = note: requested on the command line with `--force-warn elided-lifetimes-in-paths`
help: consider using the `'_` lifetime help: indicate the anonymous lifetime
| |
LL | fn foo(x: &Foo<'_>) {} LL | fn foo(x: &Foo<'_>) {}
| ~~~~~~~ | ++++
warning: 1 warning emitted warning: 1 warning emitted

View File

@ -19,9 +19,9 @@ pub struct CheaterDetectionMechanism {}
impl fmt::Debug for CheaterDetectionMechanism { impl fmt::Debug for CheaterDetectionMechanism {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
//~^ WARN hidden lifetime parameters in types are deprecated //~^ WARN hidden lifetime parameters in types are deprecated
//~| NOTE expected named lifetime parameter //~| NOTE expected lifetime parameter
//~| NOTE explicit anonymous lifetimes aid //~| NOTE explicit anonymous lifetimes aid
//~| HELP consider using the `'_` lifetime //~| HELP indicate the anonymous lifetime
fmt.debug_struct("CheaterDetectionMechanism").finish() fmt.debug_struct("CheaterDetectionMechanism").finish()
} }
} }

View File

@ -2,7 +2,9 @@ warning: hidden lifetime parameters in types are deprecated
--> $DIR/reasons.rs:20:34 --> $DIR/reasons.rs:20:34
| |
LL | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { LL | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
| ^^^^^^^^^ expected named lifetime parameter | -----^^^^^^^^^
| |
| expected lifetime parameter
| |
= note: explicit anonymous lifetimes aid reasoning about ownership = note: explicit anonymous lifetimes aid reasoning about ownership
note: the lint level is defined here note: the lint level is defined here
@ -10,10 +12,10 @@ note: the lint level is defined here
| |
LL | #![warn(elided_lifetimes_in_paths, LL | #![warn(elided_lifetimes_in_paths,
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider using the `'_` lifetime help: indicate the anonymous lifetime
| |
LL | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { LL | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
| ~~~~~~~~~~~~~ | ++++
warning: variable `Social_exchange_psychology` should have a snake case name warning: variable `Social_exchange_psychology` should have a snake case name
--> $DIR/reasons.rs:30:9 --> $DIR/reasons.rs:30:9

View File

@ -1,3 +1,6 @@
fn main() { fn main() {
0.clone::<'a>(); //~ ERROR use of undeclared lifetime name `'a` 0.clone::<'a>();
//~^ ERROR use of undeclared lifetime name `'a`
//~| WARN cannot specify lifetime arguments explicitly if late bound
//~| WARN this was previously accepted by the compiler
} }

View File

@ -6,6 +6,21 @@ LL | fn main() {
LL | 0.clone::<'a>(); LL | 0.clone::<'a>();
| ^^ undeclared lifetime | ^^ undeclared lifetime
error: aborting due to previous error warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-unresolved.rs:2:15
|
LL | 0.clone::<'a>();
| ^^
|
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
LL | fn clone(&self) -> Self;
| - the late bound lifetime parameter is introduced here
|
= note: `#[warn(late_bound_lifetime_arguments)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0261`. For more information about this error, try `rustc --explain E0261`.

View File

@ -1,5 +1,6 @@
struct Foo<'static> { //~ ERROR invalid lifetime parameter name: `'static` struct Foo<'static> {
x: &'static isize //~^ ERROR invalid lifetime parameter name: `'static`
x: &'static isize,
} }
fn main() {} fn main() {}

View File

@ -23,14 +23,14 @@ fn bar<'a>(x: &'a isize) {
let y: &'a isize = x; let y: &'a isize = x;
// &'a is not visible to *items*: // &'a is not visible to *items*:
type X = Option<&'a isize>; //~ ERROR undeclared lifetime type X = Option<&'a isize>; //~ ERROR can't use generic parameters from outer item
enum E { enum E {
E1(&'a isize) //~ ERROR undeclared lifetime E1(&'a isize) //~ ERROR can't use generic parameters from outer item
} }
struct S { struct S {
f: &'a isize //~ ERROR undeclared lifetime f: &'a isize //~ ERROR can't use generic parameters from outer item
} }
fn f(a: &'a isize) { } //~ ERROR undeclared lifetime fn f(a: &'a isize) { } //~ ERROR can't use generic parameters from outer item
// &'a CAN be declared on functions and used then: // &'a CAN be declared on functions and used then:
fn g<'a>(a: &'a isize) { } // OK fn g<'a>(a: &'a isize) { } // OK

View File

@ -1,19 +1,3 @@
error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/regions-name-undeclared.rs:28:13
|
LL | enum E {
| - help: consider introducing lifetime `'a` here: `<'a>`
LL | E1(&'a isize)
| ^^ undeclared lifetime
error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/regions-name-undeclared.rs:31:13
|
LL | struct S {
| - help: consider introducing lifetime `'a` here: `<'a>`
LL | f: &'a isize
| ^^ undeclared lifetime
error[E0261]: use of undeclared lifetime name `'b` error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/regions-name-undeclared.rs:16:24 --> $DIR/regions-name-undeclared.rs:16:24
| |
@ -22,12 +6,12 @@ LL | fn m4(&self, arg: &'b isize) { }
| |
help: consider introducing lifetime `'b` here help: consider introducing lifetime `'b` here
| |
LL | impl<'b, 'a> Foo<'a> {
| +++
help: consider introducing lifetime `'b` here
|
LL | fn m4<'b>(&self, arg: &'b isize) { } LL | fn m4<'b>(&self, arg: &'b isize) { }
| ++++ | ++++
help: consider introducing lifetime `'b` here
|
LL | impl<'b, 'a> Foo<'a> {
| +++
error[E0261]: use of undeclared lifetime name `'b` error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/regions-name-undeclared.rs:17:12 --> $DIR/regions-name-undeclared.rs:17:12
@ -37,12 +21,12 @@ LL | fn m5(&'b self) { }
| |
help: consider introducing lifetime `'b` here help: consider introducing lifetime `'b` here
| |
LL | impl<'b, 'a> Foo<'a> {
| +++
help: consider introducing lifetime `'b` here
|
LL | fn m5<'b>(&'b self) { } LL | fn m5<'b>(&'b self) { }
| ++++ | ++++
help: consider introducing lifetime `'b` here
|
LL | impl<'b, 'a> Foo<'a> {
| +++
error[E0261]: use of undeclared lifetime name `'b` error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/regions-name-undeclared.rs:18:27 --> $DIR/regions-name-undeclared.rs:18:27
@ -52,26 +36,54 @@ LL | fn m6(&self, arg: Foo<'b>) { }
| |
help: consider introducing lifetime `'b` here help: consider introducing lifetime `'b` here
| |
LL | impl<'b, 'a> Foo<'a> {
| +++
help: consider introducing lifetime `'b` here
|
LL | fn m6<'b>(&self, arg: Foo<'b>) { } LL | fn m6<'b>(&self, arg: Foo<'b>) { }
| ++++ | ++++
help: consider introducing lifetime `'b` here
|
LL | impl<'b, 'a> Foo<'a> {
| +++
error[E0261]: use of undeclared lifetime name `'a` error[E0401]: can't use generic parameters from outer item
--> $DIR/regions-name-undeclared.rs:26:22 --> $DIR/regions-name-undeclared.rs:26:22
| |
LL | fn bar<'a>(x: &'a isize) {
| -- lifetime parameter from outer item
...
LL | type X = Option<&'a isize>; LL | type X = Option<&'a isize>;
| - ^^ undeclared lifetime | - ^^ use of generic parameter from outer item
| | | |
| help: consider introducing lifetime `'a` here: `<'a>` | help: consider introducing lifetime `'a` here: `<'a>`
error[E0261]: use of undeclared lifetime name `'a` error[E0401]: can't use generic parameters from outer item
--> $DIR/regions-name-undeclared.rs:28:13
|
LL | fn bar<'a>(x: &'a isize) {
| -- lifetime parameter from outer item
...
LL | enum E {
| - help: consider introducing lifetime `'a` here: `<'a>`
LL | E1(&'a isize)
| ^^ use of generic parameter from outer item
error[E0401]: can't use generic parameters from outer item
--> $DIR/regions-name-undeclared.rs:31:13
|
LL | fn bar<'a>(x: &'a isize) {
| -- lifetime parameter from outer item
...
LL | struct S {
| - help: consider introducing lifetime `'a` here: `<'a>`
LL | f: &'a isize
| ^^ use of generic parameter from outer item
error[E0401]: can't use generic parameters from outer item
--> $DIR/regions-name-undeclared.rs:33:14 --> $DIR/regions-name-undeclared.rs:33:14
| |
LL | fn bar<'a>(x: &'a isize) {
| -- lifetime parameter from outer item
...
LL | fn f(a: &'a isize) { } LL | fn f(a: &'a isize) { }
| - ^^ undeclared lifetime | - ^^ use of generic parameter from outer item
| | | |
| help: consider introducing lifetime `'a` here: `<'a>` | help: consider introducing lifetime `'a` here: `<'a>`
@ -90,14 +102,14 @@ LL | ... &'b isize,
| ^^ undeclared lifetime | ^^ undeclared lifetime
| |
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the bound lifetime-generic with a new `'b` lifetime
|
LL | b: Box<dyn for<'b, 'a> FnOnce(&'a isize,
| +++
help: consider introducing lifetime `'b` here help: consider introducing lifetime `'b` here
| |
LL | fn fn_types<'b>(a: &'a isize, LL | fn fn_types<'b>(a: &'a isize,
| ++++ | ++++
help: consider making the bound lifetime-generic with a new `'b` lifetime
|
LL | b: Box<dyn for<'a, 'b> FnOnce(&'a isize,
| ++++
error[E0261]: use of undeclared lifetime name `'b` error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/regions-name-undeclared.rs:46:36 --> $DIR/regions-name-undeclared.rs:46:36
@ -105,15 +117,14 @@ error[E0261]: use of undeclared lifetime name `'b`
LL | ... &'b isize)>, LL | ... &'b isize)>,
| ^^ undeclared lifetime | ^^ undeclared lifetime
| |
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html help: consider making the bound lifetime-generic with a new `'b` lifetime
|
LL | b: Box<dyn for<'b, 'a> FnOnce(&'a isize,
| +++
help: consider introducing lifetime `'b` here help: consider introducing lifetime `'b` here
| |
LL | fn fn_types<'b>(a: &'a isize, LL | fn fn_types<'b>(a: &'a isize,
| ++++ | ++++
help: consider making the bound lifetime-generic with a new `'b` lifetime
|
LL | b: Box<dyn for<'a, 'b> FnOnce(&'a isize,
| ++++
error[E0261]: use of undeclared lifetime name `'a` error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/regions-name-undeclared.rs:47:17 --> $DIR/regions-name-undeclared.rs:47:17
@ -132,13 +143,14 @@ LL | async fn buggy(&self) -> &'a str {
| |
help: consider introducing lifetime `'a` here help: consider introducing lifetime `'a` here
| |
LL | impl<'a> Bug {
| ++++
help: consider introducing lifetime `'a` here
|
LL | async fn buggy<'a>(&self) -> &'a str { LL | async fn buggy<'a>(&self) -> &'a str {
| ++++ | ++++
help: consider introducing lifetime `'a` here
|
LL | impl<'a> Bug {
| ++++
error: aborting due to 12 previous errors error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0261`. Some errors have detailed explanations: E0261, E0401.
For more information about an error, try `rustc --explain E0261`.

View File

@ -5,14 +5,14 @@ LL | struct S1<F: Fn(&i32, &i32) -> &'a i32>(F);
| ^^ undeclared lifetime | ^^ undeclared lifetime
| |
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider introducing lifetime `'a` here
|
LL | struct S1<'a, F: Fn(&i32, &i32) -> &'a i32>(F);
| +++
help: consider making the bound lifetime-generic with a new `'a` lifetime help: consider making the bound lifetime-generic with a new `'a` lifetime
| |
LL | struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F); LL | struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
| +++++++ | +++++++
help: consider introducing lifetime `'a` here
|
LL | struct S1<'a, F: Fn(&i32, &i32) -> &'a i32>(F);
| +++
error[E0106]: missing lifetime specifier error[E0106]: missing lifetime specifier
--> $DIR/fn-missing-lifetime-in-item.rs:2:32 --> $DIR/fn-missing-lifetime-in-item.rs:2:32

View File

@ -0,0 +1,106 @@
error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/missing-lifetimes-in-signature.rs:38:11
|
LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| - ^^ undeclared lifetime
| |
| help: consider introducing lifetime `'a` here: `'a,`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/missing-lifetimes-in-signature.rs:19:5
|
LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
| ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 22:6]` captures the anonymous lifetime defined here
...
LL | / move || {
LL | |
LL | | *dest = g.get();
LL | | }
| |_____^
|
help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
|
LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ++++
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:32:5
|
LL | / move || {
LL | | *dest = g.get();
LL | | }
| |_____^
|
note: the parameter type `G` must be valid for the anonymous lifetime defined here...
--> $DIR/missing-lifetimes-in-signature.rs:26:26
|
LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^^^
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:55:5
|
LL | / move || {
LL | | *dest = g.get();
LL | | }
| |_____^
|
note: the parameter type `G` must be valid for the anonymous lifetime defined here...
--> $DIR/missing-lifetimes-in-signature.rs:49:34
|
LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^^^
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:65:9
|
LL | / move || {
LL | | *dest = g.get();
LL | | }
| |_________^
|
note: the parameter type `G` must be valid for the anonymous lifetime defined here...
--> $DIR/missing-lifetimes-in-signature.rs:62:47
|
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
| ^^^^^^
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:77:5
|
LL | / move || {
LL | | *dest = g.get();
LL | | }
| |_____^
|
note: the parameter type `G` must be valid for the anonymous lifetime defined here...
--> $DIR/missing-lifetimes-in-signature.rs:72:34
|
LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
| ^^^^^^
error[E0621]: explicit lifetime required in the type of `dest`
--> $DIR/missing-lifetimes-in-signature.rs:77:5
|
LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
| ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
...
LL | / move || {
LL | | *dest = g.get();
LL | | }
| |_____^ lifetime `'a` required
error[E0309]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:89:5
|
LL | / move || {
LL | | *dest = g.get();
LL | | }
| |_____^
|
= help: consider adding an explicit lifetime bound `G: 'a`...
error: aborting due to 8 previous errors
Some errors have detailed explanations: E0261, E0309, E0621, E0700.
For more information about an error, try `rustc --explain E0261`.

View File

@ -14,28 +14,31 @@ impl Get<usize> for Foo {
fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
where where
G: Get<T> G: Get<T>,
{ {
move || { move || {
//~^ ERROR hidden type for `impl Trait` captures lifetime
*dest = g.get(); *dest = g.get();
} }
} }
// After applying suggestion for `foo`: // After applying suggestion for `foo`:
fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
//~^ ERROR the parameter type `G` may not live long enough
where where
G: Get<T> G: Get<T>,
{ {
//~^ ERROR the parameter type `G` may not live long enough
move || { move || {
*dest = g.get(); *dest = g.get();
} }
} }
// After applying suggestion for `bar`: // After applying suggestion for `bar`:
fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ //~ ERROR undeclared lifetime fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
//~^ ERROR undeclared lifetime name `'a`
where where
G: Get<T> G: Get<T>,
{ {
move || { move || {
*dest = g.get(); *dest = g.get();
@ -44,9 +47,11 @@ where
// After applying suggestion for `baz`: // After applying suggestion for `baz`:
fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
//~^ ERROR the parameter type `G` may not live long enough
where where
G: Get<T> G: Get<T>,
{ {
//~^ ERROR the parameter type `G` may not live long enough
move || { move || {
*dest = g.get(); *dest = g.get();
} }
@ -55,6 +60,8 @@ where
// Same as above, but show that we pay attention to lifetime names from parent item // Same as above, but show that we pay attention to lifetime names from parent item
impl<'a> Foo { impl<'a> Foo {
fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
//~^ ERROR the parameter type `G` may not live long enough
//~| ERROR the parameter type `G` may not live long enough
move || { move || {
*dest = g.get(); *dest = g.get();
} }
@ -63,8 +70,9 @@ impl<'a> Foo {
// After applying suggestion for `qux`: // After applying suggestion for `qux`:
fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
//~^ ERROR explicit lifetime required in the type of `dest`
where where
G: Get<T> G: Get<T>,
{ {
move || { move || {
*dest = g.get(); *dest = g.get();
@ -73,19 +81,20 @@ where
// Potential incorrect attempt: // Potential incorrect attempt:
fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
//~^ ERROR the parameter type `G` may not live long enough
where where
G: Get<T> G: Get<T>,
{ {
//~^ ERROR the parameter type `G` may not live long enough
move || { move || {
*dest = g.get(); *dest = g.get();
} }
} }
// We need to tie the lifetime of `G` with the lifetime of `&mut T` and the returned closure: // We need to tie the lifetime of `G` with the lifetime of `&mut T` and the returned closure:
fn ok<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a fn ok<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
where where
G: Get<T> G: Get<T>,
{ {
move || { move || {
*dest = g.get(); *dest = g.get();
@ -95,7 +104,7 @@ where
// This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions: // This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions:
fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a
where where
G: Get<T> G: Get<T>,
{ {
move || { move || {
*dest = g.get(); *dest = g.get();

View File

@ -1,11 +1,234 @@
error[E0261]: use of undeclared lifetime name `'a` error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/missing-lifetimes-in-signature.rs:36:11 --> $DIR/missing-lifetimes-in-signature.rs:38:11
| |
LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| - ^^ undeclared lifetime | - ^^ undeclared lifetime
| | | |
| help: consider introducing lifetime `'a` here: `'a,` | help: consider introducing lifetime `'a` here: `'a,`
error: aborting due to previous error error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/missing-lifetimes-in-signature.rs:19:5
|
LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
| ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 22:6]` captures the anonymous lifetime defined here
...
LL | / move || {
LL | |
LL | | *dest = g.get();
LL | | }
| |_____^
|
help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
|
LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ++++
For more information about this error, try `rustc --explain E0261`. error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:26:37
|
LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^^^^^^^^^^^^^^^
|
note: the parameter type `G` must be valid for the anonymous lifetime defined here...
--> $DIR/missing-lifetimes-in-signature.rs:26:26
|
LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^^^
note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:32:5: 34:6]` will meet its required lifetime bounds
--> $DIR/missing-lifetimes-in-signature.rs:26:37
|
LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^^^^^^^^^^^^^^^
help: consider introducing an explicit lifetime bound
|
LL | fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
| ~~~~~ ++++
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:30:1
|
LL | / {
LL | |
LL | | move || {
LL | | *dest = g.get();
LL | | }
LL | | }
| |_^
|
note: the parameter type `G` must be valid for the anonymous lifetime defined here...
--> $DIR/missing-lifetimes-in-signature.rs:26:26
|
LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^^^
note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:32:5: 34:6]` will meet its required lifetime bounds
--> $DIR/missing-lifetimes-in-signature.rs:30:1
|
LL | / {
LL | |
LL | | move || {
LL | | *dest = g.get();
LL | | }
LL | | }
| |_^
help: consider introducing an explicit lifetime bound
|
LL ~ fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
LL |
LL | where
LL | G: Get<T>,
LL | {
LL |
...
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:49:45
|
LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^^^^^^^^^^^^^^^
|
note: the parameter type `G` must be valid for the anonymous lifetime defined here...
--> $DIR/missing-lifetimes-in-signature.rs:49:34
|
LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^^^
note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:55:5: 57:6]` will meet its required lifetime bounds
--> $DIR/missing-lifetimes-in-signature.rs:49:45
|
LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^^^^^^^^^^^^^^^
help: consider introducing an explicit lifetime bound
|
LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b
| +++ ~~~~~~~ ++++
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:53:1
|
LL | / {
LL | |
LL | | move || {
LL | | *dest = g.get();
LL | | }
LL | | }
| |_^
|
note: the parameter type `G` must be valid for the anonymous lifetime defined here...
--> $DIR/missing-lifetimes-in-signature.rs:49:34
|
LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^^^
note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:55:5: 57:6]` will meet its required lifetime bounds
--> $DIR/missing-lifetimes-in-signature.rs:53:1
|
LL | / {
LL | |
LL | | move || {
LL | | *dest = g.get();
LL | | }
LL | | }
| |_^
help: consider introducing an explicit lifetime bound
|
LL ~ fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
LL |
LL | where
LL | G: Get<T>,
LL | {
LL |
...
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:62:58
|
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
| ^^^^^^^^^^^^^^^^^^
|
note: the parameter type `G` must be valid for the anonymous lifetime defined here...
--> $DIR/missing-lifetimes-in-signature.rs:62:47
|
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
| ^^^^^^
note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:65:9: 67:10]` will meet its required lifetime bounds
--> $DIR/missing-lifetimes-in-signature.rs:62:58
|
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
| ^^^^^^^^^^^^^^^^^^
help: consider introducing an explicit lifetime bound
|
LL | fn qux<'c, 'b, G: 'c + Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'c {
| +++ ~~~~~~~ ++++
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:62:77
|
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
| _____________________________________________________________________________^
LL | |
LL | |
LL | | move || {
LL | | *dest = g.get();
LL | | }
LL | | }
| |_____^
|
note: the parameter type `G` must be valid for the anonymous lifetime defined here...
--> $DIR/missing-lifetimes-in-signature.rs:62:47
|
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
| ^^^^^^
note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:65:9: 67:10]` will meet its required lifetime bounds
--> $DIR/missing-lifetimes-in-signature.rs:62:77
|
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
| _____________________________________________________________________________^
LL | |
LL | |
LL | | move || {
LL | | *dest = g.get();
LL | | }
LL | | }
| |_____^
help: consider introducing an explicit lifetime bound
|
LL ~ fn qux<'c, 'b, G: 'c + Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
LL |
LL |
LL | move || {
LL | *dest = g.get();
LL | }
...
error[E0621]: explicit lifetime required in the type of `dest`
--> $DIR/missing-lifetimes-in-signature.rs:72:45
|
LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
| ------ ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
| |
| help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
error[E0309]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:83:44
|
LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
| - ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:89:5: 91:6]` will meet its required lifetime bounds
| |
| help: consider adding an explicit lifetime bound...: `G: 'a`
error[E0309]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:87:1
|
LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
| - help: consider adding an explicit lifetime bound...: `G: 'a`
...
LL | / {
LL | |
LL | | move || {
LL | | *dest = g.get();
LL | | }
LL | | }
| |_^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:89:5: 91:6]` will meet its required lifetime bounds
error: aborting due to 11 previous errors
Some errors have detailed explanations: E0261, E0309, E0621, E0700.
For more information about an error, try `rustc --explain E0261`.

View File

@ -18,5 +18,7 @@ type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
//~^ ERROR use of undeclared lifetime name `'a` //~^ ERROR use of undeclared lifetime name `'a`
fn my_fun() -> Return<()> {} fn my_fun() -> Return<()> {}
//~^ ERROR non-defining opaque type use in defining scope
//~| ERROR non-defining opaque type use in defining scope
fn main() {} fn main() {}

View File

@ -2,10 +2,42 @@ error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:65 --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:65
| |
LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>; LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
| - ^^ undeclared lifetime | ^^ undeclared lifetime
| | |
| help: consider introducing lifetime `'a` here: `'a,` = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the bound lifetime-generic with a new `'a` lifetime
|
LL | type Return<A> = impl for<'a> WithAssoc<A, AssocType = impl SomeTrait + 'a>;
| +++++++
help: consider introducing lifetime `'a` here
|
LL | type Return<'a, A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
| +++
error: aborting due to previous error error: non-defining opaque type use in defining scope
--> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27
|
LL | fn my_fun() -> Return<()> {}
| ^^
|
note: used non-generic type `()` for generic parameter
--> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:13
|
LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
| ^
error: non-defining opaque type use in defining scope
--> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27
|
LL | fn my_fun() -> Return<()> {}
| ^^
|
note: used non-generic type `()` for generic parameter
--> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:13
|
LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
| ^
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0261`. For more information about this error, try `rustc --explain E0261`.

View File

@ -10,22 +10,22 @@ impl<'_> IceCube<'_> {}
//~^ ERROR `'_` cannot be used here //~^ ERROR `'_` cannot be used here
struct Struct<'_> { struct Struct<'_> {
//~^ ERROR `'_` cannot be used here //~^ ERROR `'_` cannot be used here
v: Vec<&'static char> v: Vec<&'static char>
} }
enum Enum<'_> { enum Enum<'_> {
//~^ ERROR `'_` cannot be used here //~^ ERROR `'_` cannot be used here
Variant Variant
} }
union Union<'_> { union Union<'_> {
//~^ ERROR `'_` cannot be used here //~^ ERROR `'_` cannot be used here
a: u32 a: u32
} }
trait Trait<'_> { trait Trait<'_> {
//~^ ERROR `'_` cannot be used here //~^ ERROR `'_` cannot be used here
} }
fn foo<'_>() { fn foo<'_>() {

View File

@ -2,9 +2,13 @@ error[E0726]: implicit elided lifetime not allowed here
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:16 --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:16
| |
LL | impl Trait for Ref {} LL | impl Trait for Ref {}
| ^^^- help: indicate the anonymous lifetime: `<'_>` | ^^^ expected lifetime parameter
| |
= note: assuming a `'static` lifetime... = note: assuming a `'static` lifetime...
help: indicate the anonymous lifetime
|
LL | impl Trait for Ref<'_> {}
| ++++
error: incompatible lifetime on type error: incompatible lifetime on type
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:21 --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:21

View File

@ -1,20 +1,41 @@
error[E0261]: use of undeclared lifetime name `'a` error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/where-lifetime-resolution.rs:6:38 --> $DIR/where-lifetime-resolution.rs:6:38
| |
LL | fn f() where
| - help: consider introducing lifetime `'a` here: `<'a>`
LL | for<'a> dyn Trait1<'a>: Trait1<'a>, // OK
LL | (dyn for<'a> Trait1<'a>): Trait1<'a>, LL | (dyn for<'a> Trait1<'a>): Trait1<'a>,
| ^^ undeclared lifetime | ^^ undeclared lifetime
|
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the bound lifetime-generic with a new `'a` lifetime
|
LL | (dyn for<'a> Trait1<'a>): for<'a> Trait1<'a>,
| +++++++
help: consider making the bound lifetime-generic with a new `'a` lifetime
|
LL | for<'a> (dyn for<'a> Trait1<'a>): Trait1<'a>,
| +++++++
help: consider introducing lifetime `'a` here
|
LL | fn f<'a>() where
| ++++
error[E0261]: use of undeclared lifetime name `'b` error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/where-lifetime-resolution.rs:8:52 --> $DIR/where-lifetime-resolution.rs:8:52
| |
LL | fn f() where
| - help: consider introducing lifetime `'b` here: `<'b>`
...
LL | for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, LL | for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
| ^^ undeclared lifetime | ^^ undeclared lifetime
|
help: consider making the bound lifetime-generic with a new `'b` lifetime
|
LL | for<'a> dyn for<'b> Trait2<'a, 'b>: for<'b> Trait2<'a, 'b>,
| +++++++
help: consider making the bound lifetime-generic with a new `'b` lifetime
|
LL | for<'b, 'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
| +++
help: consider introducing lifetime `'b` here
|
LL | fn f<'b>() where
| ++++
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -1,8 +1,8 @@
error: unneeded unit return type error: unneeded unit return type
--> $DIR/unused_unit.rs:19:28 --> $DIR/unused_unit.rs:19:58
| |
LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> () LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
| ^^^^^^ help: remove the `-> ()` | ^^^^^^ help: remove the `-> ()`
| |
note: the lint level is defined here note: the lint level is defined here
--> $DIR/unused_unit.rs:12:9 --> $DIR/unused_unit.rs:12:9
@ -10,18 +10,18 @@ note: the lint level is defined here
LL | #![deny(clippy::unused_unit)] LL | #![deny(clippy::unused_unit)]
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
error: unneeded unit return type
--> $DIR/unused_unit.rs:19:28
|
LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
| ^^^^^^ help: remove the `-> ()`
error: unneeded unit return type error: unneeded unit return type
--> $DIR/unused_unit.rs:20:18 --> $DIR/unused_unit.rs:20:18
| |
LL | where G: Fn() -> () { LL | where G: Fn() -> () {
| ^^^^^^ help: remove the `-> ()` | ^^^^^^ help: remove the `-> ()`
error: unneeded unit return type
--> $DIR/unused_unit.rs:19:58
|
LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
| ^^^^^^ help: remove the `-> ()`
error: unneeded unit return type error: unneeded unit return type
--> $DIR/unused_unit.rs:21:26 --> $DIR/unused_unit.rs:21:26
| |

View File

@ -204,12 +204,11 @@ impl<'a> FnSig<'a> {
pub(crate) fn from_fn_kind( pub(crate) fn from_fn_kind(
fn_kind: &'a visit::FnKind<'_>, fn_kind: &'a visit::FnKind<'_>,
generics: &'a ast::Generics,
decl: &'a ast::FnDecl, decl: &'a ast::FnDecl,
defaultness: ast::Defaultness, defaultness: ast::Defaultness,
) -> FnSig<'a> { ) -> FnSig<'a> {
match *fn_kind { match *fn_kind {
visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, _) => match fn_ctxt { visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, generics, _) => match fn_ctxt {
visit::FnCtxt::Assoc(..) => { visit::FnCtxt::Assoc(..) => {
let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis); let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis);
fn_sig.defaultness = defaultness; fn_sig.defaultness = defaultness;
@ -3180,8 +3179,14 @@ impl Rewrite for ast::ForeignItem {
let inner_attrs = inner_attributes(&self.attrs); let inner_attrs = inner_attributes(&self.attrs);
let fn_ctxt = visit::FnCtxt::Foreign; let fn_ctxt = visit::FnCtxt::Foreign;
visitor.visit_fn( visitor.visit_fn(
visit::FnKind::Fn(fn_ctxt, self.ident, sig, &self.vis, Some(body)), visit::FnKind::Fn(
generics, fn_ctxt,
self.ident,
sig,
&self.vis,
generics,
Some(body),
),
&sig.decl, &sig.decl,
self.span, self.span,
defaultness, defaultness,

View File

@ -382,7 +382,6 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
pub(crate) fn visit_fn( pub(crate) fn visit_fn(
&mut self, &mut self,
fk: visit::FnKind<'_>, fk: visit::FnKind<'_>,
generics: &ast::Generics,
fd: &ast::FnDecl, fd: &ast::FnDecl,
s: Span, s: Span,
defaultness: ast::Defaultness, defaultness: ast::Defaultness,
@ -391,12 +390,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
let indent = self.block_indent; let indent = self.block_indent;
let block; let block;
let rewrite = match fk { let rewrite = match fk {
visit::FnKind::Fn(_, ident, _, _, Some(ref b)) => { visit::FnKind::Fn(_, ident, _, _, _, Some(ref b)) => {
block = b; block = b;
self.rewrite_fn_before_block( self.rewrite_fn_before_block(
indent, indent,
ident, ident,
&FnSig::from_fn_kind(&fk, generics, fd, defaultness), &FnSig::from_fn_kind(&fk, fd, defaultness),
mk_sp(s.lo(), b.span.lo()), mk_sp(s.lo(), b.span.lo()),
) )
} }
@ -552,8 +551,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
_ => visit::FnCtxt::Foreign, _ => visit::FnCtxt::Foreign,
}; };
self.visit_fn( self.visit_fn(
visit::FnKind::Fn(fn_ctxt, item.ident, sig, &item.vis, Some(body)), visit::FnKind::Fn(
generics, fn_ctxt,
item.ident,
sig,
&item.vis,
generics,
Some(body),
),
&sig.decl, &sig.decl,
item.span, item.span,
defaultness, defaultness,
@ -642,8 +647,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
let inner_attrs = inner_attributes(&ai.attrs); let inner_attrs = inner_attributes(&ai.attrs);
let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt); let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt);
self.visit_fn( self.visit_fn(
visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, Some(body)), visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, generics, Some(body)),
generics,
&sig.decl, &sig.decl,
ai.span, ai.span,
defaultness, defaultness,