require "../../spec_helper" describe "Semantic: static array" do it "types static array with var declaration" do assert_type("x = uninitialized Char[3]") { static_array_of(char, 3) } end it "types static array new" do assert_type("x = StaticArray(Char, 3).new; x") { static_array_of(char, 3) } end it "types static array with type as size" do assert_type(<<-CRYSTAL) { static_array_of(char, 1) } class Foo(N) def self.foo x = uninitialized Char[N] x end end Foo(1).foo CRYSTAL end it "errors if trying to instantiate static array with N not an integer" do assert_error <<-CRYSTAL, "can't instantiate StaticArray(T, N) with N = Int32 (N must be an integer)" x = uninitialized Char[Int32] CRYSTAL assert_error <<-CRYSTAL, StaticArray(UInt8, 1.2) CRYSTAL "can't instantiate StaticArray(T, N) with N = 1.2 (N must be an integer)" end it "allows instantiating static array instance var in initialize of generic type" do assert_type(<<-CRYSTAL) { static_array_of(char, 1) } class Foo(N) def initialize @x = uninitialized Char[N] end def x @x end end Foo(1).new.x CRYSTAL end it "errors on negative static array size" do assert_error <<-CRYSTAL, "can't instantiate StaticArray(T, N) with N = -1 (N must be positive)" x = uninitialized Int32[-1] CRYSTAL end it "types static array new with size being a constant" do assert_type(<<-CRYSTAL) { static_array_of(char, 3) } SIZE = 3 x = StaticArray(Char, SIZE).new x CRYSTAL end it "types static array new with size being a nested constant inside type declaration (#5426)" do assert_type(<<-CRYSTAL) { static_array_of(char, 3) } module Moo SIZE = 3 end class Foo @x : StaticArray(Char, Moo::SIZE) def initialize(@x) end def x @x end end Foo.new(StaticArray(Char, Moo::SIZE).new).x CRYSTAL end it "types static array new with size being a computed constant" do assert_type(<<-CRYSTAL, inject_primitives: true) { static_array_of(char, 100) } struct Int def //(other : Int) 0 end end OTHER = 10 SIZE = OTHER * 20 // 2 x = StaticArray(Char, SIZE).new x CRYSTAL end it "types static array new with size being a computed constant, and use N (bug)" do assert_type(<<-CRYSTAL, inject_primitives: true) { int32 } struct StaticArray(T, N) def size N end end SIZE = 1 * 2 x = uninitialized UInt8[SIZE] x.size a = 1 CRYSTAL end it "doesn't crash on restriction (#584)" do assert_error <<-CRYSTAL, "can't instantiate StaticArray(T, N) with N = Int32 (N must be an integer)" def foo(&block : Int32[Int32] -> Int32) block.call([0]) end foo { |x| 0 } CRYSTAL end it "can match N type argument of static array (#1203)" do assert_type(<<-CRYSTAL) { int32 } def fn(a : StaticArray(T, N)) forall T, N N end n = uninitialized StaticArray(Int32, 10) fn(n) CRYSTAL end it "can match number type argument of static array (#1203)" do assert_type(<<-CRYSTAL) { int32 } def fn(a : StaticArray(T, 10)) forall T 10 end n = uninitialized StaticArray(Int32, 10) fn(n) CRYSTAL end it "doesn't match other number type argument of static array (#1203)" do assert_error <<-CRYSTAL, "expected argument #1 to 'fn' to be StaticArray(Int32, 11), not StaticArray(Int32, 10)" def fn(a : StaticArray(T, 11)) forall T 10 end n = uninitialized StaticArray(Int32, 10) fn(n) CRYSTAL end it "doesn't crash on sizeof (#8858)" do assert_error <<-CRYSTAL, "can't use sizeof(Int32) as a generic type argument" alias BadArray = Int32[sizeof(Int32)] CRYSTAL end it "doesn't crash on instance_sizeof (#8858)" do assert_error <<-CRYSTAL, "can't use instance_sizeof(String) as a generic type argument" alias BadArray = Int32[instance_sizeof(String)] CRYSTAL end it "doesn't crash on offsetof (#8858)" do assert_error <<-CRYSTAL, "can't use offsetof(Foo, @foo) as a generic type argument" class Foo @foo : Int32 = 0 end alias BadArray = Int32[offsetof(Foo, @foo)] CRYSTAL end it "reports arithmetic overflow in static array size argument (#11746)" do assert_error <<-CRYSTAL, "Arithmetic overflow", inject_primitives: true A = 0_u64 - 1_u64 b = StaticArray(Int32, A).new CRYSTAL end end