[ Runtime ] Invoking a static method on an interface is allowed and works if your return type is nullable or void
- Dominant language
- C++
- Stars
- 18.7k
- Forks
- 3.1k
- Avg merge
- 1h 47m
- Merged PRs (30d)
- 2
Description
**Describe the bug**
`SomeInterface::someStaticMethod()` is allowed to be called at runtime.
This invokes a ghost of a method with no body, implicitly returning void.
This means that this error will go unnoticed with you return type is nullable or mixed.
**Standalone code, or other way to reproduce the problem**
```HACK
<<__EntryPoint>>
function main(): void {
// Acts as you would expect, it invokes `MyClass::doIt()`.
do_the_it_with_this_class(MyClass::class);
// This is going something weird, you invoke IFace::doIt(),
// which is a method on an interface.
// Expected runtime behavior (call the abstract static method IFace::doIt()).
do_the_it_with_this_class(IFace::class);
// Acts as you would expect, it invokes `MyClass::returnIt()`.
return_it_with_the_class(MyClass::class);
try {
// This throws a typeerror:
// "Value returned from method IFace::returnIt() must be of type int, null given"
// This is referring to the `void` return, not an actual `return null`.
// We shouldn't be allowed to invoke `IFace::returnIt()` in the first place.
return_it_with_the_class(IFace::class);
} catch (\TypeError $e) {
echo $e->getMessage().\PHP_EOL;
}
// Acts as you would expect, it invokes `MyClass::returnIt()`.
return_it_with_reified_generics();
try {
// This throws a typeerror, same as above.
return_it_with_reified_generics();
} catch (\TypeError $e) {
echo $e->getMessage().\PHP_EOL;
}
}
interface IFace {
public static function doIt(): void;
public static function returnIt(): int;
}
final class MyClass implements IFace {
public static function doIt(): void {
echo "I am doing the 'it'\n";
}
public static function returnIt(): int {
return 42;
}
}
function do_the_it_with_this_class(classname $iface): void {
$iface::doIt();
}
function return_it_with_the_class(classname $iface): void {
$iface::returnIt();
}
function return_it_with_reified_generics(): void {
// This is a typechecker error, which is correct, but very limiting.
// Typing[4073] Cannot call IFace::returnIt(); it is abstract
T::returnIt();
}
```
Steps to reproduce the behavior:
1. Invoke an interface static method either directly (typechecker error) or via a reified generic (typechecker error) or via a classname (no typechecker error).
**Expected behavior**
This should throw an `\Error` `Cannot call abstract method IFace::methodNameHere()`.
**Actual behavior**
If the return type is nullable or void as in `doIt()`, the error passes silently.
If the return type is not nullable, a `\TypeError` is thrown, indicating that the implicit `null` return from an empty method is not compatible with your type (`int` in case of `returnIt()`).
Copy-paste output, or add a screenshot to illustrate what actually happens. Copy-pasted text output (e.g. from `hhvm` or `hh_client`) is preferred to screenshots.
```
I am doing the 'it'
Value returned from method IFace::returnIt() must be of type int, null given
Value returned from method IFace::returnIt() must be of type int, null given
```
**Environment**
- Operating system: Ubuntu 20.04
- Installation method: apt-get with dl.hhvm.com
- HHVM Version: 4.56.0
```
HipHop VM 4.56.0 (rel)
Compiler: 1588614387_226336535
Repo schema: d1ae8e21bf3419a65f12a010527485564e719d07
hackc-0b10dd000fc9b454637d8dffc67fb542d231572c-4.56.0
```
**Additional context**
This issue focusses on the runtime part of this error.
The next issue will focus on why `classname::doIt()` is allowed, but `(reified) T::doIt() where T as IFace` is not.
Contributor guide
Research direction
Run the standalone `main()` example against HHVM and confirm the behavior for `IFace::doIt()` and `IFace::returnIt()`. Start by tracing the runtime handling of the static calls in `do_the_it_with_this_class()` and `return_it_with_the_class()`; done means an abstract interface method call throws `\Error` instead of returning implicitly or producing a `\TypeError`.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, php
- Domain
- backend, compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100