Skip to content

Commit

Permalink
fixes #18059 (#18140)
Browse files Browse the repository at this point in the history
* fixes #18059
  • Loading branch information
Araq committed Jun 2, 2021
1 parent 63db2b1 commit f10eef2
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 3 deletions.
28 changes: 26 additions & 2 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = semExpr(c, n, flags + {efOperand})
if result.typ != nil:
# XXX tyGenericInst here?
if result.typ.kind == tyProc and tfUnresolved in result.typ.flags:
if result.typ.kind == tyProc and hasUnresolvedParams(result, {efOperand}):
#and tfUnresolved in result.typ.flags:
localError(c.config, n.info, errProcHasNoConcreteType % n.renderTree)
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
elif {efWantStmt, efAllowStmt} * flags != {}:
Expand Down Expand Up @@ -2649,6 +2650,23 @@ proc shouldBeBracketExpr(n: PNode): bool =
n[0] = be
return true

proc asBracketExpr(c: PContext; n: PNode): PNode =
proc isGeneric(c: PContext; n: PNode): bool =
if n.kind in {nkIdent, nkAccQuoted}:
let s = qualifiedLookUp(c, n, {})
result = s != nil and isGenericRoutineStrict(s)

assert n.kind in nkCallKinds
if n.len > 1 and isGeneric(c, n[1]):
let b = n[0]
if b.kind in nkSymChoices:
for i in 0..<b.len:
if b[i].kind == nkSym and b[i].sym.magic == mArrGet:
result = newNodeI(nkBracketExpr, n.info)
for i in 1..<n.len: result.add(n[i])
return result
return nil

proc hoistParamsUsedInDefault(c: PContext, call, letSection, defExpr: var PNode) =
# This takes care of complicated signatures such as:
# proc foo(a: int, b = a)
Expand Down Expand Up @@ -2820,8 +2838,14 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# the 'newSeq[T](x)' bug
setGenericParams(c, n[0])
result = semDirectOp(c, n, flags)
elif isSymChoice(n[0]) or nfDotField in n.flags:
elif nfDotField in n.flags:
result = semDirectOp(c, n, flags)
elif isSymChoice(n[0]):
let b = asBracketExpr(c, n)
if b != nil:
result = semExpr(c, b, flags)
else:
result = semDirectOp(c, n, flags)
else:
result = semIndirectOp(c, n, flags)

Expand Down
20 changes: 19 additions & 1 deletion compiler/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,23 @@ proc hasEmpty(typ: PType): bool =
for s in typ.sons:
result = result or hasEmpty(s)

proc hasUnresolvedParams(n: PNode; flags: TExprFlags): bool =
result = tfUnresolved in n.typ.flags
when false:
case n.kind
of nkSym:
result = isGenericRoutineStrict(n.sym)
of nkSymChoices:
for ch in n:
if hasUnresolvedParams(ch, flags):
return true
result = false
else:
result = false
if efOperand in flags:
if tfUnresolved notin n.typ.flags:
result = false

proc makeDeref(n: PNode): PNode =
var t = n.typ
if t.kind in tyUserTypeClasses and t.isResolvedUserTypeClass:
Expand Down Expand Up @@ -517,7 +534,8 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
typ = typ.lastSon
if hasEmpty(typ):
localError(c.config, def.info, errCannotInferTypeOfTheLiteral % typ.kind.toHumanStr)
elif typ.kind == tyProc and tfUnresolved in typ.flags:
elif typ.kind == tyProc and hasUnresolvedParams(def, {}):
# tfUnresolved in typ.flags:
localError(c.config, def.info, errProcHasNoConcreteType % def.renderTree)
when false:
# XXX This typing rule is neither documented nor complete enough to
Expand Down
35 changes: 35 additions & 0 deletions tests/metatype/tcps.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
discard """
output: '''10
string'''
"""

# bug #18059
type
C = ref object of RootObj
fn: ContProc
ex: ref Exception

ContProc = proc (c: C): C {.nimcall.}

proc noop(c: C): C = c

type
Env[T] = ref object of C
x: T

proc foo_cont[U](c: C): C =
proc afterCall[V](c: C): C =
echo Env[V](c).x

c.fn = afterCall[U]
return noop(c)

proc foo[T](x: T): C =
return Env[T](fn: foo_cont[T], x: x)

proc tramp(c: sink C) =
while c != nil and c.fn != nil:
c = c.fn(c)

tramp foo(10)
tramp foo("string")

0 comments on commit f10eef2

Please sign in to comment.