Properly compare types for Option::as_deref suggestion

This commit is contained in:
Nilstrieb 2023-06-05 08:26:53 +00:00
parent e4106065bf
commit 896ccb9606
6 changed files with 54 additions and 38 deletions

View file

@ -3593,7 +3593,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&& let Some(deref_target_did) = tcx.lang_items().deref_target()
&& let projection = tcx.mk_projection(deref_target_did, tcx.mk_substs(&[ty::GenericArg::from(found_ty)]))
&& let Ok(deref_target) = tcx.try_normalize_erasing_regions(param_env, projection)
&& deref_target == target_ty
&& infcx.can_eq(param_env, deref_target, target_ty)
{
let help = if let hir::Mutability::Mut = needs_mut
&& let Some(deref_mut_did) = tcx.lang_items().deref_mut_trait()

View file

@ -10,10 +10,6 @@ fn no_args() -> Option<()> {
Some(())
}
fn generic_ref<T>(_: &T) -> Option<()> {
Some(())
}
extern "C" fn takes_str_but_wrong_abi(_: &str) -> Option<()> {
Some(())
}
@ -33,8 +29,6 @@ fn main() {
//~^ ERROR expected a `FnOnce<(String,)>` closure, found `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}`
let _ = produces_string().and_then(no_args);
//~^ ERROR function is expected to take 1 argument, but it takes 0 arguments
let _ = produces_string().and_then(generic_ref);
//~^ ERROR type mismatch in function arguments
let _ = Some(TypeWithoutDeref).and_then(takes_str_but_too_many_refs);
//~^ ERROR type mismatch in function arguments
}

View file

@ -1,5 +1,5 @@
error[E0631]: type mismatch in function arguments
--> $DIR/suggest-option-asderef-unfixable.rs:28:40
--> $DIR/suggest-option-asderef-unfixable.rs:24:40
|
LL | fn takes_str_but_too_many_refs(_: &&str) -> Option<()> {
| ------------------------------------------------------ found signature defined here
@ -15,7 +15,7 @@ note: required by a bound in `Option::<T>::and_then`
--> $SRC_DIR/core/src/option.rs:LL:COL
error[E0277]: expected a `FnOnce<(String,)>` closure, found `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}`
--> $DIR/suggest-option-asderef-unfixable.rs:30:40
--> $DIR/suggest-option-asderef-unfixable.rs:26:40
|
LL | let _ = produces_string().and_then(takes_str_but_wrong_abi);
| -------- ^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(String,)>` closure, found `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}`
@ -27,7 +27,7 @@ note: required by a bound in `Option::<T>::and_then`
--> $SRC_DIR/core/src/option.rs:LL:COL
error[E0277]: expected a `FnOnce<(String,)>` closure, found `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}`
--> $DIR/suggest-option-asderef-unfixable.rs:32:40
--> $DIR/suggest-option-asderef-unfixable.rs:28:40
|
LL | let _ = produces_string().and_then(takes_str_but_unsafe);
| -------- ^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
@ -40,7 +40,7 @@ note: required by a bound in `Option::<T>::and_then`
--> $SRC_DIR/core/src/option.rs:LL:COL
error[E0593]: function is expected to take 1 argument, but it takes 0 arguments
--> $DIR/suggest-option-asderef-unfixable.rs:34:40
--> $DIR/suggest-option-asderef-unfixable.rs:30:40
|
LL | fn no_args() -> Option<()> {
| -------------------------- takes 0 arguments
@ -54,28 +54,7 @@ note: required by a bound in `Option::<T>::and_then`
--> $SRC_DIR/core/src/option.rs:LL:COL
error[E0631]: type mismatch in function arguments
--> $DIR/suggest-option-asderef-unfixable.rs:36:40
|
LL | fn generic_ref<T>(_: &T) -> Option<()> {
| -------------------------------------- found signature defined here
...
LL | let _ = produces_string().and_then(generic_ref);
| -------- ^^^^^^^^^^^ expected due to this
| |
| required by a bound introduced by this call
|
= note: expected function signature `fn(String) -> _`
found function signature `for<'a> fn(&'a _) -> _`
note: required by a bound in `Option::<T>::and_then`
--> $SRC_DIR/core/src/option.rs:LL:COL
help: do not borrow the argument
|
LL - fn generic_ref<T>(_: &T) -> Option<()> {
LL + fn generic_ref<T>(_: T) -> Option<()> {
|
error[E0631]: type mismatch in function arguments
--> $DIR/suggest-option-asderef-unfixable.rs:38:45
--> $DIR/suggest-option-asderef-unfixable.rs:32:45
|
LL | fn takes_str_but_too_many_refs(_: &&str) -> Option<()> {
| ------------------------------------------------------ found signature defined here
@ -90,7 +69,7 @@ LL | let _ = Some(TypeWithoutDeref).and_then(takes_str_but_too_many_refs);
note: required by a bound in `Option::<T>::and_then`
--> $SRC_DIR/core/src/option.rs:LL:COL
error: aborting due to 6 previous errors
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0277, E0593, E0631.
For more information about an error, try `rustc --explain E0277`.

View file

@ -16,6 +16,11 @@ fn generic<T>(_: T) -> Option<()> {
Some(())
}
fn generic_ref<T>(_: T) -> Option<()> {
//~^ HELP do not borrow the argument
Some(())
}
fn main() {
let _: Option<()> = produces_string().as_deref().and_then(takes_str);
//~^ ERROR type mismatch in function arguments
@ -27,4 +32,8 @@ fn main() {
//~^ ERROR type mismatch in function arguments
//~| HELP call `Option::as_deref_mut()` first
let _ = produces_string().and_then(generic);
let _ = produces_string().as_deref().and_then(generic_ref);
//~^ ERROR type mismatch in function arguments
//~| HELP call `Option::as_deref()` first
}

View file

@ -16,6 +16,11 @@ fn generic<T>(_: T) -> Option<()> {
Some(())
}
fn generic_ref<T>(_: &T) -> Option<()> {
//~^ HELP do not borrow the argument
Some(())
}
fn main() {
let _: Option<()> = produces_string().and_then(takes_str);
//~^ ERROR type mismatch in function arguments
@ -27,4 +32,8 @@ fn main() {
//~^ ERROR type mismatch in function arguments
//~| HELP call `Option::as_deref_mut()` first
let _ = produces_string().and_then(generic);
let _ = produces_string().and_then(generic_ref);
//~^ ERROR type mismatch in function arguments
//~| HELP call `Option::as_deref()` first
}

View file

@ -1,5 +1,5 @@
error[E0631]: type mismatch in function arguments
--> $DIR/suggest-option-asderef.rs:20:52
--> $DIR/suggest-option-asderef.rs:25:52
|
LL | fn takes_str(_: &str) -> Option<()> {
| ----------------------------------- found signature defined here
@ -19,7 +19,7 @@ LL | let _: Option<()> = produces_string().as_deref().and_then(takes_str);
| +++++++++++
error[E0631]: type mismatch in function arguments
--> $DIR/suggest-option-asderef.rs:23:55
--> $DIR/suggest-option-asderef.rs:28:55
|
LL | fn takes_str(_: &str) -> Option<()> {
| ----------------------------------- found signature defined here
@ -39,7 +39,7 @@ LL | let _: Option<Option<()>> = produces_string().as_deref().map(takes_str)
| +++++++++++
error[E0631]: type mismatch in function arguments
--> $DIR/suggest-option-asderef.rs:26:55
--> $DIR/suggest-option-asderef.rs:31:55
|
LL | fn takes_str_mut(_: &mut str) -> Option<()> {
| ------------------------------------------- found signature defined here
@ -58,6 +58,31 @@ help: call `Option::as_deref_mut()` first
LL | let _: Option<Option<()>> = produces_string().as_deref_mut().map(takes_str_mut);
| +++++++++++++++
error: aborting due to 3 previous errors
error[E0631]: type mismatch in function arguments
--> $DIR/suggest-option-asderef.rs:36:40
|
LL | fn generic_ref<T>(_: &T) -> Option<()> {
| -------------------------------------- found signature defined here
...
LL | let _ = produces_string().and_then(generic_ref);
| -------- ^^^^^^^^^^^ expected due to this
| |
| required by a bound introduced by this call
|
= note: expected function signature `fn(String) -> _`
found function signature `for<'a> fn(&'a _) -> _`
note: required by a bound in `Option::<T>::and_then`
--> $SRC_DIR/core/src/option.rs:LL:COL
help: do not borrow the argument
|
LL - fn generic_ref<T>(_: &T) -> Option<()> {
LL + fn generic_ref<T>(_: T) -> Option<()> {
|
help: call `Option::as_deref()` first
|
LL | let _ = produces_string().as_deref().and_then(generic_ref);
| +++++++++++
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0631`.