Auto merge of #127635 - matthiaskrgr:rollup-foopajr, r=matthiaskrgr · rust-lang/rust@b286722
@@ -466,21 +466,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
466466 borrow_removal_span,
467467});
468468return true;
469-} else if let Some((deref_ty, _)) =
470-self.autoderef(expr.span, found_ty_inner).silence_errors().nth(1)
471-&& self.can_eq(self.param_env, deref_ty, peeled)
472-&& error_tys_equate_as_ref
473-{
474-let sugg = prefix_wrap(".as_deref()");
475- err.subdiagnostic(errors::SuggestConvertViaMethod {
476-span: expr.span.shrink_to_hi(),
477- sugg,
478- expected,
479- found,
480- borrow_removal_span,
481-});
482-return true;
483-} else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind()
469+} else if let ty::Ref(_, peeled_found_ty, _) = found_ty_inner.kind()
470+&& let ty::Adt(adt, _) = peeled_found_ty.peel_refs().kind()
484471&& self.tcx.is_lang_item(adt.did(), LangItem::String)
485472&& peeled.is_str()
486473// `Result::map`, conversely, does not take ref of the error type.
@@ -496,12 +483,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
496483Applicability::MachineApplicable,
497484);
498485return true;
486+} else {
487+if !error_tys_equate_as_ref {
488+return false;
489+}
490+let mut steps = self.autoderef(expr.span, found_ty_inner).silence_errors();
491+if let Some((deref_ty, _)) = steps.nth(1)
492+&& self.can_eq(self.param_env, deref_ty, peeled)
493+{
494+let sugg = prefix_wrap(".as_deref()");
495+ err.subdiagnostic(errors::SuggestConvertViaMethod {
496+span: expr.span.shrink_to_hi(),
497+ sugg,
498+ expected,
499+ found,
500+ borrow_removal_span,
501+});
502+return true;
503+}
504+for (deref_ty, n_step) in steps {
505+if self.can_eq(self.param_env, deref_ty, peeled) {
506+let explicit_deref = "*".repeat(n_step);
507+let sugg = prefix_wrap(&format!(".map(|v| &{explicit_deref}v)"));
508+ err.subdiagnostic(errors::SuggestConvertViaMethod {
509+span: expr.span.shrink_to_hi(),
510+ sugg,
511+ expected,
512+ found,
513+ borrow_removal_span,
514+});
515+return true;
516+}
517+}
499518}
500519}
501520502521false
503522}
504523524+/// If `ty` is `Option<T>`, returns `T, T, None`.
525+ /// If `ty` is `Result<T, E>`, returns `T, T, Some(E, E)`.
526+ /// Otherwise, returns `None`.
505527 fn deconstruct_option_or_result(
506528&self,
507529found_ty: Ty<'tcx>,