Fix Trac #5404: looking up signature binders in RnEnv
authorSimon Peyton Jones <simonpj@microsoft.com>
Mon, 15 Aug 2011 07:41:55 +0000 (08:41 +0100)
committerSimon Peyton Jones <simonpj@microsoft.com>
Mon, 15 Aug 2011 07:41:55 +0000 (08:41 +0100)
See Note [Looking up Exact RdrNames] in RnEnv

compiler/hsSyn/Convert.lhs
compiler/rename/RnEnv.lhs

index 158a9c7..54068f9 100644 (file)
@@ -1054,14 +1054,5 @@ temporary variables "a". Since there are lots of things called "a" we
 usually want to print the name with the unique, and that is indeed
 the way System Names are printed.
 
-There's a small complication of course.  For data types and
-classes we'll now have system Names in the binding positions
-for constructors, TyCons etc.  For example
-    [d| data T = MkT Int |]
-when we splice in and Convert to HsSyn RdrName, we'll get
-    data (Exact (system Name "T")) = (Exact (system Name "MkT")) ...
-So RnEnv.newGlobalBinder we spot Exact RdrNames that wrap a
-non-External Name, and make an External name for.  (Remember, 
-constructors and the like need External Names.)  Oddly, the 
-*occurrences* will continue to be that (non-External) System Name, 
-but the first sweep of the optimiser will fix that.
+There's a small complication of course; see Note [Looking up Exact
+RdrNames] in RnEnv.
index f2a0649..0989018 100644 (file)
@@ -223,14 +223,17 @@ lookupTopBndrRn_maybe rdr_name
 
 -----------------------------------------------
 lookupExactOcc :: Name -> RnM Name
+-- See Note [Looking up Exact RdrNames]
 lookupExactOcc name
-  | isExternalName name = return name
-  | otherwise           = do { env <- getGlobalRdrEnv
-                            ; let gres = lookupGRE_Name env name
-                             ; case gres of
-                                 []    -> return name
-                                 [gre] -> return (gre_name gre)
-                                 _     -> pprPanic "lookupExactOcc" (ppr name $$ ppr gres) }
+  | isExternalName name 
+  = return name
+  | otherwise           
+  = do { env <- getGlobalRdrEnv
+       ; let gres = lookupGRE_Name env name
+       ; case gres of
+           []    -> return name
+           [gre] -> return (gre_name gre)
+           _     -> pprPanic "lookupExactOcc" (ppr name $$ ppr gres) }
 
 -----------------------------------------------
 lookupInstDeclBndr :: Name -> RdrName -> RnM Name
@@ -352,6 +355,39 @@ newIPNameRn :: IPName RdrName -> TcRnIf m n (IPName Name)
 newIPNameRn ip_rdr = newIPName (mapIPName rdrNameOcc ip_rdr)
 \end{code}
 
+Note [Looking up Exact RdrNames]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Exact RdrNames are generated by Template Haskell.  See Note [Binders
+in Template Haskell] in Convert.
+
+For data types and classes have Exact system Names in the binding
+positions for constructors, TyCons etc.  For example
+    [d| data T = MkT Int |]
+when we splice in and Convert to HsSyn RdrName, we'll get
+    data (Exact (system Name "T")) = (Exact (system Name "MkT")) ...
+
+But, constructors and the like need External Names, not System Names!
+So we do the following
+
+ * In RnEnv.newGlobalBinder we spot Exact RdrNames that wrap a
+   non-External Name, and make an External name for it. This is
+   the name that goes in the GlobalRdrEnv
+
+ * When looking up an occurrence of an Exact name, done in
+   RnEnv.lookupExactOcc, we find the Name with the right unique in the
+   GlobalRdrEnv, and use the on from the envt -- it will be an
+   External Name in the case of the data type/constructor above.
+
+ * Exact names are also use for purely local binders generated
+   by TH, such as    \x_33. x_33
+   Both binder and occurrence are Exact RdrNames.  The occurrence
+   gets looked up in the LocalRdrEnv by RnEnv.lookupOccRn, and 
+   misses, because lookupLocalRdrEnv always returns Nothing for
+   an Exact Name.  Now we fall through to lookupExactOcc, which
+   will find the Name is not in the GlobalRdrEnv, so we just use
+   the Exact supplied Name.
+
+
 Note [Usage for sub-bndrs]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 If you have this
@@ -567,6 +603,10 @@ lookupBindGroupOcc :: Maybe NameSet  -- See notes on the (Maybe NameSet)
 --
 -- See Note [Looking up signature names]
 lookupBindGroupOcc mb_bound_names what rdr_name
+  | Just n <- isExact_maybe rdr_name
+  = do { n' <- lookupExactOcc n
+       ; check_local_name n' }
+  | otherwise
   = do  { local_env <- getLocalRdrEnv
         ; case lookupLocalRdrEnv local_env rdr_name of {
             Just n  -> check_local_name n;
@@ -582,7 +622,7 @@ lookupBindGroupOcc mb_bound_names what rdr_name
             [] | null gres -> bale_out_with empty
                | otherwise -> bale_out_with import_msg
         }}}
-    where
+  where
       check_local_name name    -- The name is in scope, and not imported
          = case mb_bound_names of
                  Just bound_names | not (name `elemNameSet` bound_names)