Skip to content

Commit b348385

Browse files
committed
Auto merge of #85597 - 0yoyoyo:fix-issue-71563-remove-redundant-args, r=petrochenkov
Fix span of redundant generic arguments Fixes #71563 Above issue is about lifetime arguments, but generic arguments also have same problem. This PR fixes both help messages.
2 parents aab93ca + 0edf4da commit b348385

File tree

5 files changed

+281
-124
lines changed

5 files changed

+281
-124
lines changed

compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs

+44-31
Original file line numberDiff line numberDiff line change
@@ -605,30 +605,35 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
605605
let remove_entire_generics = num_redundant_args >= self.gen_args.args.len();
606606

607607
let remove_lifetime_args = |err: &mut DiagnosticBuilder<'_>| {
608-
let idx_first_redundant_lt_args = self.num_expected_lifetime_args();
609-
let span_lo_redundant_lt_args =
610-
self.gen_args.args[idx_first_redundant_lt_args].span().shrink_to_lo();
611-
let span_hi_redundant_lt_args = self.gen_args.args
612-
[idx_first_redundant_lt_args + num_redundant_lt_args - 1]
613-
.span()
614-
.shrink_to_hi();
615-
let eat_comma =
616-
idx_first_redundant_lt_args + num_redundant_lt_args - 1 != self.gen_args.args.len();
617-
618-
let span_redundant_lt_args = if eat_comma {
619-
let span_hi = self.gen_args.args
620-
[idx_first_redundant_lt_args + num_redundant_lt_args - 1]
621-
.span()
622-
.shrink_to_hi();
623-
span_lo_redundant_lt_args.to(span_hi)
624-
} else {
625-
span_lo_redundant_lt_args.to(span_hi_redundant_lt_args)
626-
};
608+
let mut lt_arg_spans = Vec::new();
609+
let mut found_redundant = false;
610+
for arg in self.gen_args.args {
611+
if let hir::GenericArg::Lifetime(_) = arg {
612+
lt_arg_spans.push(arg.span());
613+
if lt_arg_spans.len() > self.num_expected_lifetime_args() {
614+
found_redundant = true;
615+
}
616+
} else if found_redundant {
617+
// Argument which is redundant and separated like this `'c`
618+
// is not included to avoid including `Bar` in span.
619+
// ```
620+
// type Foo<'a, T> = &'a T;
621+
// let _: Foo<'a, 'b, Bar, 'c>;
622+
// ```
623+
break;
624+
}
625+
}
626+
627+
let span_lo_redundant_lt_args = lt_arg_spans[self.num_expected_lifetime_args()];
628+
let span_hi_redundant_lt_args = lt_arg_spans[lt_arg_spans.len() - 1];
629+
630+
let span_redundant_lt_args = span_lo_redundant_lt_args.to(span_hi_redundant_lt_args);
627631
debug!("span_redundant_lt_args: {:?}", span_redundant_lt_args);
628632

633+
let num_redundant_lt_args = lt_arg_spans.len() - self.num_expected_lifetime_args();
629634
let msg_lifetimes = format!(
630635
"remove {} {} argument{}",
631-
if num_redundant_args == 1 { "this" } else { "these" },
636+
if num_redundant_lt_args == 1 { "this" } else { "these" },
632637
"lifetime",
633638
pluralize!(num_redundant_lt_args),
634639
);
@@ -642,26 +647,34 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
642647
};
643648

644649
let remove_type_or_const_args = |err: &mut DiagnosticBuilder<'_>| {
645-
let idx_first_redundant_type_or_const_args = self.get_lifetime_args_offset()
646-
+ num_redundant_lt_args
647-
+ self.num_expected_type_or_const_args();
650+
let mut gen_arg_spans = Vec::new();
651+
let mut found_redundant = false;
652+
for arg in self.gen_args.args {
653+
match arg {
654+
hir::GenericArg::Type(_) | hir::GenericArg::Const(_) => {
655+
gen_arg_spans.push(arg.span());
656+
if gen_arg_spans.len() > self.num_expected_type_or_const_args() {
657+
found_redundant = true;
658+
}
659+
}
660+
_ if found_redundant => break,
661+
_ => {}
662+
}
663+
}
648664

