Using F# Interactive, you can verify the following sizes:
// sizeof<A> = 4 bytes
type A (i: int) = struct end
// sizeof<B<int>> = 8 bytes (use any type parameter)
type B<'T> (i: int) = struct end
The reason for the extra size seems to be the presence of an integer __dummy
field in the generic case. Using F# Interactive again, you can see this using typeof
:
typeof<A>
shows DeclaredFields = [|Int32 i|]
typeof<B<int>>
shows DeclaredFields = [|Int32 i; Int32 __dummy|]
I don't understand why this __dummy
field has been added.
I think the code responsible for adding it is here:
https://github.com/fsharp/FSharp.Compiler.Service/blob/master/src/fsharp/ilxgen.fs
Line 6377 shows this:
if requiresExtraField then
yield mkILInstanceField("__dummy",cenv.g.ilg.typ_int32,None,ILMemberAccess.Assembly) ]
Line 6290 is where requiresExtraField
is defined:
let requiresExtraField =
let isEmptyStruct =
(match ilTypeDefKind with ILTypeDefKind.ValueType -> true | _ -> false) &&
// All structs are sequential by default
// Structs with no instance fields get size 1, pack 0
tycon.AllFieldsAsList |> List.exists (fun f -> not f.IsStatic)
isEmptyStruct && cenv.opts.workAroundReflectionEmitBugs && not tycon.TyparsNoRange.IsEmpty
I assume that isEmptyStruct
is supposed to mean that the struct does not have any instance fields. But the code as written is testing whether the struct does have any instance fields, which for most structs, including mine, is going to be true. I think the last part of the final test is whether there are any generic type parameters. So requiresExtraField
is false
for type A
(not generic) and true
for type B
(generic type).
Is this a compiler bug, or is the code correct? If it is correct, then what's the purpose of this __dummy
field? Is there some way I can avoid having it?
As another test, I removed my one and only instance field, and not surprisingly, I got the following sizes, showing that the __dummy
field was no longer added:
// sizeof<AA> = 1
type AA = struct end
// sizeof<BB<int>> = 1
type BB<'T> = struct end
The reason I want to have a value type, rather than a reference type, is that I will be storing lots of these objects in my data structures, not just passing them around.
A special relationship where each input has a single output. It is often written as "f(x)" where x is the input value. Example: f(x) = x/2 ("f of x equals x divided by 2")
AP Calculus teacher WHO MAJORED IN MATH: They don't serve different purposes. It's just notation f(x) is the same as y.
What Does f ' Say About f ? The first derivative of a function is an expression which tells us the slope of a tangent line to the curve at any instant. Because of this definition, the first derivative of a function tells us much about the function. If is positive, then must be increasing.
f″ denotes the second derivative of f; that is to say, it is the derivative of the derivative of f.
The explanation is given by @jyoung in the comments below my original posting.
The last line of requiresExtraField
also tests cenv.opts.workAroundReflectionEmitBugs
. This flag appears to be set in fscopts.fs. The line of code is:
workAroundReflectionEmitBugs=tcConfig.isInteractive; // REVIEW: is this still required?
So the problem of the extra __dummy
field only occurs in F# Interactive.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With