Skip to content

WIP/Experiment: runtime-ified task builder via new ConditionalAutoOpen - #20918

Draft
T-Gro wants to merge 10 commits into
mainfrom
t-gro-conditional-autoopen-production
Draft

T-Gro wants to merge 10 commits into
mainfrom
t-gro-conditional-autoopen-production

Conversation

@T-Gro

@T-Gro T-Gro commented Nov 3, 2026

Copy link
Copy Markdown
Member

Description

Experiment for fsharp/fslang-suggestions#1473: FSharp.Core ships a runtime-async task/taskSeq that a project opts into through an ordinary compiler flag, without renaming task or editing any source file. Includes #20870.

Attributes (repeatable, assembly-level only, preview language)

  • [<assembly: ConditionalAutoOpen("Some.Module", "--features:runtime-async=on")>] opens the path when the condition is present.
  • [<assembly: RetractExistingAutoopen("Some.Module", "<condition>")>] removes an ordinary assembly AutoOpen of that path. Module-level [<AutoOpen>], explicit open and qualified access are unaffected.
  • The condition is one complete compiler option, matched exactly: no parsing, no case folding, no aliases. --features:other=1,runtime-async=on does not match --features:runtime-async=on.
  • Older compilers ignore the new attributes and keep the classic behavior.

Selection runs once, before type checking; the existing auto-open pipeline still receives a plain path list:

type AssemblyAutoOpen =
    | OrdinaryAutoOpen of path: string
    | ConditionalAutoOpen of path: string * condition: string
    | RetractAutoOpen of path: string * condition: string

CLI flag / project property (same shape as C#)

  • fsc --features:runtime-async=on, mirroring csc /features:runtime-async=on.
  • <Features>$(Features);runtime-async=on</Features>, the same MSBuild property C# uses, so one Directory.Build.props line covers mixed C#/F# solutions. Each item becomes one --features: option; changing Features invalidates incremental compilation.

Conditional shadowing

  • FSharp.Core adds Microsoft.FSharp.Control.RuntimeAsync.TaskExpressions (task, taskSeq; .NET 11+) and declares ConditionalAutoOpen("Microsoft.FSharp.Control.RuntimeAsync.TaskExpressions", "--features:runtime-async=on") after the existing Microsoft.FSharp.Control auto-open.
  • With the flag, the later open shadows the classic task by ordinary name resolution; without it, nothing changes. The classic TaskBuilder is not retracted: backgroundTask, open Microsoft.FSharp.Control.TaskBuilderModule and fully qualified names still reach it.

Checklist

  • Test cases added
  • Performance benchmarks added in case of performance changes
  • Release notes entry updated

majocha and others added 7 commits October 27, 2026 01:08
…suspending handlers

A try/with handler or try/finally compensation that suspends is moved out
of its exception-handling region. The rewrite recorded the body's outcome
in a Choice<'T, exn>, allocated on every run including success, and
rethrew a pending exception with a plain throw, which reset its stack
trace. This affected a suspending finally (including use of an
IAsyncDisposable), reraise () after a suspension, and an unmatched
handler pattern.

* Record the body's result and the pending exception in two locals; the
  exception stays null when the body succeeds, so nothing is allocated.
* Rethrow with ExceptionDispatchInfo.Capture(exn).Throw(). The helper moves
  from LowerAsyncSeq into RuntimeAsyncExceptionRewrite and is shared;
  the rewrite now receives the import map.
* Tests for stack traces and success-path allocation; update the IL
  fragments of the composed CE test and pin the rethrow.
* Docs and release notes.
FSharp.Core adds repeatable ConditionalAutoOpen(path, condition) and
RetractExistingAutoopen(path, condition) assembly attributes. A condition
matches one complete compiler CLI token exactly (preview language only).
Selection runs once before type checking and passes the existing pipeline
an ordinary list of assembly auto-open paths. Retraction affects only
assembly-level AutoOpen entries.

The compiler accepts opaque --features:<string> options. FSharp.Build
passes each MSBuild Features item as --features:<item> and invalidates
incremental compilation when Features or OtherFlags change.

FSharp.Core (net) adds Microsoft.FSharp.Control.RuntimeAsync TaskBuilder,
TaskSeqBuilder and TaskExpressions.task/taskSeq. They are auto-opened for
--features:runtime-async=on and need .NET 11 or later at run time.
Builder behavior tests move to FSharp.Core.UnitTests and use the shipped
builders; the test-side builder copies are removed.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Decode conditional assembly attributes in CompilerImports and the
  in-memory reference reader through one name pattern; leave the
  attribute helpers and well-known flags unchanged.
- Ignore malformed conditional attributes like AutoOpen(null); remove
  diagnostic 3926.
- Read the FSI session config from TcImports so RequireReferences keeps
  its signature.
- Cache only Features for incremental builds, hashed case-sensitively.
- Drop runtimeasync.fsi; the public surface is unchanged.
- Keep moved builder tests close to their originals and drop duplicate,
  qualification-only and unrelated test changes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…location)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

✅ Release notes checked


✅ Found changes and release notes in following paths:

Change path Release notes path Description
`src/FSharp.Core` docs/release-notes/.FSharp.Core/11.0.200.md
`src/Compiler` docs/release-notes/.FSharp.Compiler.Service/11.0.200.md
`src/Compiler/Facilities/LanguageFeatures.fsi` docs/release-notes/.Language/preview.md

T-Gro and others added 3 commits November 3, 2026 13:15
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…toOpen tests on .NET only

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

2 participants