Closed
Description
I tried this code:
#![feature(generic_associated_types)]
use std::marker::PhantomData;
pub trait Scalar: 'static {
type RefType<'a>: ScalarRef<'a>;
}
pub trait ScalarRef<'a>: 'a {}
impl Scalar for i32 {
type RefType<'a> = i32;
}
impl Scalar for String {
type RefType<'a> = &'a str;
}
impl Scalar for bool {
type RefType<'a> = i32;
}
impl<'a> ScalarRef<'a> for bool {}
impl<'a> ScalarRef<'a> for i32 {}
impl<'a> ScalarRef<'a> for &'a str {}
fn str_contains(a: &str, b: &str) -> bool {
a.contains(b)
}
pub struct BinaryExpression<A: Scalar, B: Scalar, O: Scalar, F>
where
F: Fn(A::RefType<'_>, B::RefType<'_>) -> O,
{
f: F,
_phantom: PhantomData<(A, B, O)>,
}
impl<A: Scalar, B: Scalar, O: Scalar, F> BinaryExpression<A, B, O, F>
where
F: Fn(A::RefType<'_>, B::RefType<'_>) -> O,
{
pub fn new(f: F) -> Self {
Self {
f,
_phantom: PhantomData,
}
}
}
fn fail_case() {
// error[E0631]: type mismatch in function arguments
// --> src/main.rs:58:54
// |
// 33 | fn str_contains(a: &str, b: &str) -> bool {
// | ----------------------------------------- found signature of `for<'r, 's> fn(&'r str, &'s str) -> _`
// ...
// 58 | BinaryExpression::<String, String, bool, _>::new(str_contains);
// | ------------------------------------------------ ^^^^^^^^^^^^ expected signature of `for<'r, 's> fn(<String as Scalar>::RefType<'r>, <String as Scalar>::RefType<'s>) -> _`
// | |
// | required by a bound introduced by this call
// |
// note: required by a bound in `BinaryExpression::<A, B, O, F>::new`
// --> src/main.rs:47:8
// |
// 47 | F: Fn(A::RefType<'_>, B::RefType<'_>) -> O,
// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `BinaryExpression::<A, B, O, F>::new`
// 48 | {
// 49 | pub fn new(f: F) -> Self {
// | --- required by a bound in this
BinaryExpression::<String, String, bool, _>::new(str_contains);
}
fn success_case() {
BinaryExpression::<String, String, bool, _> {
f: str_contains,
_phantom: PhantomData,
};
}
fn main() {
println!("Hello, world!");
}
I expected to see this happen:
Both functions compile.
Instead, this happened:
If I directly call new
,
expected signature of `for<'r, 's> fn(<String as Scalar>::RefType<'r>, <String as Scalar>::RefType<'s>) -> _`
... but if I manually construct the struct, it succeeds.
Meta
rustc --version --verbose
:
rustc 1.60.0-nightly (8cdb3cd94 2022-01-25)
binary: rustc
commit-hash: 8cdb3cd94efece1e17cbd8f6edb1dc1a482779a0
commit-date: 2022-01-25
host: aarch64-apple-darwin
release: 1.60.0-nightly
LLVM version: 13.0.0
Thanks for investigating!