Diagnose or hoist NativePtr.stackalloc where localloc is invalid IL - #20491
Diagnose or hoist NativePtr.stackalloc where localloc is invalid IL#20491T-Gro wants to merge 8 commits into
Conversation
NativePtr.stackalloc emits the 'localloc' IL instruction, which the JIT rejects inside an exception-handling region, causing InvalidProgramException at method load. Detect this during PostInferenceChecks and emit compile-time error FS3916 when stackalloc is applied inside a 'with' handler or 'finally' block. A withinHandler env flag is set on the handler/finally bodies and reset at closure and method boundaries so stackalloc in a lambda or object-expression method defined in a handler stays legal. Part of issue #20295 (Case 1). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…FS3916) An immediately-applied lambda in a 'try' handler is inlined into the handler's IL region by the optimizer, so its 'localloc' still lands inside the exception-handling region and throws InvalidProgramException under --optimize+. The CheckLambdas 'withinHandler = false' reset was based on the false premise that every lambda becomes a separate method; remove it so lambda bodies inside a handler are conservatively checked. Genuine method boundaries (object-expression/interface methods) keep their reset via CheckMethod and remain legal (verified by compileExeAndRun). Part of issue #20295 (Case 1). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… Case 2) NativePtr.stackalloc used as a chained base-constructor argument emitted 'localloc' while an uninitialized 'this' was pending on the evaluation stack, which the JIT rejects (InvalidProgramException at method load). The uninitialized 'this' cannot be spilled to a local, so the existing spill mechanism could not clear the stack. When a base/self-ctor argument may emit 'localloc', evaluate the arguments into locals first (at a clean stack), then push 'this' and reload them. Left-to-right evaluation order is preserved and ordinary base ctors emit byte-identical IL. The fix is applied in both GenApp and GenILCall. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…0295) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a Fixed release note for the Case-2 base-constructor argument hoist. Verified xlf/surface-area baselines are in sync and formatting is clean; ran full regression (NativeInterop 17/17, Byref 138/138, Language RegressionTests 29/29, SurfaceAreaTest green). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…20295 Case 1) The syntactic PostInferenceChecks detection ran before inlining and closure conversion, so it could not tell an escaping closure (whose 'localloc' lands in its own method and is legal) from an inlined/immediately-applied lambda or a 'let inline' wrapper (whose 'localloc' lands in the handler region and is illegal). This produced both a false positive (rejecting legal escaping closures) and a false negative ('let inline' wrapper compiled and threw InvalidProgramException at load). Detect 'localloc' emission inside a catch/filter/finally/fault region at codegen instead, via a new eenv.withinExnHandler flag set on the handler bodies in GenTryWith/GenTryFinally and reset at method/closure boundaries. By that point inlining and closure conversion have run, so the true exception-handling region is known: escaping closures stay legal, inlined localloc is rejected. The try body keeps 'localloc' legal per ECMA-335. Removes the now-unused withinHandler plumbing and the nativeptr_stackalloc_vref intrinsic. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…20295) The prior commit's test edit stripped the [<Fact>] let header, orphaning the try-body assertion inside the escaping-closure test and breaking the ComponentTests build with FS0020. Restore it as its own Fact. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
❗ Release notes requiredYou can open this PR in browser to add release notes: open in github.dev
Warning No PR link found in some release notes, please consider adding it.
|
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Commit pushed:
|
|
🤖 LabelOps — CI fix. Fixed the net472 component-test failure in commit Merge-tree inspection found no conflicts. Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "southcentralus0.in.applicationinsights.azure.com"See Network Configuration for more information.
|
Fixes #20295
NativePtr.stackallocinside thewithhandler, filter orfinallyblock of atry(directly or via an inlinable lambda) now reports error FS3916 instead of emitting alocallocthat the runtime rejects withInvalidProgramExceptionat method load.NativePtr.stackallocpassed as a chained base-constructor argument no longer produces an assembly that throwsInvalidProgramException; the base-constructor arguments are hoisted into locals before the uninitializedthisis pushed.