Lady Ada

Ada '83 Language Reference Manual

Copyright 1980, 1982, 1983 owned by the United States Government. Direct reproduction and usage requests to the Ada Information Clearinghouse.

3.3. Types and Subtypes


A type is characterized by a set of values and a set of operations.

There exist several classes of types. Scalar types are integer types, real types, and types defined by enumeration of their values; values of these types have no components. Array and record types are composite; a value of a composite type consists of component values. An access type is a type whose values provide access to objects. Private types are types for which the set of possible values is well defined, but not directly available to the users of such types. Finally, there are task types. (Private types are described in chapter 7, task types are described in chapter 9, the other classes of types are described in this chapter.)

Certain record and private types have special components called discriminants whose values distinguish alternative forms of values of one of these types. If a private type has discriminants, they are known to users of the type. Hence a private type is only known by its name, its discriminants if any, and by the corresponding set of operations.

The set of possible values for an object of a given type can be subjected to a condition that is called a constraint (the case where the constraint imposes no restriction is also included); a value is said to satisfy a constraint if it satisfies the corresponding condition. A subtype is a type together with a constraint; a value is said to belong to a subtype of a given type if it belongs to the type and satisfies the constraint; the given type is called the base type of the subtype. A type is a subtype of itself; such a subtype is said to be unconstrained: it corresponds to a condition that imposes no restriction. The base type of a type is the type itself.

The set of operations defined for a subtype of a given type includes the operations that are defined for the type; however the assignment operation to a variable having a given subtype only assigns values that belong to the subtype. Additional operations, such as qualification (in a qualified expression), are implicitly defined by a subtype declaration.

Certain types have default initial values defined for objects of the type; certain other types have default expressions defined for some or all of their components. Certain operations of types and subtypes are called attributes; these operations are denoted by the form of name described in section 4.1.4.

The term subcomponent is used in this manual in place of the term component to indicate either a component, or a component of another component or subcomponent. Where other subcomponents are excluded, the term component is used instead.

A given type must not have a subcomponent whose type is the given type itself.

The name of a class of types is used in this manual as a qualifier for objects and values that have a type of the class considered. For example, the term "array object" is used for an object whose type is an array type; similarly, the term "access value" is used for a value of an access type.


The set of values of a subtype is a subset of the values of the base type. This subset need not be a proper subset; it can be an empty subset.

References: access type, array type, assignment, attribute, component of an array, component of a record, discriminant constraint, enumeration type, integer type, object, private type, qualified expression, real type, record type, subtype declaration, task type, type declaration.

Rationale references: 4.1 Introduction, 4.2 The Concept of Type, 4.3 Type Equivalence, 4.4 Constraints and Subtypes

Style Guide references: 3.2.2 Type Names, 3.4.1 Declaring Types, 4.1.5 Cohesion, 7.2.7 Subexpression Evaluation, 8.2.3 Assumptions, 9.1.5 Constraint Checking


3.3.1. Type Declarations


A type declaration declares a type.

    type_declaration ::=  full_type_declaration
       | incomplete_type_declaration | private_type_declaration 

    full_type_declaration ::=
         type identifier [discriminant_part] is type_definition; 

    type_definition ::=
         enumeration_type_definition | integer_type_definition
       | real_type_definition        | array_type_definition
       | record_type_definition      | access_type_definition
       | derived_type_definition 

The elaboration of a full type declaration consists of the elaboration of the discriminant part, if any (except in the case of the full type declaration for an incomplete or private type declaration), and of the elaboration of the type definition.

The types created by the elaboration of distinct type definitions are distinct types. Moreover, the elaboration of the type definition for a numeric or derived type creates both a base type and a subtype of the base type; the same holds for a constrained array definition (one of the two forms of array type definition).

The simple name declared by a full type declaration denotes the declared type, unless the type declaration declares both a base type and a subtype of the base type, in which case the simple name denotes the subtype, and the base type is anonymous. A type is said to be anonymous if it has no simple name. For explanatory purposes, this reference manual sometimes refers to an anonymous type by a pseudo-name, written in italics, and uses such pseudo-names at places where the syntax normally requires an identifier.

Examples of type definitions:

    range1 .. 72
    array(1 .. 10) of INTEGER 

Examples of type declarations:

    type COLUMN is range 1 .. 72;
    type TABLE  is array(1 .. 10) of INTEGER; 


Two type definitions always define two distinct types, even if they are textually identical. Thus, the array type definitions given in the declarations of A and B below define distinct types.

    A : array(1 .. 10) of BOOLEAN;
    B : array(1 .. 10) of BOOLEAN; 

If A and B are declared by a multiple object declaration as below, their types are nevertheless different, since the multiple object declaration is equivalent to the above two single object declarations.

    A, B : array(1 .. 10) of BOOLEAN;                                                 

Incomplete type declarations are used for the definition of recursive and mutually dependent types (see 3.8.1). Private type declarations are used in package specifications and in generic parameter declarations (see 7.4 and 12.1).

