github vimeo/psalm 7.3.1

one hour ago

What's Changed

Fixes

  • Narrow arrays of the same keys that are identical to an array of overlapping item types by @jirkace in #12707
  • fix(memoization): keep a memoized call narrowed in the initialization pass by @jirkace in #13120
  • Keep a mixed variable mixed after a ternary that narrows it by @jirkace in #12725
  • Fix: @method of a used trait or parent class overriding a declared method by @alies-dev in #13546
  • Fix parser caching for project paths containing vendor by @MohannadElemary in #13491
  • fix(types): isset narrows optional properties of object shapes by @jirkace in #13409
  • fix(static-properties): forget a static property after a call to a method that assigns it #10705 by @jirkace in #13262
  • fix(conditional): a value is never of the type never in a conditional return type by @jirkace in #13433
  • Don't let the conditions of the caller reach a method analysed inline by @jirkace in #12732
  • fix(docblock): reject the removed self-accessing/self-mutating callables with params by @jirkace in #12776
  • fix(types): '0' is a non-empty-lowercase-string by @jirkace in #12832
  • fix(templates): keep the key of a list when its template types are replaced by @jirkace in #12837
  • fix(array_pop): an optional last item of a list may leave the previous one popped by @jirkace in #12825
  • fix(alter): replace a whole union return type by @jirkace in #12876
  • Name the element of psalm.xml a config path error comes from by @jirkace in #12616
  • fix(types): validate refined stringable arguments by @1cbyc in #13472
  • fix(functions): bind the template of a conditional return type whatever the casing of the call by @jirkace in #12656
  • Report an int range offset that partly fits the keys of an array as possibly invalid by @jirkace in #12710
  • fix(shapes): keep an optional key of an unsealed shape through isset and the join of branches by @jirkace in #12646
  • Resolve self of a trait method's return type to the class using the trait (#4047) by @jirkace in #12742
  • fix(calls): name the callable in TooFewArguments and TooManyArguments by @jirkace in #12637
  • fix(callable): parse and print by-reference parameters of callable types by @jirkace in #13290
  • fix(and): a variable assigned in the right operand of && may keep its earlier type by @jirkace in #13361
  • fix(closures): the self of a closure parameter called in a trait is the using class by @jirkace in #13301
  • ctype checks of an expression of the implied type are not redundant (#12431) by @jirkace in #12748
  • fix(psalter): don't remove the others when fixing an unused property by @jirkace in #12840
  • fix(stubs): exec() output is list for an empty array by @jirkace in #12844
  • fix(types): cases() on a bare enum-string is a call on UnitEnum by @jirkace in #12908
  • feat(array_intersect_key): limit the result keys to the keys of sealed shapes by @jirkace in #12774
  • fix(types): expand the type of an @Property when narrowing it by @jirkace in #12931
  • fix(algebra): equal in-array clauses of different arrays are not a repetition by @jirkace in #12891
  • fix(loops): no stale narrowing of properties in do-while conditions by @jirkace in #12863
  • fix(callable): a first-class callable of a method keeps the return type it inherits by @jirkace in #13108
  • fix(purity): signal the implicit __toString call of an argument whatever the analysis mode by @jirkace in #13105
  • feat(type-alias): report an imported type alias named like an existing class by @jirkace in #13109
  • fix(unused): count the value of a pre-increment used as an array key by @jirkace in #13168
  • fix(docblock): the docblock before a use statement still declares the variables of the file by @jirkace in #13076
  • fix(callable): do not accept a callable that requires an optional parameter by @jirkace in #13128
  • fix(reconciler): remove null from the bound of a template on isset by @jirkace in #12954
  • fix(types): combine the types left by negating is_string/is_array by @jirkace in #12890
  • Infer array_filter() of an array or mixed like array_filter() of mixed by @jirkace in #12731
  • fix(classes): analyse an anonymous class only once at a time by @jirkace in #13115
  • fix(assert): assert an object shape on a plain object by @jirkace in #13217
  • fix(scanner): give a constant defined in several branches the union of its values by @jirkace in #13222
  • fix(docblock): accept a @psalm-check-type spanning several docblock lines by @jirkace in #13227
  • fix(reconciler): narrow with an instanceof result stored in a variable by @jirkace in #13221
  • Fix taint lost on method calls whose return type a plugin provides by @alies-dev in #13552
  • Fix conditional return type treating a __toString object as a string by @alies-dev in #13559
  • test(stubs): check stub function parameters against the call map by @jirkace in #12632
  • Report array_unique() of objects that can't be converted to strings by @jirkace in #12628
  • test(loop): an if that breaks keeps what its condition assigns (#10727) by @jirkace in #13324
  • fix(types): a class with pseudo properties satisfies an object shape by @jirkace in #12977
  • fix(stubs): the stubs generator leaves out the type of a scalar by @jirkace in #13190
  • fix(assertions): accept an object shape as the argument of an assertion about one of its properties #11386 by @jirkace in #13278
  • fix(constants): narrow static::CONSTANT separately from self::CONSTANT #10058 by @jirkace in #13282
  • fix(properties): @psalm-suppress in the docblock of a promoted property applies to the property by @jirkace in #13371
  • fix(interfaces): isset() of a property of an interface is not an interface property access by @jirkace in #13368
  • fix(reconciler): an assertion with alternatives is impossible only when all of them are by @jirkace in #13367
  • Remove an enum from the type where it is not instanceof itself by @jirkace in #13327
  • feat(config): add assumeGettersMutationFree to stop taking unannotated getters as mutation-free by @jirkace in #13351
  • fix(global): do not report InvalidGlobal in a file that documents its $this #9773 by @jirkace in #13285
  • fix(properties): $this is static in the pass that collects what a constructor initializes by @jirkace in #13373
  • fix(config): MutableDependency and ImmutableDependency are class issues, suppressible per referenced class by @jirkace in #13380
  • fix(is_a): keep the template of a class-string narrowed by is_a/is_subclass_of by @jirkace in #13393
  • docs(InvalidGlobal): say what global does in the global scope and show the allowed use by @jirkace in #13405
  • fix(match): a match with more arms than the maximum shaped array size can be exhaustive by @jirkace in #13382
  • fix(closure): a closure returned from a closure takes its types from that closure by @jirkace in #13398
  • fix(templates): class template bound by the receiver keeps invariance for method params by @jirkace in #13428
  • fix(config): include ParseError in the list of issue types by @jirkace in #13419
  • The true branch of a conditional type bounds the template by its condition (#11867) by @jirkace in #12769
  • Narrow the receiver of a nullsafe property compared to null by @jirkace in #13314
  • fix(constants): a negated defined() check no longer switches the undefined constant check off by @jirkace in #13096
  • fix(config): only the CLI entry points read the arguments of the process by @jirkace in #12815
  • fix(arguments): a parameter another unpacked array names is not mixed by @jirkace in #12849
  • fix(reconciler): do not re-report keys nested in an assigned variable in a conjunction by @jirkace in #13119
  • fix(types): combining numeric-string with the empty string twice must not widen to string by @jirkace in #12903
  • fix(array-functions): array_pop and array_shift adjust an array element too by @jirkace in #13111
  • fix(switch): report a case of switch(true) that cannot match by @jirkace in #12926
  • fix(mixed): do not report MixedAssignment of a variable narrowed by an elseif condition by @jirkace in #13174
  • DateTimeImmutable::createFromFormat() honours ignoreInternalFunctionFalseReturn by @jirkace in #12620
  • fix(array_map): a variadic callback or one using func_get_args() takes any number of arrays by @jirkace in #13370
  • Fix: Stub generation for union types that result to scalar could not be converted to identifier by @Mirco91 in #11852
  • Fix taint lost into an override's parameter through a call of the parent's variadic by @alies-dev in #13556
  • Fix conditional on a class matching a string-bounded class template by @alies-dev in #13561
  • Keep string|int|float|bool unions in generated stubs (backport) by @alies-dev in #13565
  • fix(alter): keep an assignment whose value is stored into an array element by @jirkace in #13420
  • fix(templates): a type predicate on a template bounded by another template looks through its bound by @jirkace in #13299
  • fix(templates): a template nested in a generic param is inferred, not compared invariantly by @jirkace in #13431
  • test(template): pin a conditional return making a template array non-empty by @jirkace in #13342
  • fix(types): read the escape sequences of a string literal in a docblock type as PHP does by @jirkace in #13402
  • fix(include): an included file can't change the type of $this by @jirkace in #13423
  • fix(closures): a narrowed property of an immutable object is known in an arrow function by @jirkace in #13381
  • fix(types): keep truthiness when narrowing non-empty-mixed by @jirkace in #12843
  • Type get_object_vars() with array-key keys by @jirkace in #12627
  • Leave out stub signature types with a scalar PHP can't spell by @alies-dev in #13570
  • Report a misplaced variable in a promoted property docblock as an issue, not a crash (backport) by @alies-dev in #13571
  • Fix crash on a property assertion about a non-variable argument (backport) by @alies-dev in #13572
  • Report a TypeParseTreeException in a @mixin / @psalm-require-* type as an issue, not a crash (backport) by @alies-dev in #13573
  • Accept a name after the = or ... of a callable param (backport) by @alies-dev in #13574
  • Fix crash on first-class callables in count()/gettype()/get_class() conditions (backport) by @alies-dev in #13575
  • Fix cache reads crashing while another worker rewrites the entry (backport) by @alies-dev in #13576
  • Fix warm-cache crash when a file is reached under two spellings of its path (backport) by @alies-dev in #13577
  • Fix crash when a class is named only in a template's bound (backport) by @alies-dev in #13579
  • Don't crash on a constant dividing by a zero constant of another class (backport) by @alies-dev in #13580
  • Don't fold a shift by a negative number or zero to a negative power (backport) by @alies-dev in #13582
  • Don't overflow the int range bound in a comparison with PHP_INT_MAX or PHP_INT_MIN (backport) by @alies-dev in #13583
  • Fix crash when scope summaries contain non-UTF-8 strings (backport) by @alies-dev in #13585
  • Fix crash on array_multisort() flags when Psalm runs on PHP 8.6 (backport) by @alies-dev in #13586
  • Don't crash psalter on properties declared together (backport) by @alies-dev in #13587
  • feat(docblock): choose between the @method overloads of a magic method by the arguments by @jirkace in #13352
  • Give array_reduce() callbacks the type of the array elements by @jirkace in #12610
  • fix(inheritance): an override is compared with the docblock a method inherits from its interface by @jirkace in #13446
  • fix(args): an unpacked argument passes only the parameters it has values for by @jirkace in #12671
  • Narrow the variable of a ??= condition (#11158) by @jirkace in #12743
  • fix(traits): a trait method without docblock inherits the docblock of the parent method by @jirkace in #13440
  • fix(if-else): know the variables assigned in an || condition in the else branch and ternary else by @jirkace in #12665
  • refactor(assertions): handle an asserted argument's property and the rules' class constants in one place by @jirkace in #13510
  • fix(type-parser): keep an optional shape key named like a scalar alias, self or parent by @jirkace in #12682
  • fix(types): an interpolated string with a non-falsy part is non-falsy by @jirkace in #12869
  • feat(array_merge_recursive): keep the shape of arrays that share no key by @jirkace in #13399
  • Accept a name before the = of a callable param (backport) by @alies-dev in #13578
  • fix(unused): don't report a @phpstan-var as an unnecessary @var annotation by @jirkace in #13092
  • Fix crash of multi-threaded runs without posix (backport) by @alies-dev in #13581
  • Fix crashes on NAN, INF and out-of-range float literals on PHP 8.5+ (backport) by @alies-dev in #13584
  • Accept memcached as a supported extension, as config.xsd and the stub say (backport) by @alies-dev in #13588
  • fix(unused-code): a dynamic class constant name on an expression is used by @jirkace in #12880
  • fix(arrays): assigning to the item of an array a function returns by reference has an effect by @jirkace in #13195
  • fix(types): resolve type variables read by foreach, destructuring and clone by @jirkace in #12861
  • fix(analysis): an undefined static property given to an unknown callee is reported by @jirkace in #12929
  • fix(unused-code): params of a method are used when the variables cannot be checked by @jirkace in #12780
  • fix(constants): a final constant fetched on an instance has its declared type by @jirkace in #12688
  • fix(constants): expand the declared type of a class constant before checking its value by @jirkace in #12649
  • fix(templates): map an object's extended params through the inheritance chain by @jirkace in #12777
  • Don't report arithmetic on a template bounded by int|float as mixed by @jirkace in #12606
  • fix(enum): use the value of an annotated constant as an enum case value by @jirkace in #13171
  • Don't report a shebang line as unevaluated after a namespaced exit or return by @jirkace in #12695
  • fix(docblocks): analyse the docblock of a use statement #6065 by @jirkace in #13279
  • [6.x] Fix: crash on count()/gettype()/get_class() conditions with php-parser < 5.9 by @alies-dev in #13594
  • [6.x] Infer the offsetGet type when destructuring a non-Traversable ArrayAccess by @alies-dev in #13595
  • fix(do-while): do not report NoValue for code only impossible in the first iteration by @jirkace in #12679
  • fix(language-server): omit unset optional fields instead of sending null by @jirkace in #12811
  • fix(try): the variables of every catch count when the try always exits by @jirkace in #12916
  • Count a variable referenced by a property or array item as used by @jirkace in #12693
  • fix(array_map): keep the list/keys of an array arg whose type is a template by @jirkace in #13430
  • fix(template): a literal returned where a template variable is identical to it is a T by @jirkace in #13294
  • fix(filter_var): accept both values of FILTER_FLAG_GLOBAL_RANGE by @jirkace in #12784
  • fix(return-types): expand the implementer's docblock return type like the inherited one by @jirkace in #12779
  • Expand the signature of a method's closure like a function's (#12388) by @jirkace in #12758
  • Don't fold arithmetic on array items and properties in loops like literals (#7250) by @jirkace in #12770
  • Keep a file_exists guard of an include across && and for constants by @jirkace in #13322
  • fix(taint): don't loop on files requiring each other by @jirkace in #13415
  • fix(unused-code): a variable variable may read any variable of the scope by @jirkace in #12781
  • fix(taint): a nullsafe call on a property acts on the property itself by @jirkace in #12808
  • fix(types): accept an imported type alias in key-of and value-of by @jirkace in #12806
  • Infer a non-falsy string for implode() of a non-falsy piece or separator by @jirkace in #12596
  • fix(interfaces): assigning a property of an interface that isset() found is not an interface property access by @jirkace in #13379
  • fix(control-flow): a loop that nothing leaves ends the function by @jirkace in #12846
  • An assertion on an item with a union key keeps the other items as they are (#11845) by @jirkace in #12765
  • fix(constants): don't keep the literal of a class constant read through self/static in a trait by @jirkace in #13223
  • fix(types): compare array shapes key by key when checking if they can be identical by @jirkace in #12654
  • Follow a method of a parent class or trait when checking what a constructor sets by @jirkace in #12619
  • fix(call): the templates of a method are bound by its arguments, not read as bindings of its class by @jirkace in #13447
  • Fix: infer templates from a generic array in a union with null or false by @alies-dev in #13598
  • fix(if): what is known of an offset of a variable a branch assigns is forgotten after the if by @jirkace in #13375
  • Fix: MethodSignatureMismatch repeated on every subclass for an inherited @method by @alies-dev in #13600

Internal changes

  • Show raw issue changes in the perf report headline by @alies-dev in #13567
  • Let the BC check accept the growing list of stubbed extensions (backport) by @alies-dev in #13590
  • Merge 6.x into master by @alies-dev in #13597
  • Perf: keep statements of inlined constructor callees with arrayCache on (-5 to -7 % CPU) by @alies-dev in #13589

Other changes

  • fix(closure): keep what a closure writes to a by-reference variable before it returns by @jirkace in #13177
  • fix(mixin): forward a static call to the mixin that has the method by @jirkace in #13202

New Contributors

Full Changelog: 7.3.0...7.3.1

Don't miss a new psalm release

NewReleases is sending notifications on new releases.