Add exceptional case for DateInterval::format return type inference#4442
Conversation
| // Could be lowercase-string&non-falsy-string&numeric-string&uppercase-string | ||
| assertType('lowercase-string&non-falsy-string', $dateInterval->format('%a')); | ||
| assertType( | ||
| "'(unknown)'&lowercase-string&non-empty-string&numeric-string&uppercase-string", |
There was a problem hiding this comment.
This is not ok.
I think you're expecting
'(unknown)'|lowercase-string&non-empty-string&numeric-string&uppercase-string
There was a problem hiding this comment.
Thanks for the review! I've pushed a change to fix this.
8740766 to
75008af
Compare
VincentLanglet
left a comment
There was a problem hiding this comment.
Thinking about it again, I think the approach is not correct cause you handle %a to add new ConstantStringType('(unknown)') but it could occur with eveyr other format containing %a.
| ]); | ||
| $possibleReturnTypes[] = $diffInDaysType === null | ||
| ? $intersectionType | ||
| : new UnionType([$diffInDaysType, $intersectionType]); |
There was a problem hiding this comment.
You don't have to add $diffInDayType in every string you could do
$possibleReturnTypes = [];
if ($formatString === '%a') {
$possibleReturnTypes[] = new ConstantStringType('(unknown)');
}
There was a problem hiding this comment.
If the pattern is not %a without any additional character, it won't only return (unknown) and so it would only be a lowercase-string&non-falsy-string.
There was a problem hiding this comment.
Yes, but it could be considered weird/unnecessary to have the (unknown)|foo precision for %a and not for foo %a
There was a problem hiding this comment.
The "weirdness" of it I'm gonna let you decide :) I'd say the more precise the better, but I'm okay if we don't go with this.
|
@adamturcsan Wouldn't be enough to just change into Then the dumped type will be lowercase-string&non-empty-string which seems correct. |
[UPDATED with second if] I'd argue a if (is_numeric($value))and if (strtoupper($value) === $value)into if (is_numeric($value) && $format !== '%a')and if (strtoupper($value) === $value && $formatString !== '%a')it becomes correct and results in |
Since I feel like you should keep the then it should just be
you'll need |
Difference in days might behave differently when the DateInterval is created from scratch or from a diff. Filter returned type information for DateInterval::format. It can only be non-falsy for sure if it's not '%a'.
75008af to
4b35722
Compare
|
Alright, this is much-much simpler so I really can get behind of not providing "too precise" results and it also still solves my own problem, so I pushed the relevant changes. Thanks so much for your collaboration! |
|
Thank you! |
Resolves phpstan/phpstan#13693
Difference in days might behave differently when the DateInterval is created from scratch or from a diff.
Extend returned type information for DateInterval::format method