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

The 8-year-old problem: Fully qualified name, unqualified name with import declaration resolve differently #809

Closed
5 tasks done
Happypig375 opened this issue Nov 23, 2019 · 5 comments

Comments

@Happypig375
Copy link
Contributor

https://stackoverflow.com/questions/8732769/fully-qualified-name-unqualified-name-with-import-declaration-resolve-different

I propose we allow fully qualified names to resolve to the nongeneric overload when multiple overloads of different arity are present. (The first entry of the following should be valid.)

Microsoft (R) F# Interactive version 10.6.0.0 for F# 4.7
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> System.Action(fun () -> ());;

  System.Action(fun () -> ());;
  ^^^^^^^^^^^^^

stdin(1,1): error FS1124: Multiple types exist called 'Action', taking different numbers of generic parameters. Provide a type instantiation to disambiguate the type resolution, e.g. 'Action<_,_,_,_,_,_,_,_,_>'.

> System.Action<>(fun () -> ());;

  System.Action<>(fun () -> ());;
  ^^^^^^^^^^^^^

stdin(2,1): error FS1124: Multiple types exist called 'Action', taking different numbers of generic parameters. Provide a type instantiation to disambiguate the type resolution, e.g. 'Action<_,_,_,_,_,_,_,_,_>'.

> System.Action< >(fun () -> ());;
val it : System.Action = System.Action {Method = Void Invoke();
                                        Target = FSI_0004+it@3;}

> new System.Action(fun () -> ());;
val it : System.Action = System.Action {Method = Void Invoke();
                                        Target = FSI_0005+it@4-1;}

> open System
Action(fun () -> ());;
val it : System.Action

> 

The existing ways of approaching this problem in F# are the last three entries.

Pros and Cons

The advantages of making this adjustment to F# are

  1. Consistency
  2. Convenience
  3. Conciseness

The disadvantages of making this adjustment to F# are none that I can think of.

Extra information

Estimated cost (XS, S, M, L, XL, XXL): XS - Related implementation information can be found in the linked StackOverflow question.

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this
@abelbraaksma
Copy link

I'm not sure about back in 2012,but I currently resolve such conflicts simply by using global. as prefix to the System namespace.

It's also in the docs:

You can also use global to reference the top-level .NET namespace, for example, to resolve name conflicts with other namespaces.

Though I think the ambiguities between using new and not, is actually a bug.

(I'm not saying this behaviour shouldn't be fixed, just that there's a non ambiguous way around it, specifically designed for this case)

@cartermp
Copy link
Member

Just to note that the issue as-written in SO and this suggestion doesn't reproduce on .NET Core:

λ ~/scratch/testy/ cat Program.fs
// Learn more about F# at http://fsharp.org

let f = System.Action(fun () -> Unchecked.defaultof<_>)
let f2 = System.Action(fun () -> ())

open System

let f3 = Action(fun () -> ())


[<EntryPoint>]
let main argv =
    f.Invoke()
    f2.Invoke()
    f3.Invoke()
    0 // return an integer exit code
λ ~/scratch/testy/ dotnet build
Microsoft (R) Build Engine version 16.4.0-preview-19529-02+0c507a29b for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 26.34 ms for /Users/phillip/scratch/testy/testy.fsproj.
  You are using a preview version of .NET Core. See: https://aka.ms/dotnet-core-preview
  testy -> /Users/phillip/scratch/testy/bin/Debug/netcoreapp3.1/testy.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:02.93
λ ~/scratch/testy/

Given that I don't think it's likely we'd do this just for .NET Framework, though we'd probably accept a PR that implements it correctly.

@Happypig375
Copy link
Contributor Author

Given that I don't think it's likely we'd do this just for .NET Framework, though we'd probably accept a PR that implements it correctly.

Not just .NET Framework, developing libraries on .NET Standard has this issue too.

@cartermp
Copy link
Member

I think this is only true if you're using the desktop compiler. This equally does not reproduce on .NET Core on unix for .NET Standard. We're intending to replace the desktop compiler entirely, so I don't think this is a language suggestion that'll be implemented.

@dsyme
Copy link
Collaborator

dsyme commented Sep 20, 2021

Closing out this old issue

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

No branches or pull requests

4 participants