Project

General

Profile

Actions

Bug #1747

closed

Immediate Values Can be Frozen

Added by runpaint (Run Paint Run Run) over 14 years ago. Updated almost 13 years ago.

Status:
Closed
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

Actions #1

Updated by mame (Yusuke Endoh) over 14 years ago

=begin
Hi,

2009/7/9 Run Paint Run Run :

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

=end

Actions #2

Updated by mame (Yusuke Endoh) over 14 years ago

=begin
2009/7/10 Gary Wright :

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

=end

Actions #3

Updated by runpaint (Run Paint Run Run) over 14 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

Actions #4

Updated by mame (Yusuke Endoh) over 14 years ago

=begin
Hi,

2009/7/11 Run Paint Run Run :

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

=end

Actions #5

Updated by runpaint (Run Paint Run Run) over 14 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

Actions #6

Updated by yugui (Yuki Sonoda) over 14 years ago

  • Target version set to 1.9.2

=begin

=end

Actions #7

Updated by nobu (Nobuyoshi Nakada) over 14 years ago

  • Assignee set to matz (Yukihiro Matsumoto)

=begin

=end

Actions #8

Updated by ujihisa (Tatsuhiro Ujihisa) over 14 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

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0