require "../../spec_helper" describe "Semantic: multi assign" do context "without strict_multi_assign" do it "doesn't error if assigning tuple to fewer targets" do assert_type(<<-CRYSTAL) { tuple_of [int32, int32] } require "prelude" x = {1, 2, ""} a, b = x {a, b} CRYSTAL end it "doesn't error if assigning non-Indexable (#11414)" do assert_no_errors <<-CRYSTAL class Foo def [](index) end def size 3 end end a, b, c = Foo.new CRYSTAL end it "errors if assigning non-Indexable to splat (#11414)" do assert_error <<-CRYSTAL, "right-hand side of one-to-many assignment must be an Indexable, not Foo" require "prelude" class Foo def [](index) end def size 3 end end a, *b, c = Foo.new CRYSTAL end end context "strict_multi_assign" do it "errors if assigning tuple to fewer targets" do assert_error <<-CRYSTAL, "cannot assign Tuple(Int32, Int32, String) to 2 targets", flags: "strict_multi_assign" require "prelude" x = {1, 2, ""} a, b = x CRYSTAL end pending "errors if assigning tuple to more targets" do assert_error <<-CRYSTAL, "cannot assign Tuple(Int32) to 2 targets", flags: "strict_multi_assign" require "prelude" x = {1} a, b = x CRYSTAL end it "errors if assigning union of tuples to fewer targets" do assert_error <<-CRYSTAL, "cannot assign (Tuple(Int32, Int32, Int32) | Tuple(Int32, Int32, Int32, Int32)) to 2 targets", flags: "strict_multi_assign" require "prelude" x = true ? {1, 2, 3} : {4, 5, 6, 7} a, b = x CRYSTAL end it "doesn't error if some type in union matches target count" do assert_type(<<-CRYSTAL, flags: "strict_multi_assign") { tuple_of [int32, union_of(int32, string)] } require "prelude" x = true ? {1, "", 3} : {4, 5} a, b = x {a, b} CRYSTAL end it "doesn't error if some type in union has no constant size" do assert_type(<<-CRYSTAL, flags: "strict_multi_assign") { tuple_of [int32, union_of(int32, string)] } require "prelude" x = true ? {1, "", 3} : [4, 5] a, b = x {a, b} CRYSTAL end it "errors if assigning non-Indexable (#11414)" do assert_error <<-CRYSTAL, "right-hand side of one-to-many assignment must be an Indexable, not Foo", flags: "strict_multi_assign" require "prelude" class Foo def [](index) end def size 3 end end a, b, c = Foo.new CRYSTAL end it "errors if assigning non-Indexable to splat (#11414)" do assert_error <<-CRYSTAL, "right-hand side of one-to-many assignment must be an Indexable, not Foo", flags: "strict_multi_assign" require "prelude" class Foo def [](index) end def size 3 end end a, *b, c = Foo.new CRYSTAL end end it "can pass splat variable at top-level to macros (#11596)" do assert_type(<<-CRYSTAL) { tuple_of [int32, int32, int32] } struct Tuple def self.new(*args) args end end macro foo(x) {{ x }} end a, *b, c = 1, 2, 3, 4, 5 foo(b) CRYSTAL end end