Commit 6f60f1f5 authored by Simon Peyton Jones's avatar Simon Peyton Jones

Fix tracking of what RdrNames are used (fixes Trac #5211)

The issue here was: what import declaration brings into
scope the 'op here

   import qualified Foo( op )
   import Bar( C(op) )
   instance C Int where
     op = ...

Well, the import of Bar, obviously.  But what if the
import Bar had been
   import Bar( C )
Then the instance is still supposed to work, getting
op from the Foo.op imported from Foo.  (I'm assuming its
the same op, of course.)
parent 8fb9d669
...@@ -570,7 +570,7 @@ data Provenance ...@@ -570,7 +570,7 @@ data Provenance
-- INVARIANT: the list of 'ImportSpec' is non-empty -- INVARIANT: the list of 'ImportSpec' is non-empty
data ImportSpec = ImpSpec { is_decl :: ImpDeclSpec, data ImportSpec = ImpSpec { is_decl :: ImpDeclSpec,
is_item :: ImpItemSpec } is_item :: ImpItemSpec }
deriving( Eq, Ord ) deriving( Eq, Ord )
-- | Describes a particular import declaration and is -- | Describes a particular import declaration and is
......
...@@ -24,7 +24,6 @@ import VarSet ...@@ -24,7 +24,6 @@ import VarSet
import UniqSupply import UniqSupply
import TcType import TcType
import GHC import GHC
import InteractiveEval
import Outputable import Outputable
import PprTyThing import PprTyThing
import MonadUtils import MonadUtils
......
...@@ -288,7 +288,7 @@ lookupSubBndr parent doc rdr_name ...@@ -288,7 +288,7 @@ lookupSubBndr parent doc rdr_name
-- NB: lookupGlobalRdrEnv, not lookupGRE_RdrName! -- NB: lookupGlobalRdrEnv, not lookupGRE_RdrName!
-- The latter does pickGREs, but we want to allow 'x' -- The latter does pickGREs, but we want to allow 'x'
-- even if only 'M.x' is in scope -- even if only 'M.x' is in scope
[gre] -> do { addUsedRdrNames (used_rdr_names gre) [gre] -> do { addUsedRdrName gre (used_rdr_name gre)
; return (gre_name gre) } ; return (gre_name gre) }
[] -> do { addErr (unknownSubordinateErr doc rdr_name) [] -> do { addErr (unknownSubordinateErr doc rdr_name)
; traceRn (text "RnEnv.lookup_sub_bndr" <+> (ppr rdr_name $$ ppr gres)) ; traceRn (text "RnEnv.lookup_sub_bndr" <+> (ppr rdr_name $$ ppr gres))
...@@ -296,6 +296,8 @@ lookupSubBndr parent doc rdr_name ...@@ -296,6 +296,8 @@ lookupSubBndr parent doc rdr_name
gres -> do { addNameClashErrRn rdr_name gres gres -> do { addNameClashErrRn rdr_name gres
; return (gre_name (head gres)) } } ; return (gre_name (head gres)) } }
where where
rdr_occ = rdrNameOcc rdr_name
pick NoParent gres -- Normal lookup pick NoParent gres -- Normal lookup
= pickGREs rdr_name gres = pickGREs rdr_name gres
pick (ParentIs p) gres -- Disambiguating lookup pick (ParentIs p) gres -- Disambiguating lookup
...@@ -306,13 +308,20 @@ lookupSubBndr parent doc rdr_name ...@@ -306,13 +308,20 @@ lookupSubBndr parent doc rdr_name
right_parent _ _ = False right_parent _ _ = False
-- Note [Usage for sub-bndrs] -- Note [Usage for sub-bndrs]
used_rdr_names gre used_rdr_name gre
| isQual rdr_name = [rdr_name] | isQual rdr_name = rdr_name
| otherwise = case gre_prov gre of | otherwise = case gre_prov gre of
LocalDef -> [rdr_name] LocalDef -> rdr_name
Imported is -> map mk_qual_rdr is Imported is -> used_rdr_name_from_is is
mk_qual_rdr imp_spec = mkRdrQual (is_as (is_decl imp_spec)) rdr_occ
rdr_occ = rdrNameOcc rdr_name used_rdr_name_from_is imp_specs -- rdr_name is unqualified
| not (all (is_qual . is_decl) imp_specs)
= rdr_name -- An unqualified import is available
| otherwise
= -- Only qualified imports available, so make up
-- a suitable qualifed name from the first imp_spec
ASSERT( not (null imp_specs) )
mkRdrQual (is_as (is_decl (head imp_specs))) rdr_occ
newIPNameRn :: IPName RdrName -> TcRnIf m n (IPName Name) newIPNameRn :: IPName RdrName -> TcRnIf m n (IPName Name)
newIPNameRn ip_rdr = newIPName (mapIPName rdrNameOcc ip_rdr) newIPNameRn ip_rdr = newIPName (mapIPName rdrNameOcc ip_rdr)
...@@ -334,13 +343,21 @@ Note [Usage for sub-bndrs] ...@@ -334,13 +343,21 @@ Note [Usage for sub-bndrs]
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
If you have this If you have this
import qualified M( C( f ) ) import qualified M( C( f ) )
intance M.C T where instance M.C T where
f x = x f x = x
then is the qualified import M.f used? Obviously yes. then is the qualified import M.f used? Obviously yes.
But the RdrName used in the instance decl is unqualified. In effect, But the RdrName used in the instance decl is unqualified. In effect,
we fill in the qualification by looking for f's whose class is M.C we fill in the qualification by looking for f's whose class is M.C
But when adding to the UsedRdrNames we must make that qualification But when adding to the UsedRdrNames we must make that qualification
explicit, otherwise we get "Redundant import of M.C". explicit (saying "used M.f"), otherwise we get "Redundant import of M.f".
So we make up a suitable (fake) RdrName. But be careful
import qualifed M
import M( C(f) )
instance C T where
f x = x
Here we want to record a use of 'f', not of 'M.f', otherwise
we'll miss the fact that the qualified import is redundant.
-------------------------------------------------- --------------------------------------------------
-- Occurrences -- Occurrences
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment