Open Lanayx opened 4 years ago
There's another workaround, that at least allows you to keep the thread-safety and atomic operation of Interlocked.Increment
, but it requires changing the type to a struct with two overlapping fields. This works, because after compiling, the measure-info is erased (I mean, int<seqId>
is really nothing more than just int
).
[<Measure>] type seqId
[<Struct; StructLayout(LayoutKind.Explicit)>]
type Conv =
/// This shadows the measure int<seqId>, and is kept private
[<FieldOffset 0>] val mutable private Shadow : int
/// This is your original measure-type
[<FieldOffset 0>] val mutable Value : int<seqId>
/// Creation
new (value) = { Value = value; Shadow = value * 1<_> }
/// More functional way of creation
static member create value = Conv(value)
/// By making Interlocked.Increment a member of the new type, we can keep this.Shadow private
static member Incr (conv: byref<Conv>) =
Interlocked.Increment &conv.Shadow
|> ignore
type Foo = { mutable SeqId: Conv}
let foo = { SeqId = Conv.create 1<seqId> }
let bar() =
Conv.Incr &foo.SeqId
printfn "Value: %A" foo.SeqId.Value
Imo, this also essentially shows that there isn't anything really blocking the &
to take an address of a measure-type, somehow the code should erase the measure. However, since &
is an overridable operator, I hope this can be solved in Core somehow.
Conversely, if this is indeed allowed, and let x = 1<seqId> in &x
returns the address of an int
, it will allow programmers to easily erase the type information as well by just converting it back: let f (x: inref<int>) = x
, then let x = 1<seqId>; y = f &x
will yield int
for y
, not int<seqId>
.
Is your feature request related to a problem? Please describe. I'm using Fsharp.UMX everywhere I can to make primitives typesafe, so I use it like
type SequenceId = int64<sequenceId>
However when I face the need of using Interlocked methods I can't normally use measuresDescribe the solution you'd like I'd like it to just work, e.g. implicit type conversion made and result casted back to measure
Describe alternatives you've considered There is a hacky way around provided by @Szer, which I won't use in code and rather stay without measures:
Additional context This is the commit that I had to do to revert measure