diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index bcff4eeb71b3..32104a5c0cf7 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -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); @@ -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. + 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, @@ -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>, diff --git a/tests/crashes/132765.rs b/tests/crashes/132765.rs deleted file mode 100644 index 01e8fdaacff7..000000000000 --- a/tests/crashes/132765.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #132765 - -trait LendingIterator { - type Item<'q>; - fn for_each(&self, _f: Box)>) {} -} - -fn f(_: ()) {} - -fn main() { - LendingIterator::for_each(&(), f); -} diff --git a/tests/ui/coercion/hr_alias_normalization_leaking_vars.rs b/tests/ui/coercion/hr_alias_normalization_leaking_vars.rs new file mode 100644 index 000000000000..43678fd876fb --- /dev/null +++ b/tests/ui/coercion/hr_alias_normalization_leaking_vars.rs @@ -0,0 +1,36 @@ +// We have two function parameters with types: +// - `&?0` +// - `Box fn(>::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 fn(>::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` +// 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. + + +trait LendingIterator { + type Item<'q>; + fn for_each(&self, _f: Box)>) {} +} + +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 +} diff --git a/tests/ui/coercion/hr_alias_normalization_leaking_vars.stderr b/tests/ui/coercion/hr_alias_normalization_leaking_vars.stderr new file mode 100644 index 000000000000..143cc6b29735 --- /dev/null +++ b/tests/ui/coercion/hr_alias_normalization_leaking_vars.stderr @@ -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`, found fn item + | | + | arguments to this function are incorrect + | + = note: expected struct `Box 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)>) {} + | ^^^^^^^^ --------------------------- + +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`.