Re: NULL Coercion Consistency

From: Date: Thu, 05 May 2022 15:29:56 +0000
Subject: Re: NULL Coercion Consistency
References: 1 2 3 4 5 6 7 8 9 10 11 12  Groups: php.internals 
Request: Send a blank email to internals+get-117672@lists.php.net to get a copy of this message
On 3 May 2022, at 14:55, Rowan Tommins <rowan.collins@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

« previous php.internals (#117672) next »