New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Flow chokes (takes over CPU and never finishes) on the following code example #4370
Comments
I have reduced example little bit further: /* @flow */
export type Dict<a> = {
[key: string]: a
}
export const merge = <a, b, result>(
accumulateLeft: ([string, a], result) => result,
accumulateBoth: ([string, [a, b]], result) => result,
accumulateRight: ([string, b], result) => result,
left: Dict<a>,
right: Dict<b>,
init: result
): result => {
let state = init
for (let key in left) {
if (key in right) {
state = accumulateBoth([key, [left[key], right[key]]], state)
} else {
state = accumulateLeft([key, left[key]], state)
}
}
for (let key in right) {
if (!(key in left)) {
state = accumulateRight([key, right[key]], state)
}
}
return state
}
const log = merge(
([key, left], log) => [...log, `- ${key} : ${left}`],
([key, [left, right]], log) => [...log, `= ${key} : ${left} -> ${right}`],
([key, right], log) => [...log, `+ ${key} : ${right}`],
{ a: 1, b: 2 },
{ b: 18, c: 9 },
[]
) I also noticed that const merge: <number, number, any[]> (
accumulateLeft: ([string, a]: [any, any], result: any) => any[],
accumulateBoth: ([string, [a, b]]: [any, [any, any]], result: any) => any[],
accumulateRight: ([string, b]: [any, any], result: any) => any[],
left: Dict<number>,
right: Dict<number>,
init: any[]
) => any[] Which seems somewhat odd, but not sure if it indicative of what the issue is. |
So, if I do annotate inline functions with return type flow seems to get over the hump that it otherwise chokes over: /* @flow */
export type Dict<a> = {
[key: string]: a
}
export const merge = <a, b, result>(
accumulateLeft: ([string, a], result) => result,
accumulateBoth: ([string, [a, b]], result) => result,
accumulateRight: ([string, b], result) => result,
left: Dict<a>,
right: Dict<b>,
init: result
): result => {
let state = init
for (let key in left) {
if (key in right) {
state = accumulateBoth([key, [left[key], right[key]]], state)
} else {
state = accumulateLeft([key, left[key]], state)
}
}
for (let key in right) {
if (!(key in left)) {
state = accumulateRight([key, right[key]], state)
}
}
return state
}
const log = merge(
([key, left], log): string[] => [...log, `- ${key} : ${left}`],
([key, [left, right]], log): string[] => [
...log,
`= ${key} : ${left} -> ${right}`
],
([key, right], log): string[] => [...log, `+ ${key} : ${right}`],
{ a: 1, b: 2 },
{ b: 18, c: 9 },
[]
) low focus-check src/Issue.js
[2017-07-12 10:51:46] executable=/Users/gozala/.config/yarn/global/node_modules/flow-bin/flow-osx-v0.49.1/flow
[2017-07-12 10:51:46] version=0.49.1
[2017-07-12 10:51:46] Parsing
[2017-07-12 10:51:56] Building package heap
[2017-07-12 10:51:56] Loading libraries
[2017-07-12 10:52:01] Resolving dependencies
[2017-07-12 10:52:02] Running local inference
[2017-07-12 10:52:02] Calculating dependencies
[2017-07-12 10:52:02] Merging
[2017-07-12 10:52:02] Done
Found 0 errors |
I honestly would much rather have flow request explicit annotation rather than waiting forever on for flow to infer types. At least that way it's clear what the source is and is a lot easier to find a workaround and move on. |
Looks like I have the same problem. My minimal demo repo: https://github.com/vith/flow-implosion-demo Note that I also reduced If you wait long enough (about 3 minutes on my system) a subprocess will fill up 20GB of memory and die, at which point the cli process simply prints But the log file contains:
|
This helped me find the error in my own application, after lot's of trial and error. The original code is much more complex, but here is the absolute minimal example that still hangs on 'merging inference': // @flow
export const checkComponent = (obj: any[]): Object[] =>
obj.reduce((acc, x) => {
if (x === undefined) {
return [...acc, {}];
}
if (x === 'hi') {
return [...acc, {}];
}
if (x.err) {
return [...acc, {}];
}
return acc;
}, []); Either removing one branch (if-statement), or adding type annotation to the inline function (reduce), makes flow work again. |
This seems to be rather prominent in the issues. Maybe related issues found after a five minute search:
|
Having same issue, need to type flow functions for it to work. |
Summary: When evaluating spreads inside an array literal, we would "finish" the array type with a different element type for each type that was being spread. This effectively created a "union of array types" instead of a single array type, which could be fanned into an exponential blowup, or worse, an infinite loop, by a suitably crafted cycle in the constraint graph. Now we pin the element type early and thread it through so that we can always "finish" with that element type. Fixes #4070 Fixes #4370 Reviewed By: samwgoldman Differential Revision: D7416763 fbshipit-source-id: 7de51c426df341da9916c99a6e1eba0aec35a8fd
Here is somewhat minimal example. I'm sure it could be reduced further, but given that flow takes over my machine when it attempts to type check this it's really difficult and it took me half a day yesterday to find to reduce it this from a much larger code
Here is output I get from flow:
Also worth noting that it chokes on usage of a
merge
if it's not used it seems to do fine.The text was updated successfully, but these errors were encountered: