mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 06:22:00 +00:00
Report undeclared lifetimes on AST.
This commit is contained in:
parent
4cfceeabdc
commit
fc9f25531a
@ -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.
|
||||
///
|
||||
@ -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 =
|
||||
@ -2404,20 +2404,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
/// 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)
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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,
|
||||
|
@ -2312,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,),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3119,18 +3122,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)]
|
||||
@ -1358,9 +1359,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 {
|
||||
|
Loading…
Reference in New Issue
Block a user