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

[<System.ParamArray>] parameter in member function causes type check error. #17957

Open
muqiuhan opened this issue Nov 5, 2024 · 2 comments
Open
Milestone

Comments

@muqiuhan
Copy link
Contributor

muqiuhan commented Nov 5, 2024

When I use the parameter of [<ParamArray>] attribute in member function, I cannot pass the parameter using pipeline operator:

> type X () = member _.ID ([<System.ParamArray>] arr) = arr;;
type X =
  new: unit -> X
  member ID: [<System.ParamArray>] arr: 'a -> 'a

> let x = X();;                                              
val x: X

> x.ID([| 1; 2; 3 |]);;                                      
val it: int array = [|1; 2; 3|]

> [| 1; 2; 3 |] |> x.ID;;

  [| 1; 2; 3 |] |> x.ID;;
  -----------------^^^^
/home/muqiu/stdin(10,18): error FS0001: This expression was expected to have type
    'int array'    
but here has type
    'unit'

And no type check error occurs when the [<ParamArray>] attribute is not used or using [<ParamArray>] at the top level:

> type X () = member _.ID (arr) = arr;;
type X =
  new: unit -> X
  member ID: arr: 'a -> 'a

> let x = X();;                        
val x: X

> [| 1; 2; 3 |] |> x.ID;;
val it: int array = [|1; 2; 3|]

> let ID ([<System.ParamArray>] arr) = arr;;     
val ID: [<System.ParamArray>] arr: 'a -> 'a

> [| 1; 2; 3 |] |> ID;;                     
val it: int array = [|1; 2; 3|]

Why does [<ParamArray>] behave differently in member functions? Is this a compiler bug?

@github-actions github-actions bot added this to the Backlog milestone Nov 5, 2024
@brianrourkeboll
Copy link
Contributor

Probably a duplicate of #11918.

I think it's a type inference + overload resolution thing: a method with a single parameter annotated with [<ParamArray>] can also be treated as a nullary method (or a method taking a single parameter of type unit).

But there is not perfect symmetry in how overload resolution works for directly-invoked methods and methods used in a first-class way (e.g., with piping). See #11918 (comment).

@brianrourkeboll
Copy link
Contributor

brianrourkeboll commented Nov 5, 2024

The error message is confusing, though:

> open System
-
- type T =
-     static member M ([<ParamArray>] xs : int array) = xs
-
- let xs = [|1..10|]
-
- xs |> T.M;;

  xs |> T.M;;
  ------^^^

stdin(8,7): error FS0001: This expression was expected to have type
    'int array'
but here has type
    'unit'

It sounds like the opposite of what the source code looks like.

Especially since this works:

() |> T.M

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: New
Development

No branches or pull requests

2 participants