Skip to content

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

@JanWosnitza

Description

@JanWosnitza

Operators.( .. .. ) throws an ArgumentException when ^Step does not implement non-generic System.IComparable.

Repro steps

Run the following code:

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 <StartupCode$FSI_0006>.$FSI_0006.main@()

Known workarounds

Run the code and realize you need to implement the interface System.IComparable on Step:

    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

Metadata

Metadata

Assignees

Labels

Area-LibraryIssues for FSharp.Core not covered elsewhereBugImpact-Low(Internal MS Team use only) Describes an issue with limited impact on existing code.

Type

Projects

Status

New

Relationships

None yet

Development

No branches or pull requests

Issue actions