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

template parameter type checking broken #11794

Open
timotheecour opened this issue Jul 20, 2019 · 2 comments
Open

template parameter type checking broken #11794

timotheecour opened this issue Jul 20, 2019 · 2 comments

Comments

@timotheecour
Copy link
Member

timotheecour commented Jul 20, 2019

type checking for templates doesn't work the same as for procs, causing bugs

Example0

can anyone spot the bug in swapEndian ?

template swapEndian*(outp, inp: var uint64) =
    ## copies `inp` to `outp` swapping bytes
    var i = cast[cstring](addr inp)
    var o = cast[cstring](addr outp)
    o[0] = i[7]
    o[1] = i[6]
    o[2] = i[5]
    o[3] = i[4]
    o[4] = i[3]
    o[5] = i[2]
    o[6] = i[1]
    o[7] = i[0]

despite looking type safe, it isn't so:

  type Foo = object
    output, input: uint16
    z: uint16
  var x = Foo(input: 100, z: 1000)
  echo x # (output: 0, input: 100, z: 1000)
  swapEndian(x.output, x.input)
  echo x # (output: 0, input: 0, z: 771) # z was modified under the hood! the compiler didn't complain about implicit conversion from var uint16 to var uint64

If we used a proc instead of a template, the compiler would (correctly) complain:
Error: for a 'var' type a variable needs to be passed; but 'uint64(x.output)' is immutable

Example1

  template runTest[T](a, b: T) =
    static:
      const s = $T
      echo ($T, $type(a), $type(b))
  proc main()=
    var a: int
    var b: int32
    static: echo "trying (int,int32):"
    runTest(a, b)

    var c: float
    static: echo "trying float:"
    runTest(c, c)
  main()

Current Output

trying (int,int32):
("9223372036854775807", "int", "int32")
trying float:
/Users/timothee/git_clone/nim/Nim_devel/compiler/lineinfos.nim(229) raiseRecoverableError
Error: unhandled exception: cannot extract number from invalid AST node [ERecoverableError]

there's a few bugs here:

  • $T shows as 9223372036854775807 in 1st example (int)
  • $T crashes compiler in 2nd example (float)
  • the type of template parameters is only used during signature matching (ie, the compiler just checks that types can match modulo implicit conversions) but somehow is lost when template is called:
    in example above, a, b: T should have same type T but their types are actually int and int32

Example2

in this example the signature matching itself should fail. Contrary to previous example, the bug happens during signature matching, which should fail (ie, not implicit conversion possible bc of var), but doesn't

  # proc runTest[T](a: var T, b: var T) = # this would (correctly) give Error: ... 'float64(b)' is immutable
  template runTest[T](a: var T, b: var T) =
    echo (cast[int](addr a), cast[int](addr b))
    b = a
  proc main()=
    var a: float64 = 3.14
    var b: float32 = 1.42
    runTest(a, b)
    echo (a,b)
  main()

output:

# should give CT error instead of compiling/running
(140732816759008, 140732816759004)
(3.14, 3.140000104904175)  # doesn't actually matter, just that it shouldn't compile

[EDIT]

related issues

Additional Information

  • Your Nim version (output of nim -v).
    latest devel f50e450

  • Was it working in the previous Nim releases?
    no

@timotheecour timotheecour changed the title template type checking broken template parameter type checking broken Jul 20, 2019
@Araq
Copy link
Member

Araq commented Jul 21, 2019

The problem here is that var T parameter passing makes no sense for template, template can always mutate due to its inlining semantics. IMO var T for parameters in templates should be deprecated.

@zah
Copy link
Member

zah commented Jul 21, 2019

You can still use var as a discriminator in overloading. The template can do one thing if the location is mutable and another if it isn't

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants