Skip to content

Commit 206760e

Browse files
DavidSniderfacebook-github-bot
authored andcommitted
Remove class-loading check for overriding type constants
Summary: This fatals, but hh is fine with it ``` interface I1 { abstract const type T = nothing; } interface I2 extends I1 { const type T = mixed; } ``` I went digging and discovered that HHVM doesn't understand that the type const in I1 is abstract. In fact the abstract keyword doesn't result in any emission differences. This is the rust structure: ``` pub struct HhasTypeConstant { pub name: String, pub initializer: Option<TypedValue>, } ``` It's just "Is there a value? no -> abstract, else -> non-abstract" Then in the class loading code we have this: ``` // Forbid redefining constants from interfaces, but not superclasses. // Constants from interfaces implemented by superclasses can be // overridden. ``` This is super weird IMO. At the very least we need to not fatal on this case (it has direct applications for coeffects). In the best case, we'd probably have HHVM understand the notion of abstract w/ default. As I see it there are basically 2 options: 1. delete the check (for type constants). It seems weird enough as it is that it's the only restrictions on redefinitions. Then again, that results in HHVM not having any confirmation that the hierarchy is reasonable, but we don't enforce them anyway, so that might be OK? 2. do a bunch of work to redo how HHVM sees type constants and potentially add more checks. I'm going to do the first here as a short term solution and then we can discuss the latter in more detail. Reviewed By: paulbiss Differential Revision: D26076753 fbshipit-source-id: 6aedfc10d4ab31fc61782adbadd09203aa8b9cc8
1 parent 534d890 commit 206760e

File tree

4 files changed

+16
-8
lines changed

4 files changed

+16
-8
lines changed

Diff for: hphp/hhbbc/index.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1544,7 +1544,7 @@ bool build_class_constants(BuildClsInfo& info,
15441544

15451545
// A constant from an interface or from an included enum collides
15461546
// with an existing constant.
1547-
if (rparent->cls->attrs & (AttrInterface | AttrEnum)) {
1547+
if (rparent->cls->attrs & (AttrInterface | AttrEnum) && !c.isTypeconst) {
15481548
ITRACE(2,
15491549
"build_cls_info_rec failed for `{}' because "
15501550
"`{}' was defined by both `{}' and `{}'\n",

Diff for: hphp/runtime/vm/class.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -2299,15 +2299,15 @@ void Class::setConstants() {
22992299
if (it2 != builder.end()) {
23002300
auto definingClass = builder[it2->second].cls;
23012301
// Forbid redefining constants from interfaces, but not superclasses.
2302-
// Constants from interfaces implemented by superclasses can be
2303-
// overridden.
2302+
// Constants from interfaces implemented by superclasses can be overridden.
2303+
// Note that we don't do this check for type constants due to the
2304+
// existence of abstract type constants with defaults, which we don't
2305+
// currently have a way of tracking within HHVM.
23042306
if (definingClass->attrs() & AttrInterface) {
23052307
for (auto interface : m_declInterfaces) {
2306-
if (interface->hasConstant(preConst->name()) ||
2307-
interface->hasTypeConstant(preConst->name())) {
2308-
raise_error("Cannot override previously defined %sconstant "
2308+
if (interface->hasConstant(preConst->name())) {
2309+
raise_error("Cannot override previously defined constant "
23092310
"%s::%s in %s",
2310-
builder[it2->second].isType() ? "type " : "",
23112311
builder[it2->second].cls->name()->data(),
23122312
preConst->name()->data(),
23132313
m_preClass->name()->data());

Diff for: hphp/test/slow/class_type_constant/type_constant14.php

+8
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@ class C implements I {
88
const type T = string;
99
}
1010

11+
interface I2 extends I {
12+
const type T = string;
13+
}
14+
15+
class C2 implements I2 {}
16+
1117
<<__EntryPoint>>
1218
function main(): void {
19+
new C();
20+
new C2();
1321
echo "Done.\n";
1422
}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Fatal error: Cannot override previously defined type constant I::T in C in %stest/slow/class_type_constant/type_constant14.php on line 7
1+
Done.

0 commit comments

Comments
 (0)