Fsharp: Open static classes shadows an overload unexpectedly

Created on 14 Aug 2019  路  4Comments  路  Source: dotnet/fsharp

Thanks to @TIHan for bringing this up. Consider the following example:

[<AbstractClass; Sealed>]
type One =
    static member M(x: int) = 1

[<AbstractClass; Sealed>]
type Two =
    static member M(x: float) = 1

open One
open Two

let x = M(1.0)
let y = M(1) // Compile error!

The M that takes an int is shadowed, as if these were functions.

However, this feels quite unexpected since these are methods, and methods can be overloaded. And as you'd expect, if both M methods were defined in the _same_ static class, you could write code that used both overloads. And since they have unique signatures, it's expected that you could call either.

Hence, I consider this behavior to be unexpected and/or a bug and not an explicit design decision.

However, fixing it is not so simple. Because it is possible to write F# code that calls overloaded methods but uses type inference, allowing the compiler to "see" additional overloads is a breaking change. A key distinction here is that, unlike a library or CoreFX adding an overload that causes this if people upgrade, this would be the F# compiler potentially introducing a breaking change into user code.

Hence, it is a breaking change to fix this if the feature is fully released. We have two options:

  1. Try to get in a fix ASAP
  2. Put the feature behind the preview language version and fix the bug that way
Area-Compiler bug

All 4 comments

Personally I feel like it might be generally a good idea to ship new features behind preview first in order to find issues like this. Historically, we see that new features tend to break ...

We shouldn't expect people to build PRs themselves to try out new features.

I think this has already been mentioned before but I wanted to point this out as it seems to fit to one of the suggested solutions. Obviously, just fixing the problem is always better but on stuff like this it might be technically challenging or introduce other design issues...

In this case it's unclear, we'll need to do a spike to learn more about the impact of a fix. Generally we think it should be straightforward though.

In terms of process, we're now going to be merging features earlier and behind Preview and giving them a longer lead time. Since this came in before we had a LangVersion switch, it had to linger in a branch for a long time and get LangVersion added to it after it was merged, making it (and others we're pulling like nameof) more challenging.

In short,

Broke: F# prior to F# 4.6
Woke: F# in 4.7+

We have decided to put this feature behind preview. We need a bit more time to address design-related issues and have them bake for a bit. While this feature is approved in principle, there are design implications that are undefined. I'm going to create a PR that will address the design issues and describe in detail what the current design will be. Because the feature is behind preview, the design is subject to change and will await @dsyme 's further input on it. This is the least risky thing to do given our time frame and constraints.

@matthid F# does have a history of new features tending to break. Having a preview language version flag is designed to help address quality control in regards to this. And in this case, that is exactly what we are going to do.

Perhaps moving forward, I suggest we could have a policy where certain major features like, "nameof", "open static classes" need to be shipped in preview before they make it into an official release.

Closing as this is covered in the RFC discussion thread - please follow that if interested in helping to resolve this and bring it out of preview

https://github.com/fsharp/fslang-design/issues/352#issuecomment-521998819

Was this page helpful?
0 / 5 - 0 ratings