Uh oh!
There was an error while loading. Please reload this page.
Make function pointer types look like borrowed pointer types for forwards compatability - #883
Make function pointer types look like borrowed pointer types for forwards compatability#883Ericson2314 wants to merge 12 commits into
Conversation
There was a problem hiding this comment.
Broken link, should be e.g.: [custom pointer types][1].
There was a problem hiding this comment.
In this case I wanted an actual footnote. But maybe there is a way I can make that clearer / look better.
There was a problem hiding this comment.
Oh right. There's usually a way to do superscripts but I think it's nonstandard, foo^1 on reddit and foo<sup>1</sup> on GH. (let'ssee... yup.)
There was a problem hiding this comment.
Done! How awful is it that allow tags in their markdown....
scialex
commented
Feb 18, 2015
What is the benefit of this over simply using the |
Ericson2314
commented
Feb 19, 2015
@scialex the The best hack in the existing language is to create a new type of a function pointer with a phantom lifetime for borrowed pointers, and a newtype with a drop instance for owned pointers. |
bombless
commented
Feb 19, 2015
Then how do we handle extern-functions? And can we remove that optional argument name? #838 I'll try making a PoC soon. |
ftxqxd
commented
Feb 20, 2015
I like this RFC, but I think it should be adjusted to require |
petrochenkov
commented
Feb 20, 2015
+1 to the RFC with @P1start's amendment Unfortunately, IIRC, a similar idea was already discussed and rejected. |
CloudiDust
commented
Feb 20, 2015
+1 to this with amendment. @P1start, do you mean @petrochenkov, was that discussion before the implementation of DST? |
Florob
commented
Feb 20, 2015
Particularly with the amendment, I really like this. It could alleviate the fallout from the recent-ish change that each function has its own type. I.e. where we now need: fnf(x:Ty){ ...}let f:fn(Ty) = f;// coerce to fn pointer
foo.map(f)we could probably do: fn f(x:Ty){ ...}foo.map(&f) |
petrochenkov
commented
Feb 20, 2015
Some thoughts about the proposal.
Edit: |
Ericson2314
commented
Feb 20, 2015
@bombless If you are wondering whether @P1start Are you saying we should get rid of the secret_unboxed_function -> function pointer conversion and replace it with @petrochenkov@Florob if you don't mind, I think both your examples would look great in the RFC to explain the coercion changes. @petrochenkov To be clear these semantic decisions would be left for the future, but I'm happy to speculate on how thing might turn out in the long run:
|
ftxqxd
commented
Feb 20, 2015
@Ericson2314 Yeah. In other words, a slight change in coercion rules that means that @CloudiDust @Florob Why do you need to coerce to a function pointer anyway? Assuming that @petrochenkov The anonymous function item types should already be zero-sized, but unfortunately aren’t yet (cc rust-lang/rust#19925). Regarding the |
Florob
commented
Feb 21, 2015
@P1start Indeed you may disregard that comment. It's a mixture of outdated information and lack of coherent thinking at the time. That said I am still generally in favour of this proposal. It adds a nice explicitness to things. |
9afe31f to
c712323CompareEricson2314
commented
Feb 22, 2015
Ok, added the coercion rules. The response seems pretty positive here, any team member want to comment? |
CloudiDust
commented
Feb 23, 2015
This can be seen as an amendment to RFC 401, the Function type polymorphism section.
No need to change.
No need to change.
All function pointers are implicitly coercible to a
No need to change, but we will not be passing
No need to change. Examples: fnfoo(){ ...}// `foo` has a fresh and non-denotable type. (`fn() {foo}`)fnmain(){let x:fn() = foo;// error (currently valid)let x:&fn() = &foo;// ok, `&foo` is coerced to `&fn()`. (currently invalid)let y:&Fn() = x;// ok, `x` is coerced to `&Fn` (a closure object),// legal because `x` is a `&fn()` here, and `fn()` implements `Fn()`.let z:&Fn() = foo;// error.let z:&Fn() = &foo;// ok, `&foo` is coerced to `&Fn()`,}I think one of the reasons that we want functions have unique types that implement closure traits directly, is to avoid virtual calls. Is this correct? EDIT: some corrections. |
CloudiDust
commented
Feb 23, 2015
@petrochenkov, after reading RFC 401, I think one of the reasons that "function values" (that have unique types) exist now, is because virtual calls can be avoided when function values are used as closures, while the same cannot be said about function pointers. If my understanding is correct, then it makes sense to pass function values around, and the lack of fnf(){}// f has type fn(){f}, zero sized (ideally) and unnameable// &f has type &fn(){f}, pointer to the zero sized and unnameable type// fn() is the unsized and generalized function type.// &fn() is the pointer type to the unsized and generalized function typefnmain(){let g = f;// OK, copying a "function value".let g = &f;// OK, g is a `&fn(){f}`let g:&fn() = f;// ERROR: can't coerce fn(){f} to &fn()let g:fn() = &f;// ERROR: can't create object of unsized type on stacklet g:&fn() = &f;// OK; pointers to concrete functions coerce to pointers to generalized function} |
nikomatsakis
commented
Mar 5, 2015
On Wed, Mar 04, 2015 at 03:04:47AM -0800, Huon Wilson wrote:
Thanks huon, I was going to ask for the same. At this point, I can I think my preferred proposal is as follows:
I believe this is more-or-less what @huonw presented as "option 2", |
nikomatsakis
commented
Mar 5, 2015
I was thinking about this in the shower and I realized that what I wrote doesn't actually work. In particular, the use of an unsize coercion doesn't make sense -- it only makes sense if we assume that the only pointers of type
This is basically exactly what we have today except that the type of a fn pointer is I think that going through this exercise leaves me more-or-less where I was before, but perhaps mildly more negative. The use case being addressed here feels marginal -- we're making the implementations of a dynamic linking utility library or jit a smidgen more safe. (Am I missing some other advantage?) I guess it ultimately depends on whether you prefer to see |
CloudiDust
commented
Mar 5, 2015
@nikomatsakis I think "pointers should look like pointers" outweighs the disadvantage, especially when there can be function pointers that have non-static lifetimes in the future. I notice that you assumed the I'd prefer (I expect |
Kimundi
commented
Mar 5, 2015
@nikomatsakis One issue that I see with the "custom type implementing a In other words, its not actually possible right now to define a custom function pointer type that can be used as By having function types actually just describe the actual code, unrelated to having a pointer to it, it would be possible to off-load all that complexity to the primitve, compiler-provided function types: |
CloudiDust
commented
Mar 6, 2015
@nikomatsakis, I realized that I might have missed a point of your posts. Were you implying that even if we wouldn't do If this is the case, then I'd settle with simply doing |
Ericson2314
commented
Mar 6, 2015
Sorry everybody, I've been busy with school. I'll try to fix this up this weekend---and go with the proxy approach. @Kimundi Excellent point @nikomatsakis In case you missed it, I mentioned that (using your identifiers)
|
CloudiDust
commented
Mar 6, 2015
@Ericson2314, I suspect dereferencing to unsized types need special-casing anyway, so if That said, @nikomatsakis, I wonder why |
nikomatsakis
commented
Mar 6, 2015
On Thu, Mar 05, 2015 at 06:24:58PM -0800, Richard Zhang wrote:
I was implying that, but I think I was wrong. I thought about it some |
nikomatsakis
commented
Mar 6, 2015
On Thu, Mar 05, 2015 at 11:35:36PM -0800, Richard Zhang wrote:
To be clear, any instance of type |
nikomatsakis
commented
Mar 6, 2015
Even though I wrote "to be clear", I think I was anything but. |
CloudiDust
commented
Mar 7, 2015
@nikomatsakis, thanks, so actually you were to mean: Currently, as (So, And most importantly |
nikomatsakis
commented
Mar 10, 2015
On Fri, Mar 06, 2015 at 04:57:41PM -0800, Richard Zhang wrote:
Yes.
Yes. |
CloudiDust
commented
Mar 10, 2015
So here is a summary of what we may want to do (assuming that we are going the "functions are almost statics" route):
Note:
There seems to be some asymmetry. @nikomatsakis, will |
huonw
commented
Mar 10, 2015
They should work. Although, it may require the planned changes that ensure that |
Ericson2314
commented
Mar 10, 2015
Here is a summery of what I am thinking (based off of @nikomatsakis and @CloudiDust's:
|
CloudiDust
commented
Mar 10, 2015
For |
Ericson2314
commented
Mar 11, 2015
@CloudiDust I think I see what you mean. While impls on the unsized functions are better for trait objects, impls on the pointers are better for calling polymorphic functions. Frankly though, I see the problem not specific to the closure traits, but more broadly part of a trade off between supporting in polymorphic code non-Copy types (or values that could be coppied but should be mutated in place) and cutting down on extraneous indirection. The controversy of whether iterators should be Copy, and the ByRef adapter iterator I'd wager stems in part from this. An associated type defined to a borrowed pointer for non-copy types and a the type itself non copy ones would help in many places in Rust. The counter-argument is optimization should do most of that work, and it would make a whole lot of a code much less readable. And of course, negative bounds are needed to implement this. Probably the best lower-impact solution is to make some blanket impls. This would also make "reusing" sugar-made closures more ergonomic, to give an example of a different benefit. |
CloudiDust
commented
Mar 15, 2015
I think you mean:
Right? I'm thinking, generally, for non-
I think "blanket impls" would do nothing? The impls would delegate to the underlying functions. Also, would you please update the RFC? If you are still busy I'd like to help. |
eddyb
commented
Mar 15, 2015
Most of what I see here looks good, but there's a certain detail I've been pondering on - the use of "unsized" terminology. All our (current) DSTs keep around enough information to query size and alignment, so we could have a Then "unsizing" can be defined as One might also wonder what semantics would manual implementations of traitArray<T>{constLEN:usize;}// "Just" needs generics over values.impl<T,constN:usize>Array<T>for[T;N]{constLEN = N;}impl<T>SizeableforArray<T>{fnsize_of(&self) -> usize{self.LEN*size_of::<T>()}fnmin_align_of(&self) -> usize{min_align_of::<T>()}}// This is the tricky part, that might require backwards incompatible// changes to Drop.impl<T:Drop>DropforArray<T>{fndrop(&move self){for _ inself.into_iter(){}}}I didn't mean to post that in its entirety, but there you go. More creative usecases left as an exercise for the reader. |
Ericson2314
commented
Mar 16, 2015
@CloudiDust Yeah that sounds good. A simpler way to look at the problem than my ranty post above is that in many cases we consume of an abstract type bounded on a trait that only borrows self. (e.g. consuming a FnMut in Also, size isn't important because it it trivial to always compile pass-by-value to pass-by-reference (we already do that) for specific, while the converse breaks code that depends on the pointer value itself (e.g. pointer equality). @eddyb Yeah I want that for HAMTs, where traditionally nodes has a sparse array of a dynamically sized array with a bitmap to show which elements are present to save space. The size is thus the hamming weight of the bitmap. When @nikomatsakis said "... with an "auxiliary data" type of |
eddyb
commented
Mar 16, 2015
There is no mechanism in place and such a type is not valid today, as all types are required to allow their size and alignment to be queried, dynamically in the case of DSTs. |
CloudiDust
commented
Mar 20, 2015
@Ericson2314, would you please update the RFC soon? If you are still busy, I'd like to post an alternative RFC tomorrow (local time) to describe what we have come up in the discussions. The beta is approaching fast, so I think we should move forward now. |
Ericson2314
commented
Mar 20, 2015
@CloudiDust Yeah sorry. I've been busy, and for the upcoming week I won't have internet access, so I think you better do that. Thanks for taking the initiative! |
CloudiDust
commented
Mar 21, 2015
@Ericson2314, no problem and thanks for this RFC. The new RFC is #996. |
nikomatsakis
commented
Mar 23, 2015
Should we close this RFC in favor of #996? |
Rendered