dotnet / dotnet/fsharp

No compile-time error when static abstract member accessed on type parameter whose resolved type has no concrete implementation for said member

Open
#17,139 3 comments 2 reactions 0 assignees View on GitHub
Area-Compiler-Checking Area-Compiler-SRTP Bug Impact-Low
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 22h
Merged PRs (30d)
144

Description

There is no compile-time error when:

1. You invoke a static abstract member on a type parameter that is constrained to be an interface with the given static abstract member (IWSAM).
2. The type variable for that type parameter is automatically constrained to be _the interface type itself_ (as opposed to a concrete type that has a concrete implementation of the member being invoked).

A `System.Runtime.AmbiguousImplementationException` is raised at runtime instead. This is raised even when the interface in question has only one static abstract member (or member of any kind).

**Repro steps**

```fsharp
#nowarn "3535"

type IFace =
static abstract P1 : int

type T =
interface IFace with
static member P1 = 1

let inline p1<'T & #IFace> = 'T.P1

let _ = p1 // 'T is resolved to be IFace itself.
```

![image](https://github.com/dotnet/fsharp/assets/14795984/047382e8-0d1b-4ef7-8c04-2ca1e3ffeda5)

#### `net8.0`

```stderr
Unhandled exception. System.Runtime.AmbiguousImplementationException: Could not call method 'Program+IFace.get_P1()' on interface 'Program+IFace' with type 'Program+IFace' from assembly '' because there are multiple incompatible interface methods overriding this method.
at .$Program.main@() in D:\src\ConsoleApp1\ConsoleApp1\Program.fs:line 12
```

#### `net9.0`

```stderr
Unhandled exception. System.Runtime.AmbiguousImplementationException: Ambiguous implementation found.
at .$Program.main@() in D:\src\ConsoleApp1\ConsoleApp1\Program.fs:line 12
```

**Expected behavior**

Resolution of the type variable should fail at compile-time in the absence of further type information when the type variable has a constraint involving static abstract members — although ideally it would only fail when an `abstract` (as opposed to `virtual`) member was actually being accessed, which is not visible through a constraint like `'T & #IFace` alone.

**Actual behavior**

A type variable like `'T & #IFace` resolves to the interface type `IFace` itself, and a `System.Runtime.AmbiguousImplementationException` is raised at runtime.

**Known workarounds**

Always manually ensure that all type variables are resolved to types with concrete implementations for all static abstract methods that are invoked on them.

**Related information**

.NET 8/9 preview.

This problem is similar in spirit to #14012, #16299, etc., although it might be a bit trickier to fix.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.