Modula-3: Subtyping rules

# Subtyping rules

We write `T <: U` to indicate that `T` is a subtype of `U` and `U` is a supertype of `T`.

If `T <: U`, then every value of type `T` is also a value of type `U`. The converse does not hold: for example, a record or array type with packed fields contains the same values as the corresponding type with unpacked fields, but there is no subtype relation between them. This section presents the rules that define the subtyping relation.

For ordinal types `T` and `U`, we have `T <: U` if they have the same basetype and every member of `T` is a member of `U`. That is, subtyping on ordinal types reflects the subset relation on the value sets.

For array types,

           (ARRAY OF)^m  ARRAY J_1 OF ... ARRAY J_n OF
              ARRAY K_1 OF ... ARRAY K_p OF T
        <: (ARRAY OF)^m  (ARRAY OF)^n
              ARRAY I_1 OF ... ARRAY I_p OF T

        if NUMBER(I_i) = NUMBER(K_i)  for i = 1, ..., p.

That is, an array type `A` is a subtype of an array type `B` if they have the same ultimate element type, the same number of dimensions, and, for each dimension, either both are open (as in the first m dimensions above), or `A` is fixed and `B` is open (as in the next n dimensions above), or they are both fixed and have the same size (as in the last p dimensions above).

       NULL <: REF T <: REFANY
       NULL <: UNTRACED REF T <: ADDRESS

That is, `REFANY` and `ADDRESS` contain all traced and untraced references, respectively, and `NIL` is a member of every reference type. These rules also apply to branded types.

        NULL <: PROCEDURE(A): R RAISES S   for any A, R, and S.

That is, `NIL` is a member of every procedure type.

        PROCEDURE(A): Q RAISES E  <:  PROCEDURE(B): R RAISES F
        if signature "(B): R RAISES F" covers signature "(A): Q RAISES E".

That is, for procedure types, `T <: U` if they are the same except for parameter names, defaults, and raises sets, and the raises set for `T` is contained in the raises set for `U`.

        ROOT <: REFANY
        UNTRACED ROOT <: ADDRESS
        NULL <: T OBJECT ... END <: T

That is, every object is a reference, `NIL` is a member of every object type, and every subtype is included in its supertype. The third rule also applies to branded types.

        BITS n FOR T <: T   and  T <: BITS n FOR T

That is, `BITS FOR T` has the same values as `T`.

        T <: T  for all T
        T <: U  and   U <: V  implies  T <: V  for all T, U, V.

That is, `<:` is reflexive and transitive.

Note that `T <: U` and `U <: T` does not imply that `T` and `U` are the same, since the subtype relation is unaffected by parameter names, default values, and packing.

For example, consider:

        TYPE
          T = [0..255];
          U = BITS 8 FOR [0..255];
          AT = ARRAY OF T;
          AU = ARRAY OF U;

The types `T` and `U` are subtypes of one another but are not the same. The types `AT` and `AU` are unrelated by the subtype relation.

    Last modified on Wed Apr  3 09:38:55 PST 1996 by heydon
         modified on Mon Apr 18 14:07:28 PDT 1994 by kalsow