Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:115550 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 80453 invoked from network); 22 Jul 2021 08:25:33 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 22 Jul 2021 08:25:33 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 6409B180538 for ; Thu, 22 Jul 2021 01:51:12 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-0.6 required=5.0 tests=BAYES_00,BODY_8BITS, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-lf1-f53.google.com (mail-lf1-f53.google.com [209.85.167.53]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Thu, 22 Jul 2021 01:51:11 -0700 (PDT) Received: by mail-lf1-f53.google.com with SMTP id m16so7322255lfg.13 for ; Thu, 22 Jul 2021 01:51:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=2p1txn7bCniVEdz6wnMj2iCsM8NZmfiJGaJYyIOee4A=; b=NgSUhQax3/FBk5sZAeQQysQhW2dTeEBzXKyuu+Zz2bTjzQStBdFJ8Z/6ingX+djD9u 69AZkVTSj3kaJ5+QONGJ9BGdnvW6rIe6O2Yxu5nBZ7MwFun2YQBVKa31Q7FQ743v990f fHQjBfZ7aGpZCdn7UOmmOiDES4pNKRYsdiwbeMFqHkQYCr4tcX7bb2LGm1PSXoGoV8sW zo972Q2fq37BTjNwnl2685ekgcxexsVsfM1Kttnwzp38msxZ6IGn/Oqu/cc3QrVvxxs/ +hVZm4Bf570HHNfegLrBKNJk/TvD3iW7hwI7yEQoqR2qp1+wnjmpdcgJ8XaUVPr856p8 PpIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to; bh=2p1txn7bCniVEdz6wnMj2iCsM8NZmfiJGaJYyIOee4A=; b=Y4y5GeV5QogJ5euLv/jSq5EWFa1zeOaIVlGeF4/yqMq6Fn237mho1qFbCUJxPLG0g8 jYH/LrleY9nOJyV5fiYnlEboPzvyvQBZBKp+WWqe9YmhiB2nCFBzoaSTSV0jfr7xNKtY 0H1LuVascDyNTf+vMtG50Y3nZyMd8GoSrXb2DOT/hVxGPyIT/spOgmKPuQI/aH1wtfrQ u3Wf84MsZRVZ6LwoKVo/1jDvDLcxJUNmlRrSLm9elM7Q1pUDHTOVd6nhHTtNUnweE2aY mjcl6vyC+NGMgtv6638ex71gZtTcBkVUkDAtpPrB4jLV+HG+L9sPaGtZY09GYH+PkXAj nG6A== X-Gm-Message-State: AOAM532I1fIr+jdh8IFHD2kF1j6ZjoRi7YtU0sFDtDtZ5Xalvkzrktpj oBMu1DdcyzfDVdTIO6k90WvkXKJpqpK+6J0WHZD3/lg1pnU= X-Google-Smtp-Source: ABdhPJxj93OxSFtR89LFaT5XNorQlkw3h9FXonOvgk9nE/h2h4zIRx1zmiK8VOLqmcbQcYDLnIFPnETUvoIc5JCjX1k= X-Received: by 2002:ac2:5297:: with SMTP id q23mr28131079lfm.223.1626943869963; Thu, 22 Jul 2021 01:51:09 -0700 (PDT) MIME-Version: 1.0 References: <5319a8c8-f63a-fa5d-141b-2885b21d1113@php.net> In-Reply-To: <5319a8c8-f63a-fa5d-141b-2885b21d1113@php.net> Date: Thu, 22 Jul 2021 10:50:53 +0200 Message-ID: To: PHP internals Content-Type: multipart/alternative; boundary="00000000000070522205c7b26333" Subject: Re: [PHP-DEV] Method compatibility checks and order in which files are included From: nikita.ppv@gmail.com (Nikita Popov) --00000000000070522205c7b26333 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Thu, Jul 22, 2021 at 10:32 AM Sebastian Bergmann wrote: > We noticed that the PHARs of PHPUnit stopped working with PHP 8.1 [1]. > Before [2], a commit pushed today, PHPUnit loaded all sourcecode files > packaged in the PHAR on startup (to work around problems that (hopefully) > no longer exist because PHPUnit's PHAR is scoped using PHP-Scoper > nowadays). This loading of all sourcecode files lead to the error reporte= d > in [1]. The "static include list" used for this is generated by PHPAB [3] > which performs a topological sort based "class implements interface", > "class uses trait", "class extends class", etc. dependencies. This > topological sort does not, however, consider type declarations for > properties as well parameters and return values as dependencies. > > What follows is a minimal, reproducing example: > > . > =E2=94=9C=E2=94=80=E2=94=80 autoload.php > =E2=94=9C=E2=94=80=E2=94=80 Collection.php > =E2=94=94=E2=94=80=E2=94=80 CollectionIterator.php > > 0 directories, 3 files > > This is the contents of autoload.php: > > require __DIR__ . '/Collection.php'; > require __DIR__ . '/CollectionIterator.php'; > > This is the contents of Collection.php: > > class Collection implements IteratorAggregate > { > public function getIterator(): CollectionIterator > { > return new CollectionIterator($this); > } > } > > And this is the contents of CollectionIterator.php: > > class CollectionIterator implements Iterator > { > public function __construct(Collection $collection) > { > } > > public function current(): mixed > { > } > > public function next(): void > { > } > > public function key(): int > { > } > > public function valid(): bool > { > } > > public function rewind(): void > { > } > } > > When I run autoload.php then I get > > Fatal error: Could not check compatibility between > Collection::getIterator(): CollectionIterator > and IteratorAggregate::getIterator(): Traversable, because class > CollectionIterator is not > available in /home/sb/example/Collection.php on line 4 > > I am using PHP 8.1-dev (590af4678bbdbb9422bfcc568a0b8d2d1a6f74f5). The > error does not occur with PHP 8.0.8. > > I assume the following happens: > > * The compiler works on Collection.php > * The compiler sees that Collection implements IteratorAggregate > * The compiler sees that Collection::getIterator() returns > CollectionIterator > * The compiler performs the method compatiblity check > * The method compatiblity check cannot be performed because > CollectionIterator has not been compiled yet > > When I change autoload.php like so > > require __DIR__ . '/CollectionIterator.php'; > require __DIR__ . '/Collection.php'; > > then the method compatiblity check can be performed (and succeeds without > error). > > After this long introduction (sorry!), I can finally ask my question: can > there be situations where this alternate order of requiring the source > files would also fail? Is there a potential for cyclic dependencies > between two sourcefiles that can only be resolved when autoloading is > used? I am "scared" that using "static include list" may become unfeasibl= e > when more compile-time checks such as the method compatibility check are > added. > Hey Sebastian, This behavior isn't new in PHP 8.1, it exists since the introduction of variance support in PHP 7.4. Presumably you just didn't hit a case where a) a non-trivial subtying relationship had to be established and b) the files did not happen to be included in the right order. The only thing that PHP 8.1 adds are more types on internal classes, which means that there are more type constraints to satisfy. To answer your actual question, yes, it's possible to have cyclic dependencies, and such cases are (and can only be) supported if an autoloader is used. A simple example is this structure: class A { public function method(): B {} } class B extends A { public function method(): C {} } class C extends B {} There is no legal ordering of these classes that does not involve autoloading during inheritance. Regards, Nikita --00000000000070522205c7b26333--