realsig-codegen

Diagnose and fix --realsig+ codegen bugs causing runtime access exceptions in F# IlxGen.

4.3k|872|Updated Jan 10, 2015
One-click install
npx skills add https://github.com/dotnet/fsharp --skill realsig-codegen
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: realsig-codegen
Source: https://github.com/dotnet/fsharp/tree/main/.github/skills/realsig-codegen
Command: npx skills add https://github.com/dotnet/fsharp --skill realsig-codegen

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

F# programs that compile cleanly can crash at runtime under --realsig+ with MethodAccessException, FieldAccessException, or TypeAccessException because compiler-synthesized closures and state machines are emitted as sibling types instead of nested types, losing access to private members. This Skill provides the mental model, code locations, repro methodology, and instrumentation patterns to find and fix these IlxGen codegen bugs.

Core Features & Use Cases

  • Root-cause model: Explains how --realsig+ maps source private to IL private, why ECMA-335 nested-type access rules matter, and how eenv.cloc decides where closures are nested.
  • Repro methodology: Shows how to build minimal repros that survive the optimizer (non-inlinable private members, --optimize+), compare --realsig+ vs --realsig- with a shipped SDK fsc, and read IL nesting via ildasm indentation.
  • Instrumentation and fixes: Provides eprintfn-based logging patterns for GenMethodForBinding, the worked fix from PR #19955 (normalizing cloc to the member's DeclaringTypeRef), and test conventions for EmittedIL.RealInternalSignature baselines.
  • Use Case: A contributor sees a test crash only under --realsig+; use this Skill to build a faithful repro, trace where the closure's cloc diverges, renest it under the declaring type, and add a theory test covering both realsig settings.

Quick Start

Ask the AI to diagnose why an F# program with a private member called from an inner let rec crashes with MethodAccessException only when compiled with --realsig+.

Frequently Asked Questions about realsig-codegen

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
Why does my F# program crash with MethodAccessException only under --realsig+?

Under --realsig+, source private members become IL private, and ECMA-335 only lets nested types access their enclosing type's private members. If a compiler-synthesized closure is emitted as a sibling instead of nested inside the declaring type, the CLR throws MethodAccessException at first invocation.

How do I create a minimal repro for an F# realsig codegen bug?

Make the private member non-inlinable, for example by reading mutable state or using [<NoCompilerInlining>], so the optimizer does not remove the call. Compile with a shipped SDK fsc using --realsig+ and --optimize+, then compare against --realsig- to isolate the delta.

How do I check IL nesting to confirm a closure placement bug?

Inspect the assembly with ildasm and read nesting by indentation: a child class at deeper indent under the declaring type means nested, while the same indent means sibling. Confirm with full type names in field refs, such as M/C/h@8 for nested versus M/h@8 for sibling.

What is the difference between --realsig+ and --realsig- in F#?

Under --realsig- (legacy default), source private compiles to IL assembly, hiding visibility intent. Under --realsig+, source private maps to IL private and internal to IL assembly, matching C# expectations; the flag has existed since F# 8 GA.

Why does my realsig repro stop crashing when optimization is enabled?

The F# optimizer inlines trivial private members before codegen, so the call site disappears and the crash vanishes under --optimize+. Force a faithful repro by making the member non-inlinable, such as reading mutable state, and note that NoCompilerInlining is the F# optimizer attribute, not the JIT one.

Where are realsig codegen tests located in the F# compiler repo?

Tests live under tests/FSharp.Compiler.ComponentTests/EmittedIL in the EmittedIL.RealInternalSignature namespace. Use withRealInternalSignature, compileExeAndRun for runtime checks, theory data for both realsig settings, and regenerate .il.bsl baselines with TEST_UPDATE_BSL=1.