-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Universal quantification for types #2413
Comments
Edit: OK, so I should start thinking before I send comments: the above was a discussion of how to make the proposed types object-safe, even though I explicitly mentioned they shouldn't be. So for the actual technical reasoning: in my mind, it's all about closure inference. The same behaviour can currently be replicated using a However, for closures there is a need to actually type them, and auto-deriving all traits that could potentially match a closure sounds like something that wouldn't scale well across large code bases (or would it?). So I'm thinking of a kind of “adversarial typechecking” (there must be an actual word for this in type theory, I just don't happen to know it): take the closure type and what you're trying to match it against, and, if it matches, then it's all good. So, for an example: fn foo<F: for <T: Iterator> Fn(T)>(f: F) {}
fn bar<F: for <T: Future> Fn(T)>(f: F) {}
let closure = |x| { x.next(); }
// closure has type [closure], that doesn't derive any trait
foo(closure);
// Here, type to match closure with for <T: Iterator> Fn(T). As it's a closure type,
// this needs proving that the closure indeed verifies this. We use the same code
// as for when verifying a fn baz<T: Iterator>(t: T) { t.next(); } typechecks.
// It does typecheck, so allow that
bar(closure);
// Same thing here, but fn quux<T: Future>(t: T) { t.next(); } doesn't typecheck.
// So that's a type error Did I miss another difficulty? |
For reference, this is what you get with Iirc, Haskell deals with RankNTypes by not monomorphizing things. cc @glaebhoerl on this. |
(Sorry, I didn't read the previous two comments in detail, just responding with what I know per the cc:)
To implement you |
Hmm, so with your comment I think what I'm looking for is the equivalent |
This looks to be a duplicate of #1481 |
Currently, we have
for <'a>
. I was thinking of expanding it intofor <T: Trait>
.The use case is the following:
(playground link)
Here, I don't want to expose the fact that
F
must take aFoo<T>
. I want to expose the fact thatF
must take anyTrait
. 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 forfoo
below:The actual use case that made this idea emerge was with
tokio::Stream
: I have a function like this:Actually, this is a lucky case. Indeed, had I not directly passed the
err_cb
intostream.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:What would be possible to pass into it would be (resuming with the toy example above):
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 :)
The text was updated successfully, but these errors were encountered: