Skip to content

Are late-bound argument types in named functions equivalent to higher-ranked types? #7

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
golddranks opened this issue Nov 8, 2021 · 0 comments
Labels
question Further information is requested

Comments

@golddranks
Copy link

golddranks commented Nov 8, 2021

The draft RFC about named function types mentions that impl Traits in a function argument position could be changed to be a "late-bound" part of the function type, so that the non-generic type would be settled on the function call-site, per-call basis.

Rust already has a feature called "higher-ranked trait bounds", that enables functions to have arguments with lifetimes that are a "late-bound" part of the type; that is, the function is guaranteed to work with arguments of any lifetime. Because lifetimes can always be erased, unlike other generics, this is just a type-level construct that doesn't need monomorphisation (and the lifetime erasure will make it work even with function pointers).

If a named function types feature is realised and impl Traits in function arguments are changed to behave as "late-bound", does that mean, that Rust gains new capabilities to express higher-ranked types? If the impl Traits in function argument position are considered late-bound, the following may become possible:

struct Container<F: Fn(impl Debug)> {
    f: F,
}

fn inner(input: impl Debug) {
}

fn main() {
    let container = Container { f: inner };
    (container.f)(1u32); // Different argument types here...
    (container.f)(1i32); // ...and here
}

To me, this looks remarkably similar to this hypothetical use of the for<_> syntax:

struct Container<F> where for<D: Debug> F: Fn(D) {
    f: F,
}

fn inner<D: Debug>(input: D) {
}

fn main() {
    let container = Container { f: inner };
    (container.f)(1u32); // Different argument types here...
    (container.f)(1i32); // ...and here
}

If late-bound argument types expose new functionality that is in some form equivalent to higher-ranked types, I expect the RFC to discuss about that, and consider the connection to the for<_> syntax.

@golddranks golddranks added the question Further information is requested label Nov 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant