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)]
pub enum FnKind<'a> {
/// 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`.
Closure(&'a FnDecl, &'a Expr),
@ -44,7 +44,7 @@ pub enum FnKind<'a> {
impl<'a> FnKind<'a> {
pub fn header(&self) -> Option<&'a FnHeader> {
match *self {
FnKind::Fn(_, _, sig, _, _) => Some(&sig.header),
FnKind::Fn(_, _, sig, _, _, _) => Some(&sig.header),
FnKind::Closure(_, _) => None,
}
}
@ -58,7 +58,7 @@ impl<'a> FnKind<'a> {
pub fn decl(&self) -> &'a FnDecl {
match self {
FnKind::Fn(_, _, sig, _, _) => &sig.decl,
FnKind::Fn(_, _, sig, _, _, _) => &sig.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);
}
ItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
visitor.visit_generics(generics);
let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
let kind =
FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
visitor.visit_fn(kind, item.span, item.id)
}
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);
}
ForeignItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
visitor.visit_generics(generics);
let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref());
visitor.visit_fn(kind, span, id);
}
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) {
match kind {
FnKind::Fn(_, _, sig, _, body) => {
FnKind::Fn(_, _, sig, _, generics, body) => {
visitor.visit_generics(generics);
visitor.visit_fn_header(&sig.header);
walk_fn_decl(visitor, &sig.decl);
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);
}
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, body.as_deref());
let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref());
visitor.visit_fn(kind, span, id);
}
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
/// everything into HIR lowering.
#[derive(Copy, Clone, Debug)]
enum AnonymousLifetimeMode {
pub enum AnonymousLifetimeMode {
/// For **Modern** cases, create a new anonymous region parameter
/// and reference that.
///
@ -1835,7 +1835,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Output lifetime like `'_`:
for (span, node_id) in lifetimes_to_define {
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);
}
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 {
hir::LifetimeName::Param(param_name) => param_name,
hir::LifetimeName::Implicit(_)
| hir::LifetimeName::Underscore
| hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()),
hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
hir::ParamName::Plain(lt.name.ident())
}
hir::LifetimeName::ImplicitObjectLifetimeDefault => {
self.sess.diagnostic().span_bug(
param.ident.span,
"object-lifetime-default should not occur here",
);
}
hir::LifetimeName::Error => ParamName::Error,
hir::LifetimeName::Static | hir::LifetimeName::Error => ParamName::Error,
};
let kind =
@ -2397,27 +2397,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
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;
/// return an "error lifetime".
fn new_error_lifetime(&mut self, id: Option<NodeId>, span: Span) -> hir::Lifetime {
let (id, msg, label) = match 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();
let id = id.unwrap_or_else(|| self.resolver.next_node_id());
self.new_named_lifetime(id, span, hir::LifetimeName::Error)
}
@ -2429,12 +2416,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&'s mut self,
span: Span,
count: usize,
param_mode: ParamMode,
) -> 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 {
AnonymousLifetimeMode::CreateParameter => {
// 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
// later, at which point a suitable error will be emitted.
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
}
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_id: self.next_id(),
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) {
let name = match lifetime.name {
hir::LifetimeName::Implicit(_) | hir::LifetimeName::Underscore => {
hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
if self.collect_elided_lifetimes {
// Use `'_` for both implicit and underscore lifetimes in
// `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.args = self
.elided_path_lifetimes(elided_lifetime_span, expected_lifetimes, param_mode)
.elided_path_lifetimes(elided_lifetime_span, expected_lifetimes)
.map(GenericArg::Lifetime)
.chain(generic_args.args.into_iter())
.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) =
(param_mode, self.anonymous_lifetime_mode)
{
let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", ");
let no_non_lt_args = generic_args.args.len() == expected_lifetimes;
let no_bindings = generic_args.bindings.is_empty();
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();
// Late resolver should have issued the error.
self.sess
.delay_span_bug(elided_lifetime_span, "implicit lifetime not allowed here");
}
}

View File

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

View File

@ -575,7 +575,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
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
// they wrote something like:
//

View File

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

View File

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

View File

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

View File

@ -21,7 +21,8 @@ use crate::passes::{EarlyLintPassObject, LateLintPassObject};
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
use rustc_data_structures::fx::FxHashMap;
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::def::Res;
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");
}
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) => {
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
// 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 {
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);
}
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) {
run_early_pass!(self, check_attribute, attr);
}

