Skip to content

Commit b214231

Browse files
authored
Properly scope GADT equality evidence in the judgment (#1942)
* Properly scope GADT equality evidence in the judgment Fixes #1937 * Haddock and a bit of refactoring * Track coercions in a TCvSubst instead
1 parent 3f1a7df commit b214231

File tree

9 files changed

+43
-35
lines changed

9 files changed

+43
-35
lines changed

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ destructMatches use_field_puns f scrut t jdg = do
6868
-- #syn_scoped
6969
method_hy = foldMap evidenceToHypothesis ev
7070
args = conLikeInstOrigArgTys' con apps
71-
modify $ evidenceToSubst ev
72-
subst <- gets ts_unifier
7371
ctx <- ask
7472

7573
let names_in_scope = hyNamesInScope hy
@@ -80,7 +78,7 @@ destructMatches use_field_puns f scrut t jdg = do
8078
let hy' = patternHypothesis scrut con jdg
8179
$ zip names'
8280
$ coerce args
83-
j = fmap (CType . substTyAddInScope subst . unCType)
81+
j = withNewCoercions (evidenceToCoercions ev)
8482
$ introduce ctx hy'
8583
$ introduce ctx method_hy
8684
$ withNewGoal g jdg

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import OccName
1818
import SrcLoc
1919
import Type
2020
import Wingman.GHC (algebraicTyCon, normalizeType)
21+
import Wingman.Judgements.Theta
2122
import Wingman.Types
2223

2324

@@ -69,6 +70,15 @@ withNewGoal :: a -> Judgement' a -> Judgement' a
6970
withNewGoal t = field @"_jGoal" .~ t
7071

7172

73+
------------------------------------------------------------------------------
74+
-- | Add some new type equalities to the local judgement.
75+
withNewCoercions :: [(CType, CType)] -> Judgement -> Judgement
76+
withNewCoercions ev j =
77+
let subst = allEvidenceToSubst mempty $ coerce ev
78+
in fmap (CType . substTyAddInScope subst . unCType) j
79+
& field @"j_coercion" %~ unionTCvSubst subst
80+
81+
7282
normalizeHypothesis :: Functor f => Context -> f CType -> f CType
7383
normalizeHypothesis = fmap . coerce . normalizeType
7484

@@ -414,6 +424,7 @@ mkFirstJudgement ctx hy top goal =
414424
, _jWhitelistSplit = True
415425
, _jIsTopHole = top
416426
, _jGoal = CType goal
427+
, j_coercion = emptyTCvSubst
417428
}
418429

419430

plugins/hls-tactics-plugin/src/Wingman/Judgements/Theta.hs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@ module Wingman.Judgements.Theta
55
( Evidence
66
, getEvidenceAtHole
77
, mkEvidence
8+
, evidenceToCoercions
89
, evidenceToSubst
910
, evidenceToHypothesis
1011
, evidenceToThetaType
12+
, allEvidenceToSubst
1113
) where
1214

1315
import Class (classTyVars)
1416
import Control.Applicative (empty)
1517
import Control.Lens (preview)
18+
import Data.Coerce (coerce)
1619
import Data.Maybe (fromMaybe, mapMaybe, maybeToList)
1720
import Data.Generics.Sum (_Ctor)
1821
import Data.Set (Set)
@@ -109,14 +112,17 @@ allEvidenceToSubst skolems ((a, b) : evs) =
109112
$ allEvidenceToSubst skolems
110113
$ fmap (substPair subst) evs
111114

115+
------------------------------------------------------------------------------
116+
-- | Given some 'Evidence', get a list of which types are now equal.
117+
evidenceToCoercions :: [Evidence] -> [(CType, CType)]
118+
evidenceToCoercions = coerce . mapMaybe (preview $ _Ctor @"EqualityOfTypes")
119+
112120
------------------------------------------------------------------------------
113121
-- | Update our knowledge of which types are equal.
114122
evidenceToSubst :: [Evidence] -> TacticState -> TacticState
115123
evidenceToSubst evs ts =
116124
updateSubst
117-
(allEvidenceToSubst (ts_skolems ts)
118-
$ mapMaybe (preview $ _Ctor @"EqualityOfTypes")
119-
$ evs)
125+
(allEvidenceToSubst (ts_skolems ts) . coerce $ evidenceToCoercions evs)
120126
ts
121127

122128

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ substCTy :: TCvSubst -> CType -> CType
4040
substCTy subst = coerce . substTy subst . coerce
4141

4242

