[ruby-core:126656] [Ruby Feature#22304] Add rb_warn_to_remove_at() for deprecation warnings shown by default
Issue #22304 has been reported by shugo (Shugo Maeda). ---------------------------------------- Feature #22304: Add rb_warn_to_remove_at() for deprecation warnings shown by default https://bugs.ruby-lang.org/issues/22304 * Author: shugo (Shugo Maeda) * Status: Open ---------------------------------------- Deprecations such as #22205 and #22276 are scheduled in phases: a warning shown only when `Warning[:deprecated]` is enabled, then a warning shown by default, then the removal. For the first phase, `rb_warn_deprecated_to_remove_at(X.Y, fmt, suggest, ...)` (#17432) prints "... is deprecated and will be removed in Ruby X.Y", and a RUBY_DEBUG build fails to compile when the version reaches X.Y. For the second phase, there is no equivalent API. A warning with the `:deprecated` category is suppressed by default by definition, so the warning must be emitted with `rb_warn` without a category, and the message and the version check have to be written by hand. I propose to add `rb_warn_to_remove_at(X.Y, fmt, suggest, ...)` to internal/error.h: the same message and compile-time check, emitted with `rb_warn`. The name does not contain "deprecated" because `rb_warn_deprecated*` means a warning gated by `Warning[:deprecated]`. -- https://bugs.ruby-lang.org/
Issue #22304 has been updated by shugo (Shugo Maeda). In addition, how about a higher-level macro that takes both versions of the schedule? ```c rb_warn_scheduled_deprecation(4.2, 4.3, fmt, suggest, ...) ``` Before 4.2 it warns only when `Warning[:deprecated]` is enabled, from 4.2 it warns by default via `rb_warn_to_remove`, and at 4.3 a RUBY_DEBUG build fails to compile. The version check is done at compile time, so the phase switches automatically on a version bump and cannot be forgotten. #22276 and #22273 can use it in 4.1 already, with no behavior change until 4.2. ---------------------------------------- Feature #22304: Add rb_warn_to_remove_at() for deprecation warnings shown by default https://bugs.ruby-lang.org/issues/22304#change-119066 * Author: shugo (Shugo Maeda) * Status: Open ---------------------------------------- Deprecations such as #22205 and #22276 are scheduled in phases: a warning shown only when `Warning[:deprecated]` is enabled, then a warning shown by default, then the removal. For the first phase, `rb_warn_deprecated_to_remove_at(X.Y, fmt, suggest, ...)` (#17432) prints "... is deprecated and will be removed in Ruby X.Y", and a RUBY_DEBUG build fails to compile when the version reaches X.Y. For the second phase, there is no equivalent API. A warning with the `:deprecated` category is suppressed by default by definition, so the warning must be emitted with `rb_warn` without a category, and the message and the version check have to be written by hand. I propose to add `rb_warn_to_remove_at(X.Y, fmt, suggest, ...)` to internal/error.h: the same message and compile-time check, emitted with `rb_warn`. The name does not contain "deprecated" because `rb_warn_deprecated*` means a warning gated by `Warning[:deprecated]`. -- https://bugs.ruby-lang.org/
Issue #22304 has been updated by shugo (Shugo Maeda). I've created a pull request: https://github.com/ruby/ruby/pull/18904 ---------------------------------------- Feature #22304: Add rb_warn_to_remove_at() for deprecation warnings shown by default https://bugs.ruby-lang.org/issues/22304#change-119071 * Author: shugo (Shugo Maeda) * Status: Open ---------------------------------------- Deprecations such as #22205 and #22276 are scheduled in phases: a warning shown only when `Warning[:deprecated]` is enabled, then a warning shown by default, then the removal. For the first phase, `rb_warn_deprecated_to_remove_at(X.Y, fmt, suggest, ...)` (#17432) prints "... is deprecated and will be removed in Ruby X.Y", and a RUBY_DEBUG build fails to compile when the version reaches X.Y. For the second phase, there is no equivalent API. A warning with the `:deprecated` category is suppressed by default by definition, so the warning must be emitted with `rb_warn` without a category, and the message and the version check have to be written by hand. I propose to add `rb_warn_to_remove_at(X.Y, fmt, suggest, ...)` to internal/error.h: the same message and compile-time check, emitted with `rb_warn`. The name does not contain "deprecated" because `rb_warn_deprecated*` means a warning gated by `Warning[:deprecated]`. -- https://bugs.ruby-lang.org/
Issue #22304 has been updated by Dan0042 (Daniel DeLorme). I like the idea, but the issue with version numbers is that major version jumps break linear assumptions. For example, in 2023 (Ruby 3.3), if we want to deprecate something in 3 years, we might target 3.6. But as Ruby jumped from 3.4 to 4.0, then 3.6 never exists; 4.1 is the actual 3-year mark. Because versions don't scale linearly with time, specifying a target year (e.g., 2026) or a relative year offset (e.g., 3) in rb_warn_scheduled_deprecation is much safer. This also enables a useful ENV flag to filter warnings by horizon: * RUBY_DEPRECATION_HORIZON=5: Show all deprecations coming up in the next 5 years. * RUBY_DEPRECATION_HORIZON=1: Only show warnings due immediately next version. * RUBY_DEPRECATION_HORIZON=0: No warwnings. ---------------------------------------- Feature #22304: Add rb_warn_to_remove_at() for deprecation warnings shown by default https://bugs.ruby-lang.org/issues/22304#change-119077 * Author: shugo (Shugo Maeda) * Status: Open ---------------------------------------- Deprecations such as #22205 and #22276 are scheduled in phases: a warning shown only when `Warning[:deprecated]` is enabled, then a warning shown by default, then the removal. For the first phase, `rb_warn_deprecated_to_remove_at(X.Y, fmt, suggest, ...)` (#17432) prints "... is deprecated and will be removed in Ruby X.Y", and a RUBY_DEBUG build fails to compile when the version reaches X.Y. For the second phase, there is no equivalent API. A warning with the `:deprecated` category is suppressed by default by definition, so the warning must be emitted with `rb_warn` without a category, and the message and the version check have to be written by hand. I propose to add `rb_warn_to_remove_at(X.Y, fmt, suggest, ...)` to internal/error.h: the same message and compile-time check, emitted with `rb_warn`. The name does not contain "deprecated" because `rb_warn_deprecated*` means a warning gated by `Warning[:deprecated]`. -- https://bugs.ruby-lang.org/
Issue #22304 has been updated by shugo (Shugo Maeda). Thank you for the idea. I think the API should keep the version numbers, because the warning message has to tell users the version ("will be removed in Ruby 4.3"), and a year cannot be converted to a version at compile time. A major version jump does not cause a silent problem. For example, when the version jumps from 3.4 to 4.0, a schedule such as (3.5, 3.6) is reached at once, and a RUBY_DEBUG build fails to compile at the removal check, exactly as `rb_warn_deprecated_to_remove_at` does today. So each schedule has to be reviewed and rewritten by hand at a major bump, which we should do anyway. A horizon filter like `RUBY_DEPRECATION_HORIZON` sounds useful, but it is a separate run-time mechanism (an environment variable and a version comparison), so how about proposing it in a separate ticket? ---------------------------------------- Feature #22304: Add rb_warn_to_remove_at() for deprecation warnings shown by default https://bugs.ruby-lang.org/issues/22304#change-119078 * Author: shugo (Shugo Maeda) * Status: Open ---------------------------------------- Deprecations such as #22205 and #22276 are scheduled in phases: a warning shown only when `Warning[:deprecated]` is enabled, then a warning shown by default, then the removal. For the first phase, `rb_warn_deprecated_to_remove_at(X.Y, fmt, suggest, ...)` (#17432) prints "... is deprecated and will be removed in Ruby X.Y", and a RUBY_DEBUG build fails to compile when the version reaches X.Y. For the second phase, there is no equivalent API. A warning with the `:deprecated` category is suppressed by default by definition, so the warning must be emitted with `rb_warn` without a category, and the message and the version check have to be written by hand. I propose to add `rb_warn_to_remove_at(X.Y, fmt, suggest, ...)` to internal/error.h: the same message and compile-time check, emitted with `rb_warn`. The name does not contain "deprecated" because `rb_warn_deprecated*` means a warning gated by `Warning[:deprecated]`. -- https://bugs.ruby-lang.org/
Issue #22304 has been updated by Dan0042 (Daniel DeLorme). shugo (Shugo Maeda) wrote in #note-5:
a year cannot be converted to a version at compile time.
I don't understand why converting a year to a version at compile time would be needed. We would need to compare `year >= RUBY_RELEASE_YEAR` at compile time for the hard removal check. But for runtime deprecation warnings, displaying the target version is just a simple year-to-version mapping in a central place. When a major version bump happens, we update that single mapping, instead of editing N places across the codebase where someone hardcoded the wrong version. That seems much less error-prone. (Also, as a C habit, I have a bias toward passing integers rather than floats or strings.)
each schedule has to be reviewed and rewritten by hand at a major bump, which we should do anyway.
Sorry for the trouble, but could you explain why "we should do anyway"? I might be missing something here.
A horizon filter like `RUBY_DEPRECATION_HORIZON` ... how about proposing it in a separate ticket?
Fair enough! I can open a separate ticket for that. Though it only works if we switch to year-based targets, as version numbers make dynamic horizons tricky to calculate. ---------------------------------------- Feature #22304: Add rb_warn_to_remove_at() for deprecation warnings shown by default https://bugs.ruby-lang.org/issues/22304#change-119086 * Author: shugo (Shugo Maeda) * Status: Open ---------------------------------------- Deprecations such as #22205 and #22276 are scheduled in phases: a warning shown only when `Warning[:deprecated]` is enabled, then a warning shown by default, then the removal. For the first phase, `rb_warn_deprecated_to_remove_at(X.Y, fmt, suggest, ...)` (#17432) prints "... is deprecated and will be removed in Ruby X.Y", and a RUBY_DEBUG build fails to compile when the version reaches X.Y. For the second phase, there is no equivalent API. A warning with the `:deprecated` category is suppressed by default by definition, so the warning must be emitted with `rb_warn` without a category, and the message and the version check have to be written by hand. I propose to add `rb_warn_to_remove_at(X.Y, fmt, suggest, ...)` to internal/error.h: the same message and compile-time check, emitted with `rb_warn`. The name does not contain "deprecated" because `rb_warn_deprecated*` means a warning gated by `Warning[:deprecated]`. -- https://bugs.ruby-lang.org/
Issue #22304 has been updated by shugo (Shugo Maeda). Dan0042 (Daniel DeLorme) wrote in #note-6:
Sorry for the trouble, but could you explain why "we should do anyway"? I might be missing something here.
A major version bump is a chance to introduce incompatibilities, so I think we should decide for each deprecation whether to keep the schedule or to remove it at the major version. My intention was not to make the schedule fully automatic, but to make it fail-safe. I also see two problems with years: * `RUBY_RELEASE_YEAR` is the date of the commit or the release, so it advances with every patch release, and a compile-time check on it would fail on stable branches. * The yearly release is a convention, not a guarantee. If a release is delayed or skipped, a year-based schedule silently changes its meaning. If we introduce a new macro for the compile-time check instead of `RUBY_RELEASE_YEAR`, a serial number like `RUBY_MINOR_CODE`, which is bumped for each minor version, may be better than a year. ---------------------------------------- Feature #22304: Add rb_warn_to_remove_at() for deprecation warnings shown by default https://bugs.ruby-lang.org/issues/22304#change-119089 * Author: shugo (Shugo Maeda) * Status: Open ---------------------------------------- Deprecations such as #22205 and #22276 are scheduled in phases: a warning shown only when `Warning[:deprecated]` is enabled, then a warning shown by default, then the removal. For the first phase, `rb_warn_deprecated_to_remove_at(X.Y, fmt, suggest, ...)` (#17432) prints "... is deprecated and will be removed in Ruby X.Y", and a RUBY_DEBUG build fails to compile when the version reaches X.Y. For the second phase, there is no equivalent API. A warning with the `:deprecated` category is suppressed by default by definition, so the warning must be emitted with `rb_warn` without a category, and the message and the version check have to be written by hand. I propose to add `rb_warn_to_remove_at(X.Y, fmt, suggest, ...)` to internal/error.h: the same message and compile-time check, emitted with `rb_warn`. The name does not contain "deprecated" because `rb_warn_deprecated*` means a warning gated by `Warning[:deprecated]`. -- https://bugs.ruby-lang.org/
Issue #22304 has been updated by Dan0042 (Daniel DeLorme).
A major version bump is a chance to introduce incompatibilities, so I think we should decide for each deprecation whether to keep the schedule or to remove it at the major version.
Ok I see, that makes sense. It might also be useful to say "deprecate this at v5.0" no matter what year it turns out to be. So what do you think should happen to 2023-12-25 Ruby 3.3.0 new message: feature X will be deprecated in Ruby 3.6 2025-12-25 Ruby 4.0.0 changed to: feature X will be deprecated in Ruby 4.1 2026-03-26 Ruby 3.3.11 keep incorrect "3.6" message or update to "4.1" ? Does the updated target version need to be backported to every branch ? ---------------------------------------- Feature #22304: Add rb_warn_to_remove_at() for deprecation warnings shown by default https://bugs.ruby-lang.org/issues/22304#change-119119 * Author: shugo (Shugo Maeda) * Status: Open ---------------------------------------- Deprecations such as #22205 and #22276 are scheduled in phases: a warning shown only when `Warning[:deprecated]` is enabled, then a warning shown by default, then the removal. For the first phase, `rb_warn_deprecated_to_remove_at(X.Y, fmt, suggest, ...)` (#17432) prints "... is deprecated and will be removed in Ruby X.Y", and a RUBY_DEBUG build fails to compile when the version reaches X.Y. For the second phase, there is no equivalent API. A warning with the `:deprecated` category is suppressed by default by definition, so the warning must be emitted with `rb_warn` without a category, and the message and the version check have to be written by hand. I propose to add `rb_warn_to_remove_at(X.Y, fmt, suggest, ...)` to internal/error.h: the same message and compile-time check, emitted with `rb_warn`. The name does not contain "deprecated" because `rb_warn_deprecated*` means a warning gated by `Warning[:deprecated]`. -- https://bugs.ruby-lang.org/
Issue #22304 has been updated by shugo (Shugo Maeda). Dan0042 (Daniel DeLorme) wrote in #note-8:
Does the updated target version need to be backported to every branch ?
There is a similar case. Ruby 3.3 still says "Process::Status#& is deprecated and will be removed in Ruby 3.4", although the removal was postponed to 3.5 on master and 3.4 was released without removing it. The message was not backported. But I don't know whether that was a deliberate decision, so I would like to hear the opinion of the stable branch maintainers. @hsbt @nagachika @k0kubun What do you think? ---------------------------------------- Feature #22304: Add rb_warn_to_remove_at() for deprecation warnings shown by default https://bugs.ruby-lang.org/issues/22304#change-119121 * Author: shugo (Shugo Maeda) * Status: Open ---------------------------------------- Deprecations such as #22205 and #22276 are scheduled in phases: a warning shown only when `Warning[:deprecated]` is enabled, then a warning shown by default, then the removal. For the first phase, `rb_warn_deprecated_to_remove_at(X.Y, fmt, suggest, ...)` (#17432) prints "... is deprecated and will be removed in Ruby X.Y", and a RUBY_DEBUG build fails to compile when the version reaches X.Y. For the second phase, there is no equivalent API. A warning with the `:deprecated` category is suppressed by default by definition, so the warning must be emitted with `rb_warn` without a category, and the message and the version check have to be written by hand. I propose to add `rb_warn_to_remove_at(X.Y, fmt, suggest, ...)` to internal/error.h: the same message and compile-time check, emitted with `rb_warn`. The name does not contain "deprecated" because `rb_warn_deprecated*` means a warning gated by `Warning[:deprecated]`. -- https://bugs.ruby-lang.org/
participants (2)
-
Dan0042 (Daniel DeLorme) -
shugo (Shugo Maeda)