Undefined double methods were reporting splat arguments, which is technically correct.
But for output in these cases, it makes more sense to show the exact calling args.
In Crystal 1.6, a segfault would occur in the spec spec/spectator/mocks/lazy_double_spec.cr:238
I suspect this is a Crystal bug of some kind, but can't reduce it.
The methods produced by `method_missing` don't have a return type including Symbol.
Symbol is excluded from the union of return types (Int32 | String | Nil).
The program segfaults when calling a method on the actual value, which is a symbol.
It ultimately crashes when producing a failure message, which indicates the value it tested doesn't equal the expected value (a symbol of the same value).
Avoid this issue by preventing stubs on undefined/untyped methods.
When defining a matcher outside of the `Spectator` module (custom matcher), `Value(ExpectedType)` can't be resolved.
I suspect this is a Crystal compiler bug, since a derived class should not affect lookups of parent classes like this.
Require statements are added to (hopefully) ensure `Spectator::Value` is defined for the initializer.
Related to https://github.com/icy-arctic-fox/spectator/issues/46
BUG: trying to upcast Nil (Crystal::NilType) <- NoReturn (Crystal::NoReturnType) (Exception)
from /crystal/src/compiler/crystal/codegen/cast.cr:668:5 in 'upcast_distinct'
from /crystal/src/compiler/crystal/codegen/cast.cr:523:15 in 'upcast'
from /crystal/src/compiler/crystal/codegen/codegen.cr:1369:11 in 'accept'
from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
...
This effectively allows stubs to be placed on the `new` method for types.
A strange issue arose when the keyword was allowed.
The compiler failed to resolve the Stub type from the Double initializer.
The error trace goes through null_double_spec.cr.
Running just that spec file confirms the issue is there, but running other individual files doesn't produce the error.
As a workaround, I've put the full path of Stub in the initializer.
Without this, mocked structs were not getting their stubs applied.
An unintended side-effect is the tap shows up in recorded calls.
This seems to be harmless, but might need to be revisited.