-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
fix #24912 #24913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix #24912 #24913
Changes from 12 commits
309a1f7
9169f14
8e34971
62f7bf6
a9a2f44
0919d87
2ed5744
6b0b152
5a80734
16625a2
495350f
91b03a9
4e940b7
dd9b0c5
ffe1130
67d5782
d6dec6f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -994,18 +994,18 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode, | |
let callee = result[0].sym | ||
case callee.kind | ||
of skMacro, skTemplate: discard | ||
else: | ||
if callee.kind == skIterator and callee.id == c.p.owner.id and | ||
not isClosureIterator(c.p.owner.typ): | ||
of skIterator: | ||
if callee.id == c.p.owner.id and not isClosureIterator(c.p.owner.typ): | ||
localError(c.config, n.info, errRecursiveDependencyIteratorX % callee.name.s) | ||
# error correction, prevents endless for loop elimination in transf. | ||
# See bug #2051: | ||
result[0] = newSymNode(errorSym(c, n)) | ||
elif callee.kind == skIterator: | ||
if efWantIterable in flags: | ||
let typ = newTypeS(tyIterable, c) | ||
rawAddSon(typ, result.typ) | ||
result.typ() = typ | ||
elif efWantIterable in flags: | ||
let typ = newTypeS(tyIterable, c) | ||
rawAddSon(typ, result.typ) | ||
result.typ() = typ | ||
else: | ||
discard | ||
|
||
proc resolveIndirectCall(c: PContext; n, nOrig: PNode; | ||
t: PType): TCandidate = | ||
|
@@ -1104,15 +1104,11 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType | |
elif isSymChoice(n[0]) and nfDotField notin n.flags: | ||
# overloaded generic procs e.g. newSeq[int] can end up here | ||
return semDirectOp(c, n, flags, expectedType) | ||
|
||
var t: PType = nil | ||
if n[0].typ != nil: | ||
t = skipTypes(n[0].typ, abstractInst+{tyOwned}-{tyTypeDesc, tyDistinct}) | ||
if t != nil and t.kind == tyTypeDesc: | ||
if n.len == 1: return semObjConstr(c, n, flags, expectedType) | ||
return semConv(c, n, flags) | ||
|
||
let nOrig = n.copyTree | ||
|
||
var nOrig = n.copyTree | ||
semOpAux(c, n) | ||
if t != nil and t.kind == tyProc: | ||
# This is a proc variable, apply normal overload resolution | ||
|
@@ -1154,21 +1150,45 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType | |
|
||
else: | ||
result = overloadedCallOpr(c, n) # this uses efNoUndeclared | ||
# Now that nkSym does not imply an iteration over the proc/iterator space, | ||
# the old ``prc`` (which is likely an nkIdent) has to be restored: | ||
if result == nil or result.kind == nkEmpty: | ||
# XXX: hmm, what kind of symbols will end up here? | ||
# do we really need to try the overload resolution? | ||
n[0] = prc | ||
nOrig[0] = prc | ||
n.flags.incl nfExprCall | ||
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags) | ||
if result == nil: return errorNode(c, n) | ||
var tcall = n.copyTree | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use a helper proc here and document what the heck is actually does and why it needs to do it. The compiler code is already incomprehensible with all these arbitrary transformations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I pulled out the part that is new. The rest is stuff that got re-positioned. |
||
if n[0].kind == nkDotExpr and n[0].typ.kind notin {tyProc, tyGenericInst, tyOwned}: | ||
tcall = n[0] | ||
tcall.transitionSonsKind(nkCall) | ||
for i in 1..<n.len: tcall.add n[i] | ||
let tmp = tcall[1] | ||
tcall[1] = tcall[0] | ||
tcall[0] = tmp | ||
tcall.typ() = nil | ||
nOrig = tcall.copyTree | ||
else: | ||
# Now that nkSym does not imply an iteration over the proc/iterator space, | ||
# the old ``prc`` (which is likely an nkIdent) has to be restored: | ||
tcall[0] = prc | ||
nOrig[0] = prc | ||
tcall.flags.incl nfExprCall | ||
let canspec = t != nil and t.kind in {tyFromExpr, tyTypeDesc} | ||
var fflags = flags | ||
if canspec: | ||
fflags.incl efPreferNilResult | ||
result = semOverloadedCallAnalyseEffects(c, tcall, nOrig, fflags) | ||
if result == nil: | ||
if canspec: | ||
if n.len == 2: | ||
return semConv(c, n, flags) | ||
elif n.len == 1: | ||
return semObjConstr(c, n, flags, expectedType) | ||
elif result.kind notin nkCallKinds: | ||
# the semExpr() in overloadedCallOpr can even break this condition! | ||
# See bug #904 of how to trigger it: | ||
return result | ||
#result = afterCallActions(c, result, nOrig, flags) | ||
if result == nil: | ||
return errorNode(c, n) | ||
if result.typ != nil and result.typ.kind == tyFromExpr and t != nil and t.kind == tyTypeDesc: | ||
# this is wrong but tyFromExpr doesn't always seem to be a valid result | ||
# anecdotally, this is what the compiler is trying to do but I think | ||
# tyFromExpr needs to be handled elsewhere | ||
return semObjConstr(c, n, flags, expectedType) | ||
if result[0].kind == nkSym: | ||
result = afterCallActions(c, result, nOrig, flags, expectedType) | ||
else: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
discard """ | ||
action: run | ||
""" | ||
|
||
#24913 | ||
block: | ||
type | ||
A = object | ||
b: int | ||
B = object | ||
b: proc(x: float): int | ||
|
||
proc b(T: typedesc[A]; s: float): int = 5 | ||
proc b(T: typedesc[B]; s: float): int = 7 | ||
proc testme(x: float): int = 3 | ||
doAssert A.b(1.0) == 5 | ||
doAssert B.b(1.0) == 7 | ||
doAssert B(b: testme).b(1.0) == 3 | ||
|
||
block: | ||
type | ||
Proc[T] = proc(text: T): int {.closure.} | ||
|
||
Rule[T] = object | ||
p: Proc[T] | ||
|
||
proc p(x: Rule[int]; y: float): int = 5 | ||
proc sp(y: int): int = 3 | ||
|
||
proc spring[T](rule: Rule[T]) = | ||
let p = proc (text: T) = | ||
doAssert rule.p(text) == 3 | ||
p(default(T)) | ||
|
||
Rule[int](p: sp).spring() | ||
|
||
block: | ||
type | ||
A = object | ||
|
||
proc new(T: type A): ref A = | ||
let c = (ref T)() | ||
c | ||
|
||
proc p[K](rng=A.new()) = | ||
discard new(A) | ||
|
||
p[int]() | ||
|
||
# cant be in a block | ||
type | ||
Cont[T] = ref RootObj | ||
Rule[T] = object | ||
p: Cont[T] | ||
|
||
proc p(x: Rule[int]; y: int): int = 5 | ||
|
||
proc spring[T](rule: Rule[T]) = | ||
let p = proc (x: T) = | ||
doAssert rule.p(x) == 5 | ||
p(default(T)) | ||
|
||
Rule[int]().spring() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe reuse
efNoUndeclared
instead?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't sure about this one either. Another option might be to pass through
errorsEnabled
as it is inresolveOverloads
and see if disabling the errors with this flag has bad side effects, but that doesn't sound great either. I'll useefNoUndeclared
instead if I end up sticking with this.edit: yea not sure how I missed that one