Why does F# constrain my code and remove generics?

f#

Solution

The F# compiler seems to specialise generic types if they are used at a particular instantiation in the same block of code. Try splitting up your declaration like this:

type VBO<'T when 'T : (new : unit -> 'T) and 'T : struct and 'T :> ValueType> = 
    { Handle : int
      target : BufferTarget
      size : int
      dataSize : int
      data : 'T []
      pos : int
      usage : BufferUsageHint }

type VBO = 
    static member CreateImpl(target, size, pos, usage, dataSize, (data : 'T [])) = 
        let h = GL.GenBuffer()
        { Handle = h
          target = target
          size = size
          dataSize = dataSize
          data = data
          pos = pos
          usage = usage }

type VBO with
    static member Create(target, size, pos, usage, (data : Vector3 [])) = 
        VBO.CreateImpl(target, size, pos, usage, Vector2.SizeInBytes, data)

    static member Create(target, size, pos, usage, (data : Vector2 [])) = 
        VBO.CreateImpl(target, size, pos, usage, Vector2.SizeInBytes, data)

Problem

``` type VBO<'T when 'T : (new : unit -> 'T) and 'T : struct and 'T :> ValueType> = { Handle : int target : BufferTarget size : int dataSize : int data : 'T [] pos : int usage : BufferUsageHint } type VBO = static member Create(target, size, pos, usage, (data : Vector3 [])) = VBO.CreateImpl(target, size, pos, usage, Vector2.SizeInBytes, data) // Type mismatch. Expecting Vector3 but found Vector2 static member Create(target, size, pos, usage, (data : Vector2 [])) = VBO.CreateImpl(target, size, pos, usage, Vector2.SizeInBytes, data) // This construct causes code to be less generic than indicated by the type annotations. // The type variable 'T has been constrained to be type 'Vector3'. static member CreateImpl(target, size, pos, usage, dataSize, (data : 'T [])) = let h = GL.GenBuffer() { Handle = h target = target size = size dataSize = dataSize data = data pos = pos usage = usage } ``` F# tries to constrain my code but I want it to be generic. I don't really care about what type the data is I just need it pass in the correct dataSize. What have I done wrong?

Original source