Skip to content

Commit a6bd272

Browse files
committed
print raw lifetime idents with r#
1 parent e1b9081 commit a6bd272

File tree

4 files changed

+84
-6
lines changed

4 files changed

+84
-6
lines changed

compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3112,7 +3112,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
31123112
} else {
31133113
self.suggest_introducing_lifetime(
31143114
&mut err,
3115-
Some(lifetime_ref.ident.name.as_str()),
3115+
Some(lifetime_ref.ident),
31163116
|err, _, span, message, suggestion, span_suggs| {
31173117
err.multipart_suggestion_verbose(
31183118
message,
@@ -3130,7 +3130,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
31303130
fn suggest_introducing_lifetime(
31313131
&self,
31323132
err: &mut Diag<'_>,
3133-
name: Option<&str>,
3133+
name: Option<Ident>,
31343134
suggest: impl Fn(
31353135
&mut Diag<'_>,
31363136
bool,
@@ -3177,7 +3177,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
31773177
let mut rm_inner_binders: FxIndexSet<Span> = Default::default();
31783178
let (span, sugg) = if span.is_empty() {
31793179
let mut binder_idents: FxIndexSet<Ident> = Default::default();
3180-
binder_idents.insert(Ident::from_str(name.unwrap_or("'a")));
3180+
binder_idents.insert(name.unwrap_or(Ident::from_str("'a")));
31813181

31823182
// We need to special case binders in the following situation:
31833183
// Change `T: for<'a> Trait<T> + 'b` to `for<'a, 'b> T: Trait<T> + 'b`
@@ -3232,15 +3232,16 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
32323232
.source_map()
32333233
.span_through_char(span, '<')
32343234
.shrink_to_hi();
3235-
let sugg = format!("{}, ", name.unwrap_or("'a"));
3235+
let sugg =
3236+
format!("{}, ", name.map(|i| i.to_string()).as_deref().unwrap_or("'a"));
32363237
(span, sugg)
32373238
};
32383239

32393240
if higher_ranked {
32403241
let message = Cow::from(format!(
32413242
"consider making the {} lifetime-generic with a new `{}` lifetime",
32423243
kind.descr(),
3243-
name.unwrap_or("'a"),
3244+
name.map(|i| i.to_string()).as_deref().unwrap_or("'a"),
32443245
));
32453246
should_continue = suggest(
32463247
err,

compiler/rustc_span/src/symbol.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2505,7 +2505,11 @@ impl fmt::Debug for Ident {
25052505
/// except that AST identifiers don't keep the rawness flag, so we have to guess it.
25062506
impl fmt::Display for Ident {
25072507
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2508-
fmt::Display::fmt(&IdentPrinter::new(self.name, self.is_raw_guess(), None), f)
2508+
if let Some(ident) = self.as_raw_lifetime_name_without_apostrophe() {
2509+
write!(f, "'{}", IdentPrinter::new(ident.name, true, None))
2510+
} else {
2511+
fmt::Display::fmt(&IdentPrinter::new(self.name, self.is_raw_guess(), None), f)
2512+
}
25092513
}
25102514
}
25112515

@@ -2949,6 +2953,16 @@ impl Ident {
29492953
self.name.can_be_raw() && self.is_reserved()
29502954
}
29512955

2956+
pub fn as_raw_lifetime_name_without_apostrophe(self) -> Option<Ident> {
2957+
// this should be kept consistent with `Parser::expect_lifetime` found under
2958+
// compiler/rustc_parse/src/parser/ty.rs
2959+
let name_without_apostrophe = self.without_first_quote();
2960+
(name_without_apostrophe.name != self.name
2961+
&& ![kw::UnderscoreLifetime, kw::StaticLifetime].contains(&self.name)
2962+
&& name_without_apostrophe.is_raw_guess())
2963+
.then_some(name_without_apostrophe)
2964+
}
2965+
29522966
/// Whether this would be the identifier for a tuple field like `self.0`, as
29532967
/// opposed to a named field like `self.thing`.
29542968
pub fn is_numeric(self) -> bool {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Check that we properly suggest `r#fn` if we use it undeclared.
2+
// https://github.com/rust-lang/rust/issues/143150
3+
//
4+
//@ edition: 2021
5+
6+
fn a(_: dyn Trait + 'r#fn) {
7+
//~^ ERROR use of undeclared lifetime name `'r#fn` [E0261]
8+
}
9+
10+
trait Trait {}
11+
12+
struct Test {
13+
a: &'r#fn str,
14+
//~^ ERROR use of undeclared lifetime name `'r#fn` [E0261]
15+
}
16+
17+
trait Trait1<T>
18+
where T: for<'a> Trait1<T> + 'r#fn { }
19+
//~^ ERROR use of undeclared lifetime name `'r#fn` [E0261]
20+
21+
fn main() {}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
error[E0261]: use of undeclared lifetime name `'r#fn`
2+
--> $DIR/use-of-undeclared-raw-lifetimes.rs:6:21
3+
|
4+
LL | fn a(_: dyn Trait + 'r#fn) {
5+
| ^^^^^ undeclared lifetime
6+
|
7+
help: consider introducing lifetime `'r#fn` here
8+
|
9+
LL | fn a<'fn>(_: dyn Trait + 'r#fn) {
10+
| +++++
11+
12+
error[E0261]: use of undeclared lifetime name `'r#fn`
13+
--> $DIR/use-of-undeclared-raw-lifetimes.rs:13:9
14+
|
15+
LL | a: &'r#fn str,
16+
| ^^^^^ undeclared lifetime
17+
|
18+
help: consider introducing lifetime `'r#fn` here
19+
|
20+
LL | struct Test<'fn> {
21+
| +++++
22+
23+
error[E0261]: use of undeclared lifetime name `'r#fn`
24+
--> $DIR/use-of-undeclared-raw-lifetimes.rs:18:32
25+
|
26+
LL | where T: for<'a> Trait1<T> + 'r#fn { }
27+
| ^^^^^ undeclared lifetime
28+
|
29+
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
30+
help: consider making the bound lifetime-generic with a new `'r#fn` lifetime
31+
|
32+
LL - where T: for<'a> Trait1<T> + 'r#fn { }
33+
LL + where for<'fn, 'a> T: Trait1<T> + 'r#fn { }
34+
|
35+
help: consider introducing lifetime `'r#fn` here
36+
|
37+
LL | trait Trait1<'r#fn, T>
38+
| ++++++
39+
40+
error: aborting due to 3 previous errors
41+
42+
For more information about this error, try `rustc --explain E0261`.

0 commit comments

Comments
 (0)