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

Regression from 1.6/2.0.4/devel to 2.0.5: Error: toException(self.eResultPrivate) can raise an unlisted exception: ref LPError #23519

Closed
tersec opened this issue Apr 18, 2024 · 15 comments

Comments

@tersec
Copy link
Contributor

tersec commented Apr 18, 2024

Description

type
  ResultError[E] = object of ValueError
    error: E

  Result[T, E] = object
    case oResultPrivate: bool
    of false:
      eResultPrivate: E
    of true:
      vResultPrivate: T

  LPError = object of CatchableError

func raiseResultError[T, E](self: Result[T, E]) {.noreturn, noinline.} =
  # noinline because raising should take as little space as possible at call
  # site
  mixin toException

  when E is ref Exception:
    if self.eResultPrivate.isNil: # for example Result.default()!
      raise (ref ResultError[void])(msg: "Trying to access value with err (nil)")
    raise self.eResultPrivate
  elif E is void:
    raise (ref ResultError[void])(msg: "Trying to access value with err")
  elif compiles(toException(self.eResultPrivate)):
    raise toException(self.eResultPrivate)
  elif compiles($self.eResultPrivate):
    raise (ref ResultError[E])(error: self.eResultPrivate, msg: $self.eResultPrivate)
  else:
    raise (ref ResultError[E])(
      msg: "Trying to access value with err", error: self.eResultPrivate
    )

template err[T; E: not void](R: type Result[T, E], x: untyped): R =
  R(oResultPrivate: false, eResultPrivate: x)

func tryValue[T, E](self: Result[T, E]): T {.inline.} =
  mixin raiseResultError
  case self.oResultPrivate
  of false:
    self.raiseResultError()
  of true:
    when T isnot void:
      self.vResultPrivate

{.push raises: [].}
{.push public.}

template tryGet[T: not void, E](self: Result[T, E]): T =
  self.tryValue()

func toException(e: string): ref LPError =
  (ref LPError)(msg: e)

proc `&`*() {.raises: [LPError].} =
  let foo: Result[int, string] = Result[int, string].err("")
  discard foo.tryGet()

1.6 builds, devel builds.

Nim Version

Builds:

Nim Compiler Version 1.6.21 [Linux: amd64]
Compiled at 2024-04-18
Copyright (c) 2006-2023 by Andreas Rumpf

git hash: 8ebb4dc30af3a5d3dd14bc651698d02b715befed
active boot switches: -d:release
Nim Compiler Version 2.1.1 [Linux: amd64]
Compiled at 2024-04-18
Copyright (c) 2006-2024 by Andreas Rumpf

git hash: d6823f477672e61017e9c1ce3b5221a2b80fc1b7
active boot switches: -d:release

... also builds:

Nim Compiler Version 2.0.4 [Linux: amd64]
Compiled at 2024-04-18
Copyright (c) 2006-2023 by Andreas Rumpf

git hash: b47747d31844c6bd9af4322efe55e24fefea544c
active boot switches: -d:release

Does not build:

Nim Compiler Version 2.0.5 [Linux: amd64]
Compiled at 2024-04-18
Copyright (c) 2006-2023 by Andreas Rumpf

git hash: fd64402e478432e5566d6bb2d5ced30bd82e7dd1
active boot switches: -d:release

Current Output

s.nim(57, 14) template/generic instantiation of `tryGet` from here
s.nim(50, 7) template/generic instantiation of `tryValue` from here
s.nim(41, 9) template/generic instantiation of `raiseResultError` from here
s.nim(14, 1) template/generic instantiation from here
s.nim(26, 5) Error: toException(self.eResultPrivate) can raise an unlisted exception: ref LPError

Expected Output

No response

Possible Solution

No response

Additional Information

No response

@juancarlospaco
Copy link
Collaborator

@tersec Whats pragma public ?, repro code is wrong. 🤔

@tersec
Copy link
Contributor Author

tersec commented Apr 18, 2024

Honestly, no idea.

Apparently whatever it is, it worked before and after 2.0.5.

@tersec
Copy link
Contributor Author

tersec commented Apr 18, 2024

Alternative framing: either this is valid code, and 2.0.5 has a bug, or it's not, and 1.6/2.0.4/2.1.1 have an invalid code acceptance bug. But at least one of these statements is true.

Copy link
Contributor

🐧 Linux bisect by @juancarlospaco (collaborator)
devel 👍 OK

Output


IR

Compiled filesize 92.82 Kb (95,048 bytes)
#define NIM_INTBITS 64
#include "nimbase.h"
N_LIB_PRIVATE N_NIMCALL(void, nimTestErrorFlag)(void);
N_LIB_PRIVATE N_NIMCALL(void, atmdotdotatsdotdotatsdotdotatsdotchoosenimatstoolchainsatsnimminusathdevelatslibatssystemdotnim_Init000)(void);
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void);
N_LIB_PRIVATE void PreMainInner(void) {
}
N_LIB_PRIVATE int cmdCount;
N_LIB_PRIVATE char** cmdLine;
N_LIB_PRIVATE char** gEnv;
N_LIB_PRIVATE void PreMain(void) {
#if 0
 void (*volatile inner)(void);
 inner = PreMainInner;
 atmdotdotatsdotdotatsdotdotatsdotchoosenimatstoolchainsatsnimminusathdevelatslibatssystemdotnim_Init000();
 (*inner)();
#else
 atmdotdotatsdotdotatsdotdotatsdotchoosenimatstoolchainsatsnimminusathdevelatslibatssystemdotnim_Init000();
 PreMainInner();
#endif
}
N_LIB_PRIVATE N_CDECL(void, NimMainInner)(void) {
 NimMainModule();
}
N_CDECL(void, NimMain)(void) {
#if 0
 void (*volatile inner)(void);
 PreMain();
 inner = NimMainInner;
 (*inner)();
#else
 PreMain();
 NimMainInner();
#endif
}
int main(int argc, char** args, char** env) {
 cmdLine = args;
 cmdCount = argc;
 gEnv = env;
 NimMain();
 return nim_program_result;
}
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
 nimTestErrorFlag();
}
}

Stats

  • Started 2024-04-18T19:30:31
  • Finished 2024-04-18T19:30:31
  • Duration
stable 👍 OK

Output


IR

Compiled filesize 90.64 Kb (92,816 bytes)
#define NIM_INTBITS 64
#include "nimbase.h"
N_LIB_PRIVATE N_NIMCALL(void, nimTestErrorFlag)(void);
N_LIB_PRIVATE N_NIMCALL(void, atmdotdotatsdotdotatsdotdotatsdotchoosenimatstoolchainsatsnimminus2dot0dot4atslibatssystemdotnim_Init000)(void);
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void);
N_LIB_PRIVATE void PreMainInner(void) {
}
N_LIB_PRIVATE int cmdCount;
N_LIB_PRIVATE char** cmdLine;
N_LIB_PRIVATE char** gEnv;
N_LIB_PRIVATE void PreMain(void) {
#if 0
 void (*volatile inner)(void);
 inner = PreMainInner;
 atmdotdotatsdotdotatsdotdotatsdotchoosenimatstoolchainsatsnimminus2dot0dot4atslibatssystemdotnim_Init000();
 (*inner)();
#else
 atmdotdotatsdotdotatsdotdotatsdotchoosenimatstoolchainsatsnimminus2dot0dot4atslibatssystemdotnim_Init000();
 PreMainInner();
#endif
}
N_LIB_PRIVATE N_CDECL(void, NimMainInner)(void) {
 NimMainModule();
}
N_CDECL(void, NimMain)(void) {
#if 0
 void (*volatile inner)(void);
 PreMain();
 inner = NimMainInner;
 (*inner)();
#else
 PreMain();
 NimMainInner();
#endif
}
int main(int argc, char** args, char** env) {
 cmdLine = args;
 cmdCount = argc;
 gEnv = env;
 NimMain();
 return nim_program_result;
}
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
 nimTestErrorFlag();
}
}

Stats

  • Started 2024-04-18T19:30:31
  • Finished 2024-04-18T19:30:32
  • Duration
2.0.2 👍 OK

Output


IR

Compiled filesize 90.65 Kb (92,824 bytes)
#define NIM_INTBITS 64
#include "nimbase.h"
N_LIB_PRIVATE N_NIMCALL(void, nimTestErrorFlag)(void);
N_LIB_PRIVATE N_NIMCALL(void, atmdotdotatsdotdotatsdotdotatsdotchoosenimatstoolchainsatsnimminus2dot0dot2atslibatssystemdotnim_Init000)(void);
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void);
N_LIB_PRIVATE void PreMainInner(void) {
}
N_LIB_PRIVATE int cmdCount;
N_LIB_PRIVATE char** cmdLine;
N_LIB_PRIVATE char** gEnv;
N_LIB_PRIVATE void PreMain(void) {
#if 0
 void (*volatile inner)(void);
 inner = PreMainInner;
 atmdotdotatsdotdotatsdotdotatsdotchoosenimatstoolchainsatsnimminus2dot0dot2atslibatssystemdotnim_Init000();
 (*inner)();
#else
 atmdotdotatsdotdotatsdotdotatsdotchoosenimatstoolchainsatsnimminus2dot0dot2atslibatssystemdotnim_Init000();
 PreMainInner();
#endif
}
N_LIB_PRIVATE N_CDECL(void, NimMainInner)(void) {
 NimMainModule();
}
N_CDECL(void, NimMain)(void) {
#if 0
 void (*volatile inner)(void);
 PreMain();
 inner = NimMainInner;
 (*inner)();
#else
 PreMain();
 NimMainInner();
#endif
}
int main(int argc, char** args, char** env) {
 cmdLine = args;
 cmdCount = argc;
 gEnv = env;
 NimMain();
 return nim_program_result;
}
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
 nimTestErrorFlag();
}
}

Stats

  • Started 2024-04-18T19:30:34
  • Finished 2024-04-18T19:30:35
  • Duration
1.6.14 👍 OK

Output


IR

Compiled filesize 95.29 Kb (97,576 bytes)
#define NIM_INTBITS 64
#include "nimbase.h"
#define nimfr_(x, y)
#define nimln_(x, y)
static N_INLINE(void, initStackBottomWith)(void* locals);
N_LIB_PRIVATE N_NOINLINE(void, nimGC_setStackBottom)(void* theStackBottom);
N_LIB_PRIVATE N_NIMCALL(void, atmdotdotatsdotdotatsdotdotatsdotchoosenimatstoolchainsatsnimminus1dot6dot14atslibatssystemdotnim_DatInit000)(void);
N_LIB_PRIVATE N_NIMCALL(void, atmdotdotatsdotdotatsdotdotatsdotchoosenimatstoolchainsatsnimminus1dot6dot14atslibatssystemdotnim_Init000)(void);
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void);
static N_INLINE(void, initStackBottomWith)(void* locals) {
 nimGC_setStackBottom(locals);
}
N_LIB_PRIVATE void PreMainInner(void) {
}
 N_LIB_PRIVATE int cmdCount;
 N_LIB_PRIVATE char** cmdLine;
 N_LIB_PRIVATE char** gEnv;
N_LIB_PRIVATE void PreMain(void) {
 void (*volatile inner)(void);
 inner = PreMainInner;
 atmdotdotatsdotdotatsdotdotatsdotchoosenimatstoolchainsatsnimminus1dot6dot14atslibatssystemdotnim_DatInit000();
 initStackBottomWith((void *)&inner);
 atmdotdotatsdotdotatsdotdotatsdotchoosenimatstoolchainsatsnimminus1dot6dot14atslibatssystemdotnim_Init000();
 (*inner)();
}
N_LIB_PRIVATE N_CDECL(void, NimMainInner)(void) {
 NimMainModule();
}
N_CDECL(void, NimMain)(void) {
 void (*volatile inner)(void);
 PreMain();
 inner = NimMainInner;
 initStackBottomWith((void *)&inner);
 (*inner)();
}
int main(int argc, char** args, char** env) {
 cmdLine = args;
 cmdCount = argc;
 gEnv = env;
 NimMain();
 return nim_program_result;
}
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
}
}

Stats

  • Started 2024-04-18T19:30:37
  • Finished 2024-04-18T19:30:38
  • Duration
1.4.8 👍 OK

Output


IR

Compiled filesize 91.16 Kb (93,344 bytes)
#define NIM_INTBITS 64
#include "nimbase.h"
#define nimfr_(x, y)
#define nimln_(x, y)
static N_INLINE(void, initStackBottomWith)(void* locals);
N_LIB_PRIVATE N_NOINLINE(void, nimGC_setStackBottom)(void* theStackBottom);
N_LIB_PRIVATE N_NIMCALL(void, systemDatInit000)(void);
N_LIB_PRIVATE N_NIMCALL(void, systemInit000)(void);
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void);
static N_INLINE(void, initStackBottomWith)(void* locals) {
 nimGC_setStackBottom(locals);
}
N_LIB_PRIVATE void PreMainInner(void) {
}
N_LIB_PRIVATE int cmdCount;
N_LIB_PRIVATE char** cmdLine;
N_LIB_PRIVATE char** gEnv;
N_LIB_PRIVATE void PreMain(void) {
 void (*volatile inner)(void);
 inner = PreMainInner;
 systemDatInit000();
 initStackBottomWith((void *)&inner);
 systemInit000();
 (*inner)();
}
N_LIB_PRIVATE N_CDECL(void, NimMainInner)(void) {
 NimMainModule();
}
N_CDECL(void, NimMain)(void) {
 void (*volatile inner)(void);
 PreMain();
 inner = NimMainInner;
 initStackBottomWith((void *)&inner);
 (*inner)();
}
int main(int argc, char** args, char** env) {
 cmdLine = args;
 cmdCount = argc;
 gEnv = env;
 NimMain();
 return nim_program_result;
}
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
}
}

Stats

  • Started 2024-04-18T19:30:40
  • Finished 2024-04-18T19:30:40
  • Duration
1.2.18 👍 OK

Output


IR

Compiled filesize 86.88 Kb (88,968 bytes)
#define NIM_INTBITS 64
#include "nimbase.h"
#define nimfr_(x, y)
#define nimln_(x, y)
static N_INLINE(void, initStackBottomWith)(void* locals);
N_LIB_PRIVATE N_NOINLINE(void, nimGC_setStackBottom)(void* theStackBottom);
N_LIB_PRIVATE N_NIMCALL(void, systemDatInit000)(void);
N_LIB_PRIVATE N_NIMCALL(void, systemInit000)(void);
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void);
static N_INLINE(void, initStackBottomWith)(void* locals) {
 nimGC_setStackBottom(locals);
}
N_LIB_PRIVATE void PreMainInner(void) {
}
N_LIB_PRIVATE int cmdCount;
N_LIB_PRIVATE char** cmdLine;
N_LIB_PRIVATE char** gEnv;
N_LIB_PRIVATE void PreMain(void) {
 void (*volatile inner)(void);
 inner = PreMainInner;
 systemDatInit000();
 initStackBottomWith((void *)&inner);
 systemInit000();
 (*inner)();
}
N_LIB_PRIVATE N_CDECL(void, NimMainInner)(void) {
 NimMainModule();
}
N_CDECL(void, NimMain)(void) {
 void (*volatile inner)(void);
 PreMain();
 inner = NimMainInner;
 initStackBottomWith((void *)&inner);
 (*inner)();
}
int main(int argc, char** args, char** env) {
 cmdLine = args;
 cmdCount = argc;
 gEnv = env;
 NimMain();
 return nim_program_result;
}
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
}
}

Stats

  • Started 2024-04-18T19:30:42
  • Finished 2024-04-18T19:30:43
  • Duration
1.0.10 👎 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(41, 1) template/generic instantiation from here
/home/runner/work/Nim/Nim/temp.nim(38, 8) Error: invalid pragma: public

IR

Compiled filesize 86.88 Kb (88,968 bytes)
#define NIM_INTBITS 64
#include "nimbase.h"
#define nimfr_(x, y)
#define nimln_(x, y)
static N_INLINE(void, initStackBottomWith)(void* locals);
N_LIB_PRIVATE N_NOINLINE(void, nimGC_setStackBottom)(void* theStackBottom);
N_LIB_PRIVATE N_NIMCALL(void, systemDatInit000)(void);
N_LIB_PRIVATE N_NIMCALL(void, systemInit000)(void);
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void);
static N_INLINE(void, initStackBottomWith)(void* locals) {
 nimGC_setStackBottom(locals);
}
N_LIB_PRIVATE void PreMainInner(void) {
}
N_LIB_PRIVATE int cmdCount;
N_LIB_PRIVATE char** cmdLine;
N_LIB_PRIVATE char** gEnv;
N_LIB_PRIVATE void PreMain(void) {
 void (*volatile inner)(void);
 inner = PreMainInner;
 systemDatInit000();
 initStackBottomWith((void *)&inner);
 systemInit000();
 (*inner)();
}
N_LIB_PRIVATE N_CDECL(void, NimMainInner)(void) {
 NimMainModule();
}
N_CDECL(void, NimMain)(void) {
 void (*volatile inner)(void);
 PreMain();
 inner = NimMainInner;
 initStackBottomWith((void *)&inner);
 (*inner)();
}
int main(int argc, char** args, char** env) {
 cmdLine = args;
 cmdCount = argc;
 gEnv = env;
 NimMain();
 return nim_program_result;
}
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
}
}

Stats

  • Started 2024-04-18T19:30:45
  • Finished 2024-04-18T19:30:45
  • Duration

AST

