-
Notifications
You must be signed in to change notification settings - Fork 208
PHPC-1709: Add typing information to arginfo #1337
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
@@ -11,7 +11,7 @@ require_once __DIR__ . '/../utils/basic.inc'; | |||
|
|||
echo throws(function() { | |||
new MongoDB\BSON\Decimal128([]); | |||
}, MongoDB\Driver\Exception\InvalidArgumentException::class), "\n"; | |||
}, TypeError::class), "\n"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely sure about these changes - some people may see this as a BC break. I'll have to double-check why the exception class changes for this and ObjectId.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this change apply to all PHP versions? It calls to mind some of the variations between PHP 7.x and 8.0 when we were implementing PHPC-1631.
The only other example of split tests for TypeError that comes to mind is:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It affects all PHP versions, since we unconditionally add argument types to methods. I'll take another look at this tomorrow to figure out where this is coming from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure this is the result of parameter types now being validated by arginfo instead of zpp. That's probably something we should document in release notes (you can add documentation-needed
on the ticket and make a note of this in a comment). I don't think there's any place to mention this in the extension docs, though -- it'd be pedantic to add this to every method's changelog.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I believe adding this to each method's changelog would be overkill. Maybe a paragraph in the release notes would be appropriate for this.
3cf104e
to
6bfe74d
Compare
@jmikola this is ready for a first look before I continue with the rest of these classes. Build failures on PHP 8.1 are due to deprecation warnings since we're introducing tentative return types for BSON interfaces. The affected classes will be updated in the next step once we've confirmed that the general direction is ok. |
6bfe74d
to
82f3668
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added generate-function-entries
to existing stubs and added stubs for exception classes. See a couple of notes below.
src/BSON/Binary.stub.php
Outdated
final class Binary implements BinaryInterface, JsonSerializable, Type, \Serializable | ||
{ | ||
/** @var int */ | ||
public const TYPE_GENERIC = 0x01; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added these in a separate commit since we used to use the libbson enum to define these constants. Since these are protected by the BC promise, I don't mind hardcoding the values here but can revert the change if you'd rather use libbson values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I didn't consider that. Since php_phongo_binary_init_ce
isn't going away, I think keeping the zend_declare_class_constant_long
lines in there is sensible. This is going to come up with other files as well, and I'd rather depend on the libmongoc constants if possible, since that might also catch a bug on their end.
If not, I'd at least want to have comments in these stub files referring to the libmongoc constant we're hard-coding. For example:
public const TYPE_GENERIC = 0x01; /* BSON_SUBTYPE_BINARY */
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try (may requires 8.2 to generate the arginfo)
/** @cvalue BSON_SUBTYPE_BINARY */
public const TYPE_GENERIC = UNKNOWN;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that is nice. I was already using the 8.2 file (the previous version didn't handle constants), so I switched to using @cvalue
.
|
||
INIT_NS_CLASS_ENTRY(ce, "MongoDB\\BSON", "Binary", php_phongo_binary_me); | ||
php_phongo_binary_ce = zend_register_internal_class(&ce); | ||
php_phongo_binary_ce = register_class_MongoDB_BSON_Binary(php_phongo_binary_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_serializable); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is generated by specifying generate-class-entries
in the stub file. It can't take care of object handlers, but it allows us to rely on the stub files for the class structure (modifiers, extended classes, implemented interfaces, class and property definitions, etc.).
82f3668
to
b47a633
Compare
src/BSON/Binary.stub.php
Outdated
|
||
namespace MongoDB\BSON | ||
{ | ||
final class Binary implements BinaryInterface, JsonSerializable, Type, \Serializable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should JsonSerializable
be \JsonSerializable
? It's not defined in the MongoDB\BSON
namespace.
Since php_phongo_binary_init_ce
includes:
#if PHP_VERSION_ID >= 80000
zend_class_implements(php_phongo_binary_ce, 1, zend_ce_stringable);
#endif
Would it make sense to use #if
here to define two different class declarations, or perhaps just an extra line between this and the opening {
to avoid duplication? Something like:
final class Binary implements BinaryInterface, JsonSerializable, Type, \Serializable
#if PHP_VERSION_ID >= 80000
, \Stringable
#endif
{
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes - I'll change this to \JsonSerializable
. I was confused by the php_phongo_json_serializable_ce
variable 🤦
Unfortunately, the #if
is completely ignored in the class header (both with and without duplication of the class definition in conditionals). We're unfortunately stuck adding this ourselves until we require PHP 8.0, at which point we can add it to the stub files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See: https://github.com/mongodb/mongo-php-driver/blob/1.14.0/php_phongo.c#L183
We may actually want to continue using php_phongo_json_serializable_ce
, since it's fetched during MINIT to avoid problems on some distributions where the JSON extension was not compiled in to PHP and instead loaded dynamically. That was definitely an issue back in the 5.x releases (see: PHPC-878), and it may still apply to 7.x+. We may need to confirm with @remicollet.
And while I'm looking at the above, I think the manual fetching of DateTimeImmutable
may be obsolete. I've opened PHPC-2115 to track that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Json is always build statically in 8.x, so this hack is still useful on 7.x
(btw, only there to avoid "undefined symbol" when load order is not the correct one for linux distribution using --enable-rtld-now
)
|
||
/** | ||
* @generate-class-entries static | ||
* @generate-function-entries static |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also nice to add @generate-legacy-arginfo 80000
to take benefit of compatibility stuff when using 8.2. Example when using SensitiveParameter attributes, see
See https://github.com/pierrejoye/php_zip/blob/master/php81/php_zip.stub.php#L91
And https://github.com/pierrejoye/php_zip/blob/master/php81/php_zip_arginfo.h#L532
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also notice that is some additional compatibility checks are missing, is still possible to add them in gen_stub.php before 8.2.0 GA
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have yet to check the legacy arginfo generation and the difference between files. Since we still support PHP 7.2, I assume we'll want to use @generate-legacy-arginfo 70000
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you use 70200 it will also generate a foo_legady_arginfo.h
without type hinting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generate-legacy-arginfo 70200
is not supported, so we could only generate legacy arginfo files for PHP 7.0. Since those don't include any argument types at all (which we want since PHP 7.2 allows for this), we'll just do without legacy arginfo for now. We've got everything we wanted covered this way as well:
- argument types (
mixed
and unions only on PHP 8.0+) - return types for final methods/classes
- tentative return types for non-final methods/classes (PHP 8.1+, no return type info in other versions)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generate-legacy-arginfo accepts any PHP_VERISON_ID, "legacy" file is generated as soon as < 80000 ;)
BTW? I really think it should be used, at least for SensitiveParameter.
And hacks for compatibility could probably be proposed in php_src so every ext will be benefit of them.
This is how OpenSource work ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$ ./build/gen_stub.php
In ./src/MongoDB/WriteConcern.stub.php:
Legacy PHP version must be one of: "70000" (PHP 7.0), "80000" (PHP 8.0), "80100" (PHP 8.1), "80200" (PHP 8.2), "70200" provided
I'll take a look at adding a compatibility mode for PHP 7.2, but at the moment it doesn't exist. As it is, legacy arginfo isn't useful for us.
57ae9f0
to
1a4e1a5
Compare
1a4e1a5
to
5bda12f
Compare
f6a101f
to
a3a6604
Compare
9efe977
to
f604e6a
Compare
This is necessary to let the generated arginfo files compile
f604e6a
to
aff07b4
Compare
aff07b4
to
d469466
Compare
@@ -11,7 +11,7 @@ require_once __DIR__ . '/../utils/basic.inc'; | |||
|
|||
echo throws(function() { | |||
new MongoDB\BSON\Decimal128([]); | |||
}, MongoDB\Driver\Exception\InvalidArgumentException::class), "\n"; | |||
}, TypeError::class), "\n"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure this is the result of parameter types now being validated by arginfo instead of zpp. That's probably something we should document in release notes (you can add documentation-needed
on the ticket and make a note of this in a comment). I don't think there's any place to mention this in the extension docs, though -- it'd be pedantic to add this to every method's changelog.
d469466
to
0f40aec
Compare
0f40aec
to
49e526e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GitHub decided to stop rendering the full PR diff, but I reviewed the commits since my last review and it looks like everything has been addressed.
Adding return types to interfaces breaks BC, isn't it? As stated in https://jira.mongodb.org/browse/PHPC-1711
Should this change be followed with a major release?
|
The 1.15.0 release uses tentative return types for interfaces methods. Our reasoning at the time was that this was a BC-friendly migration path since it'd have no effect on PHP 8.0 and earlier (see: That said, I now realize that users already on PHP 8.1 would have encountered this issue for the first time when upgrading from driver version 1.14.x to 1.15.0. I apologize for any inconvenience this may have caused on your side.
In hindsight, it may have been preferable punt on introducing tentative return types altogether. I don't think the change alone would be enough to warrant a bump to 2.0 (there are other larger changes planned, but not yet implemented). Tentative return types perhaps make more sense in PHP core where BC breaks regularly show up in minor releases (e.g. https://www.php.net/manual/en/migration81.incompatible.php), but not PECL extensions which follow external release schedules. PHPC-2139 is the canonical ticket for BC-breaking typing changes for 2.0. That will be the next opportunity to replace these tentative return types with actual return types. |
PHPC-1708
PHPC-1711
PHPC-2015
PHPC-2115
This PR adds stub files to generate arginfo. As a first proof of concept, this is done for BSON classes, but other classes will follow. Wherever we can't add return types yet (e.g. for interfaces and non-final classes where this constitutes a BC break) we declare a tentative return type to alert people to the upcoming change. In the stub files, this is characterised by the
@tentative-return-type
annotation in the docblock for the corresponding method.There are a couple of requirements for this, which will be added to the contribution docs later:
arginfo headers have to be generated using
build/gen_stub.php
. To get this file,phpize
needs to have been called with PHP 8.0 or laterChanging stub files entails regenerating arginfo files, as well as removing any
.lo
files for the class in question. I haven't yet managed to define the arginfo files as dependency for the respective class which would enable automatic recompilation.Create stub files for BSON classes
Create stub files for remaining classes
Update contributing docs
Integrate arginfo generation into build process (if possible)Add checks to build process to ensure stub files are up to date (if the above is not possible)