diff options
| author | Pietro Albini <pietro@pietroalbini.org> | 2018-10-25 14:31:10 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-10-25 14:31:10 +0200 |
| commit | f46ee0482f25827f9259f58c4196cde352cc7c2c (patch) | |
| tree | 580a2cc39cc92d26f56345683c9c9ed9838c3240 | |
| parent | 823244ac0459fb9d85bf97fe7d5c6afaa0964870 (diff) | |
| parent | b0d3d3b959e34ecb6c0b7c29f22c77d8c301514d (diff) | |
| download | rust-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.rs | 53 | ||||
| -rw-r--r-- | src/test/ui/did_you_mean/issue-42764.rs | 16 | ||||
| -rw-r--r-- | src/test/ui/did_you_mean/issue-42764.stderr | 11 |
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`. |
