Skip to content
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

allow generic compileTime proc folding #22022

Merged
merged 7 commits into from
Aug 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/semdata.nim
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,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

Expand Down
6 changes: 4 additions & 2 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,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
Expand Down Expand Up @@ -1118,7 +1119,8 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags; expectedTy
not (result.typ.kind == tySequence and result.elementType.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 =
Expand Down
2 changes: 2 additions & 0 deletions compiler/semmagic.nim
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,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: {})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you can see here we already have efInTypeof. Can this be used instead of c.inTypeofContext?

Copy link
Collaborator Author

@metagn metagn Aug 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I tried first, it doesn't always propagate, even in simple cases like typeof(foo(compileTimeProc())) where it's nested in another call.

dec c.inTypeofContext
result.add typExpr
result.typ = makeTypeDesc(c, typExpr.typ)

Expand Down
4 changes: 4 additions & 0 deletions compiler/semtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1836,7 +1836,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
Expand All @@ -1850,7 +1852,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
Expand Down
29 changes: 29 additions & 0 deletions tests/vm/tgenericcompiletimeproc.nim
Original file line number Diff line number Diff line change
@@ -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)))