Issue #16153 has been reported by Dan0042 (Daniel DeLorme).

----------------------------------------
Feature #16153: eventually_frozen flag to gradually phase-in frozen strings
https://bugs.ruby-lang.org/issues/16153

* Author: Dan0042 (Daniel DeLorme)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Freezing objects can give us a nice performance boost, but freezing previously non-frozen objects is a backward-incompatible change which is hard to handle because the place where the object is mutated can be far from where it was frozen.

I propose adding a flag which gives us a migration path for freezing objects. For purposes of discussion I will call this flag "eventually_frozen". It would change the behavior of the frozen flag so that mutating the object would result in a warning instead of an error. So code like `obj = obj.dup if obj.frozen?` and `+str` would work as expected. Note that eventually_frozen strings cannot be deduplicated, as they are in reality mutable.

This way it would be possible for Symbol#to_s (and many others) to return an eventually_frozen string in 2.7 which gives apps and gems time to migrate, before finally becoming a frozen deduplicated string in 3.0. This could even open up a migration path for eventually using `frozen_string_literal:true` as default. For example if it was possible to add `frozen_string_literal:eventual` to all files in a project, we could run that in production to discover where to fix things, and then change it to `frozen_string_literal:true` for a bug-free performance boost.

Proposed changes:
* Object#freeze(eventual:false)
   * if `eventual` is false
      * set frozen=true and eventually_frozen=false
   * if `eventual` is true
      * set frozen=true and eventually_frozen=true UNLESS frozen is already true
* String#-@
   * if eventually_frozen is true, deduplicate the string as if it was non-frozen
* Object#frozen?(eventual:true)
   * if `eventual` is false
      * return (frozen==true and eventually_frozen==false)
   * if `eventual` is true
      * return (frozen==true)
* rb_check_frozen
   * if eventually_frozen is true 
      * output warning
   * if eventually_frozen is false and frozen is true
      * raise error




-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>