Skip to content

Commit 173efb6

Browse files
committed
Make deprecation pattern fully backward compatible
It turned out to be quite complicated: These patterns are used to deprecate import of wildly unsafe constructors from safe modules. There are two way in which they could be imported by user: > import Data.Vector...Mutable qualified > import Data.Vector...Mutable (MVector(..)) and we want to support both. But there's a problem. When pattern is exported separately > , MU.MVector > , pattern MVector `import ... MVector(..)` doesn't work. It can't find constructor. Separate pattern doesn't count. And if constructor is in scope then following export > , MU.MVector(MVector) will always export constructor even if it only visible qualified and there's pattern with same name. So there's only one way: use `MVector(MVector)` export, never allow unsafe constructor in scope in safe modules if they need to export pattern instead. This requires defining pattern and all safe functions which make use of constructor should be defined in separate unexported module.
1 parent 5a74209 commit 173efb6

11 files changed

Lines changed: 198 additions & 101 deletions

File tree

vector/src/Data/Vector/Mutable.hs

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121

2222
module Data.Vector.Mutable (
2323
-- * Mutable boxed vectors
24-
MVector, IOVector, STVector,
25-
pattern MVector,
24+
MVector(MVector), IOVector, STVector,
2625

2726
-- * Accessors
2827

@@ -74,42 +73,24 @@ module Data.Vector.Mutable (
7473
) where
7574

7675
import qualified Data.Vector.Generic.Mutable as G
77-
import Data.Vector.Mutable.Unsafe (MVector)
78-
import qualified Data.Vector.Mutable.Unsafe as U
79-
import Data.Primitive.Array
76+
import Data.Vector.Mutable.Pat
8077
import Control.Monad.Primitive
8178

82-
import Prelude( Ord, Bool, Ordering(..), Int, Maybe, (<$>) )
79+
import Prelude( Ord, Bool, Ordering(..), Int, Maybe )
8380

8481
#include "vector.h"
8582

86-
pattern MVector :: Int -> Int -> MutableArray s a -> MVector s a
87-
pattern MVector i j arr = U.MVector i j arr
88-
{-# COMPLETE MVector #-}
89-
{-# DEPRECATED MVector "Use MVector exported from \"Data.Vector.Mutable.Unsafe\"" #-}
9083

9184
type IOVector = MVector RealWorld
9285
type STVector s = MVector s
9386

9487

9588
-- Conversions - Arrays
96-
-- -----------------------------
97-
98-
-- | /O(n)/ Make a copy of a mutable array to a new mutable vector.
9989
--
100-
-- @since 0.12.2.0
101-
fromMutableArray :: PrimMonad m => MutableArray (PrimState m) a -> m (MVector (PrimState m) a)
102-
{-# INLINE fromMutableArray #-}
103-
fromMutableArray marr =
104-
let size = sizeofMutableArray marr
105-
in MVector 0 size <$> cloneMutableArray marr 0 size
106-
107-
-- | /O(n)/ Make a copy of a mutable vector into a new mutable array.
90+
-- fromMutableArray, toMutableArray defined in Data.Vector.Mutable.Pat
10891
--
109-
-- @since 0.12.2.0
110-
toMutableArray :: PrimMonad m => MVector (PrimState m) a -> m (MutableArray (PrimState m) a)
111-
{-# INLINE toMutableArray #-}
112-
toMutableArray (MVector offset size marr) = cloneMutableArray marr offset size
92+
-- See NOTE: [Constructor deprecation]
93+
11394

11495

11596
-- Length information
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{-# LANGUAGE PatternSynonyms #-}
2+
module Data.Vector.Mutable.Pat
3+
( MVector
4+
, pattern MVector
5+
, fromMutableArray
6+
, toMutableArray
7+
) where
8+
9+
import Control.Monad.Primitive
10+
import Data.Primitive.Array
11+
import qualified Data.Vector.Mutable.Unsafe as MU
12+
import Data.Vector.Mutable.Unsafe (MVector)
13+
14+
pattern MVector :: Int -> Int -> MutableArray s a -> MVector s a
15+
pattern MVector i j arr = MU.MVector i j arr
16+
{-# COMPLETE MVector #-}
17+
{-# DEPRECATED MVector "Use MVector exported from \"Data.Vector.Mutable.Unsafe\"" #-}
18+
19+
-- See NOTE: [Constructor deprecation]
20+
21+
-- | /O(n)/ Make a copy of a mutable array to a new mutable vector.
22+
--
23+
-- @since 0.12.2.0
24+
fromMutableArray :: PrimMonad m => MutableArray (PrimState m) a -> m (MVector (PrimState m) a)
25+
{-# INLINE fromMutableArray #-}
26+
fromMutableArray marr =
27+
let size = sizeofMutableArray marr
28+
in MU.MVector 0 size <$> cloneMutableArray marr 0 size
29+
30+
-- | /O(n)/ Make a copy of a mutable vector into a new mutable array.
31+
--
32+
-- @since 0.12.2.0
33+
toMutableArray :: PrimMonad m => MVector (PrimState m) a -> m (MutableArray (PrimState m) a)
34+
{-# INLINE toMutableArray #-}
35+
toMutableArray (MU.MVector offset size marr) = cloneMutableArray marr offset size

vector/src/Data/Vector/Primitive.hs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
module Data.Vector.Primitive (
2727
-- * Primitive vectors
28-
Vector, MVector(MVector), pattern Vector,
28+
Vector(Vector), MVector(MVector),
2929

3030
-- * Accessors
3131

@@ -164,12 +164,9 @@ module Data.Vector.Primitive (
164164

165165
import Control.Applicative (Applicative)
166166
import qualified Data.Vector.Generic as G
167-
import Data.Vector.Primitive.Unsafe (Vector,unsafeCoerceVector,unsafeCast)
168-
import qualified Data.Vector.Primitive.Unsafe as U
169-
import Data.Vector.Primitive.Mutable.Unsafe (MVector)
170-
import Data.Vector.Primitive.Mutable (pattern MVector)
167+
import Data.Vector.Primitive.Unsafe (unsafeCoerceVector,unsafeCast)
168+
import Data.Vector.Primitive.Pat
171169
import Data.Primitive ( Prim )
172-
import Data.Primitive.ByteArray
173170

174171
import Control.Monad.ST ( ST )
175172
import Control.Monad.Primitive
@@ -178,10 +175,6 @@ import Prelude
178175
( Eq, Ord, Num, Enum, Monoid, Traversable, Monad, Bool, Ordering(..), Int, Maybe, Either
179176
, (==))
180177

181-
pattern Vector :: Int -> Int -> ByteArray -> Vector a
182-
pattern Vector i j arr = U.Vector i j arr
183-
{-# COMPLETE Vector #-}
184-
{-# DEPRECATED Vector "Use Vector constructor exported from \"Data.Vector.Primitive.Unsafe\"" #-}
185178

186179
-- Length
187180
-- ------

vector/src/Data/Vector/Primitive/Mutable.hs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020

2121
module Data.Vector.Primitive.Mutable (
2222
-- * Mutable vectors of primitive types
23-
MVector, IOVector, STVector,
24-
pattern MVector,
23+
MVector(MVector), IOVector, STVector,
2524

2625
-- * Accessors
2726

@@ -73,22 +72,15 @@ module Data.Vector.Primitive.Mutable (
7372

7473
import qualified Data.Vector.Generic.Mutable as G
7574
import Data.Primitive ( Prim )
76-
import Data.Primitive.ByteArray
77-
import Data.Vector.Primitive.Mutable.Unsafe
78-
(MVector,unsafeCoerceMVector,unsafeCast)
79-
import qualified Data.Vector.Primitive.Mutable.Unsafe as U
75+
import Data.Vector.Primitive.Mutable.Unsafe (unsafeCoerceMVector,unsafeCast)
76+
import Data.Vector.Primitive.Pat
8077
import Control.Monad.Primitive
8178

8279
import Prelude ( Ord, Bool, Int, Maybe, Ordering(..) )
8380

8481
#include "vector.h"
8582

8683

87-
pattern MVector :: Int -> Int -> MutableByteArray s -> MVector s a
88-
pattern MVector i j arr = U.MVector i j arr
89-
{-# COMPLETE MVector #-}
90-
{-# DEPRECATED MVector "Use MVector exported from \"Data.Vector.Primitive.Mutable.Unsafe\"" #-}
91-
9284
type IOVector = MVector RealWorld
9385
type STVector s = MVector s
9486

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{-# LANGUAGE PatternSynonyms #-}
2+
module Data.Vector.Primitive.Pat
3+
( Vector
4+
, pattern Vector
5+
, MVector
6+
, pattern MVector
7+
) where
8+
9+
import Data.Primitive.ByteArray
10+
import qualified Data.Vector.Primitive.Unsafe as U
11+
import Data.Vector.Primitive.Unsafe (Vector)
12+
import qualified Data.Vector.Primitive.Mutable.Unsafe as MU
13+
import Data.Vector.Primitive.Mutable.Unsafe (MVector)
14+
15+
pattern Vector :: Int -> Int -> ByteArray -> Vector a
16+
pattern Vector i j arr = U.Vector i j arr
17+
{-# COMPLETE Vector #-}
18+
{-# DEPRECATED Vector "Use Vector constructor exported from \"Data.Vector.Primitive.Unsafe\"" #-}
19+
20+
pattern MVector :: Int -> Int -> MutableByteArray s -> MVector s a
21+
pattern MVector i j arr = MU.MVector i j arr
22+
{-# COMPLETE MVector #-}
23+
{-# DEPRECATED MVector "Use MVector exported from \"Data.Vector.Primitive.Mutable.Unsafe\"" #-}
24+
25+
26+
-- NOTE: [Constructor deprecation]
27+
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28+
--
29+
-- These patterns are used to deprecate import of wildly unsafe
30+
-- constructors from safe modules. There are two way in which they
31+
-- could be imported by user:
32+
-- > import Data.Vector...Mutable qualified
33+
-- > import Data.Vector...Mutable (MVector(..))
34+
-- and we want to support both.
35+
--
36+
--
37+
-- But there's a problem. When pattern is exported separately
38+
-- > , MU.MVector
39+
-- > , pattern MVector
40+
--
41+
-- `import ... MVector(..)` doesn't work. It can't find constructor.
42+
-- Separate pattern doesn't count.
43+
--
44+
--
45+
-- And if constructor is in scope then following export
46+
-- > , MU.MVector(MVector)
47+
--
48+
-- will always export constructor even if it only visible qualified
49+
-- and there's pattern with same name.
50+
--
51+
--
52+
-- So there's only one way: use `MVector(MVector)` export, never allow
53+
-- unsafe constructor in scope in safe modules if they need to export
54+
-- pattern instead.
55+
--
56+
-- This requires defining pattern and all safe functions which make
57+
-- use of constructor should be defined in separate unexported module.

vector/src/Data/Vector/Storable/Mutable.hs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121

2222
module Data.Vector.Storable.Mutable(
2323
-- * Mutable vectors of 'Storable' types
24-
MVector, IOVector, STVector,
25-
pattern MVector,
24+
MVector(MVector), IOVector, STVector,
2625

2726
-- * Accessors
2827

@@ -80,25 +79,18 @@ module Data.Vector.Storable.Mutable(
8079

8180
import qualified Data.Vector.Generic.Mutable as G
8281
import Data.Vector.Storable.Mutable.Unsafe(
83-
MVector,IOVector,STVector,unsafeCast,unsafeWith,unsafeCoerceMVector,
82+
IOVector,STVector,unsafeCast,unsafeWith,unsafeCoerceMVector,
8483
unsafeToForeignPtr,unsafeToForeignPtr0,unsafeFromForeignPtr,unsafeFromForeignPtr0)
85-
import qualified Data.Vector.Storable.Mutable.Unsafe as U
84+
import Data.Vector.Storable.Pat
8685
import Foreign.Storable
8786

8887
import Control.Monad.Primitive
89-
import Foreign.ForeignPtr (ForeignPtr)
9088

9189
import Prelude (Int, Ord, Bool, Maybe, Ordering(..) )
9290

9391
#include "vector.h"
9492

9593

96-
pattern MVector :: Int -> ForeignPtr a -> MVector s a
97-
pattern MVector i ptr = U.MVector i ptr
98-
{-# COMPLETE MVector #-}
99-
{-# DEPRECATED MVector "Use MVector exported from Data.Vector.Strict.Mutable.Unsafe" #-}
100-
101-
10294
-- Length information
10395
-- ------------------
10496

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{-# LANGUAGE PatternSynonyms #-}
2+
module Data.Vector.Storable.Pat
3+
( MVector
4+
, pattern MVector
5+
) where
6+
7+
import Foreign.ForeignPtr
8+
import qualified Data.Vector.Storable.Mutable.Unsafe as MU
9+
import Data.Vector.Storable.Mutable.Unsafe (MVector)
10+
11+
12+
pattern MVector :: Int -> ForeignPtr a -> MVector s a
13+
pattern MVector i ptr = MU.MVector i ptr
14+
{-# COMPLETE MVector #-}
15+
{-# DEPRECATED MVector "Use MVector exported from Data.Vector.Strict.Mutable.Unsafe" #-}
16+
17+
-- See NOTE: [Constructor deprecation]

vector/src/Data/Vector/Strict/Mutable.hs

Lines changed: 9 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@
2525
-- are set to ⊥.
2626
module Data.Vector.Strict.Mutable (
2727
-- * Mutable boxed vectors
28-
MVector, IOVector, STVector,
29-
pattern MVector,
28+
MVector(MVector), IOVector, STVector,
3029

3130
-- * Accessors
3231

@@ -78,64 +77,30 @@ module Data.Vector.Strict.Mutable (
7877
PrimMonad, PrimState, RealWorld
7978
) where
8079

81-
import Data.Primitive.Array
8280
import qualified Data.Vector.Generic.Mutable as G
83-
import qualified Data.Vector.Mutable as MV
84-
import Data.Vector.Strict.Mutable.Unsafe (MVector)
85-
import qualified Data.Vector.Strict.Mutable.Unsafe as U
81+
import Data.Vector.Strict.Pat
8682
import Control.Monad.Primitive
8783

88-
import Prelude ( Ord, Bool, Int, Maybe, Ordering(..), Monad(..), (<$>), ($))
84+
import Prelude ( Ord, Bool, Int, Maybe, Ordering(..) )
8985

9086
#include "vector.h"
9187

92-
pattern MVector :: MV.MVector s a -> MVector s a
93-
pattern MVector v = U.MVector v
94-
{-# COMPLETE MVector #-}
95-
{-# DEPRECATED MVector "Use MVector constructor exported from \"Data.Vector.Strict.Unsafe\"" #-}
96-
9788
type IOVector = MVector RealWorld
9889
type STVector s = MVector s
9990

10091

10192
-- Conversions - Lazy vectors
102-
-- -----------------------------
103-
104-
-- | /O(1)/ Convert strict mutable vector to lazy mutable
105-
-- vector. Vectors will share mutable buffer
106-
toLazy :: MVector s a -> MV.MVector s a
107-
{-# INLINE toLazy #-}
108-
toLazy (MVector vec) = vec
109-
110-
-- | /O(n)/ Convert lazy mutable vector to strict mutable
111-
-- vector. Vectors will share mutable buffer. This function evaluates
112-
-- vector elements to WHNF.
113-
fromLazy :: PrimMonad m => MV.MVector (PrimState m) a -> m (MVector (PrimState m) a)
114-
fromLazy mvec = stToPrim $ do
115-
G.foldM' (\_ !_ -> return ()) () mvec
116-
return $ MVector mvec
93+
--
94+
-- toLazy, fromLazy are defined in Data.Vector.Strict.Pat
95+
--
96+
-- See NOTE: [Constructor deprecation]
11797

11898

11999
-- Conversions - Arrays
120-
-- -----------------------------
121-
122-
-- | /O(n)/ Make a copy of a mutable array to a new mutable
123-
-- vector. All elements of a vector are evaluated to WHNF
124100
--
125-
-- @since 0.13.2.0
126-
fromMutableArray :: PrimMonad m => MutableArray (PrimState m) a -> m (MVector (PrimState m) a)
127-
{-# INLINE fromMutableArray #-}
128-
fromMutableArray marr = stToPrim $ do
129-
mvec <- MVector <$> MV.fromMutableArray marr
130-
G.foldM' (\_ !_ -> return ()) () mvec
131-
return mvec
132-
133-
-- | /O(n)/ Make a copy of a mutable vector into a new mutable array.
101+
-- fromMutableArray, toMutableArray are defined in Data.Vector.Strict.Pat
134102
--
135-
-- @since 0.13.2.0
136-
toMutableArray :: PrimMonad m => MVector (PrimState m) a -> m (MutableArray (PrimState m) a)
137-
{-# INLINE toMutableArray #-}
138-
toMutableArray (MVector v) = MV.toMutableArray v
103+
-- See NOTE: [Constructor deprecation]
139104

140105

141106
-- Length information

0 commit comments

Comments
 (0)