References: access type definition, array type definition, base type, constrained array definition, constrained subtype, declaration, derived type, derived type definition, discriminant part, elaboration, enumeration type definition, identifier, incomplete type declaration, integer type definition, multiple object declaration, numeric type, private type declaration, real type definition, reserved word, type.

Style Guide references: 3.3.5 Data Comments

3.3.2. Subtype Declarations


A subtype declaration declares a subtype.

    subtype_declaration ::=
       subtype identifier is subtype_indication; 

    subtype_indication ::=  type_mark [constraint] 

    type_mark ::= type_name | subtype_name 

    constraint ::=
         range_constraint | floating_point_constraint | fixed_point_constraint
       | index_constraint | discriminant_constraint 

A type mark denotes a type or a subtype. If a type mark is the name of a type, the type mark denotes this type and also the corresponding unconstrained subtype. The base type of a type mark is, by definition, the base type of the type or subtype denoted by the type mark.

A subtype indication defines a subtype of the base type of the type mark. If an index constraint appears after a type mark in a subtype indication, the type mark must not already impose an index constraint. Likewise for a discriminant constraint, the type mark must not already impose a discriminant constraint.

The elaboration of a subtype declaration consists of the elaboration of the subtype indication. The elaboration of a subtype indication creates a subtype. If the subtype indication does not include a constraint, the subtype is the same as that denoted by the type mark. The elaboration of a subtype indication that includes a constraint proceeds as follows:

  1. The constraint is first elaborated.
  2. A check is then made that the constraint is compatible with the type or subtype denoted by the type mark.
The condition imposed by a constraint is the condition obtained after elaboration of the constraint. (The rules of constraint elaboration are such that the expressions and ranges of constraints are evaluated by the elaboration of these constraints.) The rules defining compatibility are given for each form of constraint in the appropriate section. These rules are such that if a constraint is compatible with a subtype, then the condition imposed by the constraint cannot contradict any condition already imposed by the subtype on its values. The exception CONSTRAINT_ERROR is raised if any check of compatibility fails.

Examples of subtype declarations:

    subtype RAINBOW   is COLOR range RED .. BLUE;        --  see 3.3.1
    subtype RED_BLUE  is RAINBOW;
    subtype INT       is INTEGER;
    subtype SMALL_INT is INTEGER range -10 .. 10;
    subtype UP_TO_K   is COLUMN range 1 .. K;            --  see 3.3.1
    subtype SQUARE    is MATRIX(1 .. 10, 1 .. 10);       --  see 3.6
    subtype MALE      is PERSON(SEX => M);               --  see 3.8


A subtype declaration does not define a new type.

References: base type, compatibility of discriminant constraints, compatibility of fixed point constraints, compatibility of floating point constraints, compatibility of index constraints, compatibility of range constraints, constraint_error exception, declaration, discriminant, discriminant constraint, elaboration, evaluation, expression, floating point constraint, fixed point constraint, index constraint, range constraint, reserved word, subtype, type, type name, unconstrained subtype.

Style Guide references: 5.3.1 Derived Types and Subtypes, 5.5.1 Range Values, 5.6.3 Case Statements, 5.7.2 The Renames Clause, 7.2.7 Subexpression Evaluation, 9.1.5 Constraint Checking

3.3.3. Classification of Operations


The set of operations of a type includes the explicitly declared subprograms that have a parameter or result of the type; such subprograms are necessarily declared after the type declaration.

The remaining operations are each implicitly declared for a given type declaration, immediately after the type definition. These implicitly declared operations comprise the basic operations, the predefined operators (see 4.5), and enumeration literals. In the case of a derived type declaration, the implicitly declared operations include any derived subprograms. The operations implicitly declared for a given type declaration occur after the type declaration and before the next explicit declaration, if any. The implicit declarations of derived subprograms occur last.

A basic operation is an operation that is inherent in one of the following:

For every type or subtype T, the following attribute is defined:


Each literal is an operation whose evaluation yields the corresponding value (see 4.2). Likewise, an aggregate is an operation whose evaluation yields a value of a composite type (see 4.3). Some operations of a type operate on values of the type, for example, predefined operators and certain subprograms and attributes. The evaluation of some operations of a type returns a value of the type, for example, literals and certain functions, attributes, and predefined operators. Assignment is an operation that operates on an object and a value. The evaluation of the operation corresponding to a selected component, an indexed component, or a slice, yields the object or value denoted by this form of name.

References: aggregate, allocator, assignment, attribute, character literal, composite type, conversion, derived subprogram, enumeration literal, formal parameter, function, indexed component, initial value, literal, membership test, and 4.5.2, null literal, numeric literal, numeric type, object, and 6.1, predefined operator, qualified expression, selected component, short-circuit control form, and 4.5.1, slice, string literal, subprogram, subtype, type, type declaration, universal_integer type, universal_real type, universal type, and 4.


[Ada Information Clearinghouse]

Address any questions or comments to