summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2019-12-17 10:07:32 +0000
committerAndreas Rumpf <rumpf_a@web.de>2019-12-17 11:07:32 +0100
commite8f4586c68dbe111ac50b9ec86f7630040492d09 (patch)
tree5ae3964ffe8010f39cbf15474f04b38cb9227e9a
parente5ed4c1b7d366c78881ad65419475a9dc40e91b5 (diff)
downloadNim-e8f4586c68dbe111ac50b9ec86f7630040492d09.tar.gz
allow typed/untyped in magic procs (#12911)
-rw-r--r--compiler/semtypes.nim14
-rw-r--r--tests/proc/untyped.nim12
2 files changed, 20 insertions, 6 deletions
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 054e04a7c..4c88da077 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -1119,6 +1119,10 @@ proc newProcType(c: PContext; info: TLineInfo; prev: PType = nil): PType =
   # usual we desperately try to save memory:
   result.n.add newNodeI(nkEffectList, info)
 
+proc isMagic(sym: PSym): bool =
+  let nPragmas = sym.ast[pragmasPos]
+  return hasPragma(nPragmas, wMagic)
+
 proc semProcTypeNode(c: PContext, n, genericParams: PNode,
                      prev: PType, kind: TSymKind; isType=false): PType =
   # for historical reasons (code grows) this is invoked for parameter
@@ -1148,11 +1152,13 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
 
     if hasType:
       typ = semParamType(c, a[^2], constraint)
-      var owner = getCurrOwner(c).owner
+      let sym = getCurrOwner(c)
+      var owner = sym.owner
       # TODO: Disallow typed/untyped in procs in the compiler/stdlib
-      if (owner.kind != skModule or owner.owner.name.s != "stdlib") and
-        kind == skProc and (typ.kind == tyTyped or typ.kind == tyUntyped):
-          localError(c.config, a[^2].info, "'" & typ.sym.name.s & "' is only allowed in templates and macros")
+      if kind == skProc and (typ.kind == tyTyped or typ.kind == tyUntyped):
+        if not isMagic(sym):
+          if (owner.kind != skModule or (owner.owner.name.s != "stdlib")):
+            localError(c.config, a[^2].info, "'" & typ.sym.name.s & "' is only allowed in templates and macros or magic procs")
 
     if hasDefault:
       def = a[^1]
diff --git a/tests/proc/untyped.nim b/tests/proc/untyped.nim
index f8b3ead7b..4a87f2b07 100644
--- a/tests/proc/untyped.nim
+++ b/tests/proc/untyped.nim
@@ -1,7 +1,15 @@
 discard """
-  errormsg: "'untyped' is only allowed in templates and macros"
-  line: 6
+  errormsg: "'untyped' is only allowed in templates and macros or magic procs"
+  line: 14
 """
 
+# magic procs are allowed with `untyped`
+proc declaredInScope2*(x: untyped): bool {.magic: "DefinedInScope", noSideEffect, compileTime.}
+proc bar(): bool =
+  var x = 1
+  declaredInScope2(x)
+static: doAssert bar()
+
+# but not non-magic procs
 proc fun(x:untyped)=discard
 fun(10)