Normalize in infcx instead of globally for Option::as_deref suggestion

The projection may contain inference variables. These inference
variables are local to the local inference context. Using
`tcx.normalize_erasing_regions` doesn't work here because this method is
global and does not have access to the inference context. It's therefore
unable to deal with the inference variables. We normalize in the local
inference context instead, which knowns about the inference variables.
This commit is contained in:
Nilstrieb 2023-06-05 08:34:06 +00:00
parent 896ccb9606
commit c12575d317
3 changed files with 35 additions and 1 deletions

View file

@ -3592,7 +3592,8 @@ fn suggest_option_method_if_applicable(
// Extract `<U as Deref>::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)
&& 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

View file

@ -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<i32> = Some(0).map(deref_int);
//~^ ERROR type mismatch in function arguments
}

View file

@ -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<i32> = 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::<T>::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`.