New Issue: Chapel 2.0: Is the interpretation of 'R' for a generic record/class type that's not fully defaulted correct?

18214, "bradcray", "Chapel 2.0: Is the interpretation of 'R' for a generic record/class type that's not fully defaulted correct?", "2021-08-12T23:06:52Z"

This is something that I seem to have internalized incorrectly, which makes me want to check that it was by design rather than by accident before declaring Chapel 2.0:

If a record R is generic, but all its generic fields have defaults, as here:

record R {
  type t = int;
  param rank: int = 2;
}

then we interpret R as being R(int, 2) when used as a type constraint. The rationale here was to permit a user to create their own int-style type as a record, in the sense that it would have a default (e.g., int(64)) that could be made available for convenience as a shorthand (e.g., int), while still supporting explicit variants (e.g., R(real, 2), R(int, 3)). If someone wants to indicate a generic R, they should use R(?) or R(?t, ?rank) or the like.

I really like the above and am not personally second-guessing it. Note that our built-in range type currently is considered to be fully defaulted (int indices, bounded, non-stridable), which means that declarations like var r: range; are legal, but also that var r: range = 1..n by 2; generates an error.

Now, if R is generic, but none of its generic fields have default, such as:

record R {
  type t;
  param rank: int;
}

then R is interpreted as being the same as R(?) (rather than, say, not being a legal type specifier because it wasn't complete in and of itself like in the previous case).

I think that this is probably right and am definitely open to it ("why make people type more than they have to?")—and would prefer not to change things of this magnitude at this point. But I wanted to be sure since I had mis-internalized this as not being a well-defined type-constraint. Note that our built-in domain type—while not a typical record—follows this behavior in that domain is treated as "any domain".

Finally, if its generic, but some of its generic fields are lacking a default, such as:

record R {
  type t;
  param rank: int = 2;
}

then R is again interpreted as being the same as R(?) (rather than, say, being interpreted as R(?t, 2)).

This case is perhaps slightly less comfortable to me since it feels like it doesn't quite sit cleanly between the previous two cases (the defaulted case is not a constraint; yet it's no different than nothing being a default). But if others felt strongly that this was the right thing, I'd be happy for an excuse not to change it. It just hasn't landed neatly in my mind.

Add some tests exhibiting meaning of generic type constraints by bradcray · Pull Request #18213 · chapel-lang/chapel · adds some tests that exercise these possibilities.