Introducing the MustUseResult attribute

October 5th 2025 software design static analysis open source


Code showing the MustUseResult attribute usage

The #[MustUseResult] attribute prevents subtle bugs however, due to a recent RFC I'd recommend another approach going forward.

Adding #[MustUseResult] (from the PHP language extensions library) to a function or method means that the result must be used by the calling code.

Consider a Money class like this:

final class Money {

  public function __construct(public readonly int $cents)
  {}

  #[MustUseResult]
  public function add(int $cents): self
  {
     return new self($cents + $this->cents);
  }
}

Note that the add method returns a new instance of Money, rather than updating the existing object.

On the face of it, the code below looks correct. However, the $money::cents property is not updated by calling the add method. Instead add returns a new instance of the Money object, this new object has the cents property set to 30.

$money = new Money(10);
$money->add(20); // This has no effect
echo $money->cents; // Value is 10 

Due to the #[MustUseResult] attribute, the code above would have an error on the $money->add(20); line:

Result returned by method must be used

The correct way of using the add method is:

$money = new Money(10);
$updated = $money->add(20);
echo $updated->cents; // Value is 30 

The#[MustUseResult] attribute helps developers use the code correctly.

Consider #[NoDiscard] instead

Since creating #[MustUseResult] PHP has introduced, from version 8.5, the #[NoDiscard] attribute. (RFC).

#[NoDiscard] and #[MustUseResult] do pretty much the same thing. A benefit of #[NoDiscard] is errors also are reported running the code and not just by static analysis.

Even if you are running PHP under 8.5, PHPStan still understands #[NoDiscard] and will report errors.

Using either #[NoDiscard] or #[MustUseResult] is a powerful way to document (to both developers and tools) the intention of how a method should be used, thus preventing bugs.


Other articles in this series

  1. Introducing the PHP Language Extensions Library
  2. Introducing the Friend attribute (example 1)
  3. Introducing the MustUseResult attribute
  4. Introducing the NamespaceVisibility attribute
  5. Introducing the TestTag attribute
  6. Introducing the RestrictTraitTo attribute
  7. Introducing the InjectableVersion attribute
  8. A static analysis first approach to RFCs