-
Notifications
You must be signed in to change notification settings - Fork 789
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
IsUnionCaseTester throwing an error #17301
Comments
Would this be fixed in F# 9 ? |
We probably should, yes. |
@ncave Could you please share code that repros this? |
I mean specifically how does this case looks like
|
@abonie Sure, here it is: type HTMLAttr =
| Href of string
| Custom
let a = Custom
let b = a.IsCustom
printfn $"IsCustom = {b}" Here, when inspecting the AST for the generated union case tester members
Based on these, see the OP above for a proposed fix in |
@abonie In other words, instead of what it is right now: member _.IsUnionCaseTester =
checkIsResolved()
match d with
| P p -> p.IsUnionCaseTester
| M m -> m.IsUnionCaseTester
| E _ | C _ | V _ -> invalidOp "the value or member is not a property" should be something like this: member _.IsUnionCaseTester =
checkIsResolved()
match d with
| P p -> p.IsUnionCaseTester
| M m -> m.IsUnionCaseTester
| V v -> v.IsPropertyGetterMethod && v.LogicalName.StartsWith("get_Is") // added missing case
| E _ | C _ -> false // fixed to return boolean |
@ncave sorry I got a bit sidetracked last couple of days. I guess I wanted to know what F# code you are inspecting that results in |
@abonie Yes, that is correct, see above for an example F# code, and the AST for the generated union case tester member |
Right @ncave, sorry for being a little clueless here, but I can't figure out how you're grabbing the Here's what I am trying in our unit tests to capture this, based on the snippet you shared: [<Fact>]
let ``IsUnionCaseTester test`` () =
FSharp """
module Lib
type HTMLAttr =
| Href of string
| Custom
let a = Custom
let b = a.IsCustom
printfn $"IsCustom = {b}"
let c = a.get_IsCustom
"""
|> withLangVersionPreview
|> typecheckResults
|> fun results ->
let isCustomSymbolUse = results.GetSymbolUseAtLocation(11, 22, "let c = a.get_IsCustom", [ "get_IsCustom" ]).Value
match isCustomSymbolUse.Symbol with
| :? FSharpMemberOrFunctionOrValue as mfv ->
Assert.True(false, $"""IsProperty = {mfv.IsProperty}
IsMethod = {mfv.IsMethod}
IsFunction = {mfv.IsFunction}
IsPropertyGetterMethod = {mfv.IsPropertyGetterMethod}
IsValue = {mfv.IsValue}""")
| _ -> failwith "Expected FSharpMemberOrFunctionOrValue" (ignore the fact that this is not a good test, using this for exploration purposes atm) let isCustomSymbolUse = results.GetSymbolUseAtLocation(11, 5, "let c = a.get_IsCustom", [ "c" ]).Value then I get both Trying to understand what's going on before deciding if the ad hoc bugfix is appropriate |
@abonie Perhaps try inspecting the |
I've started with that (it's IsMethod = false, IsPropertyGetterMethod = false). Is it possible for you to share the code that runs into IsMethod = false, IsPropertyGetterMethod = true? I mean both code that's being inspected and the code that does inspecting |
@abonie Yes, while it is true that when using the symbol look up ( e.g. this code prints the correct values (but please see below for more): let isCustomSymbolUse =
typeCheckResults.GetSymbolUseAtLocation(8, 18, inputLines.[7], [ "IsCustom" ])
match isCustomSymbolUse with
| Some v ->
match v.Symbol with
| :? FSharpMemberOrFunctionOrValue as mfv ->
printfn $"""
--- when using GetSymbolUseAtLocation ---
{mfv.CompiledName}:
IsProperty = {mfv.IsProperty}
IsUnionCaseTester = {mfv.IsUnionCaseTester}
IsMethod = {mfv.IsMethod}
IsFunction = {mfv.IsFunction}
IsPropertyGetterMethod = {mfv.IsPropertyGetterMethod}
IsValue = {mfv.IsValue}"""
| _ -> printfn "Expected FSharpMemberOrFunctionOrValue"
| _ -> printfn "Expected Symbol" will print the following:
But, if you enumerate the declarations in the AST, you can see a different story. for impl_file in projectResults.AssemblyContents.ImplementationFiles do
for file_decl in impl_file.Declarations do
match file_decl with
| FSharpImplementationFileDeclaration.Entity (ent, ent_decls) ->
for ent_decl in ent_decls do
match ent_decl with
| FSharpImplementationFileDeclaration.MemberOrFunctionOrValue (mfv, args, body) ->
if mfv.CompiledName.StartsWith("get_Is") then
printfn $"""
--- when enumerating declarations ---
{mfv.CompiledName}:
IsProperty = {mfv.IsProperty}
IsMethod = {mfv.IsMethod}
IsFunction = {mfv.IsFunction}
IsPropertyGetterMethod = {mfv.IsPropertyGetterMethod}
IsValue = {mfv.IsValue}"""
| _ -> ()
| _ -> () will print this:
And if you try to use |
Thanks @ncave, I can reproduce this now. I suspect this is a bug in these properties (and not in the
I agree with this. It seems to me there are two separate issues here: throwing instead of returning false and the weird "not a method" corner case. |
2 issues with IsUnionCaseTester:
false
on non-matching values.IsProperty
norIsMethod
(but it isIsPropertyGetterMethod
).Perhaps it's missing the
| V v -> ...
case, maybe something like this?Related to #16341
Tested on .NET 8.0, with
<LangVersion>preview</LangVersion>
.The text was updated successfully, but these errors were encountered: