在实验hack中的通用函数的约束时,我想到了以下内容:
<?hh // strict
class Base {}
class Derived extends Base {}
abstract class ImplBase {
abstract const type T as Base;
public function foo<Tf as this::T>(Tf $v): void {}
}
class ImplDerived extends ImplBase {
const type T = Derived;
}
function foo(ImplDerived $v): void {
bar($v);
}
function bar(ImplBase $v): void {
$v->foo(new Base());
$v->foo(new Derived());
}
原理足够基本:从混凝土ImplDerived
升起,Typechecker是否将ImplBase::T
视为bar
中可以通过约束将其施加到Base
中的抽象类型,还是它保留对T = Derived
的引用?不过,很奇怪的是,答案都不是。bar
中的每一行都是出于不同的原因失败:
-
$v->foo(new Base());
失败,因为Tf
被"约束至依赖类型的<expr#1>::T
[...]参考new Base()
"。 -
$v->foo(new Derived());
失败,因为POOF!Tf
突然是Base
!"[this::T]
是Base
类型的对象[...],这是由于扩展constant condImplBase::T
而产生的。
我是在问不可能,还是尚未完全实施?
有趣的是,您今天是第二个向我提及这一点的人;第一个是正在研究改善类型常数和约束之间的相互作用的黑客团队开发人员之一。
是的,我们正在研究它。在任何时间表上都没有承诺进行整理。