Hi @Tamas_Papp please don’t assume bad behaviour. I am feeling slightly offended by your phrasing. Guessing is a really good thing to do and I myself would like to encourage everyone not only to read, but also to think.
So let me apply what you quoted and what I also read before:
Can nothing be converted to Union{Nothing, Int}? yes it can
Can 4 be converted to Union{Nothing, Int} yes it can
can all arguments be converted? yes they can
The motivation you mentioned is something completely different, and I haven’t known that yet and also couldn’t find it in the documentation. Sounds very interesting.
Can you point out where the infinite recursion would happen if I would enable promote(nothing, 4) == (nothing, 4)?
foo(x::T, y::T) where T = x + 2*y
foo(x, y) = foo(promote(x, y)...)
foo(1, nothing) # would go into an infinite loop without an error
That’s not how it works (eg everything can trivially be “converted” to a common type Any, so by your logic promote could just return its arguments and call it a day).
awesome! understood. Yes, and this seems the common usecase of promote. Still it is not mentioned in the documentation to the best of my understanding. To repeat, the documentation says
promote(xs…)
Convert all arguments to a common type, and return them all (as a tuple). If no arguments can be converted, an error is raised.
The open question is, what is this common type? I would have guessed it is promote_type(typeof.(xs)...). And then, at least in mind, the logic would apply which I sketched.
In this sense I would argue that the documentation is crucially incomplete. promote seems to be made for exactly the foo use case you described, and hence the common type needs to be a concrete type.