From dae6dc6b97bcc7675b28f956d8aff2e27ede1a4f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 11 Jan 2022 20:22:00 -0800 Subject: [PATCH] Fix `try wrapping expression in variant` suggestion with struct field shorthand --- compiler/rustc_typeck/src/check/demand.rs | 87 +++++++++++++------ .../ui/did_you_mean/compatible-variants.rs | 8 ++ .../did_you_mean/compatible-variants.stderr | 31 +++++-- 3 files changed, 92 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index c351a9f7040..4898109fa38 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -338,31 +338,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .collect(); - if let [variant] = &compatible_variants[..] { - // Just a single matching variant. - err.multipart_suggestion( - &format!("try wrapping the expression in `{}`", variant), - vec![ - (expr.span.shrink_to_lo(), format!("{}(", variant)), - (expr.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MaybeIncorrect, - ); - } else if compatible_variants.len() > 1 { - // More than one matching variant. - err.multipart_suggestions( - &format!( - "try wrapping the expression in a variant of `{}`", - self.tcx.def_path_str(expected_adt.did) - ), - compatible_variants.into_iter().map(|variant| { - vec![ - (expr.span.shrink_to_lo(), format!("{}(", variant)), - (expr.span.shrink_to_hi(), ")".to_string()), - ] - }), - Applicability::MaybeIncorrect, - ); + if self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, expr.span) { + if let Ok(code) = self.tcx.sess.source_map().span_to_snippet(expr.span) { + match &compatible_variants[..] { + [] => { /* No variants to format */ } + [variant] => { + // Just a single matching variant. + err.span_suggestion_verbose( + expr.span, + &format!("try wrapping the expression in `{}`", variant), + format!("{}: {}({})", code, variant, code), + Applicability::MaybeIncorrect, + ); + } + _ => { + // More than one matching variant. + err.span_suggestions( + expr.span, + &format!( + "try wrapping the expression in a variant of `{}`", + self.tcx.def_path_str(expected_adt.did) + ), + compatible_variants + .into_iter() + .map(|variant| format!("{}: {}({})", code, variant, code)), + Applicability::MaybeIncorrect, + ); + } + } + } else { + /* Can't format this without a snippet */ + } + } else { + match &compatible_variants[..] { + [] => { /* No variants to format */ } + [variant] => { + // Just a single matching variant. + err.multipart_suggestion_verbose( + &format!("try wrapping the expression in `{}`", variant), + vec![ + (expr.span.shrink_to_lo(), format!("{}(", variant)), + (expr.span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MaybeIncorrect, + ); + } + _ => { + // More than one matching variant. + err.multipart_suggestions( + &format!( + "try wrapping the expression in a variant of `{}`", + self.tcx.def_path_str(expected_adt.did) + ), + compatible_variants.into_iter().map(|variant| { + vec![ + (expr.span.shrink_to_lo(), format!("{}(", variant)), + (expr.span.shrink_to_hi(), ")".to_string()), + ] + }), + Applicability::MaybeIncorrect, + ); + } + } } } } diff --git a/src/test/ui/did_you_mean/compatible-variants.rs b/src/test/ui/did_you_mean/compatible-variants.rs index fb6b6a5673d..a70dda8386f 100644 --- a/src/test/ui/did_you_mean/compatible-variants.rs +++ b/src/test/ui/did_you_mean/compatible-variants.rs @@ -3,6 +3,10 @@ enum Hey { B(B), } +struct Foo { + bar: Option, +} + fn f() {} fn a() -> Option<()> { @@ -40,4 +44,8 @@ fn main() { let _: Hey = false; //~^ ERROR mismatched types //~| HELP try wrapping + let bar = 1i32; + let _ = Foo { bar }; + //~^ ERROR mismatched types + //~| HELP try wrapping } diff --git a/src/test/ui/did_you_mean/compatible-variants.stderr b/src/test/ui/did_you_mean/compatible-variants.stderr index e77949687fc..1d4448764c1 100644 --- a/src/test/ui/did_you_mean/compatible-variants.stderr +++ b/src/test/ui/did_you_mean/compatible-variants.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:9:5 + --> $DIR/compatible-variants.rs:13:5 | LL | fn a() -> Option<()> { | ---------- expected `Option<()>` because of return type @@ -21,7 +21,7 @@ LL + Some(()) | error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:17:5 + --> $DIR/compatible-variants.rs:21:5 | LL | fn b() -> Result<(), ()> { | -------------- expected `Result<(), ()>` because of return type @@ -37,7 +37,7 @@ LL + Ok(()) | error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:23:25 + --> $DIR/compatible-variants.rs:27:25 | LL | let _: Option<()> = while false {}; | ---------- ^^^^^^^^^^^^^^ expected enum `Option`, found `()` @@ -52,7 +52,7 @@ LL | let _: Option<()> = Some(while false {}); | +++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:27:9 + --> $DIR/compatible-variants.rs:31:9 | LL | while false {} | ^^^^^^^^^^^^^^ expected enum `Option`, found `()` @@ -69,7 +69,7 @@ LL + Some(()) | error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:31:31 + --> $DIR/compatible-variants.rs:35:31 | LL | let _: Result = 1; | ---------------- ^ expected enum `Result`, found integer @@ -86,7 +86,7 @@ LL | let _: Result = Err(1); | ++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:34:26 + --> $DIR/compatible-variants.rs:38:26 | LL | let _: Option = 1; | ----------- ^ expected enum `Option`, found integer @@ -101,7 +101,7 @@ LL | let _: Option = Some(1); | +++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:37:28 + --> $DIR/compatible-variants.rs:41:28 | LL | let _: Hey = 1; | ------------- ^ expected enum `Hey`, found integer @@ -118,7 +118,7 @@ LL | let _: Hey = Hey::B(1); | +++++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:40:29 + --> $DIR/compatible-variants.rs:44:29 | LL | let _: Hey = false; | -------------- ^^^^^ expected enum `Hey`, found `bool` @@ -132,6 +132,19 @@ help: try wrapping the expression in `Hey::B` LL | let _: Hey = Hey::B(false); | +++++++ + -error: aborting due to 8 previous errors +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:48:19 + | +LL | let _ = Foo { bar }; + | ^^^ expected enum `Option`, found `i32` + | + = note: expected enum `Option` + found type `i32` +help: try wrapping the expression in `Some` + | +LL | let _ = Foo { bar: Some(bar) }; + | ~~~~~~~~~~~~~~ + +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0308`.