Skip to content

Commit dddebf9

Browse files
committed
Auto merge of #86116 - FabianWolff:issue-86100, r=varkor
Suggest a trailing comma if a 1-tuple is expected and a parenthesized expression is found This pull request fixes #86100. The following code: ```rust fn main() { let t: (i32,) = (1); } ``` currently produces: ``` warning: unnecessary parentheses around assigned value --> test.rs:2:21 | 2 | let t: (i32,) = (1); | ^^^ help: remove these parentheses | = note: `#[warn(unused_parens)]` on by default error[E0308]: mismatched types --> test.rs:2:21 | 2 | let t: (i32,) = (1); | ------ ^^^ expected tuple, found integer | | | expected due to this | = note: expected tuple `(i32,)` found type `{integer}` error: aborting due to previous error; 1 warning emitted ``` With my changes, I get the same warning and the following error: ``` error[E0308]: mismatched types --> test.rs:2:21 | 2 | let t: (i32,) = (1); | ------ ^^^ expected tuple, found integer | | | expected due to this | = note: expected tuple `(i32,)` found type `{integer}` help: use a trailing comma to create a tuple with one element | 2 | let t: (i32,) = (1,); | ^^^^ ``` i.e. I have added a suggestion to add a trailing comma to create a 1-tuple. This suggestion is only issued if a 1-tuple is expected and the expression (`(1)` in the example above) is surrounded by parentheses and does not already have a tuple type. In this situation, I'd say that it is pretty likely that the user meant to create a tuple.
2 parents 66ba810 + 6206247 commit dddebf9

File tree

3 files changed

+108
-1
lines changed

3 files changed

+108
-1
lines changed

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

+28-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ use rustc_hir as hir;
6464
use rustc_hir::def_id::DefId;
6565
use rustc_hir::lang_items::LangItem;
6666
use rustc_hir::{Item, ItemKind, Node};
67+
use rustc_middle::dep_graph::DepContext;
6768
use rustc_middle::ty::error::TypeError;
6869
use rustc_middle::ty::{
6970
self,
@@ -1965,7 +1966,33 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
19651966
struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
19661967
}
19671968
FailureCode::Error0308(failure_str) => {
1968-
struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str)
1969+
let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
1970+
if let ValuePairs::Types(ty::error::ExpectedFound { expected, found }) =
1971+
trace.values
1972+
{
1973+
// If a tuple of length one was expected and the found expression has
1974+
// parentheses around it, perhaps the user meant to write `(expr,)` to
1975+
// build a tuple (issue #86100)
1976+
match (expected.kind(), found.kind()) {
1977+
(ty::Tuple(_), ty::Tuple(_)) => {}
1978+
(ty::Tuple(_), _) if expected.tuple_fields().count() == 1 => {
1979+
if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) {
1980+
if let Some(code) =
1981+
code.strip_prefix('(').and_then(|s| s.strip_suffix(')'))
1982+
{
1983+
err.span_suggestion(
1984+
span,
1985+
"use a trailing comma to create a tuple with one element",
1986+
format!("({},)", code),
1987+
Applicability::MaybeIncorrect,
1988+
);
1989+
}
1990+
}
1991+
}
1992+
_ => {}
1993+
}
1994+
}
1995+
err
19691996
}
19701997
FailureCode::Error0644(failure_str) => {
19711998
struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Tests that a suggestion is issued for type mismatch errors when a
2+
// 1-tuple is expected and a parenthesized expression of non-tuple
3+
// type is supplied.
4+
5+
fn foo<T>(_t: (T,)) {}
6+
struct S { _s: (String,) }
7+
8+
fn main() {
9+
let _x: (i32,) = (5);
10+
//~^ ERROR: mismatched types [E0308]
11+
//~| HELP: use a trailing comma to create a tuple with one element
12+
13+
foo((Some(3)));
14+
//~^ ERROR: mismatched types [E0308]
15+
//~| HELP: use a trailing comma to create a tuple with one element
16+
17+
let _s = S { _s: ("abc".to_string()) };
18+
//~^ ERROR: mismatched types [E0308]
19+
//~| HELP: use a trailing comma to create a tuple with one element
20+
21+
// Do not issue the suggestion if the found type is already a tuple.
22+
let t = (1, 2);
23+
let _x: (i32,) = (t);
24+
//~^ ERROR: mismatched types [E0308]
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-86100-tuple-paren-comma.rs:9:22
3+
|
4+
LL | let _x: (i32,) = (5);
5+
| ------ ^^^ expected tuple, found integer
6+
| |
7+
| expected due to this
8+
|
9+
= note: expected tuple `(i32,)`
10+
found type `{integer}`
11+
help: use a trailing comma to create a tuple with one element
12+
|
13+
LL | let _x: (i32,) = (5,);
14+
| ^^^^
15+
16+
error[E0308]: mismatched types
17+
--> $DIR/issue-86100-tuple-paren-comma.rs:13:9
18+
|
19+
LL | foo((Some(3)));
20+
| ^^^^^^^^^ expected tuple, found enum `Option`
21+
|
22+
= note: expected tuple `(_,)`
23+
found enum `Option<{integer}>`
24+
help: use a trailing comma to create a tuple with one element
25+
|
26+
LL | foo((Some(3),));
27+
| ^^^^^^^^^^
28+
29+
error[E0308]: mismatched types
30+
--> $DIR/issue-86100-tuple-paren-comma.rs:17:22
31+
|
32+
LL | let _s = S { _s: ("abc".to_string()) };
33+
| ^^^^^^^^^^^^^^^^^^^ expected tuple, found struct `String`
34+
|
35+
= note: expected tuple `(String,)`
36+
found struct `String`
37+
help: use a trailing comma to create a tuple with one element
38+
|
39+
LL | let _s = S { _s: ("abc".to_string(),) };
40+
| ^^^^^^^^^^^^^^^^^^^^
41+
42+
error[E0308]: mismatched types
43+
--> $DIR/issue-86100-tuple-paren-comma.rs:23:22
44+
|
45+
LL | let _x: (i32,) = (t);
46+
| ------ ^^^ expected a tuple with 1 element, found one with 2 elements
47+
| |
48+
| expected due to this
49+
|
50+
= note: expected tuple `(i32,)`
51+
found tuple `({integer}, {integer})`
52+
53+
error: aborting due to 4 previous errors
54+
55+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)