diff --git a/bootstrap/crystal/codegen.cr b/bootstrap/crystal/codegen.cr
index c20e9ef8f4e54427ff5eda48ee80e9adf0c4a39a..7e5880d6d6aaa4eb83e445d753c55b7e1a143be1 100644
--- a/bootstrap/crystal/codegen.cr
+++ b/bootstrap/crystal/codegen.cr
@@ -1737,7 +1737,12 @@ module Crystal
         end
       end
 
-      if node.name == "super"
+      if !node.target_defs || node.target_def.owner.try &.is_subclass_of?(@mod.value)
+        if node_obj = node.obj
+          owner = node_obj.type?
+        end
+        owner ||= node.scope
+      elsif node.name == "super"
         owner = node.scope
       else
         owner = node.target_def.owner
@@ -1778,6 +1783,8 @@ module Crystal
         end
       end
 
+      return if node.args.any?(&.yields?) && block_breaks?
+
       if block = node.block
         @block_context << BlockContext.new(block, @vars, @type, @return_block, @return_block_table_blocks, @return_block_table_values, @return_type, @return_union)
         @vars = {} of String => LLVMVar
diff --git a/bootstrap/spec/crystal/codegen/block_spec.cr b/bootstrap/spec/crystal/codegen/block_spec.cr
index 06e8541f93c7b347057d17715fdf859d702cb37d..3e5a4055d10da2c04c9af604c0546b01aa1d1f11 100755
--- a/bootstrap/spec/crystal/codegen/block_spec.cr
+++ b/bootstrap/spec/crystal/codegen/block_spec.cr
@@ -184,524 +184,527 @@ describe "Code gen: block" do
     ").to_i.should eq(1)
   end
 
