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

Problem with forward declaration #17673

Open zeitbit opened 3 years ago

zeitbit commented 3 years ago

Hello,

This works OK:

proc fn(): int32 | int64 =
    1

var v = fn()

But using a forward declaration fails, "Error: invalid type: 'int32 or int64' for var":

proc fn(): int32 | int64

var v = fn()

proc fn(): int32 | int64 =
    1

Specifying the type (int32 or int) produces this error: "Error: type mismatch: got 'int32 or int64' for 'fn()' but expected 'int32'"

proc fn(): int32 | int64

var a: int32 = fn()

proc fn(): int32 | int64 =
    1

And with int64 the exception: "Error: unhandled exception: ccgtypes.nim(198, 17) false mapType: tyOr [AssertionDefect]"

proc fn(): int32 | int64

var a: int64 = fn()

proc fn(): int32 | int64 =
    1

Nim Compiler Version 1.5.1 [Windows: amd64] Compiled at 2021-04-03

beef331 commented 3 years ago

I couldnt resist trying the following, and it might be related to the issue. The types of a forward declared procedure seems to be unresolved until the implementation is specified meaning the return type is the typeclass you specified causing this error.

proc fn(): int32 | int64

static: assert typeof(fn()) is (int64 or int32)

proc fn(): int32 | int64 = 1

static: assert typeof(fn()) is int
saem commented 3 years ago

Oh this is interesting. The timing for this is mostly dictated in semProcAux and the generic call I think that's in semgnrcs.nim. With the type class in the return that should make this implicitly generic. If you want to take a stab at it I would poke at semProcAux as a start. It'll be a good test to see if the reworking of the code helped clarify things.

(There is a slim chance I can look at it this weekend)