summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim3
-rw-r--r--compiler/sempass2.nim24
-rw-r--r--compiler/vmdeps.nim3
-rw-r--r--lib/core/macros.nim4
-rw-r--r--tests/pragmas/tcustom_pragma.nim10
5 files changed, 30 insertions, 14 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 6302c21b9..dbf1151a9 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -322,7 +322,8 @@ const
   usesEffects* = 1      # read effects at position 1
   writeEffects* = 2     # write effects at position 2
   tagEffects* = 3       # user defined tag ('gc', 'time' etc.)
-  effectListLen* = 4    # list of effects list
+  pragmasEffects* = 4    # not an effect, but a slot for pragmas in proc type
+  effectListLen* = 5    # list of effects list
 
 type
   TTypeKind* = enum  # order is important!
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index 4d3ee0408..e7a76ec22 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -552,6 +552,10 @@ proc isOwnedProcVar(n: PNode; owner: PSym): bool =
   # XXX prove the soundness of this effect system rule
   result = n.kind == nkSym and n.sym.kind == skParam and owner == n.sym.owner
 
+proc isNoEffectList(n: PNode): bool {.inline.} =
+  assert n.kind == nkEffectList
+  n.len == 0 or (n[tagEffects] == nil and n[exceptionEffects] == nil)
+
 proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
   let a = skipConvAndClosure(n)
   let op = a.typ
@@ -561,7 +565,7 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
     let s = n.skipConv
     if s.kind == nkSym and s.sym.kind in routineKinds:
       propagateEffects(tracked, n, s.sym)
-    elif effectList.len == 0:
+    elif isNoEffectList(effectList):
       if isForwardedProc(n):
         # we have no explicit effects but it's a forward declaration and so it's
         # stated there are no additional effects, so simply propagate them:
@@ -723,7 +727,7 @@ proc track(tracked: PEffects, n: PNode) =
       var effectList = op.n.sons[0]
       if a.kind == nkSym and a.sym.kind == skMethod:
         propagateEffects(tracked, n, a.sym)
-      elif effectList.len == 0:
+      elif isNoEffectList(effectList):
         if isForwardedProc(a):
           propagateEffects(tracked, n, a.sym)
         elif isIndirectCall(a, tracked.owner):
@@ -897,19 +901,18 @@ proc checkMethodEffects*(g: ModuleGraph; disp, branch: PSym) =
           [$branch.typ.lockLevel, $disp.typ.lockLevel])
 
 proc setEffectsForProcType*(g: ModuleGraph; t: PType, n: PNode) =
-  var effects = t.n.sons[0]
+  var effects = t.n[0]
   if t.kind != tyProc or effects.kind != nkEffectList: return
-
-  let
-    raisesSpec = effectSpec(n, wRaises)
-    tagsSpec = effectSpec(n, wTags)
-  if not isNil(raisesSpec) or not isNil(tagsSpec):
+  if n.kind != nkEmpty:
     internalAssert g.config, effects.len == 0
     newSeq(effects.sons, effectListLen)
+    let raisesSpec = effectSpec(n, wRaises)
     if not isNil(raisesSpec):
-      effects.sons[exceptionEffects] = raisesSpec
+      effects[exceptionEffects] = raisesSpec
+    let tagsSpec = effectSpec(n, wTags)
     if not isNil(tagsSpec):
-      effects.sons[tagEffects] = tagsSpec
+      effects[tagEffects] = tagsSpec
+    effects[pragmasEffects] = n
 
 proc initEffects(g: ModuleGraph; effects: PNode; s: PSym; t: var TEffects) =
   newSeq(effects.sons, effectListLen)
@@ -917,6 +920,7 @@ proc initEffects(g: ModuleGraph; effects: PNode; s: PSym; t: var TEffects) =
   effects.sons[tagEffects] = newNodeI(nkArgList, s.info)
   effects.sons[usesEffects] = g.emptyNode
   effects.sons[writeEffects] = g.emptyNode
+  effects.sons[pragmasEffects] = g.emptyNode
 
   t.exc = effects.sons[exceptionEffects]
   t.tags = effects.sons[tagEffects]
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index 865ecd36e..bf2418eaf 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -229,7 +229,8 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
       for i in 1..<t.sons.len:
         fp.add newIdentDefs(t.n[i], t.sons[i])
       result.add fp
-      result.add newNodeI(nkEmpty, info)  # pragmas aren't reconstructed yet
+      result.add if t.n[0].len > 0: t.n[0][pragmasEffects].copyTree
+                 else: newNodeI(nkEmpty, info)
     else:
       result = mapTypeToBracket("proc", mNone, t, info)
   of tyOpenArray: result = mapTypeToBracket("openArray", mOpenArray, t, info)
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 1f251b73e..8a1be3720 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -1284,7 +1284,9 @@ proc customPragmaNode(n: NimNode): NimNode =
   let
     typ = n.getTypeInst()
 
-  if typ.typeKind == ntyTypeDesc:
+  if typ.kind == nnkBracketExpr and typ.len > 1 and typ[1].kind == nnkProcTy: 
+    return typ[1][1]
+  elif typ.typeKind == ntyTypeDesc:
     let impl = typ[1].getImpl()
     if impl[0].kind == nnkPragmaExpr:
       return impl[0][1]
diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim
index cd1edccf6..a5f86b54d 100644
--- a/tests/pragmas/tcustom_pragma.nim
+++ b/tests/pragmas/tcustom_pragma.nim
@@ -145,4 +145,12 @@ block:
   type Annotated {.simpleAttr.} = object
 
   proc generic_proc[T]() =
-    assert Annotated.hasCustomPragma(simpleAttr)
\ No newline at end of file
+    assert Annotated.hasCustomPragma(simpleAttr)
+
+
+#--------------------------------------------------------------------------
+# Pragma on proc type
+
+let a: proc(x: int) {.defaultValue(5).} = nil
+static:
+  doAssert hasCustomPragma(a.type, defaultValue)