classname<T> and private covariant type permits type violation
- Dominant language
- C++
- Stars
- 18.7k
- Forks
- 3.1k
- Avg merge
- 1h 47m
- Merged PRs (30d)
- 2
Description
### HHVM Version
```
$ hhvm --version
HipHop VM 3.13.1 (rel)
```
### Standalone code, or other way to reproduce the problem
Define a class covariant on one of its type parameters and assert the constructor is consistent:
``` hack
>
abstract class A<+T> {
abstract public function __construct(T $v);
abstract public function foo(): int;
}
```
Then extend that class and constrain that same type parameter to a derived type, and act on that type in some methods:
``` hack
extends A {
public function __construct(private T $v) {}
public function foo(): int {
return $this->v->foo; // we assume here T is a subtype of Derived
}
}
```
Cast the `classname` of the extended class to the `classname` of the base class parameterized with a supertype of the extended class's constraint. Invoke a method that acts on the type parameter in the extended class.
``` hack
> $v): void {
echo (new $v(new Base()))->foo(); // `B::foo` attempts to summon an int from thin air!
// It's not very effective.
}
}
```
This is where B needs to be covariant on `T`: the typechecker doesn't allow this cast if it isn't.
### Expected result
Some sort of variance violation? I don't know which is the more illegal step: allowing private properties of a covariant type, or the classname cast.
### Actual result
`No errors!` from the typechecker, but
```
Notice: Undefined property: Base::$foo in B.php on line 10
Catchable fatal error: Value returned from method B::foo() must be of type int, null given in B.php on line 10
```
from executing `C::foo()`.
Contributor guide
Assessment
This issue has not been assessed yet.