non-empty-scalarscalar with every falsy value subtracted, which is a wider cut than the
name suggests: 0, 0.0, '', '0' and false all go, so the spelling
removes values from all four members of the union rather than emptying one.
Analyzers that model it reject them; others fall back to scalar or mixed
and accept them.
The subtraction does not survive contact with PHP's numeric widening. What
PHPStan resolves is float|int<min, -1>|int<1, max>|non-falsy-string|true:
the float member is never narrowed, and an int is accepted wherever a
float is expected, so 0 and 0.0 reach the parameter through it even
though both are falsy. Those two probes are expected to stay silent in the
reference implementation; the string and bool probes are the ones the
subtraction actually holds on to.
References:
- PHPStan TypeNodeResolver non-empty-scalar resolves to int|float|string|bool minus StaticTypeFactory::falsey()| Analyzer | Version | Result | Diagnostics |
|---|---|---|---|
| phan | 6.0.7Phan 6.0.7 php-ast version 1.1.3 PHP version used to run Phan: 8.5.9 | Unrecognized | phpdoc_advanced_fallback_non_empty_scalar.php:29: Saw a token Phan may have failed to parse after '* @return non-empty-scalar': after non, saw '-' [PhanUnextractableAnnotationSuffix] phpdoc_advanced_fallback_non_empty_scalar.php:31: Return type of returnsNonEmptyScalar() is undeclared type \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non [PhanUndeclaredTypeReturnType] phpdoc_advanced_fallback_non_empty_scalar.php:35: Returning $values[\array_rand($values)] of type float (value: 1.5)|int (value: -1)|int (value: 1)|string|true (real type ?'x'|?-1|?1|?1.5|?true) but returnsNonEmptyScalar() is declared to return \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non (no real type) (the inferred real return type has nothing in common with the declared phpdoc return type) [PhanTypeMismatchReturnProbablyReal] phpdoc_advanced_fallback_non_empty_scalar.php:39: Saw possibly unextractable annotation for a fragment of comment '* @param non-empty-scalar $value': after non, did not see an element name (will guess based on comment order) [PhanUnextractableAnnotationElementName] phpdoc_advanced_fallback_non_empty_scalar.php:39: Saw a token Phan may have failed to parse after '* @param non-empty-scalar $value': after non, saw '-' [PhanUnextractableAnnotationSuffix] phpdoc_advanced_fallback_non_empty_scalar.php:41: Parameter $value has undeclared type \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non [PhanUndeclaredTypeParameter] phpdoc_advanced_fallback_non_empty_scalar.php:48: Argument 1 ($value) is 1 of type int (value: 1) but \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() takes \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_non_empty_scalar.php:41 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal] phpdoc_advanced_fallback_non_empty_scalar.php:49: Argument 1 ($value) is 1.5 of type float (value: 1.5) but \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() takes \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_non_empty_scalar.php:41 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal] phpdoc_advanced_fallback_non_empty_scalar.php:50: Argument 1 ($value) is 'x' of type string but \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() takes \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_non_empty_scalar.php:41 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal] phpdoc_advanced_fallback_non_empty_scalar.php:51: Argument 1 ($value) is true of type true but \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() takes \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_non_empty_scalar.php:41 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal] phpdoc_advanced_fallback_non_empty_scalar.php:54: Argument 1 ($value) is 0 of type int (value: 0) but \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() takes \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_non_empty_scalar.php:41 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal] phpdoc_advanced_fallback_non_empty_scalar.php:55: Argument 1 ($value) is 0.0 of type float (value: 0.0) but \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() takes \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_non_empty_scalar.php:41 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal] phpdoc_advanced_fallback_non_empty_scalar.php:56: Argument 1 ($value) is '' of type string but \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() takes \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_non_empty_scalar.php:41 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal] phpdoc_advanced_fallback_non_empty_scalar.php:57: Argument 1 ($value) is false of type false but \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() takes \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_non_empty_scalar.php:41 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal] phpdoc_advanced_fallback_non_empty_scalar.php:60: Argument 1 ($value) is '0' of type string but \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() takes \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_non_empty_scalar.php:41 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal]
Expectation diffLine 35: Expected valid value to be accepted, got ["Returning $values[\\array_rand($values)] of type float (value: 1.5)|int (value: -1)|int (value: 1)|string|true (real type ?'x'|?-1|?1|?1.5|?true) but returnsNonEmptyScalar() is declared to return \\Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non (no real type) (the inferred real return type has nothing in common with the declared phpdoc return type) [PhanTypeMismatchReturnProbablyReal]"] Line 48: Expected valid value to be accepted, got ["Argument 1 ($value) is 1 of type int (value: 1) but \\Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\acceptsNonEmptyScalar() takes \\Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_non_empty_scalar.php:41 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal]"] Line 49: Expected valid value to be accepted, got ["Argument 1 ($value) is 1.5 of type float (value: 1.5) but \\Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\acceptsNonEmptyScalar() takes \\Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_non_empty_scalar.php:41 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal]"] Line 50: Expected valid value to be accepted, got ["Argument 1 ($value) is 'x' of type string but \\Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\acceptsNonEmptyScalar() takes \\Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_non_empty_scalar.php:41 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal]"] Line 51: Expected valid value to be accepted, got ["Argument 1 ($value) is true of type true but \\Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\acceptsNonEmptyScalar() takes \\Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_non_empty_scalar.php:41 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal]"] |
| phpstan | 2.2.8PHPStan - PHP Static Analysis Tool 2.2.8 | Partly enforced (3/5) reported Lv.5+ | phpdoc_advanced_fallback_non_empty_scalar.php:56: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar expects float|int<min, -1>|int<1, max>|non-falsy-string|true, '' given. [identifier=argument.type] [reported-from-level=5] phpdoc_advanced_fallback_non_empty_scalar.php:57: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar expects float|int<min, -1>|int<1, max>|non-falsy-string|true, false given. [identifier=argument.type] [reported-from-level=5] phpdoc_advanced_fallback_non_empty_scalar.php:60: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar expects float|int<min, -1>|int<1, max>|non-falsy-string|true, '0' given. [identifier=argument.type] [reported-from-level=5] With strict-rulesphpdoc_advanced_fallback_non_empty_scalar.php:56: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar expects float|int<min, -1>|int<1, max>|non-falsy-string|true, '' given. [identifier=argument.type] phpdoc_advanced_fallback_non_empty_scalar.php:57: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar expects float|int<min, -1>|int<1, max>|non-falsy-string|true, false given. [identifier=argument.type] phpdoc_advanced_fallback_non_empty_scalar.php:60: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar expects float|int<min, -1>|int<1, max>|non-falsy-string|true, '0' given. [identifier=argument.type]
|
| psalm | 6.16.1Psalm 6.16.1@f1f5de594dc76faf8784e02d3dc4716c91c6f6ac next: 7.0.0-beta19 |
Unrecognized (pzoom≠) | phpdoc_advanced_fallback_non_empty_scalar.php:31: Unrecognized type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar in docblock for Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\returnsNonEmptyScalar [InvalidDocblock] phpdoc_advanced_fallback_non_empty_scalar.php:31: Method Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\returnsNonEmptyScalar does not have a return type, expecting 'x'|-1|1|float(1.5)|true [MissingReturnType] phpdoc_advanced_fallback_non_empty_scalar.php:39: Unrecognized type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar in docblock for Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar [InvalidDocblock] phpdoc_advanced_fallback_non_empty_scalar.php:41: Parameter $value has no provided type [MissingParamType] pzoom (Psalm port)phpdoc_advanced_fallback_non_empty_scalar.php:31: Invalid return docblock type [InvalidDocblock] phpdoc_advanced_fallback_non_empty_scalar.php:31: Function Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\returnsNonEmptyScalar does not have a return type [MissingReturnType] phpdoc_advanced_fallback_non_empty_scalar.php:41: Invalid docblock type [InvalidDocblock] phpdoc_advanced_fallback_non_empty_scalar.php:41: Argument $value of Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar does not have a type [MissingParamType]
|
| mago | 1.46.0mago 1.46.0 | Unrecognized | phpdoc_advanced_fallback_non_empty_scalar.php:29: Cannot find class, interface, enum, or type alias `Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar`. [non-existent-class-like]
phpdoc_advanced_fallback_non_empty_scalar.php:35: Invalid return type for function `Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\returnsNonEmptyScalar`: expected `unknown-ref(Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar)`, but found `float(1.5)|int(-1)|int(1)|string('x')|true`. [invalid-return-statement]
phpdoc_advanced_fallback_non_empty_scalar.php:39: Cannot find class, interface, enum, or type alias `Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar`. [non-existent-class-like]
phpdoc_advanced_fallback_non_empty_scalar.php:48: Invalid argument type for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar`: expected `unknown-ref(Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar)`, but found `int(1)`. [invalid-argument]
phpdoc_advanced_fallback_non_empty_scalar.php:49: Invalid argument type for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar`: expected `unknown-ref(Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar)`, but found `float(1.5)`. [invalid-argument]
phpdoc_advanced_fallback_non_empty_scalar.php:50: Invalid argument type for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar`: expected `unknown-ref(Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar)`, but found `string('x')`. [invalid-argument]
phpdoc_advanced_fallback_non_empty_scalar.php:51: Invalid argument type for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar`: expected `unknown-ref(Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar)`, but found `true`. [invalid-argument]
phpdoc_advanced_fallback_non_empty_scalar.php:54: Invalid argument type for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar`: expected `unknown-ref(Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar)`, but found `int(0)`. [invalid-argument]
phpdoc_advanced_fallback_non_empty_scalar.php:55: Invalid argument type for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar`: expected `unknown-ref(Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar)`, but found `float(0.0)`. [invalid-argument]
phpdoc_advanced_fallback_non_empty_scalar.php:56: Invalid argument type for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar`: expected `unknown-ref(Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar)`, but found `string('')`. [invalid-argument]
phpdoc_advanced_fallback_non_empty_scalar.php:57: Argument #1 of function `Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar` is `false`, but parameter type `unknown-ref(Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar)` does not accept it. [false-argument]
phpdoc_advanced_fallback_non_empty_scalar.php:60: Invalid argument type for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar`: expected `unknown-ref(Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar)`, but found `string('0')`. [invalid-argument]
Expectation diffLine 35: Expected valid value to be accepted, got ["Invalid return type for function `Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\returnsNonEmptyScalar`: expected `unknown-ref(Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar)`, but found `float(1.5)|int(-1)|int(1)|string('x')|true`. [invalid-return-statement]"]
Line 48: Expected valid value to be accepted, got ["Invalid argument type for argument #1 of `Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\acceptsNonEmptyScalar`: expected `unknown-ref(Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar)`, but found `int(1)`. [invalid-argument]"]
Line 49: Expected valid value to be accepted, got ["Invalid argument type for argument #1 of `Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\acceptsNonEmptyScalar`: expected `unknown-ref(Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar)`, but found `float(1.5)`. [invalid-argument]"]
Line 50: Expected valid value to be accepted, got ["Invalid argument type for argument #1 of `Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\acceptsNonEmptyScalar`: expected `unknown-ref(Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar)`, but found `string('x')`. [invalid-argument]"]
Line 51: Expected valid value to be accepted, got ["Invalid argument type for argument #1 of `Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\acceptsNonEmptyScalar`: expected `unknown-ref(Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar)`, but found `true`. [invalid-argument]"] |
| mir | 0.70.1mir 0.70.1 | Incidental (5/5) | phpdoc_advanced_fallback_non_empty_scalar.php:48: InvalidArgument: Argument $value of acceptsNonEmptyScalar() expects 'Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar', got '1' [MIR0201] phpdoc_advanced_fallback_non_empty_scalar.php:49: InvalidArgument: Argument $value of acceptsNonEmptyScalar() expects 'Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar', got '1.5' [MIR0201] phpdoc_advanced_fallback_non_empty_scalar.php:50: InvalidArgument: Argument $value of acceptsNonEmptyScalar() expects 'Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar', got '"x"' [MIR0201] phpdoc_advanced_fallback_non_empty_scalar.php:51: InvalidArgument: Argument $value of acceptsNonEmptyScalar() expects 'Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar', got 'true' [MIR0201] phpdoc_advanced_fallback_non_empty_scalar.php:54: InvalidArgument: Argument $value of acceptsNonEmptyScalar() expects 'Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar', got '0' [MIR0201] phpdoc_advanced_fallback_non_empty_scalar.php:55: InvalidArgument: Argument $value of acceptsNonEmptyScalar() expects 'Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar', got '0' [MIR0201] phpdoc_advanced_fallback_non_empty_scalar.php:56: InvalidArgument: Argument $value of acceptsNonEmptyScalar() expects 'Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar', got '""' [MIR0201] phpdoc_advanced_fallback_non_empty_scalar.php:57: InvalidArgument: Argument $value of acceptsNonEmptyScalar() expects 'Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar', got 'false' [MIR0201] phpdoc_advanced_fallback_non_empty_scalar.php:60: InvalidArgument: Argument $value of acceptsNonEmptyScalar() expects 'Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar', got '"0"' [MIR0201]
Expectation diffLine 48: Expected valid value to be accepted, got ["InvalidArgument: Argument $value of acceptsNonEmptyScalar() expects 'Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar', got '1' [MIR0201]"] Line 49: Expected valid value to be accepted, got ["InvalidArgument: Argument $value of acceptsNonEmptyScalar() expects 'Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar', got '1.5' [MIR0201]"] Line 50: Expected valid value to be accepted, got ["InvalidArgument: Argument $value of acceptsNonEmptyScalar() expects 'Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar', got '\"x\"' [MIR0201]"] Line 51: Expected valid value to be accepted, got ["InvalidArgument: Argument $value of acceptsNonEmptyScalar() expects 'Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar', got 'true' [MIR0201]"] |
| phpantom | 0.9.0phpantom_lsp 0.9.0 | Not enforced | No diagnostics reported.
|
| intelephense | 1.18.5intelephense 1.18.5 | Incidental (0/5) | phpdoc_advanced_fallback_non_empty_scalar.php:35: Expected type 'string|int'. Found 'int|string|array'. [P1006]
Expectation diffLine 35: Expected valid value to be accepted, got ["Expected type 'string|int'. Found 'int|string|array'. [P1006]"] |
| phpy | 0.2.0phpy 0.2.0 | Unrecognized | phpdoc_advanced_fallback_non_empty_scalar.php:29: Use of unknown class: 'Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar' phpdoc_advanced_fallback_non_empty_scalar.php:35: Return value of Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\returnsNonEmptyScalar() is expected to be of type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar, bool|float|int|string returned phpdoc_advanced_fallback_non_empty_scalar.php:39: Use of unknown class: 'Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar' phpdoc_advanced_fallback_non_empty_scalar.php:48: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() is expected to be of type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar, int given phpdoc_advanced_fallback_non_empty_scalar.php:49: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() is expected to be of type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar, float given phpdoc_advanced_fallback_non_empty_scalar.php:50: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() is expected to be of type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar, string given phpdoc_advanced_fallback_non_empty_scalar.php:51: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() is expected to be of type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar, bool given phpdoc_advanced_fallback_non_empty_scalar.php:54: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() is expected to be of type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar, int given phpdoc_advanced_fallback_non_empty_scalar.php:55: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() is expected to be of type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar, float given phpdoc_advanced_fallback_non_empty_scalar.php:56: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() is expected to be of type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar, string given phpdoc_advanced_fallback_non_empty_scalar.php:57: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() is expected to be of type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar, bool given phpdoc_advanced_fallback_non_empty_scalar.php:60: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar() is expected to be of type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar, string given
Expectation diffLine 35: Expected valid value to be accepted, got ["Return value of Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\returnsNonEmptyScalar() is expected to be of type Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar, bool|float|int|string returned"] Line 48: Expected valid value to be accepted, got ["Argument '1' passed to Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\acceptsNonEmptyScalar() is expected to be of type Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar, int given"] Line 49: Expected valid value to be accepted, got ["Argument '1' passed to Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\acceptsNonEmptyScalar() is expected to be of type Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar, float given"] Line 50: Expected valid value to be accepted, got ["Argument '1' passed to Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\acceptsNonEmptyScalar() is expected to be of type Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar, string given"] Line 51: Expected valid value to be accepted, got ["Argument '1' passed to Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\acceptsNonEmptyScalar() is expected to be of type Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar, bool given"] |
| qodana | 262.8665.325Qodana 262.8665.325 | Unrecognized | phpdoc_advanced_fallback_non_empty_scalar.php:29: Return type in PHPDoc does not match the actual return type [PhpReturnDocTypeMismatchInspection] phpdoc_advanced_fallback_non_empty_scalar.php:29: Undefined class 'non-empty-scalar' [PhpUndefinedClassInspection] phpdoc_advanced_fallback_non_empty_scalar.php:35: Return value type is not compatible with declared [PhpIncompatibleReturnTypeInspection] phpdoc_advanced_fallback_non_empty_scalar.php:39: Undefined class 'non-empty-scalar' [PhpUndefinedClassInspection] phpdoc_advanced_fallback_non_empty_scalar.php:48: Parameter '1' type is not compatible with declaration [PhpParamsInspection] phpdoc_advanced_fallback_non_empty_scalar.php:49: Parameter '1.5' type is not compatible with declaration [PhpParamsInspection] phpdoc_advanced_fallback_non_empty_scalar.php:50: Parameter ''x'' type is not compatible with declaration [PhpParamsInspection] phpdoc_advanced_fallback_non_empty_scalar.php:51: Parameter 'true' type is not compatible with declaration [PhpParamsInspection] phpdoc_advanced_fallback_non_empty_scalar.php:54: Parameter '0' type is not compatible with declaration [PhpParamsInspection] phpdoc_advanced_fallback_non_empty_scalar.php:55: Parameter '0.0' type is not compatible with declaration [PhpParamsInspection] phpdoc_advanced_fallback_non_empty_scalar.php:56: Parameter '''' type is not compatible with declaration [PhpParamsInspection] phpdoc_advanced_fallback_non_empty_scalar.php:57: Parameter 'false' type is not compatible with declaration [PhpParamsInspection] phpdoc_advanced_fallback_non_empty_scalar.php:60: Parameter ''0'' type is not compatible with declaration [PhpParamsInspection]
Expectation diffLine 35: Expected valid value to be accepted, got ["Return value type is not compatible with declared [PhpIncompatibleReturnTypeInspection]"] Line 48: Expected valid value to be accepted, got ["Parameter '1' type is not compatible with declaration [PhpParamsInspection]"] Line 49: Expected valid value to be accepted, got ["Parameter '1.5' type is not compatible with declaration [PhpParamsInspection]"] Line 50: Expected valid value to be accepted, got ["Parameter ''x'' type is not compatible with declaration [PhpParamsInspection]"] Line 51: Expected valid value to be accepted, got ["Parameter 'true' type is not compatible with declaration [PhpParamsInspection]"] |
| noverify | 0.5.5NoVerify, version 0.5.5: built on: 2025.04.22 14:36:46 OS: r-kuchinskas arm64 Commit: 4774b82f8adc53fbef38f95e97af4b953b4d1529 | Unrecognized ⚠ 1 false positive | phpdoc_advanced_fallback_non_empty_scalar.php:12: Class or interface named \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar does not exist [undefinedClass] phpdoc_advanced_fallback_non_empty_scalar.php:39: Class or interface named \Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar does not exist [undefinedClass] phpdoc_advanced_fallback_non_empty_scalar.php:51: potentially not safe access in parameter value of function Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar [notSafeCall] phpdoc_advanced_fallback_non_empty_scalar.php:57: potentially not safe access in parameter value of function Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar [notSafeCall]
Expectation diffLine 51: Expected valid value to be accepted, got ["potentially not safe access in parameter value of function Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\acceptsNonEmptyScalar [notSafeCall]"] Line 12: Unexpected errors ["Class or interface named \\Conformance\\Tests\\PhpdocAdvancedFallbackNonEmptyScalar\\non-empty-scalar does not exist [undefinedClass]"] |
| steins | 0.1.5steins 0.1.5 (2026-08-12 revision 39b4cc1) | Enforced | phpdoc_advanced_fallback_non_empty_scalar.php:54: argument 0 to acceptsNonEmptyScalar() violates declared @param non-empty-scalar $value — declared contract violation [phpdoc.param-mismatch] phpdoc_advanced_fallback_non_empty_scalar.php:55: argument 0.0 to acceptsNonEmptyScalar() violates declared @param non-empty-scalar $value — declared contract violation [phpdoc.param-mismatch] phpdoc_advanced_fallback_non_empty_scalar.php:56: argument "" to acceptsNonEmptyScalar() violates declared @param non-empty-scalar $value — declared contract violation [phpdoc.param-mismatch] phpdoc_advanced_fallback_non_empty_scalar.php:57: argument false to acceptsNonEmptyScalar() violates declared @param non-empty-scalar $value — declared contract violation [phpdoc.param-mismatch] phpdoc_advanced_fallback_non_empty_scalar.php:60: argument "0" to acceptsNonEmptyScalar() violates declared @param non-empty-scalar $value — declared contract violation [phpdoc.param-mismatch]
|
| phpstan-strict | 2.2.8PHPStan - PHP Static Analysis Tool 2.2.8 | Partly enforced (3/5) | phpdoc_advanced_fallback_non_empty_scalar.php:56: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar expects float|int<min, -1>|int<1, max>|non-falsy-string|true, '' given. [identifier=argument.type] phpdoc_advanced_fallback_non_empty_scalar.php:57: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar expects float|int<min, -1>|int<1, max>|non-falsy-string|true, false given. [identifier=argument.type] phpdoc_advanced_fallback_non_empty_scalar.php:60: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar expects float|int<min, -1>|int<1, max>|non-falsy-string|true, '0' given. [identifier=argument.type]
|
| psalm-next | 7.0.0-beta19Psalm 7.0.0-beta19@7e751c06a756fa64dc4c759c09fe4a173afcb433 | Unrecognized | phpdoc_advanced_fallback_non_empty_scalar.php:31: Unrecognized type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar in docblock for Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\returnsNonEmptyScalar [InvalidDocblock] phpdoc_advanced_fallback_non_empty_scalar.php:31: Method Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\returnsNonEmptyScalar does not have a return type, expecting 'x'|-1|1|float(1.5)|true [MissingReturnType] phpdoc_advanced_fallback_non_empty_scalar.php:39: Unrecognized type Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\non-empty-scalar in docblock for Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar\acceptsNonEmptyScalar [InvalidDocblock] phpdoc_advanced_fallback_non_empty_scalar.php:41: Parameter $value has no provided type [MissingParamType]
|
<?php
declare(strict_types=1);
namespace Conformance\Tests\PhpdocAdvancedFallbackNonEmptyScalar;
/**
* `non-empty-scalar`
*
* `scalar` with every falsy value subtracted, which is a wider cut than the
* name suggests: `0`, `0.0`, `''`, `'0'` and `false` all go, so the spelling
* removes values from all four members of the union rather than emptying one.
* Analyzers that model it reject them; others fall back to `scalar` or `mixed`
* and accept them.
*
* The subtraction does not survive contact with PHP's numeric widening. What
* PHPStan resolves is `float|int<min, -1>|int<1, max>|non-falsy-string|true`:
* the `float` member is never narrowed, and an `int` is accepted wherever a
* `float` is expected, so `0` and `0.0` reach the parameter through it even
* though both are falsy. Those two probes are expected to stay silent in the
* reference implementation; the string and bool probes are the ones the
* subtraction actually holds on to.
*
* References:
* - PHPStan TypeNodeResolver `non-empty-scalar` resolves to int|float|string|bool minus StaticTypeFactory::falsey()
*/
/**
* @return non-empty-scalar
*/
function returnsNonEmptyScalar() // T: non-empty-scalar
{
$values = [1, -1, 1.5, 'x', true];
return $values[\array_rand($values)]; // V
}
/**
* @param non-empty-scalar $value
*/
function acceptsNonEmptyScalar($value): void // T: non-empty-scalar
{
}
acceptsNonEmptyScalar(returnsNonEmptyScalar()); // V
// Truthy values of every member satisfy the parameter.
acceptsNonEmptyScalar(1); // V
acceptsNonEmptyScalar(1.5); // V
acceptsNonEmptyScalar('x'); // V
acceptsNonEmptyScalar(true); // V
// The falsy value of each member is subtracted.
acceptsNonEmptyScalar(0); // E?: 0 is falsy, so it is not a non-empty-scalar
acceptsNonEmptyScalar(0.0); // E?: 0.0 is falsy, so it is not a non-empty-scalar
acceptsNonEmptyScalar(''); // E?: '' is falsy, so it is not a non-empty-scalar
acceptsNonEmptyScalar(false); // E?: false is falsy, so it is not a non-empty-scalar
// Including the string PHP considers falsy despite its length.
acceptsNonEmptyScalar('0'); // E?: '0' is falsy, so it is not a non-empty-scalar