Skip to content

F# compiler crashes when calling inherited base method on external generic IL behavior type (OnDetaching / Behavior<T>) #20264

Description

@xperiandri

Summary

The F# compiler crashes while typechecking a call to a base method on an external generic IL type, specifically a method named OnDetaching on Microsoft.Xaml.Interactivity.Behavior<T>. Instead of reporting a normal type-checking error, the compiler throws an unhandled exception:

System.Exception: no method named OnDetaching found in type Microsoft.Xaml.Interactivity.Behavior1`

This looks like a compiler bug in the IL base-call semantic check path rather than a user-code problem.

Stack trace and root site

The exception is thrown from:

  • FSharp.Compiler.AbstractIL.IL.resolveILMethodRefWithRescope
  • called from FSharp.Compiler.PostTypeCheckSemanticChecks.CheckILBaseCall

The relevant stack is:

FSharp.Compiler.Service.dll!FSharp.Compiler.AbstractIL.IL.resolveILMethodRefWithRescope
FSharp.Compiler.Service.dll!FSharp.Compiler.PostTypeCheckSemanticChecks.CheckILBaseCall
FSharp.Compiler.Service.dll!FSharp.Compiler.PostTypeCheckSemanticChecks.CheckExpr
FSharp.Compiler.Service.dll!FSharp.Compiler.PostTypeCheckSemanticChecks.CheckExprLinear
FSharp.Compiler.Service.dll!FSharp.Compiler.PostTypeCheckSemanticChecks.CheckExpr
FSharp.Compiler.Service.dll!FSharp.Compiler.PostTypeCheckSemanticChecks.CheckExprNoByrefs

The failing helper is essentially doing a name+arity lookup on the raw metadata type:

let resolveILMethodRefWithRescope r (td: ILTypeDef) (mref: ILMethodRef) =
    let args = mref.ArgTypes
    let nargs = args.Length
    let nm = mref.Name
    let possibles = td.Methods.FindByNameAndArity(nm, nargs)

    if isNil possibles then
        failwith ("no method named " + nm + " found in type " + td.Name)

Observed behavior

The compiler crashes in the semantic validation phase while checking a base call, rather than performing normal validation or producing a user-facing diagnostic.

The failing method name is:

  • OnDetaching

The raw IL type name involved is:

  • Microsoft.Xaml.Interactivity.Behavior1`

This strongly suggests the compiler assumes the method exists on the immediate raw metadata type being inspected, but for external generic types the method can be inherited from a base type instead of declared directly on the current type metadata.

Expected behavior

The compiler should either:

  1. resolve the inherited base method correctly, or
  2. skip the special abstract-base IL check when the method is not declared on the immediate raw metadata type,
  3. and report a normal type-checking error only if the call is genuinely invalid.

The compiler should not throw an unhandled System.Exception in the middle of semantic checking.

Reproduction path

To reproduce, use an F# project that references Microsoft.Xaml.Interactivity and defines a custom behavior that overrides and calls the base implementation:

open System.Windows
open System.Windows.Controls
open Microsoft.Xaml.Interactivity

type MyBehavior() =
    inherit Behavior<FrameworkElement>()

    override _.OnDetaching() =
        base.OnDetaching()

Or, in a more general form:

type MyBehavior() =
    inherit Microsoft.Xaml.Interactivity.Behavior<FrameworkElement>()

    override _.OnDetaching() =
        base.OnDetaching()

Then compile the project or hit the compiler service / IDE background typechecking path.

This is enough to trigger the IL base-call diagnostics path in CheckILBaseCall.

Environment

  • Repository: dotnet/fsharp
  • Branch: fix-project-options-async-debounce
  • IDE: Visual Studio Enterprise 2026 (18.10.0-insiders)
  • F# compiler / FCS path: src/Compiler/...
  • Affected type: Microsoft.Xaml.Interactivity.Behavior<'T>
  • Relevant stack path:
    • src/Compiler/Checking/PostInferenceChecks.fs
    • src/Compiler/AbstractIL/il.fs

Why this is likely a compiler bug

The failure occurs during post-inference semantic analysis, not in user code. The code path is checking an IL base method call and crashes because it is using a strict lookup on the current raw type definition instead of handling inherited methods gracefully.

This is consistent with a type-checker bug in the IL-type method resolution logic and not with valid user code being rejected.

Minimal likely fix direction

The check should not failwith when the method is not directly declared on the current metadata type. It should either:

  • resolve inherited methods along the type hierarchy, or
  • treat the method as absent for this local guard and proceed without crashing.

The exact root cause likely sits in the interaction between:

  • CheckILBaseCall
  • tryTcrefOfAppTy g baseVal.Type
  • resolveILMethodRefWithRescope
  • the assumption that td.Methods.FindByNameAndArity(...) always succeeds for IL base calls.

Additional notes

This is a reproducible compiler crash in the IDE / compiler service layer, not just a normal F# type error. The exception is unhandled and aborts the semantic checking flow.

A robust fix should keep the abstract-base validation for genuinely local IL methods, while avoiding a hard crash when the relevant method is inherited from the external generic base type rather than declared in the immediate type metadata.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status
    New

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions