Skip to content

GHC-9.0 support for hls-tactics-plugin #2581

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Jan 19, 2022
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
40b77d8
Initial partially broken ghc9 support for tactics
anka-213 Sep 16, 2021
3741044
Merge branch 'master' into tactics-ghc90
jneira Sep 17, 2021
caba0ca
Enable tactics plugin for nix as well
anka-213 Sep 17, 2021
cda6971
Wingman does support ghc9 now
anka-213 Sep 18, 2021
dec5fc3
Fix stack support for tactics ghc-9.0.1
anka-213 Sep 18, 2021
d382412
Enable tests for tactics on ghc-9 on ci
anka-213 Sep 18, 2021
ed528be
Actually enable tactics for ghc-9 on nix
anka-213 Sep 18, 2021
1474188
Wingman: Improve test failure messages
anka-213 Sep 18, 2021
75a7d85
Merge branch 'master' into tactics-ghc90
anka-213 Sep 20, 2021
dc2c5d7
Merge branch 'tactics-ghc90' of https://github.com/anka-213/haskell-l…
isovector Jan 12, 2022
2a9ea27
Get theta
isovector Jan 12, 2022
0aa62a1
Make wrapper theta discovery more reliable
isovector Jan 12, 2022
4460c6c
Fix AutoThetaRankN
isovector Jan 12, 2022
a208dda
Fix FmapJoin and FmapJoinInLet
isovector Jan 12, 2022
67ddf23
Fix MetaBegin
isovector Jan 12, 2022
86d63ff
Cleanup
isovector Jan 12, 2022
fa3e916
Merge branch 'master' into anka-213-tactics-ghc90
isovector Jan 12, 2022
ec8e439
Fix merge
isovector Jan 12, 2022
8dc0e63
Merge branch 'master' into anka-213-tactics-ghc90
isovector Jan 13, 2022
21779f9
Need a comma
isovector Jan 13, 2022
a812243
Try a better ConPatIn
isovector Jan 16, 2022
1440350
Oops
isovector Jan 16, 2022
fe01a29
its a nightmare
isovector Jan 16, 2022
b72ee1a
i hate ci
isovector Jan 16, 2022
8d1a052
ok that fixes the conpat
isovector Jan 17, 2022
c0082bc
Maybe this is the end of it
isovector Jan 17, 2022
254f8e4
ci
isovector Jan 17, 2022
68f79e3
Merge branch 'master' into anka-213-tactics-ghc90
isovector Jan 17, 2022
c0e67f2
refinery
isovector Jan 17, 2022
8d285a6
undo some changes
isovector Jan 17, 2022
1700d9b
no more tctypes?
isovector Jan 17, 2022
168d918
maybe it builds now
isovector Jan 17, 2022
df025ea
omg
isovector Jan 17, 2022
449a451
om F g
isovector Jan 17, 2022
688d946
expect fail on 9.2
isovector Jan 18, 2022
17eaad2
Merge branch 'master' into anka-213-tactics-ghc90
isovector Jan 19, 2022
a22dd48
fix
isovector Jan 19, 2022
30723f7
fix again
isovector Jan 19, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ jobs:
name: Test hls-fourmolu-plugin
run: cabal test hls-fourmolu-plugin --test-options="$TEST_OPTS" || cabal test hls-fourmolu-plugin --test-options="$TEST_OPTS" || LSP_TEST_LOG_COLOR=0 LSP_TEST_LOG_MESSAGES=true LSP_TEST_LOG_STDERR=true cabal test hls-fourmolu-plugin --test-options="$TEST_OPTS"

- if: matrix.test && matrix.ghc != '9.0.1' && matrix.ghc != '9.0.2' && matrix.ghc != '9.2.1' && !(matrix.os == 'ubuntu-latest' && matrix.ghc == '8.6.5')
- if: matrix.test && matrix.ghc != '9.2.1'
name: Test hls-tactics-plugin test suite
run: cabal test hls-tactics-plugin --test-options="$TEST_OPTS" || cabal test hls-tactics-plugin --test-options="$TEST_OPTS" || LSP_TEST_LOG_COLOR=0 LSP_TEST_LOG_MESSAGES=true LSP_TEST_LOG_STDERR=true cabal test hls-tactics-plugin --test-options="$TEST_OPTS"

Expand Down
2 changes: 1 addition & 1 deletion cabal-ghc90.project
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ index-state: 2022-01-11T22:05:45Z
constraints:
-- These plugins don't work on GHC9 yet
-- Add a plugin needs remove the -flag but also update ghc bounds in hls.cabal
haskell-language-server +ignore-plugins-ghc-bounds -stylishhaskell -tactic,
haskell-language-server +ignore-plugins-ghc-bounds -stylishhaskell,
ghc-lib-parser ^>= 9.0

-- although we are not building all plugins cabal solver phase is run for all packages
Expand Down
2 changes: 0 additions & 2 deletions configuration-ghc-901.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

let
disabledPlugins = [
"hls-tactics-plugin"
"hls-brittany-plugin"
"hls-stylish-haskell-plugin"
];
Expand All @@ -20,7 +19,6 @@ let
(pkgs.lib.concatStringsSep " " [
"-f-brittany"
"-f-stylishhaskell"
"-f-tactic"
]) { };

# YOLO
Expand Down
20 changes: 20 additions & 0 deletions ghcide/src/Development/IDE/GHC/Compat/Core.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ module Development.IDE.GHC.Compat.Core (
-- slightly unsafe
setUnsafeGlobalDynFlags,
-- * Linear Haskell
#if !MIN_VERSION_ghc(9,0,0)
Scaled,
unrestricted,
#endif
scaledThing,
-- * Interface Files
IfaceExport,
Expand Down Expand Up @@ -127,6 +130,7 @@ module Development.IDE.GHC.Compat.Core (
TyCoRep.CoercionTy
),
pattern FunTy,
pattern ConPatIn,
#if !MIN_VERSION_ghc(9,2,0)
Development.IDE.GHC.Compat.Core.splitForAllTyCoVars,
#endif
Expand Down Expand Up @@ -536,6 +540,7 @@ import GHC.Parser.Header hiding (getImports)
import qualified GHC.Linker.Loader as Linker
import GHC.Linker.Types
import GHC.Parser.Lexer hiding (initParserState)
import GHC.Parser.Annotation (EpAnn (..))
import GHC.Platform.Ways
import GHC.Runtime.Context (InteractiveImport (..))
#else
Expand Down Expand Up @@ -876,6 +881,9 @@ dataConExTyCoVars = DataCon.dataConExTyVars
type Scaled a = a
scaledThing :: Scaled a -> a
scaledThing = id

unrestricted :: a -> Scaled a
unrestricted = id
#endif

mkVisFunTys :: [Scaled Type] -> Type -> Type
Expand Down Expand Up @@ -952,6 +960,18 @@ type PlainGhcException = Plain.PlainGhcException
type PlainGhcException = Plain.GhcException
#endif

#if MIN_VERSION_ghc(9,0,0)
-- This is from the old api, but it still simplifies
pattern ConPatIn :: SrcLoc.Located (ConLikeP GhcPs) -> HsConPatDetails GhcPs -> Pat GhcPs
#if MIN_VERSION_ghc(9,2,0)
pattern ConPatIn con args <- ConPat EpAnnNotUsed (L _ (SrcLoc.noLoc -> con)) args
where
ConPatIn con args = ConPat EpAnnNotUsed (GHC.noLocA $ SrcLoc.unLoc con) args
#else
pattern ConPatIn con args = ConPat NoExtField con args
#endif
#endif

initDynLinker, initObjLinker :: HscEnv -> IO ()
initDynLinker =
#if !MIN_VERSION_ghc(9,0,0)
Expand Down
3 changes: 2 additions & 1 deletion plugins/hls-tactics-plugin/src/Wingman/AbstractLSP.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import Language.LSP.Types hiding (CodeLens, CodeAction)
import Wingman.AbstractLSP.Types
import Wingman.EmptyCase (fromMaybeT)
import Wingman.LanguageServer (getTacticConfig, getIdeDynflags, mkWorkspaceEdits, runStaleIde, showLspMessage, mkShowMessageParams)
import Wingman.StaticPlugin (enableQuasiQuotes)
import Wingman.Types


Expand Down Expand Up @@ -110,7 +111,7 @@ runContinuation plId cont state (fc, b) = do
GraftEdit gr -> do
ccs <- lift getClientCapabilities
TrackedStale pm _ <- mapMaybeT liftIO $ stale GetAnnotatedParsedSource
case mkWorkspaceEdits le_dflags ccs (fc_uri le_fileContext) (unTrack pm) gr of
case mkWorkspaceEdits (enableQuasiQuotes le_dflags) ccs (fc_uri le_fileContext) (unTrack pm) gr of
Left errs ->
pure $ Just $ ResponseError
{ _code = InternalError
Expand Down
9 changes: 7 additions & 2 deletions plugins/hls-tactics-plugin/src/Wingman/CodeGen.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE OverloadedStrings #-}
Expand Down Expand Up @@ -56,7 +57,7 @@ destructMatches use_field_puns f scrut t jdg = do
Just (dcs, apps) ->
fmap unzipTrace $ for dcs $ \dc -> do
let con = RealDataCon dc
ev = concatMap mkEvidence $ dataConInstArgTys dc apps
ev = concatMap (mkEvidence . scaledThing) $ dataConInstArgTys dc apps
-- We explicitly do not need to add the method hypothesis to
-- #syn_scoped
method_hy = foldMap evidenceToHypothesis ev
Expand Down Expand Up @@ -184,7 +185,7 @@ conLikeInstOrigArgTys'
-- ^ Types of arguments to the ConLike with returned type is instantiated with the second argument.
conLikeInstOrigArgTys' con uniTys =
let exvars = conLikeExTys con
in conLikeInstOrigArgTys con $
in fmap scaledThing $ conLikeInstOrigArgTys con $
uniTys ++ fmap mkTyVarTy exvars
-- Rationale: At least in GHC <= 8.10, 'dataConInstOrigArgTys'
-- unifies the second argument with DataCon's universals followed by existentials.
Expand Down Expand Up @@ -228,7 +229,11 @@ destructLambdaCase' use_field_puns f jdg = do
when (isDestructBlacklisted jdg) cut -- throwError NoApplicableTactic
let g = jGoal jdg
case splitFunTy_maybe (unCType g) of
#if __GLASGOW_HASKELL__ >= 900
Just (_multiplicity, arg, _) | isAlgType arg ->
#else
Just (arg, _) | isAlgType arg ->
#endif
fmap (fmap noLoc lambdaCase) <$>
destructMatches use_field_puns f Nothing (CType arg) jdg
_ -> cut -- throwError $ GoalMismatch "destructLambdaCase'" g
Expand Down
6 changes: 6 additions & 0 deletions plugins/hls-tactics-plugin/src/Wingman/Context.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{-# LANGUAGE CPP #-}

module Wingman.Context where

import Control.Arrow
Expand All @@ -12,6 +14,10 @@ import Wingman.GHC (normalizeType)
import Wingman.Judgements.Theta
import Wingman.Types

#if __GLASGOW_HASKELL__ >= 900
import GHC.Tc.Utils.TcType
#endif


mkContext
:: Config
Expand Down
2 changes: 1 addition & 1 deletion plugins/hls-tactics-plugin/src/Wingman/EmptyCase.hs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ scrutinzedType :: EmptyCaseSort Type -> Maybe Type
scrutinzedType (EmptyCase ty) = pure ty
scrutinzedType (EmptyLamCase ty) =
case tacticsSplitFunTy ty of
(_, _, tys, _) -> listToMaybe tys
(_, _, tys, _) -> listToMaybe $ fmap scaledThing tys


------------------------------------------------------------------------------
Expand Down
16 changes: 14 additions & 2 deletions plugins/hls-tactics-plugin/src/Wingman/GHC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import Generics.SYB (Data, everything, everywhere, listify, mkQ, mkT)
import Wingman.StaticPlugin (pattern MetaprogramSyntax)
import Wingman.Types

#if __GLASGOW_HASKELL__ >= 900
import GHC.Tc.Utils.TcType
#endif


tcTyVar_maybe :: Type -> Maybe Var
tcTyVar_maybe ty | Just ty' <- tcView ty = tcTyVar_maybe ty'
Expand Down Expand Up @@ -57,7 +61,7 @@ isFunction _ = True
------------------------------------------------------------------------------
-- | Split a function, also splitting out its quantified variables and theta
-- context.
tacticsSplitFunTy :: Type -> ([TyVar], ThetaType, [Type], Type)
tacticsSplitFunTy :: Type -> ([TyVar], ThetaType, [Scaled Type], Type)
tacticsSplitFunTy t
= let (vars, theta, t') = tcSplitNestedSigmaTys t
(args, res) = tcSplitFunTys t'
Expand Down Expand Up @@ -179,7 +183,11 @@ allOccNames = everything (<>) $ mkQ mempty $ \case

------------------------------------------------------------------------------
-- | Unpack the relevant parts of a 'Match'
#if __GLASGOW_HASKELL__ >= 900
pattern AMatch :: HsMatchContext (NoGhcTc GhcPs) -> [Pat GhcPs] -> HsExpr GhcPs -> Match GhcPs (LHsExpr GhcPs)
#else
pattern AMatch :: HsMatchContext (NameOrRdrName (IdP GhcPs)) -> [Pat GhcPs] -> HsExpr GhcPs -> Match GhcPs (LHsExpr GhcPs)
#endif
pattern AMatch ctx pats body <-
Match { m_ctxt = ctx
, m_pats = fmap fromPatCompat -> pats
Expand All @@ -192,7 +200,7 @@ pattern SingleLet bind pats val expr <-
HsLet _
(HsValBinds _
(ValBinds _ (bagToList ->
[(L _ (FunBind _ (L _ bind) (MG _ (L _ [L _ (AMatch _ pats val)]) _) _ _))]) _))
[L _ (FunBind {fun_id = (L _ bind), fun_matches = (MG _ (L _ [L _ (AMatch _ pats val)]) _)})]) _))
(L _ expr)


Expand Down Expand Up @@ -255,7 +263,11 @@ pattern LamCase matches <-
-- @Just False@ if it can't be homomorphic
-- @Just True@ if it can
lambdaCaseable :: Type -> Maybe Bool
#if __GLASGOW_HASKELL__ >= 900
lambdaCaseable (splitFunTy_maybe -> Just (_multiplicity, arg, res))
#else
lambdaCaseable (splitFunTy_maybe -> Just (arg, res))
#endif
| isJust (algebraicTyCon arg)
= Just $ isJust $ algebraicTyCon res
lambdaCaseable _ = Nothing
Expand Down
33 changes: 29 additions & 4 deletions plugins/hls-tactics-plugin/src/Wingman/Judgements/Theta.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ import GHC.Generics
import Wingman.GHC
import Wingman.Types

#if __GLASGOW_HASKELL__ >= 900
import GHC.Tc.Utils.TcType
#endif


------------------------------------------------------------------------------
-- | Something we've learned about the type environment.
Expand Down Expand Up @@ -172,31 +176,52 @@ excludeForbiddenMethods = filter (not . flip S.member forbiddenMethods . hi_name
------------------------------------------------------------------------------
-- | Extract evidence from 'AbsBinds' in scope.
absBinds :: SrcSpan -> LHsBindLR GhcTc GhcTc -> [PredType]
#if __GLASGOW_HASKELL__ >= 900
absBinds dst (L src (FunBind w _ _ _))
| dst `isSubspanOf` src
= wrapper w
absBinds dst (L src (AbsBinds _ _ h _ _ z _))
#else
absBinds dst (L src (AbsBinds _ _ h _ _ _ _))
| dst `isSubspanOf` src = fmap idType h
#endif
| dst `isSubspanOf` src
= fmap idType h
#if __GLASGOW_HASKELL__ >= 900
<> foldMap (absBinds dst) z
#endif
absBinds _ _ = []


------------------------------------------------------------------------------
-- | Extract evidence from 'HsWrapper's in scope
wrapperBinds :: SrcSpan -> LHsExpr GhcTc -> [PredType]
#if __GLASGOW_HASKELL__ >= 900
wrapperBinds dst (L src (XExpr (WrapExpr (HsWrap h _))))
#else
wrapperBinds dst (L src (HsWrap _ h _))
| dst `isSubspanOf` src = wrapper h
#endif
| dst `isSubspanOf` src
= wrapper h
wrapperBinds _ _ = []


------------------------------------------------------------------------------
-- | Extract evidence from the 'ConPatOut's bound in this 'Match'.
matchBinds :: SrcSpan -> LMatch GhcTc (LHsExpr GhcTc) -> [PredType]
matchBinds dst (L src (Match _ _ pats _))
| dst `isSubspanOf` src = everything (<>) (mkQ mempty patBinds) pats
| dst `isSubspanOf` src
= everything (<>) (mkQ mempty patBinds) pats
matchBinds _ _ = []


------------------------------------------------------------------------------
-- | Extract evidence from a 'ConPatOut'.
patBinds :: Pat GhcTc -> [PredType]
patBinds ConPatOut{ pat_dicts = dicts }
#if __GLASGOW_HASKELL__ >= 900
patBinds (ConPat{ pat_con_ext = ConPatTc { cpt_dicts = dicts }})
#else
patBinds (ConPatOut { pat_dicts = dicts })
#endif
= fmap idType dicts
patBinds _ = []

Expand Down
14 changes: 11 additions & 3 deletions plugins/hls-tactics-plugin/src/Wingman/LanguageServer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,8 @@ getAlreadyDestructed (unTrack -> span) (unTrack -> binds) =

getSpanAndTypeAtHole
:: Tracked age Range
-> Tracked age (HieASTs b)
-> Maybe (Tracked age RealSrcSpan, b)
-> Tracked age (HieASTs Type)
-> Maybe (Tracked age RealSrcSpan, Type)
getSpanAndTypeAtHole r@(unTrack -> range) (unTrack -> hf) = do
join $ listToMaybe $ M.elems $ flip M.mapWithKey (getAsts hf) $ \fs ast ->
case selectSmallestContaining (rangeToRealSrcSpan (FastString.unpackFS fs) range) ast of
Expand Down Expand Up @@ -402,7 +402,11 @@ buildPatHy prov (fromPatCompat -> p0) =
(RealDataCon $ tupleDataCon boxity $ length pats)
tys
$ zip [0.. ] pats
ConPatOut (L _ con) args _ _ _ f _ ->
#if __GLASGOW_HASKELL__ >= 900
ConPat {pat_con = (L _ con), pat_con_ext = ConPatTc {cpt_arg_tys = args}, pat_args = f} ->
#else
ConPatOut {pat_con = (L _ con), pat_arg_tys = args, pat_args = f} ->
#endif
case f of
PrefixCon l_pgt ->
mkDerivedConHypothesis prov con args $ zip [0..] l_pgt
Expand Down Expand Up @@ -563,7 +567,11 @@ wingmanRules plId = do
L span (HsVar _ (L _ name))
| isHole (occName name) ->
maybeToList $ srcSpanToRange span
#if __GLASGOW_HASKELL__ >= 900
L span (HsUnboundVar _ occ)
#else
L span (HsUnboundVar _ (TrueExprHole occ))
#endif
| isHole occ ->
maybeToList $ srcSpanToRange span
#if __GLASGOW_HASKELL__ <= 808
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ homoFilter codomain domain =
liftLambdaCase :: r -> (Type -> Type -> r) -> Type -> r
liftLambdaCase nil f t =
case tacticsSplitFunTy t of
(_, _, arg : _, res) -> f res arg
(_, _, arg : _, res) -> f res $ scaledThing arg
_ -> nil


Expand Down
10 changes: 8 additions & 2 deletions plugins/hls-tactics-plugin/src/Wingman/Naming.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{-# LANGUAGE CPP #-}

module Wingman.Naming where

import Control.Arrow
Expand All @@ -18,6 +20,10 @@ import Development.IDE.GHC.Compat.Core hiding (IsFunction)
import Text.Hyphenation (hyphenate, english_US)
import Wingman.GHC (tcTyVar_maybe)

#if __GLASGOW_HASKELL__ >= 900
import GHC.Tc.Utils.TcType
#endif


------------------------------------------------------------------------------
-- | A classification of a variable, for which we have specific naming rules.
Expand All @@ -38,11 +44,11 @@ data Purpose

pattern IsPredicate :: Type
pattern IsPredicate <-
(tcSplitFunTys -> ([isFunTy -> False], isBoolTy -> True))
(tcSplitFunTys -> ([isFunTy . scaledThing -> False], isBoolTy -> True))

pattern IsFunction :: [Type] -> Type -> Type
pattern IsFunction args res <-
(tcSplitFunTys -> (args@(_:_), res))
(first (map scaledThing) . tcSplitFunTys -> (args@(_:_), res))

pattern IsString :: Type
pattern IsString <-
Expand Down
5 changes: 5 additions & 0 deletions plugins/hls-tactics-plugin/src/Wingman/StaticPlugin.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
module Wingman.StaticPlugin
( staticPlugin
, metaprogramHoleName
, enableQuasiQuotes
, pattern WingmanMetaprogram
, pattern MetaprogramSyntax
) where
Expand All @@ -13,7 +14,11 @@ import Development.IDE.GHC.Compat.Util
import GHC.LanguageExtensions.Type (Extension(EmptyCase, QuasiQuotes))
import Generics.SYB
import Ide.Types
#if __GLASGOW_HASKELL__ >= 900
import GHC.Driver.Plugins (purePlugin)
#else
import Plugins (purePlugin)
#endif

staticPlugin :: DynFlagsModifications
staticPlugin = mempty
Expand Down
Loading