dotnet / fsharp

The F# compiler, F# core library, F# language service, and F# tooling integration for Visual Studio
https://dotnet.microsoft.com/languages/fsharp
MIT License
3.9k stars 783 forks source link

SNAFU with indexed properties & type extensions: internal error & inconsistency over shadowing #16034

Open smoothdeveloper opened 1 year ago

smoothdeveloper commented 1 year ago

The modality of calling indexed properties and shadowing are a bit mixed up:

let mutable i = 0
type T() =
  member x.indexed1
    with get (a1: obj) =
      i <- i + 1
      printfn $"T().indexed1 {a1} !\t%03i{i}" 
      1
    and set (a1: obj) (value: int) =
      i <- i + 1
      printfn $"T().indexed1 {a1} <- {value} !\t%03i{i}"

module Extensions =
  let mutable j = 0
  type T with
    member x.indexed1 
      with get (aa1: obj) =
        i <- i + 1
        j <- j + 1
        printfn $"type extensions aa1 {aa1} !\t%03i{i}\t%03i{j}"
        1
      and set (aa1: obj) (value: int) =
        i <- i + 1
        j <- j + 1
        printfn $"type extension aa1 {aa1} <- {value}!\t%03i{i}\t%03i{j}"
let t = T()
t.indexed1 ["ok"] <- 1           // calls the intrinsic property    
t.indexed1 ("ok") <- 2           // calls the intrinsic property    
t.indexed1 "ok" <- 3             // calls the intrinsic property    
t.indexed1 "ok"                  // calls the intrinsic property
t.get_indexed1 "ok"              // calls the intrinsic property
t.set_indexed1 (a1="ok",value=1) // calls the intrinsic property

open Extensions

t.indexed1 "nok"        // calls the intrinsic property?
t.indexed1 (a1="ok")    // calls the intrinsic property
t.indexed1 (aa1="ok")   // calls the type extension property
t.indexed1 ["nok"] <- 1 // calls the intrinsic property?
t.indexed1 ("nok") <- 2 // calls the intrinsic property?
t.indexed1 "nok" <- 3   // calls the intrinsic property?

t.get_indexed1 ("nok") // calls the intrinsic property?
t.get_indexed1 ["nok"] // calls the intrinsic property?
t.get_indexed1 "nok"   // calls the intrinsic property?

t.set_indexed1 ("nok_015",1)          // calls the intrinsic property?
t.set_indexed1 ("nok_016",value=2)    // calls the intrinsic property?
t.set_indexed1 (a1="ok_017",value=1)  // calls the intrinsic property
t.set_indexed1 (aa1="ok_018",value=1) // calls the type extension property

t.indexed1(aa1="nok") <- 1 // error FS0073: internal error: The input must be non-negative. (Parameter 'n') (ArgumentException)
t.indexed1(a1="nok") <- 1 // error FS0073: internal error: The input must be non-negative. (Parameter 'n') (ArgumentException)

also, there is an internal error when attempting to call indexed setter when specifying the argument name.

observations:

smoothdeveloper commented 1 year ago

As far as my debugging went, there is wrong assumption in indexing in the calledArgs, probably due to the fact that it comes with a named argument (aa1), then an unnamed (value).

https://github.com/dotnet/fsharp/blob/15331e03389fa0a8750cd22b1c09b530f2fe8bf8/src/Compiler/Checking/MethodCalls.fs#L581-L585

This code needs to account for the possibility of named argument to come first.