Skip to content

Commit 896ccb9

Browse files
committed
Properly compare types for Option::as_deref suggestion
1 parent e410606 commit 896ccb9

File tree

6 files changed

+54
-38
lines changed

6 files changed

+54
-38
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3593,7 +3593,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
35933593
&& let Some(deref_target_did) = tcx.lang_items().deref_target()
35943594
&& let projection = tcx.mk_projection(deref_target_did, tcx.mk_substs(&[ty::GenericArg::from(found_ty)]))
35953595
&& let Ok(deref_target) = tcx.try_normalize_erasing_regions(param_env, projection)
3596-
&& deref_target == target_ty
3596+
&& infcx.can_eq(param_env, deref_target, target_ty)
35973597
{
35983598
let help = if let hir::Mutability::Mut = needs_mut
35993599
&& let Some(deref_mut_did) = tcx.lang_items().deref_mut_trait()

tests/ui/mismatched_types/suggest-option-asderef-unfixable.rs

-6
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ fn no_args() -> Option<()> {
1010
Some(())
1111
}
1212

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

tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr

+6-27
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0631]: type mismatch in function arguments
2-
--> $DIR/suggest-option-asderef-unfixable.rs:28:40
2+
--> $DIR/suggest-option-asderef-unfixable.rs:24:40
33
|
44
LL | fn takes_str_but_too_many_refs(_: &&str) -> Option<()> {
55
| ------------------------------------------------------ found signature defined here
@@ -15,7 +15,7 @@ note: required by a bound in `Option::<T>::and_then`
1515
--> $SRC_DIR/core/src/option.rs:LL:COL
1616

1717
error[E0277]: expected a `FnOnce<(String,)>` closure, found `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}`
18-
--> $DIR/suggest-option-asderef-unfixable.rs:30:40
18+
--> $DIR/suggest-option-asderef-unfixable.rs:26:40
1919
|
2020
LL | let _ = produces_string().and_then(takes_str_but_wrong_abi);
2121
| -------- ^^^^^^^^^^^^^^^^^^^^^^^ 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`
2727
--> $SRC_DIR/core/src/option.rs:LL:COL
2828

2929
error[E0277]: expected a `FnOnce<(String,)>` closure, found `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}`
30-
--> $DIR/suggest-option-asderef-unfixable.rs:32:40
30+
--> $DIR/suggest-option-asderef-unfixable.rs:28:40
3131
|
3232
LL | let _ = produces_string().and_then(takes_str_but_unsafe);
3333
| -------- ^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
@@ -40,7 +40,7 @@ note: required by a bound in `Option::<T>::and_then`
4040
--> $SRC_DIR/core/src/option.rs:LL:COL
4141

4242
error[E0593]: function is expected to take 1 argument, but it takes 0 arguments
43-
--> $DIR/suggest-option-asderef-unfixable.rs:34:40
43+
--> $DIR/suggest-option-asderef-unfixable.rs:30:40
4444
|
4545
LL | fn no_args() -> Option<()> {
4646
| -------------------------- takes 0 arguments
@@ -54,28 +54,7 @@ note: required by a bound in `Option::<T>::and_then`
5454
--> $SRC_DIR/core/src/option.rs:LL:COL
5555

5656
error[E0631]: type mismatch in function arguments
57-
--> $DIR/suggest-option-asderef-unfixable.rs:36:40
58-
|
59-
LL | fn generic_ref<T>(_: &T) -> Option<()> {
60-
| -------------------------------------- found signature defined here
61-
...
62-
LL | let _ = produces_string().and_then(generic_ref);
63-
| -------- ^^^^^^^^^^^ expected due to this
64-
| |
65-
| required by a bound introduced by this call
66-
|
67-
= note: expected function signature `fn(String) -> _`
68-
found function signature `for<'a> fn(&'a _) -> _`
69-
note: required by a bound in `Option::<T>::and_then`
70-
--> $SRC_DIR/core/src/option.rs:LL:COL
71-
help: do not borrow the argument
72-
|
73-
LL - fn generic_ref<T>(_: &T) -> Option<()> {
74-
LL + fn generic_ref<T>(_: T) -> Option<()> {
75-
|
76-
77-
error[E0631]: type mismatch in function arguments
78-
--> $DIR/suggest-option-asderef-unfixable.rs:38:45
57+
--> $DIR/suggest-option-asderef-unfixable.rs:32:45
7958
|
8059
LL | fn takes_str_but_too_many_refs(_: &&str) -> Option<()> {
8160
| ------------------------------------------------------ found signature defined here
@@ -90,7 +69,7 @@ LL | let _ = Some(TypeWithoutDeref).and_then(takes_str_but_too_many_refs);
9069
note: required by a bound in `Option::<T>::and_then`
9170
--> $SRC_DIR/core/src/option.rs:LL:COL
9271

93-
error: aborting due to 6 previous errors
72+
error: aborting due to 5 previous errors
9473

9574
Some errors have detailed explanations: E0277, E0593, E0631.
9675
For more information about an error, try `rustc --explain E0277`.

tests/ui/mismatched_types/suggest-option-asderef.fixed

+9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ fn generic<T>(_: T) -> Option<()> {
1616
Some(())
1717
}
1818

19+
fn generic_ref<T>(_: T) -> Option<()> {
20+
//~^ HELP do not borrow the argument
21+
Some(())
22+
}
23+
1924
fn main() {
2025
let _: Option<()> = produces_string().as_deref().and_then(takes_str);
2126
//~^ ERROR type mismatch in function arguments
@@ -27,4 +32,8 @@ fn main() {
2732
//~^ ERROR type mismatch in function arguments
2833
//~| HELP call `Option::as_deref_mut()` first
2934
let _ = produces_string().and_then(generic);
35+
36+
let _ = produces_string().as_deref().and_then(generic_ref);
37+
//~^ ERROR type mismatch in function arguments
38+
//~| HELP call `Option::as_deref()` first
3039
}

tests/ui/mismatched_types/suggest-option-asderef.rs

+9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ fn generic<T>(_: T) -> Option<()> {
1616
Some(())
1717
}
1818

19+
fn generic_ref<T>(_: &T) -> Option<()> {
20+
//~^ HELP do not borrow the argument
21+
Some(())
22+
}
23+
1924
fn main() {
2025
let _: Option<()> = produces_string().and_then(takes_str);
2126
//~^ ERROR type mismatch in function arguments
@@ -27,4 +32,8 @@ fn main() {
2732
//~^ ERROR type mismatch in function arguments
2833
//~| HELP call `Option::as_deref_mut()` first
2934
let _ = produces_string().and_then(generic);
35+
36+
let _ = produces_string().and_then(generic_ref);
37+
//~^ ERROR type mismatch in function arguments
38+
//~| HELP call `Option::as_deref()` first
3039
}

tests/ui/mismatched_types/suggest-option-asderef.stderr

+29-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0631]: type mismatch in function arguments
2-
--> $DIR/suggest-option-asderef.rs:20:52
2+
--> $DIR/suggest-option-asderef.rs:25:52
33
|
44
LL | fn takes_str(_: &str) -> Option<()> {
55
| ----------------------------------- found signature defined here
@@ -19,7 +19,7 @@ LL | let _: Option<()> = produces_string().as_deref().and_then(takes_str);
1919
| +++++++++++
2020

2121
error[E0631]: type mismatch in function arguments
22-
--> $DIR/suggest-option-asderef.rs:23:55
22+
--> $DIR/suggest-option-asderef.rs:28:55
2323
|
2424
LL | fn takes_str(_: &str) -> Option<()> {
2525
| ----------------------------------- found signature defined here
@@ -39,7 +39,7 @@ LL | let _: Option<Option<()>> = produces_string().as_deref().map(takes_str)
3939
| +++++++++++
4040

4141
error[E0631]: type mismatch in function arguments
42-
--> $DIR/suggest-option-asderef.rs:26:55
42+
--> $DIR/suggest-option-asderef.rs:31:55
4343
|
4444
LL | fn takes_str_mut(_: &mut str) -> Option<()> {
4545
| ------------------------------------------- found signature defined here
@@ -58,6 +58,31 @@ help: call `Option::as_deref_mut()` first
5858
LL | let _: Option<Option<()>> = produces_string().as_deref_mut().map(takes_str_mut);
5959
| +++++++++++++++
6060

61-
error: aborting due to 3 previous errors
61+
error[E0631]: type mismatch in function arguments
62+
--> $DIR/suggest-option-asderef.rs:36:40
63+
|
64+
LL | fn generic_ref<T>(_: &T) -> Option<()> {
65+
| -------------------------------------- found signature defined here
66+
...
67+
LL | let _ = produces_string().and_then(generic_ref);
68+
| -------- ^^^^^^^^^^^ expected due to this
69+
| |
70+
| required by a bound introduced by this call
71+
|
72+
= note: expected function signature `fn(String) -> _`
73+
found function signature `for<'a> fn(&'a _) -> _`
74+
note: required by a bound in `Option::<T>::and_then`
75+
--> $SRC_DIR/core/src/option.rs:LL:COL
76+
help: do not borrow the argument
77+
|
78+
LL - fn generic_ref<T>(_: &T) -> Option<()> {
79+
LL + fn generic_ref<T>(_: T) -> Option<()> {
80+
|
81+
help: call `Option::as_deref()` first
82+
|
83+
LL | let _ = produces_string().as_deref().and_then(generic_ref);
84+
| +++++++++++
85+
86+
error: aborting due to 4 previous errors
6287

6388
For more information about this error, try `rustc --explain E0631`.

0 commit comments

Comments
 (0)