Peel borrows before suggesting as_ref/as_deref
This commit is contained in:
parent
c92140e838
commit
a9188226a8
@ -329,15 +329,16 @@ pub struct CtorIsPrivate {
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
#[multipart_suggestion(
|
||||
hir_typeck_convert_using_method,
|
||||
code = "{sugg}",
|
||||
applicability = "machine-applicable",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub struct SuggestConvertViaMethod<'tcx> {
|
||||
#[primary_span]
|
||||
#[suggestion_part(code = "{sugg}")]
|
||||
pub span: Span,
|
||||
#[suggestion_part(code = "")]
|
||||
pub borrow_removal_span: Option<Span>,
|
||||
pub sugg: &'static str,
|
||||
pub expected: Ty<'tcx>,
|
||||
pub found: Ty<'tcx>,
|
||||
|
@ -413,7 +413,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.deconstruct_option_or_result(found, expected)
|
||||
&& let ty::Ref(_, peeled, hir::Mutability::Not) = *expected_ty_inner.kind()
|
||||
{
|
||||
// Check that given `Result<_, E>`, our expected ty is `Result<_, &E>`
|
||||
// Suggest removing any stray borrows (unless there's macro shenanigans involved).
|
||||
let inner_expr = expr.peel_borrows();
|
||||
if !inner_expr.span.eq_ctxt(expr.span) {
|
||||
return false;
|
||||
}
|
||||
let borrow_removal_span = if inner_expr.hir_id == expr.hir_id {
|
||||
None
|
||||
} else {
|
||||
Some(expr.span.shrink_to_lo().until(inner_expr.span))
|
||||
};
|
||||
// Given `Result<_, E>`, check our expected ty is `Result<_, &E>` for
|
||||
// `as_ref` and `as_deref` compatibility.
|
||||
let error_tys_equate_as_ref = error_tys.map_or(true, |(found, expected)| {
|
||||
self.can_eq(self.param_env, self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, found), expected)
|
||||
});
|
||||
@ -425,6 +436,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
sugg: ".as_ref()",
|
||||
expected,
|
||||
found,
|
||||
borrow_removal_span,
|
||||
});
|
||||
return true;
|
||||
} else if let Some((deref_ty, _)) =
|
||||
@ -437,11 +449,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
sugg: ".as_deref()",
|
||||
expected,
|
||||
found,
|
||||
borrow_removal_span,
|
||||
});
|
||||
return true;
|
||||
} else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind()
|
||||
&& Some(adt.did()) == self.tcx.lang_items().string()
|
||||
&& peeled.is_str()
|
||||
// `Result::map`, conversely, does not take ref of the error type.
|
||||
&& error_tys.map_or(true, |(found, expected)| {
|
||||
self.can_eq(self.param_env, found, expected)
|
||||
})
|
||||
|
@ -36,8 +36,9 @@ LL | fn takes_option(_arg: Option<&String>) {}
|
||||
| ^^^^^^^^^^^^ ---------------------
|
||||
help: try using `.as_ref()` to convert `&Option<String>` to `Option<&String>`
|
||||
|
|
||||
LL | takes_option(&res.as_ref());
|
||||
| +++++++++
|
||||
LL - takes_option(&res);
|
||||
LL + takes_option(res.as_ref());
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -21,8 +21,9 @@ LL | let Some(ref a): Option<&[u8]> = &some else { return };
|
||||
found reference `&Option<Vec<u8>>`
|
||||
help: try using `.as_deref()` to convert `&Option<Vec<u8>>` to `Option<&[u8]>`
|
||||
|
|
||||
LL | let Some(ref a): Option<&[u8]> = &some.as_deref() else { return };
|
||||
| +++++++++++
|
||||
LL - let Some(ref a): Option<&[u8]> = &some else { return };
|
||||
LL + let Some(ref a): Option<&[u8]> = some.as_deref() else { return };
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/let-else-ref-bindings.rs:24:34
|
||||
@ -51,8 +52,9 @@ LL | let Some(a): Option<&[u8]> = &some else { return };
|
||||
found reference `&Option<Vec<u8>>`
|
||||
help: try using `.as_deref()` to convert `&Option<Vec<u8>>` to `Option<&[u8]>`
|
||||
|
|
||||
LL | let Some(a): Option<&[u8]> = &some.as_deref() else { return };
|
||||
| +++++++++++
|
||||
LL - let Some(a): Option<&[u8]> = &some else { return };
|
||||
LL + let Some(a): Option<&[u8]> = some.as_deref() else { return };
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/let-else-ref-bindings.rs:44:46
|
||||
|
Loading…
x
Reference in New Issue
Block a user