mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Add suggestion to use Option::map_or over erroneous Option::unwrap_or
This commit is contained in:
parent
abeb7203e4
commit
5e1cabe982
@ -948,6 +948,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&mut err,
|
||||
);
|
||||
|
||||
self.suggest_deref_unwrap_or(
|
||||
&mut err,
|
||||
error_span,
|
||||
callee_ty,
|
||||
call_ident,
|
||||
expected_ty,
|
||||
provided_ty,
|
||||
provided_args[*provided_idx],
|
||||
is_method,
|
||||
);
|
||||
|
||||
// Call out where the function is defined
|
||||
self.label_fn_like(
|
||||
&mut err,
|
||||
|
@ -1429,6 +1429,71 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
true
|
||||
}
|
||||
|
||||
// Suggest to change `Option<&Vec<T>>::unwrap_or(&[])` to `Option::map_or(&[], |v| v)`.
|
||||
#[instrument(level = "trace", skip(self, err, provided_expr))]
|
||||
pub(crate) fn suggest_deref_unwrap_or(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
error_span: Span,
|
||||
callee_ty: Option<Ty<'tcx>>,
|
||||
call_ident: Option<Ident>,
|
||||
expected_ty: Ty<'tcx>,
|
||||
provided_ty: Ty<'tcx>,
|
||||
provided_expr: &Expr<'tcx>,
|
||||
is_method: bool,
|
||||
) {
|
||||
if !is_method {
|
||||
return;
|
||||
}
|
||||
let Some(callee_ty) = callee_ty else {
|
||||
return;
|
||||
};
|
||||
let ty::Adt(callee_adt, _) = callee_ty.peel_refs().kind() else {
|
||||
return;
|
||||
};
|
||||
if !self.tcx.is_diagnostic_item(sym::Option, callee_adt.did()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if call_ident.map_or(true, |ident| ident.name != sym::unwrap_or) {
|
||||
return;
|
||||
}
|
||||
|
||||
let ty::Ref(_, peeled, _mutability) = provided_ty.kind() else {
|
||||
return;
|
||||
};
|
||||
|
||||
// NOTE: Can we reuse `suggest_deref_or_ref`?
|
||||
|
||||
// Create an dummy type `&[_]` so that both &[] and `&Vec<T>` can coerce to it.
|
||||
let dummy_ty = if let ty::Array(elem_ty, size) = peeled.kind()
|
||||
&& let ty::Infer(_) = elem_ty.kind()
|
||||
&& size.try_eval_target_usize(self.tcx, self.param_env) == Some(0)
|
||||
{
|
||||
let slice = Ty::new_slice(self.tcx, *elem_ty);
|
||||
Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, slice)
|
||||
} else {
|
||||
provided_ty
|
||||
};
|
||||
|
||||
if !self.can_coerce(expected_ty, dummy_ty) {
|
||||
return;
|
||||
}
|
||||
let (provided_snip, applicability) =
|
||||
match self.tcx.sess.source_map().span_to_snippet(provided_expr.span) {
|
||||
Ok(snip) => (snip, Applicability::MachineApplicable),
|
||||
Err(_) => ("/* _ */".to_owned(), Applicability::MaybeIncorrect),
|
||||
};
|
||||
let sugg = &format!("map_or({provided_snip}, |v| v)");
|
||||
err.span_suggestion_verbose(
|
||||
error_span,
|
||||
"use `Option::map_or` to deref inner value of `Option`",
|
||||
sugg,
|
||||
applicability,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
/// Suggest wrapping the block in square brackets instead of curly braces
|
||||
/// in case the block was mistaken array syntax, e.g. `{ 1 }` -> `[ 1 ]`.
|
||||
pub(crate) fn suggest_block_to_brackets(
|
||||
|
@ -13,7 +13,7 @@ help: try using `.map(|v| &**v)` to convert `Option<&Vec<i32>>` to `Option<&[i32
|
||||
LL | arg.map(|v| &**v)
|
||||
| ++++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/transforming-option-ref-issue-127545.rs:9:19
|
||||
|
|
||||
LL | arg.unwrap_or(&[])
|
||||
@ -32,6 +32,10 @@ LL | arg.unwrap_or(&[])
|
||||
| this argument influences the return type of `unwrap_or`
|
||||
note: method defined here
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
help: use `Option::map_or` to deref inner value of `Option`
|
||||
|
|
||||
LL | arg.map_or(&[], |v| v)
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/transforming-option-ref-issue-127545.rs:13:19
|
||||
@ -52,6 +56,10 @@ LL | arg.unwrap_or(v)
|
||||
| this argument influences the return type of `unwrap_or`
|
||||
note: method defined here
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
help: use `Option::map_or` to deref inner value of `Option`
|
||||
|
|
||||
LL | arg.map_or(v, |v| v)
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user