Skip to content

Commit

Permalink
Rollup merge of rust-lang#91530 - bobrippling:suggest-1-tuple-parens,…
Browse files Browse the repository at this point in the history
… r=camelid

Suggest 1-tuple parentheses on exprs without existing parens

A follow-on from rust-lang#86116, split out from rust-lang#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.
  • Loading branch information
m-ou-se committed Feb 7, 2022
2 parents c2d6ddd + 82a0122 commit fadf0fd
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 27 deletions.
50 changes: 37 additions & 13 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2044,19 +2044,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// If a tuple of length one was expected and the found expression has
// parentheses around it, perhaps the user meant to write `(expr,)` to
// build a tuple (issue #86100)
(ty::Tuple(_), _) if expected.tuple_fields().count() == 1 => {
if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) {
if let Some(code) =
code.strip_prefix('(').and_then(|s| s.strip_suffix(')'))
{
err.span_suggestion(
span,
"use a trailing comma to create a tuple with one element",
format!("({},)", code),
Applicability::MaybeIncorrect,
);
}
}
(ty::Tuple(_), _) => {
self.emit_tuple_wrap_err(&mut err, span, found, expected)
}
// If a character was expected and the found expression is a string literal
// containing a single character, perhaps the user meant to write `'c'` to
Expand Down Expand Up @@ -2119,6 +2108,41 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
diag
}

fn emit_tuple_wrap_err(
&self,
err: &mut DiagnosticBuilder<'tcx>,
span: Span,
found: Ty<'tcx>,
expected: Ty<'tcx>,
) {
let [expected_tup_elem] = &expected.tuple_fields().collect::<Vec<_>>()[..]
else { return };

if !same_type_modulo_infer(expected_tup_elem, found) {
return;
}

let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
else { return };

let msg = "use a trailing comma to create a tuple with one element";
if code.starts_with('(') && code.ends_with(')') {
let before_close = span.hi() - BytePos::from_u32(1);
err.span_suggestion(
span.with_hi(before_close).shrink_to_hi(),
msg,
",".into(),
Applicability::MachineApplicable,
);
} else {
err.multipart_suggestion(
msg,
vec![(span.shrink_to_lo(), "(".into()), (span.shrink_to_hi(), ",)".into())],
Applicability::MachineApplicable,
);
}
}

