1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
|
-- (c) The University of Glasgow 2006
-- (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
--
-- The @Class@ datatype
module GHC.Core.Class (
Class,
ClassOpItem,
ClassATItem(..), ATValidityInfo(..),
ClassMinimalDef,
DefMethInfo, pprDefMethInfo,
FunDep, pprFundeps, pprFunDep,
mkClass, mkAbstractClass, classTyVars, classArity,
classKey, className, classATs, classATItems, classTyCon, classMethods,
classOpItems, classBigSig, classExtraBigSig, classTvsFds, classSCTheta,
classAllSelIds, classSCSelId, classSCSelIds, classMinimalDef, classHasFds,
isAbstractClass,
) where
import GHC.Prelude
import {-# SOURCE #-} GHC.Core.TyCon ( TyCon )
import {-# SOURCE #-} GHC.Core.TyCo.Rep ( Type, PredType )
import {-# SOURCE #-} GHC.Core.TyCo.Ppr ( pprType )
import GHC.Types.Var
import GHC.Types.Name
import GHC.Types.Basic
import GHC.Types.Unique
import GHC.Utils.Misc
import GHC.Utils.Panic
import GHC.Utils.Panic.Plain
import GHC.Types.SrcLoc
import GHC.Utils.Outputable
import GHC.Data.BooleanFormula (BooleanFormula, mkTrue)
import qualified Data.Data as Data
{-
************************************************************************
* *
\subsection[Class-basic]{@Class@: basic definition}
* *
************************************************************************
A @Class@ corresponds to a Greek kappa in the static semantics:
-}
data Class
= Class {
classTyCon :: TyCon, -- The data type constructor for
-- dictionaries of this class
-- See Note [ATyCon for classes] in GHC.Core.TyCo.Rep
className :: Name, -- Just the cached name of the TyCon
classKey :: Unique, -- Cached unique of TyCon
classTyVars :: [TyVar], -- The class kind and type variables;
-- identical to those of the TyCon
-- If you want visibility info, look at the classTyCon
-- This field is redundant because it's duplicated in the
-- classTyCon, but classTyVars is used quite often, so maybe
-- it's a bit faster to cache it here
classFunDeps :: [FunDep TyVar], -- The functional dependencies
classBody :: ClassBody -- Superclasses, ATs, methods
}
-- | e.g.
--
-- > class C a b c | a b -> c, a c -> b where...
--
-- Here fun-deps are [([a,b],[c]), ([a,c],[b])]
--
-- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnRarrow'',
-- For details on above see note [exact print annotations] in GHC.Parser.Annotation
type FunDep a = ([a],[a])
type ClassOpItem = (Id, DefMethInfo)
-- Selector function; contains unfolding
-- Default-method info
type DefMethInfo = Maybe (Name, DefMethSpec Type)
-- Nothing No default method
-- Just ($dm, VanillaDM) A polymorphic default method, name $dm
-- Just ($gm, GenericDM ty) A generic default method, name $gm, type ty
-- The generic dm type is *not* quantified
-- over the class variables; ie has the
-- class variables free
data ClassATItem
= ATI TyCon -- See Note [Associated type tyvar names]
(Maybe (Type, ATValidityInfo))
-- Default associated type (if any) from this template
-- Note [Associated type defaults]
-- | Information about an associated type family default implementation. This
-- is used solely for validity checking.
-- See @Note [Type-checking default assoc decls]@ in "GHC.Tc.TyCl".
data ATValidityInfo
= NoATVI -- Used for associated type families that are imported
-- from another module, for which we don't need to
-- perform any validity checking.
| ATVI SrcSpan [Type] -- Used for locally defined associated type families.
-- The [Type] are the LHS patterns.
type ClassMinimalDef = BooleanFormula Name -- Required methods
data ClassBody
= AbstractClass
| ConcreteClass {
-- Superclasses: eg: (F a ~ b, F b ~ G a, Eq a, Show b)
-- We need value-level selectors for both the dictionary
-- superclasses and the equality superclasses
cls_sc_theta :: [PredType], -- Immediate superclasses,
cls_sc_sel_ids :: [Id], -- Selector functions to extract the
-- superclasses from a
-- dictionary of this class
-- Associated types
cls_ats :: [ClassATItem], -- Associated type families
-- Class operations (methods, not superclasses)
cls_ops :: [ClassOpItem], -- Ordered by tag
-- Minimal complete definition
cls_min_def :: ClassMinimalDef
}
-- TODO: maybe super classes should be allowed in abstract class definitions
classMinimalDef :: Class -> ClassMinimalDef
classMinimalDef Class{ classBody = ConcreteClass{ cls_min_def = d } } = d
classMinimalDef _ = mkTrue -- TODO: make sure this is the right direction
{-
Note [Associated type defaults]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The following is an example of associated type defaults:
class C a where
data D a r
type F x a b :: *
type F p q r = (p,q)->r -- Default
Note that
* The TyCons for the associated types *share type variables* with the
class, so that we can tell which argument positions should be
instantiated in an instance decl. (The first for 'D', the second
for 'F'.)
* We can have default definitions only for *type* families,
not data families
* In the default decl, the "patterns" should all be type variables,
but (in the source language) they don't need to be the same as in
the 'type' decl signature or the class. It's more like a
free-standing 'type instance' declaration.
* HOWEVER, in the internal ClassATItem we rename the RHS to match the
tyConTyVars of the family TyCon. So in the example above we'd get
a ClassATItem of
ATI F ((x,a) -> b)
So the tyConTyVars of the family TyCon bind the free vars of
the default Type rhs
The @mkClass@ function fills in the indirect superclasses.
The SrcSpan is for the entire original declaration.
-}
mkClass :: Name -> [TyVar]
-> [FunDep TyVar]
-> [PredType] -> [Id]
-> [ClassATItem]
-> [ClassOpItem]
-> ClassMinimalDef
-> TyCon
-> Class
mkClass cls_name tyvars fds super_classes superdict_sels at_stuff
op_stuff mindef tycon
= Class { classKey = nameUnique cls_name,
className = cls_name,
-- NB: tyConName tycon = cls_name,
-- But it takes a module loop to assert it here
classTyVars = tyvars,
classFunDeps = fds,
classBody = ConcreteClass {
cls_sc_theta = super_classes,
cls_sc_sel_ids = superdict_sels,
cls_ats = at_stuff,
cls_ops = op_stuff,
cls_min_def = mindef
},
classTyCon = tycon }
mkAbstractClass :: Name -> [TyVar]
-> [FunDep TyVar]
-> TyCon
-> Class
mkAbstractClass cls_name tyvars fds tycon
= Class { classKey = nameUnique cls_name,
className = cls_name,
-- NB: tyConName tycon = cls_name,
-- But it takes a module loop to assert it here
classTyVars = tyvars,
classFunDeps = fds,
classBody = AbstractClass,
classTyCon = tycon }
{-
Note [Associated type tyvar names]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The TyCon of an associated type should use the same variable names as its
parent class. Thus
class C a b where
type F b x a :: *
We make F use the same Name for 'a' as C does, and similarly 'b'.
The reason for this is when checking instances it's easier to match
them up, to ensure they match. Eg
instance C Int [d] where
type F [d] x Int = ....
we should make sure that the first and third args match the instance
header.
Having the same variables for class and tycon is also used in checkValidRoles
(in GHC.Tc.TyCl) when checking a class's roles.
************************************************************************
* *
\subsection[Class-selectors]{@Class@: simple selectors}
* *
************************************************************************
The rest of these functions are just simple selectors.
-}
classArity :: Class -> Arity
classArity clas = length (classTyVars clas)
-- Could memoise this
classAllSelIds :: Class -> [Id]
-- Both superclass-dictionary and method selectors
classAllSelIds c@(Class { classBody = ConcreteClass { cls_sc_sel_ids = sc_sels }})
= sc_sels ++ classMethods c
classAllSelIds c = assert (null (classMethods c) ) []
classSCSelIds :: Class -> [Id]
-- Both superclass-dictionary and method selectors
classSCSelIds (Class { classBody = ConcreteClass { cls_sc_sel_ids = sc_sels }})
= sc_sels
classSCSelIds c = assert (null (classMethods c) ) []
classSCSelId :: Class -> Int -> Id
-- Get the n'th superclass selector Id
-- where n is 0-indexed, and counts
-- *all* superclasses including equalities
classSCSelId (Class { classBody = ConcreteClass { cls_sc_sel_ids = sc_sels } }) n
= assert (n >= 0 && lengthExceeds sc_sels n )
sc_sels !! n
classSCSelId c n = pprPanic "classSCSelId" (ppr c <+> ppr n)
classMethods :: Class -> [Id]
classMethods (Class { classBody = ConcreteClass { cls_ops = op_stuff } })
= [op_sel | (op_sel, _) <- op_stuff]
classMethods _ = []
classOpItems :: Class -> [ClassOpItem]
classOpItems (Class { classBody = ConcreteClass { cls_ops = op_stuff }})
= op_stuff
classOpItems _ = []
classATs :: Class -> [TyCon]
classATs (Class { classBody = ConcreteClass { cls_ats = at_stuff } })
= [tc | ATI tc _ <- at_stuff]
classATs _ = []
classATItems :: Class -> [ClassATItem]
classATItems (Class { classBody = ConcreteClass { cls_ats = at_stuff }})
= at_stuff
classATItems _ = []
classSCTheta :: Class -> [PredType]
classSCTheta (Class { classBody = ConcreteClass { cls_sc_theta = theta_stuff }})
= theta_stuff
classSCTheta _ = []
classTvsFds :: Class -> ([TyVar], [FunDep TyVar])
classTvsFds c = (classTyVars c, classFunDeps c)
classHasFds :: Class -> Bool
classHasFds (Class { classFunDeps = fds }) = not (null fds)
classBigSig :: Class -> ([TyVar], [PredType], [Id], [ClassOpItem])
classBigSig (Class {classTyVars = tyvars,
classBody = AbstractClass})
= (tyvars, [], [], [])
classBigSig (Class {classTyVars = tyvars,
classBody = ConcreteClass {
cls_sc_theta = sc_theta,
cls_sc_sel_ids = sc_sels,
cls_ops = op_stuff
}})
= (tyvars, sc_theta, sc_sels, op_stuff)
classExtraBigSig :: Class -> ([TyVar], [FunDep TyVar], [PredType], [Id], [ClassATItem], [ClassOpItem])
classExtraBigSig (Class {classTyVars = tyvars, classFunDeps = fundeps,
classBody = AbstractClass})
= (tyvars, fundeps, [], [], [], [])
classExtraBigSig (Class {classTyVars = tyvars, classFunDeps = fundeps,
classBody = ConcreteClass {
cls_sc_theta = sc_theta, cls_sc_sel_ids = sc_sels,
cls_ats = ats, cls_ops = op_stuff
}})
= (tyvars, fundeps, sc_theta, sc_sels, ats, op_stuff)
isAbstractClass :: Class -> Bool
isAbstractClass Class{ classBody = AbstractClass } = True
isAbstractClass _ = False
{-
************************************************************************
* *
\subsection[Class-instances]{Instance declarations for @Class@}
* *
************************************************************************
We compare @Classes@ by their keys (which include @Uniques@).
-}
instance Eq Class where
c1 == c2 = classKey c1 == classKey c2
c1 /= c2 = classKey c1 /= classKey c2
instance Uniquable Class where
getUnique c = classKey c
instance NamedThing Class where
getName clas = className clas
instance Outputable Class where
ppr c = ppr (getName c)
pprDefMethInfo :: DefMethInfo -> SDoc
pprDefMethInfo Nothing = empty -- No default method
pprDefMethInfo (Just (n, VanillaDM)) = text "Default method" <+> ppr n
pprDefMethInfo (Just (n, GenericDM ty)) = text "Generic default method"
<+> ppr n <+> dcolon <+> pprType ty
pprFundeps :: Outputable a => [FunDep a] -> SDoc
pprFundeps [] = empty
pprFundeps fds = hsep (vbar : punctuate comma (map pprFunDep fds))
pprFunDep :: Outputable a => FunDep a -> SDoc
pprFunDep (us, vs) = hsep [interppSP us, arrow, interppSP vs]
instance Data.Data Class where
-- don't traverse?
toConstr _ = abstractConstr "Class"
gunfold _ _ = error "gunfold"
dataTypeOf _ = mkNoRepType "Class"
|