facebook / facebook/flow

Refinement with `instanceof` and generic unions is unsound

Open
#6,741 5 comments 0 reactions 1 assignee Claimed by @jbrown215 View on GitHub
bug Typing: soundness
Dominant language
Rust
Stars
22.3k
Forks
1.9k
PR merge metrics
No merged PRs in 30d

Description

If `x: T | MyClass`, then Flow infers from `x instanceof MyClass`
that `x: MyClass`. This is unsound: `T` could be `MyClass` for
some other `U`, so that in fact `x: MyClass>`.

[Here is an example of how this can go wrong:][1]

```js
// @flow
class Box {
+field: T;
constructor(x) {
this.field = x;
}
}

function asBox(x: T | Box): Box {
if (x instanceof Box) {
// Here, `x` is refined to be `Box`. This is unsound: `T` could
// well be `Box` for some other `U`. Example below.
return x;
} else {
// whatever
return new Box(x);
}
}

const stringStringBox: Box> = asBox(new Box("wat")); // unsound!
stringStringBox.field.field.substr(0); // runtime error
```

[1]: https://flow.org/try/#0PTAEAEDMBsHsHcBQBjaBDAzh0AhWAPAHgBUA+UAb0VFAGpIBLAU2gBMAuUYgbmtGVgA7DABcATgFdkI2GIAU+AJSU+NEQAsGGAHSMWrUAF5Q+XjQC+iS4kgTB0hkNCY8RMgs7FQAH1wESpIqcrgEqNAyQoAqgDMIiaPZMsJGuylQ0NCCgABJMYkwANKAABvjFMdj5jIJMBjKgAEZMJSFkxdpcmthaoHYYsHYcJcTlAhJsqqBZ8CzQjc3FIQCqpOWQsqD9ALbNsBp5JUvtoACi+GhbAA7QzU1w8NqT+SISYoImZqDmoCwYzekZabqNAiJgANzyTyYLzeoBq8D8+AUik+lmsAjim3EsQA5gBlbGCHGuYL+EKiMS40jkYwuAhyeGIuQAIngIOZihRmTAfQGglYAEJEBTcQTKUTXLpmGwpfptBgJA0KXIAAxcqZgSSCEQMHY-MRiWSIIA

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.