Skip to content
Permalink
Browse files

[Bugbash] mixed refined by array produces $ReadOnlyArray<mixed>

Summary:
It is not safe to refine `mixed` to `Array<mixed>` as this allows for writing arbitrary values to the result of the refinement, and since we only know that the value is an array, we cannot know that it is safe to write a given value to the array. We do know, however, that anything we get out of the array will be `mixed`, so it is safe to type it as a `$ReadOnlyArray<mixed>`.

```
function bad(array: mixed) {
  if (Array.isArray(array)) {
    const problem: Array<mixed> = array;
    problem[1] = 0;
  }
}

bad((["3"] : Array<string>));
```

Fixes #7197 (along with another change Mike is making)

Reviewed By: mvitousek

Differential Revision: D14785979

fbshipit-source-id: eba057af9f874ab3a9619ca8cfcf515b0dec0ee1
  • Loading branch information...
dsainati1 authored and facebook-github-bot committed Apr 5, 2019
1 parent 3baafb0 commit 5639532065954e7f66a968af5e68f76a762a9c14
Showing with 82 additions and 4 deletions.
  1. +2 −2 src/typing/type_filter.ml
  2. +52 −1 tests/arrays/arrays.exp
  3. +27 −0 tests/arrays/isarray.js
  4. +1 −1 tests/refinements/refinements.exp
@@ -374,8 +374,8 @@ let not_function t =
let array t =
match t with
| DefT (r, trust, MixedT _) ->
DefT (replace_reason_const RArray r, trust,
ArrT (ArrayAT (DefT (r, trust, MixedT Mixed_everything), None))
DefT (replace_reason_const RROArrayType r, trust,
ArrT (ROArrayAT (DefT (r, trust, MixedT Mixed_everything)))
)
| DefT (_, _, (ArrT _)) | AnyT _ ->
t
@@ -15,6 +15,57 @@ References:
^^^^^^ [2]


Error -------------------------------------------------------------------------------------------------- isarray.js:4:31

Cannot assign `array` to `problem` because read-only array type [1] is incompatible with array type [2].

isarray.js:4:31
4| const problem: Array<Z> = array; // error
^^^^^

References:
isarray.js:2:24
2| function hmm<Z>(array: Z) {
^ [1]
isarray.js:4:20
4| const problem: Array<Z> = array; // error
^^^^^^^^ [2]


Error ------------------------------------------------------------------------------------------------- isarray.js:11:31

Cannot assign `array` to `problem` because read-only array type [1] is incompatible with array type [2].

isarray.js:11:31
11| const problem: Array<Z> = array; // error
^^^^^

References:
isarray.js:9:26
9| function hmm<Z>(array: Z): Z {
^ [1]
isarray.js:11:20
11| const problem: Array<Z> = array; // error
^^^^^^^^ [2]


Error ------------------------------------------------------------------------------------------------- isarray.js:24:35

Cannot assign `array` to `problem` because read-only array type [1] is incompatible with array type [2].

isarray.js:24:35
24| const problem: Array<mixed> = array; // error
^^^^^

References:
isarray.js:22:21
22| function hmm(array: mixed) {
^^^^^ [1]
isarray.js:24:20
24| const problem: Array<mixed> = array; // error
^^^^^^^^^^^^ [2]


Error ---------------------------------------------------------------------------------------------- numeric_elem.js:6:1

Cannot assign `0` to `arr[day]` because `Date` [1] is not an array index.
@@ -44,4 +95,4 @@ References:



Found 3 errors
Found 6 errors
@@ -0,0 +1,27 @@
// @flow
function hmm<Z>(array: Z) {
if (Array.isArray(array)) {
const problem: Array<Z> = array; // error
}
}

function coerce<T, U>(t: T): U {
function hmm<Z>(array: Z): Z {
if (!Array.isArray(array)) throw new Error("Unreachable.");
const problem: Array<Z> = array; // error
if (array.length === 0) throw new Error("Unreachable.");
return problem[0];
}
const result: Array<{ value: T }> = hmm([{ value: t }]);
if (Array.isArray(result)) throw new Error("Unreachable.");
return ((result: empty).value: U);
}
const twelve: number = coerce("twelve");
twelve.toFixed();

function hmm(array: mixed) {
if (Array.isArray(array)) {
const problem: Array<mixed> = array; // error
problem[1] = 0;
}
}
@@ -1041,7 +1041,7 @@ References:

Error --------------------------------------------------------------------------------------------------- mixed.js:59:17

Cannot call `takesString` with `x` bound to `x` because array [1] is incompatible with string [2].
Cannot call `takesString` with `x` bound to `x` because read-only array type [1] is incompatible with string [2].

mixed.js:59:17
59| takesString(x); // error

0 comments on commit 5639532

Please sign in to comment.
You can’t perform that action at this time.