Open JanWosnitza opened 5 years ago
This seems odd at first glance. The implementation of RangeStepGeneric
in prim-types.fs
, which is called in this case for (.. ..)
, uses =
, >
, and <
on step
, which would normally force the equality
and comparison
constraints to bubble up:
The signature for (.. ..)
in prim-types.fsi
, however, specifies neither the equality
constraint nor the comparison
constraint for ^Step
, unless ^Step
is unified with ^T
. I wonder if that plays into it at all?
It would be a compile-time breaking change to update the signature for (.. ..)
to include and ^Step: equality and ^Step: comparison
, but since any existing code where ^Step
doesn't conform to those constraints already fails at runtime, maybe it could be done?
It seems like auto-inference doesn't add the and ^Step: comparison
. Normally that happens automatically if you use it (and it is used, as you mention):
> let foo a b = a > b;;
val foo: a: 'a -> b: 'a -> bool when 'a: comparison
But also note that the *.fsi
file has and default ^Step: ^T
. This should be enough to infer that ^Step
requires equality
and comparison
as well. Is this a bug in using the default ^X: ^Y
syntax?
@brianrourkeboll, I don't know if you tested the OP's example code, but I just tried it with the latest from main
and it throws another tantrum:
error FS0193: The member or object constructor 'op_Addition' is not public. Private members may only be accessed from within the declaring type. Protected members may only be accessed from an extending type and cannot be accessed from inner lambda expressions.
This member is clearly accessible...
This, I think, is a regression. I cannot repro this with the latest RTM of F#.
I don't know if you tested the OP's example code, but I just tried it with the latest from
main
and it throws another tantrum:error FS0193: The member or object constructor 'op_Addition' is not public. Private members may only be accessed from within the declaring type. Protected members may only be accessed from an extending type and cannot be accessed from inner lambda expressions.
Hmm, I do not get that when using a VSIX built from main
in the last week or two.
Ok, this is weird.
I pasted it under module internal RangeTestsHelpers =
in the test file PrimTypes.fs
. Now, I would argue that any internal code should be accessible from other internal code, but this is likely a different issue and should be reported separately.
Once I put the code in a public module, it worked as expected.
Note that, if I change the definition to be this (as you suggested):
val inline (.. ..): start: ^T -> step: ^Step -> finish: ^T -> seq< ^T >
when (^T or ^Step): (static member (+): ^T * ^Step -> ^T)
and ^Step: (static member Zero: ^Step)
and ^T: equality
and ^T: comparison
and ^Step: equality
and ^Step: comparison
and default ^Step: ^T
and default ^T: int
it will behave as the OP suggested (though the error is thrown 8 times???)
error FS0193: The type 'Step' does not support the 'comparison' constraint. For example, it does not support the 'System.IComparable' interface
I pasted it under
module internal RangeTestsHelpers =
in the test filePrimTypes.fs
. Now, I would argue that any internal code should be accessible from other internal code, but this is likely a different issue and should be reported separately.
That seems to be #16762.
Operators.( .. .. )
throws anArgumentException
when^Step
does not implement non-genericSystem.IComparable
.Repro steps
Run the following code:
Expected behavior
I would expect a compiler error. Similar to
Step.Zero
not implementedValue.(+)
not implementedValue
not implementingSystem.IComparable
Actual behavior
The last line throws this exception:
Known workarounds
Run the code and realize you need to implement the interface
System.IComparable
onStep
:Or not using the
start .. step .. finish
operator, but generate the sequence somehow different (wherestep
is not required to be comparable toZero
at runtime).Related information
I had this issue when using 2 structs defined in C# and tried to iterate over them.