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.44k stars 1.47k forks source link

[BUG] `fields` on tuple of tuples returns a non-tuple depending on whether it's var or const #7590

Closed timotheecour closed 1 year ago

timotheecour commented 6 years ago

/cc @Araq

this is a reduction from a function that computes a join of tuples, or other processing on tuples; it's not a contrived example/

import macros
import typetraits

proc doInit[T]():auto=
  var a: T
  return a

proc fun2[T](tup1:T)=
  const tup0=doInit[T]()

  # var tup=tup0 #ok
  const tup=tup0 #causes bug

  assert tup is tuple
  assert tup[0] is tuple
  for ai in tup.fields:
    assert ai is tuple, "BUG2"

# const c=(foo:(bar1: 0.0))
const c=(foo:(bar1:"foo1"))
fun2(c)
# D20180412T184337
import macros
import typetraits

proc doInit[T]():auto=
  var a: T
  return a

proc fun[T](tup1:T)=
  const tup2=doInit[T]()
  echo "tup1:", tup1
  echo "tup2:", tup2

  # var tup=tup2 # works
  const tup=tup2 # fails

  assert tup[1] is tuple

  for ai in tup.fields:
    echo "ai:" & ai.type.name & " tuple?" & $(ai is tuple)
    assert ai is tuple, " BUG!"
  echo "----"

let a=(age:1, score: 2.5)

let b0=()
let b1=(bar1:"foo1", bar2:"foo2")
let b2=(bar1:"foo1")

fun((a,b0))
fun((a,b1))
fun((a,b2))

let c=(a,b2)
echo c[0] is tuple
echo c[1] is tuple
tup1:(Field0: (age: 1, score: 2.5), Field1: ())
tup2:(Field0: (age: 0, score: 0.0), Field1: ())
ai:(int, float64) tuple?true
ai:tuple[] tuple?true
----
tup1:(Field0: (age: 1, score: 2.5), Field1: (bar1: "foo1", bar2: "foo2"))
tup2:(Field0: (age: 0, score: 0.0), Field1: (bar1: "", bar2: ""))
ai:(int, float64) tuple?true
ai:(string, string) tuple?true
----
tup1:(Field0: (age: 1, score: 2.5), Field1: (bar1: "foo1"))
tup2:(Field0: (age: 0, score: 0.0), Field1: (bar1: ""))
ai:(int, float64) tuple?true
ai:string tuple?false
/Users/timothee/git_clone/nim/timn/bugs/t18_tuple_for_fields.nim(33) t18_tuple_for_fields
/Users/timothee/git_clone/nim/timn/bugs/t18_tuple_for_fields.nim(21) fun
/Users/timothee/.choosenim/toolchains/nim-#devel/lib/system.nim(3785) failedAssertImpl
/Users/timothee/.choosenim/toolchains/nim-#devel/lib/system.nim(3778) raiseAssert
/Users/timothee/.choosenim/toolchains/nim-#devel/lib/system.nim(2840) sysFatal
Error: unhandled exception: false  BUG! [AssertionError]
Error: execution of an external program failed: './app '
timotheecour commented 6 years ago

NOTE: implementing https://forum.nim-lang.org/t/3750/1#23343 ([RFC] for index, name in Tup.fieldsIndexed to get index at compile time of a tuple type) would allow circumventing this bug

timotheecour commented 6 years ago

if accepted, https://github.com/nim-lang/Nim/pull/7597 would allow a simple workaround