-
Notifications
You must be signed in to change notification settings - Fork 789
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
Struct records #620
Struct records #620
Conversation
…not related to structs
This is fantastic! And
equally interesting. |
Would be awesome to See this feature since it would simplify unmanaged interop a lot! |
@krauthaufen see the tests in this PR in |
@krauthaufen you could always do this with records even if they were not value types. Hmm, makes me think record types could have always worked with interop. |
@krauthaufen Great question re interop. Please continue to list possible feature interactions like this! Historically unassessed feature interactions when adding new features have been the biggest source of bugs in F#. I'm hopeful that having multiple people thinking about this in an open source context will help us avoid a bug trail. p.s. One C# user found many bugs in the production compiler simply by looking through the C# language spec for feature interactions and thinking "what mistakes would I make if I implemented this". :) |
@TIHan Instead of changing the TAST and the pickle format, you should add a new flag to EntityFlags https://github.com/TIHan/visualfsharp/blob/struct_records/src/fsharp/tast.fs#L351 using the existing space in the metadata format. A value of 0 would indicate a class record, a value of 1 a struct record. Thanks |
@dsyme ok! I will do that. :) It should make the implementation simpler. I will also write interop tests. @krauthaufen thank you for bringing interop up. I think that is something that could have been overlooked on my part. |
💯 |
Cool, great work! On the syntax side, struct types can be defined today with either Some interactions/tests that should be included/considered:
That's what I can think of for now, will chime in w/ more if I think of anything. Within reason, we should review all tests of the form "verify property X specific to struct types" or "verify property Y specific to record types" and add a variation for struct records. |
No, we don't need this.
Good point. I presume it's unrealistic to add this feature to F# 4.0 OOB1 for this reason. Maybe we could add a warning or error to the OOB1 of Visual F# Tools 4.0 if it encounters a type definition with the top bit set? However I think that would be an unfortunate limitation to require FSharp.Core 4.x.x.x since the feature has nothing to do with FSharp.Core and there are perfectly good reasons to use it when targeting 4.3.1.0, 4.4.0.0 etc.
We already auto-generate hash/equality for structs and I'd imagine that using defaultof does already give nullrefs. I don't think it's unexpected. e.g.
I'm ok with this behaviour but it should be pinned down by tests.
Good one. Add lots of tests for all the combinations here.
Yes! |
How does this interact with the |
Yes, the interaction with
|
As an aside, while looking at the code for the DefaultValue attribute I noticed an improvement we can make: http://fslang.uservoice.com/forums/245727-f-language/suggestions/9679206-defaultvalue-attribute-should-require-mutable-wh |
Integrate and fix to tests
@TIHan I made some progress on the errors. I think FSharp.Core.Unittests is now failing for the CoreCLR build due to missing APIs. Here are the failures:
We could just disable some of these tests for CoreCLR I suppose, though it would be good to have the coverage. |
@TIHan OK, just pushed another commit which should fix those I think |
Ok, this is all green now, I'm happy to see this merged |
@dsyme Thank you so much and thank you for fixing the build! I'm glad to see this is all good. I apologize for not getting to it this weekend; didn't mean to add work to your plate. |
I know that this is really late in the day but here's a question nonetheless. Am I correct that for records we'll use an attribute to mark it as a struct? Would it not make sense to use the struct keyword instead for consistencies' sake with the upcoming struct tuples? |
@isaacabraham Yes, you will use the |
@isaacabraham you mean this: type struct Foo { } or this:
? |
that keyword would need to set the attribute, right? so this PR is needed as basis, right? |
I've absolutely zero understanding of what is required in the internals of this i.e. if you need an attribute or not. I just wanted to mention this before this feature was merged just in case it's something that would need changing before merging. I'm really just thinking from a consumer point of view i.e. F# developer looking to create a struct record. @vasily-kirichenko I was thinking of your first example, with struct acting as a modifier of sorts (albeit with tuples it's at the point of value creation, here it's at the point of type definition). I just think having a keyword would be more consistent, that's all. Maybe this should go back into the RFC as @forki suggests. |
@TIHan would you expect there to be the ability to add [<Struct>]
type Name = string * string |
@isaacabraham Yes, the attribute is needed, and @TIHan is correct that this is one reason it's always been there. Using the attribute is the preferred way if indicating structness for nominal type definitions. There's also a basic principle here that F# only uses "let", "module" and "type" as top level declarations (and "exception" and "extern" but they are rarely used). We don't use new keyword-led declarations for the panoply of different kinds of nominal types. Unlike tuples, for record types the structness is an aspect of the nominal type definition, and we've long preferred attributes for those. For struct tuples, the structness is part of the syntax of anonymous types, not nominal type definitions We wouldn't expect the example above to work. You can't put a struct attribute on a type abbreviation. |
@dsyme Makes sense. I was thinking along the lines of @vasily-kirichenko 's idea - using struct as a modifier on type e.g. |
@isaacabraham Among other things, |
Ah so you are reserving the syntax for type classes. Smart move ;-)
|
@forki The funny thing is that |
@dsyme hmmm :-) I was expecting everything else to stay as is i.e. interface and class are not needed. Only for struct would there have been the extra keyword. |
Gratulations! Thanks everyone. ❤️ |
Thank you guys! |
💯 |
👍 This is excellent. |
A fantastic example to the community. Thanks everyone. On Sat, Jun 4, 2016 at 5:34 PM, Phillip Carter notifications@github.com
|
I hope I'm doing this correctly. I'm open to change anything in the PR, and I'm open to toss it if it is done incorrectly.
Here is the original user voice post. http://fslang.uservoice.com/forums/245727-f-language/suggestions/6547517-record-types-can-be-marked-with-the-struct-attribu
The idea:
Record types should be able to be marked as a struct, effectively making the record have the semantics of value types.
How to use:
Put the
StructAttribute
on the type.Key differences in struct records:
type T = { X: T }
CLIMutableAttribute
, it will not create a default ctor, because structs implicitly have one, though you can't call it from F#.I have provided typecheck tests for most if not all these cases, inlining tests, and basic unit tests for checking equality.
From the code changes themselves, I am most worried about what I am doing in
TastPickle.fs
. At the moment I can't think of a better way unless someone tells me its fine, it could be cleaned up, or could be done differently.Anyway, this feature has been long overdue, and I'm happy that it is finally here. If this works out, I'll try to tackle single case union structs as it will be roughly similar to how struct records are accomplished.