Skip to content

Commit 557d300

Browse files
authored
Rollup merge of #91530 - bobrippling:suggest-1-tuple-parens, r=camelid
Suggest 1-tuple parentheses on exprs without existing parens A follow-on from #86116, split out from #90677. This alters the suggestion to add a trailing comma to create a 1-tuple - previously we would only apply this if the relevant expression was parenthesised. We now make the suggestion regardless of parentheses, which reduces the fragility of the check (w.r.t formatting). e.g. ```rust let a: Option<(i32,)> = Some(3); ``` gets the below suggestion: ```rust let a: Option<(i32,)> = Some((3,)); // ^ ^^ ``` This change also improves the suggestion in other ways, such as by only making the suggestion if the types would match after the suggestion is applied and making the suggestion a multipart suggestion.
2 parents aee13fb + 82a0122 commit 557d300

8 files changed

+119
-27
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+37-13
Original file line numberDiff line numberDiff line change
@@ -2044,19 +2044,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
20442044
// If a tuple of length one was expected and the found expression has
20452045
// parentheses around it, perhaps the user meant to write `(expr,)` to
20462046
// build a tuple (issue #86100)
2047-
(ty::Tuple(_), _) if expected.tuple_fields().count() == 1 => {
2048-
if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) {
2049-
if let Some(code) =
2050-
code.strip_prefix('(').and_then(|s| s.strip_suffix(')'))
2051-
{
2052-
err.span_suggestion(
2053-
span,
2054-
"use a trailing comma to create a tuple with one element",
2055-
format!("({},)", code),
2056-
Applicability::MaybeIncorrect,
2057-
);
2058-
}
2059-
}
2047+
(ty::Tuple(_), _) => {
2048+
self.emit_tuple_wrap_err(&mut err, span, found, expected)
20602049
}
20612050
// If a character was expected and the found expression is a string literal
20622051
// containing a single character, perhaps the user meant to write `'c'` to
@@ -2119,6 +2108,41 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
21192108
diag
21202109
}
21212110

2111+
fn emit_tuple_wrap_err(
2112+
&self,
2113+
err: &mut DiagnosticBuilder<'tcx>,
2114+
span: Span,
2115+
found: Ty<'tcx>,
2116+
expected: Ty<'tcx>,
2117+
) {
2118+
let [expected_tup_elem] = &expected.tuple_fields().collect::<Vec<_>>()[..]
2119+
else { return };
2120+
2121+
if !same_type_modulo_infer(expected_tup_elem, found) {
2122+
return;
2123+
}
2124+
2125+
let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
2126+
else { return };
2127+
2128+
let msg = "use a trailing comma to create a tuple with one element";
2129+
if code.starts_with('(') && code.ends_with(')') {
2130+
let before_close = span.hi() - BytePos::from_u32(1);
2131+
err.span_suggestion(
2132+
span.with_hi(before_close).shrink_to_hi(),
2133+
msg,
2134+
",".into(),
2135+
Applicability::MachineApplicable,
2136+
);
2137+
} else {
2138+
err.multipart_suggestion(
2139+
msg,
2140+
vec![(span.shrink_to_lo(), "(".into()), (span.shrink_to_hi(), ",)".into())],
2141+
Applicability::MachineApplicable,
2142+
);
2143+
}
2144+
}
2145+
21222146
fn values_str(
21232147
&self,
21242148
values: ValuePairs<'tcx>,

src/test/ui/consts/const-tup-index-span.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ LL | const TUP: (usize,) = 5usize << 64;
66
|
77
= note: expected tuple `(usize,)`
88
found type `usize`
9+
help: use a trailing comma to create a tuple with one element
10+
|
11+
LL | const TUP: (usize,) = (5usize << 64,);
12+
| + ++
913

1014
error: aborting due to previous error
1115

src/test/ui/suggestions/args-instead-of-tuple-errors.rs

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ fn main() {
1010

1111
let _: Option<(i8,)> = Some();
1212
//~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied
13+
14+
let _: Option<(i32,)> = Some(5_usize);
15+
//~^ ERROR mismatched types
16+
17+
let _: Option<(i32,)> = Some((5_usize));
18+
//~^ ERROR mismatched types
1319
}
1420

1521
fn int_bool(_: (i32, bool)) {

src/test/ui/suggestions/args-instead-of-tuple-errors.stderr

+22-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ LL | int_bool(1, 2);
1515
| expected 1 argument
1616
|
1717
note: function defined here
18-
--> $DIR/args-instead-of-tuple-errors.rs:15:4
18+
--> $DIR/args-instead-of-tuple-errors.rs:21:4
1919
|
2020
LL | fn int_bool(_: (i32, bool)) {
2121
| ^^^^^^^^ --------------
@@ -28,6 +28,25 @@ LL | let _: Option<(i8,)> = Some();
2828
| |
2929
| expected 1 argument
3030

31-
error: aborting due to 3 previous errors
31+
error[E0308]: mismatched types
32+
--> $DIR/args-instead-of-tuple-errors.rs:14:34
33+
|
34+
LL | let _: Option<(i32,)> = Some(5_usize);
35+
| ^^^^^^^ expected tuple, found `usize`
36+
|
37+
= note: expected tuple `(i32,)`
38+
found type `usize`
39+
40+
error[E0308]: mismatched types
41+
--> $DIR/args-instead-of-tuple-errors.rs:17:34
42+
|
43+
LL | let _: Option<(i32,)> = Some((5_usize));
44+
| ^^^^^^^^^ expected tuple, found `usize`
45+
|
46+
= note: expected tuple `(i32,)`
47+
found type `usize`
48+
49+
error: aborting due to 5 previous errors
3250

33-
For more information about this error, try `rustc --explain E0061`.
51+
Some errors have detailed explanations: E0061, E0308.
52+
For more information about an error, try `rustc --explain E0061`.

src/test/ui/suggestions/args-instead-of-tuple.fixed

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ fn main() {
1111
let _: Option<()> = Some(());
1212
//~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied
1313

14+
let _: Option<(i32,)> = Some((3,));
15+
//~^ ERROR mismatched types
16+
17+
let _: Option<(i32,)> = Some((3,));
18+
//~^ ERROR mismatched types
19+
1420
two_ints((1, 2)); //~ ERROR this function takes 1 argument
1521

1622
with_generic((3, 4)); //~ ERROR this function takes 1 argument

src/test/ui/suggestions/args-instead-of-tuple.rs

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ fn main() {
1111
let _: Option<()> = Some();
1212
//~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied
1313

14+
let _: Option<(i32,)> = Some(3);
15+
//~^ ERROR mismatched types
16+
17+
let _: Option<(i32,)> = Some((3));
18+
//~^ ERROR mismatched types
19+
1420
two_ints(1, 2); //~ ERROR this function takes 1 argument
1521

1622
with_generic(3, 4); //~ ERROR this function takes 1 argument

src/test/ui/suggestions/args-instead-of-tuple.stderr

+35-8
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,40 @@ help: expected the unit value `()`; create it with empty parentheses
3131
LL | let _: Option<()> = Some(());
3232
| ++
3333

34+
error[E0308]: mismatched types
35+
--> $DIR/args-instead-of-tuple.rs:14:34
36+
|
37+
LL | let _: Option<(i32,)> = Some(3);
38+
| ^ expected tuple, found integer
39+
|
40+
= note: expected tuple `(i32,)`
41+
found type `{integer}`
42+
help: use a trailing comma to create a tuple with one element
43+
|
44+
LL | let _: Option<(i32,)> = Some((3,));
45+
| + ++
46+
47+
error[E0308]: mismatched types
48+
--> $DIR/args-instead-of-tuple.rs:17:34
49+
|
50+
LL | let _: Option<(i32,)> = Some((3));
51+
| ^^^ expected tuple, found integer
52+
|
53+
= note: expected tuple `(i32,)`
54+
found type `{integer}`
55+
help: use a trailing comma to create a tuple with one element
56+
|
57+
LL | let _: Option<(i32,)> = Some((3,));
58+
| +
59+
3460
error[E0061]: this function takes 1 argument but 2 arguments were supplied
35-
--> $DIR/args-instead-of-tuple.rs:14:5
61+
--> $DIR/args-instead-of-tuple.rs:20:5
3662
|
3763
LL | two_ints(1, 2);
3864
| ^^^^^^^^ - - supplied 2 arguments
3965
|
4066
note: function defined here
41-
--> $DIR/args-instead-of-tuple.rs:19:4
67+
--> $DIR/args-instead-of-tuple.rs:25:4
4268
|
4369
LL | fn two_ints(_: (i32, i32)) {
4470
| ^^^^^^^^ -------------
@@ -48,13 +74,13 @@ LL | two_ints((1, 2));
4874
| + +
4975

5076
error[E0061]: this function takes 1 argument but 2 arguments were supplied
51-
--> $DIR/args-instead-of-tuple.rs:16:5
77+
--> $DIR/args-instead-of-tuple.rs:22:5
5278
|
5379
LL | with_generic(3, 4);
5480
| ^^^^^^^^^^^^ - - supplied 2 arguments
5581
|
5682
note: function defined here
57-
--> $DIR/args-instead-of-tuple.rs:22:4
83+
--> $DIR/args-instead-of-tuple.rs:28:4
5884
|
5985
LL | fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
6086
| ^^^^^^^^^^^^ ----------------
@@ -64,13 +90,13 @@ LL | with_generic((3, 4));
6490
| + +
6591

6692
error[E0061]: this function takes 1 argument but 2 arguments were supplied
67-
--> $DIR/args-instead-of-tuple.rs:25:9
93+
--> $DIR/args-instead-of-tuple.rs:31:9
6894
|
6995
LL | with_generic(a, b);
7096
| ^^^^^^^^^^^^ - - supplied 2 arguments
7197
|
7298
note: function defined here
73-
--> $DIR/args-instead-of-tuple.rs:22:4
99+
--> $DIR/args-instead-of-tuple.rs:28:4
74100
|
75101
LL | fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
76102
| ^^^^^^^^^^^^ ----------------
@@ -79,6 +105,7 @@ help: use parentheses to construct a tuple
79105
LL | with_generic((a, b));
80106
| + +
81107

82-
error: aborting due to 6 previous errors
108+
error: aborting due to 8 previous errors
83109

84-
For more information about this error, try `rustc --explain E0061`.
110+
Some errors have detailed explanations: E0061, E0308.
111+
For more information about an error, try `rustc --explain E0061`.

src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ LL | let _x: (i32,) = (5);
1111
help: use a trailing comma to create a tuple with one element
1212
|
1313
LL | let _x: (i32,) = (5,);
14-
| ~~~~
14+
| +
1515

1616
error[E0308]: mismatched types
1717
--> $DIR/issue-86100-tuple-paren-comma.rs:13:9
@@ -24,7 +24,7 @@ LL | foo((Some(3)));
2424
help: use a trailing comma to create a tuple with one element
2525
|
2626
LL | foo((Some(3),));
27-
| ~~~~~~~~~~
27+
| +
2828

2929
error[E0308]: mismatched types
3030
--> $DIR/issue-86100-tuple-paren-comma.rs:17:22
@@ -37,7 +37,7 @@ LL | let _s = S { _s: ("abc".to_string()) };
3737
help: use a trailing comma to create a tuple with one element
3838
|
3939
LL | let _s = S { _s: ("abc".to_string(),) };
40-
| ~~~~~~~~~~~~~~~~~~~~
40+
| +
4141

4242
error[E0308]: mismatched types
4343
--> $DIR/issue-86100-tuple-paren-comma.rs:23:22

0 commit comments

Comments
 (0)