Open perimosocordiae opened 2 years ago
This should get better when we implement interfaces, but it's still probably a thing we need to watch out for. What's going on here is that the 2-parameter Print is fully generic and matches unconditionally. It dispatches to the 1-parameter Print for each argument, but one of those fails so it prints something useful from the perspective of the failing code: If you were the author of the 2-parameter Print, this would indeed be useful.
clang also adds an instantiation stack for templates so it would show this and the instantiators all the way up. If we implement interfaces correctly, we should never hit this point, because the binding of *i8
to A0
would fail immediately and generate a corresponding error message. We would also demand "Printable" on the type parameter A0
, so even without instantiations of this generic we would be able to verify correctness.
Update: for the second code snippet above (two arguments to Print), we now get this error:
Error:
Expression cannot be called with the given arguments.
32 | [139792255997768 ./frontend/source/buffer.h:151] Assertion failed
Expected: end_offset == 0
LHS: 2
RHS: 0
*** SIGABRT received at time=1641172330 on cpu 0 ***
PC: @ 0x7f23ebccc808 (unknown) pthread_kill
@ 0x18b99a0 64 absl::WriteFailureInfo()
@ 0x18b9684 224 absl::AbslFailureSignalHandler()
@ 0x7f23ebc78520 (unknown) (unknown)
Aborted (core dumped)
Reproducer:
Error message:
This is actually not too bad, except for the confusing ordering of the messages and the repeated entries starting with
* generic --
. The fun part comes when you call the two-argument version of Print:Error message:
Here, we lose the actual type of the argument (
*i8
) and instead use the generic placeholderA0
.