Initial work on stub DSL - found bug in Crystal compiler

```
Module validation failed: Invalid bitcast
  %4 = bitcast i32* %3 to %"(Spectator::Arguments(T, NT) | Nil)", !dbg !16
 (Exception)
  from /crystal/src/int.cr:541:9 in 'finish'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:71:7 in 'codegen'
  from /crystal/src/compiler/crystal/compiler.cr:173:16 in 'compile'
  from /crystal/src/compiler/crystal/command/spec.cr:98:14 in 'spec'
  from /crystal/src/hash.cr:901:11 in '__crystal_main'
  from /crystal/src/crystal/main.cr:115:5 in 'main'
  from src/env/__libc_start_main.c:94:2 in 'libc_start_main_stage2'
Error: you've found a bug in the Crystal compiler. ...
```

I haven't been able to reproduce this in a simplified form.

Passing the `constraint` argument in NullStub#and_return to ValueStub.new triggers the bug.
Removing the `constraint` argument fixes the issue.
This commit is contained in:
Michael Miller 2022-03-31 22:49:45 -06:00
parent 003be48591
commit e05ef94ef5
No known key found for this signature in database
GPG key ID: 32B47AE8F388A1FF
4 changed files with 48 additions and 0 deletions

View file

@ -0,0 +1,11 @@
require "../../../spec_helper"
Spectator.describe "Stubs DSL" do
double(:foobar, foo: 42, bar: "baz")
let(dbl) { double(:foobar) }
specify do
allow(dbl).to receive(:foo).and_return(123)
expect(dbl.foo).to eq(123)
end
end

View file

@ -127,5 +127,13 @@ module Spectator::DSL
macro double(**value_methods)
::Spectator::LazyDouble.new({{**value_methods}})
end
macro allow(stubbable)
::Spectator::Allow.new({{stubbable}})
end
macro receive(method)
::Spectator::NullStub.new({{method.id.symbolize}})
end
end
end

View file

@ -0,0 +1,14 @@
require "./stub"
require "./stubbable"
module Spectator
struct Allow(T)
def initialize(@target : T)
{% raise "Target of `allow` must be stubbable (a mock or double)." unless T < Stubbable %}
end
def to(stub : Stub) : Nil
@target._spectator_define_stub(stub)
end
end
end

View file

@ -0,0 +1,15 @@
require "./typed_stub"
require "./value_stub"
module Spectator
# Stub that does nothing and returns nil.
class NullStub < TypedStub(Nil)
def value : Nil
nil
end
def and_return(value)
ValueStub.new(method, value, constraint)
end
end
end