diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2019-01-10 12:07:57 +0000 |
---|---|---|
committer | Ben Gamari <ben@well-typed.com> | 2019-01-17 13:39:40 -0500 |
commit | 96e31b5051b2405bb92901718ab6e78db42ac27f (patch) | |
tree | 8ca13f49238aaa3ed3868198be58f1a9abdce64e /compiler | |
parent | 469fe6133646df5568c9486de2202124cb734242 (diff) | |
download | haskell-96e31b5051b2405bb92901718ab6e78db42ac27f.tar.gz |
Comments about data constructor wrappers
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/basicTypes/DataCon.hs | 70 |
1 files changed, 40 insertions, 30 deletions
diff --git a/compiler/basicTypes/DataCon.hs b/compiler/basicTypes/DataCon.hs index de4fd122b3..5f72b51a35 100644 --- a/compiler/basicTypes/DataCon.hs +++ b/compiler/basicTypes/DataCon.hs @@ -172,9 +172,38 @@ The "wrapper Id", \$WC, goes as follows nothing for the wrapper to do. That is, if its defn would be \$wC = C +Note [Data constructor workers and wrappers] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* Algebraic data types + - Always have a worker, with no unfolding + - May or may not have a wrapper; see Note [The need for a wrapper] + +* Newtypes + - Always have a worker, which has a compulsory unfolding (just a cast) + - May or may not have a wrapper; see Note [The need for a wrapper] + +* INVARIANT: the dictionary constructor for a class + never has a wrapper. + +* Neither_ the worker _nor_ the wrapper take the dcStupidTheta dicts as arguments + +* The wrapper (if it exists) takes dcOrigArgTys as its arguments + The worker takes dataConRepArgTys as its arguments + If the worker is absent, dataConRepArgTys is the same as dcOrigArgTys + +* The 'NoDataConRep' case of DataConRep is important. Not only is it + efficient, but it also ensures that the wrapper is replaced by the + worker (because it *is* the worker) even when there are no + args. E.g. in + f (:) x + the (:) *is* the worker. This is really important in rule matching, + (We could match on the wrappers, but that makes it less likely that + rules will match when we bring bits of unfoldings together.) + Note [The need for a wrapper] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Why might the wrapper have anything to do? Two reasons: +Why might the wrapper have anything to do? The full story is +in wrapper_reqd in MkId.mkDataConRep. * Unboxing strict fields (with -funbox-strict-fields) data T = MkT !(Int,Int) @@ -197,12 +226,14 @@ Why might the wrapper have anything to do? Two reasons: The third argument is a coercion [a] :: [a]~[a] -INVARIANT: the dictionary constructor for a class - never has a wrapper. +* Data family instances may do a cast on the result +* Type variables may be permuted; see MkId + Note [Data con wrappers and GADT syntax] -A note about the stupid context -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Note [The stupid context] +~~~~~~~~~~~~~~~~~~~~~~~~~ Data types can have a context: data (Eq a, Ord b) => T a b = T1 a b | T2 a @@ -566,9 +597,12 @@ perspective. -} -- | Data Constructor Representation +-- See Note [Data constructor workers and wrappers] data DataConRep - = NoDataConRep -- No wrapper + = -- NoDataConRep means that the data con has no wrapper + NoDataConRep + -- DCR means that the data con has a wrapper | DCR { dcr_wrap_id :: Id -- Takes src args, unboxes/flattens, -- and constructs the representation @@ -586,30 +620,6 @@ data DataConRep -- See Note [Bangs on data constructor arguments] } --- Algebraic data types always have a worker, and --- may or may not have a wrapper, depending on whether --- the wrapper does anything. --- --- Data types have a worker with no unfolding --- Newtypes just have a worker, which has a compulsory unfolding (just a cast) - --- _Neither_ the worker _nor_ the wrapper take the dcStupidTheta dicts as arguments - --- The wrapper (if it exists) takes dcOrigArgTys as its arguments --- The worker takes dataConRepArgTys as its arguments --- If the worker is absent, dataConRepArgTys is the same as dcOrigArgTys - --- The 'NoDataConRep' case is important --- Not only is this efficient, --- but it also ensures that the wrapper is replaced --- by the worker (because it *is* the worker) --- even when there are no args. E.g. in --- f (:) x --- the (:) *is* the worker. --- This is really important in rule matching, --- (We could match on the wrappers, --- but that makes it less likely that rules will match --- when we bring bits of unfoldings together.) ------------------------- |