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

When struct val field name equals constructor argument "ambiguous overload" #9942

Open
NinoFloris opened this issue Aug 14, 2020 · 8 comments
Labels
Area-Compiler-Checking Type checking, attributes and all aspects of logic checking Feature Request
Milestone

Comments

@NinoFloris
Copy link
Contributor

NinoFloris commented Aug 14, 2020

When struct val field name equals constructor argument "ambiguous overload"

open System

[<Struct>]
type C =
    val private x: int
    new (x) = { x = x }

//error FS0041: A unique overload for method 'C' could not be determined based on type information 
// prior to this program point. A type annotation may be needed. Candidates: C (), new : x:int -> C    
let test = C(x = 0)

https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AbEAzAzgHwgAcYA7AAgGUBPXAFxgFsBYAKDbYG0AeSuqAK5g6APgC6bOtRLkAwuQC8bcivIA3AIYZyRKAEtNDcghDk9pOstWkYAd3IAKBAEpF5AN7G3CcgF8rKmwYMHTkDPRusk5uAAzOQA===

Changing new (x) to say new (y) (and its references) allows the resolution to succeed. ¯\(ツ)

@abelbraaksma
Copy link
Contributor

I've been hit by this too, I think it's caused by the compiler thinking it's a field assignment for field x, vs a boolean expression. I've reported that somewhere as well, let me see if I can find it back.

@abelbraaksma
Copy link
Contributor

abelbraaksma commented Aug 14, 2020

Hmm, not sure it's related, but it seems in the same ballpark: #9517

My hunch is that it has the same cause.

@NinoFloris
Copy link
Contributor Author

Changed it to int as it has nothing to do with boolean expression confusion :) I think indeed there is some field and constructor argument confusion going on but it does not seem too related to #9517

@cartermp
Copy link
Contributor

Worth noting that this has no issue, which I expect to be the usual case:

open System

[<Struct>]
type C =
    val private x: int
    new (x) = { x = x }

let test = C(0)

Seems like a reasonable thing to also allow the named argument here

@NinoFloris
Copy link
Contributor Author

@cartermp this is mostly problematic when there are multiple constructors, of which at least one is for a generic field.
At that point F# will report an ambiguous overload anyway (because there is no tiebreaker for it) and there's no way to disambiguate on name either if you're dealing with a type like I showed, at that point you have no other options :)

@heronbpv
Copy link

Is it possible to use a self reference in the constructor definition, to help disambiguate?

@dsyme
Copy link
Contributor

dsyme commented Aug 24, 2020

So do we agree this is legitimately considered ambiguous?

open System

[<Struct>]
type C =
    val mutable x: int
    new (x) = { x = x }

let test = C(x = 0)

Here x = 0 may be a named argument or named field assignment.

In this case, the issue is that the private on val private x: int is not being taken into account during pre-analysis of the method call. I guess it's reasonable to take it into account, and also to check if the field is mutable or not.

@NinoFloris
Copy link
Contributor Author

I would indeed say it's ambiguous without the private access modifier

@dsyme dsyme added the Area-Compiler-Checking Type checking, attributes and all aspects of logic checking label Apr 20, 2022
@vzarytovskii vzarytovskii moved this to Not Planned in F# Compiler and Tooling Jun 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compiler-Checking Type checking, attributes and all aspects of logic checking Feature Request
Projects
Status: New
Development

No branches or pull requests

6 participants