Spurious "referenced directly or indirectly in its own initializer" when combined with narrowing, asserts function, and loop
Bug Report
🔎 Search Terms
referenced directly or indirectly asserts
🕗 Version & Regression Information
- This is the behavior in every version I tried
⏯ Playground Link
💻 Code
declare const myRequire: ((p: string) => {} | undefined) | undefined;
declare function assertIsDefined<T>(value: T): asserts value is NonNullable<T>
function fn1() {
if (!myRequire) {
return;
}
for (const p of ["a", "b"]) {
// Error?
const result = myRequire("something");
assertIsDefined(result);
}
}
🙁 Actual behavior
result is claimed to be referenced directly or indirectly in its initializer.
Modifying the code in various ways makes the error go away.
🙂 Expected behavior
No error; there's no relationship between the initializer and the result.
Here's what happens:
checkVariableLikeDeclarationcall forresultvariable.getTypeOfSymbolforresultvariable.- Type is inferred from initializer, so
checkExpressionformyRequire("something"). getFlowTypeOfReferenceformyRequire.getTypeAtFlowLoopLabelfor back edge of loop.getEffectsSignatureforassertIsDefined(result)call.inferTypeArgumentsfor that call.checkExpressionforresultargument.getTypeOfSymbolforresultvariable.- Circularity!
We probably could be a bit smarter about realizing that none of the arguments in the assertIsDefined(result) call match the reference (myRequire) for which we are currently doing CFA.
I'm noticing an odd "referenced directly or indirectly in its own initializer" error in my code. Wondering if you can help confirm whether this is the same issue or a separate one?
Not sure if this is the same case but my problem looks also very similar: Playground link
In case somebody wonders about the strange "initial buffer" location: The code originates from some audio generation where I get chunks of audio and dynamically size the buffer initially. I get the estimated audio sample count as part of the initial chunk.