[ruby-core:94851] [Ruby master Feature#16153] eventually_frozen flag to gradually phase-in frozen strings
From:
daniel@...42.com
Date:
2019-09-09 02:15:27 UTC
List:
ruby-core #94851
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>