Skip to content

Commit

Permalink
Improve spans of named lifetimes generated from elided lifetimes
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Jan 20, 2023
1 parent 8206008 commit b4c19da
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 15 deletions.
4 changes: 2 additions & 2 deletions src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub fn expand(input: &mut Item, is_local: bool) {
}
}
Item::Impl(input) => {
let mut lifetimes = CollectLifetimes::new("'impl", input.impl_token.span);
let mut lifetimes = CollectLifetimes::new("'impl");
lifetimes.visit_type_mut(&mut *input.self_ty);
lifetimes.visit_path_mut(&mut input.trait_.as_mut().unwrap().1);
let params = &input.generics.params;
Expand Down Expand Up @@ -166,7 +166,7 @@ fn transform_sig(
ReturnType::Type(arrow, ret) => (*arrow, quote!(#ret)),
};

let mut lifetimes = CollectLifetimes::new("'life", default_span);
let mut lifetimes = CollectLifetimes::new("'life");
for arg in sig.inputs.iter_mut() {
match arg {
FnArg::Receiver(arg) => lifetimes.visit_receiver_mut(arg),
Expand Down
19 changes: 8 additions & 11 deletions src/lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,28 @@ use proc_macro2::{Span, TokenStream};
use std::mem;
use syn::visit_mut::{self, VisitMut};
use syn::{
parse_quote_spanned, token, Expr, GenericArgument, Lifetime, Receiver, ReturnType, Type,
parse_quote_spanned, token, Expr, GenericArgument, Lifetime, Receiver, ReturnType, Token, Type,
TypeBareFn, TypeImplTrait, TypeParen, TypePtr, TypeReference,
};

pub struct CollectLifetimes {
pub elided: Vec<Lifetime>,
pub explicit: Vec<Lifetime>,
pub name: &'static str,
pub default_span: Span,
}

impl CollectLifetimes {
pub fn new(name: &'static str, default_span: Span) -> Self {
pub fn new(name: &'static str) -> Self {
CollectLifetimes {
elided: Vec::new(),
explicit: Vec::new(),
name,
default_span,
}
}

fn visit_opt_lifetime(&mut self, lifetime: &mut Option<Lifetime>) {
fn visit_opt_lifetime(&mut self, reference: Token![&], lifetime: &mut Option<Lifetime>) {
match lifetime {
None => *lifetime = Some(self.next_lifetime(None)),
None => *lifetime = Some(self.next_lifetime(reference.span)),
Some(lifetime) => self.visit_lifetime(lifetime),
}
}
Expand All @@ -38,9 +36,8 @@ impl CollectLifetimes {
}
}

fn next_lifetime<S: Into<Option<Span>>>(&mut self, span: S) -> Lifetime {
fn next_lifetime(&mut self, span: Span) -> Lifetime {
let name = format!("{}{}", self.name, self.elided.len());
let span = span.into().unwrap_or(self.default_span);
let life = Lifetime::new(&name, span);
self.elided.push(life.clone());
life
Expand All @@ -49,13 +46,13 @@ impl CollectLifetimes {

impl VisitMut for CollectLifetimes {
fn visit_receiver_mut(&mut self, arg: &mut Receiver) {
if let Some((_, lifetime)) = &mut arg.reference {
self.visit_opt_lifetime(lifetime);
if let Some((reference, lifetime)) = &mut arg.reference {
self.visit_opt_lifetime(*reference, lifetime);
}
}

fn visit_type_reference_mut(&mut self, ty: &mut TypeReference) {
self.visit_opt_lifetime(&mut ty.lifetime);
self.visit_opt_lifetime(ty.and_token, &mut ty.lifetime);
visit_mut::visit_type_reference_mut(self, ty);
}

Expand Down
8 changes: 6 additions & 2 deletions tests/ui/lifetime-defined-here.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ error: lifetime may not live long enough
--> tests/ui/lifetime-defined-here.rs:12:49
|
12 | async fn bar(&self, x: &str, y: &'_ str) -> &'static str {
| ----- lifetime `'life0` defined here ^^^^^^^^^^^^ type annotation requires that `'life0` must outlive `'static`
| - ^^^^^^^^^^^^ type annotation requires that `'life0` must outlive `'static`
| |
| lifetime `'life0` defined here

error: lifetime may not live long enough
--> tests/ui/lifetime-defined-here.rs:12:49
|
12 | async fn bar(&self, x: &str, y: &'_ str) -> &'static str {
| ----- lifetime `'life1` defined here ^^^^^^^^^^^^ type annotation requires that `'life1` must outlive `'static`
| - ^^^^^^^^^^^^ type annotation requires that `'life1` must outlive `'static`
| |
| lifetime `'life1` defined here

error: lifetime may not live long enough
--> tests/ui/lifetime-defined-here.rs:12:49
Expand Down

0 comments on commit b4c19da

Please sign in to comment.