nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.43k stars 1.47k forks source link

Nested dirty template in generic proc #23889

Open Graveflo opened 1 month ago

Graveflo commented 1 month ago

Description

This might be mentioned elsewhere in another form, but this is a self contained example

this does not work:

template inner(i: int) {.dirty.} =
  let thing = 1

template outer() =
  proc p[T](x: T) =
    inner(5)
    echo thing

outer()
p(0)

but this does:

template inner(i: int) {.dirty.} =
  let thing = 1

template outer() =
  proc p(x: int) =
    inner(5)
    echo thing

outer()
p(0)

Nim Version

Nim Compiler Version 2.1.9 [Linux: amd64] Compiled at 2024-07-24 Copyright (c) 2006-2024 by Andreas Rumpf

git hash: c1f91c26a5136b2ad00f7da93b19c2da9b85dd16 active boot switches: -d:releas

Current Output

Error: undeclared identifier: 'thing'

Expected Output

1

Possible Solution

No response

Additional Information

No response

Graveflo commented 1 month ago

!nim c

template inner(i: static int) {.dirty.} =
  let thing = 1

template outer() =
  proc p[T](x: T) =
    inner(5)
    echo thing

outer()
p(0)
github-actions[bot] commented 1 month ago
:penguin: Linux bisect by @Graveflo (contributor)
devel :-1: FAIL

Output

``` Error: Command failed: nim c --run -d:nimDebug -d:nimDebugDlOpen -d:ssl -d:nimDisableCertificateValidation --forceBuild:on --colors:off --verbosity:0 --hints:off --lineTrace:off --nimcache:/home/runner/work/Nim/Nim --out:/home/runner/work/Nim/Nim/temp /home/runner/work/Nim/Nim/temp.nim /home/runner/work/Nim/Nim/temp.nim(7, 6) template/generic instantiation of `outer` from here /home/runner/work/Nim/Nim/temp.nim(6, 10) Error: undeclared identifier: 'thing' assertions.nim(34) raiseAssert Error: unhandled exception: errGenerated [AssertionDefect] ```

IR

Compiled filesize 0 (0 bytes) ```cpp ```

Stats

  • Started 2024-07-24T23:03:50
  • Finished 2024-07-24T23:03:50
  • Duration

AST

```nim nnkStmtList.newTree( nnkTemplateDef.newTree( newIdentNode("inner"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("i"), nnkCommand.newTree( newIdentNode("static"), newIdentNode("int") ), newEmptyNode() ) ), nnkPragma.newTree( newIdentNode("dirty") ), newEmptyNode(), nnkStmtList.newTree( nnkLetSection.newTree( nnkIdentDefs.newTree( newIdentNode("thing"), newEmptyNode(), newLit(1) ) ) ) ), nnkTemplateDef.newTree( newIdentNode("outer"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode() ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkProcDef.newTree( newIdentNode("p"), newEmptyNode(), nnkGenericParams.newTree( nnkIdentDefs.newTree( newIdentNode("T"), newEmptyNode(), newEmptyNode() ) ), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("x"), newIdentNode("T"), newEmptyNode() ) ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkCall.newTree( newIdentNode("inner"), newLit(5) ), nnkCommand.newTree( newIdentNode("echo"), newIdentNode("thing") ) ) ) ) ), nnkCall.newTree( newIdentNode("outer") ), nnkCall.newTree( newIdentNode("p"), newLit(0) ) ) ```
stable :-1: FAIL

Output

``` Error: Command failed: nim c --run -d:nimDebug -d:nimDebugDlOpen -d:ssl -d:nimDisableCertificateValidation --forceBuild:on --colors:off --verbosity:0 --hints:off --lineTrace:off --nimcache:/home/runner/work/Nim/Nim --out:/home/runner/work/Nim/Nim/temp /home/runner/work/Nim/Nim/temp.nim /home/runner/work/Nim/Nim/temp.nim(7, 6) template/generic instantiation of `outer` from here /home/runner/work/Nim/Nim/temp.nim(6, 10) Error: undeclared identifier: 'thing' assertions.nim(34) raiseAssert Error: unhandled exception: options.nim(682, 5) `false` errGenerated [AssertionDefect] ```

IR

Compiled filesize 0 (0 bytes) ```cpp ```

Stats

  • Started 2024-07-24T23:03:54
  • Finished 2024-07-24T23:03:54
  • Duration

AST

```nim nnkStmtList.newTree( nnkTemplateDef.newTree( newIdentNode("inner"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("i"), nnkCommand.newTree( newIdentNode("static"), newIdentNode("int") ), newEmptyNode() ) ), nnkPragma.newTree( newIdentNode("dirty") ), newEmptyNode(), nnkStmtList.newTree( nnkLetSection.newTree( nnkIdentDefs.newTree( newIdentNode("thing"), newEmptyNode(), newLit(1) ) ) ) ), nnkTemplateDef.newTree( newIdentNode("outer"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode() ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkProcDef.newTree( newIdentNode("p"), newEmptyNode(), nnkGenericParams.newTree( nnkIdentDefs.newTree( newIdentNode("T"), newEmptyNode(), newEmptyNode() ) ), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("x"), newIdentNode("T"), newEmptyNode() ) ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkCall.newTree( newIdentNode("inner"), newLit(5) ), nnkCommand.newTree( newIdentNode("echo"), newIdentNode("thing") ) ) ) ) ), nnkCall.newTree( newIdentNode("outer") ), nnkCall.newTree( newIdentNode("p"), newLit(0) ) ) ```
2.0.4 :-1: FAIL

Output

``` Error: Command failed: nim c --run -d:nimDebug -d:nimDebugDlOpen -d:ssl -d:nimDisableCertificateValidation --forceBuild:on --colors:off --verbosity:0 --hints:off --lineTrace:off --nimcache:/home/runner/work/Nim/Nim --out:/home/runner/work/Nim/Nim/temp /home/runner/work/Nim/Nim/temp.nim /home/runner/work/Nim/Nim/temp.nim(7, 6) template/generic instantiation of `outer` from here /home/runner/work/Nim/Nim/temp.nim(6, 10) Error: undeclared identifier: 'thing' assertions.nim(34) raiseAssert Error: unhandled exception: options.nim(681, 5) `false` errGenerated [AssertionDefect] ```

IR

Compiled filesize 0 (0 bytes) ```cpp ```

Stats

  • Started 2024-07-24T23:03:57
  • Finished 2024-07-24T23:03:57
  • Duration

AST

```nim nnkStmtList.newTree( nnkTemplateDef.newTree( newIdentNode("inner"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("i"), nnkCommand.newTree( newIdentNode("static"), newIdentNode("int") ), newEmptyNode() ) ), nnkPragma.newTree( newIdentNode("dirty") ), newEmptyNode(), nnkStmtList.newTree( nnkLetSection.newTree( nnkIdentDefs.newTree( newIdentNode("thing"), newEmptyNode(), newLit(1) ) ) ) ), nnkTemplateDef.newTree( newIdentNode("outer"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode() ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkProcDef.newTree( newIdentNode("p"), newEmptyNode(), nnkGenericParams.newTree( nnkIdentDefs.newTree( newIdentNode("T"), newEmptyNode(), newEmptyNode() ) ), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("x"), newIdentNode("T"), newEmptyNode() ) ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkCall.newTree( newIdentNode("inner"), newLit(5) ), nnkCommand.newTree( newIdentNode("echo"), newIdentNode("thing") ) ) ) ) ), nnkCall.newTree( newIdentNode("outer") ), nnkCall.newTree( newIdentNode("p"), newLit(0) ) ) ```
2.0.0 :-1: FAIL

Output

``` Error: Command failed: nim c --run -d:nimDebug -d:nimDebugDlOpen -d:ssl -d:nimDisableCertificateValidation --forceBuild:on --colors:off --verbosity:0 --hints:off --lineTrace:off --nimcache:/home/runner/work/Nim/Nim --out:/home/runner/work/Nim/Nim/temp /home/runner/work/Nim/Nim/temp.nim /home/runner/work/Nim/Nim/temp.nim(7, 6) template/generic instantiation of `outer` from here /home/runner/work/Nim/Nim/temp.nim(6, 10) Error: undeclared identifier: 'thing' assertions.nim(34) raiseAssert Error: unhandled exception: options.nim(664, 5) `false` errGenerated [AssertionDefect] ```

IR

Compiled filesize 0 (0 bytes) ```cpp ```

Stats

  • Started 2024-07-24T23:04:00
  • Finished 2024-07-24T23:04:00
  • Duration

AST

