Skip to content

Function monomorphizes to early #141836

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
lukahasch opened this issue May 31, 2025 · 0 comments
Open

Function monomorphizes to early #141836

lukahasch opened this issue May 31, 2025 · 0 comments
Labels
C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged.

Comments

@lukahasch
Copy link

lukahasch commented May 31, 2025

I am currently trying to put together my own spin (which has probably already been done but eh) on compile time reflection in rust, and since variadic generics don't exist yet, been creating heterogenous struct-based lists. To actually do anything useful with such lists without runtime checking though you need to enforce trait bounds generically, which can (afaik) only be done through bounds on other Types.
When using these Bounds with a user defined struct they perform as expected (see below), when using them with functions however they get monomorphized on the first bound (at least that's my best guess).
Aka instead of some Object F with bounds FnMut<(A,)> + FnMut<(B,)>, I get only fn(A) -> _.

I tried this code:

#![feature(unboxed_closures)]

pub trait Function<T> {
    type Output;
    fn apply(&mut self, value: T) -> Self::Output;
}

pub trait Map<T> {
    type Output;
    fn map<'a>(&mut self, value: T) -> Self::Output;
}

#[derive(Debug, PartialEq, Hash, Clone, Copy)]
pub struct Single<T>(pub T);

#[derive(Debug, PartialEq, Hash, Clone, Copy)]
pub struct Sequence<T, R>(pub T, pub R);

impl<F, T> Map<Single<T>> for F
where
    F: Function<T>,
{
    type Output = Single<F::Output>;

    fn map<'a>(&mut self, value: Single<T>) -> Self::Output {
        Single(self.apply(value.0))
    }
}

impl<F, T, R> Map<Sequence<T, R>> for F
where
    F: Function<T>,
    F: Map<R>,
{
    type Output = Sequence<<F as Function<T>>::Output, <F as Map<R>>::Output>;

    fn map<'a>(&mut self, value: Sequence<T, R>) -> Self::Output {
        Sequence(self.apply(value.0), self.map(value.1))
    }
}

impl<F, T> Function<T> for F
where
    F: FnMut<(T,)>,
{
    type Output = <F as FnOnce<(T,)>>::Output;

    fn apply(&mut self, value: T) -> Self::Output {
        self(value)
    }
}

use std::ops::Add;

pub struct Manual;

impl<T> Function<T> for Manual
where
    T: Add<Output = T> + Copy,
{
    type Output = T;

    fn apply(&mut self, value: T) -> Self::Output {
        value + value
    }
}

fn function<T: Add<Output = T> + Copy>(v: T) -> T {
    v + v
}

fn main() {
    let t: Sequence<i32, Sequence<f32, Single<i8>>> = Sequence(1, Sequence(1.0, Single(1)));

    dbg!(Manual.map(t));
    dbg!(function.map(t));
}

I expected to see this happen:
function.map(t) should perform the same as Manual.map(t)

Instead, this happened:
error[E0631]: type mismatch in function arguments
--> src/main.rs:76:19
|
68 | fn function<T: Add<Output = T> + Copy>(v: T) -> T {
| ------------------------------------------------- found signature defined here
...
76 | dbg!(function.map(t));
| ^^^ expected due to this
|
= note: expected function signature fn(f32) -> _
found function signature fn(i32) -> _
note: required for fn(i32) -> i32 {function::<i32>} to implement Function<f32>
--> src/main.rs:42:12
|
42 | impl<F, T> Function for F
| ^^^^^^^^^^^ ^
43 | where
44 | F: FnMut<(T,)>,
| ----------- unsatisfied trait bound introduced here

Meta

Stable, Beta and Nightly all catch this though unboxed_closures is not yet stabilized.

rustc --version --verbose:

rustc 1.87.0 (17067e9ac 2025-05-09)
binary: rustc
commit-hash: 17067e9ac6d7ecb70e50f92c1944e545188d2359
commit-date: 2025-05-09
host: aarch64-apple-darwin
release: 1.87.0
LLVM version: 20.1.1

rustc +nightly --version --verbose:

rustc 1.89.0-nightly (70b3f4666 2025-05-30)
binary: rustc
commit-hash: 70b3f4666e24ce22fc32f5e357dbcf85d3254e63
commit-date: 2025-05-30
host: aarch64-apple-darwin
release: 1.89.0-nightly
LLVM version: 20.1.5

@lukahasch lukahasch added the C-bug Category: This is a bug. label May 31, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label May 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged.
Projects
None yet
Development

No branches or pull requests

2 participants