diff options
author | Adam Gundry <adam@well-typed.com> | 2015-10-16 16:08:31 +0100 |
---|---|---|
committer | Adam Gundry <adam@well-typed.com> | 2015-10-16 16:27:53 +0100 |
commit | b1884b0e62f62e3c0859515c4137124ab0c9560e (patch) | |
tree | 9037ed61aeaf16b243c4b8542e3ef11f4abd7ee7 /compiler/rename/RnSource.hs | |
parent | 808bbdf08058785ae5bc59b5b4f2b04951d4cbbf (diff) | |
download | haskell-b1884b0e62f62e3c0859515c4137124ab0c9560e.tar.gz |
Implement DuplicateRecordFields
This implements DuplicateRecordFields, the first part of the
OverloadedRecordFields extension, as described at
https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/DuplicateRecordFields
This includes fairly wide-ranging changes in order to allow multiple
records within the same module to use the same field names. Note that
it does *not* allow record selector functions to be used if they are
ambiguous, and it does not have any form of type-based disambiguation
for selectors (but it does for updates). Subsequent parts will make
overloading selectors possible using orthogonal extensions, as
described on the wiki pages. This part touches quite a lot of the
codebase, and requires changes to several GHC API datatypes in order
to distinguish between field labels (which may be overloaded) and
selector function names (which are always unique).
The Haddock submodule has been adapted to compile with the GHC API
changes, but it will need further work to properly support modules
that use the DuplicateRecordFields extension.
Test Plan: New tests added in testsuite/tests/overloadedrecflds; these
will be extended once the other parts are implemented.
Reviewers: goldfire, bgamari, simonpj, austin
Subscribers: sjcjoosten, haggholm, mpickering, bgamari, tibbe, thomie,
goldfire
Differential Revision: https://phabricator.haskell.org/D761
Diffstat (limited to 'compiler/rename/RnSource.hs')
-rw-r--r-- | compiler/rename/RnSource.hs | 74 |
1 files changed, 10 insertions, 64 deletions
diff --git a/compiler/rename/RnSource.hs b/compiler/rename/RnSource.hs index 19f05c3ca2..f89f1b2ceb 100644 --- a/compiler/rename/RnSource.hs +++ b/compiler/rename/RnSource.hs @@ -104,16 +104,11 @@ rnSrcDecls group@(HsGroup { hs_valds = val_decls, -- Again, they have no value declarations -- (tc_envs, tc_bndrs) <- getLocalNonValBinders local_fix_env group ; + setEnvs tc_envs $ do { failIfErrsM ; -- No point in continuing if (say) we have duplicate declarations - -- (C) Extract the mapping from data constructors to field names and - -- extend the record field env. - -- This depends on the data constructors and field names being in - -- scope from (B) above - inNewEnv (extendRecordFieldEnv tycl_decls inst_decls) $ \ _ -> do { - -- (D1) Bring pattern synonyms into scope. -- Need to do this before (D2) because rnTopBindsLHS -- looks up those pattern synonyms (Trac #9889) @@ -218,13 +213,7 @@ rnSrcDecls group@(HsGroup { hs_valds = val_decls, traceRn (text "finish rnSrc" <+> ppr rn_group) ; traceRn (text "finish Dus" <+> ppr src_dus ) ; return (final_tcg_env, rn_group) - }}}}} - --- some utils because we do this a bunch above --- compute and install the new env -inNewEnv :: TcM TcGblEnv -> (TcGblEnv -> TcM a) -> TcM a -inNewEnv env cont = do e <- env - setGblEnv e $ cont e + }}}} addTcgDUs :: TcGblEnv -> DefUses -> TcGblEnv -- This function could be defined lower down in the module hierarchy, @@ -1483,7 +1472,7 @@ rnConDecl decl@(ConDecl { con_names = names, con_qvars = tvs ; bindHsTyVars doc Nothing free_kvs new_tvs $ \new_tyvars -> do { (new_context, fvs1) <- rnContext doc lcxt - ; (new_details, fvs2) <- rnConDeclDetails doc details + ; (new_details, fvs2) <- rnConDeclDetails (unLoc $ head new_names) doc details ; (new_details', new_res_ty, fvs3) <- rnConResult doc (map unLoc new_names) new_details res_ty ; return (decl { con_names = new_names, con_qvars = new_tyvars @@ -1518,20 +1507,22 @@ rnConResult doc _con details (ResTyGADT ls ty) PrefixCon {} -> return (PrefixCon arg_tys, ResTyGADT ls res_ty, fvs)} rnConDeclDetails - :: HsDocContext + :: Name + -> HsDocContext -> HsConDetails (LHsType RdrName) (Located [LConDeclField RdrName]) -> RnM (HsConDetails (LHsType Name) (Located [LConDeclField Name]), FreeVars) -rnConDeclDetails doc (PrefixCon tys) +rnConDeclDetails _ doc (PrefixCon tys) = do { (new_tys, fvs) <- rnLHsTypes doc tys ; return (PrefixCon new_tys, fvs) } -rnConDeclDetails doc (InfixCon ty1 ty2) +rnConDeclDetails _ doc (InfixCon ty1 ty2) = do { (new_ty1, fvs1) <- rnLHsType doc ty1 ; (new_ty2, fvs2) <- rnLHsType doc ty2 ; return (InfixCon new_ty1 new_ty2, fvs1 `plusFV` fvs2) } -rnConDeclDetails doc (RecCon (L l fields)) - = do { (new_fields, fvs) <- rnConDeclFields doc fields +rnConDeclDetails con doc (RecCon (L l fields)) + = do { fls <- lookupConstructorFields con + ; (new_fields, fvs) <- rnConDeclFields fls doc fields -- No need to check for duplicate fields -- since that is done by RnNames.extendGlobalRdrEnvRn ; return (RecCon (L l new_fields), fvs) } @@ -1550,51 +1541,6 @@ badRecResTy doc = ptext (sLit "Malformed constructor signature") $$ doc {- ********************************************************* * * -\subsection{Support code for type/data declarations} -* * -********************************************************* - -Get the mapping from constructors to fields for this module. -It's convenient to do this after the data type decls have been renamed --} - -extendRecordFieldEnv :: [TyClGroup RdrName] -> [LInstDecl RdrName] -> TcM TcGblEnv -extendRecordFieldEnv tycl_decls inst_decls - = do { tcg_env <- getGblEnv - ; field_env' <- foldrM get_con (tcg_field_env tcg_env) all_data_cons - ; return (tcg_env { tcg_field_env = field_env' }) } - where - -- we want to lookup: - -- (a) a datatype constructor - -- (b) a record field - -- knowing that they're from this module. - -- lookupLocatedTopBndrRn does this, because it does a lookupGreLocalRn_maybe, - -- which keeps only the local ones. - lookup x = do { x' <- lookupLocatedTopBndrRn x - ; return $ unLoc x'} - - all_data_cons :: [ConDecl RdrName] - all_data_cons = [con | HsDataDefn { dd_cons = cons } <- all_ty_defs - , L _ con <- cons ] - all_ty_defs = [ defn | L _ (DataDecl { tcdDataDefn = defn }) - <- tyClGroupConcat tycl_decls ] - ++ map dfid_defn (instDeclDataFamInsts inst_decls) - -- Do not forget associated types! - - get_con (ConDecl { con_names = cons, con_details = RecCon flds }) - (RecFields env fld_set) - = do { cons' <- mapM lookup cons - ; flds' <- mapM lookup (concatMap (cd_fld_names . unLoc) - (unLoc flds)) - ; let env' = foldl (\e c -> extendNameEnv e c flds') env cons' - - fld_set' = extendNameSetList fld_set flds' - ; return $ (RecFields env' fld_set') } - get_con _ env = return env - -{- -********************************************************* -* * \subsection{Support code to rename types} * * ********************************************************* |