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

wrong error: `is of type 'NimNode' and has to be used (or discarded)` in else branch #14665

Closed ghost closed 4 months ago

ghost commented 4 years ago

This code is mostly self-explanatory, I really don't understand why that error happens :)

Example

import macros

macro test*(): untyped =   
  let b = @[1, 2, 3, 4]

  result = nnkStmtList.newTree()
  var i = 0
  while i < b.len:
    if false:
      # this quote do is mandatory, removing it fixes the problem
      result.add quote do:
        let testtest = 5
    else:
      result.add quote do:
        let test = 6
      inc i
      # removing this continue fixes the problem too
      continue
    inc i

test()

Current Output

/home/dian/Projects/nim-snippets/tt.nim(14, 7) Error: expression '
add(result, getAst(`:anonymous`(newIdentNode("result"))))
inc i, 1
continue' is of type 'NimNode' and has to be used (or discarded); start of expression here: /home/dian/Projects/nim-snippets/tt.nim(9, 5)

Expected Output

No error

Additional information

Confirmed that it worked in 1.0.6 via the playground.

$ nim -v
Nim Compiler Version 1.3.5 [Linux: amd64]
Compiled at 2020-06-14
Copyright (c) 2006-2020 by Andreas Rumpf

git hash: d749c8cd87508871dc28b528f57d26b1004007b3
active boot switches: -d:release -d:danger
ghost commented 4 years ago
import macros

macro test*(): untyped =   
  for i, x in @[1, 2, 3]:
    if false:
      # this quote do is mandatory, removing it fixes the problem
      result.add quote do:
        discard
    else:
      echo "hi"
      # removing this continue fixes the problem too
      continue

test()

A bit shorter example

ghost commented 4 years ago

git bisect showed https://github.com/nim-lang/Nim/commit/c79df2fb6abb5663505de13c0ae5995d72ae71a8 as the first bad commit, and by the looks of it that commit might be related to the issue.

timotheecour commented 4 years ago
when defined case2c:
  import macros
  proc fn(): NimNode =
    var z: NimNode
    for i in 0..2:
      if false:
        add(result, z)
      else:
        discard
        # either break, return, continue would give error
        break

Error: expression ' discard break' is of type 'NimNode' and has to be used (or discarded); start of expression here:

note: seems specific to NimNode

no error here; this is strage.

when defined case3:
  import macros
  type Foo = object
  proc fn(): seq[Foo] {.compileTime.} =
    for i in 0..2:
      if false:
        add(result, Foo())
      else:
        discard
        break
shirleyquirk commented 2 years ago

indeed i think this is the same issue as #19150. if you discard result.add z the error disappears:

import macros
proc fn(): NimNode =
  var z: NimNode
  for i in 0..2:
    if false:
      discard add(result, z)
    else:
      discard
        # either break, return, continue would give error
      break
metagn commented 2 years ago

This is not specific to NimNode.

proc add2(a: var seq[int], b: int): int =
  a.add(b)
  b

proc fn(): seq[int] =
  for i in 0..2:
    if false:
      add2(result, i)
    else:
      discard
      break

Same error with or without discardable, saying expression ' discard break' is of type 'int' and has to be used (or discarded);, which is the wrong error. There might be another open issue for this (I know there is one for try/finally).