1
+ {-# LANGUAGE CPP #-}
1
2
{-# LANGUAGE ViewPatterns #-}
2
3
3
4
module Wingman.Judgements.Theta
4
- ( getMethodHypothesisAtHole
5
+ ( Evidence
6
+ , getEvidenceAtHole
7
+ , mkEvidence
8
+ , evidenceToSubst
9
+ , evidenceToHypothesis
5
10
) where
6
11
7
- import Data.Maybe (fromMaybe )
12
+ import Data.Maybe (fromMaybe , mapMaybe )
8
13
import Data.Set (Set )
9
14
import qualified Data.Set as S
10
15
import Development.IDE.GHC.Compat
11
- import Generics.SYB
12
- import GhcPlugins (EvVar , mkVarOcc )
16
+ import Generics.SYB hiding (tyConName )
17
+ import GhcPlugins (mkVarOcc , splitTyConApp_maybe , getTyVar_maybe )
18
+ #if __GLASGOW_HASKELL__ > 806
19
+ import GhcPlugins (eqTyCon )
20
+ #else
21
+ import GhcPlugins (nameRdrName , tyConName )
22
+ import PrelNames (eqTyCon_RDR )
23
+ #endif
24
+ import TcEvidence
25
+ import TcType (tcTyConAppTyCon_maybe )
26
+ import TysPrim (eqPrimTyCon )
13
27
import Wingman.Machinery
14
28
import Wingman.Types
15
29
16
30
17
31
------------------------------------------------------------------------------
18
- -- | Create a 'Hypothesis' containing 'ClassMethodPrv' provenance. For every
19
- -- dictionary that is in scope at the given 'SrcSpan', find every method and
20
- -- superclass method available.
21
- getMethodHypothesisAtHole :: SrcSpan -> LHsBinds GhcTc -> Hypothesis CType
22
- getMethodHypothesisAtHole dst
23
- = Hypothesis
24
- . excludeForbiddenMethods
25
- . fromMaybe []
26
- . foldMap methodHypothesis
27
- . (everything (<>) $ mkQ mempty $ evbinds dst)
32
+ -- | Something we've learned about the type environment.
33
+ data Evidence
34
+ -- | The two types are equal, via a @a ~ b@ relationship
35
+ = EqualityOfTypes Type Type
36
+ -- | We have an instance in scope
37
+ | HasInstance PredType
38
+ deriving (Show )
39
+
40
+
41
+ ------------------------------------------------------------------------------
42
+ -- | Given a 'PredType', pull an 'Evidence' out of it.
43
+ mkEvidence :: PredType -> Maybe Evidence
44
+ mkEvidence (getEqualityTheta -> Just (a, b))
45
+ = Just $ EqualityOfTypes a b
46
+ mkEvidence inst@ (tcTyConAppTyCon_maybe -> Just (isClassTyCon -> True ))
47
+ = Just $ HasInstance inst
48
+ mkEvidence _ = Nothing
49
+
50
+
51
+ ------------------------------------------------------------------------------
52
+ -- | Compute all the 'Evidence' implicitly bound at the given 'SrcSpan'.
53
+ getEvidenceAtHole :: SrcSpan -> LHsBinds GhcTc -> [Evidence ]
54
+ getEvidenceAtHole dst
55
+ = mapMaybe mkEvidence
56
+ . (everything (<>) $
57
+ mkQ mempty (absBinds dst) `extQ` wrapperBinds dst `extQ` matchBinds dst)
58
+
59
+
60
+ ------------------------------------------------------------------------------
61
+ -- | Update our knowledge of which types are equal.
62
+ evidenceToSubst :: Evidence -> TacticState -> TacticState
63
+ evidenceToSubst (EqualityOfTypes a b) ts =
64
+ let tyvars = S. fromList $ mapMaybe getTyVar_maybe [a, b]
65
+ -- If we can unify our skolems, at least one is no longer a skolem.
66
+ -- Removing them from this set ensures we can get a subtitution between
67
+ -- the two. But it's okay to leave them in 'ts_skolems' in general, since
68
+ -- they won't exist after running this substitution.
69
+ skolems = ts_skolems ts S. \\ tyvars
70
+ in
71
+ case tryUnifyUnivarsButNotSkolems skolems (CType a) (CType b) of
72
+ Just subst -> updateSubst subst ts
73
+ Nothing -> ts
74
+ evidenceToSubst HasInstance {} ts = ts
75
+
76
+
77
+ ------------------------------------------------------------------------------
78
+ -- | Get all of the methods that are in scope from this piece of 'Evidence'.
79
+ evidenceToHypothesis :: Evidence -> Hypothesis CType
80
+ evidenceToHypothesis EqualityOfTypes {} = mempty
81
+ evidenceToHypothesis (HasInstance t) =
82
+ Hypothesis . excludeForbiddenMethods . fromMaybe [] $ methodHypothesis t
83
+
84
+
85
+ ------------------------------------------------------------------------------
86
+ -- | Given @a ~ b@ or @a ~# b@, returns @Just (a, b)@, otherwise @Nothing@.
87
+ getEqualityTheta :: PredType -> Maybe (Type , Type )
88
+ getEqualityTheta (splitTyConApp_maybe -> Just (tc, [_k, a, b]))
89
+ #if __GLASGOW_HASKELL__ > 806
90
+ | tc == eqTyCon
91
+ #else
92
+ | nameRdrName (tyConName tc) == eqTyCon_RDR
93
+ #endif
94
+ = Just (a, b)
95
+ getEqualityTheta (splitTyConApp_maybe -> Just (tc, [_k1, _k2, a, b]))
96
+ | tc == eqPrimTyCon = Just (a, b)
97
+ getEqualityTheta _ = Nothing
28
98
29
99
30
100
------------------------------------------------------------------------------
@@ -38,13 +108,48 @@ excludeForbiddenMethods = filter (not . flip S.member forbiddenMethods . hi_name
38
108
forbiddenMethods = S. map mkVarOcc $ S. fromList
39
109
[ -- monadfail
40
110
" fail"
111
+ -- show
112
+ , " showsPrec"
113
+ , " showList"
41
114
]
42
115
43
116
44
117
------------------------------------------------------------------------------
45
- -- | Extract the types of the evidence bindings in scope.
46
- evbinds :: SrcSpan -> LHsBindLR GhcTc GhcTc -> [PredType ]
47
- evbinds dst (L src (AbsBinds _ _ h _ _ _ _))
118
+ -- | Extract evidence from 'AbsBinds' in scope.
119
+ absBinds :: SrcSpan -> LHsBindLR GhcTc GhcTc -> [PredType ]
120
+ absBinds dst (L src (AbsBinds _ _ h _ _ _ _))
48
121
| dst `isSubspanOf` src = fmap idType h
49
- evbinds _ _ = []
122
+ absBinds _ _ = []
123
+
124
+
125
+ ------------------------------------------------------------------------------
126
+ -- | Extract evidence from 'HsWrapper's in scope
127
+ wrapperBinds :: SrcSpan -> LHsExpr GhcTc -> [PredType ]
128
+ wrapperBinds dst (L src (HsWrap _ h _))
129
+ | dst `isSubspanOf` src = wrapper h
130
+ wrapperBinds _ _ = []
131
+
132
+
133
+ ------------------------------------------------------------------------------
134
+ -- | Extract evidence from the 'ConPatOut's bound in this 'Match'.
135
+ matchBinds :: SrcSpan -> LMatch GhcTc (LHsExpr GhcTc ) -> [PredType ]
136
+ matchBinds dst (L src (Match _ _ pats _))
137
+ | dst `isSubspanOf` src = everything (<>) (mkQ mempty patBinds) pats
138
+ matchBinds _ _ = []
139
+
140
+
141
+ ------------------------------------------------------------------------------
142
+ -- | Extract evidence from a 'ConPatOut'.
143
+ patBinds :: Pat GhcTc -> [PredType ]
144
+ patBinds (ConPatOut { pat_dicts = dicts })
145
+ = fmap idType dicts
146
+ patBinds _ = []
147
+
148
+
149
+ ------------------------------------------------------------------------------
150
+ -- | Extract the types of the evidence bindings in scope.
151
+ wrapper :: HsWrapper -> [PredType ]
152
+ wrapper (WpCompose h h2) = wrapper h <> wrapper h2
153
+ wrapper (WpEvLam v) = [idType v]
154
+ wrapper _ = []
50
155
0 commit comments