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.
This commit is contained in:
commit
dddebf94bc
@ -64,6 +64,7 @@
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{Item, ItemKind, Node};
|
||||
use rustc_middle::dep_graph::DepContext;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::{
|
||||
self,
|
||||
@ -1965,7 +1966,33 @@ pub fn report_and_explain_type_error(
|
||||
struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
|
||||
}
|
||||
FailureCode::Error0308(failure_str) => {
|
||||
struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str)
|
||||
let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
|
||||
if let ValuePairs::Types(ty::error::ExpectedFound { expected, found }) =
|
||||
trace.values
|
||||
{
|
||||
// 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)
|
||||
match (expected.kind(), found.kind()) {
|
||||
(ty::Tuple(_), ty::Tuple(_)) => {}
|
||||
(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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
err
|
||||
}
|
||||
FailureCode::Error0644(failure_str) => {
|
||||
struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
|
||||
|
25
src/test/ui/suggestions/issue-86100-tuple-paren-comma.rs
Normal file
25
src/test/ui/suggestions/issue-86100-tuple-paren-comma.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// Tests that a suggestion is issued for type mismatch errors when a
|
||||
// 1-tuple is expected and a parenthesized expression of non-tuple
|
||||
// type is supplied.
|
||||
|
||||
fn foo<T>(_t: (T,)) {}
|
||||
struct S { _s: (String,) }
|
||||
|
||||
fn main() {
|
||||
let _x: (i32,) = (5);
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
//~| HELP: use a trailing comma to create a tuple with one element
|
||||
|
||||
foo((Some(3)));
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
//~| HELP: use a trailing comma to create a tuple with one element
|
||||
|
||||
let _s = S { _s: ("abc".to_string()) };
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
//~| HELP: use a trailing comma to create a tuple with one element
|
||||
|
||||
// Do not issue the suggestion if the found type is already a tuple.
|
||||
let t = (1, 2);
|
||||
let _x: (i32,) = (t);
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
}
|
55
src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr
Normal file
55
src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr
Normal file
@ -0,0 +1,55 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-86100-tuple-paren-comma.rs:9:22
|
||||
|
|
||||
LL | let _x: (i32,) = (5);
|
||||
| ------ ^^^ 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
|
||||
|
|
||||
LL | let _x: (i32,) = (5,);
|
||||
| ^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-86100-tuple-paren-comma.rs:13:9
|
||||
|
|
||||
LL | foo((Some(3)));
|
||||
| ^^^^^^^^^ expected tuple, found enum `Option`
|
||||
|
|
||||
= note: expected tuple `(_,)`
|
||||
found enum `Option<{integer}>`
|
||||
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
|
||||
|
|
||||
LL | let _s = S { _s: ("abc".to_string()) };
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected tuple, found struct `String`
|
||||
|
|
||||
= note: expected tuple `(String,)`
|
||||
found struct `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
|
||||
|
|
||||
LL | let _x: (i32,) = (t);
|
||||
| ------ ^^^ expected a tuple with 1 element, found one with 2 elements
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected tuple `(i32,)`
|
||||
found tuple `({integer}, {integer})`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user