From 3aa18b0bbd0c7f6c11dd97e8ae84a6fb2cdabea3 Mon Sep 17 00:00:00 2001 From: Panos Vekris Date: Wed, 18 Dec 2024 22:34:08 -0800 Subject: [PATCH] [flow][lib] restrict typing of Array.concat Summary: Before, given the declaration ``` declare class $ReadOnlyArray<+T> { ... concat | S>(...items: Array): Array; ... } ``` the following forms were errors ``` declare const arr: Array; arr.concat(); arr.concat() as Array; ``` * The first due to under-constrained `S` * The second due to inferring a bad bound (`mixed`) which is incompatible with `number` This change makes `.concat` behave better when called without arguments. Changelog: [fix] improved definition of `Array.concat()`. Reviewed By: gkz Differential Revision: D67421211 fbshipit-source-id: b48516259e80e94134f07320504e0e4dffd35d79 --- lib/core.js | 2 +- tests/arraylib/array_lib.js | 3 ++ tests/arraylib/arraylib.exp | 50 +++++++++---------- .../autocomplete_from_h_to_l.exp | 4 +- tests/rec/rec.exp | 4 +- 5 files changed, 33 insertions(+), 30 deletions(-) diff --git a/lib/core.js b/lib/core.js index 6e1f8d11987..dc9d016e77b 100644 --- a/lib/core.js +++ b/lib/core.js @@ -713,7 +713,7 @@ declare class $ReadOnlyArray<+T> { * Combines two or more arrays. * @param items Additional items to add to the end of array1. */ - concat | S>(...items: Array): Array; + concat(...items: Array<$ReadOnlyArray | S>): Array; /** * Returns an iterable of key, value pairs for every entry in the array */ diff --git a/tests/arraylib/array_lib.js b/tests/arraylib/array_lib.js index 0b0047da907..14b18ddf05f 100644 --- a/tests/arraylib/array_lib.js +++ b/tests/arraylib/array_lib.js @@ -24,6 +24,9 @@ var k: Array = h.concat(h); var l: Array = h.concat(1, 2, 3); var m: Array = h.concat('a', 'b', 'c'); var n: Array = h.concat('a', 'b', 'c'); // Error +var o = h.concat(); +o as Array; // OK +var p: Array = h.concat(); // OK function reduce_test() { /* Adapted from the following source: diff --git a/tests/arraylib/arraylib.exp b/tests/arraylib/arraylib.exp index f70b018ff55..db6df9be657 100644 --- a/tests/arraylib/arraylib.exp +++ b/tests/arraylib/arraylib.exp @@ -95,83 +95,83 @@ References: ^^^^^^ [2] -Error ----------------------------------------------------------------------------------------------- array_lib.js:55:29 +Error ----------------------------------------------------------------------------------------------- array_lib.js:58:29 Cannot use operator `*` with operands string [1] and number [2] [unsafe-arithmetic] - array_lib.js:55:29 - 55| [''].reduce((acc, str) => acc * str.length); // error, string ~> number + array_lib.js:58:29 + 58| [''].reduce((acc, str) => acc * str.length); // error, string ~> number ^^^^^^^^^^^^^^^^ References: - array_lib.js:55:4 - 55| [''].reduce((acc, str) => acc * str.length); // error, string ~> number + array_lib.js:58:4 + 58| [''].reduce((acc, str) => acc * str.length); // error, string ~> number ^^ [1] /core.js:1365:13 1365| length: number; ^^^^^^ [2] -Error ----------------------------------------------------------------------------------------------- array_lib.js:56:34 +Error ----------------------------------------------------------------------------------------------- array_lib.js:59:34 Cannot use operator `*` with operands string [1] and number [2] [unsafe-arithmetic] - array_lib.js:56:34 - 56| [''].reduceRight((acc, str) => acc * str.length); // error, string ~> number + array_lib.js:59:34 + 59| [''].reduceRight((acc, str) => acc * str.length); // error, string ~> number ^^^^^^^^^^^^^^^^ References: - array_lib.js:56:4 - 56| [''].reduceRight((acc, str) => acc * str.length); // error, string ~> number + array_lib.js:59:4 + 59| [''].reduceRight((acc, str) => acc * str.length); // error, string ~> number ^^ [1] /core.js:1365:13 1365| length: number; ^^^^^^ [2] -Error ------------------------------------------------------------------------------------------------ array_lib.js:68:3 +Error ------------------------------------------------------------------------------------------------ array_lib.js:71:3 Cannot cast `Array.from(...)` to array type because string [1] is incompatible with empty [2] in array element. [incompatible-cast] - array_lib.js:68:3 - 68| Array.from('abcd') as Array; // ERROR + array_lib.js:71:3 + 71| Array.from('abcd') as Array; // ERROR ^^^^^^^^^^^^^^^^^^ References: /core.js:1139:37 1139| static from(str: string): Array; ^^^^^^ [1] - array_lib.js:68:31 - 68| Array.from('abcd') as Array; // ERROR + array_lib.js:71:31 + 71| Array.from('abcd') as Array; // ERROR ^^^^^ [2] -Error ----------------------------------------------------------------------------------------------- array_lib.js:83:57 +Error ----------------------------------------------------------------------------------------------- array_lib.js:86:57 Cannot call `Array.of` because number [1] is incompatible with string [2] in array element. [incompatible-call] - array_lib.js:83:57 - 83| var incompatibleTypeNotOkay: Array = Array.of(1, 2); + array_lib.js:86:57 + 86| var incompatibleTypeNotOkay: Array = Array.of(1, 2); ^ [1] References: - array_lib.js:83:38 - 83| var incompatibleTypeNotOkay: Array = Array.of(1, 2); + array_lib.js:86:38 + 86| var incompatibleTypeNotOkay: Array = Array.of(1, 2); ^^^^^^ [2] -Error ----------------------------------------------------------------------------------------------- array_lib.js:83:60 +Error ----------------------------------------------------------------------------------------------- array_lib.js:86:60 Cannot call `Array.of` because number [1] is incompatible with string [2] in array element. [incompatible-call] - array_lib.js:83:60 - 83| var incompatibleTypeNotOkay: Array = Array.of(1, 2); + array_lib.js:86:60 + 86| var incompatibleTypeNotOkay: Array = Array.of(1, 2); ^ [1] References: - array_lib.js:83:38 - 83| var incompatibleTypeNotOkay: Array = Array.of(1, 2); + array_lib.js:86:38 + 86| var incompatibleTypeNotOkay: Array = Array.of(1, 2); ^^^^^^ [2] diff --git a/tests/autocomplete_from_h_to_l/autocomplete_from_h_to_l.exp b/tests/autocomplete_from_h_to_l/autocomplete_from_h_to_l.exp index 8ac336d0338..2f98929a08b 100644 --- a/tests/autocomplete_from_h_to_l/autocomplete_from_h_to_l.exp +++ b/tests/autocomplete_from_h_to_l/autocomplete_from_h_to_l.exp @@ -2345,7 +2345,7 @@ Flags: --pretty {"name":"?.at","type":"void | ((index: number) => T | void)"}, { "name":"?.concat", - "type":"void | ( | S>(...items: Array) => Array)" + "type":"void | ((...items: Array<$ReadOnlyArray | S>) => Array)" }, { "name":"?.copyWithin", @@ -2457,7 +2457,7 @@ Flags: --pretty {"name":"at","type":"(index: number) => T | void"}, { "name":"concat", - "type":" | S>(...items: Array) => Array" + "type":"(...items: Array<$ReadOnlyArray | S>) => Array" }, { "name":"copyWithin", diff --git a/tests/rec/rec.exp b/tests/rec/rec.exp index bd16482f928..0848b55d51a 100644 --- a/tests/rec/rec.exp +++ b/tests/rec/rec.exp @@ -393,8 +393,8 @@ defined. [method-unbinding] References: /core.js:716:5 - 716| concat | S>(...items: Array): Array; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [2] + 716| concat(...items: Array<$ReadOnlyArray | S>): Array; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [2] Error ----------------------------------------------------------------------------------------------- this_subst.js:1:53