-
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
Minimal impl Trait
#1522
Minimal impl Trait
#1522
Conversation
Impl trait edits
I should mention that being able to use
That extension to this RFC was essential to my calendar demo implementation from last year, and had a small implementation footprint. |
… as part of a return type of a freestanding function
Type parameters and trait objects seem to work quite fine without OIBIT passthrough, so maybe this could work there too? |
Bikeshed checking in: I strongly prefer a keyword like |
@steveklabnik I agree. |
@steveklabnik Compare: fn foo(x: bool) -> @Fn(&str) -> @Fn(i32) -> String {...}
fn foo(x: bool) -> impl Fn(&str) -> impl Fn(i32) -> String {...} |
Anyway, I don't want to distract with the bikeshed here: Let's worry about semantics first. I will refrain from further expressing my preferences here until the end 😄 |
+1 on Perhaps |
@comex That would be a bit confusing though, and ambiguous with the hypothetical-but-talked-about extension to return DST values. (Which is theoretically possible given outpointers and DST-allocator/box support) |
I'm -1 on having no prefix at all; among other things, I'd eventually like to be able to use |
|
||
- The type would be known to implement the specified traits. | ||
- The type would not be known to implement any other trait, with | ||
the exception of OIBITS (aka "auto traits") and default traits like `Sized`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the part about OIBITs be omitted at least initially, until the usage experience provides the evidence, that this is really really necessary and unavoidable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On Wed, Mar 02, 2016 at 08:48:13AM -0800, Vadim Petrochenkov wrote:
Can the part about OIBITs be omitted at least initially, until the usage experience provide the evidence, that this is really really necessary and unavoidable?
It could, but it is clear that in the longer term we will want to
infer Send
bounds. Certainly this is what makes generic combinator
libraries like iterators work smoothly with auto traits (OIBITs) like
send and sync. (Conversly, the fact that trait objects do NOT
permit this sort of "leakage" of auto trait information is a major
pain point with objects.)
To see why this would be limiting for generic combinator libaries,
imagine an example like this:
fn curry<F,U,V,R>(func: F, argument: U) -> @Fn(&V) -> R
where F: Fn(&U, &V) -> R
{
move |v| func(&argument, &v)
}
Now I have this nice little combinator that I can use to do stuff like
let foo = curry(Option::unwrap_or, some_opt)
. But now suppose that
I want to use Rayon to parallelize some computation:
fn my_computation() {
let foo = curry(Option::unwrap_op, some_opt);
rayon::join(
|| do_something(foo(22)),
|| do_something_else(foo(22)));
}
Now I get a compilation error because I am sharing foo
, and all we
know about foo
is that it implements Fn(&V) -> R
; we don't
know whether it is Send
.
Of course, I can modify curry
to require that its inputs are send:
fn curry<F,U,V,R>(func: F, argument: U) -> @Fn(&V) -> R + Send
where F: Fn(&U, &V) -> R + Send, U: Send
{
move |v| func(&argument, &v)
}
but now I can't use curry
for other cases, where the data is not
sendable. So I need to have curry_send
and curry
. etc.
That said, there is definitely a need to address this more generally.
For example, you will want to write iterator adapters that are
double-ended if the input is double-ended and so forth. We could
conceivably use the same mechanism to "propagate" Send
as we invent
for handling DoubleEndedIterator
. But on the other hand, the whole
point of traits like Send
and Sync
being auto traits is to ensure
that they are, well, automatic, and not something one has to opt in
to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if there were a way to specify conditional OIBITs? Awful strawman (leaving the sigil, but I'm not necessarily advocating for it):
fn curry<F,U,V,R>(func: F, argument: U) -> @Fn(&V) -> R
where F: Fn(&U, &V) -> R,
U: Send + Sync for return
{
move |v| func(&argument, &v)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens when an OIBIT is added, maybe even in a non-std
crate?
The thing you're proposing has been considered and it might work if Send
and Sync
were the only OIBITs ever. But that's wrong, even right now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't even know what an OIBIT is. Auto trait! Auto trait!
@steveklabnik It might cover my use case anyway. I'll give it a go as soon as it's available in the beta channel and then we'll see. Cheers! |
Once it's in beta, it's already on its way to stable. If you really want to make sure it works for you, you should try it out on nightly, so that way you can point out problems before it's set to go stable. |
It makes sense - it's already in there, is it not? EDIT: just got nightly but no luck - I feel I'm missing something silly here.
|
@norru The syntax is |
@eddyb Ace, yes I got the syntax wrong for no reason except me being dense :). |
How do I report it to the compiler team? |
@norru You should open an issue on https://github.com/rust-lang/rust. |
May be a dumb question, but what if Rust allowed using a trait any place where you can use a concrete type today. In a way, it'll mean traits will (syntactically) behave akin to interfaces in mainstream languages. Not only will this resolve the questions posed here (i.e. whether to use What I mean is, if you can do this today:
it should also be possible to do this:
My feeling about the proposed new use of |
@gurry: unfortunately there's an issue when you have the type These ambiguities were heavily discussed in #1603 |
@gurry Everyone would prefer if we could just say "you can use a trait any place where you can use a type," but the problem is what it means to do that. There are three obvious semantics (generics, dynamic dispatch, and the semantics in this proposal), all of which the language now supports with different syntaxes. None of them are redundant with the others. |
@withoutboats I think that ideally, existential types and generics, which both use static dispatch, should have the same syntax, and trait objects, which uses dynamic dispatch, would have a different syntax. Since that ship has sailed, I really like that this RFC introduces special syntax, But this is just that: a weird spot in the design space. It could be improved by encouraging users to use a special syntax for dynamic dispatch in the future (in another RFC), which would leave Rust with 3 different syntaxes to denote different things (generics, existential, and dynamic dispatch). Maybe that would not be that weird, but whether this is worth pursuing or not is kind of orthogonal to whether this RFC is stabilized as is. We have painted ourselves into a corner here, and as I see it, all the ways out that do not break the language involve some special syntax for |
@gnzlbg at minimum there would need to be a distinct elaborated syntax for univerals/existentials; we can't tell which you want without examining the function body which would mean global type inference |
Was the |
Thanks guys. Just read the whole of #1603. I appreciate the whole picture a lot better now. |
Will it be possible to use let a impl MyTrait = value; That would be way cleaner and readable IMHO. |
Add a initial, minimal form of
impl Trait
.Rendered
[edited to link to final rendered version]