Hannes Siebenhandl pushed to branch wip/fendor/has-field-hie at Glasgow Haskell Compiler / GHC
Commits:
-
450f1c53
by fendor at 2026-09-17T11:42:53+02:00
-
5fe3c633
by fendor at 2026-09-17T11:43:34+02:00
-
c1afd18a
by fendor at 2026-09-17T11:44:34+02:00
-
dece0fbb
by fendor at 2026-09-17T11:44:37+02:00
12 changed files:
- + changelog.d/record-dot-evidence
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Ext/Types.hs
- compiler/GHC/Iface/Ext/Utils.hs
- compiler/GHC/Rename/Expr.hs
- testsuite/tests/hiefile/should_run/HasFieldQueries.stdout
- + testsuite/tests/hiefile/should_run/HieTypeable.hs
- + testsuite/tests/hiefile/should_run/HieTypeable.stdout
- testsuite/tests/hiefile/should_run/NoFieldSelectorQueries.stdout
- testsuite/tests/hiefile/should_run/RecordDotTypes.stdout
- testsuite/tests/hiefile/should_run/T23492.stdout
- testsuite/tests/hiefile/should_run/all.T
Changes:
| 1 | +section: compiler
|
|
| 2 | +synopsis: Record selector functions as evidence for `HasField` constraints during .hie file generation.
|
|
| 3 | +description: {
|
|
| 4 | + We record the record selector `foo` of an expression such as `f.foo` as evidence for
|
|
| 5 | + solving the constraint `HasField "foo" record ty`.
|
|
| 6 | + |
|
| 7 | + This allows us to point to the definition source location of the record selector `foo`, allowing
|
|
| 8 | + users to jump to definition using the evidence variables.
|
|
| 9 | +}
|
|
| 10 | + |
|
| 11 | +issues: #25418
|
|
| 12 | +mrs: !16694 |
| ... | ... | @@ -23,7 +23,6 @@ import GHC.Core.DataCon ( dataConWrapperType ) |
| 23 | 23 | import GHC.Core.Type ( Type, ForAllTyFlag(..) )
|
| 24 | 24 | import GHC.Core.TyCon ( TyCon, tyConClass_maybe )
|
| 25 | 25 | import GHC.Core.InstEnv
|
| 26 | -import GHC.Core.Predicate ( isEvId )
|
|
| 27 | 26 | |
| 28 | 27 | import GHC.Hs
|
| 29 | 28 | import GHC.Hs.Syn.Type
|
| ... | ... | @@ -33,7 +32,7 @@ import GHC.Types.Basic |
| 33 | 32 | import GHC.Types.UnresolvedImport ( isGeneratedImport )
|
| 34 | 33 | import GHC.Types.FieldLabel
|
| 35 | 34 | import GHC.Types.Avail ( Avails )
|
| 36 | -import GHC.Types.Id ( isDataConId_maybe )
|
|
| 35 | +import GHC.Types.Id ( isDataConId_maybe, isId, idDetails )
|
|
| 37 | 36 | import GHC.Types.Name ( Name, nameSrcSpan, nameUnique, wiredInNameTyThing_maybe, getName )
|
| 38 | 37 | import GHC.Types.Name.Env ( NameEnv, emptyNameEnv, extendNameEnv, lookupNameEnv )
|
| 39 | 38 | import GHC.Types.Name.Reader ( RecFieldInfo(..), WithUserRdr(..) )
|
| ... | ... | @@ -81,6 +80,7 @@ import Control.Applicative ( (<|>) ) |
| 81 | 80 | import GHC.Types.TypeEnv ( TypeEnv )
|
| 82 | 81 | import Control.Arrow ( second )
|
| 83 | 82 | import Data.Traversable ( mapAccumR )
|
| 83 | +import GHC.Types.Id.Info (IdDetails(..), recSelParentName)
|
|
| 84 | 84 | |
| 85 | 85 | {- Note [Updating HieAst for changes in the GHC AST]
|
| 86 | 86 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -682,7 +682,7 @@ instance ToHie (Context (Located (WithUserRdr Name))) where |
| 682 | 682 | |
| 683 | 683 | hieEvIdsOfTerm :: EvTerm -> [EvId]
|
| 684 | 684 | -- Returns only EvIds satisfying relevantEvId
|
| 685 | -hieEvIdsOfTerm = runFVSelectiveList isEvId . evTermFVs
|
|
| 685 | +hieEvIdsOfTerm = runFVSelectiveList isId . evTermFVs
|
|
| 686 | 686 | |
| 687 | 687 | instance ToHie (EvBindContext (LocatedA TcEvBinds)) where
|
| 688 | 688 | toHie (EvBindContext sc sp (L span (EvBinds bs)))
|
| ... | ... | @@ -690,7 +690,7 @@ instance ToHie (EvBindContext (LocatedA TcEvBinds)) where |
| 690 | 690 | where
|
| 691 | 691 | go evbind = do
|
| 692 | 692 | let evDeps = hieEvIdsOfTerm $ eb_rhs evbind
|
| 693 | - depNames = EvBindDeps $ map varName evDeps
|
|
| 693 | + depNames = EvBindDeps $ map classifyEvBindDep evDeps
|
|
| 694 | 694 | concatM $
|
| 695 | 695 | [ toHie (C (EvidenceVarBind (EvLetBind depNames) (combineScopes sc (mkScope span)) sp)
|
| 696 | 696 | (L span $ eb_lhs evbind))
|
| ... | ... | @@ -698,6 +698,12 @@ instance ToHie (EvBindContext (LocatedA TcEvBinds)) where |
| 698 | 698 | ]
|
| 699 | 699 | toHie _ = pure []
|
| 700 | 700 | |
| 701 | +classifyEvBindDep :: EvId -> EvBindDep
|
|
| 702 | +classifyEvBindDep evId =
|
|
| 703 | + case idDetails evId of
|
|
| 704 | + RecSelId{sel_tycon} -> RecordField (varName evId) (recSelParentName sel_tycon)
|
|
| 705 | + _ -> EvidenceVar (varName evId)
|
|
| 706 | + |
|
| 701 | 707 | instance ToHie (LocatedA HsWrapper) where
|
| 702 | 708 | toHie (L osp wrap)
|
| 703 | 709 | = case wrap of
|
| ... | ... | @@ -598,17 +598,79 @@ instance Outputable EvVarSource where |
| 598 | 598 | ppr (EvInstBind True cls) = text "bound due to a superclass of " <+> ppr cls
|
| 599 | 599 | ppr (EvLetBind deps) = text "bound by a let, depending on:" <+> ppr deps
|
| 600 | 600 | |
| 601 | +-- | Evidence binding dependency with additional details.
|
|
| 602 | +data EvBindDep
|
|
| 603 | + = EvidenceVar Name
|
|
| 604 | + -- ^ Evidence variable such as a type class constructor.
|
|
| 605 | + --
|
|
| 606 | + -- For example, @C:HasField@, @$dShow@ (dictionaries) or @$fCList@.
|
|
| 607 | + --
|
|
| 608 | + -- This is the default representation of a 'EvBindDep'.
|
|
| 609 | + | RecordField
|
|
| 610 | + -- ^ Evidence variable of a record selector.
|
|
| 611 | + --
|
|
| 612 | + -- This is for example generated with @-XOverloadedRecordDot@, where
|
|
| 613 | + -- the evidence includes a reference to which record selector is used
|
|
| 614 | + -- to implement @getField@.
|
|
| 615 | + Name
|
|
| 616 | + -- ^ 'Name' of the record selector
|
|
| 617 | + Name
|
|
| 618 | + -- ^ 'Name' of the parent type.
|
|
| 619 | + | TypeableEvidence
|
|
| 620 | + -- ^ Evidence of a @Typeable@ constraint.
|
|
| 621 | + Name
|
|
| 622 | + -- ^ Name of the type the evidence was generated for.
|
|
| 623 | + deriving (Eq, Ord)
|
|
| 624 | + |
|
| 625 | +instance Outputable EvBindDep where
|
|
| 626 | + ppr = \ case
|
|
| 627 | + EvidenceVar n -> ppr n
|
|
| 628 | + RecordField sel parent -> ppr sel <+> text "of Record" <+> ppr parent
|
|
| 629 | + TypeableEvidence n -> ppr n <+> text "bound by Typeable"
|
|
| 630 | + |
|
| 631 | +evBindDepName :: EvBindDep -> Name
|
|
| 632 | +evBindDepName = \ case
|
|
| 633 | + EvidenceVar n -> n
|
|
| 634 | + RecordField selector _record -> selector
|
|
| 635 | + TypeableEvidence n -> n
|
|
| 636 | + |
|
| 637 | +evBindDepHieName :: EvBindDep -> HieName
|
|
| 638 | +evBindDepHieName = toHieName . evBindDepName
|
|
| 639 | + |
|
| 640 | +instance Binary EvBindDep where
|
|
| 641 | + put_ bh = \ case
|
|
| 642 | + EvidenceVar n -> do
|
|
| 643 | + putByte bh 0
|
|
| 644 | + put_ bh n
|
|
| 645 | + RecordField n sel -> do
|
|
| 646 | + putByte bh 1
|
|
| 647 | + put_ bh n
|
|
| 648 | + put_ bh sel
|
|
| 649 | + TypeableEvidence n -> do
|
|
| 650 | + putByte bh 2
|
|
| 651 | + put_ bh n
|
|
| 652 | + |
|
| 653 | + get bh =
|
|
| 654 | + getByte bh >>= \ case
|
|
| 655 | + 0 -> EvidenceVar <$> get bh
|
|
| 656 | + 1 -> RecordField <$> get bh <*> get bh
|
|
| 657 | + 2 -> TypeableEvidence <$> get bh
|
|
| 658 | + t -> fail $ "EvBindDep: Unknown tag: " ++ show t
|
|
| 659 | + |
|
| 601 | 660 | -- | Eq/Ord instances compare on the converted HieName,
|
| 602 | 661 | -- as non-exported names may have different uniques after
|
| 603 | 662 | -- a roundtrip
|
| 604 | -newtype EvBindDeps = EvBindDeps { getEvBindDeps :: [Name] }
|
|
| 663 | +newtype EvBindDeps = EvBindDeps { getEvBindDeps :: [EvBindDep] }
|
|
| 605 | 664 | deriving Outputable
|
| 606 | 665 | |
| 666 | +evBindDepsNames :: EvBindDeps -> [Name]
|
|
| 667 | +evBindDepsNames = map evBindDepName . getEvBindDeps
|
|
| 668 | + |
|
| 607 | 669 | instance Eq EvBindDeps where
|
| 608 | - (==) = coerce ((==) `on` map toHieName)
|
|
| 670 | + (==) = coerce ((==) `on` map evBindDepHieName)
|
|
| 609 | 671 | |
| 610 | 672 | instance Ord EvBindDeps where
|
| 611 | - compare = coerce (compare `on` map toHieName)
|
|
| 673 | + compare = coerce (compare `on` map evBindDepHieName)
|
|
| 612 | 674 | |
| 613 | 675 | instance Binary EvBindDeps where
|
| 614 | 676 | put_ bh (EvBindDeps xs) = put_ bh xs
|
| ... | ... | @@ -145,7 +145,7 @@ getEvidenceTree refmap var = go emptyNameSet var |
| 145 | 145 | det <- S.toList $ identInfo dets
|
| 146 | 146 | case det of
|
| 147 | 147 | EvidenceVarBind src@(EvLetBind (getEvBindDeps -> xs)) scp spn ->
|
| 148 | - pure $ Just ((src,scp,spn),mapMaybe (go $ extendNameSet seen var) xs)
|
|
| 148 | + pure $ Just ((src,scp,spn),mapMaybe (go (extendNameSet seen var) . evBindDepName) xs)
|
|
| 149 | 149 | EvidenceVarBind src scp spn -> pure $ Just ((src,scp,spn),[])
|
| 150 | 150 | _ -> pure Nothing
|
| 151 | 151 | pure $ Tree.Node (EvidenceInfo var sp typ (Just evdet)) children
|
| ... | ... | @@ -390,7 +390,7 @@ definedInAsts asts n = case nameSrcSpan n of |
| 390 | 390 | |
| 391 | 391 | getEvidenceBindDeps :: ContextInfo -> [Name]
|
| 392 | 392 | getEvidenceBindDeps (EvidenceVarBind (EvLetBind xs) _ _) =
|
| 393 | - getEvBindDeps xs
|
|
| 393 | + evBindDepsNames xs
|
|
| 394 | 394 | getEvidenceBindDeps _ = []
|
| 395 | 395 | |
| 396 | 396 | isEvidenceBind :: ContextInfo -> Bool
|
| ... | ... | @@ -422,7 +422,7 @@ rnExpr (HsGetField _ e f) |
| 422 | 422 | ; let f' = rnDotFieldOcc <$> f
|
| 423 | 423 | ; return ( mkExpandedExpr
|
| 424 | 424 | (HsGetField noExtField e f')
|
| 425 | - (mkGetField getField e (fmap (unLoc . dfoLabel) f'))
|
|
| 425 | + (mkGetField getField e (dfoLabel $ unLoc f'))
|
|
| 426 | 426 | , fv_e `plusFN` fv_getField ) }
|
| 427 | 427 | |
| 428 | 428 | rnExpr (HsProjection _ fs)
|
| ... | ... | @@ -431,7 +431,7 @@ rnExpr (HsProjection _ fs) |
| 431 | 431 | ; let fs' = NE.map rnDotFieldOcc fs
|
| 432 | 432 | ; return ( mkExpandedExpr
|
| 433 | 433 | (HsProjection noExtField fs')
|
| 434 | - (mkProjection getField circ $ NE.map (unLoc . dfoLabel) fs')
|
|
| 434 | + (mkProjection getField circ $ NE.map dfoLabel fs')
|
|
| 435 | 435 | , unitFN circ `plusFN` fv_getField) }
|
| 436 | 436 | |
| 437 | 437 | ------------------------------------------
|
| ... | ... | @@ -2882,8 +2882,9 @@ rnHsIf p b1 b2 |
| 2882 | 2882 | |
| 2883 | 2883 | -- mkGetField arg field calculates a get_field @field arg expression.
|
| 2884 | 2884 | -- e.g. z.x = mkGetField z x = get_field @x z
|
| 2885 | -mkGetField :: Name -> LHsExpr GhcRn -> LocatedAn NoEpAnns FieldLabelString -> HsExpr GhcRn
|
|
| 2886 | -mkGetField get_field arg field = unLoc (head $ mkGet get_field (arg :| []) field)
|
|
| 2885 | +mkGetField :: Name -> LHsExpr GhcRn -> XRec GhcRn FieldLabelString -> HsExpr GhcRn
|
|
| 2886 | +mkGetField get_field arg field =
|
|
| 2887 | + HsApp noExtField (mkGetFieldExpr get_field field) arg
|
|
| 2887 | 2888 | |
| 2888 | 2889 | -- mkSetField a field b calculates a set_field @field expression.
|
| 2889 | 2890 | -- e.g mkSetSetField a field b = set_field @"field" a b (read as "set field 'field' to a on b").
|
| ... | ... | @@ -2902,14 +2903,16 @@ mkSet set_field acc (field, g) = wrapGenSpan (mkSetField set_field g field acc) |
| 2902 | 2903 | -- mkProjection fields calculates a projection.
|
| 2903 | 2904 | -- e.g. .x = mkProjection [x] = getField @"x"
|
| 2904 | 2905 | -- .x.y = mkProjection [.x, .y] = (.y) . (.x) = getField @"y" . getField @"x"
|
| 2905 | -mkProjection :: Name -> Name -> NonEmpty FieldLabelString -> HsExpr GhcRn
|
|
| 2906 | -mkProjection getFieldName circName (field :| fields) = foldl' f (proj field) fields
|
|
| 2906 | +mkProjection :: Name -> Name -> NonEmpty (XRec GhcRn FieldLabelString) -> HsExpr GhcRn
|
|
| 2907 | +mkProjection getFieldName circName (field :| fields) =
|
|
| 2908 | + unLoc $ foldl' f (mkGetFieldExpr getFieldName field) fields
|
|
| 2907 | 2909 | where
|
| 2908 | - f :: HsExpr GhcRn -> FieldLabelString -> HsExpr GhcRn
|
|
| 2909 | - f acc field = genHsApps circName $ map wrapGenSpan [proj field, acc]
|
|
| 2910 | + f :: LHsExpr GhcRn -> XRec GhcRn FieldLabelString -> LHsExpr GhcRn
|
|
| 2911 | + f acc field = wrapGenSpan $ genHsApps circName [mkGetFieldExpr getFieldName field, acc]
|
|
| 2910 | 2912 | |
| 2911 | - proj :: FieldLabelString -> HsExpr GhcRn
|
|
| 2912 | - proj (FieldLabelString f) = genHsVar getFieldName `genAppType` genHsTyLit f
|
|
| 2913 | +mkGetFieldExpr :: Name -> XRec GhcRn FieldLabelString -> LHsExpr GhcRn
|
|
| 2914 | +mkGetFieldExpr getFieldName (L ann (FieldLabelString f)) =
|
|
| 2915 | + wrapGenSpan' (getHasLoc ann) (genHsVar getFieldName `genAppType` genHsTyLit f)
|
|
| 2913 | 2916 | |
| 2914 | 2917 | -- mkProjUpdateSetField calculates functions representing dot notation record updates.
|
| 2915 | 2918 | -- e.g. Suppose an update like foo.bar = 1.
|
| 1 | 1 | ==========================
|
| 2 | 2 | At point (13,17), we found:
|
| 3 | 3 | ==========================
|
| 4 | +┌
|
|
| 5 | +│ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field1" Thing Char
|
|
| 6 | +│ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 7 | +│ field1 of Record Thing]
|
|
| 8 | +│ with scope: ModuleScope
|
|
| 9 | +│
|
|
| 10 | +│ Defined at <no location info>
|
|
| 11 | +└
|
|
| 12 | +|
|
|
| 13 | ++- ┌
|
|
| 14 | +| │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 15 | +| │ is a usage of an external evidence variable
|
|
| 16 | +| │ Defined in `GHC.Internal.Records'
|
|
| 17 | +| └
|
|
| 18 | +|
|
|
| 19 | +`- ┌
|
|
| 20 | + │ field1 at HasFieldQueries.hs:1:1, of type: Thing -> Char
|
|
| 21 | + │ is a usage of an external evidence variable
|
|
| 22 | + │ Defined at HasFieldQueries.hs:9:21
|
|
| 23 | + └
|
|
| 24 | + |
|
| 4 | 25 | ==========================
|
| 5 | 26 | At point (16,25), we found:
|
| 6 | 27 | ==========================
|
| 7 | 28 | ==========================
|
| 8 | 29 | At point (16,27), we found:
|
| 9 | 30 | ==========================
|
| 31 | +┌
|
|
| 32 | +│ $dHasField at HasFieldQueries.hs:16:1-32, of type: HasField "field1" Thing Char
|
|
| 33 | +│ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 34 | +│ field1 of Record Thing]
|
|
| 35 | +│ with scope: LocalScope HasFieldQueries.hs:16:1-32
|
|
| 36 | +│ bound at: HasFieldQueries.hs:16:1-32
|
|
| 37 | +│ Defined at <no location info>
|
|
| 38 | +└
|
|
| 39 | +|
|
|
| 40 | ++- ┌
|
|
| 41 | +| │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 42 | +| │ is a usage of an external evidence variable
|
|
| 43 | +| │ Defined in `GHC.Internal.Records'
|
|
| 44 | +| └
|
|
| 45 | +|
|
|
| 46 | +`- ┌
|
|
| 47 | + │ field1 at HasFieldQueries.hs:1:1, of type: Thing -> Char
|
|
| 48 | + │ is a usage of an external evidence variable
|
|
| 49 | + │ Defined at HasFieldQueries.hs:9:21
|
|
| 50 | + └
|
|
| 51 | + |
|
| 10 | 52 | ==========================
|
| 11 | 53 | At point (23,17), we found:
|
| 12 | 54 | ==========================
|
| 55 | +┌
|
|
| 56 | +│ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "nested1" NestedThing Thing
|
|
| 57 | +│ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 58 | +│ nested1 of Record NestedThing]
|
|
| 59 | +│ with scope: ModuleScope
|
|
| 60 | +│
|
|
| 61 | +│ Defined at <no location info>
|
|
| 62 | +└
|
|
| 63 | +|
|
|
| 64 | ++- ┌
|
|
| 65 | +| │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 66 | +| │ is a usage of an external evidence variable
|
|
| 67 | +| │ Defined in `GHC.Internal.Records'
|
|
| 68 | +| └
|
|
| 69 | +|
|
|
| 70 | +`- ┌
|
|
| 71 | + │ nested1 at HasFieldQueries.hs:1:1, of type: NestedThing -> Thing
|
|
| 72 | + │ is a usage of an external evidence variable
|
|
| 73 | + │ Defined at HasFieldQueries.hs:20:34
|
|
| 74 | + └
|
|
| 75 | + |
|
| 13 | 76 | ==========================
|
| 14 | 77 | At point (23,25), we found:
|
| 15 | 78 | ==========================
|
| 79 | +┌
|
|
| 80 | +│ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field1" Thing Char
|
|
| 81 | +│ is an evidence variable bound by a let, depending on: [$dHasField]
|
|
| 82 | +│ with scope: ModuleScope
|
|
| 83 | +│
|
|
| 84 | +│ Defined at <no location info>
|
|
| 85 | +└
|
|
| 86 | +|
|
|
| 87 | +`- ┌
|
|
| 88 | + │ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field1" Thing Char
|
|
| 89 | + │ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 90 | + │ field1 of Record Thing]
|
|
| 91 | + │ with scope: ModuleScope
|
|
| 92 | + │
|
|
| 93 | + │ Defined at <no location info>
|
|
| 94 | + └
|
|
| 95 | + |
|
|
| 96 | + +- ┌
|
|
| 97 | + | │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 98 | + | │ is a usage of an external evidence variable
|
|
| 99 | + | │ Defined in `GHC.Internal.Records'
|
|
| 100 | + | └
|
|
| 101 | + |
|
|
| 102 | + `- ┌
|
|
| 103 | + │ field1 at HasFieldQueries.hs:1:1, of type: Thing -> Char
|
|
| 104 | + │ is a usage of an external evidence variable
|
|
| 105 | + │ Defined at HasFieldQueries.hs:9:21
|
|
| 106 | + └
|
|
| 107 | + |
|
| 16 | 108 | ==========================
|
| 17 | 109 | At point (27,20), we found:
|
| 18 | 110 | ==========================
|
| 111 | +┌
|
|
| 112 | +│ $dHasField at HasFieldQueries.hs:27:1-40, of type: HasField "nested1" r r
|
|
| 113 | +│ is an evidence variable bound by a let, depending on: [$dHasField]
|
|
| 114 | +│ with scope: LocalScope HasFieldQueries.hs:27:1-40
|
|
| 115 | +│ bound at: HasFieldQueries.hs:27:1-40
|
|
| 116 | +│ Defined at <no location info>
|
|
| 117 | +└
|
|
| 118 | +|
|
|
| 119 | +`- ┌
|
|
| 120 | + │ $dHasField at HasFieldQueries.hs:27:1-40, of type: HasField "nested1" r r
|
|
| 121 | + │ is an evidence variable bound by a type signature
|
|
| 122 | + │ with scope: LocalScope HasFieldQueries.hs:27:1-40
|
|
| 123 | + │ bound at: HasFieldQueries.hs:27:1-40
|
|
| 124 | + │ Defined at <no location info>
|
|
| 125 | + └
|
|
| 126 | + |
|
| 19 | 127 | ==========================
|
| 20 | 128 | At point (27,28), we found:
|
| 21 | 129 | ==========================
|
| 130 | +┌
|
|
| 131 | +│ $dHasField at HasFieldQueries.hs:27:1-40, of type: HasField "field2" r Bool
|
|
| 132 | +│ is an evidence variable bound by a let, depending on: [$dHasField]
|
|
| 133 | +│ with scope: LocalScope HasFieldQueries.hs:27:1-40
|
|
| 134 | +│ bound at: HasFieldQueries.hs:27:1-40
|
|
| 135 | +│ Defined at <no location info>
|
|
| 136 | +└
|
|
| 137 | +|
|
|
| 138 | +`- ┌
|
|
| 139 | + │ $dHasField at HasFieldQueries.hs:27:1-40, of type: HasField "field2" r Bool
|
|
| 140 | + │ is an evidence variable bound by a type signature
|
|
| 141 | + │ with scope: LocalScope HasFieldQueries.hs:27:1-40
|
|
| 142 | + │ bound at: HasFieldQueries.hs:27:1-40
|
|
| 143 | + │ Defined at <no location info>
|
|
| 144 | + └
|
|
| 145 | + |
|
| 22 | 146 | ==========================
|
| 23 | 147 | At point (33,22), we found:
|
| 24 | 148 | ==========================
|
| 149 | +┌
|
|
| 150 | +│ $dHasField at HasFieldQueries.hs:33:1-27, of type: HasField "field1" x Char
|
|
| 151 | +│ is an evidence variable bound by a let, depending on: [$dHasField]
|
|
| 152 | +│ with scope: LocalScope HasFieldQueries.hs:33:1-27
|
|
| 153 | +│ bound at: HasFieldQueries.hs:33:1-27
|
|
| 154 | +│ Defined at <no location info>
|
|
| 155 | +└
|
|
| 156 | +|
|
|
| 157 | +`- ┌
|
|
| 158 | + │ $dHasField at HasFieldQueries.hs:33:1-27, of type: HasField "field1" x Char
|
|
| 159 | + │ is an evidence variable bound by a HsWrapper
|
|
| 160 | + │ with scope: LocalScope HasFieldQueries.hs:33:1-27
|
|
| 161 | + │ bound at: HasFieldQueries.hs:33:1-27
|
|
| 162 | + │ Defined at <no location info>
|
|
| 163 | + └
|
|
| 164 | + |
|
| 25 | 165 | ==========================
|
| 26 | 166 | At point (37,14), we found:
|
| 27 | 167 | ==========================
|
| ... | ... | @@ -35,21 +175,70 @@ At point (37,14), we found: |
| 35 | 175 | |
|
| 36 | 176 | `- ┌
|
| 37 | 177 | │ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field1" Thing Char
|
| 38 | - │ is an evidence variable bound by a let, depending on: [C:HasField]
|
|
| 178 | + │ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 179 | + │ field1 of Record Thing]
|
|
| 39 | 180 | │ with scope: ModuleScope
|
| 40 | 181 | │
|
| 41 | 182 | │ Defined at <no location info>
|
| 42 | 183 | └
|
| 43 | 184 | |
|
| 185 | + +- ┌
|
|
| 186 | + | │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 187 | + | │ is a usage of an external evidence variable
|
|
| 188 | + | │ Defined in `GHC.Internal.Records'
|
|
| 189 | + | └
|
|
| 190 | + |
|
|
| 44 | 191 | `- ┌
|
| 45 | - │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 192 | + │ field1 at HasFieldQueries.hs:1:1, of type: Thing -> Char
|
|
| 46 | 193 | │ is a usage of an external evidence variable
|
| 47 | - │ Defined in `GHC.Internal.Records'
|
|
| 194 | + │ Defined at HasFieldQueries.hs:9:21
|
|
| 48 | 195 | └
|
| 49 | 196 | |
| 50 | 197 | ==========================
|
| 51 | 198 | At point (41,21), we found:
|
| 52 | 199 | ==========================
|
| 200 | +┌
|
|
| 201 | +│ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "nested1" NestedThing Thing
|
|
| 202 | +│ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 203 | +│ nested1 of Record NestedThing]
|
|
| 204 | +│ with scope: ModuleScope
|
|
| 205 | +│
|
|
| 206 | +│ Defined at <no location info>
|
|
| 207 | +└
|
|
| 208 | +|
|
|
| 209 | ++- ┌
|
|
| 210 | +| │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 211 | +| │ is a usage of an external evidence variable
|
|
| 212 | +| │ Defined in `GHC.Internal.Records'
|
|
| 213 | +| └
|
|
| 214 | +|
|
|
| 215 | +`- ┌
|
|
| 216 | + │ nested1 at HasFieldQueries.hs:1:1, of type: NestedThing -> Thing
|
|
| 217 | + │ is a usage of an external evidence variable
|
|
| 218 | + │ Defined at HasFieldQueries.hs:20:34
|
|
| 219 | + └
|
|
| 220 | + |
|
| 53 | 221 | ==========================
|
| 54 | 222 | At point (41,30), we found:
|
| 55 | 223 | ==========================
|
| 224 | +┌
|
|
| 225 | +│ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field1" Thing Char
|
|
| 226 | +│ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 227 | +│ field1 of Record Thing]
|
|
| 228 | +│ with scope: ModuleScope
|
|
| 229 | +│
|
|
| 230 | +│ Defined at <no location info>
|
|
| 231 | +└
|
|
| 232 | +|
|
|
| 233 | ++- ┌
|
|
| 234 | +| │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 235 | +| │ is a usage of an external evidence variable
|
|
| 236 | +| │ Defined in `GHC.Internal.Records'
|
|
| 237 | +| └
|
|
| 238 | +|
|
|
| 239 | +`- ┌
|
|
| 240 | + │ field1 at HasFieldQueries.hs:1:1, of type: Thing -> Char
|
|
| 241 | + │ is a usage of an external evidence variable
|
|
| 242 | + │ Defined at HasFieldQueries.hs:9:21
|
|
| 243 | + └
|
|
| 244 | + |
| 1 | +module Main where
|
|
| 2 | + |
|
| 3 | +import Data.Dynamic
|
|
| 4 | +import Data.Typeable
|
|
| 5 | +import TestUtils
|
|
| 6 | + |
|
| 7 | +data Thing = Thing {field1 :: Char, field2 :: Bool}
|
|
| 8 | + deriving (Show, Eq)
|
|
| 9 | + |
|
| 10 | +castFromDynamic :: Dynamic -> Maybe Thing
|
|
| 11 | +castFromDynamic d = fromDynamic d
|
|
| 12 | + -- ^ this is the point
|
|
| 13 | + |
|
| 14 | +rep :: Thing -> TypeRep
|
|
| 15 | +rep d = typeOf d
|
|
| 16 | + -- ^ this is the point
|
|
| 17 | + |
|
| 18 | +points =
|
|
| 19 | + [ (11,21)
|
|
| 20 | + , (15,10)
|
|
| 21 | + ]
|
|
| 22 | + |
|
| 23 | +main = do
|
|
| 24 | + (df, hf) <- readTestHie "HieTypeable.hie"
|
|
| 25 | + let refmap = generateReferencesMap $ getAsts $ hie_asts hf
|
|
| 26 | + |
|
| 27 | + traverse (explainEv df hf refmap) points
|
|
| 28 | + return () |
| 1 | +==========================
|
|
| 2 | +At point (11,21), we found:
|
|
| 3 | +==========================
|
|
| 4 | +┌
|
|
| 5 | +│ $dTypeable at HieTypeable.hs:1:1, of type: Typeable Thing
|
|
| 6 | +│ is an evidence variable bound by a let, depending on: [$dTypeable]
|
|
| 7 | +│ with scope: ModuleScope
|
|
| 8 | +│
|
|
| 9 | +│ Defined at <no location info>
|
|
| 10 | +└
|
|
| 11 | +|
|
|
| 12 | +`- ┌
|
|
| 13 | + │ $dTypeable at HieTypeable.hs:1:1, of type: Typeable Thing
|
|
| 14 | + │ is an evidence variable bound by a let, depending on: []
|
|
| 15 | + │ with scope: ModuleScope
|
|
| 16 | + │
|
|
| 17 | + │ Defined at <no location info>
|
|
| 18 | + └
|
|
| 19 | + |
|
| 20 | +==========================
|
|
| 21 | +At point (15,10), we found:
|
|
| 22 | +==========================
|
|
| 23 | +┌
|
|
| 24 | +│ $dTypeable at HieTypeable.hs:1:1, of type: Typeable Thing
|
|
| 25 | +│ is an evidence variable bound by a let, depending on: []
|
|
| 26 | +│ with scope: ModuleScope
|
|
| 27 | +│
|
|
| 28 | +│ Defined at <no location info>
|
|
| 29 | +└
|
|
| 30 | + |
| 1 | 1 | ==========================
|
| 2 | 2 | At point (23,16), we found:
|
| 3 | 3 | ==========================
|
| 4 | +┌
|
|
| 5 | +│ $dHasField at NoFieldSelectorQueries.hs:1:1, of type: HasField "a" A Int
|
|
| 6 | +│ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 7 | +│ a of Record A]
|
|
| 8 | +│ with scope: ModuleScope
|
|
| 9 | +│
|
|
| 10 | +│ Defined at <no location info>
|
|
| 11 | +└
|
|
| 12 | +|
|
|
| 13 | ++- ┌
|
|
| 14 | +| │ C:HasField at NoFieldSelectorQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 15 | +| │ is a usage of an external evidence variable
|
|
| 16 | +| │ Defined in `GHC.Internal.Records'
|
|
| 17 | +| └
|
|
| 18 | +|
|
|
| 19 | +`- ┌
|
|
| 20 | + │ a at NoFieldSelectorQueries.hs:1:1, of type: A -> Int
|
|
| 21 | + │ is a usage of an external evidence variable
|
|
| 22 | + │ Defined at NoFieldSelectorQueries.hs:9:14
|
|
| 23 | + └
|
|
| 24 | + |
|
| 4 | 25 | ==========================
|
| 5 | 26 | At point (27,19), we found:
|
| 6 | 27 | ==========================
|
| 28 | +┌
|
|
| 29 | +│ $dHasField at NoFieldSelectorQueries.hs:27:1-19, of type: HasField "a" r Int
|
|
| 30 | +│ is an evidence variable bound by a let, depending on: [$dHasField]
|
|
| 31 | +│ with scope: LocalScope NoFieldSelectorQueries.hs:27:1-19
|
|
| 32 | +│ bound at: NoFieldSelectorQueries.hs:27:1-19
|
|
| 33 | +│ Defined at <no location info>
|
|
| 34 | +└
|
|
| 35 | +|
|
|
| 36 | +`- ┌
|
|
| 37 | + │ $dHasField at NoFieldSelectorQueries.hs:27:1-19, of type: HasField "a" r Int
|
|
| 38 | + │ is an evidence variable bound by a HsWrapper
|
|
| 39 | + │ with scope: LocalScope NoFieldSelectorQueries.hs:27:1-19
|
|
| 40 | + │ bound at: NoFieldSelectorQueries.hs:27:1-19
|
|
| 41 | + │ Defined at <no location info>
|
|
| 42 | + └
|
|
| 43 | + |
|
| 7 | 44 | ==========================
|
| 8 | 45 | At point (30,15), we found:
|
| 9 | 46 | ==========================
|
| 47 | +┌
|
|
| 48 | +│ $dHasField at NoFieldSelectorQueries.hs:30:1-17, of type: HasField "n" B A
|
|
| 49 | +│ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 50 | +│ n of Record B]
|
|
| 51 | +│ with scope: LocalScope NoFieldSelectorQueries.hs:30:1-17
|
|
| 52 | +│ bound at: NoFieldSelectorQueries.hs:30:1-17
|
|
| 53 | +│ Defined at <no location info>
|
|
| 54 | +└
|
|
| 55 | +|
|
|
| 56 | ++- ┌
|
|
| 57 | +| │ C:HasField at NoFieldSelectorQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 58 | +| │ is a usage of an external evidence variable
|
|
| 59 | +| │ Defined in `GHC.Internal.Records'
|
|
| 60 | +| └
|
|
| 61 | +|
|
|
| 62 | +`- ┌
|
|
| 63 | + │ n at NoFieldSelectorQueries.hs:30:1-17, of type: B -> A
|
|
| 64 | + │ is a usage of an external evidence variable
|
|
| 65 | + │ Defined at NoFieldSelectorQueries.hs:10:24
|
|
| 66 | + └
|
|
| 67 | + |
|
| 10 | 68 | ==========================
|
| 11 | 69 | At point (30,17), we found:
|
| 12 | 70 | ==========================
|
| 71 | +┌
|
|
| 72 | +│ $dHasField at NoFieldSelectorQueries.hs:30:1-17, of type: HasField "b" A Char
|
|
| 73 | +│ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 74 | +│ b of Record A]
|
|
| 75 | +│ with scope: LocalScope NoFieldSelectorQueries.hs:30:1-17
|
|
| 76 | +│ bound at: NoFieldSelectorQueries.hs:30:1-17
|
|
| 77 | +│ Defined at <no location info>
|
|
| 78 | +└
|
|
| 79 | +|
|
|
| 80 | ++- ┌
|
|
| 81 | +| │ C:HasField at NoFieldSelectorQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 82 | +| │ is a usage of an external evidence variable
|
|
| 83 | +| │ Defined in `GHC.Internal.Records'
|
|
| 84 | +| └
|
|
| 85 | +|
|
|
| 86 | +`- ┌
|
|
| 87 | + │ b at NoFieldSelectorQueries.hs:30:1-17, of type: A -> Char
|
|
| 88 | + │ is a usage of an external evidence variable
|
|
| 89 | + │ Defined at NoFieldSelectorQueries.hs:9:24
|
|
| 90 | + └
|
|
| 91 | + |
|
| 13 | 92 | ==========================
|
| 14 | 93 | At point (33,16), we found:
|
| 15 | 94 | ==========================
|
| 95 | +┌
|
|
| 96 | +│ $dHasField at NoFieldSelectorQueries.hs:33:1-16, of type: HasField "c" C Float
|
|
| 97 | +│ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 98 | +│ c of Record C]
|
|
| 99 | +│ with scope: LocalScope NoFieldSelectorQueries.hs:33:1-16
|
|
| 100 | +│ bound at: NoFieldSelectorQueries.hs:33:1-16
|
|
| 101 | +│ Defined at <no location info>
|
|
| 102 | +└
|
|
| 103 | +|
|
|
| 104 | ++- ┌
|
|
| 105 | +| │ C:HasField at NoFieldSelectorQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 106 | +| │ is a usage of an external evidence variable
|
|
| 107 | +| │ Defined in `GHC.Internal.Records'
|
|
| 108 | +| └
|
|
| 109 | +|
|
|
| 110 | +`- ┌
|
|
| 111 | + │ c at NoFieldSelectorQueries.hs:1:1, of type: C -> Float
|
|
| 112 | + │ is a usage of an external evidence variable
|
|
| 113 | + │ Defined at NoFieldSelectorQueries.hs:12:9
|
|
| 114 | + └
|
|
| 115 | + |
|
| 16 | 116 | ==========================
|
| 17 | 117 | At point (36,16), we found:
|
| 18 | 118 | ==========================
|
| 119 | +┌
|
|
| 120 | +│ $dHasField at NoFieldSelectorQueries.hs:36:1-16, of type: HasField "c" C Float
|
|
| 121 | +│ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 122 | +│ c of Record C]
|
|
| 123 | +│ with scope: LocalScope NoFieldSelectorQueries.hs:36:1-16
|
|
| 124 | +│ bound at: NoFieldSelectorQueries.hs:36:1-16
|
|
| 125 | +│ Defined at <no location info>
|
|
| 126 | +└
|
|
| 127 | +|
|
|
| 128 | ++- ┌
|
|
| 129 | +| │ C:HasField at NoFieldSelectorQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 130 | +| │ is a usage of an external evidence variable
|
|
| 131 | +| │ Defined in `GHC.Internal.Records'
|
|
| 132 | +| └
|
|
| 133 | +|
|
|
| 134 | +`- ┌
|
|
| 135 | + │ c at NoFieldSelectorQueries.hs:1:1, of type: C -> Float
|
|
| 136 | + │ is a usage of an external evidence variable
|
|
| 137 | + │ Defined at NoFieldSelectorQueries.hs:12:9
|
|
| 138 | + └
|
|
| 139 | + |
|
| 19 | 140 | ==========================
|
| 20 | 141 | At point (40,23), we found:
|
| 21 | 142 | ==========================
|
| 143 | +┌
|
|
| 144 | +│ $dHasField at NoFieldSelectorQueries.hs:1:1, of type: HasField "c" C Float
|
|
| 145 | +│ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 146 | +│ c of Record C]
|
|
| 147 | +│ with scope: ModuleScope
|
|
| 148 | +│
|
|
| 149 | +│ Defined at <no location info>
|
|
| 150 | +└
|
|
| 151 | +|
|
|
| 152 | ++- ┌
|
|
| 153 | +| │ C:HasField at NoFieldSelectorQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 154 | +| │ is a usage of an external evidence variable
|
|
| 155 | +| │ Defined in `GHC.Internal.Records'
|
|
| 156 | +| └
|
|
| 157 | +|
|
|
| 158 | +`- ┌
|
|
| 159 | + │ c at NoFieldSelectorQueries.hs:1:1, of type: C -> Float
|
|
| 160 | + │ is a usage of an external evidence variable
|
|
| 161 | + │ Defined at NoFieldSelectorQueries.hs:12:9
|
|
| 162 | + └
|
|
| 163 | + |
|
| 22 | 164 | ==========================
|
| 23 | 165 | At point (43,15), we found:
|
| 24 | 166 | ==========================
|
| 167 | +┌
|
|
| 168 | +│ $dHasField at NoFieldSelectorQueries.hs:43:1-15, of type: HasField "e" C Int
|
|
| 169 | +│ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 170 | +│ e of Record C]
|
|
| 171 | +│ with scope: LocalScope NoFieldSelectorQueries.hs:43:1-15
|
|
| 172 | +│ bound at: NoFieldSelectorQueries.hs:43:1-15
|
|
| 173 | +│ Defined at <no location info>
|
|
| 174 | +└
|
|
| 175 | +|
|
|
| 176 | ++- ┌
|
|
| 177 | +| │ C:HasField at NoFieldSelectorQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 178 | +| │ is a usage of an external evidence variable
|
|
| 179 | +| │ Defined in `GHC.Internal.Records'
|
|
| 180 | +| └
|
|
| 181 | +|
|
|
| 182 | +`- ┌
|
|
| 183 | + │ e at NoFieldSelectorQueries.hs:43:1-15, of type: C -> Int
|
|
| 184 | + │ is a usage of an external evidence variable
|
|
| 185 | + │ Defined at NoFieldSelectorQueries.hs:14:9
|
|
| 186 | + └
|
|
| 187 | + |
|
| 25 | 188 | ==========================
|
| 26 | 189 | At point (46,15), we found:
|
| 27 | 190 | ==========================
|
| 191 | +┌
|
|
| 192 | +│ $dHasField at NoFieldSelectorQueries.hs:46:1-15, of type: HasField "e" C Int
|
|
| 193 | +│ is an evidence variable bound by a let, depending on: [C:HasField,
|
|
| 194 | +│ e of Record C]
|
|
| 195 | +│ with scope: LocalScope NoFieldSelectorQueries.hs:46:1-15
|
|
| 196 | +│ bound at: NoFieldSelectorQueries.hs:46:1-15
|
|
| 197 | +│ Defined at <no location info>
|
|
| 198 | +└
|
|
| 199 | +|
|
|
| 200 | ++- ┌
|
|
| 201 | +| │ C:HasField at NoFieldSelectorQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
|
|
| 202 | +| │ is a usage of an external evidence variable
|
|
| 203 | +| │ Defined in `GHC.Internal.Records'
|
|
| 204 | +| └
|
|
| 205 | +|
|
|
| 206 | +`- ┌
|
|
| 207 | + │ e at NoFieldSelectorQueries.hs:43:1-15, of type: C -> Int
|
|
| 208 | + │ is a usage of an external evidence variable
|
|
| 209 | + │ Defined at NoFieldSelectorQueries.hs:14:9
|
|
| 210 | + └
|
|
| 211 | + |
| 1 | 1 | At (22,6), got type: MyRecord
|
| 2 | -At (22,20), got type: Integer
|
|
| 2 | +At (22,20), got type: MyRecord -> Integer
|
|
| 3 | 3 | At (22,25), got type: MyRecord
|
| 4 | -At (22,28), got type: String
|
|
| 5 | -At (22,29), got type: String
|
|
| 6 | -At (22,6) - (22,8), got type: String
|
|
| 4 | +At (22,28), got type: MyChild -> [Char]
|
|
| 5 | +At (22,29), got type: MyChild -> [Char]
|
|
| 6 | +At (22,6) - (22,8), got type: [Char]
|
|
| 7 | 7 | At (22,17) - (22,20), got type: Integer
|
| 8 | 8 | At (22,25) - (22,27), got type: MyChild
|
| 9 | -At (22,25) - (22,29), got type: String |
|
| 9 | +At (22,25) - (22,29), got type: [Char] |
| ... | ... | @@ -4,4 +4,4 @@ PartialFieldSelector |
| 4 | 4 | At (18,7), got type: PartialFieldSelector -> Bool
|
| 5 | 5 | At (23,7), got type: PartialFieldSelector
|
| 6 | 6 | At (23,8), got type: PartialFieldSelector
|
| 7 | -At (23,9), got type: Bool |
|
| 7 | +At (23,9), got type: PartialFieldSelector -> Bool |
| ... | ... | @@ -12,3 +12,4 @@ test('HieGadtConSigs', [extra_run_opts('"' + config.libdir + '"'), extra_files([ |
| 12 | 12 | test('T25709', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info'])
|
| 13 | 13 | test('HasFieldQueries', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info'])
|
| 14 | 14 | test('NoFieldSelectorQueries', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info'])
|
| 15 | +test('HieTypeable', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) |