summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/typecheck/TcBinds.lhs10
-rw-r--r--docs/users_guide/glasgow_exts.xml21
2 files changed, 22 insertions, 9 deletions
diff --git a/compiler/typecheck/TcBinds.lhs b/compiler/typecheck/TcBinds.lhs
index 80a773c323..4872a80d7e 100644
--- a/compiler/typecheck/TcBinds.lhs
+++ b/compiler/typecheck/TcBinds.lhs
@@ -1076,6 +1076,7 @@ instance Outputable GeneralisationPlan where
decideGeneralisationPlan
:: DynFlags -> TopLevelFlag -> [Name] -> [LHsBind Name] -> TcSigFun -> GeneralisationPlan
decideGeneralisationPlan dflags top_lvl _bndrs binds sig_fn
+ | bang_pat_binds = NoGen
| mono_pat_binds = NoGen
| Just sig <- one_funbind_with_sig binds = if null (sig_tvs sig) && null (sig_theta sig)
then NoGen -- Optimise common case
@@ -1085,7 +1086,12 @@ decideGeneralisationPlan dflags top_lvl _bndrs binds sig_fn
| otherwise = InferGen mono_restriction
where
- mono_pat_binds = xopt Opt_MonoPatBinds dflags
+ bang_pat_binds = any (isBangHsBind . unLoc) binds
+ -- Bang patterns must not be polymorphic,
+ -- because we are going to force them
+ -- See Trac #4498
+
+ mono_pat_binds = xopt Opt_MonoPatBinds dflags
&& any (is_pat_bind . unLoc) binds
mono_restriction = xopt Opt_MonomorphismRestriction dflags
@@ -1129,7 +1135,7 @@ checkStrictBinds top_lvl rec_group binds poly_ids
; checkTc (isNonRec rec_group)
(strictBindErr "Recursive" unlifted binds)
; checkTc (isSingleton binds)
- (strictBindErr "Multiple" unlifted binds)
+ (strictBindErr "Multiple" unlifted 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:
diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml
index 7bb33c666f..161371b8c3 100644
--- a/docs/users_guide/glasgow_exts.xml
+++ b/docs/users_guide/glasgow_exts.xml
@@ -7200,16 +7200,23 @@ forces evaluation anyway does nothing.
There is one (apparent) exception to this general rule that a bang only
makes a difference when it precedes a variable or wild-card: a bang at the
top level of a <literal>let</literal> or <literal>where</literal>
-binding makes the binding strict, regardless of the pattern. For example:
+binding makes the binding strict, regardless of the pattern.
+(We say "apparent" exception because the Right Way to think of it is that the bang
+at the top of a binding is not part of the <emphasis>pattern</emphasis>; rather it
+is part of the syntax of the <emphasis>binding</emphasis>,
+creating a "bang-pattern binding".)
+For example:
<programlisting>
let ![x,y] = e in b
</programlisting>
-is a strict binding: operationally, it evaluates <literal>e</literal>, matches
-it against the pattern <literal>[x,y]</literal>, and then evaluates <literal>b</literal>.
-(We say "apparent" exception because the Right Way to think of it is that the bang
-at the top of a binding is not part of the <emphasis>pattern</emphasis>; rather it
-is part of the syntax of the <emphasis>binding</emphasis>.)
-Nested bangs in a pattern binding behave uniformly with all other forms of
+is a bang-pattern binding. Operationally, it behaves just like a case expression:
+<programlisting>
+case e of [x,y] -> b
+</programlisting>
+Like a case expression, a bang-pattern binding must be non-recursive, and
+is monomorphic.
+
+However, <emphasis>nested</emphasis> bangs in a pattern binding behave uniformly with all other forms of
pattern matching. For example
<programlisting>
let (!x,[y]) = e in b