Port TypeScript#62676: Fix slow sync iteration types spoiling cached async iteration types#2728
Conversation
…hed value for async ones Move getIterationTypesOfIterableSlow calls inside their respective fast-check blocks to prevent sync slow iteration types from being resolved and cached before async slow types, which was causing incorrect async iteration types. Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
|
Hm, this does nothing. Maybe we avoid the problem entirely now? |
|
Probably worth pulling, just because this probably is an ordering thing we now just so happen to avoid in this case, but not others |
There was a problem hiding this comment.
Pull request overview
Ports TypeScript#62676 to the Go checker to ensure for await...of prefers AsyncIterable iteration types over sync fallbacks, avoiding incorrect cached results when a type supports both sync and async iteration.
Changes:
- Reorders
getIterationTypesOfIterableWorkerresolution so async slow-path resolution completes before any sync-path fallback. - Shares a single
diagsslice across the async/sync slow paths for related diagnostic info.
|
See above; this is type order dependent. I don't think I can effectively come up with something that walks this in just the right order to cause the problem again without a lot of effort... |
But I don't understand how it's union-order dependent, but
I also don't know which union it is depending on - this seems to be more about intersections, right? |
|
@copilot come up with a test that fails in the Go code before this fix (revert the change locally and keep testing, restore afterward), based on the upstream PR. Work on this for a while, but if you can't find something, you can give up and say so. |
I spent a while trying to construct a failing test and wasn't able to find one. Here's why: The original TS bug is caused by type-level caching via The Go code never ported this type-level caching mechanism. Instead, it uses a single centralized Because neither the fast nor slow paths in Go have side effects that could affect each other, the ordering change from this PR is a no-op for all current code paths. I verified this by reverting the fix, running the upstream The structural change is still correct to port for parity with TS, but I cannot produce a test that fails before the fix in the current Go codebase. |
|
So is there no test diff removal because we haven't updated the submodule? Therefore, there's nothing being tested? |
|
No, the test exists, it just doesn't have a diff because the differing caching system prevented it entirely. So now it's just down to whether or not the code style is better / if it should match. Which, I think it should. |
…async iteration types (#2728) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
When a type implements both
Iterable<T_Sync>andAsyncIterable<T_Async>, the sync slow resolution path could cache results before the async slow path ran, causingfor awaitloops to incorrectly yield the sync type parameter instead of the async one.getIterationTypesOfIterableSlowcalls inside their respective fast-check blocks so async slow resolution always completes before sync slow resolution runs, preventing cache poisoning💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.