diff --git a/lib/crystal/parser.rb b/lib/crystal/parser.rb index 38b442836f8a..d8b1467b8887 100644 --- a/lib/crystal/parser.rb +++ b/lib/crystal/parser.rb @@ -897,6 +897,8 @@ def parse_args var.out = true var.location = @token.location args << var + + @instance_vars.add @token.value if @instance_vars else raise "expecting variable or instance variable after out" end @@ -952,6 +954,8 @@ def parse_args_space_consumed(allow_plus_and_minus = false) var.out = true var.location = @token.location args << var + + @instance_vars.add @token.value if @instance_vars else raise "expecting variable or instance variable after out" end diff --git a/lib/crystal/to_s.rb b/lib/crystal/to_s.rb index 9730ab5b5f43..9c92f88e0cf6 100644 --- a/lib/crystal/to_s.rb +++ b/lib/crystal/to_s.rb @@ -373,6 +373,7 @@ def visit_self_type(node) end def visit_instance_var(node) + @str << "out " if node.out @str << node.name end diff --git a/lib/crystal/type_inference/call.rb b/lib/crystal/type_inference/call.rb index c7d16c721df5..60d6f3e871b6 100644 --- a/lib/crystal/type_inference/call.rb +++ b/lib/crystal/type_inference/call.rb @@ -314,12 +314,15 @@ def recalculate_lib_call def check_out_args(untyped_def) untyped_def.args.each_with_index do |arg, i| - if arg.out && self.args[i] - unless self.args[i].out - self.args[i].raise "argument \##{i + 1} to #{untyped_def.owner}.#{untyped_def.name} must be passed as 'out'" + call_arg = self.args[i] + if arg.out && call_arg + unless call_arg.out + call_arg.raise "argument \##{i + 1} to #{untyped_def.owner}.#{untyped_def.name} must be passed as 'out'" end - var = parent_visitor.lookup_var_or_instance_var(self.args[i]) + var = parent_visitor.lookup_var_or_instance_var(call_arg) var.bind_to arg + elsif !arg.out && (call_arg.is_a?(Var) || call_arg.is_a?(InstanceVar)) && call_arg.out + call_arg.raise "argument \##{i + 1} to #{untyped_def.owner}.#{untyped_def.name} cannot be passed as 'out'" end end end