-  # it "return from yielder function" do
-  #   run(%q(
-  #     def foo
-  #       yield
-  #       return 1
-  #     end
-
-  #     foo { }
-  #     2
-  #   )).to_i.should eq(2)
-  # end
-
-  # it "return from block" do
-  #   run(%q(
-  #     def foo
-  #       yield
-  #     end
-
-  #     def bar
-  #       foo { return 1 }
-  #       2
-  #     end
-
-  #     bar
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "return from yielder function (2)" do
-  #   run(%q(
-  #     def foo
-  #       yield
-  #       return 1 if true
-  #       return 2
-  #     end
-
-  #     def bar
-  #       foo {}
-  #     end
-
-  #     bar
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "union value of yielder function" do
-  #   run(%q(
-  #     def foo
-  #       yield
-  #       a = 1.1
-  #       a = 1
-  #       a
-  #     end
-
-  #     foo {}.to_i
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "allow return from function called from yielder function" do
-  #   run(%q(
-  #     def foo
-  #       return 2
-  #     end
-
-  #     def bar
-  #       yield
-  #       foo
-  #       1
-  #     end
-
-  #     bar {}
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "" do
-  #   run(%q(
-  #     def foo
-  #       yield
-  #       true ? return 1 : return 1.1
-  #     end
-
-  #     foo {}.to_i
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "return from block that always returns from function that always yields inside if block" do
-  #   run(%q(
-  #     def bar
-  #       yield
-  #       2
-  #     end
-
-  #     def foo
-  #       if true
-  #         bar { return 1 }
-  #       else
-  #         0
-  #       end
-  #     end
-
-  #     foo
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "return from block that always returns from function that conditionally yields" do
-  #   run(%q(
-  #     def bar
-  #       if true
-  #         yield
-  #       end
-  #     end
-
-  #     def foo
-  #       bar { return 1 }
-  #       2
-  #     end
-
-  #     foo
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "call block from dispatch" do
-  #   run(%q(
-  #     def bar(y)
-  #       yield y
-  #     end
-
-  #     def foo
-  #       x = 1.1
-  #       x = 1
-  #       bar(x) { |z| z }
-  #     end
-
-  #     foo.to_i
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "call block from dispatch and use local vars" do
-  #   run(%q(
-  #     def bar(y)
-  #       yield y
-  #     end
-
-  #     def foo
-  #       total = 0
-  #       x = 1.5
-  #       bar(x) { |z| total += z }
-  #       x = 1
-  #       bar(x) { |z| total += z }
-  #       x = 1.5
-  #       bar(x) { |z| total += z }
-  #       total
-  #     end
-
-  #     foo.to_i
-  #   )).to_i.should eq(4)
-  # end
-
-  # it "break without value returns nil" do
-  #   run(%q(
-  #     require "nil"
-
-  #     def foo
-  #       yield
-  #       1
-  #     end
-
-  #     x = foo do
-  #       break if true
-  #     end
-
-  #     x.nil?
-  #   )).to_b.should be_true
-  # end
-
-  # it "break block with yielder inside while" do
-  #   run(%q(
-  #     require "int"
-  #     a = 0
-  #     10.times do
-  #       a += 1
-  #       break if a > 5
-  #     end
-  #     a
-  #   )).to_i.should eq(6)
-  # end
-
-  # it "break from block returns from yielder" do
-  #   run(%q(
-  #     def foo
-  #       yield
-  #       yield
-  #     end
-
-  #     a = 0
-  #     foo { a += 1; break }
-  #     a
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "break from block with value" do
-  #   run(%q(
-  #     def foo
-  #       while true
-  #         yield
-  #         a = 3
-  #       end
-  #     end
-
-  #     foo do
-  #       break 1
-  #     end
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "break from block with value" do
-  #   run(%q(
-  #     require "nil"
-
-  #     def foo
-  #       while true
-  #         yield
-  #         a = 3
-  #       end
-  #     end
-
-  #     def bar
-  #       foo do
-  #         return 1
-  #       end
-  #     end
-
-  #     bar.to_i
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "doesn't codegen after while that always yields and breaks" do
-  #   run(%q(
-  #     def foo
-  #       while true
-  #         yield
-  #       end
-  #       1
-  #     end
-
-  #     foo do
-  #       break 2
-  #     end
-  #   )).to_i.should eq(2)
-  # end
-
-  # pending "break from block with value" do
-  #   run(%q(
-  #     require "int"
-  #     10.times { break 20 }
-  #   )).to_i.should eq(20)
-  # end
-
-  # it "doesn't codegen call if arg yields and always breaks" do
-  #   run(%q(
-  #     require "nil"
-
-  #     def foo
-  #       1 + yield
-  #     end
-
-  #     foo { break 2 }.to_i
-  #   )).to_i.should eq(2)
-  # end
-
-  # it "codegens nested return" do
-  #   run(%q(
-  #     def bar
-  #       yield
-  #       a = 1
-  #     end
-
-  #     def foo
-  #       bar { yield }
-  #     end
-
-  #     def z
-  #       foo { return 2 }
-  #     end
-
-  #     z
-  #   )).to_i.should eq(2)
-  # end
-
-  # it "codegens nested break" do
-  #   run(%q(
-  #     def bar
-  #       yield
-  #       a = 1
-  #     end
-
-  #     def foo
-  #       bar { yield }
-  #     end
-
-  #     foo { break 2 }
-  #   )).to_i.should eq(2)
-  # end
-
-  # it "codegens call with block with call with arg that yields" do
-  #   run(%q(
-  #     def bar
-  #       yield
-  #       a = 2
-  #     end
-
-  #     def foo
-  #       bar { 1 + yield }
-  #     end
-
-  #     foo { break 3 }
-  #   )).to_i.should eq(3)
-  # end
-
-  # it "can break without value from yielder that returns nilable" do
-  #   run(%q(
-  #     require "nil"
-  #     require "reference"
-
-  #     def foo
-  #       yield
-  #       ""
-  #     end
-
-  #     a = foo do
-  #       break
-  #     end
-
-  #     a.nil?
-  #   )).to_b.should be_true
-  # end
-
-  # it "break with value from yielder that returns a nilable" do
-  #   run(%q(
-  #     require "nil"
-  #     require "reference"
-
-  #     def foo
-  #       yield
-  #       ""
-  #     end
-
-  #     a = foo do
-  #       break if false
-  #       break ""
-  #     end
-
-  #     a.nil?
-  #   )).to_b.should be_false
-  # end
-
-  # it "can use self inside a block called from dispatch" do
-  #   run(%q(
-  #     require "nil"
-
-  #     class Foo
-  #       def do; yield; end
-  #     end
-  #     class Bar < Foo
-  #     end
-
-
-  #     class Int
-  #       def foo
-  #         x = Foo.new
-  #         x = Bar.new
-  #         x.do { $x = self }
-  #       end
-  #     end
-
-  #     123.foo
-  #     $x.to_i
-  #   )).to_i.should eq(123)
-  # end
-
-  # it "return from block called from dispatch" do
-  #   run(%q(
-  #     class Foo
-  #       def do; yield; end
-  #     end
-  #     class Bar < Foo
-  #     end
-
-  #     def foo
-  #       x = Foo.new
-  #       x = Bar.new
-  #       x.do { return 1 }
-  #       0
-  #     end
-
-  #     foo
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "breaks from while in function called from block" do
-  #   run(%q(
-  #     def foo
-  #       yield
-  #     end
-
-  #     def bar
-  #       while true
-  #         break 1
-  #       end
-  #       2
-  #     end
-
-  #     foo do
-  #       bar
-  #     end
-  #   )).to_i.should eq(2)
-  # end
-
-  # it "allows modifying yielded value (with literal)" do
-  #   run(%q(
-  #     def foo
-  #       yield 1
-  #     end
-
-  #     foo { |x| x = 2; x }
-  #   )).to_i.should eq(2)
-  # end
-
-  # it "allows modifying yielded value (with variable)" do
-  #   run(%q(
-  #     def foo
-  #       a = 1
-  #       yield a
-  #       a
-  #     end
-
-  #     foo { |x| x = 2; x }
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "it yields nil from another call" do
-  #   run(%q(
-  #     def foo(key, default)
-  #       foo(key) { default }
-  #     end
-
-  #     def foo(key)
-  #       if !(true)
-  #         return yield key
-  #       end
-  #       yield key
-  #     end
-
-  #     foo(1, nil)
-  #   ))
-  # end
-
-  # it "allows yield from dispatch call" do
-  #   run(%q(
-  #     def foo(x : Value)
-  #       yield 1
-  #     end
-
-  #     def foo(x : Int)
-  #       yield 2
-  #     end
-
-  #     def bar
-  #       a = 1; a = 1.1
-  #       foo(a) do |i|
-  #         yield i
-  #       end
-  #     end
-
-  #     x = 0
-  #     bar { |i| x = i }
-  #     x
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "block with nilable type" do
-  #   run(%q(
-  #     class Foo
-  #       def foo
-  #         yield 1
-  #       end
-  #     end
-
-  #     class Bar
-  #       def foo
-  #         yield 2
-  #         Reference.new
-  #       end
-  #     end
-
-  #     a = Foo.new || Bar.new
-  #     a.foo {}
-  #   ))
-  # end
-
-  # it "block with nilable type 2" do
-  #   run(%q(
-  #     class Foo
-  #       def foo
-  #         yield 1
-  #         nil
-  #       end
-  #     end
-
-  #     class Bar
-  #       def foo
-  #         yield 2
-  #         Reference.new
-  #       end
-  #     end
-
-  #     a = Foo.new || Bar.new
-  #     a.foo {}
-  #   ))
-  # end
+  it "return from yielder function" do
+    run("
+      def foo
+        yield
+        return 1
+      end
+
+      foo { }
+      2
+    ").to_i.should eq(2)
+  end
+
+  it "return from block" do
+    run("
+      def foo
+        yield
+      end
+
+      def bar
+        foo { return 1 }
+        2
+      end
+
+      bar
+    ").to_i.should eq(1)
+  end
+
+  it "return from yielder function (2)" do
+    run("
+      def foo
+        yield
+        return 1 if true
+        return 2
+      end
+
+      def bar
+        foo {}
+      end
+
+      bar
+    ").to_i.should eq(1)
+  end
+
+  it "union value of yielder function" do
+    run("
+      def foo
+        yield
+        a = 1.1
+        a = 1
+        a
+      end
+
+      foo {}.to_i
+    ").to_i.should eq(1)
+  end
+
+  it "allow return from function called from yielder function" do
+    run("
+      def foo
+        return 2
+      end
+
+      def bar
+        yield
+        foo
+        1
+      end
+
+      bar {}
+    ").to_i.should eq(1)
+  end
+
+  it "" do
+    run("
+      def foo
+        yield
+        true ? return 1 : return 1.1
+      end
+
+      foo {}.to_i
+    ").to_i.should eq(1)
+  end
+
+  it "return from block that always returns from function that always yields inside if block" do
+    run("
+      def bar
+        yield
+        2
+      end
+
+      def foo
+        if true
+          bar { return 1 }
+        else
+          0
+        end
+      end
+
+      foo
+    ").to_i.should eq(1)
+  end
+
+  it "return from block that always returns from function that conditionally yields" do
+    run("
+      def bar
+        if true
+          yield
+        end
+      end
+
+      def foo
+        bar { return 1 }
+        2
+      end
+
+      foo
+    ").to_i.should eq(1)
+  end
+
+  it "call block from dispatch" do
+    run("
+      def bar(y)
+        yield y
+      end
+
+      def foo
+        x = 1.1
+        x = 1
+        bar(x) { |z| z }
+      end
+
+      foo.to_i
+    ").to_i.should eq(1)
+  end
+
+  it "call block from dispatch and use local vars" do
+    run("
+      def bar(y)
+        yield y
+      end
+
+      def foo
+        total = 0
+        x = 1.5
+        bar(x) { |z| total += z }
+        x = 1
+        bar(x) { |z| total += z }
+        x = 1.5
+        bar(x) { |z| total += z }
+        total
+      end
+
+      foo.to_i
+    ").to_i.should eq(4)
+  end
+
+  it "break without value returns nil" do
+    run("
+      require \"nil\"
+      require \"value\"
+
+      def foo
+        yield
+        1
+      end
+
+      x = foo do
+        break if 1 == 1
+      end
+
+      x.nil?
+    ").to_b.should be_true
+  end
+
+  it "break block with yielder inside while" do
+    run("
+      require \"int\"
+      a = 0
+      10.times do
+        a += 1
+        break if a > 5
+      end
+      a
+    ").to_i.should eq(6)
+  end
+
+  it "break from block returns from yielder" do
+    run("
+      def foo
+        yield
+        yield
+      end
+
+      a = 0
+      foo { a += 1; break }
+      a
+    ").to_i.should eq(1)
+  end
+
+  it "break from block with value" do
+    run("
+      def foo
+        while true
+          yield
+          a = 3
+        end
+      end
+
+      foo do
+        break 1
+      end
+    ").to_i.should eq(1)
+  end
+
+  it "break from block with value" do
+    run("
+      require \"nil\"
+
+      def foo
+        while true
+          yield
+          a = 3
+        end
+      end
+
+      def bar
+        foo do
+          return 1
+        end
+      end
+
+      bar.to_i
+    ").to_i.should eq(1)
+  end
+
+  it "doesn't codegen after while that always yields and breaks" do
+    run("
+      def foo
+        while true
+          yield
+        end
+        1
+      end
+
+      foo do
+        break 2
+      end
+    ").to_i.should eq(2)
+  end
+
+  pending "break from block with value" do
+    run("
+      require \"int\"
+      10.times { break 20 }
+    ").to_i.should eq(20)
+  end
+
+  it "doesn't codegen call if arg yields and always breaks" do
+    run("
+      require \"nil\"
+
+      def foo
+        1 + yield
+      end
+
+      foo { break 2 }.to_i
+    ").to_i.should eq(2)
+  end
+
+  it "codegens nested return" do
+    run("
+      def bar
+        yield
+        a = 1
+      end
+
+      def foo
+        bar { yield }
+      end
+
+      def z
+        foo { return 2 }
+      end
+
+      z
+    ").to_i.should eq(2)
+  end
+
+  it "codegens nested break" do
+    run("
+      def bar
+        yield
+        a = 1
+      end
+
+      def foo
+        bar { yield }
+      end
+
+      foo { break 2 }
+    ").to_i.should eq(2)
+  end
+
+  it "codegens call with block with call with arg that yields" do
+    run("
+      def bar
+        yield
+        a = 2
+      end
+
+      def foo
+        bar { 1 + yield }
+      end
+
+      foo { break 3 }
+    ").to_i.should eq(3)
+  end
+
+  it "can break without value from yielder that returns nilable" do
+    run("
+      require \"nil\"
+      require \"reference\"
+
+      def foo
+        yield
+        \"\"
+      end
+
+      a = foo do
+        break
+      end
+
+      a.nil?
+    ").to_b.should be_true
+  end
+
+  it "break with value from yielder that returns a nilable" do
+    run("
+      require \"nil\"
+      require \"reference\"
+
+      def foo
+        yield
+        \"\"
+      end
+
+      a = foo do
+        break if false
+        break \"\"
+      end
+
+      a.nil?
+    ").to_b.should be_false
+  end
+
+  it "can use self inside a block called from dispatch" do
+    run("
+      require \"nil\"
+
+      class Foo
+        def do; yield; end
+      end
+      class Bar < Foo
+      end
+
+
+      class Int
+        def foo
+          x = Foo.new
+          x = Bar.new
+          x.do { $x = self }
+        end
+      end
+
+      123.foo
+      $x.to_i
+    ").to_i.should eq(123)
+  end
+
+  it "return from block called from dispatch" do
+    run("
+      class Foo
+        def do; yield; end
+      end
+      class Bar < Foo
+      end
+
+      def foo
+        x = Foo.new
+        x = Bar.new
+        x.do { return 1 }
+        0
+      end
+
+      foo
+    ").to_i.should eq(1)
+  end
+
+  it "breaks from while in function called from block" do
+    run("
+      def foo
+        yield
+      end
+
+      def bar
+        while true
+          break 1
+        end
+        2
+      end
+
+      foo do
+        bar
+      end
+    ").to_i.should eq(2)
+  end
+
+  it "allows modifying yielded value (with literal)" do
+    run("
+      def foo
+        yield 1
+      end
+
+      foo { |x| x = 2; x }
+    ").to_i.should eq(2)
+  end
+
+  it "allows modifying yielded value (with variable)" do
+    run("
+      def foo
+        a = 1
+        yield a
+        a
+      end
+
+      foo { |x| x = 2; x }
+    ").to_i.should eq(1)
+  end
+
+  it "it yields nil from another call" do
+    run("
+      require \"bool\"
+
+      def foo(key, default)
+        foo(key) { default }
+      end
+
+      def foo(key)
+        if !(true)
+          return yield key
+        end
+        yield key
+      end
+
+      foo(1, nil)
+    ")
+  end
+
+  it "allows yield from dispatch call" do
+    run("
+      def foo(x : Value)
+        yield 1
+      end
+
+      def foo(x : Int)
+        yield 2
+      end
+
+      def bar
+        a = 1; a = 1.1
+        foo(a) do |i|
+          yield i
+        end
+      end
+
+      x = 0
+      bar { |i| x = i }
+      x
+    ").to_i.should eq(1)
+  end
+
+  it "block with nilable type" do
+    run("
+      class Foo
+        def foo
+          yield 1
+        end
+      end
+
+      class Bar
+        def foo
+          yield 2
+          Reference.new
+        end
+      end
+
+      a = Foo.new || Bar.new
+      a.foo {}
+    ")
+  end
+
+  it "block with nilable type 2" do
+    run("
+      class Foo
+        def foo
+          yield 1
+          nil
+        end
+      end
+
+      class Bar
+        def foo
+          yield 2
+          Reference.new
+        end
+      end
+
+      a = Foo.new || Bar.new
+      a.foo {}
+    ")
+  end
 
   it "allows yields with less arguments than in block" do
     run("
@@ -723,167 +726,168 @@ describe "Code gen: block" do
       ").to_i.should eq(1)
   end
 
-  # it "codegens block with nilable type with return" do
-  #   run(%q(
-  #     def foo
-  #       if yield
-  #         return Reference.new
-  #       end
-  #       nil
-  #     end
-
-  #     foo { false }
-  #     ))
-  # end
-
-  # it "codegens block with union with return" do
-  #   run(%q(
-  #     def foo
-  #       yield
-
-  #       return 1 if 1 == 2
-
-  #       nil
-  #     end
-
-  #     foo { }
-  #     ))
-  # end
-
-  # it "codegens if with call with block (ssa issue)" do
-  #   run(%q(
-  #     def bar
-  #       yield
-  #     end
-
-  #     def foo
-  #       if 1 == 2
-  #         bar do
-  #           x = 1
-  #         end
-  #       else
-  #         3
-  #       end
-  #     end
-
-  #     foo
-  #     )).to_i.should eq(3)
-  # end
-
-  # it "codegens block with return and yield and no return" do
-  #   run(%q(
-  #     lib C
-  #       fun exit : NoReturn
-  #     end
-
-  #     def foo(key)
-  #       foo(key) { C.exit }
-  #     end
-
-  #     def foo(key)
-  #       if 1 == 1
-  #         return 2
-  #       end
-  #       yield
-  #     end
-
-  #     foo 1
-  #     )).to_i.should eq(2)
-  # end
-
-  # it "codegens while/break inside block" do
-  #   run(%q(
-  #     def foo
-  #       yield
-  #     end
-
-  #     foo do
-  #       while true
-  #         break
-  #       end
-  #       1
-  #     end
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "codegens block with union arg" do
-  #   run(%q(
-  #     class Number
-  #       def abs
-  #         self
-  #       end
-  #     end
-
-  #     class Foo(T)
-  #       def initialize(x : T)
-  #         @x = x
-  #       end
-
-  #       def each
-  #         yield @x
-  #       end
-  #     end
-
-  #     a = Foo.new(1) || Foo.new(1.5)
-  #     a.each do |x|
-  #       x.abs
-  #     end.to_i
-  #     )).to_i.should eq(1)
-  # end
-
-  # it "codegens block with hierarchy type arg" do
-  #   run(%q(
-  #     class Var(T)
-  #       def initialize(x : T)
-  #         @x = x
-  #       end
-
-  #       def each
-  #         yield @x
-  #       end
-  #     end
-
-  #     class Foo
-  #       def bar
-  #         1
-  #       end
-  #     end
-
-  #     class Bar < Foo
-  #       def bar
-  #         2
-  #       end
-  #     end
-
-  #     a = Var.new(Foo.new) || Var.new(Bar.new)
-  #     a.each do |x|
-  #       x.bar
-  #     end
-  #     )).to_i.should eq(1)
-  # end
-
-  # it "codegens call with blocks of different type without args" do
-  #   run(%q(
-  #     def foo
-  #       yield
-  #     end
-
-  #     foo { 1.1 }
-  #     foo { 1 }
-  #   )).to_i.should eq(1)
-  # end
-
-  # it "codegens dispatch with block and break" do
-  #   run(%q(
-  #     require "prelude"
-
-  #     a = [1, 2, 3] || [1.5]
-  #     n = 0
-  #     a.each do |x|
-  #       break if x > 2
-  #       n += x
-  #     end
-  #     n.to_i
-  #     )).to_i.should eq(3)
-  # end
+  it "codegens block with nilable type with return" do
+    run("
+      def foo
+        if yield
+          return Reference.new
+        end
+        nil
+      end
+
+      foo { false }
+      ")
+  end
+
+  it "codegens block with union with return" do
+    run("
+      def foo
+        yield
+
+        return 1 if 1 == 2
+
+        nil
+      end
+
+      x = foo { }
+      1
+      ")
+  end
+
+  it "codegens if with call with block (ssa issue)" do
+    run("
+      def bar
+        yield
+      end
+
+      def foo
+        if 1 == 2
+          bar do
+            x = 1
+          end
+        else
+          3
+        end
+      end
+
+      foo
+      ").to_i.should eq(3)
+  end
+
+  it "codegens block with return and yield and no return" do
+    run("
+      lib C
+        fun exit : NoReturn
+      end
+
+      def foo(key)
+        foo(key) { C.exit }
+      end
+
+      def foo(key)
+        if 1 == 1
+          return 2
+        end
+        yield
+      end
+
+      foo 1
+      ").to_i.should eq(2)
+  end
+
+  it "codegens while/break inside block" do
+    run("
+      def foo
+        yield
+      end
+
+      foo do
+        while true
+          break
+        end
+        1
+      end
+    ").to_i.should eq(1)
+  end
+
+  it "codegens block with union arg" do
+    run("
+      class Number
+        def abs
+          self
+        end
+      end
+
+      class Foo(T)
+        def initialize(x : T)
+          @x = x
+        end
+
+        def each
+          yield @x
+        end
+      end
+
+      a = Foo.new(1) || Foo.new(1.5)
+      a.each do |x|
+        x.abs
+      end.to_i
+      ").to_i.should eq(1)
+  end
+
+  it "codegens block with hierarchy type arg" do
+    run("
+      class Var(T)
+        def initialize(x : T)
+          @x = x
+        end
+
+        def each
+          yield @x
+        end
+      end
+
+      class Foo
+        def bar
+          1
+        end
+      end
+
+      class Bar < Foo
+        def bar
+          2
+        end
+      end
+
+      a = Var.new(Foo.new) || Var.new(Bar.new)
+      a.each do |x|
+        x.bar
+      end
+      ").to_i.should eq(1)
+  end
+
+  it "codegens call with blocks of different type without args" do
+    run("
+      def foo
+        yield
+      end
+
+      foo { 1.1 }
+      foo { 1 }
+    ").to_i.should eq(1)
+  end
+
+  pending "codegens dispatch with block and break" do
+    run("
+      require \"bootstrap\"
+
+      a = [1, 2, 3] || [1.5]
+      n = 0
+      a.each do |x|
+        break if x > 2
+        n += x
+      end
+      n.to_i
+      ").to_i.should eq(3)
+   end
  end
diff --git a/bootstrap/spec/crystal/codegen/c_enum_spec.cr b/bootstrap/spec/crystal/codegen/c_enum_spec.cr
new file mode 100644
index 0000000000000000000000000000000000000000..ae4757b5b860fa6c924b2585efd19325215aeb26
--- /dev/null
+++ b/bootstrap/spec/crystal/codegen/c_enum_spec.cr
@@ -0,0 +1,22 @@
+#!/usr/bin/env bin/crystal -run
+require "../../spec_helper"
+
+CodeGenEnumString = "lib Foo; enum Bar; X, Y, Z = 10, W; end end"
+
+describe "Code gen: enum" do
+  it "codegens enum value" do
+    run("#{CodeGenEnumString}; Foo::Bar::X").to_i.should eq(0)
+  end
+
+  it "codegens enum value 2" do
+    run("#{CodeGenEnumString}; Foo::Bar::Y").to_i.should eq(1)
+  end
+
+  it "codegens enum value 3" do
+    run("#{CodeGenEnumString}; Foo::Bar::Z").to_i.should eq(10)
+  end
+
+  it "codegens enum value 4" do
+    run("#{CodeGenEnumString}; Foo::Bar::W").to_i.should eq(11)
+  end
+end
diff --git a/bootstrap/spec/crystal/codegen/c_struct_spec.cr b/bootstrap/spec/crystal/codegen/c_struct_spec.cr
new file mode 100644
index 0000000000000000000000000000000000000000..2ef8ded208d35a43f796b7565491da201874a317
--- /dev/null
+++ b/bootstrap/spec/crystal/codegen/c_struct_spec.cr
@@ -0,0 +1,97 @@
+#!/usr/bin/env bin/crystal -run
+require "../../spec_helper"
+
+CodeGenStructString = "lib Foo; struct Bar; x : Int32; y : Float32; end; end"
+
+describe "Code gen: struct" do
+  it "codegens struct property default value" do
+    run("#{CodeGenStructString}; bar = Foo::Bar.new; bar.x").to_i.should eq(0)
+  end
+
+  it "codegens struct property setter" do
+    run("#{CodeGenStructString}; bar = Foo::Bar.new; bar.y = 2.5_f32; bar.y").to_f32.should eq(2.5)
+  end
+
+  it "codegens struct property setter" do
+    run("#{CodeGenStructString}; bar = Foo::Bar.new; p = bar.ptr; p.value.y = 2.5_f32; bar.y").to_f32.should eq(2.5)
+  end
+
+  it "codegens set struct value with constant" do
+    run("#{CodeGenStructString}; CONST = 1; bar = Foo::Bar.new; bar.x = CONST; bar.x").to_i.should eq(1)
+  end
+
+  it "codegens union inside struct" do
+    run("
+      lib Foo
+        union Bar
+          x : Int32
+          y : Int64
+        end
+
+        struct Baz
+          lala : Bar
+        end
+      end
+
+      a = Foo::Baz.new
+      a.lala.x = 10
+      a.lala.x
+      ").to_i.should eq(10)
+  end
+
+  it "codegens struct get inside struct" do
+    run("
+      lib C
+        struct Bar
+          y : Int32
+        end
+
+        struct Foo
+          x : Int32
+          bar : Bar
+        end
+      end
+
+      foo = C::Foo.new
+      (foo.ptr.as(Int32) + 1_i64).value = 2
+
+      foo.bar.y
+      ").to_i.should eq(2)
+  end
+
+  it "codegens struct set inside struct" do
+    run("
+      lib C
+        struct Bar
+          y : Int32
+        end
+
+        struct Foo
+          x : Int32
+          bar : Bar
+        end
+      end
+
+      foo = C::Foo.new
+      bar = C::Bar.new
+      bar.y = 2
+      foo.bar = bar
+
+      foo.bar.y
+      ").to_i.should eq(2)
+  end
+
+  it "codegens pointer malloc of struct" do
+    run("
+      lib C
+        struct Foo
+          x : Int32
+        end
+      end
+
+      p = Pointer(C::Foo).malloc(1_u64)
+      p.value.x = 1
+      p.value.x
+      ").to_i.should eq(1)
+  end
+end
diff --git a/bootstrap/spec/crystal/codegen/c_union_spec.cr b/bootstrap/spec/crystal/codegen/c_union_spec.cr
new file mode 100644
index 0000000000000000000000000000000000000000..5370809396ebf55831ec5ea134a298cd25740376
--- /dev/null
+++ b/bootstrap/spec/crystal/codegen/c_union_spec.cr
@@ -0,0 +1,44 @@
+#!/usr/bin/env bin/crystal -run
+require "../../spec_helper"
+
+CodeGenUnionString = "lib Foo; union Bar; x : Int32; y : Int64; z : Float32; end; end"
+
+describe "Code gen: c union" do
+  it "codegens union property default value" do
+    run("#{CodeGenUnionString}; bar = Foo::Bar.new; bar.x").to_i.should eq(0)
+  end
+
+  it "codegens union property default value 2" do
+    run("#{CodeGenUnionString}; bar = Foo::Bar.new; bar.z").to_f32.should eq(0)
+  end
+
+  it "codegens union property setter 1" do
+    run("#{CodeGenUnionString}; bar = Foo::Bar.new; bar.x = 42; bar.x").to_i.should eq(42)
+  end
+
+  it "codegens union property setter 2" do
+    run("#{CodeGenUnionString}; bar = Foo::Bar.new; bar.z = 42.0_f32; bar.z").to_f32.should eq(42.0)
+  end
+
+  it "codegens struct inside union" do
+    run("
+      lib Foo
+        struct Baz
+          lele : Int64
+          lala : Int32
+        end
+
+        union Bar
+          x : Int32
+          y : Int64
+          z : Baz
+        end
+      end
+
+      a = Foo::Bar.new
+      a.z = Foo::Baz.new
+      a.z.lala = 10
+      a.z.lala
+      ").to_i.should eq(10)
+  end
+end
diff --git a/bootstrap/spec/crystal/codegen/case_spec.cr b/bootstrap/spec/crystal/codegen/case_spec.cr
new file mode 100644
index 0000000000000000000000000000000000000000..de1b9fd2a9d349a93c86d91d4432e21bc5fbfd84
--- /dev/null
+++ b/bootstrap/spec/crystal/codegen/case_spec.cr
@@ -0,0 +1,73 @@
+#!/usr/bin/env bin/crystal -run
+require "../../spec_helper"
+
+describe "Code gen: case" do
+  it "codegens case with one condition" do
+    run("require \"object\"; case 1; when 1; 2; else; 3; end").to_i.should eq(2)
+  end
+
+  it "codegens case with two conditions" do
+    run("require \"object\"; case 1; when 0, 1; 2; else; 3; end").to_i.should eq(2)
+  end
+
+  it "codegens case with else" do
+    run("require \"object\"; case 1; when 0; 2; else; 3; end").to_i.should eq(3)
+  end
+
+  it "codegens case that always returns" do
+    run("
+      require \"object\"
+      def foo
+        if true
+          case 0
+          when 1; return 2
+          else return 3
+          end
+        end
+        4
+      end
+
+      foo
+    ").to_i.should eq(3)
+  end
+
+  it "codegens case when cond is a call" do
+    run("
+      require \"object\"
+
+      $a = 0
+
+      def foo
+        $a += 1
+      end
+
+      case foo
+      when 2
+        1
+      when 1
+        2
+      else
+        3
+      end
+    ").to_i.should eq(2)
+  end
+
+  it "codegens case with class" do
+    run("
+      require \"nil\"
+      class Int32
+        def foo
+          self
+        end
+      end
+
+      a = -1 || 'a'
+      case a
+      when Int32
+        a.foo
+      when Char
+        a.ord
+      end.to_i
+      ").to_i.should eq(-1)
+  end
+end
diff --git a/bootstrap/spec/crystal/codegen/class_spec.cr b/bootstrap/spec/crystal/codegen/class_spec.cr
index d3b51c8cd84b5f9fed178bfb7b117feaef127d30..7276f7bcce1e979d8bfe7938794431791f9a6d37 100755
--- a/bootstrap/spec/crystal/codegen/class_spec.cr
+++ b/bootstrap/spec/crystal/codegen/class_spec.cr
@@ -37,4 +37,134 @@ describe "Code gen: class" do
   it "codegens byte size of Int32" do
     run("Int32.byte_size").to_i.should eq(4)
   end
+
+  it "codegens recursive type" do
+    run("
+      class Foo
+        def next=(@next)
+        end
+      end
+
+      f = Foo.new
+      f.next = f
+      ")
+  end
+
+  it "codegens method call of instance var" do
+    run("
+      class List
+        def initialize
+          @last = 0
+        end
+
+        def foo
+          @last = 1
+          @last.to_f
+        end
+      end
+
+      l = List.new
+      l.foo
+      ").to_f64.should eq(1.0)
+  end
+
+  it "codegens new which calls initialize" do
+    run("
+      class Foo
+        def initialize(value)
+          @value = value
+        end
+
+        def value
+          @value
+        end
+      end
+
+      f = Foo.new 1
+      f.value
+    ").to_i.should eq(1)
+  end
+
+  it "codegens method from another method without obj and accesses instance vars" do
+    run("
+      class Foo
+        def foo
+          bar
+        end
+
+        def bar
+          @a = 1
+        end
+      end
+
+      f = Foo.new
+      f.foo
+      ").to_i.should eq(1)
+  end
+
+  it "codegens virtual call that calls another method" do
+    run("
+      class Foo
+        def foo
+          foo2
+        end
+
+        def foo2
+          1
+        end
+      end
+
+      class Bar < Foo
+      end
+
+      Bar.new.foo
+      ").to_i.should eq(1)
+  end
+
+  it "codgens virtual method of generic class" do
+    run("
+      require \"char\"
+
+      class Object
+        def foo
+          bar
+        end
+
+        def bar
+          'a'
+        end
+      end
+
+      class Foo(T)
+        def bar
+          1
+        end
+      end
+
+      Foo(Int32).new.foo.to_i
+      ").to_i.should eq(1)
+  end
+
+  it "changes instance variable in method (ssa bug)" do
+    run("
+      class Foo
+        def initialize
+          @var = 0
+        end
+
+        def foo
+          @var = 1
+          bar
+          @var
+        end
+
+        def bar
+          @var = 2
+        end
+      end
+
+      foo = Foo.new
+      foo.foo
+      ").to_i.should eq(2)
+  end
 end
diff --git a/bootstrap/spec/crystal/codegen/class_var_spec.cr b/bootstrap/spec/crystal/codegen/class_var_spec.cr
new file mode 100644
index 0000000000000000000000000000000000000000..dad1361a47cbdc43276a51788864952b88813278
--- /dev/null
+++ b/bootstrap/spec/crystal/codegen/class_var_spec.cr
@@ -0,0 +1,75 @@
+#!/usr/bin/env bin/crystal -run
+require "../../spec_helper"
+
+describe "Codegen: class var" do
+  it "codegens class var" do
+    run("
+      class Foo
+        @@foo = 1
+
+        def self.foo
+          @@foo
+        end
+      end
+
+      Foo.foo
+      ").to_i.should eq(1)
+  end
+
+  it "codegens class var as nil" do
+    run("
+      require \"nil\"
+
+      class Foo
+        def self.foo
+          @@foo
+        end
+      end
+
+      Foo.foo.to_i
+      ").to_i.should eq(0)
+  end
+
+  it "codegens class var inside instance method" do
+    run("
+      class Foo
+        @@foo = 1
+
+        def foo
+          @@foo
+        end
+      end
+
+      Foo.new.foo
+      ").to_i.should eq(1)
+  end
+
+  it "codegens class var as nil if assigned for the first time inside method" do
+    run("
+      require \"nil\"
+
+      class Foo
+        def self.foo
+          @@foo = 1
+          @@foo
+        end
+      end
+
+      Foo.foo.to_i
+      ").to_i.should eq(1)
+  end
+
+  it "codegens class var of program" do
+    run("
+      @@foo = 1
+      @@foo
+      ").to_i.should eq(1)
+  end
+
+  it "codegens class var of program as nil" do
+    run("
+      require \"nil\"
+      @@foo.to_i
+      ").to_i.should eq(0)
+  end
+end
diff --git a/bootstrap/spec/crystal/codegen/const_spec.cr b/bootstrap/spec/crystal/codegen/const_spec.cr
index a26023d77768c322eab60cd0d22589626f4e345f..9537bfe1967f1a36d1e2cc3f4627849401bfc6cc 100644
--- a/bootstrap/spec/crystal/codegen/const_spec.cr
+++ b/bootstrap/spec/crystal/codegen/const_spec.cr
@@ -2,6 +2,122 @@
 require "../../spec_helper"
 
 describe "Codegen: const" do
+  it "define a constant" do
+    run("A = 1; A").to_i.should eq(1)
+  end
+
+  it "support nested constant" do
+    run("class B; A = 1; end; B::A").to_i.should eq(1)
+  end
+
+  it "support constant inside a def" do
+    run("
+      class Foo
+        A = 1
+
+        def foo
+          A
+        end
+      end
+
+      Foo.new.foo
+    ").to_i.should eq(1)
+  end
+
+  it "finds nearest constant first" do
+    run("
+      A = 1
+
+      class Foo
+        A = 2.5_f32
+
+        def foo
+          A
+        end
+      end
+
+      Foo.new.foo
+    ").to_f32.should eq(2.5)
+  end
+
+  it "allows constants with same name" do
+    run("
+      A = 1
+
+      class Foo
+        A = 2.5_f32
+
+        def foo
+          A
+        end
+      end
+
+      A
+      Foo.new.foo
+    ").to_f32.should eq(2.5)
+  end
+
+  it "constants with expression" do
+    run("
+      A = 1 + 1
+      A
+    ").to_i.should eq(2)
+  end
+
+  it "finds global constant" do
+    run("
+      A = 1
+
+      class Foo
+        def foo
+          A
+        end
+      end
+
+      Foo.new.foo
+    ").to_i.should eq(1)
+  end
+
+  it "define a constant in lib" do
+    run("lib Foo; A = 1; end; Foo::A").to_i.should eq(1)
+  end
+
+  it "invokes block in const" do
+    run("require \"bootstrap\"; A = [\"1\"].map { |x| x.to_i }; A[0]").to_i.should eq(1)
+  end
+
+  it "declare constants in right order" do
+    run("A = 1 + 1; B = true ? A : 0; B").to_i.should eq(2)
+  end
+
+  it "uses correct types lookup" do
+    run("module A; class B; def foo; 1; end; end; C = B.new; end; def foo; A::C.foo; end; foo").to_i.should eq(1)
+  end
+
+  it "codegens variable assignment in const" do
+    run("
+      class Foo
+        def initialize(@x)
+        end
+
+        def x
+          @x
+        end
+      end
+
+      A = begin
+            f = Foo.new(1)
+            f
+          end
+
+      def foo
+        A.x
+      end
+
+      foo
+      ").to_i.should eq(1)
+  end
+
   it "declaring var" do
     run("
       BAR = begin
diff --git a/bootstrap/spec/crystal/codegen/def_spec.cr b/bootstrap/spec/crystal/codegen/def_spec.cr
index b70743767e76f3302fcb63a2838ef468896fd77d..75976ca879aad10e727a63a912a5c3323e284e58 100755
--- a/bootstrap/spec/crystal/codegen/def_spec.cr
+++ b/bootstrap/spec/crystal/codegen/def_spec.cr
@@ -2,36 +2,269 @@
 require "../../spec_helper"
 
 describe "Code gen: def" do
-  it "codegens def" do
+  it "codegens empty def" do
+    run("def foo; end; foo")
+  end
+
+  it "codegens call without args" do
+    run("def foo; 1; end; 2; foo").to_i.should eq(1)
+  end
+
+  it "call functions defined in any order" do
+    run("def foo; bar; end; def bar; 1; end; foo").to_i.should eq(1)
+  end
+
+  it "codegens call with args" do
+    run("def foo(x); x; end; foo 1").to_i.should eq(1)
+  end
+
+  it "call external function 'putchar'" do
+    run("require \"io\"; C.putchar '\\0'").to_i.should eq(0)
+  end
+
+  it "uses self" do
+    run("class Int; def foo; self + 1; end; end; 3.foo").to_i.should eq(4)
+  end
+
+  it "uses var after external" do
+    run("require \"io\"; a = 1; C.putchar '\\0'; a").to_i.should eq(1)
+  end
+
+  it "allows to change argument values" do
+    run("def foo(x); x = 1; x; end; foo(2)").to_i.should eq(1)
+  end
+
+  it "runs empty def" do
+    run("def foo; end; foo")
+  end
+
+  it "builds infinite recursive function" do
+    node = parse "def foo; foo; end; foo"
+    result = infer_type node
+    result.program.build result.node
+  end
+
+  it "unifies all calls to same def" do
     run("
-      def foo
+      require \"bootstrap\"
+
+      def raise(msg)
+        nil
+      end
+
+      class Hash2
+        def initialize
+          @buckets = [[1]]
+        end
+
+        def []=(key, value)
+          bucket.push value
+        end
+
+        def [](key)
+          bucket[0]
+        end
+
+        def bucket
+          @buckets[0]
+        end
+      end
+
+      hash = Hash2.new
+      hash[1] = 2
+      hash[1]
+    ").to_i.should eq(1)
+  end
+
+  it "codegens recursive type with union" do
+    run("
+      class A
+       def next=(n)
+         @next = n
+       end
+
+       def next
+         @next
+       end
+      end
+
+      a = A.allocate
+      a.next = A.allocate
+      a = a.next
+      ")
+  end
+
+  it "codegens with related types" do
+    run("
+      class A
+       def next=(n)
+         @next = n
+       end
+
+       def next
+         @next
+       end
+      end
+
+      class B
+       def next=(n)
+         @next = n
+       end
+
+       def next
+         @next
+       end
+      end
+
+      def foo(x, y)
+        if n = x.next
+          n.next = y
+        end
+      end
+
+      a = A.allocate
+      a.next = B.allocate
+
+      foo(a, B.allocate)
+
+      c = A.allocate
+      c.next = B.allocate
+
+      foo(c, c.next)
+      ")
+  end
+
+  it "codegens and doesn't break if obj is int and there's a mutation" do
+    run("
+      require \"bootstrap\"
+
+      class Int
+        def baz(x)
+        end
+      end
+
+      elems = [1]
+      elems[0].baz [1]
+    ")
+  end
+
+  it "codegens with and witout default arguments" do
+    run("
+      def foo(x = 1)
+        x + 1
+      end
+
+      foo(2) + foo
+      ").to_i.should eq(5)
+  end
+
+  it "codegens with and witout many default arguments" do
+    run("
+      def foo(x = 1, y = 2, z = 3)
+        x + y + z
+      end
+
+      foo + foo(9) + foo(3, 4) + foo(6, 3, 1)
+      ").to_i.should eq(40)
+  end
+
+  it "codegens with interesting default argument" do
+    run("
+      class Foo
+        def foo(x = self.bar)
+          x + 1
+        end
+
+        def bar
+          1
+        end
+      end
+
+      f = Foo.new
+
+      f.foo(2) + f.foo
+      ").to_i.should eq(5)
+  end
+
+  it "codegens dispatch on static method" do
+    run("
+      def Object.foo(x)
         1
       end
 
-      foo
+      a = 1
+      a = 1.5
+      Object.foo(a)
       ").to_i.should eq(1)
   end
 
-  it "codegens def with argument" do
+  it "use target def type as return type" do
     run("
-      def foo(x)
-        x
+      require \"nil\"
+      require \"value\"
+      require \"object\"
+
+      def foo
+        if false
+          return 0
+        end
       end
 
-      foo(1)
-      ").to_i.should eq(1)
+      foo.nil? ? 1 : 0
+    ").to_i.should eq(1)
+  end
+
+  it "codegens recursive nasty code" do
+    run("
+      class Foo
+        def initialize(x)
+        end
+      end
+
+      class Bar
+        def initialize(x)
+        end
+      end
+
+      class Box
+        def set(elem)
+          @elem = elem
+        end
+
+        def get
+          @elem
+        end
+      end
+
+      def foo
+        exps = Box.new
+        sub = foo
+        t = Foo.new(sub) || Bar.new(sub)
+        exps.set t
+        exps.get || 1
+      end
+
+      false && foo
+      ")
   end
 
-  it "codegens class def" do
+  it "looks up matches in super classes and merges them with subclasses" do
     run("
       class Foo
-        def self.foo
+        def foo(other)
           1
         end
       end
 
-      Foo.foo
-      ").to_i.should eq(1)
+      class Bar < Foo
+        def foo(other : Int)
+          2
+        end
+      end
+
+      bar1 = Bar.new
+      bar1.foo(1 || 1.5)
+      ").to_i.should eq(2)
   end
 
   it "codegens def which changes type of arg" do
diff --git a/bootstrap/spec/crystal/codegen/global_spec.cr b/bootstrap/spec/crystal/codegen/global_spec.cr
new file mode 100644
index 0000000000000000000000000000000000000000..75e4c0b46b164d5f44d6e55a9a32ac517b271eca
--- /dev/null
+++ b/bootstrap/spec/crystal/codegen/global_spec.cr
@@ -0,0 +1,20 @@
+#!/usr/bin/env bin/crystal -run
+require "../../spec_helper"
+
+describe "Code gen: global" do
+  it "codegens global" do
+    run("$foo = 1; def foo; $foo = 2; end; foo; $foo").to_i.should eq(2)
+  end
+
+  it "codegens global with union" do
+    run("$foo = 1; def foo; $foo = 2.5_f32; end; foo; $foo.to_f").to_f64.should eq(2.5)
+  end
+
+  it "codegens global when not initialized" do
+    run("require \"nil\"; $foo.to_i").to_i.should eq(0)
+  end
+
+  it "codegens global when not initialized" do
+    run("require \"nil\"; def foo; $foo = 2 if 1 == 2; end; foo; $foo.to_i").to_i.should eq(0)
+  end
+end
diff --git a/bootstrap/spec/crystal/type_inference/block_spec.cr b/bootstrap/spec/crystal/type_inference/block_spec.cr
index 214a06ab4ec7111754c0d07f7c32824544e2b754..652e504bed1da99efa641359a8138ab39f7d150d 100755
--- a/bootstrap/spec/crystal/type_inference/block_spec.cr
+++ b/bootstrap/spec/crystal/type_inference/block_spec.cr
@@ -73,34 +73,34 @@ describe "Block inference" do
     ") { int32 }
   end
 
-  # it "infer type with union" do
-  #   assert_type(%q(
-  #     require "int"
-  #     require "pointer"
-  #     require "array"
-  #     a = [1] || [1.1]
-  #     a.each { |x| x }
-  #   )) { union_of(array_of(int32), array_of(float64)) }
-  # end
-
-  # it "break from block without value" do
-  #   assert_type(%q(
-  #     def foo; yield; end
-
-  #     foo do
-  #       break
-  #     end
-  #   )) { self.nil }
-  # end
-
-  # it "break without value has nil type" do
-  #   assert_type(%q(
-  #     def foo; yield; 1; end
-  #     foo do
-  #       break if false
-  #     end
-  #   )) { union_of(self.nil, int32) }
-  # end
+  it "infer type with union" do
+    assert_type("
+      require \"int\"
+      require \"pointer\"
+      require \"array\"
+      a = [1] || [1.1]
+      a.each { |x| x }
+    ") { union_of(array_of(int32), array_of(float64)) }
+  end
+
+  it "break from block without value" do
+    assert_type("
+      def foo; yield; end
+
+      foo do
+        break
+      end
+    ") { |mod| mod.nil }
+  end
+
+  it "break without value has nil type" do
+    assert_type("
+      def foo; yield; 1; end
+      foo do
+        break if false
+      end
+    ") { |mod| union_of(mod.nil, int32) }
+  end
 
   it "infers type of block before call" do
     result = assert_type("
@@ -324,45 +324,45 @@ describe "Block inference" do
     ") { |mod| mod.nil }
   end
 
-  # it "preserves type filters in block" do
-  #   assert_type(%q(
-  #     class Foo
-  #       def bar
-  #         'a'
-  #       end
-  #     end
-
-  #     def foo
-  #       yield 1
-  #     end
-
-  #     a = Foo.new || nil
-  #     if a
-  #       foo do |x|
-  #         a.bar
-  #       end
-  #     else
-  #       'b'
-  #     end
-  #     )) { char }
-  # end
-
-  # it "checks block type with hierarchy type" do
-  #   assert_type(%q(
-  #     require "prelude"
-
-  #     class A
-  #     end
-
-  #     class B < A
-  #     end
-
-  #     a = [] of A
-  #     a << B.new
-
-  #     a.map { |x| x.to_s }
-
-  #     1
-  #     )) { int32 }
-  # end
+  it "preserves type filters in block" do
+    assert_type("
+      class Foo
+        def bar
+          'a'
+        end
+      end
+
+      def foo
+        yield 1
+      end
+
+      a = Foo.new || nil
+      if a
+        foo do |x|
+          a.bar
+        end
+      else
+        'b'
+      end
+      ") { char }
+  end
+
+  it "checks block type with hierarchy type" do
+    assert_type("
+      require \"bootstrap\"
+
+      class A
+      end
+
+      class B < A
+      end
+
+      a = [] of A
+      a << B.new
+
+      a.map { |x| x.to_s }
+
+      1
+      ") { int32 }
+  end
 end
diff --git a/spec/codegen/block_spec.rb b/spec/codegen/block_spec.rb
index c2524dadc88fca9b1084fab4f09e389ceb23d047..335f065171bc6a810e5b29139b04f8b641f0c559 100644
--- a/spec/codegen/block_spec.rb
+++ b/spec/codegen/block_spec.rb
@@ -349,7 +349,7 @@ describe 'Code gen: block' do
       end
 
       x = foo do
-        break if true
+        break if 1 == 1
       end
 
       x.nil?