summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2012-05-09 15:23:25 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2012-05-09 16:03:54 +0100
commit4c550307d96257b6d128183b329ef99a07873dbc (patch)
tree64c4d1af72911cc940fbfa15e109098b20726c0e /compiler
parente08cad76e8a434aca42996f79fc8bb790f291570 (diff)
downloadhaskell-4c550307d96257b6d128183b329ef99a07873dbc.tar.gz
Take care not to mix polymorphic and unlifted bindings in a group
Fixes Trac #6078
Diffstat (limited to 'compiler')
-rw-r--r--compiler/typecheck/TcBinds.lhs59
1 files changed, 41 insertions, 18 deletions
diff --git a/compiler/typecheck/TcBinds.lhs b/compiler/typecheck/TcBinds.lhs
index 1cc97de8d3..e6e07576d2 100644
--- a/compiler/typecheck/TcBinds.lhs
+++ b/compiler/typecheck/TcBinds.lhs
@@ -379,7 +379,7 @@ tcPolyBinds top_lvl sig_fn prag_fn rec_group rec_tc bind_list
-- Set up main recover; take advantage of any type sigs
{ traceTc "------------------------------------------------" empty
- ; traceTc "Bindings for" (ppr binder_names)
+ ; traceTc "Bindings for {" (ppr binder_names)
-- -- Instantiate the polytypes of any binders that have signatures
-- -- (as determined by sig_fn), returning a TcSigInfo for each
@@ -390,7 +390,7 @@ tcPolyBinds top_lvl sig_fn prag_fn rec_group rec_tc bind_list
; let plan = decideGeneralisationPlan dflags type_env
binder_names bind_list sig_fn
; traceTc "Generalisation plan" (ppr plan)
- ; result@(_, poly_ids, _) <- case plan of
+ ; result@(tc_binds, poly_ids, _) <- case plan of
NoGen -> tcPolyNoGen sig_fn prag_fn rec_tc bind_list
InferGen mn cl -> tcPolyInfer mn cl sig_fn prag_fn rec_tc bind_list
CheckGen sig -> tcPolyCheck sig prag_fn rec_tc bind_list
@@ -398,7 +398,10 @@ tcPolyBinds top_lvl sig_fn prag_fn rec_group rec_tc bind_list
-- Check whether strict bindings are ok
-- These must be non-recursive etc, and are not generalised
-- They desugar to a case expression in the end
- ; checkStrictBinds top_lvl rec_group bind_list poly_ids
+ ; checkStrictBinds top_lvl rec_group bind_list tc_binds poly_ids
+ ; traceTc "} End of bindings for" (vcat [ ppr binder_names, ppr rec_group
+ , vcat [ppr id <+> ppr (idType id) | id <- poly_ids]
+ ])
; return result }
where
@@ -1242,21 +1245,32 @@ decideGeneralisationPlan dflags type_env bndr_names lbinds sig_fn
-------------------
checkStrictBinds :: TopLevelFlag -> RecFlag
- -> [LHsBind Name] -> [Id]
+ -> [LHsBind Name]
+ -> LHsBinds TcId -> [Id]
-> TcM ()
-- Check that non-overloaded unlifted bindings are
-- a) non-recursive,
-- b) not top level,
-- c) not a multiple-binding group (more or less implied by (a))
-checkStrictBinds top_lvl rec_group binds poly_ids
+checkStrictBinds top_lvl rec_group orig_binds tc_binds poly_ids
| unlifted || bang_pat
= do { checkTc (isNotTopLevel top_lvl)
- (strictBindErr "Top-level" unlifted binds)
+ (strictBindErr "Top-level" unlifted orig_binds)
; checkTc (isNonRec rec_group)
- (strictBindErr "Recursive" unlifted binds)
- ; checkTc (isSingleton binds)
- (strictBindErr "Multiple" unlifted binds)
+ (strictBindErr "Recursive" unlifted orig_binds)
+
+ ; checkTc (all is_monomorphic (bagToList tc_binds))
+ (polyBindErr orig_binds)
+ -- data Ptr a = Ptr Addr#
+ -- f x = let p@(Ptr y) = ... in ...
+ -- Here the binding for 'p' is polymorphic, but does
+ -- not mix with an unlifted binding for 'y'. You should
+ -- use a bang pattern. Trac #6078.
+
+ ; checkTc (isSingleton orig_binds)
+ (strictBindErr "Multiple" unlifted orig_binds)
+
-- This should be a checkTc, not a warnTc, but as of GHC 6.11
-- the versions of alex and happy available have non-conforming
-- templates, so the GHC build fails if it's an error:
@@ -1267,31 +1281,40 @@ checkStrictBinds top_lvl rec_group binds poly_ids
-- Warn about this, but not about
-- x# = 4# +# 1#
-- (# a, b #) = ...
- (unliftedMustBeBang binds) }
+ (unliftedMustBeBang orig_binds) }
| otherwise
- = return ()
+ = traceTc "csb2" (ppr poly_ids) >>
+ return ()
where
unlifted = any is_unlifted poly_ids
- bang_pat = any (isBangHsBind . unLoc) binds
- lifted_pat = any (isLiftedPatBind . unLoc) binds
+ bang_pat = any (isBangHsBind . unLoc) orig_binds
+ lifted_pat = any (isLiftedPatBind . unLoc) orig_binds
+
is_unlifted id = case tcSplitForAllTys (idType id) of
(_, rho) -> isUnLiftedType rho
+ is_monomorphic (L _ (AbsBinds { abs_tvs = tvs, abs_ev_vars = evs }))
+ = null tvs && null evs
+ is_monomorphic _ = True
+
unliftedMustBeBang :: [LHsBind Name] -> SDoc
unliftedMustBeBang binds
= hang (text "Pattern bindings containing unlifted types should use an outermost bang pattern:")
- 2 (pprBindList binds)
+ 2 (vcat (map ppr binds))
+
+polyBindErr :: [LHsBind Name] -> SDoc
+polyBindErr binds
+ = hang (ptext (sLit "You can't mix polymorphic and unlifted bindings"))
+ 2 (vcat [vcat (map ppr binds),
+ ptext (sLit "Probable fix: use a bang pattern")])
strictBindErr :: String -> Bool -> [LHsBind Name] -> SDoc
strictBindErr flavour unlifted binds
= hang (text flavour <+> msg <+> ptext (sLit "aren't allowed:"))
- 2 (pprBindList binds)
+ 2 (vcat (map ppr binds))
where
msg | unlifted = ptext (sLit "bindings for unlifted types")
| otherwise = ptext (sLit "bang-pattern bindings")
-
-pprBindList :: [LHsBind Name] -> SDoc
-pprBindList binds = vcat (map ppr binds)
\end{code}