Skip to content

Commit c4edd71

Browse files
committed
Add lifetime-aware support for Display impl of Ident
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
1 parent 5b84228 commit c4edd71

File tree

6 files changed

+55
-29
lines changed

6 files changed

+55
-29
lines changed

compiler/rustc_parse/src/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2176,7 +2176,7 @@ pub(crate) struct KeywordLifetime {
21762176
pub(crate) struct InvalidLabel {
21772177
#[primary_span]
21782178
pub span: Span,
2179-
pub name: Symbol,
2179+
pub name: String,
21802180
}
21812181

21822182
#[derive(Diagnostic)]

compiler/rustc_parse/src/parser/expr.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3077,7 +3077,10 @@ impl<'a> Parser<'a> {
30773077
if let Some((ident, is_raw)) = self.token.lifetime() {
30783078
// Disallow `'fn`, but with a better error message than `expect_lifetime`.
30793079
if matches!(is_raw, IdentIsRaw::No) && ident.without_first_quote().is_reserved() {
3080-
self.dcx().emit_err(errors::InvalidLabel { span: ident.span, name: ident.name });
3080+
self.dcx().emit_err(errors::InvalidLabel {
3081+
span: ident.span,
3082+
name: ident.name.to_string(),
3083+
});
30813084
}
30823085

30833086
self.bump();

compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3120,7 +3120,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
31203120
} else {
31213121
self.suggest_introducing_lifetime(
31223122
&mut err,
3123-
Some(lifetime_ref.ident.name.as_str()),
3123+
Some(lifetime_ref.ident),
31243124
|err, _, span, message, suggestion, span_suggs| {
31253125
err.multipart_suggestion_with_style(
31263126
message,
@@ -3143,7 +3143,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
31433143
fn suggest_introducing_lifetime(
31443144
&self,
31453145
err: &mut Diag<'_>,
3146-
name: Option<&str>,
3146+
name: Option<Ident>,
31473147
suggest: impl Fn(
31483148
&mut Diag<'_>,
31493149
bool,
@@ -3190,7 +3190,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
31903190
let mut rm_inner_binders: FxIndexSet<Span> = Default::default();
31913191
let (span, sugg) = if span.is_empty() {
31923192
let mut binder_idents: FxIndexSet<Ident> = Default::default();
3193-
binder_idents.insert(Ident::from_str(name.unwrap_or("'a")));
3193+
binder_idents.insert(name.unwrap_or(Ident::from_str("'a")));
31943194

31953195
// We need to special case binders in the following situation:
31963196
// Change `T: for<'a> Trait<T> + 'b` to `for<'a, 'b> T: Trait<T> + 'b`
@@ -3226,7 +3226,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
32263226
if i != 0 {
32273227
binders += ", ";
32283228
}
3229-
binders += x.as_str();
3229+
binders += format!("{}", x).as_str();
32303230
binders
32313231
},
32323232
);
@@ -3245,15 +3245,15 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
32453245
.source_map()
32463246
.span_through_char(span, '<')
32473247
.shrink_to_hi();
3248-
let sugg = format!("{}, ", name.unwrap_or("'a"));
3248+
let sugg = format!("{}, ", name.unwrap_or(Ident::from_str("'a")));
32493249
(span, sugg)
32503250
};
32513251

32523252
if higher_ranked {
32533253
let message = Cow::from(format!(
32543254
"consider making the {} lifetime-generic with a new `{}` lifetime",
32553255
kind.descr(),
3256-
name.unwrap_or("'a"),
3256+
name.unwrap_or(Ident::from_str("'a")),
32573257
));
32583258
should_continue = suggest(
32593259
err,

compiler/rustc_span/src/symbol.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2470,6 +2470,10 @@ impl Ident {
24702470
pub fn as_str(&self) -> &str {
24712471
self.name.as_str()
24722472
}
2473+
2474+
pub fn as_lifetime(&self) -> Option<Ident> {
2475+
self.name.as_lifetime().map(|sym| Ident::with_dummy_span(sym))
2476+
}
24732477
}
24742478

24752479
impl PartialEq for Ident {
@@ -2539,6 +2543,14 @@ impl IdentPrinter {
25392543

25402544
impl fmt::Display for IdentPrinter {
25412545
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2546+
if let Some(lifetime) = self.symbol.as_lifetime() {
2547+
f.write_str("'")?;
2548+
if self.is_raw {
2549+
f.write_str("r#")?;
2550+
}
2551+
return fmt::Display::fmt(&lifetime, f);
2552+
}
2553+
25422554
if self.is_raw {
25432555
f.write_str("r#")?;
25442556
} else if self.symbol == kw::DollarCrate {
@@ -2630,6 +2642,11 @@ impl Symbol {
26302642
self == sym::empty
26312643
}
26322644

2645+
pub fn as_lifetime(self) -> Option<Symbol> {
2646+
let name = self.as_str();
2647+
name.strip_prefix("'").map(Symbol::intern)
2648+
}
2649+
26332650
/// This method is supposed to be used in error messages, so it's expected to be
26342651
/// identical to printing the original identifier token written in source code
26352652
/// (`token_to_string`, `Ident::to_string`), except that symbols don't keep the rawness flag
@@ -2860,7 +2877,13 @@ impl Ident {
28602877
/// We see this identifier in a normal identifier position, like variable name or a type.
28612878
/// How was it written originally? Did it use the raw form? Let's try to guess.
28622879
pub fn is_raw_guess(self) -> bool {
2863-
self.name.can_be_raw() && self.is_reserved()
2880+
if self.name == kw::StaticLifetime || self.name == kw::UnderscoreLifetime {
2881+
false
2882+
} else if let Some(lifetime) = self.as_lifetime() {
2883+
lifetime.is_raw_guess()
2884+
} else {
2885+
self.name.can_be_raw() && self.is_reserved()
2886+
}
28642887
}
28652888

28662889
/// Whether this would be the identifier for a tuple field like `self.0`, as

tests/ui/lifetimes/lifetime-errors/error-lifetime-name-issue-143150.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
//@ edition: 2021
2-
fn a(_: dyn Trait + 'r#fn) { //~ ERROR use of undeclared lifetime name `'fn` [E0261]
2+
fn a(_: dyn Trait + 'r#fn) { //~ ERROR use of undeclared lifetime name `'r#fn` [E0261]
33

44
}
55

66
trait Trait {}
77

88
#[derive(Eq, PartialEq)]
99
struct Test {
10-
a: &'r#fn str,
11-
//~^ ERROR use of undeclared lifetime name `'fn` [E0261]
12-
//~| ERROR use of undeclared lifetime name `'fn` [E0261]
10+
a: &'r#fn str,
11+
//~^ ERROR use of undeclared lifetime name `'r#fn` [E0261]
12+
//~| ERROR use of undeclared lifetime name `'r#fn` [E0261]
1313
}
1414

1515
trait Trait1<T>
16-
where T: for<'a> Trait1<T> + 'r#fn { } //~ ERROR use of undeclared lifetime name `'fn` [E0261]
16+
where T: for<'a> Trait1<T> + 'r#fn { } //~ ERROR use of undeclared lifetime name `'r#fn` [E0261]
1717

1818

1919

tests/ui/lifetimes/lifetime-errors/error-lifetime-name-issue-143150.stderr

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,45 @@
1-
error[E0261]: use of undeclared lifetime name `'fn`
1+
error[E0261]: use of undeclared lifetime name `'r#fn`
22
--> $DIR/error-lifetime-name-issue-143150.rs:2:21
33
|
44
LL | fn a(_: dyn Trait + 'r#fn) {
55
| - ^^^^^ undeclared lifetime
66
| |
7-
| help: consider introducing lifetime `'fn` here: `<'fn>`
7+
| help: consider introducing lifetime `'r#fn` here: `<'r#fn>`
88

9-
error[E0261]: use of undeclared lifetime name `'fn`
9+
error[E0261]: use of undeclared lifetime name `'r#fn`
1010
--> $DIR/error-lifetime-name-issue-143150.rs:10:9
1111
|
1212
LL | struct Test {
13-
| - help: consider introducing lifetime `'fn` here: `<'fn>`
14-
LL | a: &'r#fn str,
13+
| - help: consider introducing lifetime `'r#fn` here: `<'r#fn>`
14+
LL | a: &'r#fn str,
1515
| ^^^^^ undeclared lifetime
1616

17-
error[E0261]: use of undeclared lifetime name `'fn`
17+
error[E0261]: use of undeclared lifetime name `'r#fn`
1818
--> $DIR/error-lifetime-name-issue-143150.rs:10:9
1919
|
2020
LL | #[derive(Eq, PartialEq)]
21-
| -- lifetime `'fn` is missing in item created through this procedural macro
21+
| -- lifetime `'r#fn` is missing in item created through this procedural macro
2222
LL | struct Test {
23-
| - help: consider introducing lifetime `'fn` here: `<'fn>`
24-
LL | a: &'r#fn str,
23+
| - help: consider introducing lifetime `'r#fn` here: `<'r#fn>`
24+
LL | a: &'r#fn str,
2525
| ^^^^^ undeclared lifetime
2626

27-
error[E0261]: use of undeclared lifetime name `'fn`
27+
error[E0261]: use of undeclared lifetime name `'r#fn`
2828
--> $DIR/error-lifetime-name-issue-143150.rs:16:32
2929
|
3030
LL | where T: for<'a> Trait1<T> + 'r#fn { }
3131
| ^^^^^ undeclared lifetime
3232
|
3333
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
34-
help: consider making the bound lifetime-generic with a new `'fn` lifetime
34+
help: consider making the bound lifetime-generic with a new `'r#fn` lifetime
3535
|
3636
LL - where T: for<'a> Trait1<T> + 'r#fn { }
37-
LL + where for<'fn, 'a> T: Trait1<T> + 'r#fn { }
37+
LL + where for<'r#fn, 'a> T: Trait1<T> + 'r#fn { }
3838
|
39-
help: consider introducing lifetime `'fn` here
39+
help: consider introducing lifetime `'r#fn` here
4040
|
41-
LL | trait Trait1<'fn, T>
42-
| ++++
41+
LL | trait Trait1<'r#fn, T>
42+
| ++++++
4343

4444
error: aborting due to 4 previous errors
4545

0 commit comments

Comments
 (0)