Static Semantics (GNAT Reference Manual)

#### 18.3.14.3 Static Semantics ¶

A `structural_generic_instance_name` denotes the instance that is the product of the structural instantiation of a generic unit on the specified actual parameters. This instance is unique to a partition, except when a generic subprogram instantiation is automatically demoted to a local instantiation as described under Legality Rules.

Example:

    with Ada.Containers.Vectors;

    procedure P is
       V : Ada.Containers.Vectors(Positive,Integer).Vector;

    begin
       V.Append (1);
       V.Append (0);
       Ada.Containers.Vectors(Positive,Integer).Generic_Sorting("<").Sort (V);
    end;

This procedure references two structural instantiations of two different generic units: `Ada.Containers.Vectors(Positive,Integer)` is the structural instance of the generic unit `Ada.Containers.Vectors` on `Positive` and `Integer` and `Ada.Containers.Vectors(Positive,Integer).Generic_Sorting("<")` is the structural instance of the nested generic unit `Ada.Containers.Vectors(Positive,Integer).Generic_Sorting` on `"<"`.

Note that the following example is illegal:

    with Ada.Containers.Vectors;

    package Q is
       type T is record
          I : Integer;
       end record;

       V : Ada.Containers.Vectors(Positive,T).Vector;
    end Q;

The reason is that `Ada.Containers.Vectors`, `Positive` and `Q.T` being library-level entities, the structural instance `Ada.Containers.Vectors(Positive,T)` is a library unit with a dependence on `Q` and, therefore, cannot be referenced from within `Q`. This restriction applies to structural instantiations of generic packages. The simple way out is to declare a traditional instantiation in this case:

    with Ada.Containers.Vectors;

    package Q is
       type T is record
          I : Integer;
       end record;

       package Vectors_Of_T is new Ada.Containers.Vectors(Positive,T);

       V : Vectors_Of_T.Vector;
    end Q;

But the following example is legal:

    with Ada.Containers.Vectors;

    procedure P is
       type T is record
          I : Integer;
       end record;

       V : Ada.Containers.Vectors(Positive,T).Vector;
    end;

because the structural instance `Ada.Containers.Vectors(Positive,T)` is not a library unit.

For generic subprograms, the restriction does not apply: if a local entity of a library-level package is used as an actual, the structural instantiation is automatically demoted to a local instantiation. For example:

    with Ada.Unchecked_Deallocation;

    package Q is
       type T is record
          I : Integer;
       end record;

       type T_Access is access T;
    end Q;

    package body Q is
       procedure Free_T (X : in out T_Access) is
       begin
          Ada.Unchecked_Deallocation(T, T_Access)(X);
       end Free_T;
    end Q;

is legal: since `T` and `T_Access` are local entities of `Q`, the structural instantiation of `Ada.Unchecked_Deallocation` is demoted to a local instantiation rather than producing an error. Note that the uniqueness guarantee no longer holds in this case and several instances of the generic subprogram may be present in a single partition.

The first example can be rewritten in a less verbose manner:

    with Ada.Containers.Vectors; use Ada.Containers.Vectors(Positive,Integer);

    procedure P is
       V : Vector;

    begin
       V.Append (1);
       V.Append (0);
       Generic_Sorting("<").Sort (V);
    end;

Another example, which additionally uses the inference of dependent types:

    with Ada.Unchecked_Deallocation;

    procedure P is

       type Integer_Access is access all Integer;

       A : Integer_Access := new Integer'(1);

    begin
       Ada.Unchecked_Deallocation(Name => Integer_Access) (A);
    end;