nnkStmtList.newTree(
  nnkTypeSection.newTree(
    nnkTypeDef.newTree(
      newIdentNode("ResultError"),
      nnkGenericParams.newTree(
        nnkIdentDefs.newTree(
          newIdentNode("E"),
          newEmptyNode(),
          newEmptyNode()
        )
      ),
      nnkObjectTy.newTree(
        newEmptyNode(),
        nnkOfInherit.newTree(
          newIdentNode("ValueError")
        ),
        nnkRecList.newTree(
          nnkIdentDefs.newTree(
            newIdentNode("error"),
            newIdentNode("E"),
            newEmptyNode()
          )
        )
      )
    ),
    nnkTypeDef.newTree(
      newIdentNode("Result"),
      nnkGenericParams.newTree(
        nnkIdentDefs.newTree(
          newIdentNode("T"),
          newIdentNode("E"),
          newEmptyNode(),
          newEmptyNode()
        )
      ),
      nnkObjectTy.newTree(
        newEmptyNode(),
        newEmptyNode(),
        nnkRecList.newTree(
          nnkRecCase.newTree(
            nnkIdentDefs.newTree(
              newIdentNode("oResultPrivate"),
              newIdentNode("bool"),
              newEmptyNode()
            ),
            nnkOfBranch.newTree(
              newIdentNode("false"),
              nnkRecList.newTree(
                nnkIdentDefs.newTree(
                  newIdentNode("eResultPrivate"),
                  newIdentNode("E"),
                  newEmptyNode()
                )
              )
            ),
            nnkOfBranch.newTree(
              newIdentNode("true"),
              nnkRecList.newTree(
                nnkIdentDefs.newTree(
                  newIdentNode("vResultPrivate"),
                  newIdentNode("T"),
                  newEmptyNode()
                )
              )
            )
          )
        )
      )
    ),
    nnkTypeDef.newTree(
      newIdentNode("LPError"),
      newEmptyNode(),
      nnkObjectTy.newTree(
        newEmptyNode(),
        nnkOfInherit.newTree(
          newIdentNode("CatchableError")
        ),
        newEmptyNode()
      )
    )
  ),
  nnkFuncDef.newTree(
    newIdentNode("raiseResultError"),
    newEmptyNode(),
    nnkGenericParams.newTree(
      nnkIdentDefs.newTree(
        newIdentNode("T"),
        newIdentNode("E"),
        newEmptyNode(),
        newEmptyNode()
      )
    ),
    nnkFormalParams.newTree(
      newEmptyNode(),
      nnkIdentDefs.newTree(
        newIdentNode("self"),
        nnkBracketExpr.newTree(
          newIdentNode("Result"),
          newIdentNode("T"),
          newIdentNode("E")
        ),
        newEmptyNode()
      )
    ),
    nnkPragma.newTree(
      newIdentNode("noreturn"),
      newIdentNode("noinline")
    ),
    newEmptyNode(),
    nnkStmtList.newTree(
      nnkMixinStmt.newTree(
        newIdentNode("toException")
      ),
      nnkWhenStmt.newTree(
        nnkElifBranch.newTree(
          nnkInfix.newTree(
            newIdentNode("is"),
            newIdentNode("E"),
            nnkRefTy.newTree(
              newIdentNode("Exception")
            )
          ),
          nnkStmtList.newTree(
            nnkIfStmt.newTree(
              nnkElifBranch.newTree(
                nnkDotExpr.newTree(
                  nnkDotExpr.newTree(
                    newIdentNode("self"),
                    newIdentNode("eResultPrivate")
                  ),
                  newIdentNode("isNil")
                ),
                nnkStmtList.newTree(
                  nnkRaiseStmt.newTree(
                    nnkObjConstr.newTree(
                      nnkPar.newTree(
                        nnkRefTy.newTree(
                          nnkBracketExpr.newTree(
                            newIdentNode("ResultError"),
                            newIdentNode("void")
                          )
                        )
                      ),
                      nnkExprColonExpr.newTree(
                        newIdentNode("msg"),
                        newLit("Trying to access value with err (nil)")
                      )
                    )
                  )
                )
              )
            ),
            nnkRaiseStmt.newTree(
              nnkDotExpr.newTree(
                newIdentNode("self"),
                newIdentNode("eResultPrivate")
              )
            )
          )
        ),
        nnkElifBranch.newTree(
          nnkInfix.newTree(
            newIdentNode("is"),
            newIdentNode("E"),
            newIdentNode("void")
          ),
          nnkStmtList.newTree(
            nnkRaiseStmt.newTree(
              nnkObjConstr.newTree(
                nnkPar.newTree(
                  nnkRefTy.newTree(
                    nnkBracketExpr.newTree(
                      newIdentNode("ResultError"),
                      newIdentNode("void")
                    )
                  )
                ),
                nnkExprColonExpr.newTree(
                  newIdentNode("msg"),
                  newLit("Trying to access value with err")
                )
              )
            )
          )
        ),
        nnkElifBranch.newTree(
          nnkCall.newTree(
            newIdentNode("compiles"),
            nnkCall.newTree(
              newIdentNode("toException"),
              nnkDotExpr.newTree(
                newIdentNode("self"),
                newIdentNode("eResultPrivate")
              )
            )
          ),
          nnkStmtList.newTree(
            nnkRaiseStmt.newTree(
              nnkCall.newTree(
                newIdentNode("toException"),
                nnkDotExpr.newTree(
                  newIdentNode("self"),
                  newIdentNode("eResultPrivate")
                )
              )
            )
          )
        ),
        nnkElifBranch.newTree(
          nnkCall.newTree(
            newIdentNode("compiles"),
            nnkPrefix.newTree(
              newIdentNode("$"),
              nnkDotExpr.newTree(
                newIdentNode("self"),
                newIdentNode("eResultPrivate")
              )
            )
          ),
          nnkStmtList.newTree(
            nnkRaiseStmt.newTree(
              nnkObjConstr.newTree(
                nnkPar.newTree(
                  nnkRefTy.newTree(
                    nnkBracketExpr.newTree(
                      newIdentNode("ResultError"),
                      newIdentNode("E")
                    )
                  )
                ),
                nnkExprColonExpr.newTree(
                  newIdentNode("error"),
                  nnkDotExpr.newTree(
                    newIdentNode("self"),
                    newIdentNode("eResultPrivate")
                  )
                ),
                nnkExprColonExpr.newTree(
                  newIdentNode("msg"),
                  nnkPrefix.newTree(
                    newIdentNode("$"),
                    nnkDotExpr.newTree(
                      newIdentNode("self"),
                      newIdentNode("eResultPrivate")
                    )
                  )
                )
              )
            )
          )
        ),
        nnkElse.newTree(
          nnkStmtList.newTree(
            nnkRaiseStmt.newTree(
              nnkObjConstr.newTree(
                nnkPar.newTree(
                  nnkRefTy.newTree(
                    nnkBracketExpr.newTree(
                      newIdentNode("ResultError"),
                      newIdentNode("E")
                    )
                  )
                ),
                nnkExprColonExpr.newTree(
                  newIdentNode("msg"),
                  newLit("Trying to access value with err")
                ),
                nnkExprColonExpr.newTree(
                  newIdentNode("error"),
                  nnkDotExpr.newTree(
                    newIdentNode("self"),
                    newIdentNode("eResultPrivate")
                  )
                )
              )
            )
          )
        )
      )
    )
  ),
  nnkTemplateDef.newTree(
    newIdentNode("err"),
    newEmptyNode(),
    nnkGenericParams.newTree(
      nnkIdentDefs.newTree(
        newIdentNode("T"),
        newEmptyNode(),
        newEmptyNode()
      ),
      nnkIdentDefs.newTree(
        newIdentNode("E"),
        nnkPrefix.newTree(
          newIdentNode("not"),
          newIdentNode("void")
        ),
        newEmptyNode()
      )
    ),
    nnkFormalParams.newTree(
      newIdentNode("R"),
      nnkIdentDefs.newTree(
        newIdentNode("R"),
        nnkCommand.newTree(
          newIdentNode("type"),
          nnkBracketExpr.newTree(
            newIdentNode("Result"),
            newIdentNode("T"),
            newIdentNode("E")
          )
        ),
        newEmptyNode()
      ),
      nnkIdentDefs.newTree(
        newIdentNode("x"),
        newIdentNode("untyped"),
        newEmptyNode()
      )
    ),
    newEmptyNode(),
    newEmptyNode(),
    nnkStmtList.newTree(
      nnkObjConstr.newTree(
        newIdentNode("R"),
        nnkExprColonExpr.newTree(
          newIdentNode("oResultPrivate"),
          newIdentNode("false")
        ),
        nnkExprColonExpr.newTree(
          newIdentNode("eResultPrivate"),
          newIdentNode("x")
        )
      )
    )
  ),
  nnkFuncDef.newTree(
    newIdentNode("tryValue"),
    newEmptyNode(),
    nnkGenericParams.newTree(
      nnkIdentDefs.newTree(
        newIdentNode("T"),
        newIdentNode("E"),
        newEmptyNode(),
        newEmptyNode()
      )
    ),
    nnkFormalParams.newTree(
      newIdentNode("T"),
      nnkIdentDefs.newTree(
        newIdentNode("self"),
        nnkBracketExpr.newTree(
          newIdentNode("Result"),
          newIdentNode("T"),
          newIdentNode("E")
        ),
        newEmptyNode()
      )
    ),
    nnkPragma.newTree(
      newIdentNode("inline")
    ),
    newEmptyNode(),
    nnkStmtList.newTree(
      nnkMixinStmt.newTree(
        newIdentNode("raiseResultError")
      ),
      nnkCaseStmt.newTree(
        nnkDotExpr.newTree(
          newIdentNode("self"),
          newIdentNode("oResultPrivate")
        ),
        nnkOfBranch.newTree(
          newIdentNode("false"),
          nnkStmtList.newTree(
            nnkCall.newTree(
              nnkDotExpr.newTree(
                newIdentNode("self"),
                newIdentNode("raiseResultError")
              )
            )
          )
        ),
        nnkOfBranch.newTree(
          newIdentNode("true"),
          nnkStmtList.newTree(
            nnkWhenStmt.newTree(
              nnkElifBranch.newTree(
                nnkInfix.newTree(
                  newIdentNode("isnot"),
                  newIdentNode("T"),
                  newIdentNode("void")
                ),
                nnkStmtList.newTree(
                  nnkDotExpr.newTree(
                    newIdentNode("self"),
                    newIdentNode("vResultPrivate")
                  )
                )
              )
            )
          )
        )
      )
    )
  ),
  nnkPragma.newTree(
    newIdentNode("push"),
    nnkExprColonExpr.newTree(
      newIdentNode("raises"),
      nnkBracket.newTree(
      )
    )
  ),
  nnkPragma.newTree(
    newIdentNode("push"),
    newIdentNode("public")
  ),
  nnkTemplateDef.newTree(
    newIdentNode("tryGet"),
    newEmptyNode(),
    nnkGenericParams.newTree(
      nnkIdentDefs.newTree(
        newIdentNode("T"),
        nnkPrefix.newTree(
          newIdentNode("not"),
          newIdentNode("void")
        ),
        newEmptyNode()
      ),
      nnkIdentDefs.newTree(
        newIdentNode("E"),
        newEmptyNode(),
        newEmptyNode()
      )
    ),
    nnkFormalParams.newTree(
      newIdentNode("T"),
      nnkIdentDefs.newTree(
        newIdentNode("self"),
        nnkBracketExpr.newTree(
          newIdentNode("Result"),
          newIdentNode("T"),
          newIdentNode("E")
        ),
        newEmptyNode()
      )
    ),
    newEmptyNode(),
    newEmptyNode(),
    nnkStmtList.newTree(
      nnkCall.newTree(
        nnkDotExpr.newTree(
          newIdentNode("self"),
          newIdentNode("tryValue")
        )
      )
    )
  ),
  nnkFuncDef.newTree(
    newIdentNode("toException"),
    newEmptyNode(),
    newEmptyNode(),
    nnkFormalParams.newTree(
      nnkRefTy.newTree(
        newIdentNode("LPError")
      ),
      nnkIdentDefs.newTree(
        newIdentNode("e"),
        newIdentNode("string"),
        newEmptyNode()
      )
    ),
    newEmptyNode(),
    newEmptyNode(),
    nnkStmtList.newTree(
      nnkObjConstr.newTree(
        nnkPar.newTree(
          nnkRefTy.newTree(
            newIdentNode("LPError")
          )
        ),
        nnkExprColonExpr.newTree(
          newIdentNode("msg"),
          newIdentNode("e")
        )
      )
    )
  ),
  nnkProcDef.newTree(
    nnkPostfix.newTree(
      newIdentNode("*"),
      nnkAccQuoted.newTree(
        newIdentNode("&")
      )
    ),
    newEmptyNode(),
    newEmptyNode(),
    nnkFormalParams.newTree(
      newEmptyNode()
    ),
    nnkPragma.newTree(
      nnkExprColonExpr.newTree(
        newIdentNode("raises"),
        nnkBracket.newTree(
          newIdentNode("LPError")
        )
      )
    ),
    newEmptyNode(),
    nnkStmtList.newTree(
      nnkLetSection.newTree(
        nnkIdentDefs.newTree(
          newIdentNode("foo"),
          nnkBracketExpr.newTree(
            newIdentNode("Result"),
            newIdentNode("int"),
            newIdentNode("string")
          ),
          nnkCall.newTree(
            nnkDotExpr.newTree(
              nnkBracketExpr.newTree(
                newIdentNode("Result"),
                newIdentNode("int"),
                newIdentNode("string")
              ),
              newIdentNode("err")
            ),
            newLit("")
          )
        )
      ),
      nnkDiscardStmt.newTree(
        nnkCall.newTree(
          nnkDotExpr.newTree(
            newIdentNode("foo"),
            newIdentNode("tryGet")
          )
        )
      )
    )
  )
)
??? ➡️ 🐛

Diagnostics

The commit that introduced the bug can not be found, but the bug is in the commits:

(Can not find the commit because Nim can not be re-built commit-by-commit to bisect).

Stats
  • GCC 11.4.0
  • Clang 14.0.0
  • NodeJS 20.2
  • Created 2024-04-18T19:30:01Z
  • 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

🤖 Bug found in 24 minutes bisecting 302 commits at 12 commits per second

@tersec
Copy link
Contributor Author

tersec commented Apr 18, 2024

This compiles with 1.6, 2.0.4, 2.0.5, and 2.1.1 as above:

{.push addr.}
{.push do.}
{.push static.}
{.push type.}
{.push _.}
{.push thread.}
{.push final.}
{.push profiler.}
{.push memtracker.}
{.push objchecks.}
{.push intdefine.}
{.push strdefine.}
{.push booldefine.}
{.push cursor.}
{.push noalias.}
{.push uncheckedAssign.}
{.push immediate.}
{.push destructor.}
{.push override.}
{.push requiresInit.}
{.push align.}
{.push nodecl.}
{.push pure.}
{.push nosinks.}
{.push lib.}
{.push dynlib.}
{.push compilerproc.}
{.push core.}
{.push procvar.}
{.push base.}
{.push used.}
{.push fatal.}
{.push error.}
{.push warning.}
{.push hint.}
{.push warningAsError.}
{.push hintAsError.}
{.push line.}
{.push push.}
{.push pop.}
{.push define.}
{.push undef.}
{.push lineDir.}
{.push link.}
{.push compile.}
{.push linksys.}
{.push deprecated.}
{.push varargs.}
{.push callconv.}
{.push debugger.}
{.push on.}
{.push off.}
{.push checks.}
{.push rangeChecks.}
{.push boundChecks.}
{.push overflowChecks.}
{.push nilChecks.}
{.push floatChecks.}
{.push nanChecks.}
{.push infChecks.}
{.push styleChecks.}
{.push staticBoundChecks.}
{.push nonReloadable.}
{.push executeOnReload.}

# this section is apparently intended to be genuinely pragmas
{.push assertions.}
{.push patterns.}
{.push trmacros.}
{.push sinkInference.}
{.push warnings.}
{.push hints.}
{.push optimization.}
{.push writes.}
{.push reads.}
{.push size.}
{.push effects.}
{.push invariant.}
{.push assume.}
{.push assert.}
{.push deadCodeElim.}
{.push safecode.}
{.push package.}
{.push noforward.}
{.push norewrite.}
{.push nodestroy.}
{.push pragma.}
{.push compileTime.}
{.push fieldChecks.}
{.push subschar.}
{.push computedGoto.}
{.push experimental.}
{.push doctype.}
{.push write.}
{.push gensym.}
{.push inject.}
{.push dirty.}
{.push inheritable.}
{.push threadvar.}
{.push asmNoStackFrame.}
{.push implicitStatic.}
{.push global.}
{.push unchecked.}
{.push guard.}
{.push partial.}
{.push explain.}
{.push liftlocals.}
{.push enforceNoRaises.}

# "codegen keywords, but first the ones that are also pragmas"
{.push goto.}
{.push register.}
{.push union.}
{.push packed.}
{.push volatile.}
{.push bycopy.}
{.push byref.}

# "codegen keywords but not pragmas"
{.push auto.}
{.push bool.}
{.push catch.}
{.push char.}
{.push class.}
{.push compl.}
{.push const_cast.}
{.push default.}
{.push delete.}
{.push double.}
{.push dynamic_cast.}
{.push explicit.}
{.push false.}
{.push float.}
{.push friend.}
{.push int.}
{.push long.}
{.push mutable.}
{.push namespace.}
{.push new.}
{.push operator.}
{.push private.}
{.push protected.}
{.push public.}
{.push reinterpret_cast.}
{.push restrict.}
{.push short.}
{.push signed.}
{.push sizeof.}
{.push static_cast.}
{.push struct.}
{.push switch.}
{.push this.}
{.push throw.}
{.push true.}
{.push typedef.}
{.push typeid.}
{.push typeof.}
{.push typename.}
{.push unsigned.}
{.push void.}

{.push alignas.}
{.push alignof.}
{.push constexpr.}
{.push decltype.}
{.push nullptr.}
{.push noexcept.}
{.push thread_local.}
{.push static_assert.}
{.push char16_t.}
{.push char32_t.}
{.push wchar_t.}
{.push stdin.}
{.push stdout.}
{.push stderr.}
{.push inout.}
{.push oneway.}
{.push bitsize.}
{.push all.}

# Something for all these beautiful pragmas to attach to
proc f() = discard
let x = 0

@tersec
Copy link
Contributor Author

tersec commented Apr 18, 2024

{.push emit.} ICEs, as do a few others. It's also possible to use {.push ...} to trigger nim c to instead use the C++ backend, but it doesn't do it properly so it doesn't link.

@juancarlospaco
Copy link
Collaborator

That can be a nice test actually... 🤔

@tersec
Copy link
Contributor Author

tersec commented Apr 19, 2024

Sure, though some of them are supposed to work and are actual pragmas. I'm not sure any of the "codegen keywords but not pragmas" make sense in this grammatical context though. Not sure what {.push char16_t.}, {.push addr.}, {.push do.}, et cetera should mean either.

Some of them, e.g., on and off, are kind of strange artifacts of the grammar, apparently, where they seem to be meant to be paired with a warning or similar token to provide them meaning, but are parsed regardless.

@ringabout
Copy link
Member

Yeah, the regression on ther version-2-0 failed the nightlies

@ringabout
Copy link
Member

ringabout commented Apr 19, 2024

@juancarlospaco Hi, could you add Nim compiler built on the branch version-2-0 for bisects?

@narimiran
Copy link
Member

I bisected version-2-0, and this seems to be the problematic commit: #22941

I'm backporting commits from this list: nim-lang/backport#3, and I have lots of commits yet to backport, so this might be fixed by some later commit. But in the mean time, I can revert the commit linked above.

@ringabout
Copy link
Member

Yeah, it should be reverted on the version-2-0 branch

@narimiran
Copy link
Member

Yeah, it should be reverted on the version-2-0 branch

Reverted.

@tersec The original example now works on my machine with version-2-0, closing.

@ringabout
Copy link
Member

Hi, @narimiran nightlies are still broken on version-2-0 branch => https://github.com/nim-lang/nightlies/actions/runs/8776715740/job/24080631890 probably it's a different cause?

@narimiran
Copy link
Member

Hi, @narimiran nightlies are still broken on version-2-0 branch

Today a new batch of backports will come. Let's see if something changes after that.

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

No branches or pull requests

4 participants