diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 42038dbc3d82e..80d0faca670a7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3592,8 +3592,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Extract `::Target` assoc type and check that it is `T` && 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 + && let InferOk { value: deref_target, obligations } = infcx.at(&ObligationCause::dummy(), param_env).normalize(projection) + && obligations.iter().all(|obligation| infcx.predicate_must_hold_modulo_regions(obligation)) + && 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() diff --git a/tests/ui/mismatched_types/suggest-option-asderef-inference-var.rs b/tests/ui/mismatched_types/suggest-option-asderef-inference-var.rs new file mode 100644 index 0000000000000..5febbbe392b24 --- /dev/null +++ b/tests/ui/mismatched_types/suggest-option-asderef-inference-var.rs @@ -0,0 +1,9 @@ +fn deref_int(a: &i32) -> i32 { + *a +} + +fn main() { + // https://github.com/rust-lang/rust/issues/112293 + let _has_inference_vars: Option = Some(0).map(deref_int); + //~^ ERROR type mismatch in function arguments +} diff --git a/tests/ui/mismatched_types/suggest-option-asderef-inference-var.stderr b/tests/ui/mismatched_types/suggest-option-asderef-inference-var.stderr new file mode 100644 index 0000000000000..71c4729e31038 --- /dev/null +++ b/tests/ui/mismatched_types/suggest-option-asderef-inference-var.stderr @@ -0,0 +1,24 @@ +error[E0631]: type mismatch in function arguments + --> $DIR/suggest-option-asderef-inference-var.rs:7:56 + | +LL | fn deref_int(a: &i32) -> i32 { + | ---------------------------- found signature defined here +... +LL | let _has_inference_vars: Option = Some(0).map(deref_int); + | --- ^^^^^^^^^ expected due to this + | | + | required by a bound introduced by this call + | + = note: expected function signature `fn({integer}) -> _` + found function signature `for<'a> fn(&'a i32) -> _` +note: required by a bound in `Option::::map` + --> $SRC_DIR/core/src/option.rs:LL:COL +help: do not borrow the argument + | +LL - fn deref_int(a: &i32) -> i32 { +LL + fn deref_int(a: i32) -> i32 { + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.rs b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.rs index cc9ba5514fef1..ac0831ce65508 100644 --- a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.rs +++ b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.rs @@ -10,10 +10,6 @@ fn no_args() -> Option<()> { Some(()) } -fn generic_ref(_: &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 } diff --git a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr index 079909eb48d1d..ecfbd27b180e6 100644 --- a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr +++ b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr @@ -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::::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::::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::::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::::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) -> 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::::and_then` - --> $SRC_DIR/core/src/option.rs:LL:COL -help: do not borrow the argument - | -LL - fn generic_ref(_: &T) -> Option<()> { -LL + fn generic_ref(_: 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::::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`. diff --git a/tests/ui/mismatched_types/suggest-option-asderef.fixed b/tests/ui/mismatched_types/suggest-option-asderef.fixed index 08805999341ff..5c42ece3c5d09 100644 --- a/tests/ui/mismatched_types/suggest-option-asderef.fixed +++ b/tests/ui/mismatched_types/suggest-option-asderef.fixed @@ -16,6 +16,11 @@ fn generic(_: T) -> Option<()> { Some(()) } +fn generic_ref(_: 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 } diff --git a/tests/ui/mismatched_types/suggest-option-asderef.rs b/tests/ui/mismatched_types/suggest-option-asderef.rs index 3cfb2ffa828c6..a5278b8fb1618 100644 --- a/tests/ui/mismatched_types/suggest-option-asderef.rs +++ b/tests/ui/mismatched_types/suggest-option-asderef.rs @@ -16,6 +16,11 @@ fn generic(_: T) -> Option<()> { Some(()) } +fn generic_ref(_: &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 } diff --git a/tests/ui/mismatched_types/suggest-option-asderef.stderr b/tests/ui/mismatched_types/suggest-option-asderef.stderr index 46da19d2bf4f2..01341603dde3f 100644 --- a/tests/ui/mismatched_types/suggest-option-asderef.stderr +++ b/tests/ui/mismatched_types/suggest-option-asderef.stderr @@ -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> = 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> = 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) -> 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::::and_then` + --> $SRC_DIR/core/src/option.rs:LL:COL +help: do not borrow the argument + | +LL - fn generic_ref(_: &T) -> Option<()> { +LL + fn generic_ref(_: 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`.