Skip to content

Commit

Permalink
Change the way PHP7 exception aliasing works
Browse files Browse the repository at this point in the history
Summary:
fixes #7537
fixes #6747

Old approach: when parsing, replace `Throwable` with `__SystemLib\Throwable`
New approach: when loading the process, actually create `\Throwable` as an alias of `\__SystemLib\Throwable`

get_class() and messages still say systemlib, but this is an improvement.

Reviewed By: mofarrell

Differential Revision: D5031367

fbshipit-source-id: 4985318804c5c5c190cc8141d721e3d3408fb21b
  • Loading branch information
fredemmott authored and hhvm-bot committed May 11, 2017
1 parent e32d324 commit 29fc86f
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 17 deletions.
16 changes: 0 additions & 16 deletions hphp/compiler/parser/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2529,10 +2529,6 @@ Parser::AliasFlags Parser::getAliasFlags() {
flags = flags | AliasFlags::PHP7_ScalarTypes;
}

if (RuntimeOption::PHP7_EngineExceptions) {
flags = flags | AliasFlags::PHP7_EngineExceptions;
}

return flags;
}

Expand All @@ -2558,8 +2554,6 @@ Parser::AutoAliasMap getAutoAliasedClassesHelper() {
#define HH_ALIAS(alias, name) \
ALIAS(#alias, "HH\\" #name, AliasFlags::HH)
#define SCALAR_TYPE(name) HH_TYPE(name, AliasFlags::PHP7_ScalarTypes)
#define PHP7_TYPE(name, option) \
ALIAS(#name, "__SystemLib\\" #name, AliasFlags::option)
Parser::AutoAliasMap aliases {
HH_ONLY_TYPE(AsyncIterator),
HH_ONLY_TYPE(AsyncKeyedIterator),
Expand Down Expand Up @@ -2630,17 +2624,7 @@ Parser::AutoAliasMap getAutoAliasedClassesHelper() {
HH_ALIAS(integer, int),
HH_ALIAS(double, float),
HH_ALIAS(real, float),

// Engine exception classes
PHP7_TYPE(Throwable, PHP7_EngineExceptions),
PHP7_TYPE(Error, PHP7_EngineExceptions),
PHP7_TYPE(ArithmeticError, PHP7_EngineExceptions),
PHP7_TYPE(AssertionError, PHP7_EngineExceptions),
PHP7_TYPE(DivisionByZeroError, PHP7_EngineExceptions),
PHP7_TYPE(ParseError, PHP7_EngineExceptions),
PHP7_TYPE(TypeError, PHP7_EngineExceptions),
};
#undef PHP7_TYPE
#undef HH_ALIAS
#undef SCALAR_TYPE
#undef HH_ONLY_TYPE
Expand Down
1 change: 0 additions & 1 deletion hphp/compiler/parser/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,6 @@ struct Parser : ParserBase {
None = 0,
HH = 0x1,
PHP7_ScalarTypes = 0x2,
PHP7_EngineExceptions = 0x4,
};

struct AutoAlias {
Expand Down
37 changes: 37 additions & 0 deletions hphp/system/php/lang/Error.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php
class Error implements Throwable {
use BaseException;
/**
* ( excerpt from http://php.net/manual/en/exception.construct.php )
*
* Constructs the Exception.
*
* @message mixed The Exception message to throw.
* @code mixed The Exception code.
* @previous mixed The previous exception used for the exception
* chaining.
*/
public function __construct($message = '', $code = 0,
\__SystemLib\Throwable $previous = null) {

// Child classes may just override the protected property
// without implementing a constructor or calling parent one.
// In this case we should not override it from the param.

if ($message !== '' || $this->message === '') {
$this->message = $message;
}

if ($code !== 0 || $this->code === 0) {
$this->code = $code;
}

$this->previous = $previous;
}
}

class ArithmeticError extends Error {}
class AssertionError extends Error {}
class DivisionByZeroError extends Error {}
class ParseError extends Error {}
class TypeError extends Error {}
11 changes: 11 additions & 0 deletions hphp/system/php/lang/Throwable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
interface Throwable {
public function getMessage(): string;
public function getCode(): int;
public function getFile(): string;
public function getLine(): int;
public function getTrace(): array;
public function getTraceAsString(): string;
public function getPrevious(): Throwable;
public function __toString(): string;
}
27 changes: 27 additions & 0 deletions hphp/system/systemlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "hphp/system/systemlib.h"
#include "hphp/runtime/base/array-init.h"
#include "hphp/runtime/base/init-fini-node.h"
#include "hphp/runtime/vm/unit.h"
#include "hphp/runtime/vm/class.h"
#include "hphp/runtime/base/execution-context.h"
Expand Down Expand Up @@ -250,5 +251,31 @@ void mergePersistentUnits() {
}
}

namespace {

#define PHP7_ROOT_ALIAS(x) \
auto x##Ne = NamedEntity::get(makeStaticString(#x)); \
x##Ne->m_cachedClass.bind(rds::Mode::Persistent); \
x##Ne->setCachedClass(SystemLib::s_##x##Class)

InitFiniNode aliasPhp7Classes(
[]() {
if (!RuntimeOption::PHP7_EngineExceptions) {
return;
}
PHP7_ROOT_ALIAS(Throwable);
PHP7_ROOT_ALIAS(Error);
PHP7_ROOT_ALIAS(ArithmeticError);
PHP7_ROOT_ALIAS(AssertionError);
PHP7_ROOT_ALIAS(DivisionByZeroError);
PHP7_ROOT_ALIAS(ParseError);
PHP7_ROOT_ALIAS(TypeError);
},
InitFiniNode::When::ProcessInit
);

#undef PHP7_ROOT_ALIAS
} // namespace

/////////////////////////////////////////////////////////////////////////////
}} // namespace HPHP::SystemLib
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Foo;
$y = 'Throwable';

$x = new \Exception();
var_dump($x instanceof \Throwable);
var_dump($x instanceof Throwable);
var_dump($x instanceof $y);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bool(true)
bool(false)
bool(true)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
namespace test;

function a(\Throwable $t) {
var_dump(get_class($t));
}

a(new \RuntimeException('foo'));
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
string(16) "RuntimeException"

1 comment on commit 29fc86f

@fredemmott
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error.php and Throwable.php shouldn't be here, fixing.

Please sign in to comment.