Reject top-level typed TH splices. Fixes #10945
authorJan Stolarek <jan.stolarek@p.lodz.pl>
Tue, 20 Oct 2015 12:09:13 +0000 (14:09 +0200)
committerJan Stolarek <jan.stolarek@p.lodz.pl>
Tue, 20 Oct 2015 18:27:27 +0000 (20:27 +0200)
When TemplateHaskell language extension is enabled it is valid to have
top-level expressions.  Each such expression is treated as a contents
of a splice.  The problem arises with typed splices.  They are not valid
at the top level and therefore we should interpret them not as a splice
but as a top-level expression (aka. implicit splice).  So saying:

$$foo

is equivalent of:

$( $$foo )

This patch makes sure that this is indeed the case.  Until now we
incorrectly treated typed splices as explicit splices.

compiler/parser/RdrHsSyn.hs
testsuite/tests/th/T10945.stderr [new file with mode: 0644]
testsuite/tests/th/all.T

index 8bc4f6c..e64a575 100644 (file)
@@ -263,11 +263,18 @@ mkSpliceDecl :: LHsExpr RdrName -> HsDecl RdrName
 -- but if she wrote, say,
 --      f x            then behave as if she'd written $(f x)
 --                     ie a SpliceD
+--
+-- Typed splices are not allowed at the top level, thus we do not represent them
+-- as spliced declaration.  See #10945
 mkSpliceDecl lexpr@(L loc expr)
-  | HsSpliceE splice <- expr = SpliceD (SpliceDecl (L loc splice) ExplicitSplice)
-  | otherwise                = SpliceD (SpliceDecl (L loc splice) ImplicitSplice)
-  where
-    splice = mkUntypedSplice lexpr
+  | HsSpliceE splice@(HsUntypedSplice {}) <- expr
+  = SpliceD (SpliceDecl (L loc splice) ExplicitSplice)
+
+  | HsSpliceE splice@(HsQuasiQuote {}) <- expr
+  = SpliceD (SpliceDecl (L loc splice) ExplicitSplice)
+
+  | otherwise
+  = SpliceD (SpliceDecl (L loc (mkUntypedSplice lexpr)) ImplicitSplice)
 
 mkRoleAnnotDecl :: SrcSpan
                 -> Located RdrName                   -- type being annotated
diff --git a/testsuite/tests/th/T10945.stderr b/testsuite/tests/th/T10945.stderr
new file mode 100644 (file)
index 0000000..0c1d949
--- /dev/null
@@ -0,0 +1,29 @@
+
+T10945.hs:7:11:
+    Couldn't match expected type ‘TExp DecsQ’ with actual type ‘[Dec]’
+    In the first argument of ‘return’, namely
+      ‘[SigD
+          (mkName "m")
+          (ForallT
+             [PlainTV (mkName "a")]
+             []
+             (AppT (AppT ArrowT (VarT (mkName "a"))) (VarT (mkName "a")))),
+        FunD (mkName "m") [Clause [...] (NormalB (VarE (mkName "x"))) []]]’
+    In the expression:
+      return
+        [SigD
+           (mkName "m")
+           (ForallT
+              [PlainTV (mkName "a")]
+              []
+              (AppT (AppT ArrowT (VarT (mkName "a"))) (VarT (mkName "a")))),
+         FunD (mkName "m") [Clause [...] (NormalB (VarE (mkName "x"))) []]]
+    In the Template Haskell splice
+      $$(return
+           [SigD
+              (mkName "m")
+              (ForallT
+                 [PlainTV (mkName "a")]
+                 []
+                 (AppT (AppT ArrowT (VarT (mkName "a"))) (VarT (mkName "a")))),
+            FunD (mkName "m") [Clause [...] (NormalB (VarE (mkName "x"))) []]])
index 1e05d72..3d08f36 100644 (file)
@@ -366,5 +366,5 @@ test('T10796b', normal, compile_fail, ['-v0'])
 test('T10811', normal, compile, ['-v0'])
 test('T10810', normal, compile, ['-v0'])
 test('T10891', normal, compile, ['-v0'])
-test('T10945', expect_broken(10945), compile, ['-v0'])
+test('T10945', normal, compile_fail, ['-v0'])
 test('T10946', expect_broken(10946), compile, ['-v0'])