Skip to content

Cannot make a Storable instance #2556

@trinhtuanlong

Description

@trinhtuanlong

So I have a type that I want to make a Storable instance:

{-# LANGUAGE ScopedTypeVariables, RecordWildCards, DeriveFunctor, DeriveFoldable, DeriveTraversable #-}

module Renderer.DataTypes.Vec2 where

import Foreign.Ptr
import Foreign.Storable

data Vec2 a = Vec2
  { x :: a
  , y :: a
  } deriving (Show, Eq, Ord, Functor, Foldable, Traversable)

{-@ class measure size :: forall a. a -> {s: Int | s > 0} @-}
{-@ assume sizeOf :: Storable a => x:a -> {s: Nat | s = size x} @-}
instance Storable a => Storable (Vec2 a)
 {-@ instance Storable a => Storable (Vec2 a) where
       sizeOf :: v2:Vec2 a -> {v:Int | v == 2 * size (x v2)}
       alignment :: v2:Vec2 a -> {v:Int | v == size(x v2)}
       peek :: p:{Ptr (Vec2 a) | plen p >= size (deref p)} -> IO (Vec2 a)
       poke :: p:{Ptr (Vec2 a) | plen p >= size (deref p)} -> Vec2 a -> IO ()
 @-}
     where
  sizeOf _ = 2 * sizeOf (undefined :: a)
  alignment _ = sizeOf (undefined :: a)
  peek ptr = do
    let pBase = castPtr ptr
    xVal <- peek pBase
    yVal <- peekByteOff pBase $ sizeOf (undefined :: a)
    return $ Vec2 xVal yVal
  poke ptr Vec2 {..} = do
    let pBase = castPtr ptr
    poke pBase x
    pokeByteOff pBase (sizeOf (undefined :: a)) y

xx :: Vec2 a -> Vec2 a
xx Vec2 {..} = Vec2 x x

xy :: Vec2 a -> Vec2 a
xy Vec2 {..} = Vec2 x y

yx :: Vec2 a -> Vec2 a
yx Vec2 {..} = Vec2 y x

yy :: Vec2 a -> Vec2 a
yy Vec2 {..} = Vec2 y y

But liquidHaskell throws several errors:


**** LIQUID: UNSAFE ************************************************************

src/Renderer/DataTypes/Vec2.hs:15:10: error:
    Liquid Type Mismatch
    .
    The inferred type
      VV : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a))
    .
    is not a subtype of the required type
      VV : {VV##6256 : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | plen VV##6256 >= size (deref VV##6256)}
    .
    Constraint id 71
   |
15 | instance Storable a => Storable (Vec2 a)
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/Renderer/DataTypes/Vec2.hs:15:10: error:
    Liquid Type Mismatch
    .
    The inferred type
      VV : {v : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | v == ?a}
    .
    is not a subtype of the required type
      VV : {VV##6182 : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | plen VV##6182 >= size (deref VV##6182)}
    .
    in the context
      ?a : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a))
    Constraint id 62
   |