```nim nnkStmtList.newTree( nnkTemplateDef.newTree( newIdentNode("inner"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("i"), nnkCommand.newTree( newIdentNode("static"), newIdentNode("int") ), newEmptyNode() ) ), nnkPragma.newTree( newIdentNode("dirty") ), newEmptyNode(), nnkStmtList.newTree( nnkLetSection.newTree( nnkIdentDefs.newTree( newIdentNode("thing"), newEmptyNode(), newLit(1) ) ) ) ), nnkTemplateDef.newTree( newIdentNode("outer"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode() ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkProcDef.newTree( newIdentNode("p"), newEmptyNode(), nnkGenericParams.newTree( nnkIdentDefs.newTree( newIdentNode("T"), newEmptyNode(), newEmptyNode() ) ), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("x"), newIdentNode("T"), newEmptyNode() ) ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkCall.newTree( newIdentNode("inner"), newLit(5) ), nnkCommand.newTree( newIdentNode("echo"), newIdentNode("thing") ) ) ) ) ), nnkCall.newTree( newIdentNode("outer") ), nnkCall.newTree( newIdentNode("p"), newLit(0) ) ) ```
1.6.20 :-1: FAIL

Output

``` Error: Command failed: nim c --run -d:nimDebug -d:nimDebugDlOpen -d:ssl -d:nimDisableCertificateValidation --forceBuild:on --colors:off --verbosity:0 --hints:off --lineTrace:off --nimcache:/home/runner/work/Nim/Nim --out:/home/runner/work/Nim/Nim/temp /home/runner/work/Nim/Nim/temp.nim /home/runner/work/Nim/Nim/temp.nim(7, 6) template/generic instantiation of `outer` from here /home/runner/work/Nim/Nim/temp.nim(6, 10) Error: undeclared identifier: 'thing' fatal.nim(54) sysFatal Error: unhandled exception: options.nim(662, 14) `false` errGenerated [AssertionDefect] ```

IR

Compiled filesize 0 (0 bytes) ```cpp ```

Stats

  • Started 2024-07-24T23:04:03
  • Finished 2024-07-24T23:04:03
  • Duration

AST

```nim nnkStmtList.newTree( nnkTemplateDef.newTree( newIdentNode("inner"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("i"), nnkCommand.newTree( newIdentNode("static"), newIdentNode("int") ), newEmptyNode() ) ), nnkPragma.newTree( newIdentNode("dirty") ), newEmptyNode(), nnkStmtList.newTree( nnkLetSection.newTree( nnkIdentDefs.newTree( newIdentNode("thing"), newEmptyNode(), newLit(1) ) ) ) ), nnkTemplateDef.newTree( newIdentNode("outer"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode() ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkProcDef.newTree( newIdentNode("p"), newEmptyNode(), nnkGenericParams.newTree( nnkIdentDefs.newTree( newIdentNode("T"), newEmptyNode(), newEmptyNode() ) ), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("x"), newIdentNode("T"), newEmptyNode() ) ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkCall.newTree( newIdentNode("inner"), newLit(5) ), nnkCommand.newTree( newIdentNode("echo"), newIdentNode("thing") ) ) ) ) ), nnkCall.newTree( newIdentNode("outer") ), nnkCall.newTree( newIdentNode("p"), newLit(0) ) ) ```
1.4.8 :-1: FAIL

Output

``` Error: Command failed: nim c --run -d:nimDebug -d:nimDebugDlOpen -d:ssl -d:nimDisableCertificateValidation --forceBuild:on --colors:off --verbosity:0 --hints:off --lineTrace:off --nimcache:/home/runner/work/Nim/Nim --out:/home/runner/work/Nim/Nim/temp /home/runner/work/Nim/Nim/temp.nim /home/runner/work/Nim/Nim/temp.nim(7, 6) template/generic instantiation of `outer` from here /home/runner/work/Nim/Nim/temp.nim(6, 10) Error: undeclared identifier: 'thing' ```

IR

Compiled filesize 0 (0 bytes) ```cpp ```

Stats

  • Started 2024-07-24T23:04:07
  • Finished 2024-07-24T23:04:07
  • Duration

AST

```nim nnkStmtList.newTree( nnkTemplateDef.newTree( newIdentNode("inner"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("i"), nnkCommand.newTree( newIdentNode("static"), newIdentNode("int") ), newEmptyNode() ) ), nnkPragma.newTree( newIdentNode("dirty") ), newEmptyNode(), nnkStmtList.newTree( nnkLetSection.newTree( nnkIdentDefs.newTree( newIdentNode("thing"), newEmptyNode(), newLit(1) ) ) ) ), nnkTemplateDef.newTree( newIdentNode("outer"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode() ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkProcDef.newTree( newIdentNode("p"), newEmptyNode(), nnkGenericParams.newTree( nnkIdentDefs.newTree( newIdentNode("T"), newEmptyNode(), newEmptyNode() ) ), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("x"), newIdentNode("T"), newEmptyNode() ) ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkCall.newTree( newIdentNode("inner"), newLit(5) ), nnkCommand.newTree( newIdentNode("echo"), newIdentNode("thing") ) ) ) ) ), nnkCall.newTree( newIdentNode("outer") ), nnkCall.newTree( newIdentNode("p"), newLit(0) ) ) ```
1.2.18 :-1: FAIL

Output

``` Error: Command failed: nim c --run -d:nimDebug -d:nimDebugDlOpen -d:ssl -d:nimDisableCertificateValidation --forceBuild:on --colors:off --verbosity:0 --hints:off --lineTrace:off --nimcache:/home/runner/work/Nim/Nim --out:/home/runner/work/Nim/Nim/temp /home/runner/work/Nim/Nim/temp.nim /home/runner/work/Nim/Nim/temp.nim(7, 6) template/generic instantiation of `outer` from here /home/runner/work/Nim/Nim/temp.nim(6, 10) Error: undeclared identifier: 'thing' ```

IR

Compiled filesize 0 (0 bytes) ```cpp ```

Stats

  • Started 2024-07-24T23:04:09
  • Finished 2024-07-24T23:04:09
  • Duration

AST

```nim nnkStmtList.newTree( nnkTemplateDef.newTree( newIdentNode("inner"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("i"), nnkCommand.newTree( newIdentNode("static"), newIdentNode("int") ), newEmptyNode() ) ), nnkPragma.newTree( newIdentNode("dirty") ), newEmptyNode(), nnkStmtList.newTree( nnkLetSection.newTree( nnkIdentDefs.newTree( newIdentNode("thing"), newEmptyNode(), newLit(1) ) ) ) ), nnkTemplateDef.newTree( newIdentNode("outer"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode() ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkProcDef.newTree( newIdentNode("p"), newEmptyNode(), nnkGenericParams.newTree( nnkIdentDefs.newTree( newIdentNode("T"), newEmptyNode(), newEmptyNode() ) ), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("x"), newIdentNode("T"), newEmptyNode() ) ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkCall.newTree( newIdentNode("inner"), newLit(5) ), nnkCommand.newTree( newIdentNode("echo"), newIdentNode("thing") ) ) ) ) ), nnkCall.newTree( newIdentNode("outer") ), nnkCall.newTree( newIdentNode("p"), newLit(0) ) ) ```
1.0.10 :-1: FAIL

Output

``` Error: Command failed: nim c --run -d:nimDebug -d:nimDebugDlOpen -d:ssl -d:nimDisableCertificateValidation --forceBuild:on --colors:off --verbosity:0 --hints:off --lineTrace:off --nimcache:/home/runner/work/Nim/Nim --out:/home/runner/work/Nim/Nim/temp /home/runner/work/Nim/Nim/temp.nim /home/runner/work/Nim/Nim/temp.nim(7, 6) template/generic instantiation of `outer` from here /home/runner/work/Nim/Nim/temp.nim(6, 10) Error: undeclared identifier: 'thing' ```

IR

Compiled filesize 0 (0 bytes) ```cpp ```

Stats

  • Started 2024-07-24T23:04:11
  • Finished 2024-07-24T23:04:11
  • Duration

AST

```nim nnkStmtList.newTree( nnkTemplateDef.newTree( newIdentNode("inner"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("i"), nnkCommand.newTree( newIdentNode("static"), newIdentNode("int") ), newEmptyNode() ) ), nnkPragma.newTree( newIdentNode("dirty") ), newEmptyNode(), nnkStmtList.newTree( nnkLetSection.newTree( nnkIdentDefs.newTree( newIdentNode("thing"), newEmptyNode(), newLit(1) ) ) ) ), nnkTemplateDef.newTree( newIdentNode("outer"), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode() ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkProcDef.newTree( newIdentNode("p"), newEmptyNode(), nnkGenericParams.newTree( nnkIdentDefs.newTree( newIdentNode("T"), newEmptyNode(), newEmptyNode() ) ), nnkFormalParams.newTree( newEmptyNode(), nnkIdentDefs.newTree( newIdentNode("x"), newIdentNode("T"), newEmptyNode() ) ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkCall.newTree( newIdentNode("inner"), newLit(5) ), nnkCommand.newTree( newIdentNode("echo"), newIdentNode("thing") ) ) ) ) ), nnkCall.newTree( newIdentNode("outer") ), nnkCall.newTree( newIdentNode("p"), newLit(0) ) ) ```
Stats
  • GCC 11.4.0
  • Clang 14.0.0
  • NodeJS 20.4
  • Created 2024-07-24T23:03:24Z
  • Comments 1
  • Commands nim c --run -d:nimDebug -d:nimDebugDlOpen -d:ssl -d:nimDisableCertificateValidation --forceBuild:on --colors:off --verbosity:0 --hints:off --lineTrace:off --nimcache:/home/runner/work/Nim/Nim --out:/home/runner/work/Nim/Nim/temp /home/runner/work/Nim/Nim/temp.nim

