On 3 May 2022, at 14:55, Rowan Tommins <rowan.coll...@gmail.com> wrote: > > On 03/05/2022 12:37, Craig Francis wrote: >> But what is that benefit? I'm sorry, but I really don't see it. > > > I started drafting a longer reply, but honestly I don't think we're getting > anywhere. Every attempt to explain the benefit seems to end in one of two > ways: > > - an endless back and forth nit-picking hypothetical situations where it > might or might not be useful > - an outright dismissal that "people who want it strict can go over there and > use strict_types=1 and/or static analysis" > > To me, it's *always* about trade-offs: the *benefit* of strict checks exists > for everyone, and the question is whether they want to pay the *cost* or not. > As long as we can't agree on that fundamental point, there's no point > continuing the discussion.
I hope I don't come across like that; I'm really trying to understand the benefits and costs (I tend to use small examples to help myself understand). I'm not trying to be dismissive with the use of static analysis. I just think PHP should be tolerant of some things (e.g. string '5' to int 5, and null to empty string), but I also recognise some developers prefer a very strict environment that does not do any type coercion (that's where I think static analysis works really well, as it can enforce extra checks, including type checks for all variables from all sources to all sinks). That said, I do see value in some Type Errors, like how I updated my RFC a couple of weeks ago with some examples "like `substr($string, “offset”)` and `htmlspecialchars(array())` as being clearly problematic" (thanks again George). I'm also fine with `substr('abc', $offset)` rejecting an Empty String or NULL for `$offset` (I'll note that `$offset` was never added to my list of 335 parameters). Under "Future Scope" I've given 4 example parameters that probably should reject an Empty String or NULL (because they do represent problems, similar to how `$separator` in `explode()` already has the “cannot be empty” fatal error). And finally, I can see how `mt_rand(NULL, NULL)` could be a problem (someone assuming NULL represents a default value, but it's coerced to the integer 0), but as I noted in my previous email, I cannot find anyone doing this, and after re-checking my lists and having a re-look though the manual, I think it's the only one that benefits from the rejection of NULL coercion. Taking that as my rough position on type coercion, I don't see a *benefit* from blocking NULL coercion (more below). Whereas, blocking NULL coercion does introduce an upgrade *cost* (not made easier due to the lack of tooling); and the continuing cost to some developers using the noted frameworks or `filter_input()` (e.g. always specifying an empty string default, or always manually casting NULL to a string)... the other cost is the weirdness in how NULL coercion still works for echo()/print(), string concatenation, == comparisons, arithmetics, sprintf, etc. >> I'm going on the basis that you're ok with numbers in strings being coerced >> to integers/floats (which I also see as being useful, because you're right, >> most inputs are strings)... but you're not ok with NULL being coerced (which >> is also common, because values aren't guaranteed to be provided by the user, >> and NULL is typically the default). > > > I will reply to this point, though, because I think it's a genuinely > interesting thing to ponder. > > One significant difference is that not only is it often not *useful* to > distinguish an input of 123 from '123', it's often not *possible*. There is > literally no way for an HTTP URL or header to contain an integer, rather than > a string representation of one, because it's not a binary protocol. > > On the other hand, you might well receive an empty string as input where > you're expecting an integer. Notably, that is *not* coerced automatically to > zero; the code has to explicitly decide if that should trigger distinct > behaviour (such as a validation error) or be treated as a default value. Not > receiving a field you expected feels very similar, so similar behaviour feels > reasonable. I'm someone who will try to justify some very strict coding styles - like no inline JavaScript, use of Trusted Types, the use of literal-string for SQL/HTML/etc, and in some cases the use of application/xhtml+xml (these have easily provable benefits, but they can also be tricky, so few developers use them). With your example, I'm probably fine with an Empty String or NULL not being coerced to int 0 (as in, I could see how it might represent a problem, although I wouldn't care if it did get coerced to 0). But a lot of existing PHP code simply takes user input (which can be NULL), and passes it to these functions with no expectation of a fatal error (not good if it's in mid-way though processing data). If we were talking about a desktop application, where the UI was defined and displayed by that application, then a missing field would represent a problem in that application, but we're typically talking about the web with PHP, where the data often comes from an un-trusted browser... i.e. the user/browser/extension/network can be doing something odd, all the way down to how a standard HTML checkbox works (unchecked does not provide a field). It's because of these oddities, and the way NULL has historically worked, many developers simply don't see the difference between an empty or missing field (like other sources of NULL). That's why I don't see any benefit to blocking NULL coercion in this context, as an Empty String or NULL are often seen as the same - e.g. a programmer is simply checking if a name was provided, checking an email address contains the '@' character, checking if a message is too long, trimming the whitespace from a value, getting a record with an id/slug/name/ref, adding the value to a url, showing the search term, etc. Craig -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php