Skip to content

Commit c12575d

Browse files
committed
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.
1 parent 896ccb9 commit c12575d

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

Diff for: compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3592,7 +3592,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
35923592
// Extract `<U as Deref>::Target` assoc type and check that it is `T`
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)]))
3595-
&& let Ok(deref_target) = tcx.try_normalize_erasing_regions(param_env, projection)
3595+
&& let InferOk { value: deref_target, obligations } = infcx.at(&ObligationCause::dummy(), param_env).normalize(projection)
3596+
&& obligations.iter().all(|obligation| infcx.predicate_must_hold_modulo_regions(obligation))
35963597
&& infcx.can_eq(param_env, deref_target, target_ty)
35973598
{
35983599
let help = if let hir::Mutability::Mut = needs_mut
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fn deref_int(a: &i32) -> i32 {
2+
*a
3+
}
4+
5+
fn main() {
6+
// https://github.com/rust-lang/rust/issues/112293
7+
let _has_inference_vars: Option<i32> = Some(0).map(deref_int);
8+
//~^ ERROR type mismatch in function arguments
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error[E0631]: type mismatch in function arguments
2+
--> $DIR/suggest-option-asderef-inference-var.rs:7:56
3+
|
4+
LL | fn deref_int(a: &i32) -> i32 {
5+
| ---------------------------- found signature defined here
6+
...
7+
LL | let _has_inference_vars: Option<i32> = Some(0).map(deref_int);
8+
| --- ^^^^^^^^^ expected due to this
9+
| |
10+
| required by a bound introduced by this call
11+
|
12+
= note: expected function signature `fn({integer}) -> _`
13+
found function signature `for<'a> fn(&'a i32) -> _`
14+
note: required by a bound in `Option::<T>::map`
15+
--> $SRC_DIR/core/src/option.rs:LL:COL
16+
help: do not borrow the argument
17+
|
18+
LL - fn deref_int(a: &i32) -> i32 {
19+
LL + fn deref_int(a: i32) -> i32 {
20+
|
21+
22+
error: aborting due to previous error
23+
24+
For more information about this error, try `rustc --explain E0631`.

0 commit comments

Comments
 (0)