17599, "vasslitvinov", "CG: how/when to do lifetime checking on an IC function", "2021-04-24T04:35:42Z"
main issue: #8629 related: #17037
Should early-resolution of an interface-constrained function include analyses such as lifetime and nilability checking?
Argument in favor: we would like the compiler catch as many errors as possible. If the compiler does not do early lifetime checking, the user may not know that there is a problem in their library until somebody else uses it with a class type.
Argument against: if the user who is writing generic code for their own use has never heard about classes in Chapel, they should not have to deal with nilability errors that the generic code would have if instantiated with nilable classes.
For example, if the user wrote something like this:
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;
}
we want to support both cases:
-
minFn()
is not intended to be instantiated with class types, so it should pass early checking -
minFn()
should be invocable on classes, includingowned
classes, so should not type-check
because it would want to take over the ownership from one of the formals,
however the formals are read-only, so cannot yield ownership
The current proposal is to assume one of these cases by default and require the author of the interface-constrained function to opt into the other case using predefined interface constraints. For example: an IC function cannot be instantiated with class type(s) unless it includes the constraint(s) that its generic type(s) implement certain predefined interface(s). We can predefine an interface accepting any class type, any non-nilable class type, any class type of specific memory management kind, etc. Such restriction and interfaces should transitively apply to records, arrays, tuples containing class types.
Should the default case favor:
- simple uses of interface-constrained generics, or
- breadth of applicability of generic code?
Rust trivia: it has only one "negative" constraint -- "sizeable", which states that the size of the data type may be unknown at compile time.