fsharp / fsharp/fslang-suggestions
[Suggestion] Compile-time warning when stackalloc is inlined into a for...in seq loop (hidden try/finally)
- Dominant language
- No language data
- Stars
- 373
- Forks
- 21
- PR merge metrics
- No merged PRs in 30d
Description
I was surprised after stack allocation causing me troubles in for x in ... so I am submitting this issue in good faith
---
**I propose we** emit a compile-time warning (or error) when an `inline` function that performs `stackalloc` (and returns the resulting `Span`) is inlined into a `for x in seq do` loop body. Currently this silently produces invalid IL that fails at runtime with `System.InvalidProgramException`, with no diagnostic at compile time.
**The existing way of approaching this problem in F# is** to discover it at runtime. F# compiles `for x in seq do` into a `while` loop over an enumerator wrapped in a hidden `try/finally` (to guarantee `enumerator.Dispose()` runs). When an `inline` function containing `stackalloc` (the IL `localloc` instruction) is inlined into that loop body, the `localloc` lands inside the protected region. Per ECMA-335, `localloc` is not permitted inside a `try`/`finally` region, so the JIT rejects the whole method at compile time and throws `InvalidProgramException` — before a single line of the method body executes. There is no compile-time warning; the failure only appears when the program runs.
## Pros and Cons
**The advantages of making this adjustment to F# are** that a confusing, runtime-only failure becomes a clear, actionable compile-time diagnostic. The hidden `try/finally` is invisible in source (the user never writes a `try` block), so the current behavior is genuinely surprising. A warning would save developers from a non-obvious debugging session and would document the interaction between `stackalloc`, `inline`, and `for...in seq` that is currently absent from the docs.
**The disadvantages of making this adjustment to F# are** that it adds a new diagnostic that must be maintained, and there is a small risk of false positives if the compiler cannot always determine whether a `stackalloc` will actually be inlined into a protected region. It also does not fix the underlying IL limitation — it only surfaces it earlier.
## Extra information
**Estimated cost (XS, S, M, L, XL, XXL):** S — the diagnostic is localized to the inliner/loop codegen and does not change the language semantics.
**Related suggestions:** (none found — this appears to be a novel gap; the C# docs document the `stackalloc`-in-`try` restriction more explicitly, but F# has no equivalent user-facing documentation)
## Affidavit (please submit!)
Please tick these items by placing a cross in the box:
* [x] This is not a question (e.g. like one you might ask on [StackOverflow](http://stackoverflow.com)) and I have searched StackOverflow for discussions of this issue
* [x] This is a language change and not purely a tooling change (e.g. compiler bug, editor support, warning/error messages, new warning, non-breaking optimisation) belonging to [the compiler and tooling repository](https://github.com/dotnet/fsharp)
* [x] This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it
* [x] I have [searched both open and closed suggestions on this site](http://github.com/fsharp/fslang-suggestions/issues) and believe this is not a duplicate
Please tick all that apply:
* [x] This is not a breaking change to the F# language design
* [ ] I or my company would be willing to help implement and/or test this
---
## For Readers
If you would like to see this issue implemented, please click the :+1: emoji on this issue. These counts are used to generally order the suggestions by engagement.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in the F# compiler's inliner and loop code-generation paths, and reproduce the described inline stackalloc inside a for...in seq loop. Trace how the hidden try/finally is emitted; done means the invalid protected-region case receives a compile-time diagnostic instead of only failing with InvalidProgramException at runtime.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- fsharp
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100