Skip to content

Commit 2724d9b

Browse files
committed
Merge branch 'master' into declarative-custom-config
2 parents 0960bb7 + a34d927 commit 2724d9b

File tree

9 files changed

+92
-20
lines changed

9 files changed

+92
-20
lines changed

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import ConLike
1313
import Control.Lens ((%~), (<>~), (&))
1414
import Control.Monad.Except
1515
import Control.Monad.State
16+
import Data.Bool (bool)
1617
import Data.Generics.Labels ()
1718
import Data.List
1819
import Data.Maybe (mapMaybe)
@@ -183,18 +184,19 @@ destructLambdaCase' f jdg = do
183184
------------------------------------------------------------------------------
184185
-- | Construct a data con with subgoals for each field.
185186
buildDataCon
186-
:: Judgement
187+
:: Bool -- Should we blacklist destruct?
188+
-> Judgement
187189
-> ConLike -- ^ The data con to build
188190
-> [Type] -- ^ Type arguments for the data con
189191
-> RuleM (Synthesized (LHsExpr GhcPs))
190-
buildDataCon jdg dc tyapps = do
192+
buildDataCon should_blacklist jdg dc tyapps = do
191193
let args = conLikeInstOrigArgTys' dc tyapps
192194
ext
193195
<- fmap unzipTrace
194196
$ traverse ( \(arg, n) ->
195197
newSubgoal
196198
. filterSameTypeFromOtherPositions dc n
197-
. blacklistingDestruct
199+
. bool id blacklistingDestruct should_blacklist
198200
. flip withNewGoal jdg
199201
$ CType arg
200202
) $ zip args [0..]

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/Machinery.hs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ runTactic ctx jdg t =
8787
RunTacticResults
8888
{ rtr_trace = syn_trace syn
8989
, rtr_extract = simplify $ syn_val syn
90-
, rtr_other_solns = reverse . fmap fst $ take 5 sorted
90+
, rtr_other_solns = reverse . fmap fst $ sorted
9191
, rtr_jdg = jdg
9292
, rtr_ctx = ctx
9393
}
@@ -223,6 +223,16 @@ unify goal inst = do
223223
Nothing -> throwError (UnificationError inst goal)
224224

225225

226+
------------------------------------------------------------------------------
227+
-- | Prefer the first tactic to the second, if the bool is true. Otherwise, just run the second tactic.
228+
--
229+
-- This is useful when you have a clever pruning solution that isn't always
230+
-- applicable.
231+
attemptWhen :: TacticsM a -> TacticsM a -> Bool -> TacticsM a
232+
attemptWhen _ t2 False = t2
233+
attemptWhen t1 t2 True = commit t1 t2
234+
235+
226236
------------------------------------------------------------------------------
227237
-- | Get the class methods of a 'PredType', correctly dealing with
228238
-- instantiation of quantified class types.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ mkWorkspaceEdits
139139
-> Either UserFacingMessage WorkspaceEdit
140140
mkWorkspaceEdits span dflags ccs uri pm rtr = do
141141
for_ (rtr_other_solns rtr) $ \soln -> do
142-
traceMX "other solution" soln
142+
traceMX "other solution" $ syn_val soln
143143
traceMX "with score" $ scoreSolution soln (rtr_jdg rtr) []
144144
traceMX "solution" $ rtr_extract rtr
145145
let g = graftHole (RealSrcSpan span) rtr

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

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ intros = rule $ \jdg -> do
108108
destructAuto :: HyInfo CType -> TacticsM ()
109109
destructAuto hi = requireConcreteHole $ tracing "destruct(auto)" $ do
110110
jdg <- goal
111-
let subtactic = rule $ destruct' (const subgoal) hi
111+
let subtactic = destructOrHomoAuto hi
112112
case isPatternMatch $ hi_provenance hi of
113113
True ->
114114
pruning subtactic $ \jdgs ->
@@ -121,6 +121,25 @@ destructAuto hi = requireConcreteHole $ tracing "destruct(auto)" $ do
121121
False -> subtactic
122122

123123

