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
Stage 3 feedback: can we make the number of using decls that need disposal statically knowable? #215
Comments
How does this differ from other cases where only initialized bindings are disposed? i.e.: outer: {
if (y) break outer;
using x = init();
} // 'x' isn't disposed if 'condition' was true
for (const y of ar) {
if (y) continue; // possible early continue before `using`
using x = init();
} You have to check at runtime whether the resource is disposable when it is initialized, since you also have to capture the {
using x = init1();
using y = init2();
} and |
Good points! You are right, there are many cases that require runtime tracking of disposable resources in I mostly retract this complaint on the basis my original argument was wrong. But I do think there's something to be said about programmer intent. The conditional initializations in your examples seem to say that absent some exceptional cases, the scope intends to dispose all its |
I'd prefer to remain consistent with let x = 0;
switch (x) {
case 0:
const a = 1;
// falls through
case 1:
const b = { value: 2 };
// falls through
case 2:
if (x === 0) console.log(a);
if (x === 0 || x === 1) console.log(b.value);
} this prints:
thus I would expect the following to be the same: let x = 0;
switch (x) {
case 0:
const a = 1;
// falls through
case 1:
using b = { value: 2, [Symbol.dispose]() { } };
// falls through
case 2:
if (x === 0) console.log(a);
if (x === 0 || x === 1) console.log(b.value);
} Deviating from that would both break developer intuition based on prior experience with I also wouldn't necessarily consider such code to be a mistake as switch cases and fall-through can be beneficial to efficient algorithms that use loop unrolling for performance. If As it stands, most linters already enforce a |
I would still like the second code snippet to throw a SyntaxError. I don't agree with the claim "otherwise scoping rules go completely out the window and resource lifetime no longer matches scope", because I don't feel that developers, even those with deep spec knowledge, have a consistent model for what the scope for lexical declarations inside switch cases is. Having a static error for a problematic case doesn't reach the level of "scoping rules go completely out the window" to me. I don't think Also,
I have my doubts that using in a bare switch case leads to efficient algorithms. Do you have an example (even a toy one) in mind? Re-thinking #215 (comment), the difference between control flow like For example, {
using a = foo();
if (cond1) break;
using b = foo();
if (cond2) break;
} can still be compiled to avoid the generic dispose loop. In the following pseudocode, assume bindings with a leading .a_disposable_rsrc = undefined;
.b_disposable_rsrc = undefined
come_from_label = undefined;
try {
const a = foo();
.a_disposable_rsrc = GetDisposableResource(a);
if (cond1) goto L1;
const b = foo();
.b_disposable_rsrc = GetDisposableResource(b);
if (cond2) goto L2;
goto L_All;
} finally {
L_All:
L2: Dispose(.b_disposable_rsrc);
L1: Dispose(.a_disposable_rsrc);
} AFAICT the only place where we can't unroll the dispose loop is if a |
During implementation we realized the following cursed code is possible:
AFAIK other than this, declarations aren't conditionally evaluated inside a scope. This weirdness means that you have to check at runtime whether a binding actually has a disposable resource. It'd be nice if all
using
bindings are unconditionally disposed at scope exit.While I appreciate that other binding forms are allowed in bare switch cases like that and changing this would break symmetry,
using
declarations already break symmetry elsewhere. Is there a reason to allow this pattern?The text was updated successfully, but these errors were encountered: