Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Addition operator required by type parameter constraint can't be invoked #12385

Closed
brianberns opened this issue Nov 13, 2021 · 3 comments
Closed
Labels

Comments

@brianberns
Copy link

brianberns commented Nov 13, 2021

Repro steps

Consider the following code:

let inline add<'T when 'T : (static member (+) : 'T * 'T -> 'T)> (a : 'T) (b : 'T) =
    a + b

Expected behavior

Code should compile and successfully add the two arguments.

Actual behavior

Compiler error: A type parameter is missing a constraint 'when ( ^T or ^?11088896) : (static member (+) : ^T * ^?11088896 -> ^?11088897)'

Known workarounds

The following variation works:

let inline add<'T when 'T : (static member (+) : 'T * 'T -> 'T)> (a : 'T) (b : 'T) =
    (^T : (static member (+) : ^T * ^T -> ^T)(a, b))

However, it also results in a compiler warning: Member constraints with the name 'op_Addition' are given special status by the F# compiler as certain .NET types are implicitly augmented with this member. This may result in runtime failures if you attempt to invoke the member constraint from your own code.

@brianberns brianberns added the Bug label Nov 13, 2021
@brianberns
Copy link
Author

Note that moving the code into a static member results in a warning with the same text as the original error:

type Example< ^T when ^T : (static member (+) : ^T * ^T -> ^T)> =
    static member inline Add(a : 'T, b : 'T) =
        a + b   // Warning: A type parameter is missing a constraint

This version can be successfully compiled and executed.

@dsyme
Copy link
Contributor

dsyme commented Nov 15, 2021

This issue is tracked by #9633. The general problem is that half way through inference a constraint arises that is falsely unified with the explicit consttraint. It's actually fixed in #6805 but that is a long way from going in and it's hard to isolate out the fix and extensive testing.

FWIW you can also omit the explicit type parameter declarations:

let inline addSame (x: 'T) (y: 'T) : 'T = x + y

let inline add<'T when 'T : (static member (+) : 'T * 'T -> 'T)> (a : 'T) (b : 'T) : 'T =
    addSame a b

This actually gives a fairly general technique to avoid this problem -

  1. first define a helper function without explicit type parameter declarations, reducing the genericity
  2. then call that from your code with explicit type parameter declarations

@dsyme
Copy link
Contributor

dsyme commented Nov 15, 2021

I'll close as covered by #9633

@dsyme dsyme closed this as completed Nov 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants