Apparently typedesc arguments are covariant. For example:
import typetraits
type
A = object of RootObj
B = object of A
proc f(T: typedesc[A]) =
echo "should only accept A, but not B"
echo "T is A: ", T is A
echo "name(T): ", name(T)
f(A)
f(B) # how to prevent this to compile?
This compiles and prints:
should only accept A, but not B
T is A: true
name(T): A
should only accept A, but not B
T is A: true
name(T): B
Is there an elegant solution so that I cannot accidentally invoke f(B)? The ideal solution (in my particular problem) would be to avoid the function match entirely. Otherwise some when + error statements might be needed, but when T is A doesn't work because it also returns true for subtypes, when name(T) == name(A) feels hacky.
I wonder why you use at all
B = object of A
when you do not want to enable passing B where A is expected.
But it is easy to enforce a compile time error, add
proc f(T: typedesc[B]) {.error.}
I'm stupid, I totally forgot that there is the T is A and A is T trick that allows for exact type equality comparison. I still think it is a pity that the corresponding PR has been declined (https://github.com/nim-lang/Nim/pull/8612).
@Stefan_Salewski: The actual background is somewhat involved. In the inheritance library I'm working on, there is a system to automatically perform super/base/parent class initialization. If there is an inheritance chain A => B => C, I have to make sure that when C tries to call its parent constructor, it doesn't accidentally call the constructor of A. This would be possible due to covariance, and result in a bug because B isn't initialized. I'll probably just go for named constructors because it simplifies the problem. I was asking mainly to see what alternatives others use, and the error overload is indeed a nice solution in general.