[PHP-DEV] [RFC][Discussion] Policy release process update

Hello,

I’d like to start discussion for some release process updates defined in the following RFC / linked PR:

RFC: https://wiki.php.net/rfc/policy-release-process-update
Policy PR: https://github.com/php/policies/pull/19

Regards

Jakub

Hi

Am 2025-05-09 12:47, schrieb Jakub Zelenka:

I'd like to start discussion for some release process updates defined in
the following RFC / linked PR:

RFC: PHP: rfc:policy-release-process-update
Policy PR: Add changes to the release process by bukka · Pull Request #19 · php/policies · GitHub

Thank you. The changes seem to accurately reflect the current practice and make sense to me. I however noticed that “Major” and “Minor” versions both effectively have the same allowances. Perhaps we could add some additional nuance as to what breaking changes are allowed to be approved by an RFC in a minor version, since breaking changes in majors should also require an RFC. Some thoughts:

- A minor version MUST NOT break syntax compatibility (i.e. every PHP program that compiles must continue to compile).
- Breaking changes in minor versions SHOULD be limited to extensions / the API of functions within an extension.
- The addition of deprecations themselves is not considered a breaking change (to resolve the discussion that comes up for each and every bulk-deprecation RFC, when you convert Deprecations into Exceptions that's on you).
- The addition of new symbols (e.g. functions or classes) might conflict with user-defined classes, but this is not considered a breaking change. An RFC should make a best effort to minimize the impact of a new function name by choosing among equally good names (but not unnecessarily choose a worse name, just because it is less likely to break). This is already implied by it being legal to add features without an RFC, but would be good to spell out explicitly.

Best regards
Tim Düsterhus

Hi,

On Fri, May 9, 2025 at 1:09 PM Tim Düsterhus <tim@bastelstu.be> wrote:

Hi

Am 2025-05-09 12:47, schrieb Jakub Zelenka:

I’d like to start discussion for some release process updates defined
in
the following RFC / linked PR:

RFC: https://wiki.php.net/rfc/policy-release-process-update
Policy PR: https://github.com/php/policies/pull/19

Thank you. The changes seem to accurately reflect the current practice
and make sense to me. I however noticed that “Major” and “Minor”
versions both effectively have the same allowances. Perhaps we could add
some additional nuance as to what breaking changes are allowed to be
approved by an RFC in a minor version, since breaking changes in majors
should also require an RFC.

Yeah it doesn’t make much sense to note that RFC bit. I wanted to say that breaks
are possible as it’s already happening but the wording was not the best.

Some thoughts:

  • A minor version MUST NOT break syntax compatibility (i.e. every PHP
    program that compiles must continue to compile).

Added this one

  • Breaking changes in minor versions SHOULD be limited to extensions /
    the API of functions within an extension.

I’m not sure about this wording but it’s better than it was before so used that
as well.

  • The addition of deprecations themselves is not considered a breaking
    change (to resolve the discussion that comes up for each and every
    bulk-deprecation RFC, when you convert Deprecations into Exceptions
    that’s on you).

So this would probably require the full definition of BC break and list this
as part of it. It might need more point though. I will think about it and try to
integrate it somehow.

  • The addition of new symbols (e.g. functions or classes) might conflict
    with user-defined classes, but this is not considered a breaking change.
    An RFC should make a best effort to minimize the impact of a new
    function name by choosing among equally good names (but not
    unnecessarily choose a worse name, just because it is less likely to
    break). This is already implied by it being legal to add features
    without an RFC, but would be good to spell out explicitly.

Another point for the BC break definition I think.

Kind regards,

Jakub

Hi

I gave this some additional thoughts.

Am 2025-05-09 13:36, schrieb Jakub Zelenka:

- A minor version MUST NOT break syntax compatibility (i.e. every PHP
program that compiles must continue to compile).

Added this one

Thinking about this more, I am not sure if having this as a MUST rule matches what we did in the past and I'm also not sure if it is useful to have. This rule prevents the addition of new keywords, since they might conflict with function names. Adding new symbols and adding a new keyword is functionally equivalent, both changes would result in a compile time error. Singling out the syntax change does not appear to be a useful distinction.

--------------------------

From my experience in maintaining an old PHP application and upgrading it to support the latest and greatest PHP every year, I think the following points would be a good starting point to discuss:

- For backwards compatibility breaks introduced in minor versions there MUST be a simple (for some appropriate definition of simple) way to adjust the code to be compatible with both the current PHP version and the upcoming version. Ideally the change would be compatible with a wider range of past PHP versions (past 3 or so?). It must be a change that is simple to perform even with basic tooling (i.e. not requiring an IDE or static analyzers).
- Backwards compatibility breaks in minor versions MUST NOT result in silent behavioral differences. Instead any breaking change must be "obvious" when executing the program, even when having a less-than-stellar test suite.

Adding new symbols results in a compile time error (immediately obvious) and is simple to fix (rename or remove your own implementation). Similarly throwing a ValueError for invalid inputs is reasonably easy to detect by executing the affected code path (you can't miss an Exception) and also simple to fix (don't do that). Changing operator precedence is not easy to detect, thus it is unacceptable. Throwing an error when single-letter variables (e.g. $i) would be easy to detect, but break almost every program, thus would be unacceptable.

Best regards
Tim Düsterhus

Hi,

On Sun, May 11, 2025 at 10:14 PM Tim Düsterhus <tim@bastelstu.be> wrote:

Hi

I gave this some additional thoughts.

Am 2025-05-09 13:36, schrieb Jakub Zelenka:

  • A minor version MUST NOT break syntax compatibility (i.e. every PHP
    program that compiles must continue to compile).

Added this one

Thinking about this more, I am not sure if having this as a MUST rule
matches what we did in the past and I’m also not sure if it is useful to
have. This rule prevents the addition of new keywords, since they might
conflict with function names. Adding new symbols and adding a new
keyword is functionally equivalent, both changes would result in a
compile time error. Singling out the syntax change does not appear to be
a useful distinction.

Yeah this make sense. I changed it to SHOULD in the latest version with some other updates.


From my experience in maintaining an old PHP application and upgrading
it to support the latest and greatest PHP every year, I think the
following points would be a good starting point to discuss:

  • For backwards compatibility breaks introduced in minor versions there
    MUST be a simple (for some appropriate definition of simple) way to
    adjust the code to be compatible with both the current PHP version and
    the upcoming version. Ideally the change would be compatible with a
    wider range of past PHP versions (past 3 or so?). It must be a change
    that is simple to perform even with basic tooling (i.e. not requiring an
    IDE or static analyzers).

If I understand it correctly, this sounds really more like completely new rule that we don’t currently have so I would rather not add it. We don’t have this relation differences between X.Y and X.(Y+2) to do some extra breaks so it’s more for a separate RFC. I’m also not a big fan of such change to be honest.

  • Backwards compatibility breaks in minor versions MUST NOT result in
    silent behavioral differences. Instead any breaking change must be
    “obvious” when executing the program, even when having a
    less-than-stellar test suite.

I think this makes sense and added this paragraph (with exception of that less-than-stellar test suite) to the policy.

Adding new symbols results in a compile time error (immediately obvious)
and is simple to fix (rename or remove your own implementation).
Similarly throwing a ValueError for invalid inputs is reasonably easy to
detect by executing the affected code path (you can’t miss an Exception)
and also simple to fix (don’t do that). Changing operator precedence is
not easy to detect, thus it is unacceptable. Throwing an error when
single-letter variables (e.g. $i) would be easy to detect, but break
almost every program, thus would be unacceptable.

This makes sense but might be a bit too specific. Did you mean to also include it in this policy?

Kind regards

Jakub

Hi

Am 2025-05-13 12:13, schrieb Jakub Zelenka:

From my experience in maintaining an old PHP application and upgrading
it to support the latest and greatest PHP every year, I think the
following points would be a good starting point to discuss:

- For backwards compatibility breaks introduced in minor versions there
MUST be a simple (for some appropriate definition of simple) way to
adjust the code to be compatible with both the current PHP version and
the upcoming version. Ideally the change would be compatible with a
wider range of past PHP versions (past 3 or so?). It must be a change
that is simple to perform even with basic tooling (i.e. not requiring an
IDE or static analyzers).

If I understand it correctly, this sounds really more like completely new
rule that we don't currently have so I would rather not add it. We don't
have this relation differences between X.Y and X.(Y+2) to do some extra
breaks so it's more for a separate RFC. I'm also not a big fan of such
change to be honest.

We don't currently have any rules at all, except for “when the RFC approves the break, then it's okay”. I was trying to find some guideline for BC breaks that might be okay in a minor (when approved) and BC breaks that are never okay in a minor.

The application in question is in a very similar position that PHP itself is, it has a large public API that "third party" developers rely on and a long development history. BC breaks sometimes are not avoidable when you try to move forward. Basically the rule of thumb for a breaking change in a minor version was that "most third party add-on should be adaptable with minimal changes, while remaining compatible with both minor versions after making these minimal changes".

Adding new symbols results in a compile time error (immediately obvious)
and is simple to fix (rename or remove your own implementation).
Similarly throwing a ValueError for invalid inputs is reasonably easy to
detect by executing the affected code path (you can't miss an Exception)
and also simple to fix (don't do that). Changing operator precedence is
not easy to detect, thus it is unacceptable. Throwing an error when
single-letter variables (e.g. $i) would be easy to detect, but break
almost every program, thus would be unacceptable.

This makes sense but might be a bit too specific. Did you mean to also
include it in this policy?

That paragraph is intended as an example for my train of thought / how I would interpret my suggested guidelines for hypothetical breaking changes. Of course I do not expect anyone to propose an RFC to disallow single-letter variables (not even in a major).

Best regards
Tim Düsterhus

Hi,

On Tue, May 13, 2025 at 12:56 PM Tim Düsterhus <tim@bastelstu.be> wrote:

Hi

Am 2025-05-13 12:13, schrieb Jakub Zelenka:

From my experience in maintaining an old PHP application and
upgrading
it to support the latest and greatest PHP every year, I think the
following points would be a good starting point to discuss:

  • For backwards compatibility breaks introduced in minor versions
    there
    MUST be a simple (for some appropriate definition of simple) way to
    adjust the code to be compatible with both the current PHP version and
    the upcoming version. Ideally the change would be compatible with a
    wider range of past PHP versions (past 3 or so?). It must be a change
    that is simple to perform even with basic tooling (i.e. not requiring
    an
    IDE or static analyzers).

If I understand it correctly, this sounds really more like completely
new
rule that we don’t currently have so I would rather not add it. We
don’t
have this relation differences between X.Y and X.(Y+2) to do some extra
breaks so it’s more for a separate RFC. I’m also not a big fan of such
change to be honest.

We don’t currently have any rules at all, except for “when the RFC
approves the break, then it’s okay”. I was trying to find some guideline
for BC breaks that might be okay in a minor (when approved) and BC
breaks that are never okay in a minor.

What I meant is that this would be quite significant change as it could lead to some sort of bigger breaks when people could think that introducing break after few years is ok. That’s how I understood it but thinking about it, it would be probably fine if it was an additional restriction (meaning we would still keep “Syntax backward compatibility SHOULD be preserved”). It would need some good formulation though. So if you can come up with something that is clear, I would be happy to add it.

The application in question is in a very similar position that PHP
itself is, it has a large public API that “third party” developers rely
on and a long development history. BC breaks sometimes are not avoidable
when you try to move forward. Basically the rule of thumb for a breaking
change in a minor version was that “most third party add-on should be
adaptable with minimal changes, while remaining compatible with both
minor versions after making these minimal changes”.

I understand what you mean. The only challenge is to find a good wording to the policy. :slight_smile:

Kind regards

Jakub

Thank you Jakub for tackling the problem of inconsistency between policy and practice.

Taking my PR as case study, under this policy I am allowed to choose whatever approach I want? Either deprecation or validation error.
https://github.com/php/php-src/pull/15647

  • Behavior changes in undefined or undocumented edge cases MAY be allowed if
    well justified. However, care SHOULD be taken to minimize disruption.

Kind regards,

Jorg