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: a49aef7f4526
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: 963c6d22df4c
Choose a head ref
  • 2 commits
  • 6 files changed
  • 1 contributor

Commits on Aug 11, 2016

  1. Compiler: simplify some Type includes, and removed InheritableClass m…

    …odule
    Ary Borenszweig committed Aug 11, 2016
    Copy the full SHA
    9b273a7 View commit details
  2. Fixed #3134: Inconsistent override for non-typed splats

    Ary Borenszweig committed Aug 11, 2016
    Copy the full SHA
    963c6d2 View commit details
28 changes: 28 additions & 0 deletions spec/compiler/semantic/double_splat_spec.cr
Original file line number Diff line number Diff line change
@@ -202,4 +202,32 @@ describe "Semantic: double splat" do
test(x: 7)
)) { named_tuple_of({} of String => Type) }
end

it "matches typed before non-typed (1) (#3134)" do
assert_type(%(
def bar(**args)
"free"
end
def bar(**args : Int32)
1
end
{bar(x: 1, y: 2), bar(x: 'a', y: 1)}
)) { tuple_of([int32, string]) }
end

it "matches typed before non-typed (1) (#3134)" do
assert_type(%(
def bar(**args : Int32)
1
end
def bar(**args)
"free"
end
{bar(x: 1, y: 2), bar(x: 'a', y: 1)}
)) { tuple_of([int32, string]) }
end
end
28 changes: 28 additions & 0 deletions spec/compiler/semantic/splat_spec.cr
Original file line number Diff line number Diff line change
@@ -499,6 +499,34 @@ describe "Semantic: splat" do
)) { tuple_of([int32, int32]) }
end

it "matches typed before non-typed (1) (#3134)" do
assert_type(%(
def bar(*args)
"free"
end
def bar(*args : Int32)
1
end
{bar(1, 2), bar('a', 1)}
)) { tuple_of([int32, string]) }
end

it "matches typed before non-typed (1) (#3134)" do
assert_type(%(
def bar(*args : Int32)
1
end
def bar(*args)
"free"
end
{bar(1, 2), bar('a', 1)}
)) { tuple_of([int32, string]) }
end

describe Splat do
it "without splat" do
a_def = Def.new("foo", args: [Arg.new("x"), Arg.new("y")])
2 changes: 2 additions & 0 deletions src/compiler/crystal/program.cr
Original file line number Diff line number Diff line change
@@ -20,6 +20,8 @@ module Crystal
# can also include other modules (this happens when you do `include Module`
# at the top-level).
class Program < NonGenericModuleType
include DefInstanceContainer

# All symbols (:foo, :bar) found in the program
getter symbols = Set(String).new

18 changes: 15 additions & 3 deletions src/compiler/crystal/semantic/restrictions.cr
Original file line number Diff line number Diff line change
@@ -114,9 +114,18 @@ module Crystal
if self_splat_index == other_splat_index
self_arg = self.def.args[self_splat_index]
other_arg = other.def.args[other_splat_index]
self_restriction = self_arg.restriction
other_restriction = other_arg.restriction

if (self_restriction = self_arg.restriction) && (other_restriction = other_arg.restriction)
if self_restriction && other_restriction
# If both splat have restrictions, check which one is stricter
return false unless self_restriction.restriction_of?(other_restriction, owner)
elsif self_restriction
# If only self has a restriction, it's stricter than the other
return true
elsif other_restriction
# If only the other has a restriction, it's stricter than self
return false
end
elsif self_splat_index < other_splat_index
return false
@@ -159,12 +168,15 @@ module Crystal
self_double_splat_restriction = self.def.double_splat.try &.restriction
other_double_splat_restriction = other.def.double_splat.try &.restriction

# If both double splat have restrictions, check which one is stricter
if self_double_splat_restriction && other_double_splat_restriction
return false unless self_double_splat_restriction.restriction_of?(other_double_splat_restriction, owner)
elsif self_double_splat_restriction
true
# If only self has a restriction, it's stricter than the other
return true
elsif other_double_splat_restriction
false
# If only the other has a restriction, it's stricter than self
return false
end

true
1 change: 0 additions & 1 deletion src/compiler/crystal/semantic/top_level_visitor.cr
Original file line number Diff line number Diff line change
@@ -149,7 +149,6 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor
end

if created_new_type
raise "Bug" unless type.is_a?(InheritableClass)
type.force_add_subclass
end

37 changes: 15 additions & 22 deletions src/compiler/crystal/types.cr
Original file line number Diff line number Diff line change
@@ -787,21 +787,6 @@ module Crystal
end
end

module InheritableClass
include SubclassObservable

def add_subclass(subclass)
subclasses << subclass
notify_subclass_added

superclass = superclass()
while superclass
superclass.notify_subclass_added
superclass = superclass.superclass
end
end
end

module InstanceVarInitializerContainer
class InstanceVarInitializer
getter name : String
@@ -828,7 +813,6 @@ module Crystal
end

class NonGenericModuleType < ModuleType
include DefInstanceContainer
include ClassVarContainer
include SubclassObservable

@@ -924,6 +908,8 @@ module Crystal

# A module that is related to a file and contains its private defs.
class FileModule < NonGenericModuleType
include DefInstanceContainer

getter(vars) { MetaVars.new }

def vars?
@@ -932,7 +918,8 @@ module Crystal
end

abstract class ClassType < ModuleType
include InheritableClass
include DefInstanceContainer
include SubclassObservable
include InstanceVarInitializerContainer

getter superclass : Type?
@@ -954,6 +941,17 @@ module Crystal
force_add_subclass if add_subclass
end

def add_subclass(subclass)
subclasses << subclass
notify_subclass_added

superclass = superclass()
while superclass
superclass.notify_subclass_added
superclass = superclass.superclass
end
end

def force_add_subclass
superclass.try &.add_subclass(self)
end
@@ -1080,7 +1078,6 @@ module Crystal
class NonGenericClassType < ClassType
include InstanceVarContainer
include ClassVarContainer
include DefInstanceContainer

def initialize_metaclass(metaclass)
metaclass.add_def Def.new("allocate", body: Primitive.new("allocate"))
@@ -1138,7 +1135,6 @@ module Crystal
end

class PrimitiveType < ClassType
include DefInstanceContainer
include ClassVarContainer

getter bytes : Int32
@@ -1395,7 +1391,6 @@ module Crystal

class GenericClassType < ClassType
include GenericType
include DefInstanceContainer

def initialize(program, namespace, name, superclass, @type_vars : Array(String), add_subclass = true)
super(program, namespace, name, superclass, add_subclass)
@@ -1491,7 +1486,6 @@ module Crystal
end

class GenericClassInstanceType < Type
include InheritableClass
include InstanceVarContainer
include InstanceVarInitializerContainer
include ClassVarContainer
@@ -2161,7 +2155,6 @@ module Crystal
end

class MetaclassType < ClassType
include DefInstanceContainer
include ClassVarContainer
include InstanceVarContainer