Created
August 1, 2017 22:19
-
-
Save vladfaust/8322a233f4ac89a3f235267f98f0781b to your computer and use it in GitHub Desktop.
Overloading bug (Crystal issue #4775)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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