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
|
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-} -- Outputable FieldLabelString
{-
%
% (c) Adam Gundry 2013-2015
%
Note [FieldLabel]
~~~~~~~~~~~~~~~~~
This module defines the representation of FieldLabels as stored in
TyCons. As well as a selector name, these have some extra structure
to support the DuplicateRecordFields and NoFieldSelectors extensions.
In the normal case (with NoDuplicateRecordFields and FieldSelectors),
a datatype like
data T = MkT { foo :: Int }
has
FieldLabel { flHasDuplicateRecordFields = NoDuplicateRecordFields
, flHasFieldSelector = FieldSelectors
, flSelector = foo }.
If DuplicateRecordFields is enabled, however, the same declaration instead gives
FieldLabel { flHasDuplicateRecordFields = DuplicateRecordFields
, flHasFieldSelector = FieldSelectors
, flSelector = foo }.
We need to keep track of whether FieldSelectors or DuplicateRecordFields were
enabled when a record field was defined, as they affect name resolution and
shadowing of record fields, as explained in Note [NoFieldSelectors] in GHC.Types.Name.Reader
and Note [Reporting duplicate local declarations] in GHC.Rename.Names.
-}
module GHC.Types.FieldLabel
( FieldLabelEnv
, FieldLabel(..), flLabel
, DuplicateRecordFields(..)
, FieldSelectors(..)
, flIsOverloaded
)
where
import GHC.Prelude
import {-# SOURCE #-} GHC.Types.Name
import GHC.Data.FastString.Env
import GHC.Types.Unique (Uniquable(..))
import GHC.Utils.Outputable
import GHC.Utils.Binary
import Language.Haskell.Syntax.Basic (FieldLabelString(..))
import Control.DeepSeq
import Data.Bool
import Data.Data
-- | A map from labels to all the auxiliary information
type FieldLabelEnv = DFastStringEnv FieldLabel
-- | Fields in an algebraic record type; see Note [FieldLabel].
data FieldLabel = FieldLabel {
flHasDuplicateRecordFields :: DuplicateRecordFields,
-- ^ Was @DuplicateRecordFields@ on in the defining module for this datatype?
flHasFieldSelector :: FieldSelectors,
-- ^ Was @FieldSelectors@ enabled in the defining module for this datatype?
-- See Note [NoFieldSelectors] in GHC.Rename.Env
flSelector :: Name
-- ^ The 'Name' of the selector function, which uniquely identifies
-- the field label.
}
deriving (Data, Eq)
-- | User-visible label of a field.
flLabel :: FieldLabel -> FieldLabelString
flLabel = FieldLabelString . occNameFS . nameOccName . flSelector
instance HasOccName FieldLabel where
occName = nameOccName . flSelector
instance Outputable FieldLabel where
ppr fl = ppr (flLabel fl) <> whenPprDebug (braces (ppr (flSelector fl))
<> ppr (flHasDuplicateRecordFields fl)
<> ppr (flHasFieldSelector fl))
instance Outputable FieldLabelString where
ppr (FieldLabelString l) = ppr l
instance Uniquable FieldLabelString where
getUnique (FieldLabelString fs) = getUnique fs
-- | Flag to indicate whether the DuplicateRecordFields extension is enabled.
data DuplicateRecordFields
= DuplicateRecordFields -- ^ Fields may be duplicated in a single module
| NoDuplicateRecordFields -- ^ Fields must be unique within a module (the default)
deriving (Show, Eq, Typeable, Data)
instance Binary DuplicateRecordFields where
put_ bh f = put_ bh (f == DuplicateRecordFields)
get bh = bool NoDuplicateRecordFields DuplicateRecordFields <$> get bh
instance Outputable DuplicateRecordFields where
ppr DuplicateRecordFields = text "+dup"
ppr NoDuplicateRecordFields = text "-dup"
instance NFData DuplicateRecordFields where
rnf DuplicateRecordFields = ()
rnf NoDuplicateRecordFields = ()
-- | Flag to indicate whether the FieldSelectors extension is enabled.
data FieldSelectors
= FieldSelectors -- ^ Selector functions are available (the default)
| NoFieldSelectors -- ^ Selector functions are not available
deriving (Show, Eq, Typeable, Data)
instance Binary FieldSelectors where
put_ bh f = put_ bh (f == FieldSelectors)
get bh = bool NoFieldSelectors FieldSelectors <$> get bh
instance Outputable FieldSelectors where
ppr FieldSelectors = text "+sel"
ppr NoFieldSelectors = text "-sel"
instance NFData FieldSelectors where
rnf FieldSelectors = ()
rnf NoFieldSelectors = ()
-- | We need the @Binary Name@ constraint here even though there is an instance
-- defined in "GHC.Types.Name", because the we have a SOURCE import, so the
-- instance is not in scope. And the instance cannot be added to Name.hs-boot
-- because "GHC.Utils.Binary" itself depends on "GHC.Types.Name".
instance Binary Name => Binary FieldLabel where
put_ bh (FieldLabel aa ab ac) = do
put_ bh aa
put_ bh ab
case getUserData bh of
UserData{ ud_put_binding_name = put_binding_name } ->
put_binding_name bh ac
get bh = do
aa <- get bh
ab <- get bh
ac <- get bh
return (FieldLabel aa ab ac)
flIsOverloaded :: FieldLabel -> Bool
flIsOverloaded fl =
flHasDuplicateRecordFields fl == DuplicateRecordFields
|| flHasFieldSelector fl == NoFieldSelectors
|