Saturday, February 4, 2012

F# ≥ C# (warning 9)


Today one customer ask me why the there is a warning when use StructLayout on a type.
Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.
The warning is because this can lead to some "interesting" results, make a managed code like C code. All the F# attribute is inserted an extra space so browser can display it correctly.


open System.Runtime.InteropServices

[ < StructLayout(LayoutKind.Sequential) > ]
type A =
    val mutable X : int
    val mutable Y : int
    new(x,y) = { X = x; Y = y }

[ < StructLayout(LayoutKind.Sequential) > ]
type B =
    val mutable Z : int64
    new(x) = { Z = x }

[ < StructLayout(LayoutKind.Explicit) > ]
type C =
    [ < FieldOffset 0 > ] val mutable X : A
    [ < FieldOffset 0 > ] val mutable Y : B
    new (a, b) = { X = a; Y = b }

[ < StructLayout(LayoutKind.Explicit) > ]
type D =
    [ < FieldOffset 0 > ] val mutable X : int
    [ < FieldOffset 0 > ] val mutable Y : int
    new(a,b) = { X = a; Y = b }

let a = A(0,0)
let b = B(1L)
let c = C(a,b)    //debugger will show two b's.
let d = D(1, 2)  // two fields are both 2

The managed code should not have this side-effect even a few people might think this is a good feature. I like the F#'s way to give you a warning than C# does not give you anything.




1 comment:

Arseny Kapoulkine said...

I wish the warning was more intelligent. The only instance when the IL code becomes non-verifiable is when the fields overlap, as in your example; however, this is like 1% of the usages of structlayout. In 99% of the cases you just have to disable the warning. See http://connect.microsoft.com/VisualStudio/feedback/details/643668/f-structlayout-attribute-always-produces-a-possibleunverifiablecode-warning