@@ -79,28 +79,37 @@ mapFromKeys keys = HM.fromList (zip keys (repeat ()))
79
79
------------------------------------------------------------------------
80
80
-- Issue #254
81
81
82
- data KC = KC Int
82
+ -- Key type that always collides.
83
+ newtype KC = KC Int
83
84
deriving (Eq , Ord , Show )
84
85
instance Hashable KC where
85
86
hashWithSalt salt _ = salt
86
87
87
88
issue254Lazy :: Assertion
88
89
issue254Lazy = issue254LazyLambda 2
89
90
90
- -- Important that oldV is not hoisted out by optimisation, so use NOINLINE
91
+ -- We want to make sure that old values in the HashMap are evicted when new values are inserted,
92
+ -- even if they aren't evaluated. To do that, we use the WeakPtr trick described at
93
+ -- http://simonmar.github.io/posts/2018-06-20-Finding-fixing-space-leaks.html.
94
+ -- We insert a value named oldV into the HashMap, then insert over it, checking oldV is no longer reachable.
95
+ --
96
+ -- To make the test robust, it's important that oldV isn't hoisted up to the top or shared. To do that,
97
+ -- we use NOINLINE, make oldV dependent on an unseen argument, and insert _ <- return () to ensure oldV
98
+ -- is under a lambda.
91
99
{-# NOINLINE issue254LazyLambda #-}
92
100
issue254LazyLambda :: Int -> Assertion
93
101
issue254LazyLambda i = do
94
102
_ <- return ()
95
- let oldV = show i
103
+ let oldV = error $ " Should not be evaluated: " ++ show i
96
104
weakV <- mkWeakPtr oldV Nothing
97
- let mp = HML. insert (KC 1 ) " 3 " $ HML. fromList [(KC 0 , " 1" ), (KC 1 , oldV)]
105
+ let mp = HML. insert (KC 1 ) ( error " Should not be evaluated " ) $ HML. fromList [(KC 0 , " 1" ), (KC 1 , oldV)]
98
106
_ <- evaluate mp
99
107
performGC
100
108
res <- deRefWeak weakV
101
109
_ <- evaluate mp
102
110
assert $ isNothing res
103
111
112
+ -- Like issue254Lazy, but using strict HashMap
104
113
issue254Strict :: Assertion
105
114
issue254Strict = issue254StrictLambda 2
106
115
0 commit comments