facebook / facebook/hhvm

[ TypeChecker ] Generic methods with different amount of generics make subtypes not substitutable for their supertypes

Open
#8,730 0 comments 0 reactions 0 assignees View on GitHub
hack
Dominant language
C++
Stars
18.7k
Forks
3.1k
Avg merge
1h 47m
Merged PRs (30d)
2

Description

**Describe the bug**

The typechecker does not allow for calls of a generic method if the amount of generics does not match. If a parent class declares `n` generics on a method and a child class declares more, you need to update code written for the parent if you update the typehint to the child.

**Standalone code, or other way to reproduce the problem**

```HACK
abstract class GrandFather {
abstract public function f(T1 $x): int;
}
abstract class Father extends GrandFather {
abstract public function f(T1 $x): int;
}
class Child extends Father {
public function f(T1 $x): int {
return 0;
}
}

function get_grand_father(): GrandFather { return new Child(); }
function get_father(): Father { return new Child(); }
function get_child(): Child { return new Child(); }

function main(): void {
get_grand_father()->f(0);
get_father()->f(0); // This callsite is blamed for having one generic instead of two
get_child()->f(0);
}
```

Steps to reproduce the behavior:
1. Observe typechecker error being emitted for Father, but not for GrandFather or Child.

**Expected behavior**

Either the declaration of `Father` is faulty. This should be flagged by the typechecker. The amount of generics does not match.
Or invoking `->f()` on a `Father` should be valid.

**Actual behavior**

The invocation is blamed instead of the declaration.
```
Typing[4029] Expected 2 type parameters
--> file.hack
5 | abstract public function f(T1 $x): int;
| ^ Definition is here
19 | get_father()->f(0);
| ^

1 error found.
```

**Environment**
- Ubuntu 20.04
- apt-get with dl.hhvm.com repository
```
HipHop VM 4.56.1 (rel)
Compiler: 1593547575_929404933
Repo schema: d1ae8e21bf3419a65f12a010527485564e719d07
hackc-0b10dd000fc9b454637d8dffc67fb542d231572c-4.56.1
```

**Additional context**

Making the return typehint of a function more specific (leaving the runtime type the same) should not break BC for an API.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.