summaryrefslogtreecommitdiff
path: root/libraries/ghc-prim/GHC/Prim/PtrEq.hs
blob: b552eee0b374718ca1f923a2a5a4f14182dfa3f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
{-# LANGUAGE Unsafe #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  GHC.Prim.PtrEq
-- License     :  see libraries/ghc-prim/LICENSE
--
-- Maintainer  :  cvs-ghc@haskell.org
-- Stability   :  internal
-- Portability :  non-portable (GHC Extensions)
--
-- Comparing underlying pointers for equality.
--
-- Use GHC.Exts from the base package instead of importing this
-- module directly.
--
-----------------------------------------------------------------------------

module GHC.Prim.PtrEq
  ( reallyUnsafePtrEquality,
    unsafePtrEquality#,
    sameArray#,
    sameMutableArray#,
    sameSmallArray#,
    sameSmallMutableArray#,
    sameByteArray#,
    sameMutableByteArray#,
    sameMutVar#,
    sameTVar#,
    sameMVar#,
    sameIOPort#,
    samePromptTag#,
    eqStableName#
  ) where

import GHC.Prim
import GHC.Types -- Also make implicit dependency known to build system
  ( RuntimeRep(BoxedRep), UnliftedType )
default () -- Double and Integer aren't available yet

{- **********************************************************************
*                                                                       *
*                        Pointer equality                               *
*                                                                       *
********************************************************************** -}

{- Note [Pointer equality operations]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Many primitive types - such as Array#, ByteArray#, MVar#, ... - are boxed:
they are represented by pointers to the underlying data. It is thus possible
to directly compare these pointers for equality, as opposed to comparing
the underlying data that the pointers refer to (for instance, comparing
two arrays element-wise).

To do this, GHC provides the primop reallyUnsafePtrEquality#, which is
both levity-polymorphic and heterogeneous. As its name indicates, it is an
unsafe operation which can yield unpredictable results, as explained in
Note [Pointer comparison operations] in primops.txt.pp

For a more user-friendly interface, this module defines specialisations of
the reallyUnsafePtrEquality# primop at various primitive types, such as
Array#, ByteArray#, MVar#, ...
-}

-- | Compare the underlying pointers of two values for equality.
--
-- Returns @1@ if the pointers are equal and @0@ otherwise.
--
-- The two values must be of the same type, of kind 'Type'.
-- See also 'GHC.Exts.reallyUnsafePtrEquality#', which doesn't have
-- such restrictions.
reallyUnsafePtrEquality :: a -> a -> Int#
reallyUnsafePtrEquality = reallyUnsafePtrEquality#
-- See Note [Pointer comparison operations]
--   in primops.txt.pp

-- | Compare the underlying pointers of two unlifted values for equality.
--
-- This is less dangerous than 'reallyUnsafePtrEquality',
-- since the arguments are guaranteed to be evaluated.
-- This means there is no risk of accidentally comparing
-- a thunk.
-- It's however still more dangerous than e.g. 'sameArray#'.
--
unsafePtrEquality# :: forall (a :: UnliftedType) (b :: UnliftedType). a -> b -> Int#
unsafePtrEquality# = reallyUnsafePtrEquality#
-- See Note [Pointer comparison operations]
--   in primops.txt.pp

-- | Compare the underlying pointers of two arrays.
sameArray# :: forall {l} (a :: TYPE (BoxedRep l)). Array# a -> Array# a -> Int#
sameArray# = unsafePtrEquality#

-- | Compare the underlying pointers of two mutable arrays.
sameMutableArray# :: forall {l} s (a :: TYPE (BoxedRep l)). MutableArray# s a -> MutableArray# s a -> Int#
sameMutableArray# = unsafePtrEquality#

-- | Compare the underlying pointers of two small arrays.
sameSmallArray# :: forall {l} (a :: TYPE (BoxedRep l)). SmallArray# a -> SmallArray# a -> Int#
sameSmallArray# = unsafePtrEquality#

-- | Compare the underlying pointers of two small mutable arrays.
sameSmallMutableArray# :: forall {l} s (a :: TYPE (BoxedRep l)). SmallMutableArray# s a -> SmallMutableArray# s a -> Int#
sameSmallMutableArray# = unsafePtrEquality#

-- | Compare the pointers of two byte arrays.
sameByteArray# :: ByteArray# -> ByteArray# -> Int#
sameByteArray# = unsafePtrEquality#

-- | Compare the underlying pointers of two mutable byte arrays.
sameMutableByteArray# :: MutableByteArray# s -> MutableByteArray# s -> Int#
sameMutableByteArray# = unsafePtrEquality#

-- | Compare the underlying pointers of two 'MutVar#'s.
sameMutVar# :: forall {l} s (a :: TYPE (BoxedRep l)). MutVar# s a -> MutVar# s a -> Int#
sameMutVar# = unsafePtrEquality#

-- | Compare the underlying pointers of two 'TVar#'s.
sameTVar# :: forall {l} s (a :: TYPE (BoxedRep l)). TVar# s a -> TVar# s a -> Int#
sameTVar# = unsafePtrEquality#

-- | Compare the underlying pointers of two 'MVar#'s.
sameMVar# :: forall {l} s (a :: TYPE (BoxedRep l)). MVar# s a -> MVar# s a -> Int#
sameMVar# = unsafePtrEquality#

-- | Compare the underlying pointers of two 'IOPort#'s.
sameIOPort# :: forall {l} s (a :: TYPE (BoxedRep l)). IOPort# s a -> IOPort# s a -> Int#
sameIOPort# = unsafePtrEquality#

-- | Compare the underlying pointers of two 'PromptTag#'s.
samePromptTag# :: forall a. PromptTag# a -> PromptTag# a -> Int#
samePromptTag# = unsafePtrEquality#

-- Note [Comparing stable names]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- A StableName# is actually a pointer to a stable name object (SNO)
-- containing an index into the stable name table (SNT). We
-- used to compare StableName#s by following the pointers to the
-- SNOs and checking whether they held the same SNT indices. However,
-- this is not necessary: there is a one-to-one correspondence
-- between SNOs and entries in the SNT, so simple pointer equality
-- does the trick.

-- | Compare two stable names for equality.
eqStableName# :: forall {k} {l} (a :: TYPE (BoxedRep k)) (b :: TYPE (BoxedRep l))
              . StableName# a -> StableName# b -> Int#
eqStableName# = unsafePtrEquality#