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: eceb2d825c4b
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: 824cb8ec4647
Choose a head ref
  • 3 commits
  • 4 files changed
  • 1 contributor

Commits on Sep 3, 2016

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d6e0876 View commit details
  2. Fixed #3238: problem with generic class inheritance and new

    Ary Borenszweig committed Sep 3, 2016
    Copy the full SHA
    d6da673 View commit details
  3. Compiler: fixed incorrect initialize being generated for generic subc…

    …lass
    Ary Borenszweig committed Sep 3, 2016
    Copy the full SHA
    824cb8e View commit details
Showing with 60 additions and 3 deletions.
  1. +6 −0 spec/compiler/semantic/cast_spec.cr
  2. +33 −0 spec/compiler/semantic/new_spec.cr
  3. +2 −2 src/compiler/crystal/semantic/bindings.cr
  4. +19 −1 src/compiler/crystal/semantic/new.cr
6 changes: 6 additions & 0 deletions spec/compiler/semantic/cast_spec.cr
Original file line number Diff line number Diff line change
@@ -302,4 +302,10 @@ describe "Semantic: cast" do
Bar(Int32).new.as(Foo(Int32))
)) { generic_class("Foo", int32).virtual_type! }
end

it "doesn't cast to virtual primitive (bug)" do
assert_type(%(
1.as(Int)
)) { int32 }
end
end
33 changes: 33 additions & 0 deletions spec/compiler/semantic/new_spec.cr
Original file line number Diff line number Diff line change
@@ -191,4 +191,37 @@ describe "Semantic: new" do
),
"instance variable '@caps' of My was not initialized in all of the 'initialize' methods, rendering it nilable"
end

it "inherits initialize and new methods if doesn't define new (#3238)" do
assert_type(%(
class Foo(T)
def initialize(x : Int32)
end
def self.new(x : Char)
new(1)
end
end
class Bar < Foo(Int32)
end
Bar.new('a')
)) { types["Bar"] }
end

it "doesn't have default new for inherited class from generic type" do
assert_error %(
class Foo(T)
def initialize(x : Int32)
end
end
class Bar < Foo(Int32)
end
Bar.new
),
"wrong number of arguments for 'Bar.new' (given 0, expected 1)"
end
end
4 changes: 2 additions & 2 deletions src/compiler/crystal/semantic/bindings.cr
Original file line number Diff line number Diff line change
@@ -297,7 +297,7 @@ 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.is_a?(GenericClassType) && to_type.allowed_in_generics?
filtered_type = to_type
@upcast = true
end
@@ -328,7 +328,7 @@ 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.is_a?(GenericClassType) && to_type.allowed_in_generics?
filtered_type = to_type.virtual_type
@upcast = true
end
20 changes: 19 additions & 1 deletion src/compiler/crystal/semantic/new.cr
Original file line number Diff line number Diff line change
@@ -77,15 +77,31 @@ module Crystal
type.add_def(Def.argless_initialize)
end
else
initialize_owner = nil

initialize_methods.each do |initialize|
# If the type has `self.new()`, don't override it
if initialize.args.empty? && !initialize.yields && has_default_self_new
next
end

# Only copy initialize methods from the first ancestor that has them
if initialize_owner && initialize.owner != initialize_owner
break
end

initialize_owner = initialize.owner

new_method = initialize.expand_new_from_initialize(type)
type.metaclass.as(ModuleType).add_def(new_method)
end

# Copy non-generated `new` methods from parent to child
new_methods.each do |new_method|
next if new_method.new?

type.metaclass.as(ModuleType).add_def(new_method.clone)
end
end
else
type.as(ClassType).lookup_new_in_ancestors = true
@@ -214,7 +230,9 @@ module Crystal
Call.new(Path.global("GC"), "add_finalizer", var.clone))
exps << var.clone

Def.new("new", body: exps)
a_def = Def.new("new", body: exps)
a_def.new = true
a_def
end

def self.argless_initialize