Skip to content

Commit

Permalink
Fixed #3304: Casting type to itself, when there are subclasses, crash…
Browse files Browse the repository at this point in the history
…es the compiler
Ary Borenszweig committed Sep 14, 2016

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 6bd28f4 commit fd2d51f
Showing 3 changed files with 90 additions and 4 deletions.
42 changes: 42 additions & 0 deletions spec/compiler/codegen/cast_spec.cr
Original file line number Diff line number Diff line change
@@ -289,4 +289,46 @@ describe "Code gen: cast" do
Bar.new.as(Foo(Int32)).foo
)).to_i.should eq(2)
end

it "upcasts type to virtual (#3304)" do
run(%(
class Foo
def foo
1
end
end
class Bar < Foo
def foo
2
end
end
Foo.new.as(Foo).foo
)).to_i.should eq(1)
end

it "upcasts type to virtual (2) (#3304)" do
run(%(
class Foo
def foo
1
end
end
class Bar < Foo
def foo
2
end
end
class Gen(T)
def self.cast(x)
x.as(T)
end
end
Gen(Foo).cast(Foo.new).foo
)).to_i.should eq(1)
end
end
44 changes: 44 additions & 0 deletions spec/compiler/codegen/nilable_cast_spec.cr
Original file line number Diff line number Diff line change
@@ -85,4 +85,48 @@ describe "Code gen: nilable cast" do
foo
))
end

it "upcasts type to virtual (#3304)" do
run(%(
class Foo
def foo
1
end
end
class Bar < Foo
def foo
2
end
end
f = Foo.new.as?(Foo)
f ? f.foo : 10
)).to_i.should eq(1)
end

it "upcasts type to virtual (2) (#3304)" do
run(%(
class Foo
def foo
1
end
end
class Bar < Foo
def foo
2
end
end
class Gen(T)
def self.cast(x)
x.as?(T)
end
end
f = Gen(Foo).cast(Foo.new)
f ? f.foo : 10
)).to_i.should eq(1)
end
end
8 changes: 4 additions & 4 deletions src/compiler/crystal/semantic/bindings.cr
Original file line number Diff line number Diff line change
@@ -296,8 +296,8 @@ module Crystal
#
# 1 as Int32 | Float64
# Bar.new as Foo # where Bar < Foo
if obj_type == filtered_type && obj_type != to_type &&
!to_type.is_a?(GenericClassType) && to_type.allowed_in_generics?
if obj_type == filtered_type && !to_type.is_a?(GenericClassType) &&
to_type.allowed_in_generics?
filtered_type = to_type
@upcast = true
end
@@ -327,8 +327,8 @@ module Crystal
#
# 1 as Int32 | Float64
# Bar.new as Foo # where Bar < Foo
if obj_type == filtered_type && obj_type != to_type &&
!to_type.is_a?(GenericClassType) && to_type.allowed_in_generics?
if obj_type == filtered_type && !to_type.is_a?(GenericClassType) &&
to_type.allowed_in_generics?
filtered_type = to_type.virtual_type
@upcast = true
end

0 comments on commit fd2d51f

Please sign in to comment.