Fix #9066.
authorRichard Eisenberg <eir@cis.upenn.edu>
Mon, 3 Nov 2014 16:15:35 +0000 (11:15 -0500)
committerRichard Eisenberg <eir@cis.upenn.edu>
Wed, 12 Nov 2014 17:20:38 +0000 (12:20 -0500)
When splicing in a fixity declaration, look for both term-level things
and type-level things. This requires some changes elsewhere in the
code to allow for more flexibility when looking up Exact names, which
can be assigned the wrong namespace during fixity declaration
conversion.

See the ticket for more info.

compiler/basicTypes/RdrName.lhs
compiler/hsSyn/Convert.lhs
compiler/rename/RnEnv.lhs
testsuite/tests/th/all.T

index d4afaf1..b9e3fcb 100644 (file)
@@ -157,9 +157,14 @@ setRdrNameSpace :: RdrName -> NameSpace -> RdrName
 setRdrNameSpace (Unqual occ) ns = Unqual (setOccNameSpace ns occ)
 setRdrNameSpace (Qual m occ) ns = Qual m (setOccNameSpace ns occ)
 setRdrNameSpace (Orig m occ) ns = Orig m (setOccNameSpace ns occ)
-setRdrNameSpace (Exact n)    ns = ASSERT( isExternalName n )
-                                  Orig (nameModule n)
-                                       (setOccNameSpace ns (nameOccName n))
+setRdrNameSpace (Exact n)    ns
+  | isExternalName n
+  = Orig (nameModule n) occ
+  | otherwise   -- This can happen when quoting and then splicing a fixity
+                -- declaration for a type
+  = Exact $ mkSystemNameAt (nameUnique n) occ (nameSrcSpan n)
+  where
+    occ = setOccNameSpace ns (nameOccName n)
 
 -- demoteRdrName lowers the NameSpace of RdrName.
 -- see Note [Demotion] in OccName
index 43d9bfb..6cff928 100644 (file)
@@ -172,7 +172,11 @@ cvtDec (TH.SigD nm typ)
         ; returnJustL $ Hs.SigD (TypeSig [nm'] ty') }
 
 cvtDec (TH.InfixD fx nm)
-  = do { nm' <- vNameL nm
+  -- fixity signatures are allowed for variables, constructors, and types
+  -- the renamer automatically looks for types during renaming, even when
+  -- the RdrName says it's a variable or a constructor. So, just assume
+  -- it's a variable or constructor and proceed.
+  = do { nm' <- vcNameL nm
        ; returnJustL (Hs.SigD (FixSig (FixitySig nm' (cvtFixity fx)))) }
 
 cvtDec (PragmaD prag)
@@ -521,7 +525,7 @@ cvtPragmaD (AnnP target exp)
            n' <- tconName n
            return (TypeAnnProvenance  n')
          ValueAnnotation n -> do
-           n' <- if isVarName n then vName n else cName n
+           n' <- vcName n
            return (ValueAnnProvenance n')
        ; returnJustL $ Hs.AnnD $ HsAnnotation target' exp'
        }
@@ -1071,9 +1075,10 @@ cvtFractionalLit r = FL { fl_text = show (fromRational r :: Double), fl_value =
 --------------------------------------------------------------------
 
 -- variable names
-vNameL, cNameL, tconNameL :: TH.Name -> CvtM (Located RdrName)
-vName,  cName,  tName,  tconName  :: TH.Name -> CvtM RdrName
+vNameL, cNameL, vcNameL, tconNameL :: TH.Name -> CvtM (Located RdrName)
+vName,  cName,  vcName,  tName,  tconName  :: TH.Name -> CvtM RdrName
 
+-- Variable names
 vNameL n = wrapL (vName n)
 vName n = cvtName OccName.varName n
 
@@ -1081,6 +1086,10 @@ vName n = cvtName OccName.varName n
 cNameL n = wrapL (cName n)
 cName n = cvtName OccName.dataName n
 
+-- Variable *or* constructor names; check by looking at the first char
+vcNameL n = wrapL (vcName n)
+vcName n = if isVarName n then vName n else cName n
+
 -- Type variable names
 tName n = cvtName OccName.tvName n
 
index e33ed15..0a73585 100644 (file)
@@ -309,9 +309,21 @@ lookupTopBndrRn_maybe rdr_name
 
 
 -----------------------------------------------
+-- | Lookup an @Exact@ @RdrName@. See Note [Looking up Exact RdrNames].
+-- This adds an error if the name cannot be found.
 lookupExactOcc :: Name -> RnM Name
--- See Note [Looking up Exact RdrNames]
 lookupExactOcc name
+  = do { result <- lookupExactOcc_either name
+       ; case result of
+           Left err -> do { addErr err
+                          ; return name }
+           Right name' -> return name' }
+
+-- | Lookup an @Exact@ @RdrName@. See Note [Looking up Exact RdrNames].
+-- This never adds an error, but it may return one.
+lookupExactOcc_either :: Name -> RnM (Either MsgDoc Name)
+-- See Note [Looking up Exact RdrNames]
+lookupExactOcc_either name
   | Just thing <- wiredInNameTyThing_maybe name
   , Just tycon <- case thing of
                     ATyCon tc                 -> Just tc
@@ -319,10 +331,10 @@ lookupExactOcc name
                     _                         -> Nothing
   , isTupleTyCon tycon
   = do { checkTupSize (tyConArity tycon)
-       ; return name }
+       ; return (Right name) }
 
   | isExternalName name
-  = return name
+  = return (Right name)
 
   | otherwise
   = do { env <- getGlobalRdrEnv
@@ -337,23 +349,23 @@ lookupExactOcc name
        ; case gres of
            []    -> -- See Note [Splicing Exact names]
                     do { lcl_env <- getLocalRdrEnv
-                       ; unless (name `inLocalRdrEnvScope` lcl_env) $
+                       ; if name `inLocalRdrEnvScope` lcl_env
+                         then return (Right name)
+                         else
 #ifdef GHCI
                          do { th_topnames_var <- fmap tcg_th_topnames getGblEnv
                             ; th_topnames <- readTcRef th_topnames_var
-                            ; unless (name `elemNameSet` th_topnames)
-                                     (addErr exact_nm_err)
+                            ; if name `elemNameSet` th_topnames
+                              then return (Right name)
+                              else return (Left exact_nm_err)
                             }
 #else /* !GHCI */
-                         addErr exact_nm_err
+                         return (Left exact_nm_err)
 #endif /* !GHCI */
-                       ; return name
                        }
 
-           [gre]   -> return (gre_name gre)
-           (gre:_) -> do {addErr dup_nm_err
-                         ; return (gre_name gre)
-                         }
+           [gre]   -> return (Right (gre_name gre))
+           _       -> return (Left dup_nm_err)
            -- We can get more than one GRE here, if there are multiple 
            -- bindings for the same name. Sometimes they are caught later
            -- by findLocalDupsRdrEnv, like in this example (Trac #8932):
@@ -1034,10 +1046,11 @@ lookupBindGroupOcc :: HsSigCtxt
 -- See Note [Looking up signature names]
 lookupBindGroupOcc ctxt what rdr_name
   | Just n <- isExact_maybe rdr_name
-  = do { n' <- lookupExactOcc n
-       ; return (Right n') }  -- Maybe we should check the side conditions
-                              -- but it's a pain, and Exact things only show
-                              -- up when you know what you are doing
+  = lookupExactOcc_either n   -- allow for the possibility of missing Exacts;
+                              -- see Note [dataTcOccs and Exact Names]
+      -- Maybe we should check the side conditions
+      -- but it's a pain, and Exact things only show
+      -- up when you know what you are doing
 
   | Just (rdr_mod, rdr_occ) <- isOrig_maybe rdr_name
   = do { n' <- lookupOrig rdr_mod rdr_occ
@@ -1114,10 +1127,8 @@ lookupLocalTcNames ctxt what rdr_name
 dataTcOccs :: RdrName -> [RdrName]
 -- Return both the given name and the same name promoted to the TcClsName
 -- namespace.  This is useful when we aren't sure which we are looking at.
+-- See also Note [dataTcOccs and Exact Names]
 dataTcOccs rdr_name
-  | Just n <- isExact_maybe rdr_name
-  , not (isBuiltInSyntax n)   -- See Note [dataTcOccs and Exact Names]
-  = [rdr_name]
   | isDataOcc occ || isVarOcc occ
   = [rdr_name, rdr_name_tc]
   | otherwise
@@ -1130,8 +1141,12 @@ dataTcOccs rdr_name
 Note [dataTcOccs and Exact Names]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Exact RdrNames can occur in code generated by Template Haskell, and generally
-those references are, well, exact, so it's wrong to return the TyClsName too.
-But there is an awkward exception for built-in syntax. Example in GHCi
+those references are, well, exact. However, the TH `Name` type isn't expressive
+enough to always track the correct namespace information, so we sometimes get
+the right Unique but wrong namespace. Thus, we still have to do the double-lookup
+for Exact RdrNames.
+
+There is also an awkward situation for built-in syntax. Example in GHCi
    :info []
 This parses as the Exact RdrName for nilDataCon, but we also want
 the list type constructor.
index 3d64060..342f5e3 100644 (file)
@@ -336,5 +336,4 @@ test('T8953', normal, compile, ['-v0'])
 test('T9084', normal, compile_fail, ['-v0'])
 test('T9738', normal, compile, ['-v0'])
 test('T9081', normal, compile, ['-v0'])
-test('T9066', expect_broken(9066), compile, ['-v0'])
-
+test('T9066', normal, compile, ['-v0'])