43+
getSubstForJudgement
44+
:: MonadState TacticState m
45+
=> Judgement
46+
-> m TCvSubst
47+
getSubstForJudgement j = do
48+
-- NOTE(sandy): It's OK to use mempty here, because coercions _can_ give us
49+
-- substitutions for skolems.
50+
let coercions = j_coercion j
51+
unifier <- gets ts_unifier
52+
pure $ unionTCvSubst unifier coercions
53+
4354
------------------------------------------------------------------------------
4455
-- | Produce a subgoal that must be solved before we can solve the original
4556
-- goal.
@@ -48,7 +59,7 @@ newSubgoal
4859
-> Rule
4960
newSubgoal j = do
5061
ctx <- ask
51-
unifier <- gets ts_unifier
62+
unifier <- getSubstForJudgement j
5263
subgoal
5364
$ normalizeJudgement ctx
5465
$ substJdg unifier

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import Control.Monad (unless)
1313
import Control.Monad.Except (throwError)
1414
import Control.Monad.Extra (anyM)
1515
import Control.Monad.Reader.Class (MonadReader (ask))
16-
import Control.Monad.State.Strict (StateT(..), runStateT, gets)
16+
import Control.Monad.State.Strict (StateT(..), runStateT)
1717
import Data.Bool (bool)
1818
import Data.Foldable
1919
import Data.Functor ((<&>))
@@ -72,6 +72,10 @@ assume name = rule $ \jdg -> do
7272
recursion :: TacticsM ()
7373
-- TODO(sandy): This tactic doesn't fire for the @AutoThetaFix@ golden test,
7474
-- presumably due to running afoul of 'requireConcreteHole'. Look into this!
75+
76+
-- TODO(sandy): There's a bug here! This should use the polymorphic defining
77+
-- types, not the ones available via 'getCurrentDefinitions'. As it is, this
78+
-- tactic doesn't support polymorphic recursion.
7579
recursion = requireConcreteHole $ tracing "recursion" $ do
7680
defs <- getCurrentDefinitions
7781
attemptOn (const defs) $ \(name, ty) -> markRecursion $ do
@@ -349,7 +353,7 @@ destructAll = do
349353
$ unHypothesis
350354
$ jHypothesis jdg
351355
for_ args $ \arg -> do
352-
subst <- gets ts_unifier
356+
subst <- getSubstForJudgement =<< goal
353357
destruct $ fmap (coerce substTy subst) arg
354358

355359
--------------------------------------------------------------------------------

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,9 @@ data Judgement' a = Judgement
297297
, _jWhitelistSplit :: !Bool
298298
, _jIsTopHole :: !Bool
299299
, _jGoal :: !a
300+
, j_coercion :: TCvSubst
300301
}
301-
deriving stock (Eq, Generic, Functor, Show)
302+
deriving stock (Generic, Functor, Show)
302303

303304
type Judgement = Judgement' CType
304305

@@ -328,7 +329,6 @@ data TacticError
328329
| TooPolymorphic
329330
| NotInScope OccName
330331
| TacticPanic String
331-
deriving stock (Eq)
332332

333333
instance Show TacticError where
334334
show (UndefinedHypothesis name) =

plugins/hls-tactics-plugin/test/CodeAction/RunMetaprogramSpec.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ spec = do
3333
metaTest 11 11 "MetaUseMethod"
3434
metaTest 9 38 "MetaCataCollapse"
3535
metaTest 7 16 "MetaCataCollapseUnary"
36-
metaTest 21 32 "MetaCataAST"
36+
metaTest 10 32 "MetaCataAST"
3737
metaTest 6 46 "MetaPointwise"
3838
metaTest 4 28 "MetaUseSymbol"

plugins/hls-tactics-plugin/test/golden/MetaCataAST.expected.hs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,8 @@ data AST a where
77
Equal :: AST a -> AST a -> AST Bool
88

99
eval :: AST a -> a
10-
-- NOTE(sandy): There is an unrelated bug that is shown off in this test
11-
-- namely, that
12-
--
13-
-- @eval (IntLit n) = _@
14-
--
15-
-- but should be
16-
--
17-
-- @eval (IntLit n) = n@
18-
--
19-
-- https://github.com/haskell/haskell-language-server/issues/1937
20-
2110
eval (BoolLit b) = b
22-
eval (IntLit n) = _
11+
eval (IntLit n) = n
2312
eval (If ast ast' ast_a)
2413
= let
2514
ast_c = eval ast

plugins/hls-tactics-plugin/test/golden/MetaCataAST.hs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,5 @@ data AST a where
77
Equal :: AST a -> AST a -> AST Bool
88

99
eval :: AST a -> a
10-
-- NOTE(sandy): There is an unrelated bug that is shown off in this test
11-
-- namely, that
12-
--
13-
-- @eval (IntLit n) = _@
14-
--
15-
-- but should be
16-
--
17-
-- @eval (IntLit n) = n@
18-
--
19-
-- https://github.com/haskell/haskell-language-server/issues/1937
20-
2110
eval = [wingman| intros x, cata x; collapse |]
2211

0 commit comments

Comments
 (0)