Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,9 +856,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
debug_assert!(self.shallow_resolve(a) == a);
debug_assert!(self.shallow_resolve(b) == b);

let InferOk { value: b, mut obligations } =
self.at(&self.cause, self.param_env).normalize(b);

match b.kind() {
ty::FnPtr(_, b_hdr) => {
let mut a_sig = a.fn_sig(self.tcx);
Expand Down Expand Up @@ -890,9 +887,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
}
}

let InferOk { value: a_sig, obligations: o1 } =
// FIXME: we shouldn't be normalizing here as coercion is inside of
// a probe. This can probably cause ICEs.
Comment on lines +864 to +865
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand that FIXME. Normalizing inside of a probe is totally fine as long as we don't leak the infer vars. This happens for errors of commit_if_ok but I don't think not normalizing is the solution here.

More specifically, we have to normalize here as the fn-sig is the unnnormalized one from a function definition

let InferOk { value: a_sig, mut obligations } =
self.at(&self.cause, self.param_env).normalize(a_sig);
obligations.extend(o1);

let InferOk { value, obligations: o2 } = self.coerce_from_safe_fn(
a_sig,
Expand All @@ -907,8 +905,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
}
}

/// Attempts to coerce from the type of a non-capturing closure
/// into a function pointer.
/// Attempts to coerce from a closure to a function pointer. Fails
/// if the closure has any upvars.
fn coerce_closure_to_fn(
&self,
a: Ty<'tcx>,
Expand Down
12 changes: 0 additions & 12 deletions tests/crashes/132765.rs

This file was deleted.

36 changes: 36 additions & 0 deletions tests/ui/coercion/hr_alias_normalization_leaking_vars.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// We have two function parameters with types:
// - `&?0`
// - `Box<for<'a> fn(<?0 as Trait<'a>>::Item)>`
//
// As the alias in the second parameter has a `?0` it is an ambig
// alias, and as it references bound vars it can't be normalized to
// an infer var.
//
// When checking function arguments we try to coerce both:
// - `&()` to `&?0`
// - `FnDef(f)` to `Box<for<'a> fn(<?0 as Trait<'a>>::Item)>`
//
// The first coercion infers `?0=()`. Previously when handling
// the second coercion we wound *re-normalize* the alias, which
// now that `?0` has been inferred allowed us to determine this
// alias is not wellformed and normalize it to some infer var `?1`.
//
// We would then see that `FnDef(f)` can't be coerced to `Box<fn(?1)>`
// and return a `TypeError` referencing this new variable `?1`. This
// then caused ICEs as diagnostics would encounter inferences variables
// from the result of normalization inside of the probe used be coercion.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comment that regression test for #132765?



trait LendingIterator {
type Item<'q>;
fn for_each(&self, _f: Box<fn(Self::Item<'_>)>) {}
}

fn f(_: ()) {}

fn main() {
LendingIterator::for_each(&(), f);
//~^ ERROR: the trait bound `(): LendingIterator` is not satisfied
//~| ERROR: the trait bound `(): LendingIterator` is not satisfied
//~| ERROR: mismatched types
}
46 changes: 46 additions & 0 deletions tests/ui/coercion/hr_alias_normalization_leaking_vars.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
error[E0277]: the trait bound `(): LendingIterator` is not satisfied
--> $DIR/hr_alias_normalization_leaking_vars.rs:32:31
|
LL | LendingIterator::for_each(&(), f);
| ------------------------- ^^^ the trait `LendingIterator` is not implemented for `()`
| |
| required by a bound introduced by this call
|
help: this trait has no implementations, consider adding one
--> $DIR/hr_alias_normalization_leaking_vars.rs:24:1
|
LL | trait LendingIterator {
| ^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
--> $DIR/hr_alias_normalization_leaking_vars.rs:32:36
|
LL | LendingIterator::for_each(&(), f);
| ------------------------- ^ expected `Box<fn(...)>`, found fn item
| |
| arguments to this function are incorrect
|
= note: expected struct `Box<for<'a> fn(<() as LendingIterator>::Item<'a>)>`
found fn item `fn(()) {f}`
note: method defined here
--> $DIR/hr_alias_normalization_leaking_vars.rs:26:8
|
LL | fn for_each(&self, _f: Box<fn(Self::Item<'_>)>) {}
| ^^^^^^^^ ---------------------------

error[E0277]: the trait bound `(): LendingIterator` is not satisfied
--> $DIR/hr_alias_normalization_leaking_vars.rs:32:36
|
LL | LendingIterator::for_each(&(), f);
| ^ the trait `LendingIterator` is not implemented for `()`
|
help: this trait has no implementations, consider adding one
--> $DIR/hr_alias_normalization_leaking_vars.rs:24:1
|
LL | trait LendingIterator {
| ^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 3 previous errors

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