mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Rollup merge of #114052 - clubby789:suggest-option-asref, r=WaffleLapkin
Suggest `{Option,Result}::as_ref()` instead of `cloned()` in some cases Fixes #114050 When we have an expr available that produces the type expectation, we can suggest appending `.as_ref()` to the span, instead of cloning the expr producing the mismatch
This commit is contained in:
commit
b7a1ff2aaa
@ -53,7 +53,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|| self.suggest_no_capture_closure(err, expected, expr_ty)
|
||||
|| self.suggest_boxing_when_appropriate(err, expr.span, expr.hir_id, expected, expr_ty)
|
||||
|| self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
|
||||
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
|
||||
|| self.suggest_copied_cloned_or_as_ref(err, expr, expr_ty, expected, expected_ty_expr)
|
||||
|| 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)
|
||||
|
@ -1085,12 +1085,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
false
|
||||
}
|
||||
|
||||
pub(crate) fn suggest_copied_or_cloned(
|
||||
pub(crate) fn suggest_copied_cloned_or_as_ref(
|
||||
&self,
|
||||
diag: &mut Diagnostic,
|
||||
expr: &hir::Expr<'_>,
|
||||
expr_ty: Ty<'tcx>,
|
||||
expected_ty: Ty<'tcx>,
|
||||
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
) -> bool {
|
||||
let ty::Adt(adt_def, args) = expr_ty.kind() else {
|
||||
return false;
|
||||
@ -1102,7 +1103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut suggest_copied_or_cloned = || {
|
||||
let mut suggest_copied_cloned_or_as_ref = || {
|
||||
let expr_inner_ty = args.type_at(0);
|
||||
let expected_inner_ty = expected_args.type_at(0);
|
||||
if let &ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
|
||||
@ -1119,6 +1120,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
return true;
|
||||
} else if let Some(expected_ty_expr) = expected_ty_expr {
|
||||
diag.span_suggestion_verbose(
|
||||
expected_ty_expr.span.shrink_to_hi(),
|
||||
format!(
|
||||
"use `{def_path}::as_ref()` to convert `{expected_ty}` to `{expr_ty}`"
|
||||
),
|
||||
".as_ref()",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
return true;
|
||||
} else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
|
||||
&& rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
|
||||
self,
|
||||
@ -1146,11 +1157,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// Check that the error types are equal
|
||||
&& self.can_eq(self.param_env, args.type_at(1), expected_args.type_at(1))
|
||||
{
|
||||
return suggest_copied_or_cloned();
|
||||
return suggest_copied_cloned_or_as_ref();
|
||||
} else if let Some(option_did) = self.tcx.get_diagnostic_item(sym::Option)
|
||||
&& adt_def.did() == option_did
|
||||
{
|
||||
return suggest_copied_or_cloned();
|
||||
return suggest_copied_cloned_or_as_ref();
|
||||
}
|
||||
|
||||
false
|
||||
|
@ -0,0 +1,13 @@
|
||||
// run-rustfix
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub fn foo<I: Iterator>(mut iter: I, value: &I::Item)
|
||||
where
|
||||
I::Item: Eq + Debug,
|
||||
{
|
||||
debug_assert_eq!(iter.next().as_ref(), Some(value));
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,6 +1,8 @@
|
||||
// run-rustfix
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
fn foo<I: Iterator>(mut iter: I, value: &I::Item)
|
||||
pub fn foo<I: Iterator>(mut iter: I, value: &I::Item)
|
||||
where
|
||||
I::Item: Eq + Debug,
|
||||
{
|
||||
|
@ -1,11 +1,15 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-suggest-cyclic-constraint.rs:7:35
|
||||
--> $DIR/dont-suggest-cyclic-constraint.rs:9:35
|
||||
|
|
||||
LL | debug_assert_eq!(iter.next(), Some(value));
|
||||
| ^^^^^^^^^^^ expected `Option<<I as Iterator>::Item>`, found `Option<&<I as Iterator>::Item>`
|
||||
|
|
||||
= note: expected enum `Option<<I as Iterator>::Item>`
|
||||
found enum `Option<&<I as Iterator>::Item>`
|
||||
help: use `Option::as_ref()` to convert `Option<<I as Iterator>::Item>` to `Option<&<I as Iterator>::Item>`
|
||||
|
|
||||
LL | debug_assert_eq!(iter.next().as_ref(), Some(value));
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -20,4 +20,12 @@ fn main() {
|
||||
expect::<Result<String, ()>>(x.cloned());
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP use `Result::cloned` to clone the value inside the `Result`
|
||||
|
||||
let s = String::new();
|
||||
let x = Some(s.clone());
|
||||
let y = Some(&s);
|
||||
println!("{}", x.as_ref() == y);
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP use `Option::as_ref()` to convert `Option<String>` to `Option<&String>`
|
||||
|
||||
}
|
||||
|
@ -20,4 +20,12 @@ fn main() {
|
||||
expect::<Result<String, ()>>(x);
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP use `Result::cloned` to clone the value inside the `Result`
|
||||
|
||||
let s = String::new();
|
||||
let x = Some(s.clone());
|
||||
let y = Some(&s);
|
||||
println!("{}", x == y);
|
||||
//~^ ERROR mismatched types
|
||||
//~| HELP use `Option::as_ref()` to convert `Option<String>` to `Option<&String>`
|
||||
|
||||
}
|
||||
|
@ -78,6 +78,19 @@ help: use `Result::cloned` to clone the value inside the `Result`
|
||||
LL | expect::<Result<String, ()>>(x.cloned());
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/copied-and-cloned.rs:27:25
|
||||
|
|
||||
LL | println!("{}", x == y);
|
||||
| ^ expected `Option<String>`, found `Option<&String>`
|
||||
|
|
||||
= note: expected enum `Option<String>`
|
||||
found enum `Option<&String>`
|
||||
help: use `Option::as_ref()` to convert `Option<String>` to `Option<&String>`
|
||||
|
|
||||
LL | println!("{}", x.as_ref() == y);
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
Loading…
Reference in New Issue
Block a user