-
-
Notifications
You must be signed in to change notification settings - Fork 368
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix a bug in tactics preventing split of split (#520)
The `auto` tactic attempts to prune unhelpful branches in order to avoid an exponential blowup of search space. On one these optimizations is to not build a data constructor if it doesn't result in new types to solve. For example, we're trying to avoid the following pathological example: ```haskell data Tree a = Leaf a | Branch (Tree a) (Tree a) -- given the following hole: pureTree :: a -> Tree a pureTree a = _ -- we DO NOT want to fill it with pureTree a = Branch _ _ ``` The reasoning here is that both goals in `Branch _ _` have type `Tree a`, which is already the type we're trying to solve, so introducing `Branch` doesn't make any progress. This check is performed in the `splitAuto` tactic, but I got it backwards and it wasn't explicitly tested for. The only code which hit it was `pure @[]` --- but because `[]` doesn't have any subgoals, this hit a vacuous case and flipped the result of the bad logic. Two wrongs made a hard to find bug. This PR: 1. Fixes the reversed logic in `splitAuto` 2. Has a special case for nullary data constructors, fixing the bug cause by vacuousness. 3. Adds property tests ensuring we can `auto` our way through any permutation of a tuple (which is where we originally noticed the bug) 4. Prevents `unsafeRender` from crashing when `unsafeGlobalDynFlags` is unset, such as during testing. 5. Moves tactic solution tracing into the plugin, so it won't run during tests.
- Loading branch information
Showing
13 changed files
with
151 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
{-# OPTIONS_GHC -fno-warn-orphans #-} | ||
|
||
module AutoTupleSpec where | ||
|
||
import Data.Either (isRight) | ||
import qualified Data.Map as M | ||
import Ide.Plugin.Tactic.Debug | ||
import Ide.Plugin.Tactic.Judgements (mkFirstJudgement) | ||
import Ide.Plugin.Tactic.Machinery | ||
import Ide.Plugin.Tactic.Tactics (auto') | ||
import Ide.Plugin.Tactic.Types | ||
import OccName (mkVarOcc) | ||
import Test.Hspec | ||
import Test.QuickCheck | ||
import Type (mkTyVarTy) | ||
import TysPrim (alphaTyVars) | ||
import TysWiredIn (mkBoxedTupleTy) | ||
|
||
|
||
instance Show Type where | ||
show = unsafeRender | ||
|
||
|
||
spec :: Spec | ||
spec = describe "auto for tuple" $ do | ||
it "should always be able to discover an auto solution" $ do | ||
property $ do | ||
-- Pick some number of variables | ||
n <- choose (1, 7) | ||
let vars = fmap mkTyVarTy $ take n alphaTyVars | ||
-- Pick a random ordering | ||
in_vars <- shuffle vars | ||
-- Randomly associate them into tuple types | ||
in_type <- mkBoxedTupleTy | ||
. fmap mkBoxedTupleTy | ||
<$> randomGroups in_vars | ||
out_type <- mkBoxedTupleTy | ||
. fmap mkBoxedTupleTy | ||
<$> randomGroups vars | ||
pure $ | ||
-- We should always be able to find a solution | ||
runTactic | ||
(Context [] []) | ||
(mkFirstJudgement | ||
(M.singleton (mkVarOcc "x") $ CType in_type) | ||
True | ||
mempty | ||
out_type) | ||
(auto' $ n * 2) `shouldSatisfy` isRight | ||
|
||
|
||
randomGroups :: [a] -> Gen [[a]] | ||
randomGroups [] = pure [] | ||
randomGroups as = do | ||
n <- choose (1, length as) | ||
(:) <$> pure (take n as) | ||
<*> randomGroups (drop n as) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{-# OPTIONS_GHC -F -pgmF hspec-discover -optF --module-name=Main #-} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
-- There used to be a bug where we were unable to perform a nested split. The | ||
-- more serious regression test of this is 'AutoTupleSpec'. | ||
bigTuple :: (a, b, c, d) -> (a, b, (c, d)) | ||
bigTuple = _ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
-- There used to be a bug where we were unable to perform a nested split. The | ||
-- more serious regression test of this is 'AutoTupleSpec'. | ||
bigTuple :: (a, b, c, d) -> (a, b, (c, d)) | ||
bigTuple = (\ pabcd -> case pabcd of { (a, b, c, d) -> (a, b, (c, d)) }) |