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::{
&& 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(
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(
}
}
- 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,
|| 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);
}
);
}
+ 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(