Avoid issue with TypeCastError message

For some reason, attempting to get the class of the stubbed value causes a segfault.
This appears to get swallowed in some cases.
Trying to inspect the value was difficult without triggering some error.
In the failing case, the value is 42 (returned by a stubbed foo method).
The method is supposed to return a String, and this error checking should be triggered (line 119).
The value is a union, and inspecting the bytes contained in it looks like it's prefixed with the Crystal type ID for Int32.
However it looks like Crystal tries to treat it as a Bool? I'm not sure.
Very weird behavior and instead of wasting more time on it, I'm omitting the returned type from the error.
This type of casting error shouldn't be common.
This seems like a Crystal bug, but I'm having a hard time distilling the issue.
This commit is contained in:
Michael Miller 2022-03-16 22:40:24 -06:00
parent b68c75dda5
commit 4f7a4a3453
No known key found for this signature in database
GPG key ID: AC78B32D30CE34A2
2 changed files with 4 additions and 4 deletions

View file

@ -35,13 +35,13 @@ Spectator.describe Spectator::NullDouble do
end end
context "with abstract stubs and return type annotations" do context "with abstract stubs and return type annotations" do
Spectator::NullDouble.define(TestDouble) do Spectator::NullDouble.define(TestDouble2) do
abstract_stub abstract def foo(value) : String abstract_stub abstract def foo(value) : String
end end
let(arguments) { Spectator::Arguments.capture(/foo/) } let(arguments) { Spectator::Arguments.capture(/foo/) }
let(stub) { Spectator::ValueStub.new(:foo, "bar", arguments).as(Spectator::Stub) } let(stub) { Spectator::ValueStub.new(:foo, "bar", arguments).as(Spectator::Stub) }
subject(dbl) { TestDouble.new([stub]) } subject(dbl) { TestDouble2.new([stub]) }
it "enforces the return type" do it "enforces the return type" do
expect(dbl.foo("foobar")).to compile_as(String) expect(dbl.foo("foobar")).to compile_as(String)

View file

@ -116,7 +116,7 @@ module Spectator
{% if method.return_type.resolve >= Nil %} {% if method.return_type.resolve >= Nil %}
nil nil
{% else %} {% else %}
raise TypeCastError.new("#{_spectator_stubbed_name} received message #{%call} and is attempting to return a `#{%value.class}`, but returned type must be `{{method.return_type}}`.") raise TypeCastError.new("#{_spectator_stubbed_name} received message #{%call} and is attempting to return a <Unknown>, but returned type must be `{{method.return_type}}`.")
{% end %} {% end %}
end end
end end
@ -187,7 +187,7 @@ module Spectator
{% if method.return_type.resolve >= Nil %} {% if method.return_type.resolve >= Nil %}
nil nil
{% else %} {% else %}
raise TypeCastError.new("#{_spectator_stubbed_name} received message #{%call} and is attempting to return a `#{%value.class}`, but returned type must be `{{method.return_type}}`.") raise TypeCastError.new("#{_spectator_stubbed_name} received message #{%call} and is attempting to return a <Unknown>, but returned type must be `{{method.return_type}}`.")
{% end %} {% end %}
end end
end end