Skip to content

Commit a34d927

Browse files
Give a canonical ordering for destructing terms in Wingman (#1586)
* Use a canonical ordering when destructing terms * Fix introducing hypotheses in the wrong order Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent a19d125 commit a34d927

File tree

3 files changed

+42
-11
lines changed

3 files changed

+42
-11
lines changed

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

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import Development.IDE.Spans.LocalBindings
1616
import OccName
1717
import SrcLoc
1818
import Type
19+
import Wingman.GHC (algebraicTyCon)
1920
import Wingman.Types
2021

2122

@@ -61,7 +62,10 @@ withNewGoal t = field @"_jGoal" .~ t
6162

6263

6364
introduce :: Hypothesis a -> Judgement' a -> Judgement' a
64-
introduce hy = field @"_jHypothesis" <>~ hy
65+
-- NOTE(sandy): It's important that we put the new hypothesis terms first,
66+
-- since 'jAcceptableDestructTargets' will never destruct a pattern that occurs
67+
-- after a previously-destructed term.
68+
introduce hy = field @"_jHypothesis" %~ mappend hy
6569

6670

6771
------------------------------------------------------------------------------
@@ -149,7 +153,10 @@ findPositionVal :: Judgement' a -> OccName -> Int -> Maybe OccName
149153
findPositionVal jdg defn pos = listToMaybe $ do
150154
-- It's important to inspect the entire hypothesis here, as we need to trace
151155
-- ancstry through potentially disallowed terms in the hypothesis.
152-
(name, hi) <- M.toList $ M.map (overProvenance expandDisallowed) $ hyByName $ jEntireHypothesis jdg
156+
(name, hi) <- M.toList
157+
$ M.map (overProvenance expandDisallowed)
158+
$ hyByName
159+
$ jEntireHypothesis jdg
153160
case hi_provenance hi of
154161
TopLevelArgPrv defn' pos' _
155162
| defn == defn'
@@ -238,12 +245,13 @@ patternHypothesis scrutinee dc jdg
238245
= introduceHypothesis $ \_ pos ->
239246
PatternMatchPrv $
240247
PatVal
241-
scrutinee
242-
(maybe mempty
243-
(\scrut -> S.singleton scrut <> getAncestry jdg scrut)
244-
scrutinee)
245-
(Uniquely dc)
246-
pos
248+
scrutinee
249+
(maybe
250+
mempty
251+
(\scrut -> S.singleton scrut <> getAncestry jdg scrut)
252+
scrutinee)
253+
(Uniquely dc)
254+
pos
247255

248256

249257
------------------------------------------------------------------------------
@@ -285,6 +293,21 @@ jLocalHypothesis
285293
. jHypothesis
286294

287295

296+
------------------------------------------------------------------------------
297+
-- | Given a judgment, return the hypotheses that are acceptable to destruct.
298+
--
299+
-- We use the ordering of the hypothesis for this purpose. Since new bindings
300+
-- are always inserted at the beginning, we can impose a canonical ordering on
301+
-- which order to try destructs by what order they are introduced --- stopping
302+
-- at the first one we've already destructed.
303+
jAcceptableDestructTargets :: Judgement' CType -> [HyInfo CType]
304+
jAcceptableDestructTargets
305+
= filter (isJust . algebraicTyCon . unCType . hi_type)
306+
. takeWhile (not . isAlreadyDestructed . hi_provenance)
307+
. unHypothesis
308+
. jEntireHypothesis
309+
310+
288311
------------------------------------------------------------------------------
289312
-- | If we're in a top hole, the name of the defining function.
290313
isTopHole :: Context -> Judgement' a -> Maybe OccName
@@ -391,6 +414,12 @@ isDisallowed :: Provenance -> Bool
391414
isDisallowed DisallowedPrv{} = True
392415
isDisallowed _ = False
393416

417+
------------------------------------------------------------------------------
418+
-- | Has this term already been disallowed?
419+
isAlreadyDestructed :: Provenance -> Bool
420+
isAlreadyDestructed (DisallowedPrv AlreadyDestructed _) = True
421+
isAlreadyDestructed _ = False
422+
394423

395424
------------------------------------------------------------------------------
396425
-- | Eliminates 'DisallowedPrv' provenances.

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,9 +358,7 @@ overFunctions =
358358

359359
overAlgebraicTerms :: (HyInfo CType -> TacticsM ()) -> TacticsM ()
360360
overAlgebraicTerms =
361-
attemptOn $ filter (isJust . algebraicTyCon . unCType . hi_type)
362-
. unHypothesis
363-
. jHypothesis
361+
attemptOn jAcceptableDestructTargets
364362

365363

366364
allNames :: Judgement -> Set OccName

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ instance Uniquable a => Ord (Uniquely a) where
261261
compare = nonDetCmpUnique `on` getUnique . getViaUnique
262262

263263

264+
-- NOTE(sandy): The usage of list here is mostly for convenience, but if it's
265+
-- ever changed, make sure to correspondingly update
266+
-- 'jAcceptableDestructTargets' so that it correctly identifies newly
267+
-- introduced terms.
264268
newtype Hypothesis a = Hypothesis
265269
{ unHypothesis :: [HyInfo a]
266270
}

0 commit comments

Comments
 (0)