Dereferencing static pointer arising from polymorphic function works when it probably shouldn't
I was investigating the treatment of type variables in the static pointers extension to work out how they dealt with free type variables and I realised that despite some care taken to emit a Typeable
constraint the definition of closed does not extend to type variables. This means you can dereference a static pointer at a different instantiation of a type without any ill effects.
Starting from the expression
foo = static id
Firstly note that id
is not a closed term because
the inferred type is
foo = static id :: Typeable a => StaticPtr (a -> a)
The a
is floated outside of the static
bracket and hence the id @a
is not closed.
Then I instantiate a
with a type such as Bool
, foo @Bool :: StaticPtr (Bool -> Bool)
. So foo @Bool
is a StaticPtr
which contains a function Bool -> Bool
.
However, if I lookup foo
at a different type then my program doesn't segfault.
-- But now we look it up as `Int -> Int`
foo4 :: IO (Maybe (StaticPtr (Int -> Int)))
foo4 = unsafeLookupStaticPtr (staticKey (foo @Bool))
-- And it works fine..
foo5 :: IO Int
foo5 = do
Just sp <- foo4
return $ (deRefStaticPtr sp) 5
This seems dubious to me. Bad things should happen if the type of StaticPtr
which you try to coerce to is a different type to the static form itself. At least a segfault would be appropriate here.
It is also very ad-hoc how it is claimed that only closed terms are allowed to appear in static
forms but this definition of closed does not extend to type variables. The manual is also silent on this and even about the purpose of the Typeable
constraint to begin with.
Code: https://gist.github.com/mpickering/c87616b68d73a89f95adc97971eabc01