Calling a method on an invalid numeric literal completely breaks error reporting in fsi
When calling a method on a non type-specified numeric literal (e.g. 1.ToString()), fsi outputs error FS1156, asking to better specify the numeric literal type. From that point onward, when inputting wrong expressions, the error code and position will be correct, but the expression shown in the error is the wrong one, usually the nth - numberOfTimesCallingTheMethodOnUnspecifiedLiteral expression. Sorry for being super unclear but I don't know the internals of FSI so it's just empirical evidence.
Repro steps
- Load up fsi
- send
List.sum [1;'2';3];;, see the error is correct - send
1.ToString();; - send
List.sum [1;'2';3];;again and see the wrong expression is still considered to be1.ToString() - send more times
1.ToString() - Send a mix of right expressions like
List.sum [1;2;3]and then start sending again wrong expression. The displayed string in the error block will be thenth - numberOfErrorsMade
Expected behavior
Display the right expression in the error block.
Known workarounds
I tried many different things but I found no way to fix the issue without killing the fsi process.
Related information
- MacOS 12.3.1 on M1 Pro
- .NET 6.0.202, FSI 12.0.1.0 for F# 6.0
- I have no way to check on earlier .NET versions for now
Commented FSI log
Microsoft (R) F# Interactive version 12.0.1.0 for F# 6.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
For help type #help;;
> List.sum [1;2;3];;
val it: int = 6
> List.sum [1;'2';3];;
List.sum [1;'2';3];;
------------^^^
/Users/giorgio/stdin(2,13): error FS0001: All elements of a list must be implicitly convertible to the type of the first element, which here is 'int'. This element has type 'char'.
> List.sum ['1';2;3];;
List.sum ['1';2;3];;
--------------^
/Users/giorgio/stdin(3,15): error FS0001: All elements of a list must be implicitly convertible to the type of the first element, which here is 'char'. This element has type 'int'.
/////// All fine until now;
> 123.Whatever;;
123.Whatever;;
^^^^^^^^^^^^
/Users/giorgio/stdin(4,1): error FS1156: This is not a valid numeric literal. Valid numeric literals include 1, 0x1, 0o1, 0b1, 1l (int), 1u (uint32), 1L (int64), 1UL (uint64), 1s (int16), 1y (sbyte), 1uy (byte), 1.0 (float), 1.0f (float32), 1.0m (decimal), 1I (BigInteger).
/////// Now the displayed expression in the error will be nth - 1 and the error will make no sense:
> List.sum ['1';2;3];;
123.Whatever;;
--------------^
/Users/giorgio/stdin(4,15): error FS0001: All elements of a list must be implicitly convertible to the type of the first element, which here is 'char'. This element has type 'int'.
/////// No problem on non-errors
> List.sum [1;2;3];;
val it: int = 6
/////// Makes no sense here. Notice the correct position of the ^s
> List.sum [1;2;'3'];;
List.sum [1;2;3];;
--------------^^^
/Users/giorgio/stdin(6,15): error FS0001: All elements of a list must be implicitly convertible to the type of the first element, which here is 'int'. This element has type 'char'.
/////// We now make 2 more errors, inflating the "lag" count to 3. The displayed expression will be the nth - 3.
> 123.Whatever;;
List.sum [1;2;'3'];;
^^^^^^^^^^^^
/Users/giorgio/stdin(7,1): error FS1156: This is not a valid numeric literal. Valid numeric literals include 1, 0x1, 0o1, 0b1, 1l (int), 1u (uint32), 1L (int64), 1UL (uint64), 1s (int16), 1y (sbyte), 1uy (byte), 1.0 (float), 1.0f (float32), 1.0m (decimal), 1I (BigInteger).
> 123.Whatever;;
List.sum [1;2;'3'];;
^^^^^^^^^^^^
/Users/giorgio/stdin(7,1): error FS1156: This is not a valid numeric literal. Valid numeric literals include 1, 0x1, 0o1, 0b1, 1l (int), 1u (uint32), 1L (int64), 1UL (uint64), 1s (int16), 1y (sbyte), 1uy (byte), 1.0 (float), 1.0f (float32), 1.0m (decimal), 1I (BigInteger).
/////// We "anchored" ourselves to List.sum [1;2;'3'], or nth - number of errors
> List.sum ['1';2;3];;
List.sum [1;2;'3'];;
--------------^
/Users/giorgio/stdin(7,15): error FS0001: All elements of a list must be implicitly convertible to the type of the first element, which here is 'char'. This element has type 'int'.
Might be duplicate of https://github.com/dotnet/fsharp/issues/9631, is certainly similar
I am looking into this now. It does indeed seem to be the same issue as #9631. As far as I can tell so far, it happens when an exception is thrown in lexer on scanning the very first token of input (so for example 1.ToString() + "" will result in this behaviour, but "" + 1.ToString() won't).
I am still not sure what is the root cause though - need to wrap my head around our error reporting and recovery logic. I am also allowing possibility that this might be a bug in FsLex.