Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 57717d4c0727
Choose a base ref
...
head repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 9826714fb7ff
Choose a head ref
  • 2 commits
  • 11 files changed
  • 1 contributor

Commits on May 3, 2016

  1. Disallow inheriting a non-abstract struct. Part of #2529

    Ary Borenszweig committed May 3, 2016
    Copy the full SHA
    2857ac1 View commit details
  2. Compiler: make abstract structs work in a similar way to virtual type…

    …s, and represent them as union of all concrete types. Fixes #2529. Fixes #2527. Fixes #2382
    Ary Borenszweig committed May 3, 2016
    Copy the full SHA
    9826714 View commit details
30 changes: 30 additions & 0 deletions spec/compiler/codegen/struct_spec.cr
Original file line number Diff line number Diff line change
@@ -319,4 +319,34 @@ describe "Code gen: struct" do
foo.value
)).to_i.should eq(123)
end

it "codegens virtual struct" do
run(%(
abstract struct Foo
end
struct Bar < Foo
def initialize
@x = 1
end
def x
@x
end
end
struct Baz < Foo
def initialize
@x = 2
end
def x
@x
end
end
foo = Bar.new || Baz.new
foo.x
)).to_i.should eq(1)
end
end
2 changes: 1 addition & 1 deletion spec/compiler/type_inference/alias_spec.cr
Original file line number Diff line number Diff line change
@@ -162,7 +162,7 @@ describe "type inference: alias" do
%w(class struct).each do |type|
it "inherits #{type} through alias" do
assert_type(%(
#{type} Parent
abstract #{type} Parent
end
alias Alias = Parent
88 changes: 77 additions & 11 deletions spec/compiler/type_inference/struct_spec.cr
Original file line number Diff line number Diff line change
@@ -28,17 +28,32 @@ describe "Type inference: struct" do
end
end

it "doesn't allow struct to participate in virtual" do
it "allows struct to participate in virtual" do
assert_type("
struct Foo
abstract struct Foo
end
struct Bar < Foo
end
Foo.new || Bar.new
") do
union_of(types["Foo"], types["Bar"])
struct Baz < Foo
end
Bar.new || Baz.new
") { types["Foo"].virtual_type! }
end

%w(Value Struct Int Float).each do |type|
it "doesn't make virtual for #{type}" do
assert_type("
struct Foo < #{type}
end
struct Bar < #{type}
end
Foo.new || Bar.new
") { union_of(types["Foo"], types["Bar"]) }
end
end

@@ -136,16 +151,67 @@ describe "Type inference: struct" do
"recursive struct Foo detected: `@bar : Bar?` -> `@foo : Foo?`"
end

it "errors on recursive struct through inheritance (#2136)" do
it "can't extend struct from non-abstract struct" do
assert_error %(
struct A
struct B < A end
def initialize(@x : A::B?) end
end
a = A.new A::B.new nil
struct B < A
end
),
"recursive struct A::B detected: `@x : A::B?`"
"can't extend non-abstract struct A"
end

it "unifies type to virtual type" do
assert_type(%(
abstract struct Foo
end
struct Bar < Foo
end
ptr = Pointer(Foo).malloc(1_u64)
ptr.value = Bar.new
ptr.value
)) { types["Foo"].virtual_type! }
end

it "doesn't error if method is not found in abstract type" do
assert_type(%(
abstract struct Foo
end
struct Bar < Foo
def foo
1
end
end
struct Baz < Foo
def foo
'a'
end
end
ptr = Pointer(Foo).malloc(1_u64)
ptr.value = Bar.new
ptr.value = Baz.new
ptr.value.foo
)) { union_of(int32, char) }
end

it "can cast to base abstract struct" do
assert_type(%(
abstract struct Foo
end
struct Bar < Foo
def foo
1
end
end
Bar.new as Foo
)) { types["Foo"].virtual_type! }
end
end
Loading