Skip to content

Commit b6eb265

Browse files
committed
Keep redundant-capture suggestions syntactically valid
The lint suggestion now removes the `+` joiner adjacent to a redundant `use<...>` clause, so applying the suggestion does not leave a dangling `+` that fails to parse. The existing `tests/ui/impl-trait/precise-capturing/redundant.stderr` baseline emits the same diagnostic with the expanded suggestion span and is blessed along with the new `run-rustfix` test. Tested: - ./x test tests/ui/impl-trait/precise-capturing/redundant.rs --force-rerun - ./x test tests/ui/impl-trait/precise-capturing/redundant-machine-applicable.rs --force-rerun - ./x test tidy
1 parent 3bf5c6d commit b6eb265

5 files changed

Lines changed: 118 additions & 16 deletions

File tree

compiler/rustc_lint/src/impl_trait_overcaptures.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,9 +361,9 @@ where
361361
// have no uncaptured args, then we should warn to the user that
362362
// it's redundant to capture all args explicitly.
363363
if new_capture_rules
364-
&& let Some((captured_args, capturing_span)) =
365-
opaque.bounds.iter().find_map(|bound| match *bound {
366-
hir::GenericBound::Use(a, s) => Some((a, s)),
364+
&& let Some((use_idx, captured_args, capturing_span)) =
365+
opaque.bounds.iter().enumerate().find_map(|(i, bound)| match *bound {
366+
hir::GenericBound::Use(a, s) => Some((i, a, s)),
367367
_ => None,
368368
})
369369
{
@@ -400,11 +400,25 @@ where
400400
.iter()
401401
.all(|(def_id, _)| explicitly_captured.contains(def_id))
402402
{
403+
// Extend the removal span to include the `+` joiner adjacent
404+
// to `use<...>`, so applying the suggestion does not leave
405+
// behind a stray `+` that fails to parse.
406+
let suggestion_span = if let Some(next) = opaque.bounds.get(use_idx + 1) {
407+
capturing_span.with_hi(next.span().lo())
408+
} else if let Some(prev_idx) = use_idx.checked_sub(1) {
409+
let prev = opaque.bounds[prev_idx];
410+
capturing_span.with_lo(prev.span().hi())
411+
} else {
412+
// `impl use<...>` with no other bound is not valid
413+
// syntax, so this branch is unreachable in practice.
414+
capturing_span
415+
};
416+
403417
self.tcx.emit_node_span_lint(
404418
IMPL_TRAIT_REDUNDANT_CAPTURES,
405419
self.tcx.local_def_id_to_hir_id(opaque_def_id),
406420
opaque_span,
407-
ImplTraitRedundantCapturesLint { capturing_span },
421+
ImplTraitRedundantCapturesLint { capturing_span: suggestion_span },
408422
);
409423
}
410424
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//@ run-rustfix
2+
//@ rustfix-only-machine-applicable
3+
//@ edition: 2024
4+
5+
// Verify that the suggestion produced by `impl_trait_redundant_captures`
6+
// removes the adjacent `+` joiner along with `use<...>`, instead of leaving
7+
// behind a stray `+` that fails to compile. Regression test for
8+
// https://github.com/rust-lang/rust/issues/143216.
9+
10+
#![allow(unused)]
11+
#![deny(impl_trait_redundant_captures)]
12+
13+
// `use<>` at the end of the bound list: the suggestion must remove the
14+
// preceding `+`.
15+
fn end_position() -> impl Sized {}
16+
//~^ ERROR all possible in-scope parameters are already captured
17+
18+
// `use<>` at the start of the bound list: the suggestion must remove the
19+
// following `+`.
20+
fn start_position() -> impl Sized {}
21+
//~^ ERROR all possible in-scope parameters are already captured
22+
23+
// `use<>` in the middle of the bound list: the suggestion must remove
24+
// exactly one `+`, keeping the other to join the remaining bounds.
25+
fn middle_position() -> impl Sized + Send {}
26+
//~^ ERROR all possible in-scope parameters are already captured
27+
28+
fn main() {}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//@ run-rustfix
2+
//@ rustfix-only-machine-applicable
3+
//@ edition: 2024
4+
5+
// Verify that the suggestion produced by `impl_trait_redundant_captures`
6+
// removes the adjacent `+` joiner along with `use<...>`, instead of leaving
7+
// behind a stray `+` that fails to compile. Regression test for
8+
// https://github.com/rust-lang/rust/issues/143216.
9+
10+
#![allow(unused)]
11+
#![deny(impl_trait_redundant_captures)]
12+
13+
// `use<>` at the end of the bound list: the suggestion must remove the
14+
// preceding `+`.
15+
fn end_position() -> impl Sized + use<> {}
16+
//~^ ERROR all possible in-scope parameters are already captured
17+
18+
// `use<>` at the start of the bound list: the suggestion must remove the
19+
// following `+`.
20+
fn start_position() -> impl use<> + Sized {}
21+
//~^ ERROR all possible in-scope parameters are already captured
22+
23+
// `use<>` in the middle of the bound list: the suggestion must remove
24+
// exactly one `+`, keeping the other to join the remaining bounds.
25+
fn middle_position() -> impl Sized + use<> + Send {}
26+
//~^ ERROR all possible in-scope parameters are already captured
27+
28+
fn main() {}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
2+
--> $DIR/redundant-machine-applicable.rs:15:22
3+
|
4+
LL | fn end_position() -> impl Sized + use<> {}
5+
| ^^^^^^^^^^--------
6+
| |
7+
| help: remove the `use<...>` syntax
8+
|
9+
note: the lint level is defined here
10+
--> $DIR/redundant-machine-applicable.rs:11:9
11+
|
12+
LL | #![deny(impl_trait_redundant_captures)]
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
15+
error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
16+
--> $DIR/redundant-machine-applicable.rs:20:24
17+
|
18+
LL | fn start_position() -> impl use<> + Sized {}
19+
| ^^^^^--------^^^^^
20+
| |
21+
| help: remove the `use<...>` syntax
22+
23+
error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
24+
--> $DIR/redundant-machine-applicable.rs:25:25
25+
|
26+
LL | fn middle_position() -> impl Sized + use<> + Send {}
27+
| ^^^^^^^^^^^^^--------^^^^
28+
| |
29+
| help: remove the `use<...>` syntax
30+
31+
error: aborting due to 3 previous errors
32+

tests/ui/impl-trait/precise-capturing/redundant.stderr

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ error: all possible in-scope parameters are already captured, so `use<...>` synt
22
--> $DIR/redundant.rs:5:19
33
|
44
LL | fn hello<'a>() -> impl Sized + use<'a> {}
5-
| ^^^^^^^^^^^^^-------
6-
| |
7-
| help: remove the `use<...>` syntax
5+
| ^^^^^^^^^^----------
6+
| |
7+
| help: remove the `use<...>` syntax
88
|
99
note: the lint level is defined here
1010
--> $DIR/redundant.rs:3:9
@@ -16,25 +16,25 @@ error: all possible in-scope parameters are already captured, so `use<...>` synt
1616
--> $DIR/redundant.rs:10:27
1717
|
1818
LL | fn inherent(&self) -> impl Sized + use<'_> {}
19-
| ^^^^^^^^^^^^^-------
20-
| |
21-
| help: remove the `use<...>` syntax
19+
| ^^^^^^^^^^----------
20+
| |
21+
| help: remove the `use<...>` syntax
2222

2323
error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
2424
--> $DIR/redundant.rs:15:22
2525
|
2626
LL | fn in_trait() -> impl Sized + use<'a, Self>;
27-
| ^^^^^^^^^^^^^-------------
28-
| |
29-
| help: remove the `use<...>` syntax
27+
| ^^^^^^^^^^----------------
28+
| |
29+
| help: remove the `use<...>` syntax
3030

3131
error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
3232
--> $DIR/redundant.rs:19:22
3333
|
3434
LL | fn in_trait() -> impl Sized + use<'a> {}
35-
| ^^^^^^^^^^^^^-------
36-
| |
37-
| help: remove the `use<...>` syntax
35+
| ^^^^^^^^^^----------
36+
| |
37+
| help: remove the `use<...>` syntax
3838

3939
error: aborting due to 4 previous errors
4040

0 commit comments

Comments
 (0)