about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPietro Albini <pietro@pietroalbini.org>2018-10-25 14:31:10 +0200
committerGitHub <noreply@github.com>2018-10-25 14:31:10 +0200
commitf46ee0482f25827f9259f58c4196cde352cc7c2c (patch)
tree580a2cc39cc92d26f56345683c9c9ed9838c3240
parent823244ac0459fb9d85bf97fe7d5c6afaa0964870 (diff)
parentb0d3d3b959e34ecb6c0b7c29f22c77d8c301514d (diff)
downloadrust-f46ee0482f25827f9259f58c4196cde352cc7c2c.tar.gz
rust-f46ee0482f25827f9259f58c4196cde352cc7c2c.zip
Rollup merge of #55253 - zackmdavis:some_suggestion, r=pnkfelix
only issue "variant of the expected type" suggestion for enums

This suggestion (introduced in pull-request #43178 / eac74104) was being issued for one-field-struct expected types (in which case it is misleading and outright wrong), even though it was only intended for one-field enum-variants (most notably, `Some`).

Add a conditional to adhere to the original intent. (It would be possible to generalize to structs, but not obviously net desirable.) This adds a level of indentation, so the diff here is going to be
easier to read in [ignore-whitespace mode](https://github.com/rust-lang/rust/commit/b0d3d3b9?w=1).

Resolves #55250.

r? @pnkfelix
-rw-r--r--src/librustc_typeck/check/demand.rs53
-rw-r--r--src/test/ui/did_you_mean/issue-42764.rs16
-rw-r--r--src/test/ui/did_you_mean/issue-42764.stderr11
3 files changed, 53 insertions, 27 deletions
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index d82d36a1937..7773e2d5708 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -111,34 +111,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);
         let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
 
-        // If the expected type is an enum with any variants whose sole
-        // field is of the found type, suggest such variants. See Issue
-        // #42764.
+        // If the expected type is an enum (Issue #55250) with any variants whose
+        // sole field is of the found type, suggest such variants. (Issue #42764)
         if let ty::Adt(expected_adt, substs) = expected.sty {
-            let mut compatible_variants = expected_adt.variants
-                                                  .iter()
-                                                  .filter(|variant| variant.fields.len() == 1)
-                                                  .filter_map(|variant| {
-                let sole_field = &variant.fields[0];
-                let sole_field_ty = sole_field.ty(self.tcx, substs);
-                if self.can_coerce(expr_ty, sole_field_ty) {
-                    let variant_path = self.tcx.item_path_str(variant.did);
-                    Some(variant_path.trim_left_matches("std::prelude::v1::").to_string())
-                } else {
-                    None
+            if expected_adt.is_enum() {
+                let mut compatible_variants = expected_adt.variants
+                    .iter()
+                    .filter(|variant| variant.fields.len() == 1)
+                    .filter_map(|variant| {
+                        let sole_field = &variant.fields[0];
+                        let sole_field_ty = sole_field.ty(self.tcx, substs);
+                        if self.can_coerce(expr_ty, sole_field_ty) {
+                            let variant_path = self.tcx.item_path_str(variant.did);
+                            Some(variant_path.trim_left_matches("std::prelude::v1::").to_string())
+                        } else {
+                            None
+                        }
+                    }).peekable();
+
+                if compatible_variants.peek().is_some() {
+                    let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr));
+                    let suggestions = compatible_variants
+                        .map(|v| format!("{}({})", v, expr_text)).collect::<Vec<_>>();
+                    err.span_suggestions_with_applicability(
+                        expr.span,
+                        "try using a variant of the expected type",
+                        suggestions,
+                        Applicability::MaybeIncorrect,
+                    );
                 }
-            }).peekable();
-
-            if compatible_variants.peek().is_some() {
-                let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr));
-                let suggestions = compatible_variants.map(|v|
-                    format!("{}({})", v, expr_text)).collect::<Vec<_>>();
-                err.span_suggestions_with_applicability(
-                     expr.span,
-                     "try using a variant of the expected type",
-                     suggestions,
-                     Applicability::MaybeIncorrect,
-                );
             }
         }
 
diff --git a/src/test/ui/did_you_mean/issue-42764.rs b/src/test/ui/did_you_mean/issue-42764.rs
index ff4bb428d5f..1c79499ba59 100644
--- a/src/test/ui/did_you_mean/issue-42764.rs
+++ b/src/test/ui/did_you_mean/issue-42764.rs
@@ -20,4 +20,20 @@ fn main() {
     let n: usize = 42;
     this_function_expects_a_double_option(n);
     //~^ ERROR mismatched types
+    //~| HELP try using a variant of the expected type
+}
+
+
+// But don't issue the "try using a variant" help if the one-"variant" ADT is
+// actually a one-field struct.
+
+struct Payload;
+
+struct Wrapper { payload: Payload }
+
+struct Context { wrapper: Wrapper }
+
+fn overton() {
+    let _c = Context { wrapper: Payload{} };
+    //~^ ERROR mismatched types
 }
diff --git a/src/test/ui/did_you_mean/issue-42764.stderr b/src/test/ui/did_you_mean/issue-42764.stderr
index f1da920872d..e256a436aff 100644
--- a/src/test/ui/did_you_mean/issue-42764.stderr
+++ b/src/test/ui/did_you_mean/issue-42764.stderr
@@ -13,6 +13,15 @@ LL |     this_function_expects_a_double_option(DoubleOption::FirstSome(n));
 LL |     this_function_expects_a_double_option(DoubleOption::AlternativeSome(n));
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/issue-42764.rs:37:33
+   |
+LL |     let _c = Context { wrapper: Payload{} };
+   |                                 ^^^^^^^^^ expected struct `Wrapper`, found struct `Payload`
+   |
+   = note: expected type `Wrapper`
+              found type `Payload`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.