Type Compatibility for Extensible Module Types, Their Reference Parameters, and Their Pointer Types

: Objects in object-oriented languages have often been treated as a special kind of entity different from other variables or constants. Similarly, their types, which are typically called classes, have often been treated differently from other types. This complicates the understanding of these concepts. The present paper proposes to see the classes as module types leading to a very natural integration of objects and classes into the framework of contemporary programming languages. The main part of the paper contains typing rules for module types for assignment and for value and variable parameters. It is shown that the rules for reference parameters in some existing languages lead to unexpected results and sometimes to undefined behavior. Furthermore, assignment involving dereferenced pointers to modules is studied for the first time in detail. The paper shows that the type compatibility rule for pointer assignment is not sufficient for deref assignment. The last part of the paper contains a comparison of the language definitions and of compilers for Borland Pascal with Objects, C++, Oberon, and Object CHILL.


Introduction
Objects in object-oriented languages have often been treated as a special kind of entity different from other variables or constants.Similarly, their types, which are typically called classes, have often been treated as a special kind of type.This complicates the understanding of these concepts.The present paper proposes to see the classes as module types leading to a very natural integration of objects and classes into the framework of contemporary programming languages.The main part of the paper deals with type compatibility rules for extensible module types.We show that some languages use compatibility rules for reference parameters which lead to unexpected results and sometimes to undefined behavior.We show especially that reference parameters are not pointers.Furthermore, assignment involving dereferenced pointers to modules is studied for the first time in detail.The paper shows that the type compatibility rule for pointer assignment is not sufficient for deref assignment.The last part of the paper contains a comparison of the language definitions and of compilers for Borland Pascal with Objects, C++, Oberon, and Object CHILL.
The formalisms used are all defined in the paper.We assume a general familiarity with the basic concepts of object-orientation.For program examples we use a suggestive syntax which should be self explanatory.For easier reference for the reader the central definitions of the paper are collected in the Appendix.
Despite the assumed familiarity with the basic concepts of object-orientation we mention four essential concepts of OO which are relevant to the topics of this paper: a) module as first class value: modules as values of variables, as parameters, and as the target value of a pointer; b) type derivation and substitutivity: wherever an object OTb of a (base) type Tb is used an object OTd of a (derived) type Td can be used instead; c) reimplementation of operations in derived types: an operation O defined in a type Tb may be given a new implementation (body) in a derived type Td; d) combination of reimplementation and substitutivity (polymorphism): if an operation O is applied to a variable, which may refer to objects of different (but usually related) types, then the implementation belonging to the type of the current object is used, i.e. depending on the type of the current object one of possibly several different implementations of that operation is used.

Why Module Types ?
In this paper we use the term module type for what is often called class or object type in object-oriented languages.There are several reasons for this.First, object usually has a very general meaning: "something physical or mental of which a subject is cognitively aware" (Merriam Webster New Collegiate Dictionary, 1977: 791).In the field of programming languages object is also often used in a more general sense: "An object is an entity that contains (has) a value of a given type."or "An object declaration creates one or more variables.These variables can be of any type and need not just be instances of classes."[CW 96: 76].This general meaning of "object" seems to be appropriate, and this is the reason not to adopt e.g. the term "object type" [CDG 92: 19].In object-oriented languages object is used more narrowly for one special kind of such objects, namely for variables or constants of so called classes."An object is a class instance or an array."[GJS 96: 38].Sometimes the term object is even used with several meanings: "From now on, object will have a precise meaning: a record with procedure fields, accessed through a pointer."[RW 92: 218], "Declarations also serve to specify certain permanent properties of an object, such as whether it is a constant, a type, a variable or a procedure."[RW 92: 284].
The second reason is that of all the different entities in contemporary programming languages the objects of object-oriented languages resemble mostly the modules of CHILL [Rec 93] or Modula [Wir 88b] (package in Ada [Ref 83], unit in Borland Pascal with Objects [Bor 93]).This resemblance can be characterized by the key concepts "aggregation", "encapsulation/abstraction", and "scoping".The relation between module and module type is very much the same as that between a record variable and a record type. ) the procedures are isolated from the data components, whereas in an object in a typical OO language the data components are automatically visible in the bodies of the procedure components.

Typing
In programming languages with typing entities may be typed.The type T of a typed entity describes the set of admissible values T V and the set of operations T O involving those values.A type may be static, i.e.T O and especially T V are a static property, or it may be dynamic.The language is strongly typed if type errors are always detected [Seb 93: 151].There is a preference for static properties because they can be checked at compile time.But not all aspects of types are static properties.In Ada e.g. for a range type the set T V may only be fixed at runtime but the type of the values is fixed statically: TYPE IntRange IS Integer RANGE 1..ReadAnInteger; In this example the values of IntRange will always be integer numbers but the set T V is only fixed at runtime (and may even be empty).
In general, a variable V may therefore have a static type ST(V) and also a dynamic type DT(V).The application of an operation is legal if the static types of all operands and the result (if there is one) are correct with respect to the static semantics of the language.The application of an operation is safe if all operands and the result (if there is one) have values within their types.The application of an operation is statically safe if safety is a static property; it is dynamically safe if it is not statically safe and safety is guaranteed by dynamic checks.

Remarks:
(a) Safety is used here only with respect to typing; i.e. it should not be confused with the much broader meaning of safety in the term software safety.
(b) in this paper we always use simple variables.All observations and results also hold for variables which are components of larger variables as e.g.records or arrays.

Basic Properties of Module Types
A module type MT is characterized by its set of components: There are two important subsets of a module type: If id is the identifier of a component in E(MT) MV.id is an access to this component.Outside the definition of MT such an access is legal for all elements of E(MT) but not for those in CS(MT) -E(MT).These are called the internal components.In some languages the internal components are further divided into different groups but this is of no importance to the topic of this paper.
V(MT) ⊆ CS(MT) is the set of variable components.
A variable component of MV may assume different values as is typical for variables.In most cases the variable components are data variables but there may also be variable components of procedure or module type.It depends on the specific language and its type system which kinds of variable components are possible.
There is no fixed relationship between E(MT) and V(MT).
A type MTd may be directly derived from a given type MTb.There exist different solutions for these problems, e.g. to forbid the critical situation, to allow the introduction of aliases for such components in MTd, or to give priority to one of the replicas.For the following we assume that these visibility problems have been solved and especially, that there are not several replicas of a component in one MT which have the same visibility status.The semantics of multiple inheritance is then CS(MTd) ⊇ CS(MTb i ), for i = 1 .. n.For each component of MTd it is well defined from which MTb i it has been inherited.A type MTd is derived from another type MTb, MTd ≥ MTb, if MTd is either directly derived from MTb or if it is derived from a type MT which is directly derived from MTb.The derivation relation is restricted in such a way that its graph is a set of directed acyclic graphs, because the derivation of MT from MT, either directly or indirectly, is usually not allowed.We assume the direction of the arcs from MTd to MTb.In these DAGs the nodes with no successor are minimal wrt "≥" and the nodes with no predecessor are maximal.To each element e of these DAGs belongs a nonempty set of minimal elements min(e) and a nonempty set of maximal elements max(e).We use MT1 > MT2 as an abbreviation for MT1 ≠ MT2 ∧ MT1 ≥ MT2.Remark: The relation ≥ is sometimes defined the other way round.The definition here is motivated by the relation between the sets of components: This monotonicity of derivation wrt to the component set is fundamental to the topics and results of this paper (e.g. for substitutivity).For the topic of this paper it is important that the derivation has additionally the following monotonicity properties:

Monotonicity of the variable components)
There are languages for which MonE does not always hold (e.g. for private derivation in C++).MonV holds in most OO languages.In our framework here, MonV is a consequence of the semantics of inheritance.Because MonV is important for several properties discussed we have mentioned it particularly and given it an own name.
For pointer types of the kind "REF MT", where MT is a module type, we transfer the ordering relation: The ordering relation can be defined analogously for higher order pointers.For each pointer level ("REF MT", "REF REF MT", etc.) we obtain a derivation graph isomorphic to that for the module types.A consequence of this correspondence are propositions as e.g.min("REF MT") = "REF min(MT)".
Modula-3 [CDG 92] and Java [GJS 96] see module types (actually called "object types" in Modula-3 and "class types" in Java) as a mixture of module type and "pointer to module type": assignment e.g. is pointer assignment, dereferencing is not possible, and "variable.component-id"accesses one of the components.Therefore, not all situations, which are investigated in this paper, are relevant to these two languages.

Example
In the rest of the paper we will refer to the following example of module types: It is straightforward to compute the different sets of components as in the preceding example.

Variables
If we declare a variable of type MT we may ask whether derivation has any influence on the type of this variable.For the declaration VAR MV: MT; we have the following two conditions: This means that MV is always of type MT as is typical for variables in typed languages.The value of MV is always a module of type MT.Therefore, derivation has no influence on the typing of variables of module type.The main reason to use these classical rules for the typing of variables of module type is one of implementation efficiency.It would be more complicated to implement the variables if the dynamic type could vary.This polymorphism is usually reserved for variables of type "pointer to module type" for which it is much easier to implement.Pointer types are treated in sect.6.The preceding paragraphs hold for both statically declared variables and dynamically created anonymous variables and for variables which are components of larger variables.

Assignment
In most languages with extensible types type compatibility for assignment is usually defined in a more relaxed form than for other types.This relaxation is due to the properties of the derivation relation.For an assignment of the form: where ST(LHS) and ST(RHS) are module types, we have the following rules.
If MonV holds, the assignment is statically safe.Since assignment means assignment of a copy of the corresponding components into the subcomponents of the variable LHS, the static type of LHS is not affected at all.Therefore this assignment is NOT an example of substitutivity.These rules are typically used in object-oriented languages with strong typing as e.g.Borland Pascal with Objects, C++, and Oberon.Object CHILL uses the stronger rule ST(LHS) = ST(RHS) because projection was not rated as very important by the first users of the language.Different systems have been developed using Object CHILL [GW 92], but none of the users missed projection.Java does not provide assignment for composite types [GJS 96: 41,460].
For the variables VAR MyFigure, YourFigure: BasicFigureType; VAR MyCircle: CircleType; the following assignments are legal and statically safe: On the other hand the following assignment is illegal: MyCircle := MyFigure; --which value should be --assigned to MyCircle.CurrentRadius ?

Parameters
The properties of a formal parameter FP of a procedure P are defined by its kind.The essential point is the mechanism of parameter association, i.e. the mechanism used to associate the formal parameter FP with the actual parameter AP given in a call ″P(FP => AP);".In the following we discuss two kinds of parameters, value parameters and reference parameters, because these two forms are mostly used in typed object-oriented languages.

Value Parameters
A procedure with a value parameter typically looks like: PROC P(FVP: MT); Body For value parameters parameter association is defined as follows: the call P(FVP => AVP); is equivalent to This means that "ST(FVP) = DT(FVP)" is an invariant in the scope of FVP.Often FVP is treated as a local variable (CHILL and Object CHILL, Pascal, Modula) and in other cases as a local constant (Ada).This difference is of no importance to the topic of this paper.What is important here is that parameter association is essentially the same as assignment.This observation suggests to use the same rules for typing and semantics as for assignment.This is typically done.Borland Pascal with Objects, C++, and Oberon use ST(FVP) ≤ ST(AVP) and projection, and Object CHILL uses ST(FVP) = ST(AVP).
If we have the following procedure P: are both legal and statically safe if the projection rule is used.
To call this parameter a "value parameter" is somewhat unfortunate because this term does not clearly describe the role FVP plays in P (as mentioned FVP is often a variable in the body of P).The term is mainly implementation oriented motivated by the fact that the value of the AVP is copied into the FVP.

Reference Parameters
The term reference parameter (sometimes also called variable parameter) is also an implementation oriented term but does not reflect the logic of parameter association.Reference parameters are used e.g. in CHILL, C++, Modula, Oberon, and Pascal.In Ada a more abstract view of formal parameters is used.For a reference parameter FRP in a procedure P A reference parameter FRP therefore has the following important properties: Ref1) FRP is a variable of type MT and not a reference or pointer; in this aspect it is similar to a value parameter.
Ref2) FRP is a new (additional) name for the variable identified by ARP, i.e. the connection between FRP and ARP is much more close than for a value parameter.One consequence of this property is that anywhere in the intersection of the scopes of FRP and ARP FRP can be replaced with ARP, or equivalently FRP=ARP is an invariant in this intersection.
A The problem which becomes manifest in the assignment (2) can already be observed in the declaration (1): if In assignments (2) and ( 3) ST(LHS) > ST(RHS) and V(ST(LHS)) ⊃ V(ST(RHS)) hold, which contradict the rule Ass1 given in sect.5.2.Assignment (3) is therefore especially dangerous because the implementation strategy for such assignments based on the rules MAss1 and MAss2 would assign an undefined value to Local- Circle.CurrentRadius.One solution to this problem is to check the assignment (3) dynamically.This would mean that a module assignment involving var parameters had to be implemented differently from a module assignment not involving such parameters.Apart from this, the conceptual problem of what the semantics of "VAR Circle: CircleType ALIAS MyFigure;" should actually be would still exist.Borland Pascal with Objects, C++, and Oberon use the following type compatibility rule for reference parameters: ST(FRP) ≤ ST(ARP) which can lead to the problem presented in example a).Object CHILL uses the type compatibility rule ST(FRP) = ST(ARP) which guarantees that assignments involving reference parameters of module type are statically safe if the rules for assignment given in sect.5.2 hold.We discuss this problem further in sect.7 after we have discussed the typing rules for pointer-to-module types in sect.6.

Function result
In strongly typed procedural languages a function behaves very much in the same way as a variable, where the result type of the function corresponds to the type of the variable.Therefore MVar1 and MVar2 should also hold for function result.

Typing Rules for Pointer-to-Module Types
In object-oriented languages pointer-to-module types (PTMT) are typically treated differently from other pointer types.The reason is the following.The types of a derivation tree are logically related to each other in very much the same way as the variants of a record type with variants in Ada or Pascal.The variants of such a record type with variants are defined within one type: We have seen in sect.5.1 that such a polymorphism is typically not defined for variables of module type.The reason is that the variants are more isolated when they are defined via derivation.( This greater isolation has also some advantages but this is of no importance to the topic of this paper.)After the definition of the root type of a derivation hierarchy, as e.g.BasicFigure in the running example, the set of variants is not fixed but may be extended by the definition of additional derived types.Such derived types may even be defined in other or as other compilation units.This is the reason that implementation is more complicated than for record types with variants.
For PTMT the situation is simpler because the representation of a pointer value usually uses the same amount of storage even if the type of the value pointed to varies.This observation allows a polymorphism as used for record variables in the preceding assignment to be used for PTMT variables.

Variables
For a variable of a PTMT

VAR PV: REF MT;
typing is defined by a more relaxed rule: PV may assume pointers pointing to variables of any type MTp ≥ MT.Therefore the following is legal: The set of admissible values of a PTMT "REF MT" can be characterized by: For a variable PV of a PTMT the following condition holds: PPoly) DT(PV) ≥ ST(PV) is an invariant in the scope of PV.
The variability of the dynamic type of a PTMT variable together with the reimplementation of procedures is the technical basis for polymorphism.
If any PTMT variable PV is initialized with nil in its declaration then DT(PV) ≥ ST(PV) holds after the declaration of PV.
We assume that all pointer values ≠ nil are created by the operation NEW.An expression "NEW MT" has the following property: We use a notation in which the dereferencing of a pointer is indicated explicitly: if PV is a pointer variable "PV↑" is the variable pointed to by PV.The rule PBasic is an implication of the rule MVar2 (sect.5.1), because for any PTMT variable PV "PV↑" is an MT variable.
As a reminder we remark that despite polymorphism a PTMT variable PV of static type "REF MT" usually provides only access to the elements of E(MT).A useful consequence of this rule is that due to MonE all accesses "PV↑.id" are statically safe independently of the dynamic type of PV.Despite this constraint polymorphism is a useful mechanism.It allows the aggregation of variables of different (but related) module types into one data structure as e.g. an array or a linked list.It is furthermore useful in combination with reimplementation of procedures.Sometimes the term "redefinition" is used instead of reimplementation, and in some languages such procedures are called virtual or dynamic procedures.We do not go into further details here because we assume the reader is familiar with the main concepts of objectorientation.

Assignment
If we have PTMT variables two forms of assignment have to be distinguished: a) LHS := RHS; where the type of LHS is a PTMT.This means that the assignment is on the level of pointer types.Therefore, this form of assignment is called pointer assignment.
b) LHS := RHS; where at least one of LHS and RHS has the form "expr↑" and the type of expr is a PTMT.This means that the assignment is on the level of module types and at least one of the operands is a dereferenced pointer whose type is a PTMT.Therefore, this form of assignment is called deref assignment.If neither LHS nor RHS has the form "expr↑" we have an assignment of the form which has been discussed already in sect.5.2 or a pointer assignment.
For the discussion of assignment it is helpful to distinguish between the state before the assignment and the state after the assignment.We use the following notation: LHS is the state of that entity before the assignment and LHS' is the state after the assignment.

Pointer Assignment
The discussion in sect.6.1 means that for pointer assignment for PTMT a more relaxed rule than for other pointer types applies.Let ST(LHS) and ST(RHS) be PTMTs.For an assignment of the form: LHS := RHS; we have the following rules.The type compatibility rule PAss1 allows for ST(LHS) > ST(RHS).In this case a dynamic check is necessary to guarantee the safety of the assignment, i.e.PPoly cannot be guaranteed statically.Some typed object-oriented languages (e.g.Borland Pascal with Objects, Eiffel, Oberon) use the type compatibility rule: PAss3) ST(LHS) ≤ ST(RHS) instead of PAss1.PAss3 is stronger than PAss1 and guarantees PPoly statically.For the moment we do not include parameters which are treated in sect.6.3.Therefore, PPoly can only be affected by the declaration and by assignment.
PROPOSITION 1: If PAss2 and PAss3 hold and any PTMT variable PV is initialized with nil, then PPoly is a static property in programs using declaration and assignment.PROOF: The proof is by induction on the sequence of operations manipulating one specific pointer value p.Such a sequence begins either with the declaration of PV, with an assignment of the form "PV := NEW MT;" or with an assignment of the form "PV := nil;".The other elements of the sequence all have the form "PV1 := PV2;" where p is the value of PV2.For any assignment "PV := RHS" we have ST(PV) = ST(PV').1) DT(PV) ≥ ST(PV) holds after the declaration (see sect.þ The rules PAss2, PAss3 and MonE ensure that pointer assignments and access to external entities of module variables pointed to by pointer variables are statically safe if only assignments are performed.The case of parameters will be discussed in sect.6.3.Object CHILL and Simula use a more relaxed type compatibility rule for pointer assignment: For PAss4 a dynamic check is necessary if ST(LHS) > ST(RHS).Rule PAss3 is essentially the same as MAss1.But there is a big difference between these two forms of assignment: • a variable VMT of a module type has always the same type ST(VMT), i.e.DT(VMT) = ST(VMT) is an invariant during the lifetime of VMT.• a variable VPMT of a PTMT is polymorphic which leads to the weaker invariant DT(VPMT) ≥ ST(VPMT).This means that, as has been described in sect.6.1, VPMT may point to variables of different module types.This observation is important for deref assignment.

Deref Assignment
A deref assignment is actually an assignment for module types, i.e.MAss1 and MAss2 must hold.The most general form of a deref assignment is PVL↑ := PVR↑; where both PVL and PVR are of type PTMT.We assume PVL and PVR are both ≠ nil, since otherwise the attempt to execute the statement will result in an error.As a consequence of MAss1 we obtain: ST(PVL↑) ≤ ST(PVR↑)

≡
[PBasic] deref(DT(PVL)) ≤ deref(DT(PVR)) ≡ [PDer] DT(PVL) ≤ DT(PVR).Even if we require ST(PVL) = ST(PVR) the deref assignment is not statically safe: þ PAss5 is a very strong restriction, but if it is not used a dynamic check is necessary, i.e.PAss5 is also necessary.This can be seen at the minimal derivation tree, which has one minimal node MT1 and more than one maximal nodes MT2 and MT3: means that the deref assignment is not safe because MT3 may contain a component not contained in MT2.On the other hand, a deref assignment is never safe if the two types are not on the same path.Therefore, PAss6) ST(PVL) and ST(PVR) are on the same path could be a minimal requirement to be checked statically.This rule is used in Object CHILL.

Value Parameters
For a value parameter of a PTMT the same observations as for module types apply: the value parameter is a local variable and the association between the formal parameter FVP and the actual parameter AVP is an assignment "FVP := AVP;".Therefore, the same rules as for pointer assignment can be used.

Reference Parameters
In sect.5.3.2 it is shown that ST(FRP) = ST(ARP) must hold, due to the alias relation between FRP and ARP.This rule is used in Borland Pascal with Objects, C++, Oberon, and Object CHILL.It is easy to give examples where weaker rules lead to illegal situations.One such example is given in [CCJ 93: 151].

PPoly as a Static Property
If for assignment to formal parameters the same rules hold as for variables PPoly is a static property.
PROPOSITION 3: If PAss2 and PAss3 hold and all PTMT variables PV are initialized with nil, then PPoly is a static property in programs using declaration, assignment, value parameters, and reference parameters.PROOF: The proof is by induction on the sequence S of operations manipulating one specific pointer value p. 1) Value parameter: an FVP is essentially a PTMT variable and the association with the AVP is essentially an assignment.Therefore, all possible steps of S involving an FVP are already covered by the proof of Prop.1.2) Reference parameter: an FRP is essentially a PTMT variable and the association with the ARP is essentially aliasing.Since the proof of Prop.1 does not rely on the fact that there is only one identifier for a variable all possible steps of S involving an FRP are already covered by the proof of Prop.1.þ

Function Result
In strongly typed procedural languages a function behaves very much in the same way as a variable, where the result type of the function corresponds to the type of the variable.Therefore functions should be treated in the same way as variables.

Behavior in Different Languages
When discussing real languages we have to distinguish between the language definition and a compiler (or interpreter) for the language.

Languages
The tables 1 and 2 contain the compatibility rules for the languages Borland Pascal with Objects (BPO), C++, Oberon, and Object CHILL (OC) as they are given in the language definitions.     1 contains the rules for MTAssign in the column for DerefAssign but taking PBasic into account.We may stress that this is our own interpretation, the language definitions just do not answer this question explicitly.
Table 2 shows furthermore that BPO, C++, and Oberon use two different compatibility rules for reference parameters: a) if the type of the formal paramter is a MT the rule ST(FRP) ≤ ST(ARP) is used; b) if the type of the formal parameter is a PTMT the rule ST(FRP) = ST(ARP) is used (which is also used for all other types).As has already been mentioned in sect.5.3.2 the compatibility rule for RefPTMTPar is not fully compatible with the alias relation between FRP and ARP.The reason for this erroneous rule seems to be that reference parameters are mistaken for pointers ("Reference parameters (in Pascal and Modula called VAR-parameters) are considered as local pointers to which a reference to the actual parameter is assigned initially.It follows that the same relaxation holds for both value and reference parameters."[Wir 88a: 209]).The alias relation is in fact implemented very similar to a pointer but on language level it has a different meaning.

Compilers
The behavior of compilers for these four languages is given in Table 3.It shows that the behavior of some of these compilers differs from the corresponding language definitions.BPO: the compiler used is Borland Pascal with Objects V7.0 running under Windows 3.1 (case 33 could only be executed under MS DOS 6.0).All checks that looked as if they could be useful were activated.When using a deref assignment several assignments, which are illegal if the assignment is done directly, are executed (cases 11, 12, 15, 16)  ] also covers assignment, but it seems in a more limited form than in OOL, because the typing of the assignment is given by the rule "var(A) := A".In OOL assignment often includes projection when the type of the RHS is an extension of the type of the LHS.

Reference Parameters
The survey of the type compatibility rules in the four languages shows that three of them (BPO, C++, Oberon) have a rule for reference parameters of module type which may lead to situations with undefined behavior.The technical properties and consequences of this rule are: a) the rule interferes with the homogeneity of the language.In those three languages assignments between module variables are statically safe.The rule for reference parameters of module type makes assignments involving such parameters statically unsafe.Such parameters are conceptually conceived as variables but differ in their properties from other variables.b) more important is the fact that the statically declared type of a reference parameter of module type is no longer a static property; due to the aliasing the actual type may be different for different calls.
In C++ a special kind of values is used to realize the effect of reference parameters; these values are called references.When used as a formal parameter a reference to a module type is converted to "a reference to the base class sub-object of the derived class object" [ES 90: 38,49].No precise definition of the sub-object is given.The compiler does obviously not generate any code for this conversion.Therefore, this sub-object is a sort of hybrid: the external interface is that of the basic type and the behavior is that of the derived type of the ARP.It is therefore possible to manipulate data components defined only in a derived type by calling a procedure which is reimplemented in the derived type and which manipulates such components.This has been validated by a corresponding experiment with the Borland C++ compiler.In order to produce a consistent sub-object the compiler should generate code to alter the pointer to the type descriptor such that it points temporarily to the descriptor of the base type.

Deref Assignment
It seems that up to now not all ramifications of the deref assignment have been seen.Table II suggests that BPO, C++, and Oberon use statically the same rule as for pointer assignment: ST(LHS) ≤ ST(RHS).Oberon, which does runtime checks, traps the erroneous cases (and one legal one (# 13)) at runtime.BPO and C++ (Borland) do not recognize the erroneous cases which are possible if only ST(LHS) ≤ ST(RHS) is checked at compile time.MAss2) Semantics: Assignment of corresponding variable components; this is called a projection because V(ST(LHS)) ⊂ V(ST(RHS)) is possible.This rule guarantees that MVar2 holds.

Ref1)
FRP is a variable of type MT and not a reference or pointer; in this aspect it is similar to a value parameter.

Ref2)
FRP is a new (additional) name for the variable identified by ARP, i.e. the connection between FRP and ARP is much more close than for a value parameter.One consequence of this property is that anywhere in the intersection of the scopes of FRP and ARP FRP can be replaced with ARP, or equivalently FRP=ARP is an invariant in this intersection.
PPoly) DT(PV) ≥ ST(PV) is an invariant in the scope of PV.

PNil
This defines a module type BasicFigureType which contains two components: the procedure Move and the variable CurrentPosition.The components of the external interface are written under the heading PUBLIC.There is one public component: the procedure Move.The internal components are written under the heading INTER- PROC P(Figure: BasicFigureType); BEGIN Figure.SetPosition(To => (1,4)); END P; the calls P(Figure => MyFigure); P(Figure => MyCircle); consequence of Ref2 is that ST(FRP) = ST(ARP) must hold.If ST(FRP) ≠ ST(ARP) were allowed the substitution (FRP → ARP) would give ST(ARP) ≠ ST(ARP), which is a clear contradiction.ST(FRP) = ST(ARP) holds for all kinds of types.The following examples show that weaker rules for parameter association lead to situations with undefined behavior.a) ST(FRP) ≤ ST(ARP) b) ST(FRP) ≥ ST(ARP) Example a) (ST(FRP) < ST(ARP)): => MyCircle);is now equivalent to the following block, in which the rule Ref2 has been applied to the parameterFigure:   to the alias relation between FRP and ARP, this is equivalent to: Figure denotes a variable of type BasicFigureType it cannot simultaneously denote a variable of type CircleType, which is different from BasicFigureType.Example b) (ST(FRP) > ST(ARP)): to the alias relation between FRP and ARP this equivalent to: type Figure is polymorphic in the following way.For a variable VAR MyFigure: Figure; the following assignments are legal and safe: This is possible because the set of variants is fixed in the definition of the type Figure.
points to a variable of --type CircleTypeTo describe this behavior we distinguish between the static type and the dynamic type of a PTMT variable.As for other variables the static type is fixed in the declaration: ST(PV) = "REF MT" and ST(PointerToFigure) = "REF BasicFigureType".On the other hand, the dynamic type may vary: PNew) ST("NEW MT") = DT("NEW MT") = "REF MT".For pointers the only operations are create, copy, and destroy.Therefore, a pointer value of type "REF MT" always points to a variable of type deref("REF MT") = MT.This gives us the basic property of PTMT variables: PBasic) PV ≠ nil ⇒ ST(PV↑) = DT(PV↑) = deref(DT(PV))
(PVL) and DT(PVR) are --not related at all!The only condition making a deref assignment statically safe under PPoly is PAss5) max(ST(PVL)) = { ST(PVR) } PROPOSITION 2: If PAss2 and PAss5 hold, then the deref statement "PVL↑ := PVR↑" is statically safe under PPoly.PROOF: Since the right hand side of PAss5 consists of a singleton set, ST(PVR) is the only leaf in the subtree whose root is ST(PVL).Therefore this tree consists just of the path from ST(PVL) to ST(PVR).If ST(PVR) is maximal PPoly implies DT(PVR) = ST(PVR).If we assume DT(PVL) > DT(PVR) this means that DT(PVL) > ST(PVR) which contradicts the fact that ST(PVR) is maximal.Therefore DT(PVL) ≤ DT(PVR) must hold and according to PBasic ST(PVL↑) ≤ ST(PVR↑), i.e.MAss1 holds.
" ≥ "REF MT2" :⇔ MT1 ≥ MT2.MVar1) ST(MV) = MT for VAR MV: MT; MVar2) ST(MV) = DT(MV) is an invariant during the lifetime of MV.MAss1) Type compatibility for MT assignment: ST(LHS) ≤ ST(RHS) ) ST(nil) ≥ PT and DT(nil) ≥ PT for any PTMT PT.PNew) ST("NEW MT") = DT("NEW MT") = "REF MT".PBasic) PV ≠ nil ⇒ ST(PV↑) = DT(PV↑) = deref(DT(PV)) These observations are the essential reason to use the term "module mode" in].(There are additionally monitor modes and task modes in CHILL-96, where, as in Algol 68, "mode" is used instead of "type".)The third reason is that the use of "module type" avoids the problematic term class [Win 92].Since the classes of object oriented languages are essentially types, i.e. descriptions describing the nature of variables (and constants), it seems very natural to use the term type also in this case.Other more recent approaches to objectorientation also avoid the term class [OMG 93].In rare cases there could be some misunderstanding because the term module is sometimes also used in a more general sense meaning a building block in general which could also encompass procedures.This view is especially used when speaking about linking several (object) modules into a single object program.Another possible name for this kind of type could be tuple type which is even more neutral than module type.From a somewhat abstract point of view the objects of object-oriented programming are (heterogeneous) tuples i.e. aggregations of components of possibly different type.The term tuple is also used in Linda[CG 89] and in[Car 93].There would be no problem to replace in this paper the term module type by tuple type.But this would not reflect the visibility properties of objects.In a tuple (e.g. a record with data and procedure components in Algol68 [KMP 69] or Modula-2[Wir 88b]

Table 1 .
Compatibility Rules for Assignments

Table 2 .
Compatibility Rules for ParametersBPO, C++, and Oberon define the same rules for MTAssign and for PTMTAssign.OC differs in both cases; MTAssign being more restrictive and PTMTAssign being more liberal.For DerefAssign the situation is different because this form of assignment is not explicitly mentioned in the language definitions.Since a DerefAssign is essentially an assignment on the level of module values Table . Other assignments, which are legally executed if the assignment is done directly, are flagged at compile time (cases 17, 18).In the case of a RefMTPar case 35 shows the problems discussed in sect.5.3.2.The test program contains the assignments "LocalVariable := Parameter;" and "Parameter := LocalVariable;".They are both executed without any warnings.

Table 3 .
Behavior of CompilersContinued on next page OC: the compiler used is Object-CHILL V3.01 running under OS/2 2.1.The generation of runtime checks for module types and PTMT was activated.The compiler and the generated programs comply with the language definition.Car 93].The type systems studied in these approaches usually deal with the types of simple and higher order functions.Practical OOL do mostly not support higher order functions in general but contain other elements which are not covered by the approaches based on FP, as e.g.assignment and pointers.Therefore, the approach of this paper and the approaches based on FP overlap only partially.Similar differences are also observed in[CCH 89a].The very comprehensive paper [Car 93] contains also a number of those concepts used in practical OOL.The paper [LW 93] is based on a "proof-theoretic" approach instead of a "modeltheoretic", on which the majority of work an typing is based.[LW 93] has a focus on assertions and does neither treat reference parameters nor pointers.Similarly, [PS 94] deals neither with reference parameters nor with pointers (in the sense that pointer level and the level of dereferenced pointers are distinguished).
b) Assignment is typically avoided in FP. [Car 93