mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 20:17:42 +00:00
allow generic compileTime proc folding (#22022)
fixes #10753, fixes #22021, refs #19365 (was fixed by #22029, but more faithful test added) For whatever reason `compileTime` proc calls did not fold if the proc was generic ([since this folding was introduced](c25ffbf262 (diff-539da3a63df08fa987f1b0c67d26cdc690753843d110b6bf0805a685eeaffd40))). I'm guessing the intention was for *unresolved* generic procs to not fold, which is now the logic. Non-magic `compileTime` procs also now don't fold at compile time in `typeof` contexts to avoid possible runtime errors (only the important) and prevent double/needless evaluation. (cherry picked from commitf7c11a8978)
This commit is contained in:
@@ -170,6 +170,7 @@ type
|
||||
inUncheckedAssignSection*: int
|
||||
importModuleLookup*: Table[int, seq[int]] # (module.ident.id, [module.id])
|
||||
skipTypes*: seq[PNode] # used to skip types between passes in type section. So far only used for inheritance, sets and generic bodies.
|
||||
inTypeofContext*: int
|
||||
TBorrowState* = enum
|
||||
bsNone, bsReturnNotMatch, bsNoDistinct, bsGeneric, bsNotSupported, bsMatch
|
||||
|
||||
|
||||
@@ -971,7 +971,8 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||
|
||||
if callee.magic notin ctfeWhitelist: return
|
||||
|
||||
if callee.kind notin {skProc, skFunc, skConverter, skConst} or callee.isGenericRoutine:
|
||||
if callee.kind notin {skProc, skFunc, skConverter, skConst} or
|
||||
callee.isGenericRoutineStrict:
|
||||
return
|
||||
|
||||
if n.typ != nil and typeAllowed(n.typ, skConst, c) != nil: return
|
||||
@@ -1117,7 +1118,8 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags; expectedTy
|
||||
not (result.typ.kind == tySequence and result.typ[0].kind == tyEmpty):
|
||||
liftTypeBoundOps(c, result.typ, n.info)
|
||||
#result = patchResolvedTypeBoundOp(c, result)
|
||||
if c.matchedConcept == nil:
|
||||
if c.matchedConcept == nil and (c.inTypeofContext == 0 or callee.magic != mNone):
|
||||
# don't fold calls in concepts and typeof
|
||||
result = evalAtCompileTime(c, result)
|
||||
|
||||
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
|
||||
@@ -47,7 +47,9 @@ proc semTypeOf(c: PContext; n: PNode): PNode =
|
||||
else:
|
||||
m = mode.intVal
|
||||
result = newNodeI(nkTypeOfExpr, n.info)
|
||||
inc c.inTypeofContext
|
||||
let typExpr = semExprWithType(c, n[1], if m == 1: {efInTypeof} else: {})
|
||||
dec c.inTypeofContext
|
||||
result.add typExpr
|
||||
result.typ = makeTypeDesc(c, typExpr.typ)
|
||||
|
||||
|
||||
@@ -1806,7 +1806,9 @@ proc semStaticType(c: PContext, childNode: PNode, prev: PType): PType =
|
||||
|
||||
proc semTypeOf(c: PContext; n: PNode; prev: PType): PType =
|
||||
openScope(c)
|
||||
inc c.inTypeofContext
|
||||
let t = semExprWithType(c, n, {efInTypeof})
|
||||
dec c.inTypeofContext
|
||||
closeScope(c)
|
||||
fixupTypeOf(c, prev, t)
|
||||
result = t.typ
|
||||
@@ -1820,7 +1822,9 @@ proc semTypeOf2(c: PContext; n: PNode; prev: PType): PType =
|
||||
localError(c.config, n.info, "typeof: cannot evaluate 'mode' parameter at compile-time")
|
||||
else:
|
||||
m = mode.intVal
|
||||
inc c.inTypeofContext
|
||||
let t = semExprWithType(c, n[1], if m == 1: {efInTypeof} else: {})
|
||||
dec c.inTypeofContext
|
||||
closeScope(c)
|
||||
fixupTypeOf(c, prev, t)
|
||||
result = t.typ
|
||||
|
||||
29
tests/vm/tgenericcompiletimeproc.nim
Normal file
29
tests/vm/tgenericcompiletimeproc.nim
Normal file
@@ -0,0 +1,29 @@
|
||||
block: # issue #10753
|
||||
proc foo(x: int): int {.compileTime.} = x
|
||||
const a = foo(123)
|
||||
doAssert foo(123) == a
|
||||
|
||||
proc bar[T](x: T): T {.compileTime.} = x
|
||||
const b = bar(123)
|
||||
doAssert bar(123) == b
|
||||
const c = bar("abc")
|
||||
doAssert bar("abc") == c
|
||||
|
||||
block: # issue #22021
|
||||
proc foo(x: static int): int {.compileTime.} = x + 1
|
||||
doAssert foo(123) == 124
|
||||
|
||||
block: # issue #19365
|
||||
proc f[T](x: static T): T {.compileTime.} = x + x
|
||||
doAssert f(123) == 246
|
||||
doAssert f(1.0) == 2.0
|
||||
|
||||
block:
|
||||
# don't fold compile time procs in typeof
|
||||
proc fail[T](x: T): T {.compileTime.} =
|
||||
doAssert false
|
||||
x
|
||||
doAssert typeof(fail(123)) is typeof(123)
|
||||
proc p(x: int): int = x
|
||||
|
||||
type Foo = typeof(p(fail(123)))
|
||||
Reference in New Issue
Block a user