Hi,

Am 12.08.19 um 10:26 schrieb Nikita Popov:
On Mon, Aug 12, 2019 at 10:17 AM Nicolas Grekas <
nicolas.grekas+...@gmail.com> wrote:

Le lun. 11 déc. 2017 à 14:44, Nikita Popov <nikita....@gmail.com> a
écrit :

Some time ago I introduced the following proposal for namespace-scoped
declares:

     https://wiki.php.net/rfc/namespace_scoped_declares

The idea is to allow specifying declare directives for a whole library or
project using:

     namespace_declare('Vendor\Lib', ['strict_types' => 1]);

I've finally gotten around to implementing this proposal (
https://github.com/php/php-src/pull/2972) and would like to move forward
with it.

The reason why I'm picking it up again is some feedback I received for the
explicit call-time send-by-ref proposal. The main objection seems to be
that the feature has limited usefulness if it's optional rather than
required, because you still can't be sure that something is a by-value
pass, just because no & is present. At the same time, we can't make this
required anytime soon due to the large BC impact.

Namespace-scoped declares are perfectly suited to resolve this problem. We
can introduce a require_explicit_send_by_ref declare directive to make the
call-site annotation required, and libraries/projects can easily opt-in to
it using namespace_declare(). There would be no BC impact, while at the
same time projects could benefit from the additional clarity and
performance improvements immediately.


I've read discussions about the notion of a "package" and the way we
should define its boundaries.
What about the following?

Individual files could declare their package using this style:
<?php declare(package=MyVendor\MyPackage);

That would be enough to group a set of files together and make them share
eg some private classes, some optional PHP behaviors, etc.

The right side "MyVendor\MyPackage" would also be a FQCN that PHP would
autoload as a regular class. The corresponding class would then be the
place where ppl would declare the engine behavior they want for their
package (strict types, etc). To enforce this, the engine could require that
the "MyPackage" class implements some interface/extend some base abstract
class.

Of course, one could hijack a package and declare an unrelated file as
part of it, but I don't think that's an issue: the situation is the same as
for namespaces, where one can hijack a third party vendor namespace. In
practice, it proved not being an issue, and the original author's intent is
clear: "this is my namespace/package, if you mess with it, fine, but you're
on your own".

Nicolas


FTR I've created a draft-implementation for a package system here:
https://github.com/php/php-src/pull/4490

It uses a slightly different approach in that it keeps the package name a
string (that should usually match the Composer package name) and uses a
function to register the package.

The main annoyance is that this requires declaring the package in every
file, something I would like to avoid. An alternative I played with is to
allow specifying the package at include time, which would allow the
autoloader to specify which package a file is part. However, while this is
more ergonomic for the user, I'm afraid that this will make static analysis
& IDE scenarios problematic, because they will not be able to easily know
what the package is in cases that fall outside convention. So in the end,
an explicit per-file package declaration may be the best we can do.


I'm not sure if this was discussed/proposed before:

Why not have a concept similar to autoloaders that resolves a given class name to some declare statements.

That way you could implement a composer based resolver that takes a class name, (internally) resolves it to a package (based on the autoloader configuration in composer.json), and returns an array of the specified declare statements.

Developers do not need to specify a package or any declare statements in PHP files at all, as PHP (or static analyzers) would be able to ask the class-name-to-declare-statements resolver which declare statements a PHP file defines.

Alternatively, you could introduce the concept of a Package(Specification) class as proposed by Nicolas (but without the need to extend and implement it in each package). That way the resolver does not return the array of declare statements but an instance of the Package(Specification) class that was constructed by the composer-based resolver dynamically with the declare statements as defined in composer.json.

Not sure: Perhaps you even do not need a new concept of a resolver but could extend the concept of autoloaders?

Regards
Thomas

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to