From 0d53f699eaa7d1fec1e6013a6a42b39992c119d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Aug 2019 12:32:18 -0700 Subject: [PATCH] review comments --- src/librustc_typeck/check/expr.rs | 13 ++--- src/librustc_typeck/check/mod.rs | 89 +++++++++++++++++-------------- 2 files changed, 56 insertions(+), 46 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 5c859b9fd32..9680f61d699 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -550,18 +550,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { assert!(e_ty.is_unit()); let ty = coerce.expected_ty(); coerce.coerce_forced_unit(self, &cause, &mut |err| { - let msg = "give it a value of the expected type"; - let label = destination.label - .map(|l| format!(" {}", l.ident)) - .unwrap_or_else(String::new); - let sugg = format!("break{} {}", label, match ty.sty { + let val = match ty.sty { ty::Bool => "true", ty::Char => "'a'", ty::Int(_) | ty::Uint(_) => "42", ty::Float(_) => "3.14159", ty::Error | ty::Never => return, _ => "value", - }); + }; + let msg = "give it a value of the expected type"; + let label = destination.label + .map(|l| format!(" {}", l.ident)) + .unwrap_or_else(String::new); + let sugg = format!("break{} {}", label, val); err.span_suggestion(expr.span, msg, sugg, Applicability::HasPlaceholders); }, false); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 130cc8f3a60..be2af2db66d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3819,6 +3819,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pointing_at_return_type } + /// When encountering an fn-like ctor that needs to unify with a value, check whether calling + /// the ctor would successfully solve the type mismatch and if so, suggest it: + /// ``` + /// fn foo(x: usize) -> usize { x } + /// let x: usize = foo; // suggest calling the `foo` function: `foo(42)` + /// ``` fn suggest_fn_call( &self, err: &mut DiagnosticBuilder<'tcx>, @@ -3826,48 +3832,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, ) -> bool { - if let ty::FnDef(..) | ty::FnPtr(_) = &found.sty { - let sig = found.fn_sig(self.tcx); - let sig = self - .replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, &sig) - .0; - let sig = self.normalize_associated_types_in(expr.span, &sig); - if let Ok(_) = self.try_coerce(expr, sig.output(), expected, AllowTwoPhase::No) { - let (mut sugg_call, applicability) = if sig.inputs().is_empty() { - (String::new(), Applicability::MachineApplicable) - } else { - ("...".to_owned(), Applicability::HasPlaceholders) - }; - let mut msg = "call this function"; - if let ty::FnDef(def_id, ..) = found.sty { - match self.tcx.hir().get_if_local(def_id) { - Some(Node::Item(hir::Item { - node: ItemKind::Fn(.., body_id), - .. - })) => { - let body = self.tcx.hir().body(*body_id); - sugg_call = body.arguments.iter() - .map(|arg| hir::print::to_string( - hir::print::NO_ANN, - |s| s.print_pat(&arg.pat), - )).collect::>().join(", "); - } - Some(Node::Ctor(hir::VariantData::Tuple(field, _))) => { - sugg_call = field.iter().map(|_| "_").collect::>().join(", "); - msg = "instatiate this tuple struct"; - } - _ => {} + match found.sty { + ty::FnDef(..) | ty::FnPtr(_) => {} + _ => return false, + } + + let sig = found.fn_sig(self.tcx); + let sig = self + .replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, &sig) + .0; + let sig = self.normalize_associated_types_in(expr.span, &sig); + if let Ok(_) = self.try_coerce(expr, sig.output(), expected, AllowTwoPhase::No) { + let (mut sugg_call, applicability) = if sig.inputs().is_empty() { + (String::new(), Applicability::MachineApplicable) + } else { + ("...".to_owned(), Applicability::HasPlaceholders) + }; + let mut msg = "call this function"; + if let ty::FnDef(def_id, ..) = found.sty { + match self.tcx.hir().get_if_local(def_id) { + Some(Node::Item(hir::Item { + node: ItemKind::Fn(.., body_id), + .. + })) => { + let body = self.tcx.hir().body(*body_id); + sugg_call = body.arguments.iter() + .map(|arg| hir::print::to_string( + hir::print::NO_ANN, + |s| s.print_pat(&arg.pat), + )).collect::>().join(", "); } - }; - if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) { - err.span_suggestion( - expr.span, - &format!("use parentheses to {}", msg), - format!("{}({})", code, sugg_call), - applicability, - ); - return true; + Some(Node::Ctor(hir::VariantData::Tuple(field, _))) => { + sugg_call = field.iter().map(|_| "_").collect::>().join(", "); + msg = "instatiate this tuple struct"; + } + _ => {} } + }; + if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) { + err.span_suggestion( + expr.span, + &format!("use parentheses to {}", msg), + format!("{}({})", code, sugg_call), + applicability, + ); + return true; } } false