Skip to content

refactor(all): add [<return: Struct>] to partial active patterns#4658

Open
dbrattli wants to merge 1 commit into
mainfrom
fix/ionide-009-struct-active-patterns
Open

refactor(all): add [<return: Struct>] to partial active patterns#4658
dbrattli wants to merge 1 commit into
mainfrom
fix/ionide-009-struct-active-patterns

Conversation

@dbrattli

Copy link
Copy Markdown
Collaborator

Summary

Resolves all open IONIDE-009 code scanning alerts ("Consider adding [<return: Struct>] to partial active pattern") in src/Fable.Transforms. Converts 73 partial active patterns to struct-returning (ValueOption) form across 9 files.

Struct active patterns avoid the heap allocation of Option on every pattern match, which matters in the hot compiler paths these patterns sit on (replacements, AST transforms).

What changed

For each flagged pattern: added [<return: Struct>] and changed only the return-position values to ValueSome/ValueNone. Nested option match patterns (e.g. { FieldType = Some t }), inner option plumbing, and cross-pattern/recursive calls in pattern position were left untouched. Where a pattern's result came from a helper returning a plain option, it is bridged with an explicit match or ValueOption.ofOption.

File Patterns
FSharp2Fable.Util.fs 19
Replacements.Util.fs 21
Transforms.Util.fs 14
Replacements.fs 5
Global/Prelude.fs 4
Fable2Babel.fs 4
Global/Naming.fs 3
FableTransforms.fs 2
Python/Replacements.fs 1

(|CustomOp|_|) is also invoked as a plain function (not in pattern position) at two sites in Beam/Replacements.fs; those matches are adapted to the new voption result.

Intentionally skipped

Tags.(|Contains|_|) at src/Fable.AST/Fable.fs:12 (1 alert) is not changed — Fable.AST is the public AST and switching an active pattern's return type from Option to ValueOption is a binary-breaking change requiring a major version bump (per AGENTS.md).

Verification

dotnet build src/Fable.Cli/Fable.Cli.fsproj -c Release (covers all targets — JS/TS, Python, Rust, Dart, BEAM) succeeds with 0 warnings, 0 errors.

🤖 Generated with Claude Code

Convert 73 partial active patterns across the compiler transforms to
struct-returning (ValueOption) form, resolving all open IONIDE-009 code
scanning alerts in src/Fable.Transforms. Only return-position values were
changed to ValueSome/ValueNone; nested option match patterns and inner
option plumbing are left intact (bridged with explicit matches or
ValueOption.ofOption where a helper produced a plain option).

The (|CustomOp|_|) pattern is also invoked as a plain function in
Beam/Replacements.fs; those two call sites are adapted to the new voption
result.

Fable.AST/Fable.fs is intentionally not touched: changing a public AST
active pattern's return type is a binary-breaking change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dbrattli dbrattli changed the title refactor(transforms): add [<return: Struct>] to partial active patterns refactor(all): add [<return: Struct>] to partial active patterns Jun 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Python Type Checking Results (Pyright)

Metric Value
Total errors 34
Files with errors 4
Excluded files 4
New errors ✅ No
Excluded files with errors (4 files)

These files have known type errors and are excluded from CI. Remove from pyrightconfig.ci.json as errors are fixed.

File Errors Status
temp/tests/Python/test_hash_set.py 18 Excluded
temp/tests/Python/test_applicative.py 12 Excluded
temp/tests/Python/test_nested_and_recursive_pattern.py 2 Excluded
temp/tests/Python/fable_modules/thoth_json_python/encode.py 2 Excluded

@dbrattli dbrattli requested review from MangelMaxime and ncave June 13, 2026 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant