Skip to content

template generics don't bind generic params on instantiation; causing wrong runtime values or crashes #13527

@timotheecour

Description

@timotheecour

template generics don't bind generic params on instantiation; causing wrong runtime values or crashes

Example

when true:
  template getTypStr[T](a: T): string = $T
  echo(getTypStr(1))   # 170141183460469231731687303715884105727; should be: int
  # echo(getTypStr(true))   # true ; should be: bool
  # echo(getTypStr(1.0)) # Error: unhandled exception: cannot extract number from invalid AST node 
  # echo(getTypStr(1u8))   # Error: internal error: expr(skType); unknown symbol

Current Output

170141183460469231731687303715884105727

Expected Output

int

other example: default

  template isDefault[T](a: T): bool = a == default(T) # BUG
  doAssert isDefault(0.0)

gives: Error: type mismatch: got <int> but expected one of: proc default(T: typedesc): T:type

workarounds are not good

use type(a) instead of T works in example above but won't work in more general cases eg:

  type Foo[M, P] = object
  template getTypStr[T1, T2](a: Foo[T1, T2]): untyped =
    # $T1 # doesn't work because of this issue
    $type(a).M # bad: you have to "know" that `T1` corresponds to `M`
  let a = Foo[int8, bool]()
  let b=getTypStr(a)
  echo (b, $type(b))

but then (despite being bad), that doesn't even work with special cases like seq[T], giving Error: undeclared field: 'T'

  template getTypStr[X](a: seq[X]): untyped =
    $type(a).T # doesnt' work for seq[T] even though it's declared like seq[T] !
  var a: seq[int]
  let b=getTypStr(a)
  echo (b, $type(b))

So you're forced to use the newly introduced typetraits.genericParams (see #13433), which seems overkill for these specific cases.

note

interestingly, static[T] generic params do seem to bind correctly, unlike non-static generic params eg:

  type Foo[N: static float, T: Ordinal] = object
  template getTypStr[N, T](a: Foo[N, T]): auto = N
  let a = Foo[3.1, bool]()
  doAssert getTypStr(a) == 3.1

root cause for:

Additional Information

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions