diff --git a/spec/compiler/codegen/macro_spec.cr b/spec/compiler/codegen/macro_spec.cr
index ae5769e88f4cb54d988bbac662ab6c17e5038bc4..34e7d6ae4dcff8878e3dc64f3426a656cb5beb29 100755
--- a/spec/compiler/codegen/macro_spec.cr
+++ b/spec/compiler/codegen/macro_spec.cr
@@ -288,4 +288,23 @@ describe "Code gen: macro" do
       foo(1)
       )).to_i.should eq(3)
   end
+
+  it "expands def macro with instance var and method call (bug)" do
+    run(%(
+      struct Nil
+        def to_i
+          0
+        end
+      end
+
+      class Foo
+        def foo : Int32
+          name = 1
+          @name = name
+        end
+      end
+
+      Foo.new.foo.to_i
+      )).to_i.should eq(1)
+  end
 end
diff --git a/src/compiler/crystal/macros.cr b/src/compiler/crystal/macros.cr
index fcbf276ed1bd61bec3604b2409ddc4d0f64e3d4f..22cfc4f8cfca1937fa56d48577df99162cc39475 100644
--- a/src/compiler/crystal/macros.cr
+++ b/src/compiler/crystal/macros.cr
@@ -38,7 +38,9 @@ module Crystal
       target_def.vars = vars
       arg_names = target_def.args.map(&.name)
 
-      generated_nodes = parse_macro_source(generated_source, the_macro, target_def, arg_names.to_set)
+      generated_nodes = parse_macro_source(generated_source, the_macro, target_def, arg_names.to_set) do |parser|
+        parser.parse_to_def(target_def)
+      end
 
       type_visitor = TypeVisitor.new(@program, vars, target_def)
       type_visitor.scope = owner
@@ -51,11 +53,15 @@ module Crystal
       target_def.body = generated_nodes
     end
 
+    def parse_macro_source(generated_source, the_macro, node, vars)
+      parse_macro_source generated_source, the_macro, node, vars, &.parse
+    end
+
     def parse_macro_source(generated_source, the_macro, node, vars)
       begin
         parser = Parser.new(generated_source, [vars])
         parser.filename = VirtualFile.new(the_macro, generated_source, node.location)
-        normalize parser.parse
+        normalize(yield parser)
       rescue ex : Crystal::SyntaxException
         node.raise "macro didn't expand to a valid program, it expanded to:\n\n#{"=" * 80}\n#{"-" * 80}\n#{generated_source.lines.to_s_with_line_numbers}\n#{"-" * 80}\n#{ex.to_s(generated_source)}\n#{"=" * 80}"
       end
diff --git a/src/compiler/crystal/parser.cr b/src/compiler/crystal/parser.cr
index af82c6f99a7c250a9e7499fb351afb28399ca6c3..232bf24e845e2e4281ed90b6cc2b3857536c602e 100644
--- a/src/compiler/crystal/parser.cr
+++ b/src/compiler/crystal/parser.cr
@@ -20,7 +20,6 @@ module Crystal
       @def_nest = 0
       @block_arg_count = 0
       @in_macro_expression = false
-      @in_def_count = 0
       @stop_on_yield = 0
     end
 
@@ -1597,11 +1596,24 @@ module Crystal
       inc
     end
 
+    def parse_to_def(a_def)
+      instance_vars = prepare_parse_def
+      @def_nest += 1
+
+      # Small memory optimization: don't keep the Set in the Def if it's empty
+      instance_vars = nil if instance_vars.empty?
+
+      result = parse
+
+      a_def.instance_vars = instance_vars
+      a_def.calls_super = @calls_super
+      a_def.uses_block_arg = @uses_block_arg
+
+      result
+    end
+
     def parse_def
-      instance_vars = @instance_vars = Set(String).new
-      @calls_super = false
-      @uses_block_arg = false
-      @block_arg_name = nil
+      instance_vars = prepare_parse_def
       a_def = parse_def_helper
 
       # Small memory optimization: don't keep the Set in the Def if it's empty
@@ -1617,6 +1629,13 @@ module Crystal
       a_def
     end
 
+    def prepare_parse_def
+      @calls_super = false
+      @uses_block_arg = false
+      @block_arg_name = nil
+      @instance_vars = Set(String).new
+    end
+
     def parse_macro
       push_def
       @def_nest += 1
diff --git a/src/compiler/crystal/types.cr b/src/compiler/crystal/types.cr
index ea401564f5c4935291daab98cd48c027c3ea7ecc..048e2063905ed85b8559af8fd68eb8dc43e6338d 100644
--- a/src/compiler/crystal/types.cr
+++ b/src/compiler/crystal/types.cr
@@ -1018,6 +1018,9 @@ module Crystal
     end
 
     def transfer_instance_vars(a_def)
+      # Don't consider macro defs here (only later, when expanded)
+      return if a_def.return_type
+
       is_initialize = a_def.name == "initialize"
 
       if a_def_instance_vars = a_def.instance_vars