649665
let span_lo_redundant_type_or_const_args =
650-
self.gen_args.args[idx_first_redundant_type_or_const_args].span().shrink_to_lo();
651-
652-
let span_hi_redundant_type_or_const_args = self.gen_args.args
653-
[idx_first_redundant_type_or_const_args + num_redundant_type_or_const_args - 1]
654-
.span()
655-
.shrink_to_hi();
666+
gen_arg_spans[self.num_expected_type_or_const_args()];
667+
let span_hi_redundant_type_or_const_args = gen_arg_spans[gen_arg_spans.len() - 1];
656668

657669
let span_redundant_type_or_const_args =
658670
span_lo_redundant_type_or_const_args.to(span_hi_redundant_type_or_const_args);
659-
660671
debug!("span_redundant_type_or_const_args: {:?}", span_redundant_type_or_const_args);
661672

673+
let num_redundant_gen_args =
674+
gen_arg_spans.len() - self.num_expected_type_or_const_args();
662675
let msg_types_or_consts = format!(
663676
"remove {} {} argument{}",
664-
if num_redundant_args == 1 { "this" } else { "these" },
677+
if num_redundant_gen_args == 1 { "this" } else { "these" },
665678
"generic",
666679
pluralize!(num_redundant_type_or_const_args),
667680
);

src/test/ui/error-codes/E0107.rs

+26
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
struct Foo<'a>(&'a str);
22
struct Buzz<'a, 'b>(&'a str, &'b str);
3+
struct Qux<'a, T>(&'a T);
4+
struct Quux<T>(T);
35

46
enum Bar {
57
A,
@@ -19,6 +21,30 @@ struct Baz<'a, 'b, 'c> {
1921
foo2: Foo<'a, 'b, 'c>,
2022
//~^ ERROR this struct takes 1 lifetime argument
2123
//~| HELP remove these lifetime arguments
24+
25+
qux1: Qux<'a, 'b, i32>,
26+
//~^ ERROR this struct takes 1 lifetime argument
27+
//~| HELP remove this lifetime argument
28+
29+
qux2: Qux<'a, i32, 'b>,
30+
//~^ ERROR this struct takes 1 lifetime argument
31+
//~| HELP remove this lifetime argument
32+
33+
qux3: Qux<'a, 'b, 'c, i32>,
34+
//~^ ERROR this struct takes 1 lifetime argument
35+
//~| HELP remove these lifetime arguments
36+
37+
qux4: Qux<'a, i32, 'b, 'c>,
38+
//~^ ERROR this struct takes 1 lifetime argument
39+
//~| HELP remove these lifetime arguments
40+
41+
qux5: Qux<'a, 'b, i32, 'c>,
42+
//~^ ERROR this struct takes 1 lifetime argument
43+
//~| HELP remove this lifetime argument
44+
45+
quux: Quux<'a, i32, 'b>,
46+
//~^ ERROR this struct takes 0 lifetime arguments
47+
//~| HELP remove this lifetime argument
2248
}
2349

2450
fn main() {}

src/test/ui/error-codes/E0107.stderr

+89-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0107]: this struct takes 2 lifetime arguments but 1 lifetime argument was supplied
2-
--> $DIR/E0107.rs:11:11
2+
--> $DIR/E0107.rs:13:11
33
|
44
LL | buzz: Buzz<'a>,
55
| ^^^^ -- supplied 1 lifetime argument
@@ -17,21 +17,21 @@ LL | buzz: Buzz<'a, 'a>,
1717
| ^^^^
1818

1919
error[E0107]: this enum takes 0 lifetime arguments but 1 lifetime argument was supplied
20-
--> $DIR/E0107.rs:15:10
20+
--> $DIR/E0107.rs:17:10
2121
|
2222
LL | bar: Bar<'a>,
2323
| ^^^---- help: remove these generics
2424
| |
2525
| expected 0 lifetime arguments
2626
|
2727
note: enum defined here, with 0 lifetime parameters
28-
--> $DIR/E0107.rs:4:6
28+
--> $DIR/E0107.rs:6:6
2929
|
3030
LL | enum Bar {
3131
| ^^^
3232

3333
error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied
34-
--> $DIR/E0107.rs:19:11
34+
--> $DIR/E0107.rs:21:11
3535
|
3636
LL | foo2: Foo<'a, 'b, 'c>,
3737
| ^^^ ------ help: remove these lifetime arguments
@@ -44,6 +44,90 @@ note: struct defined here, with 1 lifetime parameter: `'a`
4444
LL | struct Foo<'a>(&'a str);
4545
| ^^^ --
4646

47-
error: aborting due to 3 previous errors
47+
error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
48+
--> $DIR/E0107.rs:25:11
49+
|
50+
LL | qux1: Qux<'a, 'b, i32>,
51+
| ^^^ -- help: remove this lifetime argument
52+
| |
53+
| expected 1 lifetime argument
54+
|
55+
note: struct defined here, with 1 lifetime parameter: `'a`
56+
--> $DIR/E0107.rs:3:8
57+
|
58+
LL | struct Qux<'a, T>(&'a T);
59+
| ^^^ --
60+
61+
error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
62+
--> $DIR/E0107.rs:29:11
63+
|
64+
LL | qux2: Qux<'a, i32, 'b>,
65+
| ^^^ -- help: remove this lifetime argument
66+
| |
67+
| expected 1 lifetime argument
68+
|
69+
note: struct defined here, with 1 lifetime parameter: `'a`
70+
--> $DIR/E0107.rs:3:8
71+
|
72+
LL | struct Qux<'a, T>(&'a T);
73+
| ^^^ --
74+
75+
error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied
76+
--> $DIR/E0107.rs:33:11
77+
|
78+
LL | qux3: Qux<'a, 'b, 'c, i32>,
79+
| ^^^ ------ help: remove these lifetime arguments
80+
| |
81+
| expected 1 lifetime argument
82+
|
83+
note: struct defined here, with 1 lifetime parameter: `'a`
84+
--> $DIR/E0107.rs:3:8
85+
|
86+
LL | struct Qux<'a, T>(&'a T);
87+
| ^^^ --
88+
89+
error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied
90+
--> $DIR/E0107.rs:37:11
91+
|
92+
LL | qux4: Qux<'a, i32, 'b, 'c>,
93+
| ^^^ ------ help: remove these lifetime arguments
94+
| |
95+
| expected 1 lifetime argument
96+
|
97+
note: struct defined here, with 1 lifetime parameter: `'a`
98+
--> $DIR/E0107.rs:3:8
99+
|
100+
LL | struct Qux<'a, T>(&'a T);
101+
| ^^^ --
102+
103+
error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied
104+
--> $DIR/E0107.rs:41:11
105+
|
106+
LL | qux5: Qux<'a, 'b, i32, 'c>,
107+
| ^^^ -- help: remove this lifetime argument
108+
| |
109+
| expected 1 lifetime argument
110+
|
111+
note: struct defined here, with 1 lifetime parameter: `'a`
112+
--> $DIR/E0107.rs:3:8
113+
|
114+
LL | struct Qux<'a, T>(&'a T);
115+
| ^^^ --
116+
117+
error[E0107]: this struct takes 0 lifetime arguments but 2 lifetime arguments were supplied
118+
--> $DIR/E0107.rs:45:11
119+
|
120+
LL | quux: Quux<'a, i32, 'b>,
121+
| ^^^^ -- help: remove this lifetime argument
122+
| |
123+
| expected 0 lifetime arguments
124+
|
125+
note: struct defined here, with 0 lifetime parameters
126+
--> $DIR/E0107.rs:4:8
127+
|
128+
LL | struct Quux<T>(T);
129+
| ^^^^
130+
131+
error: aborting due to 9 previous errors
48132

49133
For more information about this error, try `rustc --explain E0107`.

src/test/ui/generics/wrong-number-of-args.rs

+6
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ mod lifetime_and_type {
6666
//~| ERROR missing lifetime specifier
6767
//~| HELP consider introducing
6868
//~| HELP add missing
69+
70+
type F = Ty<'static, usize, 'static, usize>;
71+
//~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments
72+
//~| ERROR this struct takes 1 generic argument but 2 generic arguments
73+
//~| HELP remove this lifetime argument
74+
//~| HELP remove this generic argument
6975
}
7076

7177
mod type_and_type_and_type {

0 commit comments

Comments
 (0)