parent
63db2b19bf
commit
f10eef29b5
3 changed files with 80 additions and 3 deletions
|
|
@ -54,7 +54,8 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result = semExpr(c, n, flags + {efOperand})
|
result = semExpr(c, n, flags + {efOperand})
|
||||||
if result.typ != nil:
|
if result.typ != nil:
|
||||||
# XXX tyGenericInst here?
|
# 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)
|
localError(c.config, n.info, errProcHasNoConcreteType % n.renderTree)
|
||||||
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
|
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
|
||||||
elif {efWantStmt, efAllowStmt} * flags != {}:
|
elif {efWantStmt, efAllowStmt} * flags != {}:
|
||||||
|
|
@ -2649,6 +2650,23 @@ proc shouldBeBracketExpr(n: PNode): bool =
|
||||||
n[0] = be
|
n[0] = be
|
||||||
return true
|
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) =
|
proc hoistParamsUsedInDefault(c: PContext, call, letSection, defExpr: var PNode) =
|
||||||
# This takes care of complicated signatures such as:
|
# This takes care of complicated signatures such as:
|
||||||
# proc foo(a: int, b = a)
|
# proc foo(a: int, b = a)
|
||||||
|
|
@ -2820,7 +2838,13 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
# the 'newSeq[T](x)' bug
|
# the 'newSeq[T](x)' bug
|
||||||
setGenericParams(c, n[0])
|
setGenericParams(c, n[0])
|
||||||
result = semDirectOp(c, n, flags)
|
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)
|
result = semDirectOp(c, n, flags)
|
||||||
else:
|
else:
|
||||||
result = semIndirectOp(c, n, flags)
|
result = semIndirectOp(c, n, flags)
|
||||||
|
|
|
||||||
|
|
@ -385,6 +385,23 @@ proc hasEmpty(typ: PType): bool =
|
||||||
for s in typ.sons:
|
for s in typ.sons:
|
||||||
result = result or hasEmpty(s)
|
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 =
|
proc makeDeref(n: PNode): PNode =
|
||||||
var t = n.typ
|
var t = n.typ
|
||||||
if t.kind in tyUserTypeClasses and t.isResolvedUserTypeClass:
|
if t.kind in tyUserTypeClasses and t.isResolvedUserTypeClass:
|
||||||
|
|
@ -517,7 +534,8 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
typ = typ.lastSon
|
typ = typ.lastSon
|
||||||
if hasEmpty(typ):
|
if hasEmpty(typ):
|
||||||
localError(c.config, def.info, errCannotInferTypeOfTheLiteral % typ.kind.toHumanStr)
|
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)
|
localError(c.config, def.info, errProcHasNoConcreteType % def.renderTree)
|
||||||
when false:
|
when false:
|
||||||
# XXX This typing rule is neither documented nor complete enough to
|
# XXX This typing rule is neither documented nor complete enough to
|
||||||
|
|
|
||||||
35
tests/metatype/tcps.nim
Normal file
35
tests/metatype/tcps.nim
Normal file
|
|
@ -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")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue