Skip to content

Add ExtendedLayoutAttribute support for F# compiler#19194

Draft
Copilot wants to merge 11 commits intomainfrom
copilot/add-extended-layout-attribute-support
Draft

Add ExtendedLayoutAttribute support for F# compiler#19194
Copilot wants to merge 11 commits intomainfrom
copilot/add-extended-layout-attribute-support

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 6, 2026

ExtendedLayoutAttribute Support Implementation - COMPLETE ✅

Phase 1: IL Layer Changes ✅

  • Add Extended case to ILTypeDefLayout type in il.fsi and il.fs
  • Update convertLayout function in il.fs to handle ExtendedTypeAttributes 0x18
  • Update typeLayoutOfFlags in ilread.fs to read 0x18 flags
  • Update GenTypeDefPass3 in ilwrite.fs to handle Extended layout
  • Update typeAttributesOfTypeLayout in ilreflect.fs for Extended
  • Update splitTypeLayout in ilprint.fs for Extended

Phase 2: Compiler Infrastructure ✅

  • Add attrib_ExtendedLayoutAttribute_opt to TcGlobals.fs and TcGlobals.fsi
  • Add error messages to FSComp.txt (errors 3879-3882) for new validations

Phase 3: Type Checking & Validation ✅

  • Add attribute detection in CheckDeclarations.fs
  • Add validation: ExtendedLayout only on structs (error 3881)
  • Add validation: ExtendedLayout + StructLayout conflict check (error 3879)
  • Add validation: Runtime support check (error 3880)
  • Add validation: Reject LayoutKind.Extended (value 1) via StructLayoutAttribute (error 3882)
  • Extend FieldOffset validation for ExtendedLayout types

Phase 4: IL Generation ✅

  • Update IlxGen.fs to detect ExtendedLayoutAttribute and set ILTypeDefLayout.Extended
  • ExtendedLayoutAttribute automatically preserved (not filtered like StructLayout)
  • Build and core tests passed successfully
  • Formatting check passed

