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

nim compiler mistakes `!(a == b)` for `!a == b` and fails to compile #12184

Closed Muratam closed 5 years ago

Muratam commented 5 years ago

Overriding equal function causes incorrect behaviour. Nim compiler translates !(a == b) into !a == b and fails to compile.

Example

type CSet {.importcpp: "std::set", header: "<set>".} [T] = object
proc cInitSet(T: typedesc): CSet[T] {.importcpp: "std::set<'*1>()", nodecl.}
proc insert[T](self: var CSet[T],x:T) {.importcpp: "#.insert(@)", nodecl.}
proc `==`[T](x,y:CSet[T]):bool{.importcpp: "#==#", nodecl.}
var (S1,S2) = (cInitSet(int),cInitSet(int))
S1.insert 1
if S1 == S2: echo "wrong"
else: echo "correct"

Current Output

Nim fails to compile and prints the following error.

Error: execution of an external compiler program 'clang++ -c  -w  -~/.choosenim/toolchains/nim-0.20.0/lib -I~/codes/nim/ -o ~/.cache/nim/t_d/t.nim.cpp.o ~/.cache/nim/t_d/t.nim.cpp' failed with exit code: 1

~/.cache/nim/t_d/t.nim.cpp:153:7: error: invalid argument type 'TY_89ajMAHL4D29bP2aGRstu1mQ' (aka 'set<long long>') to unary expression
                if (!S1_X5vbOHyI0SI13LVkxEIzEQ==S2_q2YrwwKwgOf4xdemDnRTYA) goto LA4_;
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

Expected Output

correct

Possible Solution (not fundamental)

Change the definition of ==

before:

proc `==`[T](x,y:CSet[T]):bool{.importcpp: "#==#", nodecl.}

after:

proc equalRawImpl[T](x,y:CSet[T]):bool{.importcpp: "#==#", nodecl.}
proc `==`[T](x,y:CSet[T]):bool = not(not(x.equalRawImpl y))

But, it is not not not a fundamental solution .

By the way, if you don't override == function, it will print the wrong result (print wrong).

Additional Information

Raw C code (error:14th line):

N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
    tyTuple_WVskh7WUQHL0ugdByxngAw T1_;
    nimfr_("t", "/path/to/t.nim");
    nimln_(8, "/path/to/t.nim"); 
    T1_.Field0 = std::set<NI>();
    T1_.Field1 = std::set<NI>();
    S1_X5vbOHyI0SI13LVkxEIzEQ = T1_.Field0;
    S2_q2YrwwKwgOf4xdemDnRTYA = T1_.Field1;
    nimln_(9, "/path/to/t.nim"); 
    S1_X5vbOHyI0SI13LVkxEIzEQ.insert(((NI) 1));
    nimln_(10, "/path/to/t.nim"); 
    {
        if (!S1_X5vbOHyI0SI13LVkxEIzEQ==S2_q2YrwwKwgOf4xdemDnRTYA) goto LA4_;
{       echoBinSafe(TM_earX20ePV9cxitomwdUMS7g_2, 1);
}   }
    goto LA2_;
    LA4_: ;
    {
        nimln_(11, "/path/to/t.nim"); 
        echoBinSafe(TM_earX20ePV9cxitomwdUMS7g_4, 1);
    }
    LA2_: ;
    popFrame();
}
}
$ nim -v
Nim Compiler Version 0.20.0 [MacOSX: amd64]
Compiled at 2019-06-06
Copyright (c) 2006-2019 by Andreas Rumpf
git hash: e7471cebae2a404f3e4239f199f5a0c422484aac
active boot switches: -d:release

It was not working in the previous Nim releases too.

Araq commented 5 years ago

Instead use


proc `==`[T](x,y:CSet[T]):bool{.importcpp: "(#==#)", nodecl.}
andreaferretti commented 5 years ago

Isn't this a duplicate of https://github.com/nim-lang/Nim/issues/2534 ?

Araq commented 5 years ago

Indeed.