From 4f7a4a34534846c4d1742b817891a019b53a80c9 Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Wed, 16 Mar 2022 22:40:24 -0600 Subject: [PATCH] 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. --- spec/spectator/mocks/null_double_spec.cr | 4 ++-- src/spectator/mocks/stubbable.cr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/spectator/mocks/null_double_spec.cr b/spec/spectator/mocks/null_double_spec.cr index 1773a3f..134f0e0 100644 --- a/spec/spectator/mocks/null_double_spec.cr +++ b/spec/spectator/mocks/null_double_spec.cr @@ -35,13 +35,13 @@ Spectator.describe Spectator::NullDouble do end 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 end let(arguments) { Spectator::Arguments.capture(/foo/) } 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 expect(dbl.foo("foobar")).to compile_as(String) diff --git a/src/spectator/mocks/stubbable.cr b/src/spectator/mocks/stubbable.cr index 4a14324..932e697 100644 --- a/src/spectator/mocks/stubbable.cr +++ b/src/spectator/mocks/stubbable.cr @@ -116,7 +116,7 @@ module Spectator {% if method.return_type.resolve >= Nil %} nil {% 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 , but returned type must be `{{method.return_type}}`.") {% end %} end end @@ -187,7 +187,7 @@ module Spectator {% if method.return_type.resolve >= Nil %} nil {% 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 , but returned type must be `{{method.return_type}}`.") {% end %} end end