ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: eregontp@gmail.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:95660] [Ruby master Feature#16153] eventually_frozen flag to gradually phase-in frozen strings
Date: Sun, 03 Nov 2019 16:58:24 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-82449.20191103165823.4d142ce0c8ba219f@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-16153.20190909021526@ruby-lang.org

Issue #16153 has been updated by Eregon (Benoit Daloze).


For this discussion, I would focus on having this for Strings only initially.
I don't think it's about the "grand design of immutability", but rather a tool to ease migration towards frozen Strings for some APIs.

My main concern about it would be that such strings are reported as Kernel#frozen? but actually are not. That is some inconsistency.
I think it would be more logical to return `false` for Kernel#frozen? and just have String#+@/String#dup make a copy without the eventually_frozen flag.

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

* 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, and tests might not cover the cases of frozen input vs non-frozen input.

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 act as a pseudo-frozen flag where mutating the object would result in a warning instead of an error. It would also change the return value of `Object#frozen?` so code like `obj = obj.dup if obj.frozen?` would work as expected to remove the warning. 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 might 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 (or as a global switch), 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(immediately:true)
   * if `immediately` keyword is true, set frozen=true and eventually_frozen=false
   * if `immediately` keyword is false, set eventually_frozen=true UNLESS frozen flag is already true
* String#+@
   * if eventually_frozen is true, create a duplicate string with eventually_frozen=false
* Object#frozen?(immediately:false)
   * return true if `immediately` keyword is false and eventually_frozen flag is true
* rb_check_frozen
   * output warning if eventually_frozen flag is true

Alternatively, setting the eventually_frozen flag is not possible via ruby code. Object#freeze behaves as if `immediately=true`, and a C macro like `OBJ_EVENTUAL_FREEZE` is used in `rb_sym_to_s` and others to get the `immediately=false` behavior.



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

  parent reply	other threads:[~2019-11-03 16:58 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-16153.20190909021526@ruby-lang.org>
2019-09-09  2:15 ` [ruby-core:94851] [Ruby master Feature#16153] eventually_frozen flag to gradually phase-in frozen strings daniel
2019-09-19  9:11 ` [ruby-core:94986] " duerst
2019-09-19 18:46 ` [ruby-core:94992] " daniel
2019-09-20 11:32 ` [ruby-core:95003] " duerst
2019-09-21  8:33 ` [ruby-core:95016] " shevegen
2019-09-21 16:27 ` [ruby-core:95018] " mame
2019-09-23 20:43 ` [ruby-core:95046] " daniel
2019-11-01 13:56 ` [ruby-core:95635] " daniel
2019-11-03 16:52 ` [ruby-core:95659] " eregontp
2019-11-03 16:58 ` eregontp [this message]
2019-11-04 16:17 ` [ruby-core:95669] " daniel
2019-11-06 10:49 ` [ruby-core:95721] " eregontp
2019-11-06 11:09 ` [ruby-core:95723] " jean.boussier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-82449.20191103165823.4d142ce0c8ba219f@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).