Take the State of PHP 2026 Survey →

throw expression View as Markdown

Implemented (PHP 8.0)
Authors
Ilija Tovilo, tovilo.ilija@gmail.com
Date
2020-03-21
Target
PHP 8.0
Implementation
https://github.com/php/php-src/pull/5279
Source
wiki.php.net/rfc/throw_expression

Vote

Would you like to convert the throw statement into an expression? closed
Yes
46
No
3
49 voters
ajf No 2020-04-12 14:48
alcaeus Yes 2020-04-15 14:59
as Yes 2020-04-07 22:07
ashnazg Yes 2020-04-08 14:34
beberlei Yes 2020-04-05 13:12
brzuchal Yes 2020-04-06 05:54
bukka Yes 2020-04-05 19:52
bwoebi Yes 2020-04-09 10:46
carusogabriel Yes 2020-04-05 13:04
colinodell Yes 2020-04-14 11:10
danack No 2020-04-05 11:39
daverandom Yes 2020-04-07 22:08
derick Yes 2020-04-06 00:06
dragoonis Yes 2020-04-06 04:19
duncan3dc Yes 2020-04-06 12:55
duodraco Yes 2020-04-15 16:56
ekin Yes 2020-04-07 17:58
galvao Yes 2020-04-06 00:30
geekcom Yes 2020-04-13 14:12
jasny Yes 2020-04-09 10:41
jhdxr No 2020-04-15 16:56
kalle Yes 2020-04-05 10:29
kguest Yes 2020-04-07 09:39
krakjoe Yes 2020-04-15 06:55
lcobucci Yes 2020-04-07 08:47
levim Yes 2020-04-05 21:51
marandall Yes 2020-04-09 10:46
mariano Yes 2020-04-05 16:03
nicolasgrekas Yes 2020-04-07 16:17
nikic Yes 2020-04-05 12:38
ocramius Yes 2020-04-05 12:50
petk Yes 2020-04-07 05:23
pierrick Yes 2020-04-05 18:39
pmjones Yes 2020-04-06 17:03
pmmaga Yes 2020-04-08 14:36
ralphschindler Yes 2020-04-06 14:12
ramsey Yes 2020-04-13 20:14
rasmus Yes 2020-04-10 14:04
reywob Yes 2020-04-14 14:28
salathe Yes 2020-04-14 10:20
sammyk Yes 2020-04-18 18:32
sergey Yes 2020-04-09 13:00
stas Yes 2020-04-05 20:54
svpernova09 Yes 2020-04-14 12:59
tandre Yes 2020-04-11 17:08
thekid Yes 2020-04-05 14:53
wyrihaximus Yes 2020-04-07 14:21
yunosh Yes 2020-04-13 17:52
zimt Yes 2020-04-06 11:31

Discussions on the mailing list

Throw Question
by Jason Garber · 3 messages
Using `throw` with expr or expr logic
by Sara Golemon · 4 messages
"or throw new" syntax
by Kalle Sommer Nielsen · 2 messages
[RFC][DISCUSSION] throw expression
by Ilija Tovilo · 14 messages
[VOTE] throw expression
by Ilija Tovilo · 10 messages
RFC Throw expression was accepted
by Ilija Tovilo · 1 message
Convert return to expression like throw
by Florian Stascheck · 2 messages

RFC text

Copied from wiki.php.net, last synchronized Oct 13, 2026 11:51 UTC

Introduction

Since in PHP throw is a statement it makes it impossible to throw exceptions in places where only expressions are allowed, like arrow functions, the coalesce operator and the ternary/elvis operator. This RFC proposes converting the throw statement into an expression so that these cases become possible.

Proposal

Allow using throw in any context where an expression is accepted. These examples come to mind that seem useful:

// This was previously not possible since arrow functions only accept a single expression while throw was a statement.
$callable = fn() => throw new Exception();
 
// $value is non-nullable.
$value = $nullableValue ?? throw new InvalidArgumentException();
 
// $value is truthy.
$value = $falsableValue ?: throw new InvalidArgumentException();
 
// $value is only set if the array is not empty.
$value = !empty($array)
    ? reset($array)
    : throw new InvalidArgumentException();

There are other places where it could be used which are more controversial. These cases are allowed in this RFC.

// An if statement could make the intention clearer
$condition && throw new Exception();
$condition || throw new Exception();
$condition and throw new Exception();
$condition or throw new Exception();

Operator precedence

If throw becomes an expression operator precedence becomes relevant. These examples are working today.

throw $this->createNotFoundException();
// Evaluated as
throw ($this->createNotFoundException());
// Instead of
(throw $this)->createNotFoundException();
 
throw static::createNotFoundException();
// Evaluated as
throw (static::createNotFoundException());
// Instead of
(throw static)::createNotFoundException();
 
throw $userIsAuthorized ? new ForbiddenException() : new UnauthorizedException();
// Evaluated as
throw ($userIsAuthorized ? new ForbiddenException() : new UnauthorizedException());
// Instead of
(throw $userIsAuthorized) ? new ForbiddenException() : new UnauthorizedException();
 
throw $maybeNullException ?? new Exception();
// Evaluated as
throw ($maybeNullException ?? new Exception());
// Instead of
(throw $maybeNullException) ?? new Exception();
 
throw $exception = new Exception();
// Evaluated as
throw ($exception = new Exception());
// Instead of
(throw $exception) = new Exception();
 
throw $exception ??= new Exception();
// Evaluated as
throw ($exception ??= new Exception());
// Instead of
(throw $exception) ??= new Exception();
 
throw $condition1 && $condition2 ? new Exception1() : new Exception2();
// Evaluated as
throw ($condition1 && $condition2 ? new Exception1() : new Exception2());
// Instead of
(throw $condition1) && $condition2 ? new Exception1() : new Exception2();

The common theme here is that everything after the throw keyword has a higher precedence. For this reason this RFC proposes to use the lowest operator precedence possible. All the current code, even if broken or strange, will continue behaving the same way. This isn't a problem because generally throw should be the last operator you're using as every expression after it wouldn't be evaluated anyway.

The only downside of the low precedence is that a throw between two short-circuit operators would not be possible without parentheses:

$condition || throw new Exception('$condition must be truthy')
  && $condition2 || throw new Exception('$condition2 must be truthy');
// Evaluated as
$condition || (throw new Exception('$condition must be truthy') && $condition2 || (throw new Exception('$condition2 must be truthy')));
// Instead of
$condition || (throw new Exception('$condition must be truthy'))
  && $condition2 || (throw new Exception('$condition2 must be truthy'));

But I see little use for code like this.

Backward Incompatible Changes

None, specifically because the lowest precedence was chosen.

Other languages

The same was implemented in C# 7.0 in 2017. 1)

There aren't many other languages that allow this. There's an ECMAScript proposal because the same issues exist there. 2)

Proposed PHP Version(s)

Proposed version is PHP 8.

Voting

Voting starts 2020-04-05 and ends 2020-04-19.

As this is a language change, a 2/3 majority is required. The vote is a straight Yes/No vote for accepting the RFC and merging the patch.

Vote: Would you like to convert the throw statement into an expression? — Yes: 46 · No: 3 (closed)

References

Old discussion in internals list

1)https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/throw#the-throw-expression

2)https://github.com/tc39/proposal-throw-expressions