Open
Description
// For indirection
pub trait With {
type F;
}
impl With for i32 {
type F = fn(&str);
}
// A function item to coerce
fn f(_: &str) {}
fn main() {
// Tuple constructor fails
let _: V<i32> = V(f);
pub struct V<T: With>(<T as With>::F);
// Trait projection in variant fails
pub enum E3<T: With> { Var(<T as With>::F), }
let _: E3<i32> = E3::Var(f);
}
I expected to see this happen: Successful compilation due to the function item coercing to a function pointer.
Instead, this happened: E0271 due to coercion not applying through the trait projection:
error[[E0271]](https://doc.rust-lang.org/stable/error-index.html#E0271): type mismatch resolving `<i32 as With>::F == for<'r> fn(&'r str) {f}`
[--> src/main.rs:16:21
](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=eff917c8034cf4f25f51a32ae093abab#) |
16 | let _: V<i32> = V(f);
| ^^^^ type mismatch resolving `<i32 as With>::F == for<'r> fn(&'r str) {f}`
|
note: expected this to be `for<'r> fn(&'r str)`
[--> src/main.rs:7:14
](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=eff917c8034cf4f25f51a32ae093abab#) |
7 | type F = fn(&str);
| ^^^^^^^^
= note: expected fn pointer `for<'r> fn(&'r str)`
found fn item `for<'r> fn(&'r str) {f}`
error[[E0271]](https://doc.rust-lang.org/stable/error-index.html#E0271): type mismatch resolving `<i32 as With>::F == for<'r> fn(&'r str) {f}`
[--> src/main.rs:21:22
](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=eff917c8034cf4f25f51a32ae093abab#) |
21 | let _: E3<i32> = E3::Var(f);
| ^^^^^^^^^^ type mismatch resolving `<i32 as With>::F == for<'r> fn(&'r str) {f}`
|
note: expected this to be `for<'r> fn(&'r str)`
[--> src/main.rs:7:14
](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=eff917c8034cf4f25f51a32ae093abab#) |
7 | type F = fn(&str);
| ^^^^^^^^
= note: expected fn pointer `for<'r> fn(&'r str)`
found fn item `for<'r> fn(&'r str) {f}`
Further notes
Edit This doesn't really seem to be about constructors, but functions more generally; see below.
Pre-edit notes
As can be seen in the playground link, the coercion applies for
- Ascripted bindings
- Function arguments (normal functions vs generated constructors)
- Actual tuples
- Bracketed struct and bracket variant fields
The last bullet also did not work in Rust 1.19 and prior, but this was fixed by #42807. So technically this could be considered a dupe of #31260 as "coercion sites are not consistent between struct tuples and structs" is still true.
Coercion also applies if the indirection through the trait is not present.
Meta
Discovered on the playground
- Stable version: 1.60.0
- Beta version: 1.61.0-beta.1 (2022-04-05 0f23125)
- Nightly version: 1.62.0-nightly (2022-04-08 f4a7ce9)
@rustbot modify labels: T-compiler