Skip to content

Commit 0ca9093

Browse files
isovectormergify[bot]jneira
authored
Wingman: Add "New Unification Variable" helper (#2164)
* Add a newUnivar machinery, and strengthen unification tests * Get rid of explicit univar constructions * Cleanup AutoTupleSpec Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Javier Neira <atreyu.bbb@gmail.com>
1 parent 94ebd4d commit 0ca9093

File tree

4 files changed

+45
-23
lines changed

4 files changed

+45
-23
lines changed

plugins/hls-tactics-plugin/src/Wingman/Machinery.hs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ import Refinery.Tactic.Internal
3333
import System.Timeout (timeout)
3434
import TcType
3535
import Type (tyCoVarsOfTypeWellScoped)
36+
import TysPrim (alphaTyVar, alphaTy)
3637
import Wingman.Context (getInstance)
37-
import Wingman.GHC (tryUnifyUnivarsButNotSkolems, updateSubst, tacticsGetDataCons)
38+
import Wingman.GHC (tryUnifyUnivarsButNotSkolems, updateSubst, tacticsGetDataCons, freshTyvars)
3839
import Wingman.Judgements
3940
import Wingman.Simplify (simplify)
4041
import Wingman.Types
@@ -229,6 +230,12 @@ newtype Reward a = Reward a
229230
deriving (Eq, Ord, Show) via a
230231

231232

233+
------------------------------------------------------------------------------
234+
-- | Generate a unique unification variable.
235+
newUnivar :: MonadState TacticState m => m Type
236+
newUnivar = do
237+
freshTyvars $
238+
mkInvForAllTys [alphaTyVar] alphaTy
232239

233240

234241
------------------------------------------------------------------------------

plugins/hls-tactics-plugin/src/Wingman/Tactics.hs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import Refinery.Tactic
3636
import Refinery.Tactic.Internal
3737
import TcType
3838
import Type hiding (Var)
39-
import TysPrim (betaTy, alphaTy, betaTyVar, alphaTyVar)
4039
import Wingman.CodeGen
4140
import Wingman.GHC
4241
import Wingman.Judgements
@@ -543,10 +542,10 @@ applyByType ty = tracing ("applyByType " <> show ty) $ do
543542
-- | Make an n-ary function call of the form
544543
-- @(_ :: forall a b. a -> a -> b) _ _@.
545544
nary :: Int -> TacticsM ()
546-
nary n =
547-
applyByType $
548-
mkInvForAllTys [alphaTyVar, betaTyVar] $
549-
mkFunTys' (replicate n alphaTy) betaTy
545+
nary n = do
546+
a <- newUnivar
547+
b <- newUnivar
548+
applyByType $ mkFunTys' (replicate n a) b
550549

551550

552551
self :: TacticsM ()
@@ -589,8 +588,7 @@ letBind occs = do
589588
-> fmap (occ, )
590589
$ fmap (<$ jdg)
591590
$ fmap CType
592-
$ freshTyvars
593-
$ mkInvForAllTys [alphaTyVar] alphaTy
591+
$ newUnivar
594592
rule $ nonrecLet occ_tys
595593

596594

@@ -630,7 +628,7 @@ collapse = do
630628
with_arg :: TacticsM ()
631629
with_arg = rule $ \jdg -> do
632630
let g = jGoal jdg
633-
fresh_ty <- freshTyvars $ mkInvForAllTys [alphaTyVar] alphaTy
631+
fresh_ty <- newUnivar
634632
a <- newSubgoal $ withNewGoal (CType fresh_ty) jdg
635633
f <- newSubgoal $ withNewGoal (coerce mkFunTys' [fresh_ty] g) jdg
636634
pure $ fmap noLoc $ (@@) <$> fmap unLoc f <*> fmap unLoc a

plugins/hls-tactics-plugin/test/AutoTupleSpec.hs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44

55
module AutoTupleSpec where
66

7+
import Control.Monad (replicateM)
8+
import Control.Monad.State (evalState)
79
import Data.Either (isRight)
810
import OccName (mkVarOcc)
911
import System.IO.Unsafe
1012
import Test.Hspec
1113
import Test.QuickCheck
12-
import Type (mkTyVarTy)
13-
import TysPrim (alphaTyVars)
1414
import TysWiredIn (mkBoxedTupleTy)
1515
import Wingman.Judgements (mkFirstJudgement)
1616
import Wingman.Machinery
@@ -24,7 +24,8 @@ spec = describe "auto for tuple" $ do
2424
property $ do
2525
-- Pick some number of variables
2626
n <- choose (1, 7)
27-
let vars = fmap mkTyVarTy $ take n alphaTyVars
27+
let vars = flip evalState defaultTacticState
28+
$ replicateM n newUnivar
2829
-- Pick a random ordering
2930
in_vars <- shuffle vars
3031
-- Randomly associate them into tuple types

plugins/hls-tactics-plugin/test/UnificationSpec.hs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
module UnificationSpec where
55

66
import Control.Arrow
7+
import Control.Monad (replicateM, join)
8+
import Control.Monad.State (evalState)
79
import Data.Bool (bool)
810
import Data.Functor ((<&>))
911
import Data.Maybe (mapMaybe)
@@ -13,10 +15,9 @@ import Data.Tuple (swap)
1315
import TcType (substTy, tcGetTyVar_maybe)
1416
import Test.Hspec
1517
import Test.QuickCheck
16-
import Type (mkTyVarTy)
17-
import TysPrim (alphaTyVars)
1818
import TysWiredIn (mkBoxedTupleTy)
1919
import Wingman.GHC
20+
import Wingman.Machinery (newUnivar)
2021
import Wingman.Types
2122

2223

@@ -25,8 +26,11 @@ spec = describe "unification" $ do
2526
it "should be able to unify univars with skolems on either side of the equality" $ do
2627
property $ do
2728
-- Pick some number of unification vars and skolem
28-
n <- choose (1, 1)
29-
let (skolems, take n -> univars) = splitAt n $ fmap mkTyVarTy alphaTyVars
29+
n <- choose (1, 20)
30+
let (skolems, take n -> univars)
31+
= splitAt n
32+
$ flip evalState defaultTacticState
33+
$ replicateM (n * 2) newUnivar
3034
-- Randomly pair them
3135
skolem_uni_pairs <-
3236
for (zip skolems univars) randomSwap
@@ -42,13 +46,25 @@ spec = describe "unification" $ do
4246
(CType lhs)
4347
(CType rhs) of
4448
Just subst ->
45-
-- For each pair, running the unification over the univar should
46-
-- result in the skolem
47-
conjoin $ zip univars skolems <&> \(uni, skolem) ->
48-
let substd = substTy subst uni
49-
in counterexample (show substd) $
50-
counterexample (show skolem) $
51-
CType substd === CType skolem
49+
conjoin $ join $
50+
[ -- For each pair, running the unification over the univar should
51+
-- result in the skolem
52+
zip univars skolems <&> \(uni, skolem) ->
53+
let substd = substTy subst uni
54+
in counterexample (show substd) $
55+
counterexample (show skolem) $
56+
CType substd === CType skolem
57+
58+
-- And also, no two univars should equal to one another
59+
-- before or after substitution.
60+
, zip univars (tail univars) <&> \(uni1, uni2) ->
61+
let uni1_sub = substTy subst uni1
62+
uni2_sub = substTy subst uni2
63+
in counterexample (show uni1) $
64+
counterexample (show uni2) $
65+
CType uni1 =/= CType uni2 .&&.
66+
CType uni1_sub =/= CType uni2_sub
67+
]
5268
Nothing -> True === False
5369

5470

0 commit comments

Comments
 (0)