Project

General

Profile

Actions

Bug #19354

closed

Issues with arguments validation in IO.read

Added by andrykonchin (Andrew Konchin) over 2 years ago. Updated over 2 years ago.

Status:
Feedback
Assignee:
-
Target version:
-
[ruby-core:111907]

Description

I've noticed a strange error message when IO.read is called with additional positional argument:

IO.read("a.txt", 3, 0, {mode: "r+"})
# (irb):2:in `read': wrong number of arguments (given 3, expected 0..2) (ArgumentError)

But I would expect receiving given 4, expected 1..3 as far as the first argument (file name) is mandatory and all the other arguments - are optional.

I've encountered another related issue - looks like existing of a file with specified name is checked before number of arguments.

So when passed additional argument and specified a name of not existing file - I receive error about wrong file name, but would expect more basic and essential error about wrong number of arguments:

IO.read("b.txt", 3, 0, {mode: "r+"})
# (irb):3:in `read': No such file or directory @ rb_sysopen - b.txt (Errno::ENOENT)
Actions #1

Updated by andrykonchin (Andrew Konchin) over 2 years ago

  • ruby -v changed from 3.2.1, 3.2.1 to 3.2.0, 3.2.1
Actions #2

Updated by andrykonchin (Andrew Konchin) over 2 years ago

  • ruby -v changed from 3.2.0, 3.2.1 to 3.2.0, 3.1.3

Updated by nobu (Nobuyoshi Nakada) over 2 years ago

  • Status changed from Open to Feedback

IO.read opens the file given as the first argument, then delegates the other arguments to IO#read on the instance.
Your error happens in the delegated IO#read.

Since 3.0, keyword arguments are separated from mere hashes.
I think you may want to write:

IO.read("a.txt", 3, 0, mode: "r+")

Updated by andrykonchin (Andrew Konchin) over 2 years ago

Yeah, I understand that it's caused by the way how IO.read is implemented.

My point is that from the end-user point of view current error message (given 3, expected 0..2) is slightly misleading/confusing.

Updated by Eregon (Benoit Daloze) over 2 years ago

I think the current error could be acceptable if it's clear IO#read is in the backtrace.
But it's not part of the backtrace currently (and on top it's not possible to differentiate IO.read and IO#read from the backtrace):

$ ruby -e 'IO.read("a.txt", 3, 0, {mode: "r+"})'      
-e:1:in `read': wrong number of arguments (given 3, expected 0..2) (ArgumentError)
	from -e:1:in `<main>'

And so this is rather inconsistent (in expected args) with:

$ ruby -e 'IO.read("a.txt", 3, 0, {mode: "r+"}, 5, 6)'
-e:1:in `read': wrong number of arguments (given 6, expected 1..4) (ArgumentError)
	from -e:1:in `<main>'

The second error in the description seems clearly wrong behavior.
So I guess we should check args more strictly in IO.read itself, before calling IO#read.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0