diff --git a/spec/compiler/codegen/splat_spec.cr b/spec/compiler/codegen/splat_spec.cr index 77454eb49123fb283f09975ff4aaf7187a7223dd..63dd1bd7fe6a57a68a1f9054250dc38faebfe730 100644 --- a/spec/compiler/codegen/splat_spec.cr +++ b/spec/compiler/codegen/splat_spec.cr @@ -42,4 +42,14 @@ describe "Code gen: splat" do foo *tuple )).to_i.should eq(3) end + + it "splats without args" do + run(%( + def foo(*args) + args.length + end + + foo + )).to_i.should eq(0) + end end diff --git a/spec/compiler/normalize/def_spec.cr b/spec/compiler/normalize/def_spec.cr index 2ad03918a56987dc618265727a76e8f0ce3d958a..1fc55461e4ebcd8dbd86a16ca902c39bc1d034e2 100644 --- a/spec/compiler/normalize/def_spec.cr +++ b/spec/compiler/normalize/def_spec.cr @@ -71,4 +71,10 @@ describe "Normalize: def" do expected = parse("def foo(x, _arg0, z)\n args = {_arg0}\n args\nend") actual.should eq(expected) end + + it "expands with splat and zero" do + a_def = parse("def foo(*args); args; end") as Def + actual = a_def.expand_default_arguments(0) + actual.to_s.should eq("def foo\n args = {}\n args\nend") + end end diff --git a/src/compiler/crystal/type_inference.cr b/src/compiler/crystal/type_inference.cr index d80ac7721256fc0d5cc934185ad9d4650f920508..ca8f9a4c7156a93aae365e233f165dd9caa9b2da 100644 --- a/src/compiler/crystal/type_inference.cr +++ b/src/compiler/crystal/type_inference.cr @@ -2197,6 +2197,7 @@ module Crystal def end_visit(node : TupleLiteral) node.elements.each &.add_observer(node) + node.mod = @mod node.update false end diff --git a/src/compiler/crystal/type_inference/ast.cr b/src/compiler/crystal/type_inference/ast.cr index 79ba48397da5441e6f4cb19d38bf83aef8bb2d60..43bf54f077483b2b3702a92c1e8bce51467d5107 100644 --- a/src/compiler/crystal/type_inference/ast.cr +++ b/src/compiler/crystal/type_inference/ast.cr @@ -260,12 +260,14 @@ module Crystal end class TupleLiteral + property! :mod + def update(from = nil) return unless elements.all? &.type? types = [] of Type | ASTNode elements.each { |exp| types << exp.type } - self.type = elements.first.type.program.tuple_of types + self.type = mod.tuple_of types end end @@ -345,8 +347,10 @@ module Crystal new_body << Assign.new(Var.new(args[splat_index].name), tuple) end - args[args_length .. -1].each do |arg| - new_body << Assign.new(Var.new(arg.name), arg.default_value.not_nil!) + if splat_index == -1 + args[args_length .. -1].each do |arg| + new_body << Assign.new(Var.new(arg.name), arg.default_value.not_nil!) + end end new_body.push body.clone