Void being () or Unit as some other languages call it allows for some nice things. Scala in particular has erased values and whatnot that take advantage of this. Some use cases in Nim would be like so:
Nim currently has a feature where let _ = foo corresponds to discard foo. This is because _ is a special identifier. This behaviour is arbitrary and doesn't do things you would expect, such as this one in proc definitions, and a bug that I couldn't find related to object variants (also to note, you can name an object field _ and it works like a regular parameter but errors if you name it _name).
There is a section in the experimental manual about the void type, and how it can be used in object fields and proc parameters to signify a parameter that doesn't exist. This implementation seems a bit verbose however, such as the following code:
proc callProc[T](p: proc (x: T), x: T) =
when T is void:
p()
else:
p(x)
proc intProc(x: int) = discard
proc emptyProc() = discard
callProc[int](intProc, 12)
callProc[void](emptyProc)
Defining type void = tuple[] and adding special behaviour to tuple[] specifically (such as tuple[] is a subtype of every type, and it is eluded in proc parameters) seems like it would fit Nim's philosophy of being elegant more than the existing void. let _ = foo could be replaced by let () = foo a la OCaml, and it would fit more of discard's philosophy of "turning into a void value".
Not to mention, in the above code snippet, typing p(x) would be equivalent to p(()), which seems more appropriate to translate to p() than it having the unique type void.
It would also mean a standalone discard could just be translated to the expression (). This is just a personal thing, but this would look way better in case object branches in my opinion, more appropriate than discard or nil since the intended message is "there are no fields here".
distinct void/distinct tuple[] types could be used in generics to fulfill the effect of special types. This would replace the current convention of just using an empty object type, which is unpreferable for many reasons that I don't think I need to go into in this post. This is even in the Nim standard library already, see StaticParam[T] in typetraits.
While writing this post, I remembered an RFC I wrote a while ago, proposing void converters <https://github.com/nim-lang/RFCs/issues/61>_. The "discard overload" part of this RFC is incompatible with what I am suggesting here, since discard would be pretty much just syntax sugar. I also don't think void converters are good since they're hidden control flow, but that's unrelated. The point I am making is tuple[] will allow for solutions to more abstract problems like the ones implied in my RFC if you can do things like distinct tuple[]. For example, a function that normally returns void but has the possibility of setting a global error variable could cause problems if the code it's called in doesn't check for that error variable. If you give it a return type CanError = distinct void, the compiler will complain if you don't discard the call, thus you can be reminded to check for an error.
The problem with this concept is tuple[] is currently treated as a value in Nim. let x = () works, echo(()) prints () meaning $() == "()", so on. So this would be a breaking change. Not to say that anyone is actually using tuple[] in their code, most people probably don't even account for its existence in generics causing some potential bugs, it would just change the behaviour of the language. It's also going to harm Nim's maturity when it gets implemented, so it might be best if this was considered around Nim 2.0, but there are existing features in the language that are incomplete yet related such as let _ = foo, so I believe it's also fairly relevant now.
Will this happen? Are there any pitfalls that I haven't considered? Does it warrant an RFC or is there already one I don't know?