Bug #19721
closedIO#timeout= can be called without required argument
Description
f = File.open("a.txt", "w")
f.timeout=() # => nil
IO#timeout=
requires an argument (or it's supposed to require it) but if it's called as a method it seems the check is skipped and missing argument is treated as nil
value.
If it's called with #send
- then argument presence is checked:
f.send :"timeout="
# ...:in `timeout=': wrong number of arguments (given 0, expected 1) (ArgumentError)
Updated by ufuk (Ufuk Kayserilioglu) over 1 year ago
I believe the syntax f.timeout=()
is not calling the timeout=
method with no parameters, but instead it is assigning ()
to f.timeout
attribute. Since ()
in Ruby evaluates to nil
(because it is an empty subexpression), in essence, that line should be equivalent to f.timeout = nil
. That's why you get the nil
value.
You can check that this expression gets turned into an assigment by looking at the AST generated from f.timeout=()
on https://ruby-syntax-tree.github.io/:
(program
(statements
((assign
(field (vcall (ident "f")) (period ".") (ident "timeout"))
(paren (statements ((void_stmt))))
))
)
)
Updated by jeremyevans0 (Jeremy Evans) over 1 year ago
- Status changed from Open to Rejected
All assignment methods called via recv.method =
are called with one argument. ()
is translated to nil
by the compiler, because it is an expression that is evaluated to nil
:
eval('()')
# => nil
Updated by andrykonchin (Andrew Konchin) over 1 year ago
Ah, I see. Thank you.