}
}
- pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, expected: Ty<'tcx>) {
- if let Some(mut err) = self.demand_coerce_diag(expr, checked_ty, expected) {
+ pub fn demand_coerce(&self,
+ expr: &hir::Expr,
+ checked_ty: Ty<'tcx>,
+ expected: Ty<'tcx>)
+ -> Ty<'tcx> {
+ let (ty, err) = self.demand_coerce_diag(expr, checked_ty, expected);
+ if let Some(mut err) = err {
err.emit();
}
+ ty
}
// Checks that the type of `expr` can be coerced to `expected`.
pub fn demand_coerce_diag(&self,
expr: &hir::Expr,
checked_ty: Ty<'tcx>,
- expected: Ty<'tcx>) -> Option<DiagnosticBuilder<'tcx>> {
+ expected: Ty<'tcx>)
+ -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) {
let expected = self.resolve_type_vars_with_obligations(expected);
- if let Err(e) = self.try_coerce(expr, checked_ty, self.diverges.get(), expected) {
- let cause = self.misc(expr.span);
- let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);
- let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
+ let e = match self.try_coerce(expr, checked_ty, self.diverges.get(), expected) {
+ Ok(ty) => return (ty, None),
+ Err(e) => 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 let ty::TyAdt(expected_adt, substs) = expected.sty {
- let mut compatible_variants = vec![];
- for variant in &expected_adt.variants {
- if variant.fields.len() == 1 {
- 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 mut variant_path = self.tcx.item_path_str(variant.did);
- variant_path = variant_path.trim_left_matches("std::prelude::v1::")
- .to_string();
- compatible_variants.push(variant_path);
- }
+ let cause = self.misc(expr.span);
+ 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 let ty::TyAdt(expected_adt, substs) = expected.sty {
+ let mut compatible_variants = vec![];
+ for variant in &expected_adt.variants {
+ if variant.fields.len() == 1 {
+ 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 mut variant_path = self.tcx.item_path_str(variant.did);
+ variant_path = variant_path.trim_left_matches("std::prelude::v1::")
+ .to_string();
+ compatible_variants.push(variant_path);
}
}
- if !compatible_variants.is_empty() {
- let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr));
- let suggestions = compatible_variants.iter()
- .map(|v| format!("{}({})", v, expr_text)).collect::<Vec<_>>();
- err.span_suggestions(expr.span,
- "try using a variant of the expected type",
- suggestions);
- }
}
+ if !compatible_variants.is_empty() {
+ let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr));
+ let suggestions = compatible_variants.iter()
+ .map(|v| format!("{}({})", v, expr_text)).collect::<Vec<_>>();
+ err.span_suggestions(expr.span,
+ "try using a variant of the expected type",
+ suggestions);
+ }
+ }
- if let Some(suggestion) = self.check_ref(expr,
- checked_ty,
- expected) {
- err.help(&suggestion);
- } else {
- let mode = probe::Mode::MethodCall;
- let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
- mode,
- expected,
- checked_ty,
- ast::DUMMY_NODE_ID);
- if suggestions.len() > 0 {
- err.help(&format!("here are some functions which \
- might fulfill your needs:\n{}",
- self.get_best_match(&suggestions).join("\n")));
- }
+ if let Some(suggestion) = self.check_ref(expr,
+ checked_ty,
+ expected) {
+ err.help(&suggestion);
+ } else {
+ let mode = probe::Mode::MethodCall;
+ let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
+ mode,
+ expected,
+ checked_ty,
+ ast::DUMMY_NODE_ID);
+ if suggestions.len() > 0 {
+ err.help(&format!("here are some functions which \
+ might fulfill your needs:\n{}",
+ self.get_best_match(&suggestions).join("\n")));
}
- return Some(err);
}
- None
+ (expected, Some(err))
}
fn format_method_suggestion(&self, method: &AssociatedItem) -> String {