:robot: Bug found in 24 minutes bisecting 8 commits at 0 commits per second

Graveflo commented 1 month ago

yea has nothing to do with statics actually

SirOlaf commented 1 month ago

The failure probably happens because typed templates are deferred for too long (or maybe it would be unsafe to expand), so it's not expanded by the time the generic body is checked. Works with untyped.

SirOlaf commented 1 month ago

Take a look around this location https://github.com/nim-lang/Nim/blob/c1f91c26a5136b2ad00f7da93b19c2da9b85dd16/compiler/semgnrc.nim#L284

And potentially here, maybe allUntyped should only be false when a param contains typed/generic parameters, currently it does a negative check against tyUntyped https://github.com/nim-lang/Nim/blob/c1f91c26a5136b2ad00f7da93b19c2da9b85dd16/compiler/semtempl.nim#L640

Graveflo commented 1 month ago

Take a look around this location

https://github.com/nim-lang/Nim/blob/c1f91c26a5136b2ad00f7da93b19c2da9b85dd16/compiler/semgnrc.nim#L284

Thanks for looking into this. As I said here https://github.com/nim-lang/Nim/pull/23890#issuecomment-2249361096 I'm not too sure if early expansion is going to to be the right call, but it's certainly something to try. Intuitively it makes sense, but I wonder why this expansion was conditional in the first place.

metagn commented 1 month ago

This is an issue with generics more than templates and there are other issues that cover the exact same problem which I will edit this comment to link later. (Edit: #21376, #21249, #22084, #15693) This is a simpler example:

template inner(i: int) {.dirty.} = # or just a normal template with {.inject.}
  let thing = 1 

proc p[T](x: T) =
  inner(5)
  echo thing

p(0)

The undeclared identifier error isn't actually fatal but as discovered in #23890 not erroring early can lead to some quirky behavior. The existing attitude to this issue has been "will be fixed with proper generic expression typechecking" in the comments of the other issues but maybe in the meantime we can find ways to signal to the compiler that there shouldn't be an error, these might prove useful even when we get generic typechecking. Or they might not be useful at all.

Some ways I can think of right off the bat:

  1. At the callsite:
proc p[T](x: T) =
  inner(5)
  {.inject: thing.} # generic proc is told that a symbol `thing` has been injected
  echo thing
  1. As information about the template, maybe this can be inferred but stuff like overloads might complicate it:
template inner(i: int) {.injects: [thing].} =
  let thing {.inject.} = 1 

proc p[T](x: T) =
  inner(5) # compiler knows `thing` was injected
  echo thing
Graveflo commented 1 month ago

@metagn

Thanks for explaining that. I've been messing with simpler examples too. I don't like this duct tape syntax because it'll just force a refactor later, or worse. It could end up being something that sticks around longer then it needs to. If there is a problem why not just go for the throat and look into this "proper generic expression type checking" problem?

If the solution to that problem is anything like what we currently have, there is still a problem with when to do the template expansion.

edit: posted a bad example. I'll try and come up with a better one

Graveflo commented 1 month ago

ah nvm maybe it is just the type checking. I'm assuming the operands to the template and macro are the problem according to SirOlaf's sfAllUntyped in s.flags and sc.safeLen <= 1 reference

metagn commented 1 month ago

I edited my comment to link the other issues but it seems like you found them already, yes this only triggers when the template has a typed argument or is overloaded, fully untyped single templates get evaluated early at a syntax level in generic procs.

If there is a problem why not just go for the throat and look into this "proper generic expression type checking" problem?

It's mentioned here: https://github.com/nim-lang/RFCs/issues/168, Araq can probably explain it better. It's also in the roadmap under Upcoming Versions -> Language. I would encourage asking Araq about it, it's really his plan and he might have ideas about how to speed it up.

It needs (for new functionality) a stronger type system, especially more fleshed out concepts, hence the RFC it was brought up in. The PRs that focus on sigmatch handling typeclasses like concrete types are also related. #22029 was a microcosm of it for type sections, it wasn't perfect and we're still dealing with the fallout.

Araq commented 1 month ago

It needs (for new functionality) a stronger type system, especially more fleshed out concepts, hence the RFC it was brought up in.

FWIW I had it working in a prototype and it didn't need concept at all.