Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[resolved-env] Another take on type cycles including tparams: pre-pop…
…ulate tparam types Summary: Changelog: [internal] Type cycles including tparams can easily cause problems under our current resolved-env setup. If you don't do any special handling for them, then they will sometimes crash, because the topological sort is not guaranteed to generate an order that will visit the tparams in dependency order. Flagging the cycle as illegal doesn't help, since in principle we should support cyclic types, and even if we drop that principle, we still need to ensure we don't crash in the presence of illegal cycle. In D36912180 (6215ad7), I first tried to fix the problem by weakening the principle of supporting cyclic types and use an `any` type for its dependency when we try to resolve a tparam but its dependency isn't ready. This works well in most cases, but in case that we do want to support, like the module_ref case shown below, this will degrade our accurate too much. ``` type $unwrap = <T>(l: JSResourceReference<T>) => T; class JSResourceReference<+T> { +_moduleId: $Flow$ModuleRef<T>; constructor(moduleId: $Flow$ModuleRef<T>) { this._moduleId = moduleId; } static loadAll<I: Array<JSResourceReference<mixed>>>( loaders: I, callback: (...modules: $TupleMap<I, $unwrap>) => void, ): void { // ...load the modules and then pass them to the callback } } ``` Therefore, in this diff, I decided to take another approach. I will pre-populate the tparams types before resolving all other defs in the same component of resolved-env. This will always succeed and work as expected for the following reasons: 1. Dependency graph of resolving all tparams (according to tparams_locs) will always be a tree by construction. Therefore, we will never run into a cycle if we are resolving tparams alone. 2. Later reads will be guaranteed to read an already populated tparam, also by construction due to how we collect tparams in name_def. When pre-populating the tparam types, we can use whatever order in the name_def graph. When we try to resolve a tparam or its dependency in the map, we can either read it from `Loc_env.tparams`, which stores already computed ones, or by creating one and store it in `Loc_env.tparams`. Reviewed By: mvitousek Differential Revision: D37574157 fbshipit-source-id: d8f36009061e1b4f9c606adb2b0a2869679a8bac
- Loading branch information