dotnet / dotnet/fsharp

Operators.( .. .. ) throws an ArgumentException when ^Step does not implement IComparable

Open
#6,238 6 comments 1 reaction 1 assignee Claimed by @abelbraaksma View on GitHub
Area-Library Bug Impact-Low
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 22h
Merged PRs (30d)
144

Description

[`Operators.( .. .. )`](https://msdn.microsoft.com/visualfsharpdocs/conceptual/operators.%5B-..-..-%5D%5B%5Et,%5Estep%5D-function-%5Bfsharp%5D?f=255&MSPPError=-2147217396) throws an `ArgumentException` when `^Step` does not implement non-generic `System.IComparable`.

#### Repro steps

Run the following code:
```fsharp
type Step(value:int) =
member __.Value = value

static member Zero = Step 0

type Value(value:int) =
member __.Value = value

static member (+)(a:Value, b:Step) = Value(a.Value + b.Value)

interface System.IComparable with
member a.CompareTo(b) =
match b with
| :? Value as b' -> compare a.Value b'.Value
| _ -> failwith "unsupported"

[Value 0 .. Step 2 .. Value 2]
```

#### Expected behavior

I would expect a compiler error. Similar to
- `Step.Zero` not implemented
- `Value.(+)` not implemented
- `Value` not implementing `System.IComparable`

#### Actual behavior

The last line throws this exception:
```
System.ArgumentException: Failure during generic comparison: the type 'FSI_0006+Step' does not implement the System.IComparable interface. This error may be arise from the use of a function such as 'compare', 'max'
or 'min' or a data structure such as 'Set' or 'Map' whose keys contain instances of this type.
at Microsoft.FSharp.Core.LanguagePrimitives.HashCompare.FailGenericComparison[a](Object obj)
at Microsoft.FSharp.Core.LanguagePrimitives.HashCompare.GenericCompare(GenericComparer comp, Object xobj, Object yobj)
at Microsoft.FSharp.Core.LanguagePrimitives.HashCompare.GenericLessThanIntrinsic[T](T x, T y)
at Microsoft.FSharp.Core.Operators.OperatorIntrinsics.gen@4848-3[TStep,T](TStep zero, FSharpFunc`2 add, T start, TStep step, T stop, Unit unitVar0)
at Microsoft.FSharp.Core.Operators.OperatorIntrinsics.RangeStepGeneric@4936-1.System-Collections-Generic-IEnumerable`1-GetEnumerator()
at Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1.MoveNextImpl()
at Microsoft.FSharp.Collections.SeqModule.ToList[T](IEnumerable`1 source)
at .$FSI_0006.main@()
```

#### Known workarounds

Run the code and realize you need to implement the interface `System.IComparable` on `Step`:
```fsharp
interface System.IComparable with
member a.CompareTo(b) =
match b with
| :? Step as b' -> compare a.Value b'.Value
| _ -> failwith "unsupported"
```

Or not using the `start .. step .. finish` operator, but generate the sequence somehow different (where `step` is not required to be comparable to `Zero` at runtime).

#### Related information

I had this issue when using 2 structs defined in C# and tried to iterate over them.

* Microsoft (R) F# Interactive version 10.2.3 for F# 4.5
* Microsoft Windows 10

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.