# [RFC] Namespace-scoped declares, again

- Thread: https://externals.io/message/101323
- Original archive: https://news-web.php.net/php.internals/101323
- Started by Nikita Popov on 2017-12-11T13:43:41+00:00
- Messages: 70
- RFC: Namespace-scoped declares (Inactive) — https://externals.io/rfc/namespace_scoped_declares.md
- Page 1 of 3: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/101323.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #101323 — Nikita Popov — 2017-12-11T13:43:41+00:00

URL: https://externals.io/message/101323#101323

Hi internals!

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.

Thanks,
Nikita

---

## #101324 — Sara Golemon — 2017-12-11T15:46:34+00:00

URL: https://externals.io/message/101323#101324 · In reply to: #101323

> 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.
>
Being lazy here because I'm literally on my way out the door and don't
have a moment to parse through the implementation, but can you clarify
how this impact compile-time declares?

<?php

require('a.php");
require('b.php"); // This file has a namespace declaration
require('c.php");

In this example, does a.php wind up getting compiled with a different
set of declares than b.php and c.php?

-Sara

---

## #101325 — Mark Randall — 2017-12-11T15:55:48+00:00

URL: https://externals.io/message/101323#101325 · In reply to: #101323

> 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(). 

Seems solid to me, I would definitely make use of this feature, as I 
found adding the declare to each file felt untidy and even a little clumsy.

I certainly like the direction that PHP seems to be moving in terms of 
making the script structure more like a compiled application, rather 
than a set of independent scripts.

If this doesn't pass, long term I think the main alternative would be to 
have a single statement that was like a quasi-include of declarations in 
another file, almost like a ".h"

declare_import('/my/namespace/nsprefs.php');

--
Mark Randall

---

## #101326 — Nikita Popov — 2017-12-11T15:56:16+00:00

URL: https://externals.io/message/101323#101326 · In reply to: #101324

> On Mon, Dec 11, 2017 at 8:43 AM, Nikita Popov <nikita.ppv@gmail.com>
> wrote:
> > […]
> Being lazy here because I'm literally on my way out the door and don't
> have a moment to parse through the implementation, but can you clarify
> how this impact compile-time declares?
>
> <?php
>
> require('a.php");
> require('b.php"); // This file has a namespace declaration
> require('c.php");
>
> In this example, does a.php wind up getting compiled with a different
> set of declares than b.php and c.php?
>
> -Sara
>

Nope. The namespace_declare() call in this case will throw an Error,
because code using that namespace has already been loaded. The
implementation is careful to ensure that it's never possible to end up in a
situation where the used declare directives are inconsistent.

Nikita

---

## #101331 — Stanislav Malyshev — 2017-12-12T07:46:03+00:00

URL: https://externals.io/message/101323#101331 · In reply to: #101323

Hi!

> The idea is to allow specifying declare directives for a whole library or
> project using:
> 
>     namespace_declare('Vendor\Lib', ['strict_types' => 1]);

I am not sure I like this. Namespace is a prefix to a class name.
Anybody can declare a class with any name, and the side-effect that they
would inherit some context, which is completely invisible and would
magically exist somewhere globally, does not seem like a good idea to
me. Moreover, what if something - like older version of the same library
or test or something like that - would have different idea about what
that global state should be? How nice would it be if a piece of
unrelated code could completely change how my code is interpreted? How
nice would it be if whether it works or not would depend on in which
order classes were loaded in this particular request?

Hidden global context has the same smell as php.ini settings, and for
the same reason - but this, as far as I can see, will also be hidden and
depending on file loading order, class loading order, etc. which in big
applications can lead to a lot of fun debugging why some code randomly
produces fatal errors... Debugging PHP is fun enough without quantum
entanglement-like effects :)

> 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.

Where "soon" means "for all practical purposes, forever, unless we stop
calling that new thing PHP", IMO.

> Namespace-scoped declares are perfectly suited to resolve this problem. We

I don't think so. First of all, I don't think, of course, that this
problem needs to be solved by adding more complexity to save a purely
cosmetic feature. But second of all, I don't think global hidden context
that could change at a distance how the code is interpreted is a good
idea regardless of whether it solves the issues with send-by-ref.

-- 
Stas Malyshev
smalyshev@gmail.com

---

## #101334 — Nikita Popov — 2017-12-12T13:43:39+00:00

URL: https://externals.io/message/101323#101334 · In reply to: #101331

On Tue, Dec 12, 2017 at 8:46 AM, Stanislav Malyshev <smalyshev@gmail.com>
wrote:

> Hi!
>
> > […]
>
> I am not sure I like this. Namespace is a prefix to a class name.
> Anybody can declare a class with any name, and the side-effect that they
> would inherit some context, which is completely invisible and would
> magically exist somewhere globally, does not seem like a good idea to
> me. Moreover, what if something - like older version of the same library
> or test or something like that - would have different idea about what
> that global state should be? How nice would it be if a piece of
> unrelated code could completely change how my code is interpreted? How
> nice would it be if whether it works or not would depend on in which
> order classes were loaded in this particular request?
>

The way PHP works, it's not possible to have two versions of a library
loaded at the same time. There are projects like
https://github.com/humbug/php-scoper to allow loading a library multiple
times, which work by prefixing all namespaces. Of course, in this case
namespace_declares() would also be applied to different namespaces and
there will be no interference.

There is no dependence on loading order. The implementation is careful to
ensure that the used declare state is consistent. It's not possible to call
namespace_declare() twice on the same namespace. It's not possible to first
load some files from a namespace, do the namespace_declare() call and then
load some more files. If a namespace_declare() call succeeds without
throwing an error, then that is the ground truth, without any dependence on
order or other calls.


> Hidden global context has the same smell as php.ini settings, and for
> the same reason - but this, as far as I can see, will also be hidden and
> depending on file loading order, class loading order, etc. which in big
> applications can lead to a lot of fun debugging why some code randomly
> produces fatal errors... Debugging PHP is fun enough without quantum
> entanglement-like effects :)
>

As said above, the implementation makes sure that all quantum state is
collapsed ;) The only possible mistake that can occur is that the
namespace_declare() call doesn't happen at all, but anything depending on
loading order or conflicting calls is not possible.

The big issue with ini settings is (mostly) not the "hidden" part, it's the
"global" part. Ini settings that change language behavior are tabu because
they apply to everything, so no library can assume any particular ini
configuration. Namespace-scoped declares explicitly avoid this. A library
can namespace_declare() it's configuration and be sure that this is the
configuration it's going to get, at the same time not interfering with any
other library or code that uses a different configuration.

> The reason why I'm picking it up again is some feedback I received for the
> > […]
>
> Where "soon" means "for all practical purposes, forever, unless we stop
> calling that new thing PHP", IMO.
>
> > […]
> We
>
> I don't think so. First of all, I don't think, of course, that this
> problem needs to be solved by adding more complexity to save a purely
> cosmetic feature. But second of all, I don't think global hidden context
> that could change at a distance how the code is interpreted is a good
> idea regardless of whether it solves the issues with send-by-ref.
>

I haven't thought too carefully about whether having an option for the
explicit-send-by-ref feature *specifically* would be beneficial, but I
think it's very important to at least have the option on the table. Too
many issues in PHP cannot be solved for reasons of backwards-compatibility.
We need to have *some* way to evolve the language without BC breaks, and I
think namespace-declares are an elegant way to do this.

Regards,
Nikita

---

## #101337 — Christoph M. Becker — 2017-12-12T16:32:57+00:00

URL: https://externals.io/message/101323#101337 · In reply to: #101323

> 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.

Generally I'm not keen on letting the language diverge via whatever
mechanism, but that has already happened and there seems to be some
further need, and the namespace scoped declares appear to be preferable
to per-file declares or even ini settings.

What I don't like about the present proposal is that it introduces a
proper function instead of a language construct.  Is there a particular
reason for this design decision?  Couldn't we add the namespace scoped
declares to the namespace declaration directly, e.g.

  namespace Foo declare strict_types=1;

-- 
Christoph M. Becker

---

## #101340 — Stanislav Malyshev — 2017-12-12T23:14:34+00:00

URL: https://externals.io/message/101323#101340 · In reply to: #101334

Hi!

> There is no dependence on loading order. The implementation is careful
> to ensure that the used declare state is consistent. It's not possible
> to call namespace_declare() twice on the same namespace. It's not
> possible to first load some files from a namespace, do the
> namespace_declare() call and then load some more files. If a

This means that namespace_declare can be only in one file, and if any
mention of any namespace class has been made before that file has been
loaded, then the declare would fail. That is loading order dependency -
if A.php contains namespace_declare and B.php contains another class of
the same namespace, then order (A, B) works but order (B, A) does not.

> The big issue with ini settings is (mostly) not the "hidden" part, it's
> the "global" part. Ini settings that change language behavior are tabu

Exactly. And this proposal adds another global state, which is also
invisible, so figuring out what the state is when debugging is... fun.
It's better than php.ini as it's "namespaced php.ini" but still suffers
from the same problems within the namespace (and namespaces can be
pretty big).

> this. A library can namespace_declare() it's configuration and be sure
> that this is the configuration it's going to get, at the same time not
> interfering with any other library or code that uses a different
> configuration.

This assumes each namespace is homogeneous code always belonging to the
same library and nothing is every added to that namespace. This is not
always the case.

-- 
Stas Malyshev
smalyshev@gmail.com

---

## #101342 — Andreas Hennings — 2017-12-13T00:16:12+00:00

URL: https://externals.io/message/101323#101342 · In reply to: #101334

I agree with all of Stanislav's emails in this thread so far.


> On Tue, Dec 12, 2017 at 8:46 AM, Stanislav Malyshev <smalyshev@gmail.com>
> wrote:
>
> > […]
>
> The way PHP works, it's not possible to have two versions of a library
> loaded at the same time.

Really?
PHP does not even know what a "library" is. PHP sees files,
directories and namespaces. But it does not know how to conceptualize
any of this as a "library".

With Composer you get the notion of a "package".
In general, Composer would prevent you from using different versions
of the same package.
But you could manually download two versions of a package, and wire up
the class loader in a way that it would load some classes from one
version, and some classes from another version.
E.g. if a class does not exist in version 2, load the class from
version 1 instead.

PHP as a language should not assume that someone is using Composer correctly.

And even if we avoid two package versions coexisting: There could
easily be two distinct packages that use the same namespace.
We could discuss if this is a good idea, but it should not be the job
of PHP as a language to make this situation difficult.

>
> There is no dependence on loading order. The implementation is careful to
> ensure that the used declare state is consistent. It's not possible to call
> namespace_declare() twice on the same namespace. It's not possible to first
> load some files from a namespace, do the namespace_declare() call and then
> load some more files. If a namespace_declare() call succeeds without
> throwing an error, then that is the ground truth, without any dependence on
> order or other calls.

So by "is not possible", in fact you mean "will trigger an error".

I imagine with Composer we would have to agree on a canonical file
name where a namespace_declare() would be found.
Maybe something like in src/Acme/Animal.namespace.php.

The class loader would then have to make sure that this file is
included before the first class from that namespace is included.
Or alternatively, Composer init script would have to include all such
files at the beginning of the process.

If Composer (or whichever tool one wants to use) would include class
file src/Acme/Animal/Cat.php without prior inclusion of the
Animal.namespace.php, the class file would be interpreted without the
desired setting.
If the process then continues without ever including
Animal.namespace.php, it will silently misbehave.
If, however, Animal.namespace.php is included some time later in the
process, then it would notice that something went wrong, and trigger
an error.

> I haven't thought too carefully about whether having an option for the
> explicit-send-by-ref feature *specifically* would be beneficial, but I
> think it's very important to at least have the option on the table. Too
> many issues in PHP cannot be solved for reasons of backwards-compatibility.
> We need to have *some* way to evolve the language without BC breaks, and I
> think namespace-declares are an elegant way to do this.


So if you want a setting for explicit-send-by-ref, why not do this per
file, as we already do for strict_types?

If at some day in the future we find that the declares become too
verbose, we could bundle multiple declares into a new setting.
E.g. something like "declare(php=8.1);" to combine all the declares
that would be considered default in PHP 8.1.

Or introduce some other shortcut like "<?php.8.1" instead of "<?php"
opening tag.

---

## #101343 — michal@brzuchalski.com — 2017-12-13T04:04:23+00:00

URL: https://externals.io/message/101323#101343 · In reply to: #101342

2017-12-13 1:16 GMT+01:00 Andreas Hennings <andreas@dqxtech.net>:

> I agree with all of Stanislav's emails in this thread so far.
>
> 
> > […]
> library or
> > […]
>
> Really?
> PHP does not even know what a "library" is. PHP sees files,
> directories and namespaces. But it does not know how to conceptualize
> any of this as a "library".
>
> With Composer you get the notion of a "package".
> In general, Composer would prevent you from using different versions
> of the same package.
> But you could manually download two versions of a package, and wire up
> the class loader in a way that it would load some classes from one
> version, and some classes from another version.
> E.g. if a class does not exist in version 2, load the class from
> version 1 instead.
>
> PHP as a language should not assume that someone is using Composer
> correctly.
>
> And even if we avoid two package versions coexisting: There could
> easily be two distinct packages that use the same namespace.
> We could discuss if this is a good idea, but it should not be the job
> of PHP as a language to make this situation difficult.
>
> > […]
> call
> > […]
> first
> > […]
> then
> > […]
> on
> > […]
>
> So by "is not possible", in fact you mean "will trigger an error".
>
> I imagine with Composer we would have to agree on a canonical file
> name where a namespace_declare() would be found.
> Maybe something like in src/Acme/Animal.namespace.php.
>
> The class loader would then have to make sure that this file is
> included before the first class from that namespace is included.
> Or alternatively, Composer init script would have to include all such
> files at the beginning of the process.
>
> If Composer (or whichever tool one wants to use) would include class
> file src/Acme/Animal/Cat.php without prior inclusion of the
> Animal.namespace.php, the class file would be interpreted without the
> desired setting.
> If the process then continues without ever including
> Animal.namespace.php, it will silently misbehave.
> If, however, Animal.namespace.php is included some time later in the
> process, then it would notice that something went wrong, and trigger
> an error.
>
>
If we're going to introduce someday a namespace file, then IMO it should
not be putted outside namespace folder.
For eg class Acme\Animal\Cat in src/Acme/Animal/Cat.php should have
namespace file in src/Acme/Aniimal/namespace.php
or even more src/Acme/Animal/ns.php
Why? Because users use PSR-4 so then they're src folder looks more like:
src/Cat.php <-- class Acme\Animal\Cat
src/ns.php <-- that should be then a place for namespace declare or even
function and constants.

Such namespace file can be a good place for namespace function and
constants declaration.
Also I think there is no need for another global function named
`namespace_declare` if we had namespace file
then we can utilise declare for that.
Lets imagine such syntax:

// src/Acme/Animal/ns.php
<?php

namespace Acme\Animal declare(strict_types=1,another_option=0);
const CAT = 1;
function createCat() : Cat {}

A good reason for that is that we're not using namespace as a string in
function call which is more IDE friendly to refactor.
There is another good reason for that - some code generators/container
compilers etc. whatever else
uses one file for more than one class that means there would be still an
option to pack few namespaces in one
separate file like for. eg:

<?php

namespace Acme\Animal declare(strict_types=1) {
    class Cat {}
}

namespace Another\Library { // <-- there is no declare for this namespace
    class SomeClass {}
}

These are just my thoughts and they can be completely nonsense.
I think it might be also a good place to provide more info in a future.
I know PHP is not Java9 and I'm gratefull for that, but IMHO sometimes
there are good concepts,
like module info in module-info.java file with module exports and requires
and info about what it provides at all.

> I haven't thought too carefully about whether having an option for the
> > […]
> backwards-compatibility.
> > […]
> I
> > […]
>
>
> So if you want a setting for explicit-send-by-ref, why not do this per
> file, as we already do for strict_types?
>
> If at some day in the future we find that the declares become too
> verbose, we could bundle multiple declares into a new setting.
> E.g. something like "declare(php=8.1);" to combine all the declares
> that would be considered default in PHP 8.1.
>
> Or introduce some other shortcut like "<?php.8.1" instead of "<?php"
> opening tag.
>
> --
> 
> 
>
>


-- 
regards / pozdrawiam,
--
Michał Brzuchalski
about.me/brzuchal
brzuchalski.com

---

## #101344 — Andreas Hennings — 2017-12-13T04:24:34+00:00

URL: https://externals.io/message/101323#101344 · In reply to: #101343

>
> If we're going to introduce someday a namespace file, then IMO it should not
> be putted outside namespace folder.
> For eg class Acme\Animal\Cat in src/Acme/Animal/Cat.php should have
> namespace file in src/Acme/Aniimal/namespace.php
> or even more src/Acme/Animal/ns.php
> Why? Because users use PSR-4 so then they're src folder looks more like:
> src/Cat.php <-- class Acme\Animal\Cat
> src/ns.php <-- that should be then a place for namespace declare or even
> function and constants.

You are right, my previous proposal src/Acme/Animal.namespace.php
would not work universally.

But your proposal, src/Acme/Animal/ns.php clashes with the class file
for class \Acme\Animal\ns.

We would need something other than NAME.php.
E.g. src/Acme/Animal/ns.inc.php

But then Composer would still need to make sure that this file is
always included before any class files from this directory.
On language level we cannot assume that Composer is being used, and
that it is being used correctly.

So again this would be fragile.

>
> Such namespace file can be a good place for namespace function and constants
> declaration.
> Also I think there is no need for another global function named
> `namespace_declare` if we had namespace file
> then we can utilise declare for that.
> Lets imagine such syntax:
>
> // src/Acme/Animal/ns.php
> <?php
>
> namespace Acme\Animal declare(strict_types=1,another_option=0);
> const CAT = 1;
> function createCat() : Cat {}

This means you are changing the meaning of existing declare() to apply
to the entire namespace?
Or to the entire directory?

Or maybe the difference here is that there is no semicolon directly
after the namespace declaration?

I am not convinced by this syntax.
But even if we would find a good syntax, the behavioral problems
pointed out by Stanislav still apply.

---

## #101345 — michal@brzuchalski.com — 2017-12-13T04:38:26+00:00

URL: https://externals.io/message/101323#101345 · In reply to: #101344

2017-12-13 5:24 GMT+01:00 Andreas Hennings <andreas@dqxtech.net>:

> On 13 December 2017 at 05:04, Michał Brzuchalski <michal@brzuchalski.com>
> wrote:
> > […]
> not
> > […]
>
> You are right, my previous proposal src/Acme/Animal.namespace.php
> would not work universally.
>
> But your proposal, src/Acme/Animal/ns.php clashes with the class file
> for class \Acme\Animal\ns.
>
> We would need something other than NAME.php.
> E.g. src/Acme/Animal/ns.inc.php
>
> But then Composer would still need to make sure that this file is
> always included before any class files from this directory.
> On language level we cannot assume that Composer is being used, and
> that it is being used correctly.
>
> So again this would be fragile.
>
> > […]
> constants
> > […]
>
> This means you are changing the meaning of existing declare() to apply
> to the entire namespace?
> Or to the entire directory?
>
>
To entire namespace just like:

<?php declare(strict_types=0);

namespace_declare('Acme\Animal', [
    'strict_types' => 1,
    'dynamic_object_properties' => 0,
    ...
]);

namespace Acme\Animal declare(
    strict_types=1,
    dynamic_object_properties=0
); // <-- this works same as namespace_declare call above

namespace Acme\Machines {
    // here we have strict_types=0 turned off
}


> Or maybe the difference here is that there is no semicolon directly
> after the namespace declaration?
>
> I am not convinced by this syntax.
> But even if we would find a good syntax, the behavioral problems
> pointed out by Stanislav still apply.
>



-- 
regards / pozdrawiam,
--
Michał Brzuchalski
about.me/brzuchal
brzuchalski.com

---

## #101347 — michal@brzuchalski.com — 2017-12-13T05:04:55+00:00

URL: https://externals.io/message/101323#101347 · In reply to: #101345

2017-12-13 5:38 GMT+01:00 Michał Brzuchalski <michal@brzuchalski.com>:

>
>
> 2017-12-13 5:24 GMT+01:00 Andreas Hennings <andreas@dqxtech.net>:
>
> > […]
>
Actually not true. `namespace` keyword is reserved and none class can have
such name.
This means this example couses a syntax error:

<?php
namespace Acme\Animals;
class namespace {}

That why we can assume we can utilise namespace.php file name.
And also why not trying to include it on autoload call?
For eg.
<?php

new Acme\Animal\Cat(); // tries to load $file = "src/Acme/Animal/Cat.php"

// but prevoiusly tries to load
require_once dirname($file) . `DIRECTORY_SEPARATOR` . 'namespace.php';

It's bad because it';s magic, but the `namespace.php` filename is still
available to use.


> > […]
> To entire namespace just like:
>
> <?php declare(strict_types=0);
>
> namespace_declare('Acme\Animal', [
>     'strict_types' => 1,
>     'dynamic_object_properties' => 0,
>     ...
> ]);
>
> namespace Acme\Animal declare(
>     strict_types=1,
>     dynamic_object_properties=0
> ); // <-- this works same as namespace_declare call above
>
> namespace Acme\Machines {
>     // here we have strict_types=0 turned off
> }
>
>
> > […]
>
>
>
> --
> regards / pozdrawiam,
> --
> Michał Brzuchalski
> about.me/brzuchal
> brzuchalski.com
>



-- 
regards / pozdrawiam,
--
Michał Brzuchalski
about.me/brzuchal
brzuchalski.com

---

## #101348 — Ivan Enderlin — 2017-12-13T06:36:10+00:00

URL: https://externals.io/message/101323#101348 · In reply to: #101323

> 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.
Thanks for the proposal.

While it seems comfortable for the user, and I understand the point 
you're trying to solve somehow, it can be a nightmare for the VM, the 
developer, and the user.

I've few remarks and/or questions:

* When parsing a file, the way the VM has to interprete/execute the file 
depends on a _runtime_ configuration defined in _another_ file. It makes 
things more implicit, and that's not good.

* It can also be a nightmare for the developer. The behavior of their 
library can be changed by another library because there is no 
restriction about the location or usage of `namespace_declare`. If at 
least `namespace_declare` would only apply to the _current_ namespace, 
it might be better.

* If `namespace_declare` is called twice for the same namespace, an 
error is raised, OK. It's easy to break someone's code by registering a 
file in an autoloader to load first, and call `namespace_declare` for 
that file. What the error will look like? It's important to prompt the 
correct culprit to the user. Any strategy to find which one is the culprit?

* As you said in the RFC in the Proliferation of declare directives 
Section, it's not a good thing for the language to introduce more and 
more directives. PHP is living a time where it makes good things easier 
to do, and bad things harder to do. Everything I can imagine with 
`namespace_declare` is definitively not good for the language, the VM, 
and the ecosystem. Introducing a `strict` mode for the language is 
definitively a good thing to progressively make PHP stricter, yes, but I 
don't see a real need or a real motiviation behind `namespace_declare`, 
I for one see only dangers.

So I'm sorry to say that —right now— I'm totally oppose to this RFC :-).

Cheers.
-Ivan.

---

## #101349 — michal@brzuchalski.com — 2017-12-13T07:12:31+00:00

URL: https://externals.io/message/101323#101349 · In reply to: #101347

2017-12-13 6:04 GMT+01:00 Michał Brzuchalski <michal@brzuchalski.com>:

>
>
> 2017-12-13 5:38 GMT+01:00 Michał Brzuchalski <michal@brzuchalski.com>:
>
> > […]
> Actually not true. `namespace` keyword is reserved and none class can have
> such name.
> This means this example couses a syntax error:
>
> <?php
> namespace Acme\Animals;
> class namespace {}
>
> That why we can assume we can utilise namespace.php file name.
> And also why not trying to include it on autoload call?
> For eg.
> <?php
>
> new Acme\Animal\Cat(); // tries to load $file = "src/Acme/Animal/Cat.php"
>
> // but prevoiusly tries to load
> require_once dirname($file) . `DIRECTORY_SEPARATOR` . 'namespace.php';
>
> It's bad because it';s magic, but the `namespace.php` filename is still
> available to use.
>
>
Andreas, we're touching namespaces which is a hard subject, but if I could
fly away with my thoughts
I'd propose to introduce something called for eg. a package and then
divide it's name in class/function/const name with a single colon, for eg.
Acme:Animal\Cat
which gives additional information about package which then declares
something and may be
a good start for future scoped declarations.

I've prepared a short gist to illustrate that
https://gist.github.com/brzuchal/352ffce2717648f0d43f2d5a0c4bfb7b

This solution doesn't require usage of Composer, but needs to pass an
aotuloader function a type to load.
There was a proposal on internal some time ago to pass additional parameter
to load function.


>
> > […]
>
>
>
> --
> regards / pozdrawiam,
> --
> Michał Brzuchalski
> about.me/brzuchal
> brzuchalski.com
>



-- 
regards / pozdrawiam,
--
Michał Brzuchalski
about.me/brzuchal
brzuchalski.com

---

## #101350 — Tony Marston — 2017-12-13T10:37:41+00:00

URL: https://externals.io/message/101323#101350 · In reply to: #101342

"Andreas Hennings"  wrote in message 
news:CAH0Uv3FnYf_c7in4_6AmDO5pUZHsgU0m5scjU5oRz2kTAJ=+bw@mail.gmail.com...
>
>I agree with all of Stanislav's emails in this thread so far.
>
>
> > […]
<snip>
>
>PHP as a language should not assume that someone is using Composer 
>correctly.
>

Or even using Composer at all.

-- 
Tony Marston

---

## #101351 — Tony Marston — 2017-12-13T10:43:46+00:00

URL: https://externals.io/message/101323#101351 · In reply to: #101343

""Michal Brzuchalski""  wrote in message 
news:CABdc3WpomNLz+vX_m0B0wQ3uCiMiw8xw4Ea_sGD-PTDGfV-PbA@mail.gmail.com...
>
>2017-12-13 1:16 GMT+01:00 Andreas Hennings <andreas@dqxtech.net>:
>
<snip>
>
>Why? Because users use PSR-4 so then they're src folder looks more like:
?
<snip>

You are assuming that everybody is using PSR-4. That is a wrong assumption 
to make.

-- 
Tony Marston

---

## #101352 — michal.brzuchalski@gmail.com — 2017-12-13T13:19:26+00:00

URL: https://externals.io/message/101323#101352 · In reply to: #101351

13.12.2017 11:44 "Tony Marston" <TonyMarston@hotmail.com> napisał(a):

""Michal Brzuchalski""  wrote in message news:CABdc3WpomNLz+vX_m0B0wQ3u
CiMiw8xw4Ea_sGD-PTDGfV-PbA@mail.gmail.com...


> 2017-12-13 1:16 GMT+01:00 Andreas Hennings <andreas@dqxtech.net>:
>
> <snip>


> Why? Because users use PSR-4 so then they're src folder looks more like:
>
?
<snip>

You are assuming that everybody is using PSR-4. That is a wrong assumption
to make.


I didn't say everybody at all! Please read carefully.


-- 
Tony Marston

---

## #101353 — Tony Marston — 2017-12-13T13:53:15+00:00

URL: https://externals.io/message/101323#101353 · In reply to: #101352

""Michal Brzuchalski""  wrote in message 
news:CABdc3Wrz8qu_hGsBTjGbWwcT8YpLxgChONeE9NiJKWcDEruySw@mail.gmail.com...
>
>13.12.2017 11:44 "Tony Marston" <TonyMarston@hotmail.com> napisal(a):
>
>""Michal Brzuchalski""  wrote in message news:CABdc3WpomNLz+vX_m0B0wQ3u
>CiMiw8xw4Ea_sGD-PTDGfV-PbA@mail.gmail.com...
>
>
> > […]
>
>
> > […]
>?
><snip>
>
>You are assuming that everybody is using PSR-4. That is a wrong assumption
>to make.
>
>
>I didn't say everybody at all! Please read carefully.
>

I DID read carefully. You wrote "users use PSR-4" and not "those users who 
use PSR-4". You did not specify a subset of users, so this implies all 
users.

-- 
Tony Marston

---

## #101390 — Rowan Collins — 2017-12-16T23:18:48+00:00

URL: https://externals.io/message/101323#101390 · In reply to: #101349

> Andreas, we're touching namespaces which is a hard subject, but if I could
> fly away with my thoughts
> I'd propose to introduce something called for eg. a package


My thoughts were actually going along the same lines: basically, the 
current implementation of namespaces is, I think by design, very 
conservative in what a namespace represents. A namespace doesn't have 
any identity, and doesn't have any codified structure, it's just a 
shorthand for referring to similarly named classes (plus functions and 
constants).

There are several things that I think would feel more natural with 
"packages" than namespaces as they exist today:

- Declare directives, as discussed here
- Visibility modifiers, e.g. a "private class", accessible only within 
its package
- Per-package autoloaders, that only get called for classes in that 
package, rather than a global autoloader which parses out the prefixes 
it's interested in
- An autoloader callback that fires once for each package, to setup 
these options

Another difference is that namespaces tend to form deep hierarchies, but 
you're unlikely to set options at every level of the hierarchy. For 
instance, you probably don't want to set strict_types on for 
Acme\MyPackage\Input but off for Acme\MyPackage\Output. So a separate 
syntax to mark which level is the "package" would reduce the number of 
places a setting could be set, which would reduce the number of places 
you'd need to look - a bit like having Apache settings in a VirtualHost 
for the whole site, rather than .htaccess files in every directory.

All that being said, I'm not 100% convinced this is solving a real 
problem. Yes, the option has to be set in every file, but that's because 
it effects the way that file is compiled, and the compiler sees one file 
at a time. The same applies to the "namespace" directive, which you 
might otherwise set against a particular directory. I don't see a 
pressing need to add the complexity.

Regards,

-- 
Rowan Collins
[IMSoP]

---

## #106295 — Nikita Popov — 2019-07-25T13:34:07+00:00

URL: https://externals.io/message/101323#106295

> Hi internals!
>
> 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.
>
> Thanks,
> Nikita
>

I plan to pick up this proposal again. I think the motivation here has
become more pressing in the meantime. The strict_operators proposal is
under discussion, and Rowan's "locked classes" essentially concluded with
"doing this with a declare is better". I also think that this proposal will
be helpful for the explicit call-site by-reference passing RFC.

Based on the received feedback, I plan to change this proposal from being
"namespace-scoped" to being "directory-scoped" instead. This should both
resolve some of the concerns and make the proposal more flexible: Not all
code sharing the same namespace is part of the same package (multiple
packages may have classes in the same namespace), or not of the same type
(code and tests may share a namespace) and sometimes people use incorrect
namespaces out of ignorance (e.g. place their own Doctrine models under the
Doctrine namespace). Making the declares apply to a directory avoids these
issues.

Nikita

---

## #106302 — Rasmus Schultz — 2019-07-27T08:33:15+00:00

URL: https://externals.io/message/101323#106302

...
> Based on the received feedback, I plan to change this proposal from being
> "namespace-scoped" to being "directory-scoped" instead

...


I think that's a better approach.

But please consider doing this without adding another global function that
defines more global (compiler) state?

If it's going to be directory-scoped, using some kind of project root file,
in my opinion, is the more traditional way to declare directory-scoped
boundaries.

For example, if you could just put a "php.json" file in the root of your
namespace folder, this becomes very easy to spot next to your ".gitignore",
"composer.json", "package.json", "tsconfig.json" and any other well-known
project configuration files.

Finding these in the root of any project/library is pretty intuitive -
poking through bootstrapping scripts for a global function call, meh, not
so much.

(This file could be used to declare other repetitive things too - for one,
why is the declare() situation any different from having to repeat a
namespace declaration in every file? This is just another global setting
that could just as well be declared once in a project root file. If this
file were parsable or reflectable by e.g. Composer, this could probably be
used to make the "autoload" section in Composer optional, for one.)

(You could expand upon this feature in the future to add other compiler
options - for instance, toggling global functions, which would allow for
things like correcting inconsistent argument order in the standard
libraries, toggling incompatible language features, toggling improved
defaults for certain functions, a proper strict type-checking mode at some
point in the future, etc...)

---

## #106303 — Mark Randall — 2019-07-27T22:53:52+00:00

URL: https://externals.io/message/101323#106303

> 
> > […]

Personally I'm not a huge fan of using implicit hierarchical directories 
for managing defines.

It's certainly better than global state functions, but in general I 
don't feel comfortable with the idea that an arbitrary file can effect 
the behaviour of the VM for particular files that does not directly 
reference it.

Obviously there's lots of functions that do that, set_error_handler etc, 
but I think it is best avoided wherever possible.

I think what the situation calls for is the PHP equivalent of #include - 
we need to be able to explicitly import the definitions from another file.

====== MyProject\Models\Test\SomeClass.php =======
```
<?php
import_declares(\MyProject);

namespace MyProject\Models\Test

class SomeClass {
   public function action(&$ref) { ... }
}
```

====== MyProject\declares.inc =======
```
<?php
declare(strict_types=1)
declare(call_site_references=1)
declare(global_function_fallback=0)
```

This forms an explicit link between the file and the declarations.

Clearly the question is "how to locate that file" as we don't want to 
return to the days of having to add relative file paths to every file.

An option which immediately comes to mind would be a new autoloader 
routine that maps namespaces to PSR4 physical directories. Sounds like a 
job for composer tbh so userland workload would be limited for projects 
using modern workflows.

This would of course be dependent on if the compiler stage has the 
ability to branch off and call an autoloader the first time it 
encounters the import_declares.

Just my 2 pence worth.

--
Mark Randall

---

## #106306 — Stanislav Malyshev — 2019-07-28T03:17:07+00:00

URL: https://externals.io/message/101323#106306

Hi!

> I plan to pick up this proposal again. I think the motivation here has
> become more pressing in the meantime. The strict_operators proposal is
> under discussion, and Rowan's "locked classes" essentially concluded with
> "doing this with a declare is better". I also think that this proposal will
> be helpful for the explicit call-site by-reference passing RFC.

I think it's a wrong way to make semantics of the language to be
different in different libraries. We add one option, than another, than
another, and soon we have 512 variants of the language, all slightly
different, and you have to keep track which one you are dealing with on
each file, and God forbid you move a piece of code from one library to
another, you have to rewrite half of it because it was written in PHP
#243 but this library is actually PHP #116.

I know there is not a consensus about usage of some newly proposed
language features. I think introducing this kind of fragmentation to
deal with it is exactly wrong way to deal with it. It leads to code from
different codebases being incompatible with each other on source level
(even if they work together at runtime). We've decided not to do INI
options to change language behavior, and I think we should also not make
declare() options to change language behavior, because they are -
especially when applying to more than local file - essentially low-grade
INI options. They create non-local context that changes behavior of the
language, and they make it impossible, reading the local code, to know
what it actually means and what would happen if you run it.
I think it's much better for the language not to have some features than
to fragment the language and make it incompatible with itself.

> Based on the received feedback, I plan to change this proposal from being
> "namespace-scoped" to being "directory-scoped" instead. This should both

I don't think it improves much, in my opinion, and it also introduces
hard dependency in the language on specific placing of files and
directories - i.e. if you move file on the filesystem, it can actually
work differently, which was never the case before. Having concepts like
filenames change the core functionality of the language looks to me like
an example of leaky abstraction and a hack which may solve a particular
problem now but at the cost of making the whole design more messy and
introducing more problems in the future.
I said before that moving code between libraries in this setup could
break it - but with this change, even copying a file to a different
directory may break it! Moreover, change in one part of project,
changing some behavioral option, would propagate and influence code
about which the changer may not even know (e.g. if parts of the project
are developed and tested separately and only deployed in final form on a
production filesystem).
This looks like potential to create an environment that is very hard to
navigate and keep straight which of the options is in play for each
peace of code.
-- 
Stas Malyshev
smalyshev@gmail.com

---

## #106307 — me@jhdxr.com — 2019-07-28T06:33:40+00:00

URL: https://externals.io/message/101323#106307

The introduction in this RFC says "A common complaint is that this directive has to be specified in every single file.". I think people will complain import_declares if we follow your design.

Regards,
CHU Zhaowei

> -----Original Message-----
> From: Mark Randall <markyr@gmail.com>
> Sent: Sunday, July 28, 2019 6:54 AM
> To: internals@lists.php.net
> Subject: Re: [PHP-DEV] Re: [RFC] Namespace-scoped declares, again
> 
> 
> > […]
> 
> Personally I'm not a huge fan of using implicit hierarchical directories for
> managing defines.
> 
> It's certainly better than global state functions, but in general I don't feel
> comfortable with the idea that an arbitrary file can effect the behaviour of the
> VM for particular files that does not directly reference it.
> 
> Obviously there's lots of functions that do that, set_error_handler etc, but I
> think it is best avoided wherever possible.
> 
> I think what the situation calls for is the PHP equivalent of #include - we need to
> be able to explicitly import the definitions from another file.
> 
> ====== MyProject\Models\Test\SomeClass.php ======= ``` <?php
> import_declares(\MyProject);
> 
> namespace MyProject\Models\Test
> 
> class SomeClass {
>    public function action(&$ref) { ... } } ```
> 
> ====== MyProject\declares.inc =======
> ```
> <?php
> declare(strict_types=1)
> declare(call_site_references=1)
> declare(global_function_fallback=0)
> ```
> 
> This forms an explicit link between the file and the declarations.
> 
> Clearly the question is "how to locate that file" as we don't want to return to the
> days of having to add relative file paths to every file.
> 
> An option which immediately comes to mind would be a new autoloader routine
> that maps namespaces to PSR4 physical directories. Sounds like a job for
> composer tbh so userland workload would be limited for projects using modern
> workflows.
> 
> This would of course be dependent on if the compiler stage has the ability to
> branch off and call an autoloader the first time it encounters the
> import_declares.
> 
> Just my 2 pence worth.
> 
> --
> Mark Randall
> 
> --
>  To unsubscribe, visit:
> http://www.php.net/unsub.php

---

Next page: https://externals.io/message/101323.md?page=2
