From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on starla X-Spam-Level: X-Spam-Status: No, score=-1.1 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,MAILING_LIST_MULTI,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 Received: from nue.mailmanlists.eu (nue.mailmanlists.eu [IPv6:2a01:4f8:1c0c:6b10::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id D82E31F405 for ; Thu, 25 Jan 2024 14:33:43 +0000 (UTC) Authentication-Results: dcvr.yhbt.net; dkim=pass (1024-bit key; secure) header.d=ml.ruby-lang.org header.i=@ml.ruby-lang.org header.a=rsa-sha256 header.s=mail header.b=o5rFnncF; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=ruby-lang.org header.i=@ruby-lang.org header.a=rsa-sha256 header.s=s1 header.b=mHgOZws9; dkim-atps=neutral Received: from nue.mailmanlists.eu (localhost [127.0.0.1]) by nue.mailmanlists.eu (Postfix) with ESMTP id BDA2C81F42; Thu, 25 Jan 2024 14:33:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ml.ruby-lang.org; s=mail; t=1706193214; bh=kS4dt9n2zcjLHStyyRZdtoal0iZ7J1B21FbQp+ESBDg=; h=Date:References:To:Reply-To:Subject:List-Id:List-Archive: List-Help:List-Owner:List-Post:List-Subscribe:List-Unsubscribe: From:Cc:From; b=o5rFnncF1C85TMZF/iUpGaEZZc49xxiA/c2oeBNfJ7wTxUA7wzUqoATQsj1awg9ok g8rxBtdnQf40CeLaCJBj5mW50prHOFWftT0rKJ6Du1axqH7InolhKaGFcHTFJh80yo LiW4c54BnOhRSFWuJRKxn+33GaUorU2dPaX6TJ6w= Received: from csnrwnwx.outbound-mail.sendgrid.net (csnrwnwx.outbound-mail.sendgrid.net [198.37.146.154]) by nue.mailmanlists.eu (Postfix) with ESMTPS id 9400781F2E for ; Thu, 25 Jan 2024 14:33:30 +0000 (UTC) Authentication-Results: nue.mailmanlists.eu; dkim=pass (2048-bit key; unprotected) header.d=ruby-lang.org header.i=@ruby-lang.org header.a=rsa-sha256 header.s=s1 header.b=mHgOZws9; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ruby-lang.org; h=from:references:subject:mime-version:content-type: content-transfer-encoding:list-id:to:cc:content-type:from:subject:to; s=s1; bh=VrtfWvN8UJiyvCk+AzdXvTJ14YumU7vXJVLNW25JwnE=; b=mHgOZws9aCeXixU+QYHyN1E0l0ER2aKjV62IxGGqklGQ6rtmzZW8Ms7rX5rF0bGkqibD lGMB12kQ7ro5a+8CaRj2C+BH+EFxoEyJEh/+aLRcLJUZuNbj/GzV0wK2ehB77ZMyovZDLT +dNdpHcreZEOSTCYYgu5vBM3RiaqOTA+0ZoLqFi+zAlNvQ7PDwArDj+dqq6N23klvOOcqa uFI+Q9nmOeEMGi1CdVOXWwTH3SZrsnGwbXhthazyF16D5oIbmO5iLXMF09aC1IPh0JEPgj 5RmY3cZSOzVVLPiUCQ1d13ZAkCaUr+DO5YT7m5o2bLiEgThJgNVNzOdpmMBgKtmQ== Received: by recvd-6f5889c959-9b587 with SMTP id recvd-6f5889c959-9b587-1-65B27138-12 2024-01-25 14:33:28.42527669 +0000 UTC m=+51689.055408643 Received: from herokuapp.com (unknown) by geopod-ismtpd-28 (SG) with ESMTP id fx41821KT1uLoJKaqic1bA for ; Thu, 25 Jan 2024 14:33:28.380 +0000 (UTC) Date: Thu, 25 Jan 2024 14:33:28 +0000 (UTC) Message-ID: References: Mime-Version: 1.0 X-Redmine-Project: ruby-master X-Redmine-Issue-Tracker: Feature X-Redmine-Issue-Id: 20205 X-Redmine-Issue-Author: byroot X-Redmine-Sender: byroot X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: All Auto-Submitted: auto-generated X-Redmine-MailingListIntegration-Message-Ids: 93002 X-SG-EID: =?us-ascii?Q?Dq8GNIcVqP8cs5uR+EIAabfg3LE9XdC6dZ5KYNrMpf6VzBWG6HqArcu5raQjXL?= =?us-ascii?Q?IGTFdxKHUt7++67+KD54pNYXheirMcsUIf3sdgF?= =?us-ascii?Q?Riq06jGQSJW93NMt2iknkXudTFZ+zVHOrxmoUvn?= =?us-ascii?Q?=2FQ5oT6aWTNpTdnXT8NfZ46=2FqBHf90qqBl33hkii?= =?us-ascii?Q?rVYSnl14oqwTS8tHUkhfjrCmTOUuHCnM5cfK=2F1=2F?= =?us-ascii?Q?9tKG+XMH9qyKVJu=2FpyL+y6ZRDj5uzxRSa=2FNVQ+b?= =?us-ascii?Q?O7O8LInCkM21Nq0VKWXTQ=3D=3D?= To: ruby-core@ml.ruby-lang.org X-Entity-ID: b/2+PoftWZ6GuOu3b0IycA== Message-ID-Hash: NHK34PCUAHB3XIIJQVZF3ILML5YU3OPL X-Message-ID-Hash: NHK34PCUAHB3XIIJQVZF3ILML5YU3OPL X-MailFrom: bounces+313651-b711-ruby-core=ml.ruby-lang.org@em5188.ruby-lang.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.3 Precedence: list Reply-To: Ruby developers Subject: [ruby-core:116445] [Ruby master Feature#20205] Enable `frozen_string_literal` by default List-Id: Ruby developers Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: "byroot (Jean Boussier) via ruby-core" Cc: "byroot (Jean Boussier)" Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Issue #20205 has been updated by byroot (Jean Boussier). > The worst case is -6% on setivar_object This is a fluke caused by random slowdown on my development machine. Here's the benchmark source: https://github.com/Shopify/yjit-bench/blob/3774b4bc320519f8b560eb23bdea48f549cf8b30/benchmarks/setivar_object.rb There is absolutely nothing in there influenced by frozen strings. I'm somewhat confident on the 5% figure for lobsters because I ran it alone about 10 times and always got 5%. But running the full suite on my machine takes way too long to do that for all benchmarks. I shouldn't have ran the micro-benchmarks anyway, only the headline benchmarks make sense. What is certain is that turning on `frozen_string_literal` cannot possibly have a negative performance impact. Only null or positive. So don't lean to much on these preliminary results. ---------------------------------------- Feature #20205: Enable `frozen_string_literal` by default https://bugs.ruby-lang.org/issues/20205#change-106469 * Author: byroot (Jean Boussier) * Status: Open * Priority: Normal ---------------------------------------- ### Context The `frozen_string_literal: true` pragma was introduced in Ruby 2.3, and as far as I'm aware the plan was initially to make it the default for Ruby 3.0, but this plan was abandoned because it would be too much of a breaking change without any real further notice. According to Matz, he still wishes to enable `frozen_string_literal` by default in the future, but a reasonable migration plan is required. The main issue is backward compatibility, flipping the switch immediately would break a lot of code, so there must be some deprecation period. The usual the path forward for this kind of change is to emit deprecation warnings one of multiple versions in advance. One example of that was the Ruby 2.7 keyword argument deprecation. It was quite verbose, and some users were initially annoyed, but I think the community pulled through it and I don't seem to hear much about it anymore. So for frozen string literals, the first step would be to start warning when a string that would be frozen in the future is mutated. ### Deprecation Warning Implementation I implemented a quick proof of concept with @etienne in https://github.com/Shopify/ruby/pull/549 In short: - Files with `# frozen_string_literal: true` or `# frozen_string_literal: false` don't change in behavior at all. - Files with no `# frozen_string_literal` comment are compiled to use `putchilledstring` opcode instead of regular `putstring`. - This opcode mark the string with a user flag, when these strings are mutated, a warning is issued. Currently the proof of concept issue the warning at the mutation location, which in some case can make locating where the string was allocated a bit hard. But it is possible to improve it so the message also include the location at which the literal string was allocated, and learning from the keyword argument warning experience, we can record which warnings were already issued to avoid spamming users with duplicated warnings. As currently implemented, there is almost no overhead. If we modify the implementation to record the literal location, we'd incur a small memory overhead for each literal string in a file without an explicit `frozen_string_literal` pragma. But I believe we could do it in a way that has no overhead if `Warning[:deprecated] = false`. ### Timeline The migration would happen in 3 steps, each step can potentially last multiple releases. e.g. `R0` could be `3.4`, `R1` be `3.7` and `R2` be `4.0`. I don't have a strong opinion on the pace. - Release `R0`: introduce the deprecation warning (only if deprecation warnings enabled). - Release `R1`: make the deprecation warning show up regardless of verbosity level. - Release `R2`: make string literals frozen by default. ### Impact Given that `rubocop` is quite popular in the community and it has enforced the usage of `# frozen_string_literal: true` for years now, I suspect a large part of the actively maintained codebases in the wild wouldn't see any warnings. And with recent versions of `minitest` enabling deprecation warnings by default (and [potentially RSpec too](https://github.com/rspec/rspec-core/issues/2867)), the few that didn't migrate will likely be made compatible quickly. The real problem of course are the less actively developed libraries and applications. For such cases, any codebase can remain compatible by setting `RUBYOPT="--disable=frozen_string_literal"`, and so even after `R2` release. The flag would never be removed any legacy codebase can continue upgrading Ruby without changing a single line of cod by just flipping this flag. ### Workflow for library maintainers As a library maintainer, fixing the deprecation warnings can be as simple as prepending `# frozen_string_literal: false` at the top of all their source files, and this will keep working forever. Alternatively they can of course make their code compatible with frozen string literals. Code that is frozen string literal compatible doesn't need to explicitly declare it. Only code that need it turned of need to do so. ### Workflow for application owners For application owners, the workflow is the same than for libraries. However if they depend on a gem that hasn't updated, or that they can't upgrade it, they can run their application with `RUBYOPT="--disable=frozen_string_literal"` and it will keep working forever. Any user running into an incompatibility issue can set `RUBYOPT="--disable=frozen_string_literal"` forever, even in `4.x`, the only thing changing is the default value. And any application for which all dependencies have been made fully frozen string literal compatible can set `RUBYOPT="--enable=frozen_string_literal"` and start immediately removing magic comment from their codebase. -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/