1
Fork 0

Lint elided lifetimes in path on the AST.

This commit is contained in:
Camille GILLOT 2022-03-10 23:12:35 +01:00
parent ca57bada05
commit a9e13fa553
24 changed files with 279 additions and 154 deletions

View file

@ -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,7 +2017,7 @@ 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::Implicit | hir::LifetimeName::Underscore => {
hir::ParamName::Plain(lt.name.ident())
}
hir::LifetimeName::ImplicitObjectLifetimeDefault => {
@ -2397,7 +2397,7 @@ 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),
}
}
@ -2416,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
@ -2437,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)
}
}
}
@ -2480,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,
}
}
}
@ -2587,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");
}
}