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

Compiler failing with ArgumentException when calling data constructor with equality operator #823

Closed
bleis-tift opened this issue Dec 22, 2015 · 4 comments
Labels
Bug Impact-Medium (Internal MS Team use only) Describes an issue with moderate impact on existing code. Ready

Comments

@bleis-tift
Copy link

Description:

fsc.exe and fsi.exe throw ArgumentException when calling data constructor with two equality operators.

Repro Steps:

> let x, y = 1, 2
Some (x = y, x = x);;

Expected:

Some (false, true) // or error FS0691?

Actual:

  Some (x = y, x = x);;
  ^^^^^^^^^^^^^^^^^^^

C:\Users\b\AppData\Local\Temp\stdin(16,1): error FS0073: 内部エラー: インデックスはリストの要素の範囲外にありました。

パラメーター名:index (ArgumentException)

Version: Language, compiler, library, platform version

VS2013, VS2015 (VS2012 works well)

Workaround: List any known workarounds

use paren.

Some ((x = y), (x = x)) // OK
Some ((x = y), x = x) // NG
Some (x = y, (x = x)) // error FS0691
@yukitos
Copy link

yukitos commented Dec 22, 2015

FYI: English version's error message is here:

error FS0073: internal error: The index was outside the range of elements in the list.

Parameter name: index (ArgumentException)

@cdrnet
Copy link

cdrnet commented Dec 22, 2015

Another workaround: Some ((x = y, x = x)), also Some <| (x = y, x = x)

@abelbraaksma
Copy link
Contributor

Interesting bug, I noticed the following, which may help pointing to the underlying issue, i.e. a (normal) named arguments error:

// in FSI
Some (x = 1, 1 = 2)   // error FS0691: Named arguments must appear after all other arguments
Some (1 = x, 1 = 2)   // OK

A different kind of IndexOutOfRangeException occurs when you have more than two items in the tuple, where one of them has a variable reference on the LHS:

// in FSI
Some (1 = x, 2 = y, 2 = 2, 3 = 2, 2 = x, y = 3)    // error FS0193: internal error: Index was outside the bounds of the array.
Some (1 = x, 2 = y, 2 = 2, 3 = 2, 2 = x, 3 = y)    // OK

And your reported error happens for only two items in the tuple (at least of what I could find out), and if the last item starts with a variable as the LHS of the equal-operator:

// in FSI
Some (1 = 2, x = 2)    // error FS0073: internal error: The index was outside the range of elements in the list.

When I tried some of the examples in VS2015, it crashed fsc.exe. Debugging fsc.exe gave an IndexOutOfRangeException again. For some reason VS2015 does not want me to download the symbols for fsc.exe, so I can't dump a meaningful stacktrace here.

When trying to actually build (ignoring the crash) the output window showed three errors for

let x = 1
let y = 2
let x = Some (1 = x, y = y)

Result:

typecheck error FS0193: error : The index was outside the range of elements in the list. Parameter name: index
typecheck error FS0073: error : The index was outside the range of elements in the list. Parameter name: index (ArgumentException)
parameter error FS0193: error : The index was outside the range of elements in the list. Parameter name: index

This was all tested with VS2015, F# 4.0.

I think it is fair to assume that the compiler incorrectly chooses whether something is a named parameter or not, and when it considers it to be a named parameter and tries to treat it as one, it fails, because there is no such named parameter. But instead of giving an error of sorts, pointing to the ambiguity in your code, it crashes.

@abelbraaksma
Copy link
Contributor

Perhaps superfluous, but if you have a type:

type Test =
    static member Test(a, b, c) = if a then if b then if c then ()

Then, with the same code, you'd get a more expected error:

let x, y = 1, 2
// error FS0495: The member or object constructor 'Test' has no argument or settable return 
// property 'y'. The required signature is static member Test.Test : a:bool * b:bool * c:bool -> unit.
let z = Test.Test (1 = 2, y = 2, x = x) 

(which can be resolved in a variety of obvious ways). The same error appears when you add (a, b, c) as part of the constructor. I think this is proper and by design.

However: the issue with Some as in the title of this bug can be reproduced with your own type if it is a union type:

type Test<'a> =
| New of ('a * 'a * 'a)

and:

let x, y = 1, 2
let z = Test.New (1 = 2, y = 2, x = x) 

This crashes fsc.exe again and dumps this to stderr (the same as above):

typecheck error FS0193: error : The index was outside the range of elements in the list. Parameter name: index
typecheck error FS0073: error : The index was outside the range of elements in the list. Parameter name: index (ArgumentException)
parameter error FS0193: error : The index was outside the range of elements in the list. Parameter name: index

To sum up

To reproduce:

  • Take or create a union type with a discriminator that accepts a tuple of more than 1
  • Use the type constructor
  • Result: the mentioned internal error and crashing compiler after the typecheck error FS0193, typecheck error FS0073 and parameter error FS0193 (not sure whey they are differently named).

@dsyme dsyme added Bug Area-Compiler Impact-Medium (Internal MS Team use only) Describes an issue with moderate impact on existing code. labels Jan 8, 2016
@dsyme dsyme added the Ready label Jul 5, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Impact-Medium (Internal MS Team use only) Describes an issue with moderate impact on existing code. Ready
Projects
None yet
Development

No branches or pull requests

5 participants