require "../../spec_helper" describe "Semantic: NoReturn" do it "types call to LibC.exit as NoReturn" do assert_type("lib LibC; fun exit : NoReturn; end; LibC.exit") { no_return } end it "types raise as NoReturn" do assert_type("require \"prelude\"; raise \"foo\"") { no_return } end it "types union of NoReturn and something else" do assert_type("lib LibC; fun exit : NoReturn; end; 1 == 1 ? LibC.exit : 1", inject_primitives: true) { int32 } end it "types union of NoReturns" do assert_type("lib LibC; fun exit : NoReturn; end; 1 == 2 ? LibC.exit : LibC.exit", inject_primitives: true) { no_return } end it "types with no return even if code follows" do assert_type("lib LibC; fun exit : NoReturn; end; LibC.exit; 1") { no_return } end it "assumes if condition's type filters when else is no return" do assert_type(<<-CRYSTAL) { int32 } lib LibC fun exit : NoReturn end class Foo def foo 1 end end foo = Foo.new || nil LibC.exit unless foo foo.foo CRYSTAL end it "computes NoReturn in a lazy way inside if then (#314) (1)" do assert_type(<<-CRYSTAL) { union_of(int32, string) } require "prelude" a = 1 b = 1 x = nil while a < 10 if a == 2 b = "hello" x.not_nil! end x = 1 a += 1 end b CRYSTAL end it "computes NoReturn in a lazy way inside if then (#314) (2)" do assert_type(<<-CRYSTAL) { int32 } require "prelude" a = 1 b = 1 x = nil while a < 10 if a == 2 b = "hello" x.not_nil! end a += 1 end b CRYSTAL end it "computes NoReturn in a lazy way inside if then (#314) (3)" do assert_type(<<-CRYSTAL) { nilable(string) } require "prelude" a = 1 c = nil x = nil while a < 10 if a == 2 b = "hello" x.not_nil! end if b c = b end x = 1 a += 1 end c CRYSTAL end it "computes NoReturn in a lazy way inside if then (#314) (4)" do assert_type(<<-CRYSTAL) { nil_type } require "prelude" a = 1 c = nil x = nil while a < 10 if a == 2 b = "hello" x.not_nil! end if b c = b end a += 1 end c CRYSTAL end it "computes NoReturn in a lazy way inside if then (#314) (5)" do assert_error <<-CRYSTAL, "undefined method 'size' for Nil" require "prelude" a = 1 x = nil while a < 10 if a == 1 x.not_nil! else b = "hello" end b.size b = nil x = 1 a += 1 end CRYSTAL end it "computes NoReturn in a lazy way inside if else (#314) (1)" do assert_type(<<-CRYSTAL) { union_of(int32, string) } require "prelude" a = 1 b = 1 x = nil while a < 10 if a == 2 else b = "hello" x.not_nil! end x = 1 a += 1 end b CRYSTAL end it "computes NoReturn in a lazy way inside if else (#314) (2)" do assert_type(<<-CRYSTAL) { int32 } require "prelude" a = 1 b = 1 x = nil while a < 10 if a == 2 else b = "hello" x.not_nil! end a += 1 end b CRYSTAL end it "computes NoReturn in a lazy way inside if else (#314) (3)" do assert_type(<<-CRYSTAL) { nilable(string) } require "prelude" a = 1 c = nil x = nil while a < 10 if a == 2 else b = "hello" x.not_nil! end if b c = b end x = 1 a += 1 end c CRYSTAL end it "computes NoReturn in a lazy way inside if else (#314) (4)" do assert_type(<<-CRYSTAL) { nil_type } require "prelude" a = 1 c = nil x = nil while a < 10 if a == 2 else b = "hello" x.not_nil! end if b c = b end a += 1 end c CRYSTAL end it "computes NoReturn in a lazy way inside if else (#314) (5)" do assert_error <<-CRYSTAL, "undefined method 'size' for Nil" require "prelude" a = 1 x = nil while a < 10 if a == 1 b = "hello" else x.not_nil! end b.size b = nil x = 1 a += 1 end CRYSTAL end it "types exception handler as NoReturn if ensure is NoReturn" do assert_type(<<-CRYSTAL) { no_return } lib LibC fun foo : NoReturn end begin 1 ensure LibC.foo end CRYSTAL end it "types as NoReturn even if Nil return type is forced (#3096)" do assert_type(<<-CRYSTAL) { int32 } lib LibC fun exit(Int32) : NoReturn end def foo : Nil LibC.exit(0) yield end def bar(x) x end def baz foo { } bar 0 end baz CRYSTAL end it "types as NoReturn if typeof(exp)'s exp is NoReturn" do assert_type(<<-CRYSTAL) { no_return.metaclass } require "prelude" typeof(raise("").foo) CRYSTAL end it "types as NoReturn if followed by one-to-many assignment (#15638)" do assert_type(<<-CRYSTAL) { bool } def foo(x) {'a', ""} end def raise(msg) while true end end def bar x = 1 return true if x.is_a?(Int32) a, b = foo(x) end bar CRYSTAL end end