View File

@ -418,6 +418,7 @@ pub enum BuiltinLintDiagnostics {
AbsPathWithModule(Span),
ProcMacroDeriveResolutionFallback(Span),
MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
ElidedLifetimesInPaths(usize, Span, bool, Span),
UnknownCrateTypes(Span, String, String),
UnusedImports(String, Vec<(Span, String)>, Option<Span>),
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`.
if crate_name != kw::Empty {
// `crate_name` should not be interpreted as relative.
module_path.push(Segment {
ident: Ident { name: kw::PathRoot, span: source.ident.span },
id: Some(self.r.next_node_id()),
has_generic_args: false,
});
module_path.push(Segment::from_ident_and_id(
Ident { name: kw::PathRoot, span: source.ident.span },
self.r.next_node_id(),
));
source.ident.name = crate_name;
}
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) {
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 {
self.visit_generics(generics);
let return_impl_trait_id =
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 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);
let record_segment_res = |this: &mut Self, res| {
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::late::lifetimes::{ElisionFailureInfo, LifetimeContext};
use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind};
use crate::late::{LifetimeBinderKind, LifetimeRibKind};
use crate::path_names_to_string;
use crate::{Finalize, Module, ModuleKind, ModuleOrUniformRoot};
use crate::{PathResult, PathSource, Segment};
@ -1793,6 +1794,102 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
(*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> {
@ -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.
crate fn report_elision_failure(
&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
// 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.
@ -2416,9 +2420,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
);
let is_allowed_lifetime = matches!(
lifetime_ref.name,
hir::LifetimeName::Implicit(_)
| hir::LifetimeName::Static
| hir::LifetimeName::Underscore
hir::LifetimeName::Implicit | hir::LifetimeName::Static | hir::LifetimeName::Underscore
);
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,
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,
/// Indicates that we only care about the definition of a trait. This should
@ -455,7 +452,6 @@ fn do_resolve(
tcx,
map: &mut named_region_map,
scope: ROOT_SCOPE,
is_in_fn_syntax: false,
is_in_const_generic: false,
trait_definition_only,
labels_in_fn: vec![],
@ -874,8 +870,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
match ty.kind {
hir::TyKind::BareFn(ref c) => {
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> =
c.generic_params.iter().rev().find_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => Some(param.span),
@ -917,7 +911,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
intravisit::walk_ty(this, ty);
});
self.missing_named_lifetime_spots.pop();
self.is_in_fn_syntax = was_in_fn_syntax;
}
hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
debug!(?bounds, ?lifetime, "TraitObject");
@ -928,7 +921,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
});
match lifetime.name {
LifetimeName::Implicit(_) => {
LifetimeName::Implicit => {
// For types like `dyn Foo`, we should
// generate a special form of elided.
span_bug!(ty.span, "object-lifetime-default expected, not implicit",);
@ -1805,7 +1798,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
tcx: *tcx,
map,
scope: &wrap_scope,
is_in_fn_syntax: self.is_in_fn_syntax,
is_in_const_generic: self.is_in_const_generic,
trait_definition_only: self.trait_definition_only,
labels_in_fn,
@ -2320,7 +2312,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
self.insert_lifetime(lifetime_ref, def);
} 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 {
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.is_in_fn_syntax = was_in_fn_syntax;
return;
}
@ -2963,9 +2955,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
let error = loop {
match *scope {
// 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, .. } => {
// collect named lifetimes for suggestions
@ -2992,7 +2984,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
self.insert_lifetime(lifetime_ref, lifetime);
}
break Ok(());
return;
}
Scope::Elision { elide: Elide::Exact(l), .. } => {
@ -3000,7 +2992,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
for lifetime_ref in lifetime_refs {
self.insert_lifetime(lifetime_ref, lifetime);
}
break Ok(());
return;
}
Scope::Elision { elide: Elide::Error(ref e), ref s, .. } => {
@ -3025,10 +3017,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
_ => 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::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
// diagnostic pass and we don't want to emit more errors.
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 {
let name = lifetime_i_name.ident().name;
if name == kw::UnderscoreLifetime || name == kw::StaticLifetime {
let mut err = struct_span_err!(
self.tcx.sess,
self.tcx.sess.delay_span_bug(
lifetime_i.span,
E0262,
"invalid lifetime parameter name: `{}`",
lifetime_i.name.ident(),
&format!("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();
}
hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit(_) => {
hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => {
self.resolve_lifetime_ref(lt);
}
hir::LifetimeName::ImplicitObjectLifetimeDefault => {

View File

@ -11,6 +11,7 @@
#![feature(drain_filter)]
#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(let_else)]
#![feature(never_type)]
@ -27,7 +28,7 @@ pub use rustc_hir::def::{Namespace, PerNS};
use rustc_arena::{DroplessArena, TypedArena};
use rustc_ast::node_id::NodeMap;
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_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::intern::Interned;
@ -282,6 +283,9 @@ pub struct Segment {
/// Signals whether this `PathSegment` has generic arguments. Used to avoid providing
/// nonsensical suggestions.
has_generic_args: bool,
/// Signals whether this `PathSegment` has lifetime arguments.
has_lifetime_args: bool,
args_span: Span,
}
impl Segment {
@ -290,7 +294,23 @@ impl 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 {
@ -300,7 +320,28 @@ impl Segment {
impl<'a> From<&'a ast::PathSegment> for 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 {
let next =
self.next_node_id.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))
let start = self.next_node_id;
let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
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 {

View File

@ -2,9 +2,13 @@ error[E0726]: implicit elided lifetime not allowed here
--> $DIR/async-fn-path-elision.rs:5:20
|
LL | async fn error(lt: HasLifetime) {
| ^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
| ^^^^^^^^^^^ expected lifetime parameter
|
= note: assuming a `'static` lifetime...
help: indicate the anonymous lifetime
|
LL | async fn error(lt: HasLifetime<'_>) {
| ++++
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
|
LL | fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
| - ^^ undeclared lifetime
| |
| help: consider introducing lifetime `'x` here: `<'x>`
| ^^ 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 `'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
--> $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>>;
| ^^ 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
|
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`
--> $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
|
LL | trait Iterable<'undeclared> {
| +++++++++++++
help: consider introducing lifetime `'undeclared` here
|
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

View File

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

View File

@ -1,19 +1,50 @@
error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/issue-67510.rs:7:21
|
LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
| - ^^ undeclared lifetime
| |
| help: consider introducing lifetime `'a` here: `<'a>`
LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
| ^^ 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 | 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`
--> $DIR/issue-67510.rs:7:26
--> $DIR/issue-67510.rs:7:28
|
LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
| - ^^ undeclared lifetime
| |
| help: consider introducing lifetime `'a` here: `<'a>`
LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
| ^^ undeclared lifetime
|
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>;
fn cursor(&self) -> Self::Cursor<'_> {
DocCursorImpl {
document: &self,
}
DocCursorImpl { document: &self }
}
}
trait DocCursor<'a> {}
struct DocCursorImpl<'a> {
@ -35,7 +32,6 @@ where
_phantom: std::marker::PhantomData<&'d ()>,
}
impl<'d, Cursor> Lexer<'d, Cursor>
where
Cursor: DocCursor<'d>,
@ -44,10 +40,7 @@ where
where
Doc: Document<Cursor<'d> = Cursor>,
{
Lexer {
cursor: document.cursor(),
_phantom: std::marker::PhantomData,
}
Lexer { cursor: document.cursor(), _phantom: std::marker::PhantomData }
}
}

View File

@ -1,5 +1,5 @@
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<'_>> {
| ^^ 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
|
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`
--> $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
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`
--> $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);
| ^^ 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
|
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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,51 +5,55 @@ LL | trait Serializable<'self, T> {
| ^^^^^
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
--> $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
--> $DIR/issue-10412.rs:6:6
--> $DIR/issue-10412.rs:7:6
|
LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^
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 {
| ^^^^^
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
--> $DIR/issue-10412.rs:13:37
--> $DIR/issue-10412.rs:16:37
|
LL | fn deserialize(repr: &[u8]) -> &'self str {
| ^^^^^
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 {
| ^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Serializable<'_, str>`
| ^^^^^^^^^^^^^^^^^ expected lifetime parameter
|
= 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
--> $DIR/issue-10412.rs:6:13
--> $DIR/issue-10412.rs:7:13
|
LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^^^^^^^^^^^^^ 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
|
LL | fn f() -> Ptr<Thing>;
| ^ expected named lifetime parameter
| ^ expected lifetime parameter
|
note: the lint level is defined here
--> $DIR/issue-91763.rs:3:9
|
LL | #![deny(elided_lifetimes_in_paths)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
help: indicate the anonymous lifetime
|
LL | fn f() -> Ptr<Thing><'_>;
| ++++
error: aborting due to previous error

View File

@ -9,6 +9,8 @@ LL | a: &'b str,
error[E0261]: use of undeclared lifetime name `'b`
--> $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 {
| - help: consider introducing lifetime `'b` here: `<'b>`
LL | a: &'b str,
@ -22,11 +24,11 @@ LL | fn foo(&'b self) {}
|
help: consider introducing lifetime `'b` here
|
LL | impl<'b> T for Test {
LL | fn foo<'b>(&'b self) {}
| ++++
help: consider introducing lifetime `'b` here
|
LL | fn foo<'b>(&'b self) {}
LL | impl<'b> T for Test {
| ++++
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
|
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`
help: consider using the `'_` lifetime
help: indicate the anonymous lifetime
|
LL | fn foo(x: &Foo<'_>) {}
| ~~~~~~~
| ++++
warning: 1 warning emitted

View File

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

View File

@ -2,7 +2,9 @@ warning: hidden lifetime parameters in types are deprecated
--> $DIR/reasons.rs:20:34
|
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: the lint level is defined here
@ -10,10 +12,10 @@ note: the lint level is defined here
|
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 {
| ~~~~~~~~~~~~~
| ++++
warning: variable `Social_exchange_psychology` should have a snake case name
--> $DIR/reasons.rs:30:9

View File

@ -1,3 +1,6 @@
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>();
| ^^ 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`.

View File

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

View File

@ -23,14 +23,14 @@ fn bar<'a>(x: &'a isize) {
let y: &'a isize = x;
// &'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 {
E1(&'a isize) //~ ERROR undeclared lifetime
E1(&'a isize) //~ ERROR can't use generic parameters from outer item
}
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:
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`
--> $DIR/regions-name-undeclared.rs:16:24
|
@ -22,12 +6,12 @@ LL | fn m4(&self, arg: &'b isize) { }
|
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) { }
| ++++
help: consider introducing lifetime `'b` here
|
LL | impl<'b, 'a> Foo<'a> {
| +++
error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/regions-name-undeclared.rs:17:12
@ -37,12 +21,12 @@ LL | fn m5(&'b self) { }
|
help: consider introducing lifetime `'b` here
|
LL | impl<'b, 'a> Foo<'a> {
| +++
help: consider introducing lifetime `'b` here
|
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`
--> $DIR/regions-name-undeclared.rs:18:27
@ -52,26 +36,54 @@ LL | fn m6(&self, arg: Foo<'b>) { }
|
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>) { }
| ++++
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
|
LL | fn bar<'a>(x: &'a isize) {
| -- lifetime parameter from outer item
...
LL | type X = Option<&'a isize>;
| - ^^ undeclared lifetime
| - ^^ use of generic parameter from outer item
| |
| 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
|
LL | fn bar<'a>(x: &'a isize) {
| -- lifetime parameter from outer item
...
LL | fn f(a: &'a isize) { }
| - ^^ undeclared lifetime
| - ^^ use of generic parameter from outer item
| |
| help: consider introducing lifetime `'a` here: `<'a>`
@ -90,14 +102,14 @@ LL | ... &'b isize,
| ^^ 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
|
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`
--> $DIR/regions-name-undeclared.rs:46:36
@ -105,15 +117,14 @@ error[E0261]: use of undeclared lifetime name `'b`
LL | ... &'b isize)>,
| ^^ 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
|
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`
--> $DIR/regions-name-undeclared.rs:47:17
@ -132,13 +143,14 @@ LL | async fn buggy(&self) -> &'a str {
|
help: consider introducing lifetime `'a` here
|
LL | impl<'a> Bug {
LL | async fn buggy<'a>(&self) -> &'a str {
| ++++
help: consider introducing lifetime `'a` here
|
LL | async fn buggy<'a>(&self) -> &'a str {
LL | impl<'a> Bug {
| ++++
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
|
= 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
|
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
--> $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()
where
G: Get<T>
G: Get<T>,
{
move || {
//~^ ERROR hidden type for `impl Trait` captures lifetime
*dest = g.get();
}
}
// After applying suggestion for `foo`:
fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
//~^ ERROR the parameter type `G` may not live long enough
where
G: Get<T>
G: Get<T>,
{
//~^ ERROR the parameter type `G` may not live long enough
move || {
*dest = g.get();
}
}
// 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
G: Get<T>
G: Get<T>,
{
move || {
*dest = g.get();
@ -44,9 +47,11 @@ where
// After applying suggestion for `baz`:
fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
//~^ ERROR the parameter type `G` may not live long enough
where
G: Get<T>
G: Get<T>,
{
//~^ ERROR the parameter type `G` may not live long enough
move || {
*dest = g.get();
}
@ -55,6 +60,8 @@ where
// Same as above, but show that we pay attention to lifetime names from parent item
impl<'a> Foo {
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 || {
*dest = g.get();
}
@ -63,8 +70,9 @@ impl<'a> Foo {
// After applying suggestion for `qux`:
fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
//~^ ERROR explicit lifetime required in the type of `dest`
where
G: Get<T>
G: Get<T>,
{
move || {
*dest = g.get();
@ -73,19 +81,20 @@ where
// Potential incorrect attempt:
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
G: Get<T>
G: Get<T>,
{
//~^ ERROR the parameter type `G` may not live long enough
move || {
*dest = g.get();
}
}
// 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
where
G: Get<T>
G: Get<T>,
{
move || {
*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:
fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a
where
G: Get<T>
G: Get<T>,
{
move || {
*dest = g.get();

View File

@ -1,11 +1,234 @@
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() + '_
| - ^^ undeclared lifetime
| |
| 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`
fn my_fun() -> Return<()> {}
//~^ ERROR non-defining opaque type use in defining scope
//~| ERROR non-defining opaque type use in defining scope
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
|
LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
| - ^^ undeclared lifetime
| |
| help: consider introducing lifetime `'a` here: `'a,`
| ^^ 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 | 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`.

View File

@ -10,22 +10,22 @@ impl<'_> IceCube<'_> {}
//~^ ERROR `'_` cannot be used here
struct Struct<'_> {
//~^ ERROR `'_` cannot be used here
//~^ ERROR `'_` cannot be used here
v: Vec<&'static char>
}
enum Enum<'_> {
//~^ ERROR `'_` cannot be used here
//~^ ERROR `'_` cannot be used here
Variant
}
union Union<'_> {
//~^ ERROR `'_` cannot be used here
//~^ ERROR `'_` cannot be used here
a: u32
}
trait Trait<'_> {
//~^ ERROR `'_` cannot be used here
//~^ ERROR `'_` cannot be used here
}
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
|
LL | impl Trait for Ref {}
| ^^^- help: indicate the anonymous lifetime: `<'_>`
| ^^^ expected lifetime parameter
|
= note: assuming a `'static` lifetime...
help: indicate the anonymous lifetime
|
LL | impl Trait for Ref<'_> {}
| ++++
error: incompatible lifetime on type
--> $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`
--> $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>,
| ^^ 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`
--> $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>,
| ^^ 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

View File

@ -1,5 +1,5 @@
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) -> ()
| ^^^^^^ help: remove the `-> ()`
@ -11,15 +11,15 @@ LL | #![deny(clippy::unused_unit)]
| ^^^^^^^^^^^^^^^^^^^
error: unneeded unit return type
--> $DIR/unused_unit.rs:20:18
--> $DIR/unused_unit.rs:19:28
|
LL | where G: Fn() -> () {
LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
| ^^^^^^ help: remove the `-> ()`
error: unneeded unit return type
--> $DIR/unused_unit.rs:19:58
--> $DIR/unused_unit.rs:20:18
|
LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
LL | where G: Fn() -> () {
| ^^^^^^ help: remove the `-> ()`
error: unneeded unit return type

View File

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

View File

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