Universal quantification for types
Nobody has claimed this yet.
- Dominant language
- Markdown
- Stars
- 6.6k
- Forks
- 1.7k
- Avg merge
- 16h 14m
- Merged PRs (30d)
- 1
Description
Currently, we have for <'a>. I was thinking of expanding it into for <T: Trait>.
The use case is the following:
trait Trait {}
// This is implementation detail
struct Foo<T>(T);
impl<T> Trait for Foo<T> {}
// This is public API, foo takes a type and a closure that takes a Trait as input
pub fn foo<T, F: Fn(Foo<T>)>(t: T, f: F) {
f(Foo(t))
}
Here, I don't want to expose the fact that F must take a Foo<T>. I want to expose the fact that F must take any Trait. But there's no way I can think of to encode this assertion in the Rust type system, currently.
So I was thinking of adding for <T: Trait> bound on types. As was pointed out to me, eg. for <T: Trait> Fn(T) wouldn't be object-safe. But I think that's something that could be useful nonetheless, as exposed by the corrected signature for foo below:
pub fn foo<T, F: for <P: Trait> Fn(P)>(t: T, f: F)
The actual use case that made this idea emerge was with tokio::Stream: I have a function like this:
pub fn bar<
Stream,
HandleErr,
Callback: Fn(MapErr<Stream, HandleErr>) -> MapErr<Stream, HandleErr>
>(
stream: Stream,
err_cb: HandleErr,
callback: Callback
)
Actually, this is a lucky case. Indeed, had I not directly passed the err_cb into stream.map_err, but instead passed eg. a closure, I'd have been completely unable to write the type… and would have had to re-write the closure type by hand just to be able to type it.
So, with the proposed for <T: Trait> idea, the function would look like this:
pub fn bar<Stream, HandleErr, Callback: for <S: Stream> Fn(S) -> S>(...)
What would be possible to pass into it would be (resuming with the toy example above):
// Template functions:
fn baz<T: Trait>(t: T) { }
foo(baz);
// If type inference permits, closures where the body uses only functions from `Trait`
foo(|x| ());
So if that's technically possible I think it'd be great. But I'm not sure it is? I guess it'd require monomorphization of the argument inside of the function body before knowing the size of the said argument, at least.
Anyway, would be glad to hear any opinion on this idea :)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the proposed for <T: Trait> syntax and the linked Rust playground example, then assess its interaction with generic closures, trait bounds, object safety, type inference, and monomorphization. Done means determining whether the proposal is technically feasible and what RFC-level design and constraints it requires.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100