New Issue: Static array and domain types

20250, "vasslitvinov", "Static array and domain types", "2022-07-19T04:58:36Z"

This is a gentler alternative to #19292. This proposal allows us to address the runtime-type-related issues in semantics and implementation and to "legalize" skyline arrays, de-facto available since #8073.

Basic Principles

We propose to introduce static array and domain types as distinct from runtime types. The static types are available during compilation, with user-facing semantics.

  • Each runtime type has a corresponding static type. The static type is obtained from a runtime type by discarding the runtime component.

  • The type of an expression is a runtime type only in the cases where the runtime component is available. Otherwise it is a static type.

  • Generic types - other than array/domain types - are always instantiated with static types.

  • When the type of a variable is declared with a static array/domain type, it cannot be default-initialized.
    Here "variable" includes fields, tuple components, array elements, and formals.

Details

  • Even though a generic type is instantiated with static type(s), runtime type(s) can sometimes be obtained from values of this type. For example:
var A: [D] real;
type RTT = A.type;                   // RTT is a runtime array type
type STT = the static type of A;     // STT is a static array type

record R1 { type t; }

var r1 = new R1(RTT);    // r1.type   = R1(STT)
                         // r1.type.t = STT
                         // r1.t      = RTT  <----- based on the value r1

type T1 = R1(RTT);       // T1   = R1(STT)
                         // T1.t = STT

record R2 { var x; }

var  r2 = new R2(A);     // r2.type   = R2(STT)
                         // r2.x.type = RTT  <----- based on the value r2.x

type T2 = R2(RTT);      // T2   = R2(STT)
                        // T2.x = STT
  • Consider a variable declared with a static array/domain type. Once it is initialized, aVariable.type returns a runtime type. This runtime type is derived from the value held in aVariable.

  • An array/domain-typed field in a record can be default-initialized as long as there is a corresponding runtime type coming into the initializer. For example:

record R3 {
  type t;
  var x: t;
  proc init(type t) {
    this.t = t;
    // x is default-initialized
  }
}
                               
var r3 = new R3(myArray.type); // default initialization is OK because
                               // `t` is a runtime type in the initializer
// runtime types: r3.t, r3.x.type
// static types: r3.type.t, R3(myArray.type).t, R3(myArray.type).x
  • Skyline arrays are where this proposal shines. The element type of a skyline array is a STATIC array type. We cannot get to the domain of the element type from the type of the skyline array itself. Cf. the runtime type of a given element of a skyline array A is available as A[i].type.

  • When an array stores an iterable expression with array elements, the enclosing array's element type is static. This is somewhat similar to skyline arrays.

  • A static array type could be written as [domain(2)] real.

  • We could introduce a built-in method EXPR.staticType that produces the static type when EXPR is an array/domain value or type. In the other cases it is the same as EXPR.type.

Related issues

Bugs:
#11549 handle record and class types with runtime types
#15929 Problem with runtime type and default initialization
#20050 internal compiler error / instantiating a type field with an array type

Semantics:
#8152 what should .eltType do for skyline arrays?
#11220 Runtime type for an array of arrays

Skyline-related:
#11254 forall-over-forall results in empty array
#11039 for/forall expression with arrays as elements does not work
#11884 avoid extra iterator invocation upon reduce
#11882 avoid evaluating the argument of .type (see the discussion)