Skip to content

Instantly share code, notes, and snippets.

@vladfaust
Created August 1, 2017 22:19
Show Gist options
  • Save vladfaust/8322a233f4ac89a3f235267f98f0781b to your computer and use it in GitHub Desktop.
Save vladfaust/8322a233f4ac89a3f235267f98f0781b to your computer and use it in GitHub Desktop.
Overloading bug (Crystal issue #4775)
# Using crystal 0.23.1
# See https://github.com/crystal-lang/crystal/issues/4775
# Run `crystal spec test.cr` to test
# PART 0: Definitions
module Abstract
abstract class Dog
def initialize(@color : String)
end
abstract def bark
end
# Cats are here to show that when the special dog is barking after the special cat's meowing it's still awaited to compile
abstract class Cat
def initialize(@color : String)
end
abstract def meow
end
abstract class Zoo
def make_some_noise
color = case rand(2)
when 0 then "Black"
else "White"
end
animal = select_animal
if animal.is_a?(Abstract::Dog.class)
animal.new(color).bark
elsif animal.is_a?(Abstract::Cat.class)
animal.new(color).meow
end
end
private abstract def select_animal : Abstract::Dog.class | Abstract::Cat.class | Nil
end
end
module MyDogs
class Special < Abstract::Dog
# This dog is unusual, it has size
def initialize(color : String, @size : Int32)
super(color)
end
def bark
p "Specical #{@color} dog with a size of #{@size} inches barks"
end
end
class B < Abstract::Dog
def bark
p "#{@color} dog B barks"
end
end
class C < Abstract::Dog
def bark
p "#{@color} dog C barks"
end
end
class D < Abstract::Dog
def bark
p "#{@color} dog D barks"
end
end
end
module MyCats
# This Cat utilizes unusual Dog!
class Special < Abstract::Cat
def meow
p "Special #{@color} cat meows to a same big special dog, and it answers: "
MyDogs::Special.new(@color, 42).bark
end
end
class B < Abstract::Cat
def meow
p "#{@color} cat B meows"
end
end
end
# PART 1: Successfully compiled
require "spec"
class MyZoo1 < Abstract::Zoo
def select_animal
MyDogs::B
end
end
class MyZoo2 < Abstract::Zoo
def select_animal
MyCats::Special # It's here, initializing special dog with an additional argument
end
end
class MyZoo3 < Abstract::Zoo
def select_animal
case rand(3)
when 0
MyCats::Special # Also here, but #make_some_noise still doesn't have to initialize Special Dog explicitly
else
MyDogs::B
end
end
end
class MyZoo4 < Abstract::Zoo
def select_animal
case rand(2)
when 0
MyDogs::B
else
MyDogs::B
end
end
end
class MyZoo5 < Abstract::Zoo
def select_animal
case rand(2)
when 0
MyDogs::C
else
MyDogs::C
end
end
end
class MyZoo6 < Abstract::Zoo
def select_animal
case rand(2)
when 0
MyDogs::D
when 1
MyDogs::D
end
end
end
class MyZoo7 < Abstract::Zoo
def select_animal
case rand(3)
when 0
MyCats::Special
when 1
MyCats::B
else
MyDogs::B
end
end
end
describe Abstract::Zoo do
{% for value in (1..7) %}
it "MyZoo{{value.id}} compiles" do
MyZoo{{value.id}}.new.make_some_noise
true.should be_truthy
end
{% end %}
end
# PART 2: Failing to compile
class MyZooWhichCantCompile < Abstract::Zoo
def select_animal
# Uncomment an expression to see it in action
# Fails as expected with `wrong number of arguments for 'MyDogs::Special.new' (given 1, expected 2)`
# MyDogs::Special
# These fail with `wrong number of arguments for 'MyDogs::Special#initialize' (given 1, expected 2)`
# case rand(2)
# when 0
# MyDogs::B
# else
# MyDogs::C
# end
# case rand(2)
# when 0
# MyDogs::B
# when 1
# MyDogs::C
# end
# case rand(3)
# when 0
# MyCats::Special
# when 1
# MyDogs::B
# when 2
# MyDogs::C
# end
# case rand(3)
# when 0
# MyCats::Special
# when 1
# MyDogs::B
# else
# MyDogs::C
# end
# case rand(4)
# when 0
# MyCats::Special
# when 1
# MyDogs::B
# when 2
# MyDogs::C
# end
# case rand(4)
# when 0
# MyCats::Special
# when 1
# MyDogs::B
# else
# MyDogs::C
# end
# case rand(4)
# when 0
# MyCats::Special
# when 1
# MyCats::B
# when 2
# MyDogs::C
# else
# MyDogs::D
# end
# case rand(4)
# when 0
# MyCats::Special
# when 1
# MyDogs::B
# when 2
# MyDogs::C
# when 3
# MyDogs::D
# end
end
end
MyZooWhichCantCompile.new.make_some_noise
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment