mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-31 18:32:11 +00:00
Merge branch 'master' of github.com:Araq/Nimrod into upstream
This commit is contained in:
@@ -79,6 +79,7 @@ type
|
||||
exc: PNode # stack of exceptions
|
||||
tags: PNode # list of tags
|
||||
bottom: int
|
||||
owner: PSym
|
||||
|
||||
PEffects = var TEffects
|
||||
|
||||
@@ -173,11 +174,16 @@ proc trackTryStmt(tracked: PEffects, n: PNode) =
|
||||
track(tracked, b.sons[blen-1])
|
||||
tracked.bottom = oldBottom
|
||||
|
||||
proc isIndirectCall(n: PNode): bool =
|
||||
proc isIndirectCall(n: PNode, owner: PSym): bool =
|
||||
# we don't count f(...) as an indirect call if 'f' is an parameter.
|
||||
# Instead we track expressions of type tyProc too. See the manual for
|
||||
# details:
|
||||
result = n.kind != nkSym or n.sym.kind notin (routineKinds+{skParam})
|
||||
if n.kind != nkSym:
|
||||
result = true
|
||||
elif n.sym.kind == skParam:
|
||||
result = owner != n.sym.owner or owner == nil
|
||||
elif n.sym.kind notin routineKinds:
|
||||
result = true
|
||||
|
||||
proc isForwardedProc(n: PNode): bool =
|
||||
result = n.kind == nkSym and sfForward in n.sym.flags
|
||||
@@ -274,7 +280,7 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
elif effectList.len == 0:
|
||||
if isForwardedProc(a):
|
||||
propagateEffects(tracked, n, a.sym)
|
||||
elif isIndirectCall(a):
|
||||
elif isIndirectCall(a, tracked.owner):
|
||||
addEffect(tracked, createRaise(n))
|
||||
addTag(tracked, createTag(n))
|
||||
else:
|
||||
@@ -355,6 +361,7 @@ proc trackProc*(s: PSym, body: PNode) =
|
||||
var t: TEffects
|
||||
t.exc = effects.sons[exceptionEffects]
|
||||
t.tags = effects.sons[tagEffects]
|
||||
t.owner = s
|
||||
track(t, body)
|
||||
|
||||
let p = s.ast.sons[pragmasPos]
|
||||
|
||||
@@ -2910,7 +2910,8 @@ possibly raised exceptions; the algorithm operates on ``p``'s call graph:
|
||||
raise ``system.E_Base`` (the base type of the exception hierarchy) and
|
||||
thus any exception unless ``T`` has an explicit ``raises`` list.
|
||||
However if the call is of the form ``f(...)`` where ``f`` is a parameter
|
||||
is ignored. Rule 2 compensates for this case.
|
||||
of the currently analysed routine it is ignored. The call is optimistically
|
||||
assumed to have no effect. Rule 2 compensates for this case.
|
||||
2. Every expression of some proc type wihtin a call that is not a call
|
||||
itself (and not nil) is assumed to be called indirectly somehow and thus
|
||||
its raises list is added to ``p``'s raises list.
|
||||
@@ -2933,9 +2934,9 @@ Rules 1-2 ensure the following works:
|
||||
proc doRaise() {.raises: [EIO].} =
|
||||
raise newException(EIO, "IO")
|
||||
|
||||
proc use() =
|
||||
proc use() {.raises: [].} =
|
||||
# doesn't compile! Can raise EIO!
|
||||
noRaise(doRaise)
|
||||
# Here the compiler inferes that EIO can be raised.
|
||||
|
||||
So in many cases a callback does not cause the compiler to be overly
|
||||
conservative in its effect analysis.
|
||||
|
||||
@@ -78,7 +78,7 @@ proc innerText*(n: PXmlNode): string =
|
||||
result = ""
|
||||
assert n.k == xnElement
|
||||
for i in 0 .. n.s.len-1:
|
||||
if n.s[i].k in {xnText, xnEntity}: result.add(n.fText)
|
||||
if n.s[i].k in {xnText, xnEntity}: result.add(n.s[i].fText)
|
||||
|
||||
proc tag*(n: PXmlNode): string {.inline.} =
|
||||
## gets the tag name of `n`. `n` has to be an ``xnElement`` node.
|
||||
|
||||
14
tests/reject/teffects5.nim
Normal file
14
tests/reject/teffects5.nim
Normal file
@@ -0,0 +1,14 @@
|
||||
discard """
|
||||
errormsg: 'type mismatch'
|
||||
line: 7
|
||||
"""
|
||||
|
||||
proc p(q: proc() ): proc() {.tags: [], raises: [], closure.} =
|
||||
return proc () =
|
||||
q()
|
||||
|
||||
let yay = p(proc () = raise newException(EIO, "IO"))
|
||||
|
||||
proc main() {.raises: [], tags: [].} = yay()
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user