Project

General

Profile

Bug #1747

Immediate Values Can be Frozen

Added by runpaint (Run Paint Run Run) over 10 years ago. Updated over 8 years ago.

Status:
Closed
Priority:
Normal
Target version:
ruby -v:
ruby 1.9.2dev (2009-07-08 trunk 23995) [i686-linux]
Backport:
[ruby-core:24221]

Description

=begin
On 1.8 you couldn't freeze an immediate. On 1.9 you can. Presumably this is a bug.

$ ruby -ve 'a=true;a.freeze;p a.frozen?'
ruby 1.9.2dev (2009-07-08 trunk 23995) [i686-linux]
true

$ ruby8 -ve 'a=true;a.freeze;p a.frozen?'
ruby 1.8.8dev (2009-07-01) [i686-linux]
false
=end

History

#1

Updated by mame (Yusuke Endoh) over 10 years ago

=begin
Hi,

2009/7/9 Run Paint Run Run redmine@ruby-lang.org:

Bug #1747: Immediate Values Can be Frozen
http://redmine.ruby-lang.org/issues/show/1747

Author: Run Paint Run Run
Status: Open, Priority: Normal
Category: core
ruby -v: ruby 1.9.2dev (2009-07-08 trunk 23995) [i686-linux]

On 1.8 you couldn't freeze an immediate. On 1.9 you can. Presumably this is a bug.

$ ruby -ve 'a=true;a.freeze;p a.frozen?'
ruby 1.9.2dev (2009-07-08 trunk 23995) [i686-linux]
true

$ ruby8 -ve 'a=true;a.freeze;p a.frozen?'
ruby 1.8.8dev (2009-07-01) [i686-linux]
false

It seems to be an intentional change for the following use case:

# http://nov.tdiary.net/20071215.html#p02 (In Japanese)
CONST2 = ["hoge", 1].freeze
CONST2.each(&:freeze).all?(&:frozen?) #=> false (expected true)

I have no idea whether the the rationale is sensible or not.
If the compatibility can be ignored, it would be more reasonable that
all immediate values are frozen as a default.

--
Yusuke ENDOH mame@tsg.ne.jp

=end

#2

Updated by mame (Yusuke Endoh) over 10 years ago

=begin
2009/7/10 Gary Wright gwtmp01@mac.com:

On Jul 9, 2009, at 12:15 AM, Yusuke ENDOH wrote:

It seems to be an intentional change for the following use case:

 # http://nov.tdiary.net/20071215.html#p02 (In Japanese)
 CONST2 = ["hoge", 1].freeze
 CONST2.each(&:freeze).all?(&:frozen?) #=> false (expected true)

I have no idea whether the the rationale is sensible or not.
If the compatibility can be ignored, it would be more reasonable that
all immediate values are frozen as a default.

Making Fixnum instances frozen by default would break code that depended on
instance variable state:

class Fixnum
 attr_accessor :note
end

42.note = 'the meaning of life'

I see. Then, the current behavior of 1.9 seems to me to be reasonable.

--
Yusuke ENDOH mame@tsg.ne.jp

=end

#3

Updated by runpaint (Run Paint Run Run) over 10 years ago

=begin
Defining instance methods on Fixnum instances seems a particularly contrived case, even for ruby-core. ;-) The troubled soul wishing to engage in such hackery could surely stretch as far as using a Struct to wrap his annotated numerals? Note that freezing immediates does not imply freezing their classes; singleton methods could still be added if desired.

In addition, it makes little conceptual sense to freeze a value that is frozen by definition. This is especially obvious when you consider that because immediates can't be dup'd, they can never be thawed. The abstraction is broken.

Triskadekaphobiacs are presumably upset that, although 13.untrust appears to succeed and reinforce their beliefs, the state doesn't stick; 13.untrusted? subsequently returns false. Similarly, logicians and cynics alike must, respectively, rejoice and despair that true.untrust.untrusted? is perpetually false.

It is irrational in equal measures to #freeze an immediate as it is to #dup it; to #taint truth (true) as it is to assign to it; to #trust the unknowable (nil) as it is to #untrust it.

If methods don't make a sense for an object, they shouldn't appear to work. :-)
=end

#4

Updated by mame (Yusuke Endoh) over 10 years ago

=begin
Hi,

2009/7/11 Run Paint Run Run redmine@ruby-lang.org:

Defining instance methods on Fixnum instances seems a particularly contrived case, even for ruby-core. ;-)

Please don't count on me so much ;-)

Triskadekaphobiacs are presumably upset that, although 13.untrust appears to succeed and reinforce their beliefs, the state doesn't stick; 13.untrusted? subsequently returns false. Similarly, logicians and cynics alike must, respectively, rejoice and despair that true.untrust.untrusted? is perpetually false.

Whoa! The current behavior of 1.9 is never reasonable.
Here is a patch:

Index: object.c
===================================================================
--- object.c (revision 24034)
+++ object.c (working copy)
@@ -641,6 +641,8 @@
return Qnil;
}

+static st_table immediate_tainted_tbl = 0;
+
/

  • call-seq:
  • obj.tainted? => true or false @@ -653,6 +655,10 @@ { if (OBJ_TAINTED(obj)) return Qtrue;
    • if (SPECIAL_CONST_P(obj)) {
    • if (!immediate_tainted_tbl) return Qfalse;
    • if (st_lookup(immediate_tainted_tbl, obj, 0)) return Qtrue;
    • } return Qfalse; }

@@ -674,6 +680,12 @@
rb_error_frozen("object");
}
OBJ_TAINT(obj);

  • if (SPECIAL_CONST_P(obj)) {
  • if (!immediate_tainted_tbl) {
  • immediate_tainted_tbl = st_init_numtable();
  • }
  • st_insert(immediate_tainted_tbl, obj, (st_data_t)Qtrue);
  • } } return obj; } @@ -696,9 +708,14 @@ } FL_UNSET(obj, FL_TAINT); }
  • if (SPECIAL_CONST_P(obj) && immediate_tainted_tbl) {
  • st_delete(immediate_tainted_tbl, &obj, NULL);
  • } return obj; }

+static st_table immediate_untrusted_tbl = 0;
+
/

  • call-seq:
  • obj.untrusted? => true or false @@ -711,6 +728,10 @@ { if (OBJ_UNTRUSTED(obj)) return Qtrue;
    • if (SPECIAL_CONST_P(obj)) {
    • if (!immediate_untrusted_tbl) return Qfalse;
    • if (st_lookup(immediate_untrusted_tbl, obj, 0)) return Qtrue;
    • } return Qfalse; }

@@ -730,6 +751,12 @@
rb_error_frozen("object");
}
OBJ_UNTRUST(obj);

  • if (SPECIAL_CONST_P(obj)) {
  • if (!immediate_untrusted_tbl) {
  • immediate_untrusted_tbl = st_init_numtable();
  • }
  • st_insert(immediate_untrusted_tbl, obj, (st_data_t)Qtrue);
  • } } return obj; } @@ -752,6 +779,9 @@ } FL_UNSET(obj, FL_UNTRUSTED); }
  • if (SPECIAL_CONST_P(obj) && immediate_untrusted_tbl) {
  • st_delete(immediate_untrusted_tbl, &obj, NULL);
  • } return obj; }

Maybe it is best to freeze all immediates (+ bignum) by default.
If Gary's example is needed at any cost, it can probably be rewrited
without using instance variables.

class Fixnum
h = {}
define_method(:note=) {|x| h[self] = x }
define_method(:note) { h[self] }
end

42.note = "the answer"
p 42.note

At any rate, I think that this is a talk about the future, perhaps
after Ruby 2.0.

--
Yusuke ENDOH mame@tsg.ne.jp

=end

#5

Updated by runpaint (Run Paint Run Run) over 10 years ago

=begin

Triskadekaphobiacs are presumably upset that, although 13.untrust appears to succeed and reinforce their beliefs, the state doesn't stick; 13.untrusted? subsequently returns false. Similarly, logicians and cynics alike must, respectively, rejoice and despair that true.untrust.untrusted? is perpetually false.

Whoa!  The current behavior of 1.9 is never reasonable.
Here is a patch:

Thank you, Yusuke. :-) While I would prefer that immediates couldn't
be tainted/untrusted, I accept that's a topic for the future. For now,
that patch would certainly restore some sanity. :-)

=end

#6

Updated by yugui (Yuki Sonoda) over 10 years ago

  • Target version set to 1.9.2

=begin

=end

#7

Updated by nobu (Nobuyoshi Nakada) over 10 years ago

  • Assignee set to matz (Yukihiro Matsumoto)

=begin

=end

#8

Updated by ujihisa (Tatsuhiro Ujihisa) about 10 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

=begin
This issue seems to be closed already except that the topic for the future if immediates couldn't be tainted/untrusted.
=end

Also available in: Atom PDF