Skip to content
1 change: 1 addition & 0 deletions eng/known-domains.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ github.com/dotnet/diagnostics
github.com/dotnet/dotnet
github.com/dotnet/dotnet-docker
github.com/dotnet/efcore
github.com/dotnet/fsharp
github.com/dotnet/maui
github.com/dotnet/msbuild
github.com/dotnet/roslyn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: >
NOT for writing new programs.
USE FOR: upgrading TargetFramework from net10.0 to net11.0, fixing build errors
after updating the .NET 11 SDK, resolving source-breaking and behavioral changes
in .NET 11 runtime, C# 15 compiler, and EF Core 11, adapting to updated minimum
in .NET 11 runtime, C# 15 / F# 11 compiler, and EF Core 11, adapting to updated minimum
hardware requirements (x86-64-v2, Arm64 LSE), and updating CI/CD pipelines and
Dockerfiles for .NET 11.
DO NOT USE FOR: .NET Framework migrations, upgrading from .NET 9 or earlier,
Expand All @@ -26,7 +26,7 @@ Migrate a .NET 10 project or solution to .NET 11, systematically resolving all b
- Resolving build errors or new warnings after updating the .NET 11 SDK
- Adapting to behavioral changes in .NET 11 runtime, ASP.NET Core 11, or EF Core 11
- Updating CI/CD pipelines, Dockerfiles, or deployment scripts for .NET 11
- Fixing C# 15 compiler breaking changes after SDK upgrade
- Fixing C# 15 and F# 11 compiler breaking changes after SDK upgrade

## When Not to Use

Expand All @@ -39,7 +39,7 @@ Migrate a .NET 10 project or solution to .NET 11, systematically resolving all b

| Input | Required | Description |
|-------|----------|-------------|
| Project or solution path | Yes | The `.csproj`, `.sln`, or `.slnx` entry point to migrate |
| Project or solution path | Yes | The `.csproj`, `.fsproj`, `.sln`, or `.slnx` entry point to migrate |
| Build command | No | How to build (e.g., `dotnet build`, a repo build script). Auto-detect if not provided |
| Test command | No | How to run tests (e.g., `dotnet test`). Auto-detect if not provided |
| Project type hints | No | Whether the project uses ASP.NET Core, EF Core, Cosmos DB, etc. Auto-detect from PackageReferences and SDK attributes if not provided |
Expand All @@ -52,7 +52,7 @@ Migrate a .NET 10 project or solution to .NET 11, systematically resolving all b

### Step 1: Assess the project

1. Identify how the project is built and tested. Look for build scripts, `.sln`/`.slnx` files, or individual `.csproj` files.
1. Identify how the project is built and tested. Look for build scripts, `.sln`/`.slnx` files, or individual `.csproj`/`.fsproj` files.
2. Run `dotnet --version` to confirm the .NET 11 SDK is installed. If it is not, stop and inform the user.
3. Determine which technology areas the project uses by examining:
- **SDK attribute**: `Microsoft.NET.Sdk.Web` → ASP.NET Core; `Microsoft.NET.Sdk.WindowsDesktop` with `<UseWPF>` or `<UseWindowsForms>` → WPF/WinForms
Expand All @@ -67,7 +67,7 @@ Migrate a .NET 10 project or solution to .NET 11, systematically resolving all b

### Step 2: Update the Target Framework

1. In each `.csproj` (or `Directory.Build.props` if centralized), change:
1. In each `.csproj`/`.fsproj` (or `Directory.Build.props` if centralized), change:
```xml
<TargetFramework>net10.0</TargetFramework>
```
Expand All @@ -85,16 +85,7 @@ Migrate a .NET 10 project or solution to .NET 11, systematically resolving all b

### Step 3: Fix source-breaking and compilation changes

Load reference documents based on the project's technology areas:

