From 4738ce463e29da3bb96d14d15e77519bf21bcd49 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 4 Dec 2021 17:33:59 +0000 Subject: [PATCH 1/7] Suggest 1-tuple parentheses, without existing parens --- .../src/infer/error_reporting/mod.rs | 20 +++++++++---------- .../ui/consts/const-tup-index-span.stderr | 4 ++++ src/test/ui/typeck/issue-84768.stderr | 4 ++++ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 1eb8190bd7d2f..486dec50d9ef5 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2046,16 +2046,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // 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, - ); - } + let code_stripped = code + .strip_prefix('(') + .and_then(|s| s.strip_suffix(')')) + .unwrap_or(&code); + err.span_suggestion( + span, + "use a trailing comma to create a tuple with one element", + format!("({},)", code_stripped), + Applicability::MaybeIncorrect, + ); } } // If a character was expected and the found expression is a string literal diff --git a/src/test/ui/consts/const-tup-index-span.stderr b/src/test/ui/consts/const-tup-index-span.stderr index 6724984d8d7ac..392d83a6f345b 100644 --- a/src/test/ui/consts/const-tup-index-span.stderr +++ b/src/test/ui/consts/const-tup-index-span.stderr @@ -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 diff --git a/src/test/ui/typeck/issue-84768.stderr b/src/test/ui/typeck/issue-84768.stderr index 0a79d539ea962..f99d389f940d4 100644 --- a/src/test/ui/typeck/issue-84768.stderr +++ b/src/test/ui/typeck/issue-84768.stderr @@ -12,6 +12,10 @@ LL | ::call_once(f, 1) | = note: expected tuple `(&mut u8,)` found type `{integer}` +help: use a trailing comma to create a tuple with one element + | +LL | ::call_once(f, (1,)) + | ~~~~ error: aborting due to 2 previous errors From c734c32776e26861c89e261b8757522e46031978 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 4 Dec 2021 22:22:23 +0000 Subject: [PATCH 2/7] Replace span suggestion with multipart --- .../src/infer/error_reporting/mod.rs | 20 ++++++++----------- .../ui/consts/const-tup-index-span.stderr | 2 +- src/test/ui/typeck/issue-84768.stderr | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 486dec50d9ef5..e169e9a843197 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2045,18 +2045,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // 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) { - let code_stripped = code - .strip_prefix('(') - .and_then(|s| s.strip_suffix(')')) - .unwrap_or(&code); - err.span_suggestion( - span, - "use a trailing comma to create a tuple with one element", - format!("({},)", code_stripped), - Applicability::MaybeIncorrect, - ); - } + err.multipart_suggestion( + "use a trailing comma to create a tuple with one element", + vec![ + (span.shrink_to_lo(), "(".into()), + (span.shrink_to_hi(), ",)".into()), + ], + Applicability::MaybeIncorrect, + ); } // 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 diff --git a/src/test/ui/consts/const-tup-index-span.stderr b/src/test/ui/consts/const-tup-index-span.stderr index 392d83a6f345b..d301f8c4054c2 100644 --- a/src/test/ui/consts/const-tup-index-span.stderr +++ b/src/test/ui/consts/const-tup-index-span.stderr @@ -9,7 +9,7 @@ LL | const TUP: (usize,) = 5usize << 64; help: use a trailing comma to create a tuple with one element | LL | const TUP: (usize,) = (5usize << 64,); - | ~~~~~~~~~~~~~~~ + | + ++ error: aborting due to previous error diff --git a/src/test/ui/typeck/issue-84768.stderr b/src/test/ui/typeck/issue-84768.stderr index f99d389f940d4..331aa25c7a3d4 100644 --- a/src/test/ui/typeck/issue-84768.stderr +++ b/src/test/ui/typeck/issue-84768.stderr @@ -15,7 +15,7 @@ LL | ::call_once(f, 1) help: use a trailing comma to create a tuple with one element | LL | ::call_once(f, (1,)) - | ~~~~ + | + ++ error: aborting due to 2 previous errors From 18cea90d4a01cbb3a1285f633b1058fd39931956 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 28 Jan 2022 22:32:16 +0000 Subject: [PATCH 3/7] Handle existing parentheses when suggesting trailing-tuple-comma --- .../src/infer/error_reporting/mod.rs | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e169e9a843197..71a81d12839dc 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2045,14 +2045,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // parentheses around it, perhaps the user meant to write `(expr,)` to // build a tuple (issue #86100) (ty::Tuple(_), _) if expected.tuple_fields().count() == 1 => { - err.multipart_suggestion( - "use a trailing comma to create a tuple with one element", - vec![ - (span.shrink_to_lo(), "(".into()), - (span.shrink_to_hi(), ",)".into()), - ], - Applicability::MaybeIncorrect, - ); + if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) { + 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(), + "use a trailing comma to create a tuple with one element", + ",".into(), + Applicability::MaybeIncorrect, + ); + } else { + err.multipart_suggestion( + "use a trailing comma to create a tuple with one element", + vec![ + (span.shrink_to_lo(), "(".into()), + (span.shrink_to_hi(), ",)".into()), + ], + Applicability::MaybeIncorrect, + ); + } + } } // 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 From 91a43f04237dc9fe839fe8466d459e4f215d02fc Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 28 Jan 2022 23:17:47 +0000 Subject: [PATCH 4/7] Only suggest 1-tuple if expected and found types match --- .../src/infer/error_reporting/mod.rs | 48 +++++++++++-------- src/test/ui/typeck/issue-84768.stderr | 4 -- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 71a81d12839dc..c16181aab04fb 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2044,26 +2044,34 @@ 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 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(), - "use a trailing comma to create a tuple with one element", - ",".into(), - Applicability::MaybeIncorrect, - ); - } else { - err.multipart_suggestion( - "use a trailing comma to create a tuple with one element", - vec![ - (span.shrink_to_lo(), "(".into()), - (span.shrink_to_hi(), ",)".into()), - ], - Applicability::MaybeIncorrect, - ); + (ty::Tuple(_), _) => { + if let [expected_tup_elem] = + expected.tuple_fields().collect::>()[..] + { + if same_type_modulo_infer(expected_tup_elem, found) { + if let Ok(code) = + self.tcx.sess().source_map().span_to_snippet(span) + { + 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(), + "use a trailing comma to create a tuple with one element", + ",".into(), + Applicability::MaybeIncorrect, + ); + } else { + err.multipart_suggestion( + "use a trailing comma to create a tuple with one element", + vec![ + (span.shrink_to_lo(), "(".into()), + (span.shrink_to_hi(), ",)".into()), + ], + Applicability::MaybeIncorrect, + ); + } + } } } } diff --git a/src/test/ui/typeck/issue-84768.stderr b/src/test/ui/typeck/issue-84768.stderr index 331aa25c7a3d4..0a79d539ea962 100644 --- a/src/test/ui/typeck/issue-84768.stderr +++ b/src/test/ui/typeck/issue-84768.stderr @@ -12,10 +12,6 @@ LL | ::call_once(f, 1) | = note: expected tuple `(&mut u8,)` found type `{integer}` -help: use a trailing comma to create a tuple with one element - | -LL | ::call_once(f, (1,)) - | + ++ error: aborting due to 2 previous errors From 72d3b45af055276b07e73611278268282848a139 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 28 Jan 2022 23:27:01 +0000 Subject: [PATCH 5/7] Test 1-tuple parentheses wrapping --- .../args-instead-of-tuple-errors.rs | 6 +++ .../args-instead-of-tuple-errors.stderr | 25 +++++++++-- .../suggestions/args-instead-of-tuple.fixed | 6 +++ .../ui/suggestions/args-instead-of-tuple.rs | 6 +++ .../suggestions/args-instead-of-tuple.stderr | 43 +++++++++++++++---- .../issue-86100-tuple-paren-comma.stderr | 6 +-- 6 files changed, 78 insertions(+), 14 deletions(-) diff --git a/src/test/ui/suggestions/args-instead-of-tuple-errors.rs b/src/test/ui/suggestions/args-instead-of-tuple-errors.rs index 2c3ee5fcb8039..5403b8d6d2871 100644 --- a/src/test/ui/suggestions/args-instead-of-tuple-errors.rs +++ b/src/test/ui/suggestions/args-instead-of-tuple-errors.rs @@ -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)) { diff --git a/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr b/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr index a2ad602dbd47a..ddcdfb1c3b344 100644 --- a/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr +++ b/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr @@ -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)) { | ^^^^^^^^ -------------- @@ -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`. diff --git a/src/test/ui/suggestions/args-instead-of-tuple.fixed b/src/test/ui/suggestions/args-instead-of-tuple.fixed index c9b8a41d469b9..66e53f9ce2c80 100644 --- a/src/test/ui/suggestions/args-instead-of-tuple.fixed +++ b/src/test/ui/suggestions/args-instead-of-tuple.fixed @@ -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 diff --git a/src/test/ui/suggestions/args-instead-of-tuple.rs b/src/test/ui/suggestions/args-instead-of-tuple.rs index d4cc3024dd0d2..a15bff07ebfe6 100644 --- a/src/test/ui/suggestions/args-instead-of-tuple.rs +++ b/src/test/ui/suggestions/args-instead-of-tuple.rs @@ -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 diff --git a/src/test/ui/suggestions/args-instead-of-tuple.stderr b/src/test/ui/suggestions/args-instead-of-tuple.stderr index 172db7ee3df38..6a7602c9d0f45 100644 --- a/src/test/ui/suggestions/args-instead-of-tuple.stderr +++ b/src/test/ui/suggestions/args-instead-of-tuple.stderr @@ -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)) { | ^^^^^^^^ ------------- @@ -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((a, b): (i32, T)) { | ^^^^^^^^^^^^ ---------------- @@ -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((a, b): (i32, T)) { | ^^^^^^^^^^^^ ---------------- @@ -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`. diff --git a/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr index 9c8356a528470..0016f19284250 100644 --- a/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr +++ b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr @@ -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 @@ -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 @@ -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 From 344ea6e0e5d5fca3fbfb065a9fd03eff55f76471 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 2 Feb 2022 22:18:36 +0000 Subject: [PATCH 6/7] Factor out emit_tuple_wrap_err, improve Applicability --- .../src/infer/error_reporting/mod.rs | 68 +++++++++++-------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index c16181aab04fb..3b7e861e44efa 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2045,35 +2045,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // parentheses around it, perhaps the user meant to write `(expr,)` to // build a tuple (issue #86100) (ty::Tuple(_), _) => { - if let [expected_tup_elem] = - expected.tuple_fields().collect::>()[..] - { - if same_type_modulo_infer(expected_tup_elem, found) { - if let Ok(code) = - self.tcx.sess().source_map().span_to_snippet(span) - { - 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(), - "use a trailing comma to create a tuple with one element", - ",".into(), - Applicability::MaybeIncorrect, - ); - } else { - err.multipart_suggestion( - "use a trailing comma to create a tuple with one element", - vec![ - (span.shrink_to_lo(), "(".into()), - (span.shrink_to_hi(), ",)".into()), - ], - Applicability::MaybeIncorrect, - ); - } - } - } - } + 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 @@ -2136,6 +2108,44 @@ 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::>()[..] + 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 }; + + 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(), + "use a trailing comma to create a tuple with one element", + ",".into(), + Applicability::MachineApplicable, + ); + } else { + err.multipart_suggestion( + "use a trailing comma to create a tuple with one element", + vec![ + (span.shrink_to_lo(), "(".into()), + (span.shrink_to_hi(), ",)".into()), + ], + Applicability::MachineApplicable, + ); + } + } + fn values_str( &self, values: ValuePairs<'tcx>, From 82a012299dcf6fefc107cbb7036465fe94ec1e2d Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 2 Feb 2022 22:22:13 +0000 Subject: [PATCH 7/7] Merge duplicate suggestion string --- compiler/rustc_infer/src/infer/error_reporting/mod.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 3b7e861e44efa..c5da9977db782 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2125,22 +2125,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { 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(), - "use a trailing comma to create a tuple with one element", + msg, ",".into(), Applicability::MachineApplicable, ); } else { err.multipart_suggestion( - "use a trailing comma to create a tuple with one element", - vec![ - (span.shrink_to_lo(), "(".into()), - (span.shrink_to_hi(), ",)".into()), - ], + msg, + vec![(span.shrink_to_lo(), "(".into()), (span.shrink_to_hi(), ",)".into())], Applicability::MachineApplicable, ); }