Diagnostic for `NativePtr.stackalloc` in positions where `localloc` can never be valid IL
- Dominant language
- F#
- Stars
- 4.3k
- Forks
- 876
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 131
Description
The following snippets are accepted by the F# compiler but throw `System.InvalidProgramException` at load, before any user code runs. Follow-up to #8083 (general case fixed by #20302).
**1. `localloc` in an exception handler**
```fsharp
open Microsoft.FSharp.NativeInterop
try () with _ -> NativePtr.stackalloc 1 |> ignore
```
**2. `localloc` while `this` is uninitialized (chained base constructor)**
```fsharp
open Microsoft.FSharp.NativeInterop
type A(p: nativeptr) = class end
type B() = inherit A(NativePtr.stackalloc 1)
B() |> ignore
```
Suggest rejecting them in `PostInferenceChecks` (dsyme's suggestion on #8083) — a compile-time error instead of an `InvalidProgramException` at JIT time.
Details
Fixed for the general case by #20302: `IlxGen` spills the pending stack, emits `localloc` at an empty stack, then reloads the pending values under the result pointer.
**Case 1 (handler).** The CoreCLR importer rejects `localloc` when `block->hasHndIndex()` (`dotnet/runtime`, `jit/importer.cpp`) — that is, inside a `catch`, `finally`, or `filter` handler, not a `try` body. This is why the `for .. in seq` shape in fsharp/fslang-suggestions#1469 works. `eenv.withinSEH` does not yet separate a handler from a `try` body, so the diagnostic needs a new flag.
**Case 2 (uninitialized `this`).** ECMA forbids spilling an uninitialized `this`, so `EmitLocallocCode` falls back to a plain emit when `uninitializedThisOnStackCount > 0`. The code is a use-after-free regardless: the stack memory dies when the constructor returns. A real fix, instead of a diagnostic, would hoist the base-constructor arguments into locals before `this` is pushed.
Contributor guide
Research direction
Start in PostInferenceChecks and trace the NativePtr.stackalloc path into IlxGen and EmitLocallocCode. Investigate how handler context and uninitializedThisOnStackCount are represented, using the two snippets as reproductions. Done means both invalid localloc positions produce compile-time diagnostics instead of InvalidProgramException at load or JIT time.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- fsharp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100