add Callable typehint
php-5.4 has it http://www.php.net/manual/en/language.types.callable.php
Esse commit está contido em:
@@ -66,6 +66,7 @@ typedef __sighandler_t *sighandler_t;
|
||||
#include "runtime/base/runtime_option.h"
|
||||
#include "runtime/base/server/source_root_info.h"
|
||||
#include "runtime/ext/ext_continuation.h"
|
||||
#include "runtime/ext/ext_function.h"
|
||||
#include "runtime/vm/debug/debug.h"
|
||||
#include "runtime/vm/translator/targetcache.h"
|
||||
#include "runtime/vm/translator/translator-deps.h"
|
||||
@@ -10258,6 +10259,16 @@ VerifyParamTypeSlow(const Class* cls, const Class* constraint, int param) {
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
VerifyParamCallable(ObjectData* obj, int param) {
|
||||
TypedValue tv;
|
||||
tvWriteObject(obj, &tv);
|
||||
if (!UNLIKELY(f_is_callable(tvAsCVarRef(&tv)))) {
|
||||
VerifyParamTypeFail(param);
|
||||
}
|
||||
tvDecRef(&tv);
|
||||
}
|
||||
|
||||
void
|
||||
TranslatorX64::translateVerifyParamType(const Tracelet& t,
|
||||
const NormalizedInstruction& i) {
|
||||
@@ -10283,18 +10294,21 @@ TranslatorX64::translateVerifyParamType(const Tracelet& t,
|
||||
ScratchReg cls(m_regMap);
|
||||
// Constraint may not be in the class-hierarchy of the method being traced,
|
||||
// look up the class handle and emit code to put the Class* into a reg.
|
||||
bool isSelfOrParent = tc.isSelf() || tc.isParent();
|
||||
bool isSpecial = tc.isSelf() || tc.isParent() || tc.isCallable();
|
||||
const Class* constraint = nullptr;
|
||||
const StringData* clsName;
|
||||
if (!isSelfOrParent) {
|
||||
if (!isSpecial) {
|
||||
clsName = tc.typeName();
|
||||
constraint = Unit::lookupUniqueClass(clsName);
|
||||
} else {
|
||||
if (tc.isSelf()) {
|
||||
tc.selfToClass(curFunc(), &constraint);
|
||||
} else {
|
||||
assert(tc.isParent());
|
||||
} else if (tc.isParent()) {
|
||||
tc.parentToClass(curFunc(), &constraint);
|
||||
} else {
|
||||
assert(tc.isCallable());
|
||||
EMIT_RCALL(a, i, VerifyParamCallable, R(src), IMM(param));
|
||||
return;
|
||||
}
|
||||
clsName = constraint ? constraint->preClass()->name() : nullptr;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <util/base.h>
|
||||
#include <util/trace.h>
|
||||
#include <runtime/ext/ext_function.h>
|
||||
#include <runtime/vm/hhbc.h>
|
||||
#include <runtime/vm/class.h>
|
||||
#include <runtime/vm/unit.h>
|
||||
@@ -39,22 +40,23 @@ TypeConstraint::TypeConstraint(const StringData* typeName /* = NULL */,
|
||||
const StringData* name;
|
||||
Type type;
|
||||
} pairs[] = {
|
||||
{ StringData::GetStaticString("bool"), { KindOfBoolean, Precise }},
|
||||
{ StringData::GetStaticString("boolean"), { KindOfBoolean, Precise }},
|
||||
{ StringData::GetStaticString("bool"), { KindOfBoolean, Precise }},
|
||||
{ StringData::GetStaticString("boolean"), { KindOfBoolean, Precise }},
|
||||
|
||||
{ StringData::GetStaticString("int"), { KindOfInt64, Precise }},
|
||||
{ StringData::GetStaticString("integer"), { KindOfInt64, Precise }},
|
||||
{ StringData::GetStaticString("int"), { KindOfInt64, Precise }},
|
||||
{ StringData::GetStaticString("integer"), { KindOfInt64, Precise }},
|
||||
|
||||
{ StringData::GetStaticString("real"), { KindOfDouble, Precise }},
|
||||
{ StringData::GetStaticString("double"), { KindOfDouble, Precise }},
|
||||
{ StringData::GetStaticString("float"), { KindOfDouble, Precise }},
|
||||
{ StringData::GetStaticString("real"), { KindOfDouble, Precise }},
|
||||
{ StringData::GetStaticString("double"), { KindOfDouble, Precise }},
|
||||
{ StringData::GetStaticString("float"), { KindOfDouble, Precise }},
|
||||
|
||||
{ StringData::GetStaticString("string"), { KindOfString, Precise }},
|
||||
{ StringData::GetStaticString("string"), { KindOfString, Precise }},
|
||||
|
||||
{ StringData::GetStaticString("array"), { KindOfArray, Precise }},
|
||||
{ StringData::GetStaticString("array"), { KindOfArray, Precise }},
|
||||
|
||||
{ StringData::GetStaticString("self"), { KindOfObject, Self }},
|
||||
{ StringData::GetStaticString("parent"), { KindOfObject, Parent }},
|
||||
{ StringData::GetStaticString("self"), { KindOfObject, Self }},
|
||||
{ StringData::GetStaticString("parent"), { KindOfObject, Parent }},
|
||||
{ StringData::GetStaticString("callable"), { KindOfObject, Callable }},
|
||||
};
|
||||
for (unsigned i = 0; i < sizeof(pairs) / sizeof(Pair); ++i) {
|
||||
s_typeNamesToTypes[pairs[i].name] = pairs[i].type;
|
||||
@@ -107,11 +109,13 @@ TypeConstraint::check(const TypedValue* tv, const Func* func) const {
|
||||
return true;
|
||||
}
|
||||
const Class *c = nullptr;
|
||||
if (isSelf() || isParent()) {
|
||||
if (isSelf() || isParent() || isCallable()) {
|
||||
if (isSelf()) {
|
||||
selfToClass(func, &c);
|
||||
} else if (isParent()) {
|
||||
parentToClass(func, &c);
|
||||
} else if (isCallable()) {
|
||||
return f_is_callable(tvAsCVarRef(tv));
|
||||
}
|
||||
} else {
|
||||
// We can't save the Class* since it moves around from request
|
||||
|
||||
@@ -34,7 +34,8 @@ protected:
|
||||
enum MetaType {
|
||||
Precise,
|
||||
Self,
|
||||
Parent
|
||||
Parent,
|
||||
Callable
|
||||
};
|
||||
|
||||
struct Type {
|
||||
@@ -46,6 +47,9 @@ protected:
|
||||
constexpr bool isSelf() const {
|
||||
return m_metatype == Self;
|
||||
}
|
||||
constexpr bool isCallable() const {
|
||||
return m_metatype == Callable;
|
||||
}
|
||||
};
|
||||
|
||||
Type m_type;
|
||||
@@ -74,10 +78,15 @@ public:
|
||||
bool isParent() const {
|
||||
return m_type.isParent();
|
||||
}
|
||||
|
||||
bool isCallable() const {
|
||||
return m_type.isCallable();
|
||||
}
|
||||
|
||||
bool isObject() const {
|
||||
assert(IMPLIES(isParent(), m_type.m_dt == KindOfObject));
|
||||
assert(IMPLIES(isSelf(), m_type.m_dt == KindOfObject));
|
||||
assert(IMPLIES(isCallable(), m_type.m_dt == KindOfObject));
|
||||
return m_type.m_dt == KindOfObject;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
function a(callable $b) { $b(); }
|
||||
|
||||
$c = function() { var_dump(true); };
|
||||
a($c);
|
||||
|
||||
try {
|
||||
a('hi');
|
||||
} catch (Exception $e) {
|
||||
var_dump($e);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
bool(true)
|
||||
HipHop Fatal error: Argument 1 passed to a() must be an instance of callable, string given in hphp/test/vm/typehint_callable.php on line 3
|
||||
Link simbólico
+1
@@ -0,0 +1 @@
|
||||
filepath.filter
|
||||
Referência em uma Nova Issue
Bloquear um usuário