Add call in `emit_type_mismatch_suggestions`

This commit is contained in:
Esteban Küber 2023-01-08 07:14:17 +00:00
parent d5a1609ec4
commit ddd9a9fb46
2 changed files with 42 additions and 46 deletions

View File

@ -45,7 +45,7 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::Expr;
use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{Coercion, InferOk, InferResult, TyCtxtInferExt};
use rustc_infer::infer::{Coercion, InferOk, InferResult};
use rustc_infer::traits::Obligation;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::adjustment::{
@ -1565,9 +1565,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
&& let hir::ExprKind::Loop(loop_blk, ..) = expression.kind {
intravisit::walk_block(& mut visitor, loop_blk);
}
if let Some(expr) = expression {
self.note_result_coercion(fcx, &mut err, expr, expected, found);
}
}
ObligationCauseCode::ReturnValue(id) => {
err = self.report_return_mismatched_types(
@ -1584,9 +1581,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
let id = fcx.tcx.hir().parent_id(id);
unsized_return = self.is_return_ty_unsized(fcx, id);
}
if let Some(expr) = expression {
self.note_result_coercion(fcx, &mut err, expr, expected, found);
}
}
_ => {
err = fcx.err_ctxt().report_mismatched_types(
@ -1626,44 +1620,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
}
}
fn note_result_coercion(
&self,
fcx: &FnCtxt<'_, 'tcx>,
err: &mut Diagnostic,
expr: &hir::Expr<'tcx>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
) {
let ty::Adt(e, substs_e) = expected.kind() else { return; };
let ty::Adt(f, substs_f) = found.kind() else { return; };
if e.did() != f.did() {
return;
}
if Some(e.did()) != fcx.tcx.get_diagnostic_item(sym::Result) {
return;
}
let e = substs_e.type_at(1);
let f = substs_f.type_at(1);
if fcx
.infcx
.type_implements_trait(
fcx.tcx.get_diagnostic_item(sym::Into).unwrap(),
[fcx.tcx.erase_regions(f), fcx.tcx.erase_regions(e)],
fcx.param_env,
)
.must_apply_modulo_regions()
{
err.multipart_suggestion(
"you can rely on the implicit conversion that `?` does to transform the error type",
vec![
(expr.span.shrink_to_lo(), "Ok(".to_string()),
(expr.span.shrink_to_hi(), "?)".to_string()),
],
Applicability::MaybeIncorrect,
);
}
}
fn note_unreachable_loop_return(
&self,
err: &mut Diagnostic,

View File

@ -59,7 +59,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
|| self.suggest_into(err, expr, expr_ty, expected)
|| self.suggest_floating_point_literal(err, expr, expected);
|| self.suggest_floating_point_literal(err, expr, expected)
|| self.note_result_coercion(err, expr, expected, expr_ty);
if !suggested {
self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected);
}
@ -697,6 +698,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
pub(crate) fn note_result_coercion(
&self,
err: &mut Diagnostic,
expr: &hir::Expr<'tcx>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
) -> bool {
let ty::Adt(e, substs_e) = expected.kind() else { return false; };
let ty::Adt(f, substs_f) = found.kind() else { return false; };
if e.did() != f.did() {
return false;
}
if Some(e.did()) != self.tcx.get_diagnostic_item(sym::Result) {
return false;
}
let e = substs_e.type_at(1);
let f = substs_f.type_at(1);
if self
.infcx
.type_implements_trait(
self.tcx.get_diagnostic_item(sym::Into).unwrap(),
[self.tcx.erase_regions(f), self.tcx.erase_regions(e)],
self.param_env,
)
.must_apply_modulo_regions()
{
err.multipart_suggestion(
"you can rely on the implicit conversion that `?` does to transform the error type",
vec![
(expr.span.shrink_to_lo(), "Ok(".to_string()),
(expr.span.shrink_to_hi(), "?)".to_string()),
],
Applicability::MaybeIncorrect,
);
return true;
}
false
}
/// 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)
fn suggest_compatible_variants(