1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Kernel#inspect: improve consistency and do not call #to_s.

* object.c (rb_obj_inspect): Kernel#inspect: do not call #to_s. A class
  can now benefit from the nice default #inspect even if it defines #to_s.
  Also, there is no more unexpected change in #inspect result.
* NEWS: Add note about the change.
* bignum.c, io.c, numeric.c, object.c, proc.c, vm.c (Init_*):
  Adapt internal structures (by aliasing #inspect to #to_s) so they
  don't rely on the removed behavior (#inspect calling overridden #to_s).
* test/ruby/test_object.rb (test_inspect): add tests for Kernel#inspect.
* lib/pp.rb (class PP): do not call #to_s anymore, as #inspect
  no more does (mame).
* test/test_pp.rb (class PPInspectTest): remove related assertion (mame).
  [ruby-core:43238][Feature #6130]
* test/drb/drbtest.rb (DRbCore#teardown, DRbAry#teardown):
  adapt DRb tests with the new change (shirosaki).
  [ruby-core:47182][Bug #6866]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36709 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2012-08-15 11:50:01 +00:00
parent e272790d11
commit fd7dc23d28
12 changed files with 72 additions and 39 deletions

View file

@ -1,3 +1,27 @@
Wed Aug 15 20:47:49 2012 Benoit Daloze <eregontp@gmail.com>
* object.c (rb_obj_inspect): Kernel#inspect: do not call #to_s. A class
can now benefit from the nice default #inspect even if it defines #to_s.
Also, there is no more unexpected change in #inspect result.
* NEWS: Add note about the change.
* bignum.c, io.c, numeric.c, object.c, proc.c, vm.c (Init_*):
Adapt internal structures (by aliasing #inspect to #to_s) so they
don't rely on the removed behavior (#inspect calling overridden #to_s).
* test/ruby/test_object.rb (test_inspect): add tests for Kernel#inspect.
* lib/pp.rb (class PP): do not call #to_s anymore, as #inspect
no more does (mame).
* test/test_pp.rb (class PPInspectTest): remove related assertion (mame).
[ruby-core:43238][Feature #6130]
* test/drb/drbtest.rb (DRbCore#teardown, DRbAry#teardown):
adapt DRb tests with the new change (shirosaki).
[ruby-core:47182][Bug #6866]
Wed Aug 15 18:05:37 2012 NAKAMURA Usaku <usa@ruby-lang.org> Wed Aug 15 18:05:37 2012 NAKAMURA Usaku <usa@ruby-lang.org>
* lib/test/unit.rb (Test::Unit::Runner#failed): need to delete the * lib/test/unit.rb (Test::Unit::Runner#failed): need to delete the

2
NEWS
View file

@ -46,6 +46,8 @@ with all sufficient information, see the ChangeLog file.
* __callee__ has returned to the original behavior, and now * __callee__ has returned to the original behavior, and now
returns the called name but not the original name in an returns the called name but not the original name in an
aliased method. aliased method.
* Kernel#inspect does not call #to_s anymore
(it used to call redefined #to_s).
* LoadError * LoadError
* added method: * added method:

View file

@ -3835,6 +3835,7 @@ Init_Bignum(void)
rb_cBignum = rb_define_class("Bignum", rb_cInteger); rb_cBignum = rb_define_class("Bignum", rb_cInteger);
rb_define_method(rb_cBignum, "to_s", rb_big_to_s, -1); rb_define_method(rb_cBignum, "to_s", rb_big_to_s, -1);
rb_define_alias(rb_cBignum, "inspect", "to_s");
rb_define_method(rb_cBignum, "coerce", rb_big_coerce, 1); rb_define_method(rb_cBignum, "coerce", rb_big_coerce, 1);
rb_define_method(rb_cBignum, "-@", rb_big_uminus, 0); rb_define_method(rb_cBignum, "-@", rb_big_uminus, 0);
rb_define_method(rb_cBignum, "+", rb_big_plus, 1); rb_define_method(rb_cBignum, "+", rb_big_plus, 1);

1
io.c
View file

@ -11505,6 +11505,7 @@ Init_IO(void)
rb_define_method(rb_cARGF, "initialize", argf_initialize, -2); rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1); rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
rb_define_method(rb_cARGF, "to_s", argf_to_s, 0); rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
rb_define_alias(rb_cARGF, "inspect", "to_s");
rb_define_method(rb_cARGF, "argv", argf_argv, 0); rb_define_method(rb_cARGF, "argv", argf_argv, 0);
rb_define_method(rb_cARGF, "fileno", argf_fileno, 0); rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);

View file

@ -265,8 +265,7 @@ class PP < PrettyPrint
module ObjectMixin module ObjectMixin
# 1. specific pretty_print # 1. specific pretty_print
# 2. specific inspect # 2. specific inspect
# 3. specific to_s # 3. generic pretty_print
# 4. generic pretty_print
# A default pretty printing method for general objects. # A default pretty printing method for general objects.
# It calls #pretty_print_instance_variables to list instance variables. # It calls #pretty_print_instance_variables to list instance variables.
@ -283,18 +282,10 @@ class PP < PrettyPrint
inspect_method = method_method.call(:inspect) inspect_method = method_method.call(:inspect)
rescue NameError rescue NameError
end end
begin
to_s_method = method_method.call(:to_s)
rescue NameError
end
if inspect_method && /\(Kernel\)#/ !~ inspect_method.inspect if inspect_method && /\(Kernel\)#/ !~ inspect_method.inspect
q.text self.inspect q.text self.inspect
elsif !inspect_method && self.respond_to?(:inspect) elsif !inspect_method && self.respond_to?(:inspect)
q.text self.inspect q.text self.inspect
elsif to_s_method && /\(Kernel\)#/ !~ to_s_method.inspect
q.text self.to_s
elsif !to_s_method && self.respond_to?(:to_s)
q.text self.to_s
else else
q.pp_object(self) q.pp_object(self)
end end

View file

@ -3660,6 +3660,7 @@ Init_Numeric(void)
rb_cFixnum = rb_define_class("Fixnum", rb_cInteger); rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
rb_define_method(rb_cFixnum, "to_s", fix_to_s, -1); rb_define_method(rb_cFixnum, "to_s", fix_to_s, -1);
rb_define_alias(rb_cFixnum, "inspect", "to_s");
rb_define_method(rb_cFixnum, "-@", fix_uminus, 0); rb_define_method(rb_cFixnum, "-@", fix_uminus, 0);
rb_define_method(rb_cFixnum, "+", fix_plus, 1); rb_define_method(rb_cFixnum, "+", fix_plus, 1);
@ -3720,6 +3721,7 @@ Init_Numeric(void)
rb_define_const(rb_cFloat, "NAN", DBL2NUM(NAN)); rb_define_const(rb_cFloat, "NAN", DBL2NUM(NAN));
rb_define_method(rb_cFloat, "to_s", flo_to_s, 0); rb_define_method(rb_cFloat, "to_s", flo_to_s, 0);
rb_define_alias(rb_cFloat, "inspect", "to_s");
rb_define_method(rb_cFloat, "coerce", flo_coerce, 1); rb_define_method(rb_cFloat, "coerce", flo_coerce, 1);
rb_define_method(rb_cFloat, "-@", flo_uminus, 0); rb_define_method(rb_cFloat, "-@", flo_uminus, 0);
rb_define_method(rb_cFloat, "+", flo_plus, 1); rb_define_method(rb_cFloat, "+", flo_plus, 1);

View file

@ -450,11 +450,8 @@ inspect_obj(VALUE obj, VALUE str, int recur)
* obj.inspect -> string * obj.inspect -> string
* *
* Returns a string containing a human-readable representation of <i>obj</i>. * Returns a string containing a human-readable representation of <i>obj</i>.
* By default, if the <i>obj</i> has instance variables, show the class name * By default, show the class name and the list of the instance variables and
* and instance variable details which is the list of the name and the result * their values (by calling #inspect on each of them).
* of <i>inspect</i> method for each instance variable.
* Otherwise uses the <i>to_s</i> method to generate the string.
* If the <i>to_s</i> method is overridden, uses it.
* User defined classes should override this method to make better * User defined classes should override this method to make better
* representation of <i>obj</i>. When overriding this method, it should * representation of <i>obj</i>. When overriding this method, it should
* return a string whose encoding is compatible with the default external * return a string whose encoding is compatible with the default external
@ -479,35 +476,21 @@ inspect_obj(VALUE obj, VALUE str, int recur)
* "baz" * "baz"
* end * end
* end * end
* Baz.new.inspect #=> "baz" * Baz.new.inspect #=> "#<Baz:0x0300c868>"
*/ */
static VALUE static VALUE
rb_obj_inspect(VALUE obj) rb_obj_inspect(VALUE obj)
{ {
if (RB_TYPE_P(obj, T_OBJECT) && rb_obj_basic_to_s_p(obj)) { if (rb_ivar_count(obj) > 0) {
int has_ivar = 0; VALUE str;
VALUE *ptr = ROBJECT_IVPTR(obj); const char *c = rb_obj_classname(obj);
long len = ROBJECT_NUMIV(obj);
long i;
for (i = 0; i < len; i++) { str = rb_sprintf("-<%s:%p", c, (void*)obj);
if (ptr[i] != Qundef) { return rb_exec_recursive(inspect_obj, obj, str);
has_ivar = 1; } else {
break;
}
}
if (has_ivar) {
VALUE str;
const char *c = rb_obj_classname(obj);
str = rb_sprintf("-<%s:%p", c, (void*)obj);
return rb_exec_recursive(inspect_obj, obj, str);
}
return rb_any_to_s(obj); return rb_any_to_s(obj);
} }
return rb_funcall(obj, rb_intern("to_s"), 0, 0);
} }
static VALUE static VALUE
@ -2951,6 +2934,7 @@ Init_Object(void)
rb_define_method(rb_cModule, ">=", rb_mod_ge, 1); rb_define_method(rb_cModule, ">=", rb_mod_ge, 1);
rb_define_method(rb_cModule, "initialize_copy", rb_mod_init_copy, 1); /* in class.c */ rb_define_method(rb_cModule, "initialize_copy", rb_mod_init_copy, 1); /* in class.c */
rb_define_method(rb_cModule, "to_s", rb_mod_to_s, 0); rb_define_method(rb_cModule, "to_s", rb_mod_to_s, 0);
rb_define_alias(rb_cModule, "inspect", "to_s");
rb_define_method(rb_cModule, "included_modules", rb_mod_included_modules, 0); /* in class.c */ rb_define_method(rb_cModule, "included_modules", rb_mod_included_modules, 0); /* in class.c */
rb_define_method(rb_cModule, "include?", rb_mod_include_p, 1); /* in class.c */ rb_define_method(rb_cModule, "include?", rb_mod_include_p, 1); /* in class.c */
rb_define_method(rb_cModule, "name", rb_mod_name, 0); /* in variable.c */ rb_define_method(rb_cModule, "name", rb_mod_name, 0); /* in variable.c */
@ -3003,6 +2987,7 @@ Init_Object(void)
rb_cTrueClass = rb_define_class("TrueClass", rb_cObject); rb_cTrueClass = rb_define_class("TrueClass", rb_cObject);
rb_define_method(rb_cTrueClass, "to_s", true_to_s, 0); rb_define_method(rb_cTrueClass, "to_s", true_to_s, 0);
rb_define_alias(rb_cTrueClass, "inspect", "to_s");
rb_define_method(rb_cTrueClass, "&", true_and, 1); rb_define_method(rb_cTrueClass, "&", true_and, 1);
rb_define_method(rb_cTrueClass, "|", true_or, 1); rb_define_method(rb_cTrueClass, "|", true_or, 1);
rb_define_method(rb_cTrueClass, "^", true_xor, 1); rb_define_method(rb_cTrueClass, "^", true_xor, 1);
@ -3015,6 +3000,7 @@ Init_Object(void)
rb_cFalseClass = rb_define_class("FalseClass", rb_cObject); rb_cFalseClass = rb_define_class("FalseClass", rb_cObject);
rb_define_method(rb_cFalseClass, "to_s", false_to_s, 0); rb_define_method(rb_cFalseClass, "to_s", false_to_s, 0);
rb_define_alias(rb_cFalseClass, "inspect", "to_s");
rb_define_method(rb_cFalseClass, "&", false_and, 1); rb_define_method(rb_cFalseClass, "&", false_and, 1);
rb_define_method(rb_cFalseClass, "|", false_or, 1); rb_define_method(rb_cFalseClass, "|", false_or, 1);
rb_define_method(rb_cFalseClass, "^", false_xor, 1); rb_define_method(rb_cFalseClass, "^", false_xor, 1);

1
proc.c
View file

@ -2217,6 +2217,7 @@ Init_Proc(void)
rb_define_method(rb_cProc, "eql?", proc_eq, 1); rb_define_method(rb_cProc, "eql?", proc_eq, 1);
rb_define_method(rb_cProc, "hash", proc_hash, 0); rb_define_method(rb_cProc, "hash", proc_hash, 0);
rb_define_method(rb_cProc, "to_s", proc_to_s, 0); rb_define_method(rb_cProc, "to_s", proc_to_s, 0);
rb_define_alias(rb_cProc, "inspect", "to_s");
rb_define_method(rb_cProc, "lambda?", rb_proc_lambda_p, 0); rb_define_method(rb_cProc, "lambda?", rb_proc_lambda_p, 0);
rb_define_method(rb_cProc, "binding", proc_binding, 0); rb_define_method(rb_cProc, "binding", proc_binding, 0);
rb_define_method(rb_cProc, "curry", proc_curry, -1); rb_define_method(rb_cProc, "curry", proc_curry, -1);

View file

@ -73,7 +73,7 @@ module DRbCore
def teardown def teardown
@ext.stop_service if defined?(@ext) && @ext @ext.stop_service if defined?(@ext) && @ext
DRbService.manager.unregist(@service_name) DRbService.manager.unregist(@service_name)
while (@there.inspect rescue nil) while (@there.to_s rescue nil)
# nop # nop
end end
signal = /mswin|mingw/ =~ RUBY_PLATFORM ? :INT : :TERM signal = /mswin|mingw/ =~ RUBY_PLATFORM ? :INT : :TERM
@ -294,7 +294,7 @@ module DRbAry
def teardown def teardown
@ext.stop_service if defined?(@ext) && @ext @ext.stop_service if defined?(@ext) && @ext
DRbService.manager.unregist(@service_name) DRbService.manager.unregist(@service_name)
while (@there.inspect rescue nil) while (@there.to_s rescue nil)
# nop # nop
end end
signal = /mswin|mingw/ =~ RUBY_PLATFORM ? :INT : :TERM signal = /mswin|mingw/ =~ RUBY_PLATFORM ? :INT : :TERM

View file

@ -690,6 +690,31 @@ class TestObject < Test::Unit::TestCase
assert_equal(true, s.tainted?) assert_equal(true, s.tainted?)
end end
def test_inspect
x = Object.new
assert_match(/\A#<Object:0x\h+>\z/, x.inspect)
x.instance_variable_set(:@ivar, :value)
assert_match(/\A#<Object:0x\h+ @ivar=:value>\z/, x.inspect)
x = Object.new
x.instance_variable_set(:@recur, x)
assert_match(/\A#<Object:0x\h+ @recur=#<Object:0x\h+ \.\.\.>>\z/, x.inspect)
x = Object.new
x.instance_variable_set(:@foo, "value")
x.instance_variable_set(:@bar, 42)
assert_match(/\A#<Object:0x\h+ (?:@foo="value", @bar=42|@bar=42, @foo="value")>\z/, x.inspect)
# #inspect does not call #to_s anymore
feature6130 = '[ruby-core:43238]'
x = Object.new
def x.to_s
"to_s"
end
assert_match(/\A#<Object:0x\h+>\z/, x.inspect, feature6130)
end
def test_exec_recursive def test_exec_recursive
Thread.current[:__recursive_key__] = nil Thread.current[:__recursive_key__] = nil
a = [[]] a = [[]]

View file

@ -118,7 +118,6 @@ class PPInspectTest < Test::Unit::TestCase
def a.to_s() "aaa" end def a.to_s() "aaa" end
result = PP.pp(a, '') result = PP.pp(a, '')
assert_equal("#{a.inspect}\n", result) assert_equal("#{a.inspect}\n", result)
assert_equal("aaa\n", result)
end end
end end

1
vm.c
View file

@ -2229,6 +2229,7 @@ Init_top_self(void)
vm->top_self = rb_obj_alloc(rb_cObject); vm->top_self = rb_obj_alloc(rb_cObject);
rb_define_singleton_method(rb_vm_top_self(), "to_s", main_to_s, 0); rb_define_singleton_method(rb_vm_top_self(), "to_s", main_to_s, 0);
rb_define_alias(rb_singleton_class(rb_vm_top_self()), "inspect", "to_s");
/* initialize mark object array */ /* initialize mark object array */
vm->mark_object_ary = rb_ary_tmp_new(1); vm->mark_object_ary = rb_ary_tmp_new(1);