Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/instructions/FSharp.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ When the IDE's F# semantic tools are unavailable, use the `F#` MCP server (`.mcp

## Values and types

- `voption` – `ValueSome`/`ValueNone` – over `option`; it is this compiler's option type. Fields, members, parameters and values shared between threads included: none of them is a reason to pick `option`. Exception: when an API hands you `'T option` and has no `voption` counterpart, unwrap with `Option.defaultValue`/`Option.defaultWith` directly – do not insert `ValueOption.ofOption` just to switch modules.
- `voption` – `ValueSome`/`ValueNone` – over `option`; it is this compiler's option type. Exception: when an API hands you `'T option` and has no `voption` counterpart, unwrap with `Option.defaultValue`/`Option.defaultWith` directly – do not insert `ValueOption.ofOption` just to switch modules.
- A field one thread writes without a lock and another reads needs an *atomic-sized* write, not `voption`'s style. `'T option` is always a single reference (atomic on any width); `'T voption` is a struct that grows with `'T` and can span more than one word – for a `'T` already close to a full word (like `Position`'s `[<Struct>]` `int64`, where the voption tag pads it past one), a torn write is possible. Use `'T option` for such a field specifically, and only for it – a local binding built from it, never touched by another thread, stays `voption` as always.
- The mirror case, an API that *takes* `'T option` (an optional argument `?caret = …`, a field typed `IDisposable option`): stay in `ValueOption` through the whole chain and convert once, last – `x |> ValueOption.bind _.Position |> ValueOption.toOption`, never `x |> ValueOption.toOption |> Option.bind _.Position`.
- `vsintegration` has `voption`-returning counterparts of the FSharp.Core collection functions, suffixed `V`, in `FSharp.Editor/Common/Extensions.fs`: `Seq.tryHeadV`/`tryFindV`/`tryFindIndexV`/`tryPickV`/`chooseV`, `Array.tryHeadV`/`tryFindV`/`tryPickV`/`chooseV`, `List.tryFindV`, `ImmutableArray.tryHeadV`. Reach for those rather than the `option`-returning original. The module is `[<AutoOpen>]` and compiles before the rest of `FSharp.Editor`, so a file in the `Microsoft.VisualStudio.FSharp.Editor` namespace needs no `open` for them. `src/Compiler` has no equivalents.
- `struct ('T1 * 'T2)` tuples and `[<Struct>]` types on allocation-sensitive paths.
Expand Down
Loading