-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Add support for constants in stubs #7434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
336562d
to
83fb7f8
Compare
The key problem with constants is that they are usually define to the value of a C constant. I just did a grep of "REGISTER.*CONSTANT", and it looks like the vast majority is of that kind. There's only few cases that define the constants as a fixed value. In many cases, the value being assigned is not even controlled by PHP, but a symbol exported by some library. E.g. all the curl constants. |
Yeah, I'm aware of this issue, but I think it would be OK to generate constants for values which we can control. We could generate the C constant from the PHP constant by default ( |
@kocsismate I don't think this would cover enough use cases. Constant values that we don't control are really common, probably the majority. Even if we do control them, the C constants may have different scope, e.g. be defined in a header and used in multiple files. arginfo.h should only be included once. The only way I can see this working is if we allow referencing C constants from stubs, like But this doesn't really seem better than what we have now. What is the motivation for moving this to stubs? Also @sgolemon may have some insight here. I think they had some bad experiences with doing this in HHVM... |
My main motivation is that adding support for constants in gen_stubs could improve the DX of developing extensions, and also, we could autogenerate more class synopsis pages without any manual intervention (after the initial sync). So I'm not saying that we should migrate all the constants of php-src to stubs or support all the use-cases, but IMO a few major extensions (like ext/json, ext/spl, ext/date) would benefit from some kind of autogeneration support, not to mention 3rd party or new extensions.
I agree that It's a valid concern (and I didn't yet consider it). But maybe we could generate a new header file for the C constants, and reference it during the registration of PHP constants/in the implementation of internal functions in order to solve the problem. |
f995aec
to
537490c
Compare
I managed to implement a POC, tests should pass now. |
561cd69
to
c4aaab9
Compare
Even if we wouldn't use the constants in the stubs for the implementation (or only some of these constants), this appears to be still useful for IDEs/static analyzers and for the PHP manual, even if the value of the constants would just be UNKNOWN. |
8bee45a
to
928df50
Compare
I agree: as it turned out, the majority of the stub-class synopsis diffs comes from the missing class constant support (43 files), so we would make a huge leap towards being able to fully autogenerate class declarations in the manual by adding constant support in stubs, as only ~20-25 files would need to be fixed afterwards. |
@kocsismate I mean that the stubs take care of registering the constants (from a PHP perspective), but the actual value of the constant is usually defined by a C constant. I don't really see a risk for discrepancies there. |
Ok, understood now, and it would make this PR easier to implement in the expense of the class synopses in the manual not being able to list the exact constant default values: as I noted before, I think it would be a moderate to serious regression compared to what we have now, but if necessary, I could live with it if this is the cost of having a consensus regarding this PR. @cmb69 do you have preference/input about class constant values? I'd highly appreciate the input from Bob, Derick, and Ilija as well :) |
Tough call. I agree with Nikita that most of the values should not be documented, but I understand Bob's counterargument. From my experience, some user will submit a note listing the values anyway, so maybe we should actually drop the values from the manual. And we could still switch back if users complain. |
Thanks, Christoph! If there is no objection, I'll simplify this PR for now according to Nikita's suggestion. Then I can provide followup changes if needed. |
Another alternative could be saying "constant is |
aff9ea8
to
88d23e6
Compare
I reworked the PR yesterday: now, constants are only allowed to be declared with an Another alternative which I considered is requiring C constant values to be passed as arguments for the function which registers the PHP constants (i.e. |
I'm quite unhappy with it. Nearly all constants will have a C define, and if it's only to consume the value in C as well. Meaning that the stubs effectively will end up as either a) a mere constants registry without values or b) need to duplicate the values hardcoded. There are quite a few instances where the constants value has not only value in debugging, but also when coding directly. Just as an example from this PR: the date constants describing formats. Currently they're all well described here: https://www.php.net/manual/en/class.datetimeinterface.php#datetimeinterface.synopsis - removing them would be quite the regression. And stubs should be usable in a way exposing these values as well. I'm currently wondering whether it would make sense to preprocess stubs and substitute C defines. I.e. the generator script would modify the stubs themselves and ensure the correctness of the values. So for example, a stub defined as:
will search the neighboring c and header files for
(Obviously only applicable if the expression is not complex, but a simple expression or string nor multiply defined (like within #if)... which 99% of the constants are.) That way round the PHP stubs are directly usable in development environments with cross-referencing. The github actions check verifying that running the stubs generator doesn't change anything will ensure that the values are also up to date. Obviously, that way, we expose the constants values. But I think this is a net positive. |
I also liked the previous version more, but the current one follows a more conservative solution, which we can occasionally improve easily if needed.
I don't completely disagree with you, but IMO having only constant names and types is still useful. E.g. originally, Ondrej asked us to provide info about constants in the stubs (https://bugs.php.net/bug.php?id=80188) for him to be able to use them in PHPStan. Back then we didn't have such plans, but in the meanwhile I changed my mind because adding constants would make a huge step forward for being able to completely autogenerate the class synopsis manual pages. In my opinion, this is more valuable than displaying the exact values.
To be honest, this solution would be way more esoteric than mine used to be, so I don't think we should go this way. However, I also came up with another idea: what about simply hardcoding the exact constant values in the stubs along with the |
@bwoebi To be clear, I don't think we should omit all constant values from docs. The date format strings are certainly a case where the value must be included in the documentation. However, the vast majority of the constants we have are really enum-like, where no exact value is guaranteed and often not even controlled by us (but rather a 3rd-party library). The way I would view this is that the constant value is on the same level as the constant description: Something that needs to be curated by a human, not indiscriminately generated just because we happen to know it (on some PHP version). |
And the exact value of the global constants are documented on the bottom of the very same page: https://www.php.net/manual/en/class.datetimeinterface.php#datetime.constants.types |
@nikic But still, the way it is now, things are manually curated, if we want a C constant, it may go out of sync with the "truth". Similarly e.g. E_* constants are quite useful to be documented. It's not like we're just changing values anytime. While in a pure academical sense they wouldn't have to be documented or the values considered public API, in a practical sense, it would constitute a practical BC break. @kocsismate Yeah, the documentation is sort of portraying it like the class constants are the source of truth and the top-level constants aliases for them. Btw. at the bottom of the page are only examples, not the values directly.
Yes, sure. But I'm just wanting to push one step further :-)
That sounds like an acceptable compromise :-) Generating a bunch of _StaticAssert(). (At least for any non-nested (i.e. nesting other constants) value)
Maybe it should be defined the other way round in the stubs then ... to reflect the manual. Doesn't do any harm I guess :-D |
OK, I made another significant change: now, constants in the stubs are allowed to have a literal value, which are only exposed for the manual and 3rd party tools, but php-src doesn't use them directly. In order to ensure that the documented values in the stubs match the real values defined in C, I added With the current approach, we are able to selectively choose what values to expose for the manual without introducing disruptive changes for the C codebase. The downside we should accept is that some constant values will be duplicated, but IMO this is an acceptable compromise due to the added consistency checks, and at least we don't lose the ability to conveniently document constant values.
I achieved this by recursively finding the first literal value of a constant. So with the latest commit, constant values of WDYT? |
I think what we have now is pretty reasonable :-) Thanks for your effort @kocsismate ! |
@nikic Is the new approach satisfactory for you? If the PR is OK conceptually, and there are no serious concerns/issues with the implementation, I'd like to go ahead with finishing the PR soon... But of course I can provide followup changes and fixes if necessary. |
I'm going to merge this PR at the end of next week, unless there's still significant problems with the implementation/concept. |
No description provided.