Skip to content

Commit 66457ac

Browse files
authored
Rollup merge of #154703 - fru1tworld:fix-154600-trailing-comma, r=chenyukang
Fix trailing comma in lifetime suggestion for empty angle brackets Fixes #154600 When suggesting a lifetime parameter (e.g., `'a`) for a type like `Foo<>` (empty angle brackets), the compiler was incorrectly producing `Foo<'a, >` with a trailing comma. ## Root Cause The `has_existing_params` check used `segment.args` to determine if generic parameters exist. However, for empty angle brackets (`<>`), the parser doesn't create any `args`, so `has_existing_params` was `false` — even though the angle brackets themselves exist. This caused the suggestion logic to skip the comma+space suffix (`"'a, "`), but the insert position was still inside the angle brackets, leading to `Foo<'a, >` instead of `Foo<'a>`. ## Fix Replace the `segment.args`-based check with a source text inspection using `span_to_snippet`. The new logic: 1. Finds the `<` character in the source text 2. Extracts the content between `<` and `>` 3. Checks if that content is non-empty (after trimming whitespace) This correctly identifies `<>` as having no existing parameters, avoiding the trailing comma. ## Test Added `tests/ui/lifetimes/E0106-trailing-comma-in-lifetime-suggestion.rs` covering the specific case of empty angle brackets with lifetime suggestions.
2 parents e923bac + 46b0527 commit 66457ac

4 files changed

Lines changed: 55 additions & 8 deletions

File tree

compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4094,6 +4094,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
40944094
};
40954095

40964096
let mut spans_suggs: Vec<_> = Vec::new();
4097+
let source_map = self.r.tcx.sess.source_map();
40974098
let build_sugg = |lt: MissingLifetime| match lt.kind {
40984099
MissingLifetimeKind::Underscore => {
40994100
debug_assert_eq!(lt.count, 1);
@@ -4104,9 +4105,12 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
41044105
(lt.span.shrink_to_hi(), format!("{existing_name} "))
41054106
}
41064107
MissingLifetimeKind::Comma => {
4107-
let sugg: String = std::iter::repeat_n([existing_name.as_str(), ", "], lt.count)
4108-
.flatten()
4108+
let sugg: String = std::iter::repeat_n(existing_name.as_str(), lt.count)
4109+
.intersperse(", ")
41094110
.collect();
4111+
let is_empty_brackets =
4112+
source_map.span_look_ahead(lt.span, ">", Some(50)).is_some();
4113+
let sugg = if is_empty_brackets { sugg } else { format!("{sugg}, ") };
41104114
(lt.span.shrink_to_hi(), sugg)
41114115
}
41124116
MissingLifetimeKind::Brackets => {

tests/ui/generics/wrong-number-of-args.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ LL | type E = Ty<>;
2828
|
2929
help: consider introducing a named lifetime parameter
3030
|
31-
LL | type E<'a> = Ty<'a, >;
32-
| ++++ +++
31+
LL | type E<'a> = Ty<'a>;
32+
| ++++ ++
3333

3434
error[E0106]: missing lifetime specifier
3535
--> $DIR/wrong-number-of-args.rs:120:22
@@ -55,12 +55,12 @@ LL | type F = Box<dyn GenericLifetime<>>;
5555
|
5656
help: consider making the bound lifetime-generic with a new `'a` lifetime
5757
|
58-
LL | type F = Box<dyn for<'a> GenericLifetime<'a, >>;
59-
| +++++++ +++
58+
LL | type F = Box<dyn for<'a> GenericLifetime<'a>>;
59+
| +++++++ ++
6060
help: consider introducing a named lifetime parameter
6161
|
62-
LL | type F<'a> = Box<dyn GenericLifetime<'a, >>;
63-
| ++++ +++
62+
LL | type F<'a> = Box<dyn GenericLifetime<'a>>;
63+
| ++++ ++
6464

6565
error[E0106]: missing lifetime specifier
6666
--> $DIR/wrong-number-of-args.rs:163:43
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Regression test for <https://github.com/rust-lang/rust/issues/154600>.
2+
//
3+
// When suggesting lifetime parameters for empty angle brackets like `Foo<>`,
4+
// the suggestion should not include a trailing comma (e.g., `Foo<'a>` not `Foo<'a, >`).
5+
// When there are other generic arguments like `Foo<T>`, the trailing comma is needed
6+
// (e.g., `Foo<'a, T>`).
7+
8+
#![crate_type = "lib"]
9+
10+
struct Foo<'a>(&'a ());
11+
12+
type A = Foo<>;
13+
//~^ ERROR missing lifetime specifier [E0106]
14+
15+
struct Bar<'a, T>(&'a T);
16+
17+
type B = Bar<u8>;
18+
//~^ ERROR missing lifetime specifier [E0106]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/E0106-trailing-comma-in-lifetime-suggestion.rs:12:13
3+
|
4+
LL | type A = Foo<>;
5+
| ^ expected named lifetime parameter
6+
|
7+
help: consider introducing a named lifetime parameter
8+
|
9+
LL | type A<'a> = Foo<'a>;
10+
| ++++ ++
11+
12+
error[E0106]: missing lifetime specifier
13+
--> $DIR/E0106-trailing-comma-in-lifetime-suggestion.rs:17:13
14+
|
15+
LL | type B = Bar<u8>;
16+
| ^ expected named lifetime parameter
17+
|
18+
help: consider introducing a named lifetime parameter
19+
|
20+
LL | type B<'a> = Bar<'a, u8>;
21+
| ++++ +++
22+
23+
error: aborting due to 2 previous errors
24+
25+
For more information about this error, try `rustc --explain E0106`.

0 commit comments

Comments
 (0)