diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/basicTypes/OccName.lhs | 53 | ||||
-rw-r--r-- | compiler/hsSyn/Convert.lhs | 25 | ||||
-rw-r--r-- | compiler/iface/IfaceEnv.lhs | 40 | ||||
-rw-r--r-- | compiler/prelude/PrelNames.lhs | 97 | ||||
-rw-r--r-- | compiler/prelude/TysWiredIn.lhs | 70 |
5 files changed, 150 insertions, 135 deletions
diff --git a/compiler/basicTypes/OccName.lhs b/compiler/basicTypes/OccName.lhs index 81f7e5dee2..e870c46d7f 100644 --- a/compiler/basicTypes/OccName.lhs +++ b/compiler/basicTypes/OccName.lhs @@ -51,7 +51,6 @@ module OccName ( mkTcOcc, mkTcOccFS, mkClsOcc, mkClsOccFS, mkDFunOcc, - mkTupleOcc, setOccNameSpace, demoteOccName, HasOccName(..), @@ -82,8 +81,6 @@ module OccName ( isTcClsNameSpace, isTvNameSpace, isDataConNameSpace, isVarNameSpace, isValNameSpace, - isTupleOcc_maybe, - -- * The 'OccEnv' type OccEnv, emptyOccEnv, unitOccEnv, extendOccEnv, mapOccEnv, lookupOccEnv, mkOccEnv, mkOccEnv_C, extendOccEnvList, elemOccEnv, @@ -108,7 +105,6 @@ module OccName ( import Util import Unique -import BasicTypes import DynFlags import UniqFM import UniqSet @@ -812,55 +808,6 @@ tidyOccName env occ@(OccName occ_sp fs) %************************************************************************ %* * - Stuff for dealing with tuples -%* * -%************************************************************************ - -\begin{code} -mkTupleOcc :: NameSpace -> TupleSort -> Arity -> OccName -mkTupleOcc ns sort ar = OccName ns (mkFastString str) - where - -- no need to cache these, the caching is done in the caller - -- (TysWiredIn.mk_tuple) - str = case sort of - UnboxedTuple -> '(' : '#' : commas ++ "#)" - BoxedTuple -> '(' : commas ++ ")" - ConstraintTuple -> '(' : commas ++ ")" - -- Cute hack: reuse the standard tuple OccNames (and hence code) - -- for fact tuples, but give them different Uniques so they are not equal. - -- - -- You might think that this will go wrong because isTupleOcc_maybe won't - -- be able to tell the difference between boxed tuples and fact tuples. BUT: - -- 1. Fact tuples never occur directly in user code, so it doesn't matter - -- that we can't detect them in Orig OccNames originating from the user - -- programs (or those built by setRdrNameSpace used on an Exact tuple Name) - -- 2. Interface files have a special representation for tuple *occurrences* - -- in IfaceTyCons, their workers (in IfaceSyn) and their DataCons (in case - -- alternatives). Thus we don't rely on the OccName to figure out what kind - -- of tuple an occurrence was trying to use in these situations. - -- 3. We *don't* represent tuple data type declarations specially, so those - -- are still turned into wired-in names via isTupleOcc_maybe. But that's OK - -- because we don't actually need to declare fact tuples thanks to this hack. - -- - -- So basically any OccName like (,,) flowing to isTupleOcc_maybe will always - -- refer to the standard boxed tuple. Cool :-) - - commas = take (ar-1) (repeat ',') - -isTupleOcc_maybe :: OccName -> Maybe (NameSpace, TupleSort, Arity) --- Tuples are special, because there are so many of them! -isTupleOcc_maybe (OccName ns fs) - = case unpackFS fs of - '(':'#':',':rest -> Just (ns, UnboxedTuple, 2 + count_commas rest) - '(':',':rest -> Just (ns, BoxedTuple, 2 + count_commas rest) - _other -> Nothing - where - count_commas (',':rest) = 1 + count_commas rest - count_commas _ = 0 -\end{code} - -%************************************************************************ -%* * \subsection{Lexical categories} %* * %************************************************************************ diff --git a/compiler/hsSyn/Convert.lhs b/compiler/hsSyn/Convert.lhs index 9996e620f0..1a821e9485 100644 --- a/compiler/hsSyn/Convert.lhs +++ b/compiler/hsSyn/Convert.lhs @@ -1112,8 +1112,10 @@ thRdrName loc ctxt_ns th_occ th_name TH.NameQ mod -> (mkRdrQual $! mk_mod mod) $! occ TH.NameL uniq -> nameRdrName $! (((Name.mkInternalName $! mk_uniq uniq) $! occ) loc) TH.NameU uniq -> nameRdrName $! (((Name.mkSystemNameAt $! mk_uniq uniq) $! occ) loc) - TH.NameS | Just name <- isBuiltInOcc ctxt_ns th_occ -> nameRdrName $! name - | otherwise -> mkRdrUnqual $! occ + TH.NameS | Just name <- isBuiltInOcc_maybe occ -> nameRdrName $! name + | otherwise -> mkRdrUnqual $! occ + -- We check for built-in syntax here, because the TH + -- user might have written a (NameS "(,,)"), for example where occ :: OccName.OccName occ = mk_occ ctxt_ns th_occ @@ -1133,25 +1135,6 @@ thRdrNameGuesses (TH.Name occ flavour) | otherwise = [OccName.varName, OccName.tvName] occ_str = TH.occString occ -isBuiltInOcc :: OccName.NameSpace -> String -> Maybe Name.Name --- Built in syntax isn't "in scope" so an Unqual RdrName won't do --- We must generate an Exact name, just as the parser does -isBuiltInOcc ctxt_ns occ - = case occ of - ":" -> Just (Name.getName consDataCon) - "[]" -> Just (Name.getName nilDataCon) - "()" -> Just (tup_name 0) - '(' : ',' : rest -> go_tuple 2 rest - _ -> Nothing - where - go_tuple n ")" = Just (tup_name n) - go_tuple n (',' : rest) = go_tuple (n+1) rest - go_tuple _ _ = Nothing - - tup_name n - | OccName.isTcClsNameSpace ctxt_ns = Name.getName (tupleTyCon BoxedTuple n) - | otherwise = Name.getName (tupleCon BoxedTuple n) - -- The packing and unpacking is rather turgid :-( mk_occ :: OccName.NameSpace -> String -> OccName.OccName mk_occ ns occ = OccName.mkOccName ns occ diff --git a/compiler/iface/IfaceEnv.lhs b/compiler/iface/IfaceEnv.lhs index 42c3e32605..4a00c91381 100644 --- a/compiler/iface/IfaceEnv.lhs +++ b/compiler/iface/IfaceEnv.lhs @@ -28,13 +28,10 @@ module IfaceEnv ( import TcRnMonad import TysWiredIn import HscTypes -import TyCon import Type -import DataCon import Var import Name import Avail -import PrelNames import Module import UniqFM import FastString @@ -183,23 +180,34 @@ lookupOrig mod occ See Note [The Name Cache] above. +Note [Built-in syntax and the OrigNameCache] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You might think that usin isBuiltInOcc_maybe in lookupOrigNameCache is +unnecessary because tuple TyCon/DataCons are parsed as Exact RdrNames +and *don't* appear as original names in interface files (because +serialization gives them special treatment), so we will never look +them up in the original name cache. + +However, there are two reasons why we might look up an Orig RdrName: + + * If you use setRdrNameSpace on an Exact RdrName it may be + turned into an Orig RdrName. + + * Template Haskell turns a BuiltInSyntax Name into a TH.NameG + (DsMeta.globalVar), and parses a NameG into an Orig RdrName + (Convert.thRdrName). So, eg $(do { reify '(,); ... }) will + go this route (Trac #8954). + \begin{code} lookupOrigNameCache :: OrigNameCache -> Module -> OccName -> Maybe Name -lookupOrigNameCache _ mod occ - -- Don't need to mention gHC_UNIT here because it is explicitly - -- included in TysWiredIn.wiredInTyCons - | mod == gHC_TUPLE || mod == gHC_PRIM, -- Boxed tuples from one, - Just tup_info <- isTupleOcc_maybe occ -- unboxed from the other - = -- Special case for tuples; there are too many +lookupOrigNameCache nc mod occ + | Just name <- isBuiltInOcc_maybe occ + = -- See Note [Known-key names], 3(c) in PrelNames + -- Special case for tuples; there are too many -- of them to pre-populate the original-name cache - Just (mk_tup_name tup_info) - where - mk_tup_name (ns, sort, arity) - | ns == tcName = tyConName (tupleTyCon sort arity) - | ns == dataName = dataConName (tupleCon sort arity) - | otherwise = Var.varName (dataConWorkId (tupleCon sort arity)) + Just name -lookupOrigNameCache nc mod occ -- The normal case + | otherwise = case lookupModuleEnv nc mod of Nothing -> Nothing Just occ_env -> lookupOccEnv occ_env occ diff --git a/compiler/prelude/PrelNames.lhs b/compiler/prelude/PrelNames.lhs index c0c1615daa..c586a7b9bd 100644 --- a/compiler/prelude/PrelNames.lhs +++ b/compiler/prelude/PrelNames.lhs @@ -37,55 +37,70 @@ Nota Bene: all Names defined in here should come from the base package Note [Known-key names] ~~~~~~~~~~~~~~~~~~~~~~ +It is *very* important that the compiler gives wired-in things and +things with "known-key" names the correct Uniques wherever they +occur. We have to be careful about this in exactly two places: -It is *very* important that the compiler gives wired-in things and things with "known-key" names -the correct Uniques wherever they occur. We have to be careful about this in exactly two places: + 1. When we parse some source code, renaming the AST better yield an + AST whose Names have the correct uniques - 1. When we parse some source code, renaming the AST better yield an AST whose Names have the - correct uniques - - 2. When we read an interface file, the read-in gubbins better have the right uniques + 2. When we read an interface file, the read-in gubbins better have + the right uniques This is accomplished through a combination of mechanisms: - 1. When parsing source code, the RdrName-decorated AST has some RdrNames which are Exact. These are - wired-in RdrNames where the we could directly tell from the parsed syntax what Name to use. For - example, when we parse a [] in a type we can just insert an Exact RdrName Name with the listTyConKey. - - Currently, I believe this is just an optimisation: it would be equally valid to just output Orig - RdrNames that correctly record the module etc we expect the final Name to come from. However, - were we to eliminate isTupleOcc_maybe it would become essential (see point 3). - - 2. The knownKeyNames (which consist of the basicKnownKeyNames from the module, and those names reachable - via the wired-in stuff from TysWiredIn) are used to initialise the "original name cache" in IfaceEnv. - This initialization ensures that when the type checker or renamer (both of which use IfaceEnv) look up - an original name (i.e. a pair of a Module and an OccName) for a known-key name they get the correct Unique. + 1. When parsing source code, the RdrName-decorated AST has some + RdrNames which are Exact. These are wired-in RdrNames where the + we could directly tell from the parsed syntax what Name to + use. For example, when we parse a [] in a type we can just insert + an Exact RdrName Name with the listTyConKey. + + Currently, I believe this is just an optimisation: it would be + equally valid to just output Orig RdrNames that correctly record + the module etc we expect the final Name to come from. However, + were we to eliminate isBuiltInOcc_maybe it would become essential + (see point 3). + + 2. The knownKeyNames (which consist of the basicKnownKeyNames from + the module, and those names reachable via the wired-in stuff from + TysWiredIn) are used to initialise the "OrigNameCache" in + IfaceEnv. This initialization ensures that when the type checker + or renamer (both of which use IfaceEnv) look up an original name + (i.e. a pair of a Module and an OccName) for a known-key name + they get the correct Unique. + + This is the most important mechanism for ensuring that known-key + stuff gets the right Unique, and is why it is so important to + place your known-key names in the appropriate lists. + + 3. For "infinite families" of known-key names (i.e. tuples), we have + to be extra careful. Because there are an infinite number of + these things, we cannot add them to the list of known-key names + used to initialise the OrigNameCache. Instead, we have to + rely on never having to look them up in that cache. - This is the most important mechanism for ensuring that known-key stuff gets the right Unique, and is why - it is so important to place your known-key names in the appropriate lists. + This is accomplished through a variety of mechanisms: - 3. For "infinite families" of known-key names (i.e. tuples, Any tycons and implicit parameter TyCons), we - have to be extra careful. Because there are an infinite number of these things, we cannot add them to - the list of known-key names used to initialise the original name cache. Instead, we have to rely on - never having to look them up in that cache. + a) The parser recognises them specially and generates an + Exact Name (hence not looked up in the orig-name cache) - This is accomplished through a variety of mechanisms: + b) The known infinite families of names are specially + serialised by BinIface.putName, with that special treatment + detected when we read back to ensure that we get back to the + correct uniques. - a) The known infinite families of names are specially serialised by BinIface.putName, with that special treatment - detected when we read back to ensure that we get back to the correct uniques. + Most of the infinite families cannot occur in source code, + so mechanisms (a,b) sufficies to ensure that they always have + the right Unique. In particular, implicit param TyCon names, + constraint tuples and Any TyCons cannot be mentioned by the + user. - b) Most of the infinite families cannot occur in source code, so mechanism a) sufficies to ensure that they - always have the right Unique. In particular, implicit param TyCon names, constraint tuples and Any TyCons - cannot be mentioned by the user. + c) IfaceEnv.lookupOrigNameCache uses isBuiltInOcc_maybe to map + built-in syntax directly onto the corresponding name, rather + than trying to find it in the original-name cache. - c) Tuple TyCon/DataCon names have a special hack (isTupleOcc_maybe) that is used by the original name cache - lookup routine to detect tuple names and give them the right Unique. You might think that this is unnecessary - because tuple TyCon/DataCons are parsed as Exact RdrNames and *don't* appear as original names in interface files - (because serialization gives them special treatment), so we will never look them up in the original name cache. + See also Note [Built-in syntax and the OrigNameCache] - However, there is a subtle reason why this is not the case: if you use setRdrNameSpace on an Exact RdrName - it may be turned into an Orig RdrName. So if the original name was an Exact tuple Name we might end up with - an Orig instead, which *will* lead to an original name cache query. \begin{code} module PrelNames ( Unique, Uniquable(..), hasKey, -- Re-exported for convenience @@ -474,10 +489,10 @@ mkMainModule_ m = mkModule mainPackageId m %************************************************************************ \begin{code} -mkTupleModule :: TupleSort -> Arity -> Module -mkTupleModule BoxedTuple _ = gHC_TUPLE -mkTupleModule ConstraintTuple _ = gHC_TUPLE -mkTupleModule UnboxedTuple _ = gHC_PRIM +mkTupleModule :: TupleSort -> Module +mkTupleModule BoxedTuple = gHC_TUPLE +mkTupleModule ConstraintTuple = gHC_TUPLE +mkTupleModule UnboxedTuple = gHC_PRIM \end{code} diff --git a/compiler/prelude/TysWiredIn.lhs b/compiler/prelude/TysWiredIn.lhs index aa1b169c0c..de0713a640 100644 --- a/compiler/prelude/TysWiredIn.lhs +++ b/compiler/prelude/TysWiredIn.lhs @@ -8,7 +8,7 @@ -- must be wired into the compiler nonetheless. C.f module TysPrim module TysWiredIn ( -- * All wired in things - wiredInTyCons, + wiredInTyCons, isBuiltInOcc_maybe, -- * Bool boolTy, boolTyCon, boolTyCon_RDR, boolTyConName, @@ -331,11 +331,11 @@ typeSymbolKind = TyConApp (promoteTyCon typeSymbolKindCon) [] %************************************************************************ %* * -\subsection[TysWiredIn-tuples]{The tuple types} + Stuff for dealing with tuples %* * %************************************************************************ -Note [How tuples work] +Note [How tuples work] See also Note [Known-key names] in PrelNames ~~~~~~~~~~~~~~~~~~~~~~ * There are three families of tuple TyCons and corresponding DataCons, (boxed, unboxed, and constraint tuples), expressed by the @@ -354,6 +354,68 @@ Note [How tuples work] are not serialised into interface files using OccNames at all. \begin{code} +isBuiltInOcc_maybe :: OccName -> Maybe Name +-- Built in syntax isn't "in scope" so these OccNames +-- map to wired-in Names with BuiltInSyntax +isBuiltInOcc_maybe occ + = case occNameString occ of + "[]" -> choose_ns listTyCon nilDataCon + ":" -> Just consDataConName + "[::]" -> Just parrTyConName + "(##)" -> choose_ns unboxedUnitTyCon unboxedUnitDataCon + "()" -> choose_ns unitTyCon unitDataCon + '(':'#':',':rest -> parse_tuple UnboxedTuple 2 rest + '(':',':rest -> parse_tuple BoxedTuple 2 rest + _other -> Nothing + where + ns = occNameSpace occ + + parse_tuple sort n rest + | (',' : rest2) <- rest = parse_tuple sort (n+1) rest2 + | tail_matches sort rest = choose_ns (tupleTyCon sort n) + (tupleCon sort n) + | otherwise = Nothing + + tail_matches BoxedTuple ")" = True + tail_matches UnboxedTuple "#)" = True + tail_matches _ _ = False + + choose_ns tc dc + | isTcClsNameSpace ns = Just (getName tc) + | isDataConNameSpace ns = Just (getName dc) + | otherwise = Just (getName (dataConWorkId dc)) + +mkTupleOcc :: NameSpace -> TupleSort -> Arity -> OccName +mkTupleOcc ns sort ar = mkOccName ns str + where + -- No need to cache these, the caching is done in mk_tuple + str = case sort of + UnboxedTuple -> '(' : '#' : commas ++ "#)" + BoxedTuple -> '(' : commas ++ ")" + ConstraintTuple -> '(' : commas ++ ")" + + commas = take (ar-1) (repeat ',') + + -- Cute hack: we reuse the standard tuple OccNames (and hence code) + -- for fact tuples, but give them different Uniques so they are not equal. + -- + -- You might think that this will go wrong because isBuiltInOcc_maybe won't + -- be able to tell the difference between boxed tuples and constraint tuples. BUT: + -- 1. Constraint tuples never occur directly in user code, so it doesn't matter + -- that we can't detect them in Orig OccNames originating from the user + -- programs (or those built by setRdrNameSpace used on an Exact tuple Name) + -- 2. Interface files have a special representation for tuple *occurrences* + -- in IfaceTyCons, their workers (in IfaceSyn) and their DataCons (in case + -- alternatives). Thus we don't rely on the OccName to figure out what kind + -- of tuple an occurrence was trying to use in these situations. + -- 3. We *don't* represent tuple data type declarations specially, so those + -- are still turned into wired-in names via isBuiltInOcc_maybe. But that's OK + -- because we don't actually need to declare constraint tuples thanks to this hack. + -- + -- So basically any OccName like (,,) flowing to isBuiltInOcc_maybe will always + -- refer to the standard boxed tuple. Cool :-) + + tupleTyCon :: TupleSort -> Arity -> TyCon tupleTyCon sort i | i > mAX_TUPLE_SIZE = fst (mk_tuple sort i) -- Build one specially tupleTyCon BoxedTuple i = fst (boxedTupleArr ! i) @@ -386,7 +448,7 @@ mk_tuple sort arity = (tycon, tuple_con) UnboxedTuple -> Nothing ConstraintTuple -> Nothing - modu = mkTupleModule sort arity + modu = mkTupleModule sort tc_name = mkWiredInName modu (mkTupleOcc tcName sort arity) tc_uniq (ATyCon tycon) BuiltInSyntax tc_kind = mkArrowKinds (map tyVarKind tyvars) res_kind |