| Reference file | When to load |
|----------------|-------------|
| `references/csharp-compiler-dotnet10to11.md` | Always (C# 15 compiler breaking changes) |
| `references/core-libraries-dotnet10to11.md` | Always (applies to all .NET 11 projects) |
| `references/sdk-msbuild-dotnet10to11.md` | Always (SDK and build tooling changes) |
| `references/efcore-dotnet10to11.md` | Project uses Entity Framework Core (especially Cosmos DB provider) |
| `references/cryptography-dotnet10to11.md` | Project uses cryptography APIs or targets macOS |
| `references/runtime-jit-dotnet10to11.md` | Deploying to older hardware or embedded devices |
Load the appropriate reference documents from the Reference Documents table at the end of this skill based on the project's technology areas.

Work through each build error systematically. Common patterns:

Expand Down Expand Up @@ -185,7 +176,8 @@ The `references/` folder contains detailed breaking change information organized

| Reference file | When to load |
|----------------|-------------|
| `references/csharp-compiler-dotnet10to11.md` | Always (C# 15 compiler breaking changes) |
| `references/csharp-compiler-dotnet10to11.md` | Project uses C# (C# 15 compiler breaking changes) |
| `references/fsharp-compiler-dotnet10to11.md` | Project uses F# (F# 11 compiler breaking changes) |
| `references/core-libraries-dotnet10to11.md` | Always (applies to all .NET 11 projects) |
| `references/sdk-msbuild-dotnet10to11.md` | Always (SDK and build tooling changes) |
| `references/efcore-dotnet10to11.md` | Project uses Entity Framework Core (especially Cosmos DB provider) |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# F# 11 Compiler Breaking Changes (.NET 11)

These breaking changes affect F# projects targeting `net11.0` (which uses F# 11 by default). F# 11 ships with the .NET 11 SDK.

> **Note:** .NET 11 is in preview. This covers changes through Preview 1. Additional breaking changes may be introduced in later previews.

## Source-Incompatible Changes

### ML compatibility removal

**Impact: Medium.** F# 11 removes all remaining ML/OCaml compatibility constructs that the compiler has carried since F#'s origins as an OCaml dialect. This is a significant cleanup (~7,000 lines of legacy code removed).

The following are **removed**:
- **Source file extensions:** `.ml` and `.mli` files are no longer recognized as F# source files.
- **Directives:** `#light` and `#indent` directives are removed. (Whitespace-sensitive syntax has been the default for many years.)
- **Compiler flags:** `--mlcompatibility`, `--light`, `--indentation-syntax`, `--no-indentation-syntax`, and `--ml-keywords` are all removed.
- **Reserved keywords released:** `asr`, `land`, `lor`, `lsl`, `lsr`, and `lxor` — previously reserved for ML compatibility — are now available as regular identifiers.

```fsharp
// BREAKS — .ml file extension
// Rename MyModule.ml → MyModule.fs
// Rename MyModule.mli → MyModule.fsi

// BREAKS — #light directive
#light "off" // error: directive no longer recognized

// FIX — simply remove the directive (whitespace-sensitive syntax is the default)
```

**Fix:**
1. Rename any `.ml` files to `.fs` and `.mli` files to `.fsi`.
2. Remove all `#light` and `#indent` directives from source files.
3. Remove `--mlcompatibility` and related flags from project files, build scripts, and CI configurations.
4. If you used `asr`, `land`, `lor`, `lsl`, `lsr`, or `lxor` as escaped identifiers (e.g., `` ``asr`` ``), you can now use them as plain identifiers.

See also: [dotnet/fsharp#19143](https://github.com/dotnet/fsharp/pull/19143)

## Performance Improvements (non-breaking)

### Parallel compilation enabled by default

Parallel compilation (preview in F# 10) is now enabled by default for all projects. This includes parallel reference resolution, graph-based type checking, parallel optimizations, and parallel IL code generation.

If you encounter issues, opt out with the `--parallelcompilation-` compiler flag.

### Faster compilation of computation expression-heavy code

The compiler's stack-overflow prevention mechanism (`StackGuard`) has been replaced with `RuntimeHelpers.TryEnsureSufficientExecutionStack()`, significantly reducing thread creation for deeply nested computation expressions (e.g., `task { }`, `async { }`).
28 changes: 8 additions & 20 deletions plugins/dotnet-upgrade/skills/migrate-dotnet8-to-dotnet9/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ name: migrate-dotnet8-to-dotnet9
description: >
Migrate a .NET 8 project to .NET 9 and resolve all breaking changes.
USE FOR: upgrading TargetFramework from net8.0 to net9.0, fixing build errors
after updating the .NET 9 SDK, resolving behavioral changes in .NET 9 / C# 13 /
after updating the .NET 9 SDK, resolving behavioral changes in .NET 9 / C# 13 / F# 9 /
ASP.NET Core 9 / EF Core 9, replacing BinaryFormatter (now always throws),
resolving SYSLIB0054-SYSLIB0057, adapting to params span overload resolution,
fixing C# 13 compiler changes, updating HttpClientFactory for SocketsHttpHandler,
fixing C# 13 / F# 9 compiler changes, updating HttpClientFactory for SocketsHttpHandler,
and resolving EF Core 9 migration/Cosmos DB changes.
DO NOT USE FOR: .NET Framework migrations, upgrading from .NET 7 or earlier,
greenfield .NET 9 projects, or cosmetic modernization unrelated to the upgrade.
Expand Down Expand Up @@ -35,7 +35,7 @@ Migrate a .NET 8 project or solution to .NET 9, systematically resolving all bre

| Input | Required | Description |
|-------|----------|-------------|
| Project or solution path | Yes | The `.csproj`, `.sln`, or `.slnx` entry point to migrate |
| Project or solution path | Yes | The `.csproj`, `.fsproj`, `.sln`, or `.slnx` entry point to migrate |
| Build command | No | How to build (e.g., `dotnet build`, a repo build script). Auto-detect if not provided |
| Test command | No | How to run tests (e.g., `dotnet test`). Auto-detect if not provided |
| Project type hints | No | Whether the project uses ASP.NET Core, EF Core, WinForms, WPF, containers, etc. Auto-detect from PackageReferences and SDK attributes if not provided |
Expand All @@ -48,7 +48,7 @@ Migrate a .NET 8 project or solution to .NET 9, systematically resolving all bre

### Step 1: Assess the project

1. Identify how the project is built and tested. Look for build scripts, `.sln`/`.slnx` files, or individual `.csproj` files.
1. Identify how the project is built and tested. Look for build scripts, `.sln`/`.slnx` files, or individual `.csproj`/`.fsproj` files.
2. Run `dotnet --version` to confirm the .NET 9 SDK is installed. If it is not, stop and inform the user.
3. Determine which technology areas the project uses by examining:
- **SDK attribute**: `Microsoft.NET.Sdk.Web` → ASP.NET Core; `Microsoft.NET.Sdk.WindowsDesktop` with `<UseWPF>` or `<UseWindowsForms>` → WPF/WinForms
Expand All @@ -63,7 +63,7 @@ Migrate a .NET 8 project or solution to .NET 9, systematically resolving all bre

### Step 2: Update the Target Framework

1. In each `.csproj` (or `Directory.Build.props` if centralized), change:
1. In each `.csproj`/`.fsproj` (or `Directory.Build.props` if centralized), change:
```xml
<TargetFramework>net8.0</TargetFramework>
```
Expand All @@ -83,20 +83,7 @@ Migrate a .NET 8 project or solution to .NET 9, systematically resolving all bre

### Step 3: Resolve build errors and source-incompatible changes

Work through compilation errors and new warnings systematically. Load the appropriate reference documents based on the project type:

| If the project uses… | Load reference |
|-----------------------|----------------|
| Any .NET 9 project | `references/csharp-compiler-dotnet8to9.md` |
| Any .NET 9 project | `references/core-libraries-dotnet8to9.md` |
| Any .NET 9 project | `references/sdk-msbuild-dotnet8to9.md` |
| ASP.NET Core | `references/aspnet-core-dotnet8to9.md` |
| Entity Framework Core | `references/efcore-dotnet8to9.md` |
| Cryptography APIs | `references/cryptography-dotnet8to9.md` |
| System.Text.Json, HttpClient, networking | `references/serialization-networking-dotnet8to9.md` |
| Windows Forms or WPF | `references/winforms-wpf-dotnet8to9.md` |
| Docker containers, native interop | `references/containers-interop-dotnet8to9.md` |
| Runtime configuration, deployment | `references/deployment-runtime-dotnet8to9.md` |
Work through compilation errors and new warnings systematically. Load the appropriate reference documents from the Reference Documents table at the end of this skill based on the project type.

**Common source-incompatible changes to check for:**

Expand Down Expand Up @@ -219,7 +206,8 @@ The `references/` folder contains detailed breaking change information organized

| Reference file | When to load |
|----------------|-------------|
| `references/csharp-compiler-dotnet8to9.md` | Always (C# 13 compiler breaking changes — InlineArray on records, iterator safe context, collection expression overloads) |
| `references/csharp-compiler-dotnet8to9.md` | Project uses C# (C# 13 compiler breaking changes — InlineArray on records, iterator safe context, collection expression overloads) |
| `references/fsharp-compiler-dotnet8to9.md` | Project uses F# (F# 9 compiler breaking changes) |
| `references/core-libraries-dotnet8to9.md` | Always (applies to all .NET 9 projects) |
| `references/sdk-msbuild-dotnet8to9.md` | Always (SDK and build tooling changes) |
| `references/aspnet-core-dotnet8to9.md` | Project uses ASP.NET Core |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# F# 9 Compiler Breaking Changes (.NET 9)

These breaking changes affect F# projects targeting `net9.0` (which uses F# 9 by default). F# 9 ships with the .NET 9 SDK.

## Source-Incompatible Changes

### Auto-generated `.Is*` properties on discriminated unions

**Impact: Medium.** F# 9 auto-generates `.Is*` properties for each case of a discriminated union. If you already defined custom `Is*` properties or members with the same names, a conflict will occur.

```fsharp
// BREAKS — custom property conflicts with auto-generated one
type Shape =
| Circle of radius: float
| Rectangle of width: float * height: float
member this.IsCircle = // now conflicts with auto-generated IsCircle
match this with Circle _ -> true | _ -> false
```

**Fix:** Remove the custom `Is*` members — the compiler-generated versions provide the same functionality.

### Struct unions with overlapping fields and reflection

**Impact: Low–Medium.** In FSharp.Core 9.0, struct unions with overlapping fields now generate detailed internal mappings to support correct reading via reflection. Code or libraries using `FSharpValue.GetUnionFields` or similar reflection APIs on struct unions may see different behavior or exceptions if they relied on the previous incomplete mapping.

**Fix:** Update libraries that reflect over struct unions. The new mapping is more complete and correct.

### `ArgumentOutOfRangeException` for collection index out-of-bounds

**Impact: Low.** Accessing an out-of-bounds index in FSharp.Core collections (e.g., `Array`, `List`) now throws `System.ArgumentOutOfRangeException` instead of `System.ArgumentException` in some cases. If your exception-handling code specifically catches `ArgumentException` and not `ArgumentOutOfRangeException`, update it.

```fsharp
// Before: threw ArgumentException in some cases
// After: throws ArgumentOutOfRangeException
try
let _ = [1; 2; 3].[10]
()
with
| :? System.ArgumentOutOfRangeException -> () // update catch patterns
```

## New Language Features (non-breaking but relevant)

### Nullable reference type support (opt-in)

F# 9 adds support for nullable reference types, but this is **off by default**. Enable with `<Nullable>enable</Nullable>` in the `.fsproj` file. Enabling this may surface new warnings about null usage in existing code.

### `_.Property` shorthand for member access in lambdas

F# 9 introduces `_.Property` shorthand syntax in pipelines:
```fsharp
customers |> List.map _.Name
```

This is purely additive and does not break existing code.
Loading