Commit 7a763cff authored by Adam Gundry's avatar Adam Gundry Committed by Marge Bot

Reject all duplicate declarations involving DuplicateRecordFields (fixes #17965)

This fixes a bug that resulted in some programs being accepted that used the same
identifier as a field label and another declaration, depending on the order they
appeared in the source code.
parent 926d2aab
......@@ -638,9 +638,12 @@ extendGlobalRdrEnvRn avails new_fixities
| otherwise
= return (extendGlobalRdrEnv env gre)
where
name = gre_name gre
occ = nameOccName name
dups = filter isLocalGRE (lookupGlobalRdrEnv env occ)
occ = greOccName gre
dups = filter isDupGRE (lookupGlobalRdrEnv env occ)
-- Duplicate GREs are those defined locally with the same OccName,
-- except cases where *both* GREs are DuplicateRecordFields (#17965).
isDupGRE gre' = isLocalGRE gre'
&& not (isOverloadedRecFldGRE gre && isOverloadedRecFldGRE gre')
{- *********************************************************************
......@@ -1767,14 +1770,13 @@ addDupDeclErr gres@(gre : _)
= addErrAt (getSrcSpan (last sorted_names)) $
-- Report the error at the later location
vcat [text "Multiple declarations of" <+>
quotes (ppr (nameOccName name)),
quotes (ppr (greOccName gre)),
-- NB. print the OccName, not the Name, because the
-- latter might not be in scope in the RdrEnv and so will
-- be printed qualified.
text "Declared at:" <+>
vcat (map (ppr . nameSrcLoc) sorted_names)]
where
name = gre_name gre
sorted_names =
sortBy (SrcLoc.leftmost_smallest `on` nameSrcSpan)
(map gre_name gres)
......
......@@ -57,7 +57,7 @@ module GHC.Types.Name.Reader (
gresToAvailInfo,
-- ** Global 'RdrName' mapping elements: 'GlobalRdrElt', 'Provenance', 'ImportSpec'
GlobalRdrElt(..), isLocalGRE, isRecFldGRE, greLabel,
GlobalRdrElt(..), isLocalGRE, isRecFldGRE, isOverloadedRecFldGRE, greLabel,
unQualOK, qualSpecOK, unQualSpecOK,
pprNameProvenance,
Parent(..), greParent_maybe,
......@@ -842,6 +842,12 @@ isRecFldGRE :: GlobalRdrElt -> Bool
isRecFldGRE (GRE {gre_par = FldParent{}}) = True
isRecFldGRE _ = False
isOverloadedRecFldGRE :: GlobalRdrElt -> Bool
-- ^ Is this a record field defined with DuplicateRecordFields?
-- (See Note [Parents for record fields])
isOverloadedRecFldGRE (GRE {gre_par = FldParent{par_lbl = Just _}}) = True
isOverloadedRecFldGRE _ = False
-- Returns the field label of this GRE, if it has one
greLabel :: GlobalRdrElt -> Maybe FieldLabelString
greLabel (GRE{gre_par = FldParent{par_lbl = Just lbl}}) = Just lbl
......
{-# LANGUAGE DuplicateRecordFields #-}
main = return ()
newtype Record a = Record { f :: a -> a }
class C a where f :: a -> a
T17965.hs:4:17: error:
Multiple declarations of ‘f’
Declared at: T17965.hs:3:29
T17965.hs:4:17
......@@ -32,3 +32,4 @@ test('hasfieldfail03', normal, compile_fail, [''])
test('T14953', [extra_files(['T14953_A.hs', 'T14953_B.hs'])],
multimod_compile_fail, ['T14953', ''])
test('DuplicateExports', normal, compile_fail, [''])
test('T17965', normal, compile_fail, [''])
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