fn values_str(
&self,
values: ValuePairs<'tcx>,
Expand Down
4 changes: 4 additions & 0 deletions src/test/ui/consts/const-tup-index-span.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ LL | const TUP: (usize,) = 5usize << 64;
|
= note: expected tuple `(usize,)`
found type `usize`
help: use a trailing comma to create a tuple with one element
|
LL | const TUP: (usize,) = (5usize << 64,);
| + ++

error: aborting due to previous error

Expand Down
6 changes: 6 additions & 0 deletions src/test/ui/suggestions/args-instead-of-tuple-errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ fn main() {

let _: Option<(i8,)> = Some();
//~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied

let _: Option<(i32,)> = Some(5_usize);
//~^ ERROR mismatched types

let _: Option<(i32,)> = Some((5_usize));
//~^ ERROR mismatched types
}

fn int_bool(_: (i32, bool)) {
Expand Down
25 changes: 22 additions & 3 deletions src/test/ui/suggestions/args-instead-of-tuple-errors.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ LL | int_bool(1, 2);
| expected 1 argument
|
note: function defined here
--> $DIR/args-instead-of-tuple-errors.rs:15:4
--> $DIR/args-instead-of-tuple-errors.rs:21:4
|
LL | fn int_bool(_: (i32, bool)) {
| ^^^^^^^^ --------------
Expand All @@ -28,6 +28,25 @@ LL | let _: Option<(i8,)> = Some();
| |
| expected 1 argument

error: aborting due to 3 previous errors
error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple-errors.rs:14:34
|
LL | let _: Option<(i32,)> = Some(5_usize);
| ^^^^^^^ expected tuple, found `usize`
|
= note: expected tuple `(i32,)`
found type `usize`

error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple-errors.rs:17:34
|
LL | let _: Option<(i32,)> = Some((5_usize));
| ^^^^^^^^^ expected tuple, found `usize`
|
= note: expected tuple `(i32,)`
found type `usize`

error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0061`.
Some errors have detailed explanations: E0061, E0308.
For more information about an error, try `rustc --explain E0061`.
6 changes: 6 additions & 0 deletions src/test/ui/suggestions/args-instead-of-tuple.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ fn main() {
let _: Option<()> = Some(());
//~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied

let _: Option<(i32,)> = Some((3,));
//~^ ERROR mismatched types

let _: Option<(i32,)> = Some((3,));
//~^ ERROR mismatched types

two_ints((1, 2)); //~ ERROR this function takes 1 argument

with_generic((3, 4)); //~ ERROR this function takes 1 argument
Expand Down
6 changes: 6 additions & 0 deletions src/test/ui/suggestions/args-instead-of-tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ fn main() {
let _: Option<()> = Some();
//~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied

let _: Option<(i32,)> = Some(3);
//~^ ERROR mismatched types

let _: Option<(i32,)> = Some((3));
//~^ ERROR mismatched types

two_ints(1, 2); //~ ERROR this function takes 1 argument

with_generic(3, 4); //~ ERROR this function takes 1 argument
Expand Down
43 changes: 35 additions & 8 deletions src/test/ui/suggestions/args-instead-of-tuple.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,40 @@ help: expected the unit value `()`; create it with empty parentheses
LL | let _: Option<()> = Some(());
| ++

error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple.rs:14:34
|
LL | let _: Option<(i32,)> = Some(3);
| ^ expected tuple, found integer
|
= note: expected tuple `(i32,)`
found type `{integer}`
help: use a trailing comma to create a tuple with one element
|
LL | let _: Option<(i32,)> = Some((3,));
| + ++

error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple.rs:17:34
|
LL | let _: Option<(i32,)> = Some((3));
| ^^^ expected tuple, found integer
|
= note: expected tuple `(i32,)`
found type `{integer}`
help: use a trailing comma to create a tuple with one element
|
LL | let _: Option<(i32,)> = Some((3,));
| +

error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/args-instead-of-tuple.rs:14:5
--> $DIR/args-instead-of-tuple.rs:20:5
|
LL | two_ints(1, 2);
| ^^^^^^^^ - - supplied 2 arguments
|
note: function defined here
--> $DIR/args-instead-of-tuple.rs:19:4
--> $DIR/args-instead-of-tuple.rs:25:4
|
LL | fn two_ints(_: (i32, i32)) {
| ^^^^^^^^ -------------
Expand All @@ -48,13 +74,13 @@ LL | two_ints((1, 2));
| + +

error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/args-instead-of-tuple.rs:16:5
--> $DIR/args-instead-of-tuple.rs:22:5
|
LL | with_generic(3, 4);
| ^^^^^^^^^^^^ - - supplied 2 arguments
|
note: function defined here
--> $DIR/args-instead-of-tuple.rs:22:4
--> $DIR/args-instead-of-tuple.rs:28:4
|
LL | fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
| ^^^^^^^^^^^^ ----------------
Expand All @@ -64,13 +90,13 @@ LL | with_generic((3, 4));
| + +

error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/args-instead-of-tuple.rs:25:9
--> $DIR/args-instead-of-tuple.rs:31:9
|
LL | with_generic(a, b);
| ^^^^^^^^^^^^ - - supplied 2 arguments
|
note: function defined here
--> $DIR/args-instead-of-tuple.rs:22:4
--> $DIR/args-instead-of-tuple.rs:28:4
|
LL | fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
| ^^^^^^^^^^^^ ----------------
Expand All @@ -79,6 +105,7 @@ help: use parentheses to construct a tuple
LL | with_generic((a, b));
| + +

error: aborting due to 6 previous errors
error: aborting due to 8 previous errors

For more information about this error, try `rustc --explain E0061`.
Some errors have detailed explanations: E0061, E0308.
For more information about an error, try `rustc --explain E0061`.
6 changes: 3 additions & 3 deletions src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ LL | let _x: (i32,) = (5);
help: use a trailing comma to create a tuple with one element
|
LL | let _x: (i32,) = (5,);
| ~~~~
| +

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

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

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

0 comments on commit fadf0fd

Please sign in to comment.