Skip to content

Know that numeric-string and decimal-int-string are non-empty-string - #6959

Merged
ondrejmirtes merged 2 commits into
2.3.xfrom
numeric-string-non-empty
Nov 5, 2026
Merged

ondrejmirtes merged 2 commits into
2.3.xfrom
numeric-string-non-empty

Conversation

@ondrejmirtes

Copy link
Copy Markdown
Member

AccessoryNumericStringType::isSubTypeOf() and AccessoryDecimalIntegerStringType::isSubTypeOf() answered Maybe for AccessoryNonEmptyStringType, although '' is neither numeric nor a decimal integer. So:

  • non-empty-string|numeric-string stayed a union instead of non-empty-string,
  • non-empty-string&numeric-string kept the redundant non-empty-string,
  • decimal-int-string|(non-empty-string&uppercase-string) ((string) int|float) stayed a union.

The loose comparison narrowing from #6938 now produces such unions: $string == $nonEmptyString narrows $string to non-empty-string|numeric-string, which fails phpstan/phpstan-webmozart-assert's Assert::eq() test.

This mirrors AccessoryNonFalsyStringType, which already answers Yes for AccessoryNonEmptyStringType. The C++ mirrors in turbo-ext get the same change.

Updated expectations are the same sets, written without the redundant parts. mixed~non-empty-string is now not a numeric string (only '' and non-strings are left).

Found while probing, not fixed here

non-empty-string&non-decimal-int-string is a subtype of non-falsy-string ('0' is the only non-empty falsy string, and it is a decimal-int string), but isSuperTypeOf() answers Maybe because neither accessory alone implies non-falsy. The same goes for numeric-string&non-decimal-int-string. Fixing it needs IntersectionType to reason over its members together.

The new float range types came out clean: no subset or membership gaps across float, float<min, max>, finite-float, the signed float types, bounded ranges and the INF/-INF/NAN/zero constants.

AccessoryNumericStringType::isSubTypeOf() and
AccessoryDecimalIntegerStringType::isSubTypeOf() answered Maybe for
AccessoryNonEmptyStringType, although '' is neither numeric nor a decimal
integer. So non-empty-string|numeric-string stayed a union, and
non-empty-string&numeric-string kept the redundant non-empty-string.
Loose comparison narrowing now produces such unions, e.g.
$string == $nonEmptyString gave non-empty-string|numeric-string.

This mirrors AccessoryNonFalsyStringType, which already answers Yes for
AccessoryNonEmptyStringType.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1ad71-9d5a-7120-9844-bfb0954d122f
@ondrejmirtes
ondrejmirtes merged commit d8f0239 into 2.3.x Nov 5, 2026
543 of 544 checks passed
@ondrejmirtes
ondrejmirtes deleted the numeric-string-non-empty branch November 5, 2026 21:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant