{-# LANGUAGE DataKinds, MagicHash, RoleAnnotations #-}
module Data.Ref.Impl (module Data.Ref.Impl) where

import GHC.Base (MutVar#, RealWorld, sameMutVar#, isTrue#)

{-
The `r` parameter is deliberately nominal here, which prevents the use of
coerce to "safely" escape the lifetime of a reference:

> escape :: a -> RT (Ref r a)
> escape x = newRef x (return . coerce)

Would compile if the annotation was left as phantom (which is the inferred).
This is clearly not something we want to allow, so nominal it is.
-}
type role Ref nominal representational
-- Don't even expose the constructor, then it's pretty much safe?
data Ref r a = Ref (MutVar# RealWorld a)

-- It's nice that two references must clearly have the same lifetime to be equal
instance Eq (Ref r a) where
  Ref MutVar# RealWorld a
ref1# == :: Ref r a -> Ref r a -> Bool
== Ref MutVar# RealWorld a
ref2# = Int# -> Bool
isTrue# (MutVar# RealWorld a -> MutVar# RealWorld a -> Int#
forall s a. MutVar# s a -> MutVar# s a -> Int#
sameMutVar# MutVar# RealWorld a
ref1# MutVar# RealWorld a
ref2#)