Ada Resource Association
News and resources for the Ada programming language
Ada Reference ManualLegal Information
Contents   Index   References   Search   Previous   Next 

3.7 Discriminants

A composite type (other than an array or interface type) can have discriminants, which parameterize the type. A known_discriminant_part specifies the discriminants of a composite type. A discriminant of an object is a component of the object, and is either of a discrete type or an access type. An unknown_discriminant_part in the declaration of a view of a type specifies that the discriminants of the type are unknown for the given view; all subtypes of such a view are indefinite subtypes. 


discriminant_part ::= unknown_discriminant_part | known_discriminant_part
unknown_discriminant_part ::= (<>)
known_discriminant_part ::= 
   (discriminant_specification {; discriminant_specification})
discriminant_specification ::= 
   defining_identifier_list : [null_exclusionsubtype_mark [:= default_expression]
 | defining_identifier_list : access_definition [:= default_expression]
default_expression ::= expression

Name Resolution Rules

The expected type for the default_expression of a discriminant_specification is that of the corresponding discriminant. 

Legality Rules

A discriminant_part is only permitted in a declaration for a composite type that is not an array or interface type (this includes generic formal types). A type declared with a known_discriminant_part is called a discriminated type, as is a type that inherits (known) discriminants. 
The subtype of a discriminant may be defined by an optional null_exclusion and a subtype_mark, in which case the subtype_mark shall denote a discrete or access subtype, or it may be defined by an access_definition. A discriminant that is defined by an access_definition is called an access discriminant and is of an anonymous access type. 
  Default_expressions shall be provided either for all or for none of the discriminants of a known_discriminant_part. No default_expressions are permitted in a known_discriminant_part in a declaration of a tagged type or a generic formal type.
 A discriminant_specification for an access discriminant may have a default_expression only in the declaration for a task or protected type, or for a type that is a descendant of an explicitly limited record type. In addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit. 
 This paragraph was deleted.
For a type defined by a derived_type_definition, if a known_discriminant_part is provided in its declaration, then: 
The type of the default_expression, if any, for an access discriminant shall be convertible to the anonymous access type of the discriminant (see 4.6).

Static Semantics

A discriminant_specification declares a discriminant; the subtype_mark denotes its subtype unless it is an access discriminant, in which case the discriminant's subtype is the anonymous access-to-variable subtype defined by the access_definition.
For a type defined by a derived_type_definition, each discriminant of the parent type is either inherited, constrained to equal some new discriminant of the derived type, or constrained to the value of an expression. When inherited or constrained to equal some new discriminant, the parent discriminant and the discriminant of the derived type are said to correspond. Two discriminants also correspond if there is some common discriminant to which they both correspond. A discriminant corresponds to itself as well. If a discriminant of a parent type is constrained to a specific value by a derived_type_definition, then that discriminant is said to be specified by that derived_type_definition.
A constraint that appears within the definition of a discriminated type depends on a discriminant of the type if it names the discriminant as a bound or discriminant value. A component_definition depends on a discriminant if its constraint depends on the discriminant, or on a discriminant that corresponds to it. 
A component depends on a discriminant if: 
Each value of a discriminated type includes a value for each component of the type that does not depend on a discriminant; this includes the discriminants themselves. The values of discriminants determine which other component values are present in the value of the discriminated type. 
A type declared with a known_discriminant_part is said to have known discriminants; its first subtype is unconstrained. A type declared with an unknown_discriminant_part is said to have unknown discriminants. A type declared without a discriminant_part has no discriminants, unless it is a derived type; if derived, such a type has the same sort of discriminants (known, unknown, or none) as its parent (or ancestor) type. A tagged class-wide type also has unknown discriminants. Any subtype of a type with unknown discriminants is an unconstrained and indefinite subtype (see 3.2 and 3.3).

Dynamic Semantics

 For an access discriminant, its access_definition is elaborated when the value of the access discriminant is defined: by evaluation of its default_expression, by elaboration of a discriminant_constraint, or by an assignment that initializes the enclosing object.
52  If a discriminated type has default_expressions for its discriminants, then unconstrained variables of the type are permitted, and the values of the discriminants can be changed by an assignment to such a variable. If defaults are not provided for the discriminants, then all variables of the type are constrained, either by explicit constraint or by their initial value; the values of the discriminants of such a variable cannot be changed after initialization. 
53  The default_expression for a discriminant of a type is evaluated when an object of an unconstrained subtype of the type is created.
54  Assignment to a discriminant of an object (after its initialization) is not allowed, since the name of a discriminant is a constant; neither assignment_statements nor assignments inherent in passing as an in out or out parameter are allowed. Note however that the value of a discriminant can be changed by assigning to the enclosing object, presuming it is an unconstrained variable. 
55  A discriminant that is of a named access type is not called an access discriminant; that term is used only for discriminants defined by an access_definition.


Examples of discriminated types: 
type Buffer(Size : Buffer_Size := 100)  is        -- see 3.5.4
      Pos   : Buffer_Size := 0;
      Value : String(1 .. Size);
   end record;
type Matrix_Rec(Rows, Columns : Integer) is
      Mat : Matrix(1 .. Rows, 1 .. Columns);       -- see 3.6
   end record;
type Square(Side : Integer) is new
   Matrix_Rec(Rows => Side, Columns => Side);
type Double_Square(Number : Integer) is
      Left  : Square(Number);
      Right : Square(Number);
   end record;
task type Worker(Prio : System.Priority; Buf : access Buffer) is
   -- discriminants used to parameterize the task type (see 9.1)
   pragma Priority(Prio);  -- see D.1
   entry Fill;
   entry Drain;
end Worker;

Contents   Index   References   Search   Previous   Next 
Ada-Europe Sponsored by Ada-Europe