15 | instance Storable a => Storable (Vec2 a)
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/Renderer/DataTypes/Vec2.hs:26:25: error:
    Liquid Type Mismatch
    .
    The inferred type
      VV : {v : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | v == ptr##a2BA
                                                                 && plen v >= size (deref v)}
    .
    is not a subtype of the required type
      VV : {VV##6879 : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | 0 <= plen VV##6879}
    .
    in the context
      ptr##a2BA : {ptr##a2BA : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | plen ptr##a2BA >= size (deref ptr##a2BA)}
    Constraint id 124
   |
26 |     let pBase = castPtr ptr
   |                         ^^^

src/Renderer/DataTypes/Vec2.hs:27:13: error:
    Liquid Type Mismatch
    .
    The inferred type
      VV : {v : (GHC.Ptr.Ptr a) | v == GHC.Ptr.castPtr ptr##a2BA
                                  && plen v == plen ptr##a2BA
                                  && 0 <= plen v}
    .
    is not a subtype of the required type
      VV : {VV##6874 : (GHC.Ptr.Ptr a) | 0 < plen VV##6874}
    .
    in the context
      ptr##a2BA : {ptr##a2BA : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | plen ptr##a2BA >= size (deref ptr##a2BA)}
    Constraint id 121
   |
27 |     xVal <- peek pBase
   |             ^^^^^^^^^^

src/Renderer/DataTypes/Vec2.hs:31:25: error:
    Liquid Type Mismatch
    .
    The inferred type
      VV : {v : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | v == ptr##a2BE
                                                                 && plen v >= size (deref v)}
    .
    is not a subtype of the required type
      VV : {VV##7144 : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | 0 <= plen VV##7144}
    .
    in the context
      ptr##a2BE : {ptr##a2BE : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | plen ptr##a2BE >= size (deref ptr##a2BE)}
    Constraint id 146
   |
31 |     let pBase = castPtr ptr
   |                         ^^^

src/Renderer/DataTypes/Vec2.hs:32:5: error:
    Liquid Type Mismatch
    .
    The inferred type
      VV : {v : (GHC.Ptr.Ptr a) | v == GHC.Ptr.castPtr ptr##a2BE
                                  && plen v == plen ptr##a2BE
                                  && 0 <= plen v}
    .
    is not a subtype of the required type
      VV : {VV##7139 : (GHC.Ptr.Ptr a) | 0 < plen VV##7139}
    .
    in the context
      ptr##a2BE : {ptr##a2BE : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | plen ptr##a2BE >= size (deref ptr##a2BE)}
    Constraint id 143
   |
32 |     poke pBase x
   |     ^^^^^^^^^^^^

If I remove the annotations the errors are:

src/Renderer/DataTypes/Vec2.hs:15:10: error:
    Liquid Type Mismatch
    .
    The inferred type
      VV : {v : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | v == ?a}
    .
    is not a subtype of the required type
      VV : {VV##6298 : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | 0 < plen VV##6298}
    .
    in the context
      ?a : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a))
    Constraint id 62
   |
15 | instance Storable a => Storable (Vec2 a) where
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/Renderer/DataTypes/Vec2.hs:19:25: error:
    Liquid Type Mismatch
    .
    The inferred type
      VV : {v : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | v == ptr##a2BA}
    .
    is not a subtype of the required type
      VV : {VV##6918 : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | 0 <= plen VV##6918}
    .
    in the context
      ptr##a2BA : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a))
    Constraint id 137
   |
19 |     let pBase = castPtr ptr
   |                         ^^^

src/Renderer/DataTypes/Vec2.hs:20:13: error:
    Liquid Type Mismatch
    .
    The inferred type
      VV : {v : (GHC.Ptr.Ptr a) | v == GHC.Ptr.castPtr ptr##a2BA
                                  && plen v == plen ptr##a2BA
                                  && 0 <= plen v}
    .
    is not a subtype of the required type
      VV : {VV##6913 : (GHC.Ptr.Ptr a) | 0 < plen VV##6913}
    .
    in the context
      ptr##a2BA : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a))
    Constraint id 134
   |
20 |     xVal <- peek pBase
   |             ^^^^^^^^^^

src/Renderer/DataTypes/Vec2.hs:24:25: error:
    Liquid Type Mismatch
    .
    The inferred type
      VV : {v : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | v == ptr##a2BE}
    .
    is not a subtype of the required type
      VV : {VV##7133 : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a)) | 0 <= plen VV##7133}
    .
    in the context
      ptr##a2BE : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a))
    Constraint id 163
   |
24 |     let pBase = castPtr ptr
   |                         ^^^

src/Renderer/DataTypes/Vec2.hs:25:5: error:
    Liquid Type Mismatch
    .
    The inferred type
      VV : {v : (GHC.Ptr.Ptr a) | v == GHC.Ptr.castPtr ptr##a2BE
                                  && plen v == plen ptr##a2BE
                                  && 0 <= plen v}
    .
    is not a subtype of the required type
      VV : {VV##7128 : (GHC.Ptr.Ptr a) | 0 < plen VV##7128}
    .
    in the context
      ptr##a2BE : (GHC.Ptr.Ptr (Renderer.DataTypes.Vec2.Vec2 a))
    Constraint id 160
   |
25 |     poke pBase x
   |     ^^^^^^^^^^^^

It seems that I have to somehow inform the functions in this instance that Ptr (Vec2 a), or at least the ptr in peek and poke, would always have plen > 0, but how do I do this? I cannot find any examples anywhere.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions