Skip to content

Commit

Permalink
Remove custom type errors from Member (#429)
Browse files Browse the repository at this point in the history
* Remove Member type errors

* Remove unused custom type errors

* Deprecate MemberWithError

* Remove readme notes about type errors

* Remove MemberWithError
  • Loading branch information
isovector authored Nov 16, 2021
1 parent ac431a1 commit 5515064
Show file tree
Hide file tree
Showing 15 changed files with 19 additions and 386 deletions.
6 changes: 0 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,6 @@ makes the helpful suggestion:
$ \case
```

Likewise it will give you tips on what to do if you forget a `TypeApplication`
or forget to handle an effect.

Don't like helpful errors? That's OK too - just flip the `error-messages`
flag and enjoy the raw, unadulterated fury of the typesystem.

## Necessary Language Extensions

You're going to want to stick all of this into your `package.yaml` file.
Expand Down
11 changes: 0 additions & 11 deletions package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,6 @@ flags:
description: Dump HTML for the core generated by GHC during compilation
default: False
manual: True
error-messages:
description: Provide custom error messages
default: True
manual: True

library:
ghc-options: -Wall
Expand All @@ -87,13 +83,6 @@ library:
dependencies:
- unsupported-ghc-version > 1 && < 1

- condition: flag(error-messages)
then:
# dummy value because cabal is stupid
cpp-options: -DCABAL_SERIOUSLY_CMON_MATE
else:
cpp-options: -DNO_ERROR_MESSAGES

tests:
polysemy-test:
main: Main.hs
Expand Down
1 change: 0 additions & 1 deletion polysemy-plugin/polysemy-plugin.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ test-suite polysemy-plugin-test
main-is: Main.hs
other-modules:
AmbiguousSpec
BadSpec
DoctestSpec
ExampleSpec
InsertSpec
Expand Down
51 changes: 2 additions & 49 deletions polysemy-plugin/src/Polysemy/Plugin/Fundep.hs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ data FindConstraint = FindConstraint
-- | Given a list of constraints, filter out the 'FindConstraint's.
getFindConstraints :: PolysemyStuff 'Things -> [Ct] -> [FindConstraint]
getFindConstraints (findClass -> cls) cts = do
cd@CDictCan{cc_class = cls', cc_tyargs = [_, eff, r]} <- cts
cd@CDictCan{cc_class = cls', cc_tyargs = [eff, r]} <- cts
guard $ cls == cls'
pure $ FindConstraint
{ fcLoc = ctLoc cd
Expand Down Expand Up @@ -229,53 +229,6 @@ mkWanted fc solve_ctx given =
wanted = fcEffect fc


------------------------------------------------------------------------------
-- | Given a list of 'Ct's, find any that are of the form
-- @[Irred] Sem r a ~ Something@, and return their @r@s.
getBogusRs :: PolysemyStuff 'Things -> [Ct] -> [Type]
getBogusRs stuff wanteds = do
CIrredCan ct _ <- wanteds
(_, [_, _, a, b]) <- pure . splitAppTys $ ctev_pred ct
maybeToList (extractRowFromSem stuff a)
++ maybeToList (extractRowFromSem stuff b)


------------------------------------------------------------------------------
-- | Take the @r@ out of @Sem r a@.
extractRowFromSem :: PolysemyStuff 'Things -> Type -> Maybe Type
extractRowFromSem (semTyCon -> sem) ty = do
(tycon, [r, _]) <- splitTyConApp_maybe ty
guard $ tycon == sem
pure r


------------------------------------------------------------------------------
-- | Given a list of bogus @r@s, and the wanted constraints, produce bogus
-- evidence terms that will prevent @IfStuck (LocateEffect _ r) _ _@ error messsages.
solveBogusError :: PolysemyStuff 'Things -> [Ct] -> [(EvTerm, Ct)]
solveBogusError stuff wanteds = do
let splitTyConApp_list = maybeToList . splitTyConApp_maybe

let bogus = getBogusRs stuff wanteds
ct@(CIrredCan ce _) <- wanteds
(stuck, [_, _, expr, _, _]) <- splitTyConApp_list $ ctev_pred ce
guard $ stuck == ifStuckTyCon stuff
(idx, [_, _, r]) <- splitTyConApp_list expr
guard $ idx == locateEffectTyCon stuff
guard $ elem @[] (OrdType r) $ coerce bogus
pure (error $ unlines
[ "Bogus proof for stuck type family."
, ""
, "This means there's a type error in your program, but the fact that"
, "you're seeing this message is a bug in `polysemy-plugin`."
, ""
, "Please file a bug at https://github.com/polysemy-research/polysemy"
, "with a minimal reproduction for how you managed to get this error."
]
, ct
)


------------------------------------------------------------------------------
-- | Determine if there is exactly one wanted find for the @r@ in question.
exactlyOneWantedForR
Expand Down Expand Up @@ -369,5 +322,5 @@ solveFundep (ref, stuff) given _ wanted = do
let (unifications, new_wanteds) = unzipNewWanteds already_emitted $ catMaybes eqs
tcPluginIO $ modifyIORef ref $ S.union $ S.fromList unifications

pure $ TcPluginOk (solveBogusError stuff wanted) new_wanteds
pure $ TcPluginOk [] new_wanteds

16 changes: 5 additions & 11 deletions polysemy-plugin/src/Polysemy/Plugin/Fundep/Stuff.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ import GHC.Types.Name.Occurrence (mkTcOcc)
import GHC.Tc.Plugin (TcPluginM, tcLookupClass, tcLookupTyCon, unsafeTcPluginTcM)
import GHC.Plugins (getDynFlags, unitState)
import GHC.Unit.State (lookupModuleWithSuggestions, LookupResult (..))
import GHC.Utils.Outputable (pprPanic, empty, text, (<+>), ($$))
import GHC.Utils.Outputable (pprPanic, text, (<+>), ($$))
#else
import FastString (fsLit)
import OccName (mkTcOcc)
import TcPluginM (TcPluginM, tcLookupClass, tcLookupTyCon, unsafeTcPluginTcM)
import GhcPlugins (getDynFlags)
import Packages (lookupModuleWithSuggestions, LookupResult (..))
import Outputable (pprPanic, empty, text, (<+>), ($$))
import Outputable (pprPanic, text, (<+>), ($$))
#endif


Expand All @@ -34,19 +34,15 @@ import Outputable (pprPanic, empty, text, (<+>), ($$))
data PolysemyStuff (l :: LookupState) = PolysemyStuff
{ findClass :: ThingOf l Class
, semTyCon :: ThingOf l TyCon
, ifStuckTyCon :: ThingOf l TyCon
, locateEffectTyCon :: ThingOf l TyCon
}


------------------------------------------------------------------------------
-- | All of the things we need to lookup.
polysemyStuffLocations :: PolysemyStuff 'Locations
polysemyStuffLocations = PolysemyStuff
{ findClass = ("Polysemy.Internal.Union", "Find")
, semTyCon = ("Polysemy.Internal", "Sem")
, ifStuckTyCon = ("Polysemy.Internal.CustomErrors.Redefined", "IfStuck")
, locateEffectTyCon = ("Polysemy.Internal.Union", "LocateEffect")
{ findClass = ("Polysemy.Internal.Union", "Member")
, semTyCon = ("Polysemy.Internal", "Sem")
}


Expand Down Expand Up @@ -79,11 +75,9 @@ polysemyStuff = do
#endif
_ -> pure ()

let PolysemyStuff a b c d = polysemyStuffLocations
let PolysemyStuff a b = polysemyStuffLocations
PolysemyStuff <$> doLookup a
<*> doLookup b
<*> doLookup c
<*> doLookup d


------------------------------------------------------------------------------
Expand Down
16 changes: 1 addition & 15 deletions polysemy-plugin/test/AmbiguousSpec.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE MultiParamTypeClasses #-}

{-# OPTIONS_GHC -fdefer-type-errors #-}
{-# OPTIONS_GHC -fno-warn-deferred-type-errors #-}
{-# OPTIONS_GHC -fplugin=Polysemy.Plugin #-}
{-# OPTIONS_GHC -fplugin=Polysemy.Plugin #-}

module AmbiguousSpec where

Expand Down Expand Up @@ -38,12 +36,6 @@ uniquelyB = put $ mptc False
uniquelyIO :: Members '[Embed IO, Embed Identity] r => Sem r ()
uniquelyIO = embed $ liftIO $ pure ()

ambiguous1 :: Members '[State (Sum Int), State String] r => Sem r ()
ambiguous1 = put mempty

ambiguous2 :: (Num String, Members '[State Int, State String] r) => Sem r ()
ambiguous2 = put 10


spec :: Spec
spec = describe "example" $ do
Expand All @@ -67,9 +59,3 @@ spec = describe "example" $ do
z <- runM . runEmbedded @Identity (pure . runIdentity) $ uniquelyIO
z `shouldBe` ()

it "should not typecheck ambiguous1" $ do
shouldNotTypecheck ambiguous1

it "should not typecheck ambiguous2" $ do
shouldNotTypecheck ambiguous2

38 changes: 0 additions & 38 deletions polysemy-plugin/test/BadSpec.hs

This file was deleted.

9 changes: 0 additions & 9 deletions polysemy.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ flag dump-core
manual: True
default: False

flag error-messages
description: Provide custom error messages
manual: True
default: True

library
exposed-modules:
Polysemy
Expand Down Expand Up @@ -132,10 +127,6 @@ library
if impl(ghc < 8.2.2)
build-depends:
unsupported-ghc-version >1 && <1
if flag(error-messages)
cpp-options: -DCABAL_SERIOUSLY_CMON_MATE
else
cpp-options: -DNO_ERROR_MESSAGES
default-language: Haskell2010

test-suite polysemy-test
Expand Down
1 change: 0 additions & 1 deletion src/Polysemy.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ module Polysemy
( -- * Core Types
Sem ()
, Member
, MemberWithError
, Members

-- * Running Sem
Expand Down
1 change: 0 additions & 1 deletion src/Polysemy/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
module Polysemy.Internal
( Sem (..)
, Member
, MemberWithError
, Members
, send
, sendUsing
Expand Down
81 changes: 1 addition & 80 deletions src/Polysemy/Internal/CustomErrors.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,8 @@
{-# OPTIONS_HADDOCK not-home #-}

module Polysemy.Internal.CustomErrors
( AmbiguousSend
, WhenStuck
( WhenStuck
, FirstOrder
, UnhandledEffect
, DefiningModule
, DefiningModuleForEffect
, type (<>)
, type (%)
) where
Expand All @@ -25,18 +21,6 @@ import Polysemy.Internal.CustomErrors.Redefined
import Type.Errors hiding (IfStuck, WhenStuck, UnlessStuck)


------------------------------------------------------------------------------
-- | The module this effect was originally defined in. This type family is used
-- only for providing better error messages.
--
-- Calls to 'Polysemy.Internal.TH.Effect.makeSem' will automatically give
-- instances of 'DefiningModule'.
type family DefiningModule (t :: k) :: Symbol

type family DefiningModuleForEffect (e :: k) :: Symbol where
DefiningModuleForEffect (e a) = DefiningModuleForEffect e
DefiningModuleForEffect e = DefiningModule e

-- These are taken from type-errors-pretty because it's not in stackage for 9.0.1
-- See https://github.com/polysemy-research/polysemy/issues/401
type family ToErrorMessage (t :: k) :: ErrorMessage where
Expand Down Expand Up @@ -77,51 +61,6 @@ type family ShowRQuoted (rstate :: EffectRowCtor) (r :: EffectRow) :: ErrorMessa
ShowRQuoted 'ConsR r = ShowTypeBracketed r


type AmbigousEffectMessage (rstate :: EffectRowCtor)
(r :: EffectRow)
(e :: k)
(t :: Effect)
(vs :: [Type])
= "Ambiguous use of effect '" <> e <> "'"
% "Possible fix:"
% " add (Member (" <> t <> ") " <> ShowRQuoted rstate r <> ") to the context of "
% " the type signature"
% "If you already have the constraint you want, instead"
% " add a type application to specify"
% " " <> PrettyPrintList vs <> " directly, or activate polysemy-plugin which"
% " can usually infer the type correctly."

type AmbiguousSend e r =
(IfStuck r
(AmbiguousSendError 'TyVarR r e)
(Pure (AmbiguousSendError (UnstuckRState r) r e)))


type family AmbiguousSendError rstate r e where
AmbiguousSendError rstate r (e a b c d f) =
TypeError (AmbigousEffectMessage rstate r e (e a b c d f) '[a, b c d f])

AmbiguousSendError rstate r (e a b c d) =
TypeError (AmbigousEffectMessage rstate r e (e a b c d) '[a, b c d])

AmbiguousSendError rstate r (e a b c) =
TypeError (AmbigousEffectMessage rstate r e (e a b c) '[a, b c])

AmbiguousSendError rstate r (e a b) =
TypeError (AmbigousEffectMessage rstate r e (e a b) '[a, b])

AmbiguousSendError rstate r (e a) =
TypeError (AmbigousEffectMessage rstate r e (e a) '[a])

AmbiguousSendError rstate r e =
TypeError
( "Could not deduce: (Member " <> e <> " " <> ShowRQuoted rstate r <> ") "
% "Fix:"
% " add (Member " <> e <> " " <> r <> ") to the context of"
% " the type signature"
)


data FirstOrderErrorFcf :: k -> Symbol -> Exp Constraint
type instance Eval (FirstOrderErrorFcf e fn) = $(te[t|
UnlessPhantom
Expand All @@ -138,23 +77,5 @@ type instance Eval (FirstOrderErrorFcf e fn) = $(te[t|
type FirstOrder (e :: Effect) fn = UnlessStuck e (FirstOrderErrorFcf e fn)


------------------------------------------------------------------------------
-- | Unhandled effects
type UnhandledEffectMsg e
= "Unhandled effect '" <> e <> "'"
% "Probable fix:"
% " add an interpretation for '" <> e <> "'"

type CheckDocumentation e
= " If you are looking for inspiration, try consulting"
% " the documentation for module '" <> DefiningModuleForEffect e <> "'"

type family UnhandledEffect e where
UnhandledEffect e =
IfStuck (DefiningModule e)
(TypeError (UnhandledEffectMsg e))
(DoError (UnhandledEffectMsg e ':$$: CheckDocumentation e))


data DoError :: ErrorMessage -> Exp k
type instance Eval (DoError a) = TypeError a
Loading

0 comments on commit 5515064

Please sign in to comment.