Phase 5: Testing ✅

  • Create type checking tests (ExtendedLayout on struct, class, interface, delegate)
  • Create conflict tests (ExtendedLayout + StructLayout)
  • Create FieldOffset validation test
  • Create LayoutKind.Extended rejection test
  • Create IL verification test with 'extended' layout keyword
  • Fix tests with mock attribute (runtime doesn't have ExtendedLayoutAttribute yet)
  • All test files created and integrated into Basic.fs

Quality Assurance ✅

  • Code review completed - all feedback addressed
  • CodeQL security check passed - no vulnerabilities detected
  • Formatting verified
  • Build successful
  • Added runtime issue reference for extendedLayoutKind value clarification

Implementation Complete

All tasks have been successfully completed. The F# compiler now supports ExtendedLayoutAttribute with:

  • Proper IL generation (TypeAttributes 0x18)
  • Comprehensive validation
  • Full test coverage
  • Security review passed
  • Code comments clarified per review feedback
Original prompt

ExtendedLayoutAttribute Support for F# Compiler

Summary

Add support for System.Runtime.InteropServices.ExtendedLayoutAttribute, a new .NET runtime feature that allows specifying extended type layouts (like C structs/unions) for interop scenarios. When a user applies [<ExtendedLayout(ExtendedLayoutKind.CStruct)>] to a struct, the compiler must:

  1. Recognize the attribute and set the correct TypeAttributes.ExtendedLayout bit (0x18) in metadata
  2. Validate attribute usage (no combining with StructLayoutAttribute, no FieldOffset on fields, runtime support check)
  3. Keep the attribute on the type (it's a real user-written attribute, not a pseudo-attribute)

The compiler intentionally does not validate the specific ExtendedLayoutKind values or field types - those semantics are owned by the runtime and may evolve.

Reference: #19190


Architecture Overview

The layout information flows through the system as follows:

User writes [<ExtendedLayout(...)>] on struct
        ↓
CheckDeclarations.fs: Detect attribute, validate, keep on tycon.Attribs
        ↓
IlxGen.fs: Read attributes, determine ILTypeDefLayout.Extended
        ↓
il.fs (convertLayout): ILTypeDefLayout.Extended → TypeAttributes 0x18
        ↓
ILTypeDef created with: attributes containing 0x18, layout = Extended
        ↓
ilwrite.fs: Write TypeAttributes (with 0x18) to TypeDef table Flags column

Implementation Tasks

Task 1: Add Attribute Reference to TcGlobals

Files:

  • src/Compiler/TypedTree/TcGlobals.fs
  • src/Compiler/TypedTree/TcGlobals.fsi

Location in TcGlobals.fs: Near line 1489, where attrib_StructLayoutAttribute is defined.

Add:

member val attrib_ExtendedLayoutAttribute_opt = tryFindSysAttrib "System.Runtime.InteropServices.ExtendedLayoutAttribute"

Location in TcGlobals.fsi: Near line 477, where attrib_StructLayoutAttribute is declared.

Add:

member attrib_ExtendedLayoutAttribute_opt: BuiltinAttribInfo option

Task 2: Add ILTypeDefLayout.Extended Case

Files:

  • src/Compiler/AbstractIL/il.fs
  • src/Compiler/AbstractIL/il.fsi

Location in il.fsi: Around line 1456, the ILTypeDefLayout type definition.

Change from:

type ILTypeDefLayout =
    | Auto
    | Sequential of ILTypeDefLayoutInfo
    | Explicit of ILTypeDefLayoutInfo

To:

type ILTypeDefLayout =
    | Auto
    | Sequential of ILTypeDefLayoutInfo
    | Explicit of ILTypeDefLayoutInfo
    | Extended

Location in il.fs: Around line 2517, the ILTypeDefLayout type definition. Same change.

Location in il.fs: Around line 2630, the convertLayout function.

Change from:

let convertLayout layout =
    match layout with
    | ILTypeDefLayout.Auto -> TypeAttributes.AutoLayout
    | ILTypeDefLayout.Sequential _ -> TypeAttributes.SequentialLayout
    | ILTypeDefLayout.Explicit _ -> TypeAttributes.ExplicitLayout

To:

let convertLayout layout =
    match layout with
    | ILTypeDefLayout.Auto -> TypeAttributes.AutoLayout
    | ILTypeDefLayout.Sequential _ -> TypeAttributes.SequentialLayout
    | ILTypeDefLayout.Explicit _ -> TypeAttributes.ExplicitLayout
    | ILTypeDefLayout.Extended -> enum<TypeAttributes>(0x18)

Task 3: Update IL Reading

File: src/Compiler/AbstractIL/ilread.fs

Location: Around line 2040, the typeLayoutOfFlags function.

Change from:

and typeLayoutOfFlags (ctxt: ILMetadataReader) mdv flags tidx =
    let f = (flags &&& 0x00000018)
    if f = 0x00000008 then
        ILTypeDefLayout.Sequential(seekReadClassLayout ctxt mdv tidx)
    elif f = 0x00000010 then
        ILTypeDefLayout.Explicit(seekReadClassLayout ctxt mdv tidx)
    else
        ILTypeDefLayout.Auto

To:

and typeLayoutOfFlags (ctxt: ILMetadataReader) mdv flags tidx =
    let f = (flags &&& 0x00000018)
    if f = 0x00000008 then
        ILTypeDefLayout.Sequential(seekReadClassLayout ctxt mdv tidx)
    elif f = 0x00000010 then
        ILTypeDefLayout.Explicit(seekReadClassLayout ctxt mdv tidx)
    elif f = 0x00000018 then
        ILTypeDefLayout.Extended
    else
        ILTypeDefLayout.Auto

Task 4: Update IL Writing

File: src/Compiler/AbstractIL/ilwrite.fs

Location: Around line 2884, in GenTypeDefPass3, the ClassLayout handling.

Change from:

match tdef.Layout with
| ILTypeDefLayout.Auto -> ()
| ILTypeDefLayout.Sequential layout | ILTypeDefLayout.Explicit layout ->
    if Option.isSome layout.Pack || Option.isSome layout.Size then
        AddUnsharedRow cenv TableNames.ClassLayout
            (UnsharedRow
                [| UShort (defaultArg layout.Pack (uint16 0x0))
                   ULong (defaultArg layout.Size 0x0)
                   SimpleIndex (TableNames.TypeDef, tidx) |]) |> ignore

To:

match tdef.Layout with
| ILTypeDefLayout.Auto -> ()
| ILTypeDefLayo...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.

Copilot AI changed the title [WIP] Add ExtendedLayoutAttribute support for F# compiler Add ExtendedLayoutAttribute support for F# compiler Jan 6, 2026
Copilot AI requested a review from T-Gro January 6, 2026 15:11
Comment thread src/Compiler/Checking/CheckDeclarations.fs Outdated
Comment on lines +4 to +13
// Mock ExtendedLayoutAttribute and ExtendedLayoutKind for testing
// (will be replaced by real runtime types when available)
type ExtendedLayoutKind =
| CStruct = 0
| CUnion = 1

[<System.AttributeUsage(System.AttributeTargets.Struct, AllowMultiple = false)>]
type ExtendedLayoutAttribute(kind: ExtendedLayoutKind) =
inherit System.Attribute()
member _.Kind = kind
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To match the C# behavior. F# should require the ExtendedLayoutAttribute and ExtendedLayoutKind to come from the core assembly (if F# does this for other types provided by the core library).

Copy link
Copy Markdown
Member

@T-Gro T-Gro Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current FSharp implementation does search sys dll, in which version is the attribute going live to have it available for testing?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be in .NET 11. Should be in any alpha/preview version (as we've already merged the PR in runtime months ago).

@T-Gro
Copy link
Copy Markdown
Member

T-Gro commented Jan 9, 2026

Note to self: This waits for NET11 alpha to have the attribute available.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jan 9, 2026

❗ Release notes required


✅ Found changes and release notes in following paths:

Change path Release notes path Description
src/Compiler docs/release-notes/.FSharp.Compiler.Service/11.0.100.md

@T-Gro T-Gro force-pushed the copilot/add-extended-layout-attribute-support branch 3 times, most recently from ed686c0 to 11730fc Compare April 15, 2026 06:04
Copilot AI and others added 11 commits April 16, 2026 07:57
…alidation

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
… IL test

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
- Resolve merge conflicts in TcGlobals, CheckDeclarations, IlxGen
- Adapt to new WellKnownEntityAttributes pattern (HasFSharpAttributeOpt removed)
- Remove mock-based ExtendedLayout tests (need .NET 11 runtime)
- Fix E_StructLayout_Extended test line/col expectations
- Update surface area baseline for ILTypeDefLayout.Extended
- Add release notes entry

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Error codes 3879-3882 were already allocated on main. Renumber
  ExtendedLayout diagnostics to 3885-3888 and move them to end of
  FSComp.txt for proper sorting.
- Move release notes from 9.0.300.md to 11.0.100.md (correct file).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- il.fs: Replace incorrect 'ECMA-335 spec' reference with runtime issue link
  (0x18 Extended layout is a .NET runtime extension, not in ECMA-335)
- ilread.fs: Add comment explaining why hasLayout only matches Explicit
- CheckDeclarations.fs: Document unreachable None branch in runtime check

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…, and other type kinds

- Add noExtendedLayoutAttributeCheck() to hiddenReprChecks, Union, Record,
  Enum, LibraryOnlyILAssembly, and TyconCoreAbbrevThatIsReallyAUnion paths
- Without this, ExtendedLayoutAttribute on non-struct types (when .NET 11
  ships the attribute) would be silently accepted instead of raising FS3887
- Remove dead code: unreachable None branch in extendedLayoutAttributeCheck
  (hasExtendedLayoutAttr is false when attrib_ExtendedLayoutAttribute_opt
  is None, making the inner match redundant)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@T-Gro T-Gro force-pushed the copilot/add-extended-layout-attribute-support branch from 11730fc to 798f2ee Compare April 16, 2026 06:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

3 participants