Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126971 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id 8F1DF1A00BC for ; Fri, 28 Mar 2025 20:43:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1743194447; bh=RG3NO/JEgJFVkZkMGXiy8l0A30+WlxpYo+4YcxQVgoU=; h=References:In-Reply-To:From:Date:Subject:To:From; b=XJTs0FEV9tqaEXVyOt/NQXoVo0xJ1QusoWIOSqTuIUSsl0P6maBT/KdRfKWnDGMVP rgaocH+UAbwfiMwQbBcgCLNKIMjrljX+jiSLpFWCLBmdwBeQdwOhTNmKcll/9zQ+5j MXACEO4oWH+m9acvJ6sXSnEg4bXB1qZOXQDdqbpnV97CUo0BPwUpcnrdvNQ29SlBFv NK7Vhb9UtADenvnmcPMZE3G1zNGJBD66Nv2UWAt+5LJxauTaBi5Uo6ybt+ogOnSy2W qr50L7AQ1ChQcrsje/T00IebJjN1yUk+brvkNv5D5KwDBQYKFX0wKKbEUfXxInFUYZ Nvk0i+1SDnw+Q== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 4353D1801D8 for ; Fri, 28 Mar 2025 20:40:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-0.2 required=5.0 tests=BAYES_20,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-pj1-f46.google.com (mail-pj1-f46.google.com [209.85.216.46]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 28 Mar 2025 20:40:46 +0000 (UTC) Received: by mail-pj1-f46.google.com with SMTP id 98e67ed59e1d1-2ff694d2d4dso4333055a91.0 for ; Fri, 28 Mar 2025 13:43:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1743194593; x=1743799393; darn=lists.php.net; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=ai5B/yq7RbxnMz/zg5nH+gLkvwVB4ytnKvtOIOmxHH0=; b=WarnUSdIEpfxnediNSFm8vA8MlPAWvbVCxVbg0LgjAleH80UY8bxuY4v2Gba+OOmYy QFkdDZ9K2kzr9IJ6E2djtT87vxoytfXyCdb4oDfrHla3A8XJnHKoE/JfaUGRAnUX2vFE ghjEGxO55nvZSuI1jD28vJc0+4YfTsB3yXApROyI4ryH4ApQH6UzYz64s7JIiEBh4GWQ Qegb/pfhiXj4Rzusf1PW4iGEIsqR4xqpBuvYOKASm2U5kAn7HWeKfKxQb8LrCkrlBpFn VAYGG4IrVt4NiP7Gjs5IN1Xxuc6pyXTH5sK5cwj/Y4QNLtnAeC2zCdyQLOhUlUAEIMdz 9xUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1743194593; x=1743799393; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ai5B/yq7RbxnMz/zg5nH+gLkvwVB4ytnKvtOIOmxHH0=; b=mzsxp8puHIkFzDUCHLLS0xtjtklMvBKG80yHNYOrT0ZOL+wnyu5m5G8h2SoQjnL2CO II2ewNU4OVwB80eHIjrOuzcW2UIvPjRqesuJKrLD1n4XLKnCWRApVxgyy6SalQx2Z6/z dT+ShrdkeDiMxdzfO1fsaCe5r3GoXNQQQJkFagfH8nQEU45V44jwJF+qMH6sAnChU+4K x/Bd2xsuUtYhYNZPXh+ALtek7HM9l7NTxWac2pX/U0PivnoCQDc4rw1GIK7k2V7/xgU5 HG3ZGtuhVpYepowTY3iWP+wuAarfi2WaKf4kjogobj2A3ozNV3Qa9OwOO4jomi7yfsJ8 t+3w== X-Gm-Message-State: AOJu0YxVxNP0AhWrPmsb+IuYj0amg8AqjOtbT1syhqnLfnVp2pZIVGpU J6ueKueROL+e1b7+DifCWp266AePm7czQs99V4TiLZkVy1ooBDA+8OEEOHZCANeXB3LZEl+iFmj kiguH9f7NNU6q4c4l3C/4bO4edybNlQ== X-Gm-Gg: ASbGnctbEJTnJPBqkej6CPH9OXdUmCr6Ce3fVm69dV+EIrCuO6i0FvRhXXviurF9XL5 9FhEf8hyNB61WqhtuFg/dhyVv6exWSsC9swdODTwzaFyn6CVCLHVIJXck30t/UV/HpZIaBn4Ry3 ODq5un2ENa/thi7j2S1xlbulo6vB1OvohuXv8kWRaLIa88C7t5VtMEqC6yVQ== X-Google-Smtp-Source: AGHT+IEYJQQEoAzaOZLssLXu8GkyQKMeUNvJ/zlENv0rAwTbClLcl8a/kPZNCUzoitbz/9mE83nVPCxajER90Z6Y/7s= X-Received: by 2002:a17:90b:48d0:b0:2ee:db8a:2a01 with SMTP id 98e67ed59e1d1-3053216198emr1037851a91.30.1743194592293; Fri, 28 Mar 2025 13:43:12 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Fri, 28 Mar 2025 13:42:46 -0700 X-Gm-Features: AQ5f1JpIPsgU6Hvc7QIQbM--k8e7xLrIz8TUASsJ5rYHByM43tVHYn2cl91drRw Message-ID: Subject: Re: [PHP-DEV] [RFC] [Discussion] Never parameters To: PHP internals Content-Type: multipart/alternative; boundary="00000000000072baac06316d1ee8" From: matthewfonda@gmail.com (Matt Fonda) --00000000000072baac06316d1ee8 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Tim and Larry, Thanks for sharing examples. I'm not sure I follow how never parameters help in either of these cases. As far as I can tell, the problem remains that these methods can't actually be called. On Fri, Mar 21, 2025 at 4:50=E2=80=AFAM Tim D=C3=BCsterhus wrote: > Am 2025-03-20 21:27, schrieb Matt Fonda: > > If an interface adds a method but makes no promises about what > > parameters > > it accepts, then why is it part of the interface in the first > > place--why > > add a method that can't be used? > > It would more cleanly allow for userland / PHPDoc-based generics, while > still providing some engine-enforced type safety. Consider this example > (not sure if I got the syntax completely right): > > /** @template T */ > interface Comparable { > /** @param T $other */ > public function compareTo(never $other): int; > } > > /** @implements Comparable */ > final class Number implements Comparable { > public function compareTo(Number $other): int { return $this <= =3D> > $other; } > } I don't follow why Number would implement Comparable in the first place, since we won't actually be able to call Comparable::compareTo. i.e. we cannot write the following method: function greaterThan(Comparable $a, Comparable $b): bool { return $a->compareTo($b) > 0; } If we wanted to actually call compareTo, we need to use a specific implementation: function greaterThan(Number $a, Number $b): bool { return $a->compareTo($b) > 0; } At this point, we're no longer using the interface, so there's no point in Number implementing it. Number is then free to define compareTo(Number $other). I share Nikita's sentiment in the previous RFC discussion [1], and have yet to see an answer to it: I don't think this really addresses my concern, so let me repeat it: You > cannot actually call a method using a never-type argument while typing > against the interface. What's the point of the interface then? > > I don't think "you must use this in conjunction with a 3rd-party phpdoc > generics implementation for it to make any sense at all" is a suitable wa= y > to resolve that. On Fri, Mar 21, 2025 at 8:53=E2=80=AFAM Larry Garfield wrote: > Changing the interface to use `never` instead of `mixed` would have the > weakest guarantees of the three, since it doesn't force me to use the > *same* widened type on serializeInt(), serializeFloat(), serializeString(= ), > etc., even though it would always be the same. But it would allow me to > communicate more type information than I can now. > Suppose you made this change from mixed to never. As long as you're typing against the Formatter interface and not a specific implementation, then you cannot actually call $formatter->serializeInt() etc. because the interface defines the parameter type as never, and you cannot call a method with a parameter type of never. This is the case in your real world usage [1]. Here, $serializer->formatter is typed against Formatter [2], not a specific implementation. As such, all we know is that we have an instance of Formatter--we don't know anything about the concrete type--and thus we can't actually call e.g. serializeInt() because never is the only type we know here. Best regards, --Matthew [1] https://externals.io/message/115712#115752 [2] https://github.com/Crell/Serde/blob/777fc16e932d4dcf1d600335961685885cd815c= 4/src/PropertyHandler/ScalarExporter.php#L17 [3] https://github.com/Crell/Serde/blob/777fc16e932d4dcf1d600335961685885cd815c= 4/src/Serializer.php#L31 --00000000000072baac06316d1ee8 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Tim and Larry,

= Thanks for sharing examples. I'm not sure I follow how never parameters= help in either of these cases. As far as I can tell, the problem remains t= hat these methods can't actually be called.

<= /div>
On Fri, Mar 21, 2025 at 4:50=E2=80=AFAM Tim D=C3=BCst= erhus <tim@bastels= tu.be> wrote:
Am 2025-03-20 21:27, schrieb Matt Fonda:
> If an interface adds a method but makes no promises about what
> parameters
> it accepts, then why is it part of the interface in the first
> place--why
> add a method that can't be used?

It would more cleanly allow for userland / PHPDoc-based generics, while still providing some engine-enforced type safety. Consider this example (not sure if I got the syntax completely right):

=C2=A0 =C2=A0 =C2=A0/** @template T */
=C2=A0 =C2=A0 =C2=A0interface Comparable {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/** @param T $other */
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0public function compareTo(never $other): = int;
=C2=A0 =C2=A0 =C2=A0}

=C2=A0 =C2=A0 =C2=A0/** @implements Comparable<Number> */
=C2=A0 =C2=A0 =C2=A0final class Number implements Comparable {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0public function compareTo(Number $other):= int { return $this <=3D>
$other; }
=C2=A0 =C2=A0 =C2=A0}=C2=A0
=C2=A0=C2=A0

I don't fol= low why Number would implement Comparable in the first place, since we won&= #39;t actually be able to call Comparable::compareTo. i.e. we cannot write = the following method:

function greaterThan(Compara= ble $a, Comparable $b): bool {
=C2=A0 =C2=A0 return $a->compar= eTo($b) > 0;
}

If we wanted to actual= ly call compareTo, we need to use a specific implementation:

=
function greaterThan(Number $a, Number $b): bool {
=C2=A0 =C2=A0 return $a->compareTo($b) > 0;
}
=

At this point, we're no longer using the interface,= so there's no point in Number implementing it. Number is then free to = define compareTo(Number $other).

I share Niki= ta's sentiment in the previous RFC discussion [1], and have yet to see = an answer to it:

I don't think this really addresses my concern, so let me r= epeat it: You
cannot actually call a method using a never-type argument = while typing
against the interface. What's the point of the interfac= e then?

I don't think "you must use this in conjunction wit= h a 3rd-party phpdoc
generics implementation for it to make any sense at= all" is a suitable way
to resolve that.
On Fri, Mar 21, 2025 at 8:53=E2=80=AFAM Larry = Garfield <la= rry@garfieldtech.com> wrote:
Changing the in= terface to use `never` instead of `mixed` would have the weakest guarantees= of the three, since it doesn't force me to use the *same* widened type= on serializeInt(), serializeFloat(), serializeString(), etc., even though = it would always be the same.=C2=A0 But it would allow me to communicate mor= e type information than I can now.

Supp= ose you made this change from mixed to never. As long as you're typing = against the Formatter interface and not a specific implementation, then you= cannot actually call $formatter->serializeInt() etc. because the interf= ace defines the parameter type as never, and you cannot call a method with = a parameter type of never.

This is the case in you= r real world usage [1]. Here, $serializer->formatter is typed against Fo= rmatter [2], not a specific implementation. As such, all we know is that we= have an instance of Formatter--we don't know anything about the concre= te type--and thus we can't actually call e.g. serializeInt() because ne= ver is the only type we know here.

Best regards,
--Matthew

--00000000000072baac06316d1ee8--