124+
------------------------------------------------------------------------------
125+
-- | When running auto, in order to prune the auto search tree, we try
126+
-- a homomorphic destruct whenever possible. If that produces any results, we
127+
-- can probably just prune the other side.
128+
destructOrHomoAuto :: HyInfo CType -> TacticsM ()
129+
destructOrHomoAuto hi = tracing "destructOrHomoAuto" $ do
130+
jdg <- goal
131+
let g = unCType $ jGoal jdg
132+
ty = unCType $ hi_type hi
133+
134+
attemptWhen
135+
(rule $ destruct' (\dc jdg ->
136+
buildDataCon False jdg dc $ snd $ splitAppTys g) hi)
137+
(rule $ destruct' (const subgoal) hi)
138+
$ case (splitTyConApp_maybe g, splitTyConApp_maybe ty) of
139+
(Just (gtc, _), Just (tytc, _)) -> gtc == tytc
140+
_ -> False
141+
142+
124143
------------------------------------------------------------------------------
125144
-- | Case split, and leave holes in the matches.
126145
destruct :: HyInfo CType -> TacticsM ()
@@ -132,7 +151,7 @@ destruct hi = requireConcreteHole $ tracing "destruct(user)" $
132151
-- | Case split, using the same data constructor in the matches.
133152
homo :: HyInfo CType -> TacticsM ()
134153
homo = requireConcreteHole . tracing "homo" . rule . destruct' (\dc jdg ->
135-
buildDataCon jdg dc $ snd $ splitAppTys $ unCType $ jGoal jdg)
154+
buildDataCon False jdg dc $ snd $ splitAppTys $ unCType $ jGoal jdg)
136155

137156

138157
------------------------------------------------------------------------------
@@ -147,7 +166,7 @@ homoLambdaCase :: TacticsM ()
147166
homoLambdaCase =
148167
tracing "homoLambdaCase" $
149168
rule $ destructLambdaCase' $ \dc jdg ->
150-
buildDataCon jdg dc
169+
buildDataCon False jdg dc
151170
. snd
152171
. splitAppTys
153172
. unCType
@@ -242,7 +261,7 @@ splitConLike dc =
242261
let g = jGoal jdg
243262
case splitTyConApp_maybe $ unCType g of
244263
Just (_, apps) -> do
245-
buildDataCon (unwhitelistingSplit jdg) dc apps
264+
buildDataCon True (unwhitelistingSplit jdg) dc apps
246265
Nothing -> throwError $ GoalMismatch "splitDataCon" g
247266

248267
------------------------------------------------------------------------------
@@ -339,9 +358,7 @@ overFunctions =
339358

340359
overAlgebraicTerms :: (HyInfo CType -> TacticsM ()) -> TacticsM ()
341360
overAlgebraicTerms =
342-
attemptOn $ filter (isJust . algebraicTyCon . unCType . hi_type)
343-
. unHypothesis
344-
. jHypothesis
361+
attemptOn jAcceptableDestructTargets
345362

346363

347364
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
@@ -240,6 +240,10 @@ instance Uniquable a => Ord (Uniquely a) where
240240
compare = nonDetCmpUnique `on` getUnique . getViaUnique
241241

242242

243+
-- NOTE(sandy): The usage of list here is mostly for convenience, but if it's
244+
-- ever changed, make sure to correspondingly update
245+
-- 'jAcceptableDestructTargets' so that it correctly identifies newly
246+
-- introduced terms.
243247
newtype Hypothesis a = Hypothesis
244248
{ unHypothesis :: [HyInfo a]
245249
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ spec = do
4949
autoTest 9 12 "AutoEndo.hs"
5050
autoTest 2 16 "AutoEmptyString.hs"
5151
autoTest 7 35 "AutoPatSynUse.hs"
52+
autoTest 2 28 "AutoZip.hs"
5253

5354
failing "flaky in CI" $
5455
autoTest 2 11 "GoldenApplicativeThen.hs"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
zip_it_up_and_zip_it_out :: [a] -> [b] -> [(a, b)]
2+
zip_it_up_and_zip_it_out = _
3+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
zip_it_up_and_zip_it_out :: [a] -> [b] -> [(a, b)]
2+
zip_it_up_and_zip_it_out _ [] = []
3+
zip_it_up_and_zip_it_out [] (_ : _) = []
4+
zip_it_up_and_zip_it_out (a : l_a5) (b : l_b3)
5+
= (a, b) : zip_it_up_and_zip_it_out l_a5 l_b3
6+

0 commit comments

Comments
 (0)