diff options
author | Dr. ERDI Gergo <gergo@erdi.hu> | 2014-12-17 22:09:06 +0800 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2015-01-09 15:48:15 +0000 |
commit | 5830fc449af6b2c0ef5be409fd3457114ae938ca (patch) | |
tree | 1c5aaec0bcfc183c9533942c9e0190686c216b12 | |
parent | 678df4c2930c4aef61b083edb0f5c4d8c8914a76 (diff) | |
download | haskell-5830fc449af6b2c0ef5be409fd3457114ae938ca.tar.gz |
Pattern synonym names need to be in scope before renaming bindings (#9889)
I did a bit of refactoring at the same time, needless to say
-rw-r--r-- | compiler/hsSyn/HsBinds.hs | 10 | ||||
-rw-r--r-- | compiler/hsSyn/HsUtils.hs | 130 | ||||
-rw-r--r-- | compiler/rename/RnBinds.hs | 28 | ||||
-rw-r--r-- | compiler/rename/RnEnv.hs | 2 | ||||
-rw-r--r-- | compiler/rename/RnNames.hs | 26 | ||||
-rw-r--r-- | compiler/rename/RnPat.hs | 18 | ||||
-rw-r--r-- | compiler/rename/RnSource.hs | 26 | ||||
-rw-r--r-- | compiler/typecheck/TcBinds.hs | 55 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T8776.stdout | 2 | ||||
-rw-r--r-- | testsuite/tests/patsyn/should_compile/T9889.hs | 6 | ||||
-rw-r--r-- | testsuite/tests/patsyn/should_compile/all.T | 1 | ||||
-rw-r--r-- | testsuite/tests/patsyn/should_fail/local.stderr | 4 | ||||
-rw-r--r-- | testsuite/tests/patsyn/should_run/ghci.stdout | 2 |
13 files changed, 188 insertions, 122 deletions
diff --git a/compiler/hsSyn/HsBinds.hs b/compiler/hsSyn/HsBinds.hs index 82d014b642..5528c3ff5a 100644 --- a/compiler/hsSyn/HsBinds.hs +++ b/compiler/hsSyn/HsBinds.hs @@ -73,15 +73,24 @@ type HsLocalBinds id = HsLocalBindsLR id id -- or a 'where' clause data HsLocalBindsLR idL idR = HsValBinds (HsValBindsLR idL idR) + -- There should be no pattern synonyms in the HsValBindsLR + -- These are *local* (not top level) bindings + -- The parser accepts them, however, leaving the the + -- renamer to report them + | HsIPBinds (HsIPBinds idR) + | EmptyLocalBinds deriving (Typeable) + deriving instance (DataId idL, DataId idR) => Data (HsLocalBindsLR idL idR) type HsValBinds id = HsValBindsLR id id -- | Value bindings (not implicit parameters) +-- Used for both top level and nested bindings +-- May contain pattern synonym bindings data HsValBindsLR idL idR = -- | Before renaming RHS; idR is always RdrName -- Not dependency analysed @@ -97,6 +106,7 @@ data HsValBindsLR idL idR [(RecFlag, LHsBinds idL)] [LSig Name] deriving (Typeable) + deriving instance (DataId idL, DataId idR) => Data (HsValBindsLR idL idR) diff --git a/compiler/hsSyn/HsUtils.hs b/compiler/hsSyn/HsUtils.hs index 6694138d57..398aafdb01 100644 --- a/compiler/hsSyn/HsUtils.hs +++ b/compiler/hsSyn/HsUtils.hs @@ -61,12 +61,13 @@ module HsUtils( -- Collecting binders collectLocalBinders, collectHsValBinders, collectHsBindListBinders, + collectHsIdBinders, collectHsBindsBinders, collectHsBindBinders, collectMethodBinders, collectPatBinders, collectPatsBinders, collectLStmtsBinders, collectStmtsBinders, collectLStmtBinders, collectStmtBinders, - hsLTyClDeclBinders, hsTyClDeclsBinders, + hsLTyClDeclBinders, hsTyClForeignBinders, hsPatSynBinders, hsForeignDeclsBinders, hsGroupBinders, hsDataFamInstBinders, -- Collecting implicit binders @@ -596,39 +597,48 @@ So these functions should not be applied to (HsSyn RdrName) ----------------- Bindings -------------------------- collectLocalBinders :: HsLocalBindsLR idL idR -> [idL] -collectLocalBinders (HsValBinds val_binds) = collectHsValBinders val_binds -collectLocalBinders (HsIPBinds _) = [] -collectLocalBinders EmptyLocalBinds = [] +collectLocalBinders (HsValBinds binds) = collectHsIdBinders binds + -- No pattern synonyms here +collectLocalBinders (HsIPBinds _) = [] +collectLocalBinders EmptyLocalBinds = [] -collectHsValBinders :: HsValBindsLR idL idR -> [idL] -collectHsValBinders (ValBindsIn binds _) = collectHsBindsBinders binds -collectHsValBinders (ValBindsOut binds _) = foldr collect_one [] binds - where - collect_one (_,binds) acc = collect_binds binds acc +collectHsIdBinders, collectHsValBinders :: HsValBindsLR idL idR -> [idL] +-- Collect Id binders only, or Ids + pattern synonmys, respectively +collectHsIdBinders = collect_hs_val_binders True +collectHsValBinders = collect_hs_val_binders False collectHsBindBinders :: HsBindLR idL idR -> [idL] -collectHsBindBinders b = collect_bind b [] - -collect_bind :: HsBindLR idL idR -> [idL] -> [idL] -collect_bind (PatBind { pat_lhs = p }) acc = collect_lpat p acc -collect_bind (FunBind { fun_id = L _ f }) acc = f : acc -collect_bind (VarBind { var_id = f }) acc = f : acc -collect_bind (AbsBinds { abs_exports = dbinds, abs_binds = _binds }) acc - = map abe_poly dbinds ++ acc - -- ++ foldr collect_bind acc binds - -- I don't think we want the binders from the nested binds - -- The only time we collect binders from a typechecked - -- binding (hence see AbsBinds) is in zonking in TcHsSyn -collect_bind (PatSynBind (PSB { psb_id = L _ ps })) acc = ps : acc +-- Collect both Ids and pattern-synonym binders +collectHsBindBinders b = collect_bind False b [] collectHsBindsBinders :: LHsBindsLR idL idR -> [idL] -collectHsBindsBinders binds = collect_binds binds [] +collectHsBindsBinders binds = collect_binds False binds [] collectHsBindListBinders :: [LHsBindLR idL idR] -> [idL] -collectHsBindListBinders = foldr (collect_bind . unLoc) [] - -collect_binds :: LHsBindsLR idL idR -> [idL] -> [idL] -collect_binds binds acc = foldrBag (collect_bind . unLoc) acc binds +-- Same as collectHsBindsBinders, but works over a list of bindings +collectHsBindListBinders = foldr (collect_bind False . unLoc) [] + +collect_hs_val_binders :: Bool -> HsValBindsLR idL idR -> [idL] +collect_hs_val_binders ps (ValBindsIn binds _) = collect_binds ps binds [] +collect_hs_val_binders ps (ValBindsOut binds _) = collect_out_binds ps binds + +collect_out_binds :: Bool -> [(RecFlag, LHsBinds id)] -> [id] +collect_out_binds ps = foldr (collect_binds ps . snd) [] + +collect_binds :: Bool -> LHsBindsLR idL idR -> [idL] -> [idL] +-- Collect Ids, or Ids + patter synonyms, depending on boolean flag +collect_binds ps binds acc = foldrBag (collect_bind ps . unLoc) acc binds + +collect_bind :: Bool -> HsBindLR idL idR -> [idL] -> [idL] +collect_bind _ (PatBind { pat_lhs = p }) acc = collect_lpat p acc +collect_bind _ (FunBind { fun_id = L _ f }) acc = f : acc +collect_bind _ (VarBind { var_id = f }) acc = f : acc +collect_bind _ (AbsBinds { abs_exports = dbinds }) acc = map abe_poly dbinds ++ acc + -- I don't think we want the binders from the abe_binds + -- The only time we collect binders from a typechecked + -- binding (hence see AbsBinds) is in zonking in TcHsSyn +collect_bind omitPatSyn (PatSynBind (PSB { psb_id = L _ ps })) acc = + if omitPatSyn then acc else ps : acc collectMethodBinders :: LHsBindsLR RdrName idR -> [Located RdrName] -- Used exclusively for the bindings of an instance decl which are all FunBinds @@ -728,21 +738,18 @@ So in mkSelectorBinds in DsUtils, we want just m,n as the variables bound. hsGroupBinders :: HsGroup Name -> [Name] hsGroupBinders (HsGroup { hs_valds = val_decls, hs_tyclds = tycl_decls, hs_instds = inst_decls, hs_fords = foreign_decls }) --- Collect the binders of a Group = collectHsValBinders val_decls - ++ hsTyClDeclsBinders tycl_decls inst_decls - ++ hsForeignDeclsBinders foreign_decls - -hsForeignDeclsBinders :: [LForeignDecl Name] -> [Name] -hsForeignDeclsBinders foreign_decls - = [n | L _ (ForeignImport (L _ n) _ _ _) <- foreign_decls] + ++ hsTyClForeignBinders tycl_decls inst_decls foreign_decls -hsTyClDeclsBinders :: [TyClGroup Name] -> [Located (InstDecl Name)] -> [Name] +hsTyClForeignBinders :: [TyClGroup Name] -> [LInstDecl Name] + -> [LForeignDecl Name] -> [Name] -- We need to look at instance declarations too, -- because their associated types may bind data constructors -hsTyClDeclsBinders tycl_decls inst_decls - = map unLoc (concatMap (concatMap hsLTyClDeclBinders . group_tyclds) tycl_decls ++ - concatMap (hsInstDeclBinders . unLoc) inst_decls) +hsTyClForeignBinders tycl_decls inst_decls foreign_decls + = map unLoc $ + hsForeignDeclsBinders foreign_decls ++ + concatMap (concatMap hsLTyClDeclBinders . group_tyclds) tycl_decls ++ + concatMap hsLInstDeclBinders inst_decls ------------------- hsLTyClDeclBinders :: Eq name => Located (TyClDecl name) -> [Located name] @@ -751,11 +758,8 @@ hsLTyClDeclBinders :: Eq name => Located (TyClDecl name) -> [Located name] -- mentioned in multiple constructors, the SrcLoc will be from the first -- occurrence. We use the equality to filter out duplicate field names. -- --- Each returned (Located name) is wrapped in a @SrcSpan@ of the whole --- /declaration/, not just the name itself (which is how it appears in --- the syntax tree). This SrcSpan (for the entire declaration) is used --- as the SrcSpan for the Name that is finally produced, and hence for --- error messages. (See Trac #8607.) +-- Each returned (Located name) has a SrcSpan for the /whole/ declaration. +-- See Note [SrcSpan for binders] hsLTyClDeclBinders (L loc (FamDecl { tcdFam = FamilyDecl { fdLName = L _ name } })) = [L loc name] @@ -769,11 +773,33 @@ hsLTyClDeclBinders (L loc (DataDecl { tcdLName = L _ name, tcdDataDefn = defn = L loc name : hsDataDefnBinders defn ------------------- -hsInstDeclBinders :: Eq name => InstDecl name -> [Located name] -hsInstDeclBinders (ClsInstD { cid_inst = ClsInstDecl { cid_datafam_insts = dfis } }) +hsForeignDeclsBinders :: [LForeignDecl name] -> [Located name] +-- See Note [SrcSpan for binders] +hsForeignDeclsBinders foreign_decls + = [ L decl_loc n + | L decl_loc (ForeignImport (L _ n) _ _ _) <- foreign_decls] + +------------------- +hsPatSynBinders :: LHsBindsLR idL idR -> [Located idL] +-- Collect pattern-synonym binders only, not Ids +-- See Note [SrcSpan for binders] +hsPatSynBinders binds = foldrBag addPatSynBndr [] binds + +addPatSynBndr :: LHsBindLR idL idR -> [Located idL] -> [Located idL] +-- See Note [SrcSpan for binders] +addPatSynBndr bind pss + | L bind_loc (PatSynBind (PSB { psb_id = L _ n })) <- bind + = L bind_loc n : pss + | otherwise + = pss + +------------------- +hsLInstDeclBinders :: Eq name => LInstDecl name -> [Located name] +hsLInstDeclBinders (L _ (ClsInstD { cid_inst = ClsInstDecl { cid_datafam_insts = dfis } })) = concatMap (hsDataFamInstBinders . unLoc) dfis -hsInstDeclBinders (DataFamInstD { dfid_inst = fi }) = hsDataFamInstBinders fi -hsInstDeclBinders (TyFamInstD {}) = [] +hsLInstDeclBinders (L _ (DataFamInstD { dfid_inst = fi })) + = hsDataFamInstBinders fi +hsLInstDeclBinders (L _ (TyFamInstD {})) = [] ------------------- -- the SrcLoc returned are for the whole declarations, not just the names @@ -811,6 +837,16 @@ hsConDeclsBinders cons = go id cons (map (L loc . unLoc) names) ++ go remSeen rs {- + +Note [SrcSpan for binders] +~~~~~~~~~~~~~~~~~~~~~~~~~~ +When extracting the (Located RdrNme) for a binder, at least for the +main name (the TyCon of a type declaration etc), we want to give it +the @SrcSpan@ of the whole /declaration/, not just the name itself +(which is how it appears in the syntax tree). This SrcSpan (for the +entire declaration) is used as the SrcSpan for the Name that is +finally produced, and hence for error messages. (See Trac #8607.) + Note [Binders in family instances] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In a type or data family instance declaration, the type diff --git a/compiler/rename/RnBinds.hs b/compiler/rename/RnBinds.hs index 1af93f35d2..46d36a720f 100644 --- a/compiler/rename/RnBinds.hs +++ b/compiler/rename/RnBinds.hs @@ -258,6 +258,9 @@ rnLocalValBindsLHS fix_env binds -- g = let f = ... in f -- should. ; let bound_names = collectHsValBinders binds' + -- There should be only Ids, but if there are any bogus + -- pattern synonyms, we'll collect them anyway, so that + -- we don't generate subsequent out-of-scope messages ; envs <- getRdrEnvs ; checkDupAndShadowedNames envs bound_names @@ -431,22 +434,27 @@ rnBindLHS name_maker _ bind@(PatBind { pat_lhs = pat }) -- gets updated to the FVs of the whole bind -- when doing the RHS below -rnBindLHS name_maker _ bind@(FunBind { fun_id = name@(L nameLoc _) }) - = do { newname <- applyNameMaker name_maker name - ; return (bind { fun_id = L nameLoc newname +rnBindLHS name_maker _ bind@(FunBind { fun_id = rdr_name }) + = do { name <- applyNameMaker name_maker rdr_name + ; return (bind { fun_id = name , bind_fvs = placeHolderNamesTc }) } -rnBindLHS name_maker _ (PatSynBind psb@PSB{ psb_id = rdrname@(L nameLoc _) }) - = do { unless (isTopRecNameMaker name_maker) $ - addErr localPatternSynonymErr - ; addLocM checkConName rdrname +rnBindLHS name_maker _ (PatSynBind psb@PSB{ psb_id = rdrname }) + | isTopRecNameMaker name_maker + = do { addLocM checkConName rdrname + ; name <- lookupLocatedTopBndrRn rdrname -- Should be bound at top level already + ; return (PatSynBind psb{ psb_id = name }) } + + | otherwise -- Pattern synonym, not at top level + = do { addErr localPatternSynonymErr -- Complain, but make up a fake + -- name so that we can carry on ; name <- applyNameMaker name_maker rdrname - ; return (PatSynBind psb{ psb_id = L nameLoc name }) } + ; return (PatSynBind psb{ psb_id = name }) } where localPatternSynonymErr :: SDoc localPatternSynonymErr - = hang (ptext (sLit "Illegal pattern synonym declaration")) - 2 (ptext (sLit "Pattern synonym declarations are only valid in the top-level scope")) + = hang (ptext (sLit "Illegal pattern synonym declaration for") <+> quotes (ppr rdrname)) + 2 (ptext (sLit "Pattern synonym declarations are only valid at top level")) rnBindLHS _ _ b = pprPanic "rnBindHS" (ppr b) diff --git a/compiler/rename/RnEnv.hs b/compiler/rename/RnEnv.hs index 6aa21fa0ba..f7a450414d 100644 --- a/compiler/rename/RnEnv.hs +++ b/compiler/rename/RnEnv.hs @@ -260,7 +260,7 @@ lookupTopBndrRn :: RdrName -> RnM Name lookupTopBndrRn n = do nopt <- lookupTopBndrRn_maybe n case nopt of Just n' -> return n' - Nothing -> do traceRn $ text "lookupTopBndrRn" + Nothing -> do traceRn $ (text "lookupTopBndrRn fail" <+> ppr n) unboundName WL_LocalTop n lookupLocatedTopBndrRn :: Located RdrName -> RnM (Located Name) diff --git a/compiler/rename/RnNames.hs b/compiler/rename/RnNames.hs index 145d6fca7d..5cb7b18cf7 100644 --- a/compiler/rename/RnNames.hs +++ b/compiler/rename/RnNames.hs @@ -491,14 +491,15 @@ getLocalNonValBinders :: MiniFixityEnv -> HsGroup RdrName -- Get all the top-level binders bound the group *except* -- for value bindings, which are treated separately -- Specifically we return AvailInfo for --- type decls (incl constructors and record selectors) --- class decls (including class ops) --- associated types --- foreign imports --- (in hs-boot files) value signatures +-- * type decls (incl constructors and record selectors) +-- * class decls (including class ops) +-- * associated types +-- * foreign imports +-- * pattern synonyms +-- * value signatures (in hs-boot files) getLocalNonValBinders fixity_env - (HsGroup { hs_valds = val_binds, + (HsGroup { hs_valds = binds, hs_tyclds = tycl_decls, hs_instds = inst_decls, hs_fords = foreign_decls }) @@ -515,11 +516,11 @@ getLocalNonValBinders fixity_env ; nti_avails <- concatMapM new_assoc inst_decls -- Finish off with value binders: - -- foreign decls for an ordinary module + -- foreign decls and pattern synonyms for an ordinary module -- type sigs in case of a hs-boot file only ; is_boot <- tcIsHsBootOrSig ; let val_bndrs | is_boot = hs_boot_sig_bndrs - | otherwise = for_hs_bndrs + | otherwise = for_hs_bndrs ++ patsyn_hs_bndrs ; val_avails <- mapM new_simple val_bndrs ; let avails = nti_avails ++ val_avails @@ -529,15 +530,18 @@ getLocalNonValBinders fixity_env ; envs <- extendGlobalRdrEnvRn avails fixity_env ; return (envs, new_bndrs) } } where + ValBindsIn val_binds val_sigs = binds + for_hs_bndrs :: [Located RdrName] - for_hs_bndrs = [ L decl_loc (unLoc nm) - | L decl_loc (ForeignImport nm _ _ _) <- foreign_decls] + for_hs_bndrs = hsForeignDeclsBinders foreign_decls + + patsyn_hs_bndrs :: [Located RdrName] + patsyn_hs_bndrs = hsPatSynBinders val_binds -- In a hs-boot file, the value binders come from the -- *signatures*, and there should be no foreign binders hs_boot_sig_bndrs = [ L decl_loc (unLoc n) | L decl_loc (TypeSig ns _ _) <- val_sigs, n <- ns] - ValBindsIn _ val_sigs = val_binds -- the SrcSpan attached to the input should be the span of the -- declaration, not just the name diff --git a/compiler/rename/RnPat.hs b/compiler/rename/RnPat.hs index 160f9ad2d1..7f593f1398 100644 --- a/compiler/rename/RnPat.hs +++ b/compiler/rename/RnPat.hs @@ -212,6 +212,11 @@ rnHsSigCps :: HsWithBndrs RdrName (LHsType RdrName) rnHsSigCps sig = CpsRn (rnHsBndrSig PatCtx sig) +newPatLName :: NameMaker -> Located RdrName -> CpsRn (Located Name) +newPatLName name_maker rdr_name@(L loc _) + = do { name <- newPatName name_maker rdr_name + ; return (L loc name) } + newPatName :: NameMaker -> Located RdrName -> CpsRn Name newPatName (LamMk report_unused) rdr_name = CpsRn (\ thing_inside -> @@ -307,8 +312,9 @@ rnPat :: HsMatchContext Name -- for error messages rnPat ctxt pat thing_inside = rnPats ctxt [pat] (\pats' -> let [pat'] = pats' in thing_inside pat') -applyNameMaker :: NameMaker -> Located RdrName -> RnM Name -applyNameMaker mk rdr = do { (n, _fvs) <- runCps (newPatName mk rdr); return n } +applyNameMaker :: NameMaker -> Located RdrName -> RnM (Located Name) +applyNameMaker mk rdr = do { (n, _fvs) <- runCps (newPatLName mk rdr) + ; return n } -- ----------- Entry point 2: rnBindPat ------------------- -- Binds local names; in a recursive scope that involves other bound vars @@ -392,17 +398,17 @@ rnPatAndThen _ (NPat lit mb_neg _eq) ; return (NPat lit' mb_neg' eq') } rnPatAndThen mk (NPlusKPat rdr lit _ _) - = do { new_name <- newPatName mk rdr + = do { new_name <- newPatLName mk rdr ; lit' <- liftCpsFV $ rnOverLit lit ; minus <- liftCpsFV $ lookupSyntaxName minusName ; ge <- liftCpsFV $ lookupSyntaxName geName - ; return (NPlusKPat (L (nameSrcSpan new_name) new_name) lit' ge minus) } + ; return (NPlusKPat new_name lit' ge minus) } -- The Report says that n+k patterns must be in Integral rnPatAndThen mk (AsPat rdr pat) - = do { new_name <- newPatName mk rdr + = do { new_name <- newPatLName mk rdr ; pat' <- rnLPatAndThen mk pat - ; return (AsPat (L (nameSrcSpan new_name) new_name) pat') } + ; return (AsPat new_name pat') } rnPatAndThen mk p@(ViewPat expr pat _ty) = do { liftCps $ do { vp_flag <- xoptM Opt_ViewPatterns diff --git a/compiler/rename/RnSource.hs b/compiler/rename/RnSource.hs index 2c9331f00b..d9536fbfae 100644 --- a/compiler/rename/RnSource.hs +++ b/compiler/rename/RnSource.hs @@ -94,9 +94,19 @@ rnSrcDecls extra_deps group@(HsGroup { hs_valds = val_decls, local_fix_env <- makeMiniFixityEnv fix_decls ; -- (B) Bring top level binders (and their fixities) into scope, - -- *except* for the value bindings, which get brought in below. - -- However *do* include class ops, data constructors - -- And for hs-boot files *do* include the value signatures + -- *except* for the value bindings, which get done in step (D) + -- with collectHsIdBinders. However *do* include + -- + -- * Class ops, data constructors, and record fields, + -- because they do not have value declarations. + -- Aso step (C) depends on datacons and record fields + -- + -- * Pattern synonyms, becuase they (and data constructors) + -- are needed for rnTopBindLHS (Trac #9889) + -- + -- * For hs-boot files, include the value signatures + -- Again, they have no value declarations + -- (tc_envs, tc_bndrs) <- getLocalNonValBinders local_fix_env group ; setEnvs tc_envs $ do { @@ -114,12 +124,13 @@ rnSrcDecls extra_deps group@(HsGroup { hs_valds = val_decls, -- It uses the fixity env from (A) to bind fixities for view patterns. new_lhs <- rnTopBindsLHS local_fix_env val_decls ; -- bind the LHSes (and their fixities) in the global rdr environment - let { val_binders = collectHsValBinders new_lhs ; + let { val_binders = collectHsIdBinders new_lhs ; + -- Not pattern-synonym binders, because we did + -- them in step (B) all_bndrs = extendNameSetList tc_bndrs val_binders ; val_avails = map Avail val_binders } ; traceRn (text "rnSrcDecls" <+> ppr val_avails) ; (tcg_env, tcl_env) <- extendGlobalRdrEnvRn val_avails local_fix_env ; - traceRn (ptext (sLit "Val binders") <+> (ppr val_binders)) ; setEnvs (tcg_env, tcl_env) $ do { -- Now everything is in scope, as the remaining renaming assumes. @@ -185,9 +196,8 @@ rnSrcDecls extra_deps group@(HsGroup { hs_valds = val_decls, hs_vects = rn_vect_decls, hs_docs = rn_docs } ; - tycl_bndrs = hsTyClDeclsBinders rn_tycl_decls rn_inst_decls ; - ford_bndrs = hsForeignDeclsBinders rn_foreign_decls ; - other_def = (Just (mkNameSet tycl_bndrs `unionNameSet` mkNameSet ford_bndrs), emptyNameSet) ; + tcf_bndrs = hsTyClForeignBinders rn_tycl_decls rn_inst_decls rn_foreign_decls ; + other_def = (Just (mkNameSet tcf_bndrs), emptyNameSet) ; other_fvs = plusFVs [src_fvs1, src_fvs2, src_fvs3, src_fvs4, src_fvs5, src_fvs6, src_fvs7, src_fvs8, src_fvs9] ; diff --git a/compiler/typecheck/TcBinds.hs b/compiler/typecheck/TcBinds.hs index 50bc62d087..340de68bfa 100644 --- a/compiler/typecheck/TcBinds.hs +++ b/compiler/typecheck/TcBinds.hs @@ -362,9 +362,9 @@ tc_group top_lvl sig_fn prag_fn (NonRecursive, binds) thing_inside -- We want to keep non-recursive things non-recursive -- so that we desugar unlifted bindings correctly = do { let bind = case bagToList binds of - [] -> panic "tc_group: empty list of binds" [bind] -> bind - _ -> panic "tc_group: NonRecursive binds is not a singleton bag" + [] -> panic "tc_group: empty list of binds" + _ -> panic "tc_group: NonRecursive binds is not a singleton bag" ; (bind', thing) <- tc_single top_lvl sig_fn prag_fn bind thing_inside ; return ( [(NonRecursive, bind')], thing) } @@ -375,9 +375,7 @@ tc_group top_lvl sig_fn prag_fn (Recursive, binds) thing_inside -- (This used to be optional, but isn't now.) do { traceTc "tc_group rec" (pprLHsBinds binds) ; when hasPatSyn $ recursivePatSynErr binds - ; (binds1, _ids, thing) <- go sccs - -- Here is where we should do bindInstsOfLocalFuns - -- if we start having Methods again + ; (binds1, thing) <- go sccs ; return ([(Recursive, binds1)], thing) } -- Rec them all together where @@ -388,12 +386,12 @@ tc_group top_lvl sig_fn prag_fn (Recursive, binds) thing_inside sccs :: [SCC (LHsBind Name)] sccs = stronglyConnCompFromEdgedVertices (mkEdges sig_fn binds) - go :: [SCC (LHsBind Name)] -> TcM (LHsBinds TcId, [TcId], thing) + go :: [SCC (LHsBind Name)] -> TcM (LHsBinds TcId, thing) go (scc:sccs) = do { (binds1, ids1, closed) <- tc_scc scc - ; (binds2, ids2, thing) <- tcExtendLetEnv top_lvl closed ids1 $ - go sccs - ; return (binds1 `unionBags` binds2, ids1 ++ ids2, thing) } - go [] = do { thing <- thing_inside; return (emptyBag, [], thing) } + ; (binds2, thing) <- tcExtendLetEnv top_lvl closed ids1 $ + go sccs + ; return (binds1 `unionBags` binds2, thing) } + go [] = do { thing <- thing_inside; return (emptyBag, thing) } tc_scc (AcyclicSCC bind) = tc_sub_group NonRecursive [bind] tc_scc (CyclicSCC binds) = tc_sub_group Recursive binds @@ -417,20 +415,14 @@ tc_single :: forall thing. tc_single _top_lvl sig_fn _prag_fn (L _ (PatSynBind psb@PSB{ psb_id = L _ name })) thing_inside = do { (pat_syn, aux_binds) <- tc_pat_syn_decl ; let tything = AConLike (PatSynCon pat_syn) --- SLPJ: Why is this necessary? --- implicit_ids = patSynMatcher pat_syn : --- maybeToList (patSynWorker pat_syn) - - ; thing <- tcExtendGlobalEnv [tything] $ --- tcExtendGlobalEnvImplicit (map AnId implicit_ids) $ - thing_inside + ; thing <- tcExtendGlobalEnv [tything] thing_inside ; return (aux_binds, thing) } where tc_pat_syn_decl = case sig_fn name of - Nothing -> tcInferPatSynDecl psb + Nothing -> tcInferPatSynDecl psb Just (TcPatSynInfo tpsi) -> tcCheckPatSynDecl psb tpsi - Just _ -> panic "tc_single" + Just _ -> panic "tc_single" tc_single top_lvl sig_fn prag_fn lbind thing_inside = do { (binds1, ids, closed) <- tcPolyBinds top_lvl sig_fn prag_fn @@ -445,10 +437,9 @@ noCompleteSig Nothing = True noCompleteSig (Just sig) = isPartialSig sig ------------------------ -mkEdges :: TcSigFun -> LHsBinds Name - -> [(LHsBind Name, BKey, [BKey])] +mkEdges :: TcSigFun -> LHsBinds Name -> [Node BKey (LHsBind Name)] -type BKey = Int -- Just number off the bindings +type BKey = Int -- Just number off the bindings mkEdges sig_fn binds = [ (bind, key, [key | n <- nameSetElems (bind_fvs (unLoc bind)), @@ -463,24 +454,17 @@ mkEdges sig_fn binds key_map :: NameEnv BKey -- Which binding it comes from key_map = mkNameEnv [(bndr, key) | (L _ bind, key) <- keyd_binds - , bndr <- bindersOfHsBind bind ] - -bindersOfHsBind :: HsBind Name -> [Name] -bindersOfHsBind (PatBind { pat_lhs = pat }) = collectPatBinders pat -bindersOfHsBind (FunBind { fun_id = L _ f }) = [f] -bindersOfHsBind (PatSynBind PSB{ psb_id = L _ psyn }) = [psyn] -bindersOfHsBind (AbsBinds {}) = panic "bindersOfHsBind AbsBinds" -bindersOfHsBind (VarBind {}) = panic "bindersOfHsBind VarBind" + , bndr <- collectHsBindBinders bind ] ------------------------ tcPolyBinds :: TopLevelFlag -> TcSigFun -> PragFun - -> RecFlag -- Whether the group is really recursive - -> RecFlag -- Whether it's recursive after breaking - -- dependencies based on type signatures - -> [LHsBind Name] + -> RecFlag -- Whether the group is really recursive + -> RecFlag -- Whether it's recursive after breaking + -- dependencies based on type signatures + -> [LHsBind Name] -- None are PatSynBind -> TcM (LHsBinds TcId, [TcId], TopLevelFlag) --- Typechecks a single bunch of bindings all together, +-- Typechecks a single bunch of values bindings all together, -- and generalises them. The bunch may be only part of a recursive -- group, because we use type signatures to maximise polymorphism -- @@ -489,6 +473,7 @@ tcPolyBinds :: TopLevelFlag -> TcSigFun -> PragFun -- important. -- -- Knows nothing about the scope of the bindings +-- None of the bindings are pattern synonyms tcPolyBinds top_lvl sig_fn prag_fn rec_group rec_tc bind_list = setSrcSpan loc $ diff --git a/testsuite/tests/ghci/scripts/T8776.stdout b/testsuite/tests/ghci/scripts/T8776.stdout index 5aea751e80..7f8d57e7ee 100644 --- a/testsuite/tests/ghci/scripts/T8776.stdout +++ b/testsuite/tests/ghci/scripts/T8776.stdout @@ -1 +1 @@ -pattern P :: (Num t, Eq t1) => A t t1 -- Defined at T8776.hs:6:9 +pattern P :: (Num t, Eq t1) => A t t1 -- Defined at T8776.hs:6:1 diff --git a/testsuite/tests/patsyn/should_compile/T9889.hs b/testsuite/tests/patsyn/should_compile/T9889.hs new file mode 100644 index 0000000000..27b219f6ff --- /dev/null +++ b/testsuite/tests/patsyn/should_compile/T9889.hs @@ -0,0 +1,6 @@ +{-# LANGUAGE PatternSynonyms #-} +module ShouldCompile where + +pattern Id x = x + +Id x = True diff --git a/testsuite/tests/patsyn/should_compile/all.T b/testsuite/tests/patsyn/should_compile/all.T index d5d5eed1ce..086875ffa4 100644 --- a/testsuite/tests/patsyn/should_compile/all.T +++ b/testsuite/tests/patsyn/should_compile/all.T @@ -20,3 +20,4 @@ test('T8968-2', normal, compile, ['']) test('T8968-3', expect_broken(9953), compile, ['']) test('ImpExp_Imp', [extra_clean(['ImpExp_Exp.hi', 'ImpExp_Exp.o'])], multimod_compile, ['ImpExp_Imp', '-v0']) test('T9857', normal, compile, ['']) +test('T9889', normal, compile, ['']) diff --git a/testsuite/tests/patsyn/should_fail/local.stderr b/testsuite/tests/patsyn/should_fail/local.stderr index a9a8d01af9..c570809640 100644 --- a/testsuite/tests/patsyn/should_fail/local.stderr +++ b/testsuite/tests/patsyn/should_fail/local.stderr @@ -1,4 +1,4 @@ local.hs:7:5: - Illegal pattern synonym declaration - Pattern synonym declarations are only valid in the top-level scope + Illegal pattern synonym declaration for āPā + Pattern synonym declarations are only valid at top level diff --git a/testsuite/tests/patsyn/should_run/ghci.stdout b/testsuite/tests/patsyn/should_run/ghci.stdout index 796aa72d61..e434de3dd6 100644 --- a/testsuite/tests/patsyn/should_run/ghci.stdout +++ b/testsuite/tests/patsyn/should_run/ghci.stdout @@ -1,3 +1,3 @@ -pattern Single :: t -> [t] -- Defined at <interactive>:4:9 +pattern Single :: t -> [t] -- Defined at <interactive>:4:1 foo :: [Bool] -> [Bool] [False] |