17842, "vasslitvinov", "IFC: how to write an interface-constrained function min() ?", "2021-05-27T22:49:16Z"
main issue: #8629 related: #17262 #17540 #17599
Splitting this issue from CG: semantics of 'implements' with a class · Issue #17262 · chapel-lang/chapel · GitHub
Background
If I have a "comparable" interface, I can write a min() function that takes two comparables:
interface Comparable {
operator <(lhs: Self, rhs: Self): bool;
}
proc minFn(x: ?T, y: T): T
where T implements Comparable
{
if x < y then return x; else return y;
}
This works fine if I am dealing just with numbers. This even works with POD records. (It escapes me However, it hits an error when I implement Comparable
for an owned
class.
Questions
This leads me to these questions:
- Is it reasonable for a user to write the above code?
- If so, what should be the compilation outcome - success, error, what error?
- How to make the above code work with
owned
?
Proposal how to handle the code as-is
I suggest that the above code is reasonable and should compile successfully.
I also suggest that it should generate an EARLY-checking error message when there is a possibility of minFn to be invoked on an owned object. For example, if I declare implements Comparable(owned MyClass)
. In such a case the compiler currently issues a late-checking error, i.e., only if the minFn()
is invoked on owned MyClass
.
One way to get there is to introduce an interface denoting a "normal" type - i.e. a type that can be assigned, copied, etc. Each interface formal could be implicitly required to satisfy this interface unless opted out. If the interface constraints of minFn()
allow non-"normal" argument types, the compiler should report an early error. owned
types would not be able to implement this normal-type interface.
How to make minFn() accept owned
One way is to have the user rewrite it with in-intents:
proc minFn(in x: ?T, in y: T): T where .......
{
if x < y then return x; else return y;
}
This works, however it is perhaps not the intended behavior because this minFn takes over the ownership of both arguments then returns one and deletes the other.
Another way is to have the Comparable
interface be implemented for a borrowed
type, then allow implicit conversions, see #17540, when operator <
or proc minFn
are passed class types.