Version 1.11 of ais/ai-00130.txt

Unformatted version of ais/ai-00130.txt version 1.11
Other versions for file ais/ai-00130.txt

!standard 13.12 (08)          00-04-11 AI95-00130/07
!standard 13.12 (09)
!standard D.7 (04)
!standard H.4 (08)
!class binding interpretation 96-04-13
!status Corrigendum 2000 99-07-20
!status WG9 approved 99-06-12
!status ARG approved (with editiorial changes) 8-0-1 99-03-25
!status work item 96-04-17
!status received 96-04-13
!priority Medium
!difficulty Medium
!qualifier Clarification
!subject Enforcing Restrictions might violate the generic contract model
!summary
The enforcement of restrictions might violate the contract model of generics, as well as violate the "privateness" of code in a private part or body.
To be consistent with the No_Task_Hierarchy and No_Nested_Finalization restrictions, the No_Local_Allocators restriction should not preclude nested generic instantiations. No_Nested_Finalization is broadened to cover finalization associated with protected and task objects. For the purposes of these (post-compilation) rules, a generic template is logically expanded at the point of each instantiation, and all of the expressions of the type definition for a record or protected type logically appear at the point of any default-initialized object creation, and default parameter expressions logically appear where used.
!question
H.4(8) says:
No_Local_Allocators
Allocators are prohibited in subprograms, generic subprograms, tasks and entry bodies; instantiations of generic packages are also prohibited in these contexts.
Why are instantiations prohibited in these contexts? (This ruling allows them.)
The restrictions No_Task_Hierarchy and No_Nested_Finalization do not prohibit such instantiations.
!recommendation 99-03-21
An implementation supporting the No_Task_Hierarchy, No_Nested_Finalization, or No_Local_Allocators restrictions must enforce the intent of these restrictions with checks prior to run-time.
For the purposes of these checks:
- Generic instances are logically expanded at the point of instantiation;
- If an object of a type is declared or allocated and not explicitly
initialized, then all expressions appearing in the definition for the type and any of its ancestors are presumed to be used.
- Default formal parameters are presumed to be used only if the
corresponding actual parameter is not provided in a given call or instantiation;
- Notwithstanding the above, for code which is recognized at compile-time
as unreachable, and for which no object code is generated, implementations are permitted to omit these checks.
No_Task_Hierarchy means that only tasks directly dependent on the master representing the execution of the environment task (body) are permitted. Tasks dependent on masters which correspond to other bodies or blocks are not permitted, even if these masters are executed by the environment task.
No_Nested_Finalization should be broadened to mean that objects requiring finalization due to having a controlled, protected, or task part are not permitted unless they are at the library level.
No_Local_Allocators means that allocators are prohibited in subprograms, generic subprograms, task bodies, and entry bodies. As indicated above, rather than precluding nested instantiations, instantiations are to be logically expanded at the point of instantiation for the purposes of this check.
!wording
Paragraph H.4(8) should be revised to say simply:
No_Local_Allocators
Allocators are prohibited in subprograms, generic subprograms, tasks, and entry bodies.
Paragraph D.7(4) should be revised to say:
No_Nested_Finalization
Objects with controlled, protected, or task parts, and access types that designate such objects, shall be declared only at library level.
Paragraph 13.12(8) should be amended to include rules for how the enforcement of restrictions relates to the expansion of generic instantiations, default initializations, and default parameters.
!discussion
Precluding nested generic instances for the No_Local_Allocators restriction in H.4(8) in an attempt to preserve a generic contract model for restrictions is inconsistent with the rules for No_Task_Hierarchy given in D.7(3) and for No_Nested_Finalization given in D.7(4). In general, enforcing pragma Restrictions across a partition will necessarily violate the "privateness" of a private part or a body, as well as the generic contract model.
Although it might be useful to know that if a generic body does not by itself violate a restriction, then neither will any instantiation, enforcing this kind of "contract" rule for restrictions that distinguish library level from non-library level usages would overly limit the nested instantiations of useful, benign generics. Furthermore, the pragma Restrictions is primarily designed to support application environments where schedulability and formal verification requirements dictate that generics can only be certified with respect to particular instantiations -- never in the abstract.
A more serious problem with the rules given for the No_Task_Hierarchy restriction in D.7(3), No_Nested_Finalization in D.7(4), and No_Local_Allocators in H.4(8), is that they do not properly account for violations appearing in expressions used for default parameters and for default initialization.
For example, the following partition obeys the static criteria given in H.4(8) for the No_Local_Allocators restriction, yet (in the absence of code-removing optimizations) the main subprogram evaluates an allocator:
package P is type Integer_Pointer is access Integer; type R is record C: Integer_Pointer := new Integer; end record; end P;
with P; procedure Main is X: P.R; -- X.C is initialized by invoking an allocator begin null; end Main;
To close such loopholes, it is necessary to logically substitute default initialization and default parameters in line at the point of usage.
To ease the burden for implementations which check these restrictions late in the compilation process or during linking, implementations are permitted to omit the checks within constructs which generate no object code, because they are recognized as unreachable. Code which presumes a given implementation takes advantage of this permission is clearly less portable.
For an implementation that shares code between generic instantiations, it might be necessary for it to collect information while compiling a generic body which would allow the implementation to determine at link-time whether particular instantiations do or do not violate these restrictions. This is similar to other information gathering that is required of all implementations as part of implementing the Restrictions pragma, so this is not felt to be unduly burdensome.
!corrigendum 13.12(8)
Insert after the paragraph:
A pragma Restrictions is a configuration pragma; unless otherwise specified for a particular restriction, a partition shall obey the restriction if a pragma Restrictions applies to any compilation unit included in the partition.
the new paragraphs:
For the purpose of checking whether a partition contains constructs that violate any restriction (unless specified otherwise for a particular restriction):
!corrigendum 13.12(9)
Insert after the paragraph:
An implementation may place limitations on the values of the expression that are supported, and limitations on the supported combinations of restrictions. The consequences of violating such limitations are implementation defined.
the new paragraph:
An implementation is permitted to omit restriction checks for code that is recognized at compile time to be unreachable and for which no code is generated.
!corrigendum D.7(4)
Replace the paragraph:
No_Nested_Finalization
Objects with controlled parts and access types that designate such objects shall be declared only at library level.
by:
No_Nested_Finalization
Objects with controlled, protected, or task parts, and access types that designate such objects, shall be declared only at library level.
!corrigendum H.4(8)
Replace the paragraph:
No_Local_Allocators
Allocators are prohibited in subprograms, generic subprograms, tasks, and entry bodies; instantiations of generic packages are also prohibited in these contexts.
by:
No_Local_Allocators
Allocators are prohibited in subprograms, generic subprograms, tasks, and entry bodies.
!ACATS test
Create a C-Test to check that No_Local_Allocators and No_Nested_Finalization allow generic instantiations of appropriate packages.
!appendix

[Note: The original comment inadvertently referred to G.4(08)
 rather than H.4(08).  We have changed those references to H.4 here.]

!section H.4(08)
!subject Should No_Local_Allocators disallow nested instantiations?
!reference RM95-H.4(08)
!from Bob Duff
!reference 96-5477.a Robert A Duff 96-4-12>>
!discussion

The following is a bunch of e-mail I got on the subject of whether
No_Local_Allocators should forbid nested instantiations.  I think this
deserves an AI.  I agree that the restriction should be removed.

- Bob

Date: Fri, 8 Mar 1996 14:53:41 -0500
From: stt@dsd.camb.inmet.com (Tucker Taft)
To: hrg@waffle.cise.npl.co.uk
Subject: Nested instantiations and H.4(8)

A member of the ACVC team brought paragraph H.4(8) to my attention:

   No_Local_Allocators
      Allocators are prohibited in subprograms, generic subprograms, tasks
      and entry bodies; instantiations of generic packages are also
      prohibited in these contexts.

The restriction against nested instantiations seems unnecessary and
inconsistent with other restrictions, such as No_Task_Hierarchy
and No_Nested_Finalization.  The AARM indicates that the restriction
against nested instantiations is to preserve the generic contract
model.  However, there seems no strong argument why the generic
contract model need be preserved by pragma Restrictions.

Pragma restrictions will often require link-time detection
of problems anyway, and so finding out about a problem associated
with an instantiation at that point (which is the down side of not
preserving the generic contract model) seems OK as well.

Hence, I would suggest that the HRG consider removing the part of H.4(8)
that follows the ";", because it is inconsistent with other restrictions,
and unnecessarily restrictive.

-Tuck

Date: Fri, 8 Mar 96 16:11:23 EST
From: dewar@gnat.com (Robert Dewar)
To: hrg@waffle.cise.npl.co.uk, stt@dsd.camb.inmet.com
Subject: Re: Nested instantiations and H.4(8)
Content-Length: 449

what's the point of preserving generic contract model when the lnker will
check for consistency anyway. Moreover, this imitation is a very serious
one from a programming point of view, making the pragma Restrictions
pretty much useless. If this is not changed, then any reasonable
iplementation will have to add

  pragma Restrictions (No_Local_Allocators_Sensible_Version);

so I think we should consider this restriction a mistake and remove it.

Date: Mon, 11 Mar 96 09:15:57 GMT
From: Brian A Wichmann <baw@cise.npl.co.uk>
To: hrg@cise.npl.co.uk, stt@dsd.camb.inmet.com
Subject: Re:  Nested instantiations and H.4(8)

I am not sure how this restriction came about. Does Bob Duff
have any idea? Removing it seems fine at first glance... Brian.

-------------------------------------------------------------
Brian Wichmann                Tele: +44 181 943 6976 (direct)
National Physical Laboratory   FAX: +44 181 977 7091
Teddington Middlesex           e-mail: baw@cise.npl.co.uk
TW11 0LW
UK

WWW: http://www.npl.co.uk/npl/search/staff?Dr+Brian+Wichmann
-------------------------------------------------------------


****************************************************************

!section H.4(08)
!subject Should No_Local_Allocators disallow nested instantiations?
!reference RM95-H.4(08)
!reference 96-5478.a Robert A Duff 96-4-12
!from Robert I. Eachus
!reference 96-5488.a Robert I. Eachus 96-4-15>>

!discussion

   Bob Duff said:

  > I agree that the restriction should be removed.

   So do I, but I don't agree Tuck:

  > Hence, I would suggest that the HRG consider removing the part of H.4(8)
  > that follows the ";", because it is inconsistent with other restrictions,
  > and unnecessarily restrictive.

   I think instead we need to "elaborate" the original intent:

      No_Local_Allocators

         Allocators are prohibited in subprograms, generic
         subprograms, tasks and entry bodies; instantiations of
         generic packages _which_contain_allocators_or_task_declarations_
         are also prohibited in these contexts.

    But this also has an AARM implication.  An implementation might
normally implement generic packages by allocating space on the heap,
and in the case of nested packages, recovering the space once the
scope is left.  Such an implementation should be forbidden in the
presence of this pragma.

  Back to Tuck:

  > Pragma restrictions will often require link-time detection
  > of problems anyway, and so finding out about a problem associated
  > with an instantiation at that point (which is the down side of not
  > preserving the generic contract model) seems OK as well.

    Notice that it is only nested generic package instantiations that
are forbidden.  Nested generic subprogram instantiations are permitted
and instantiations with formal private type parameters could require
the link time check:

   generic
     type Fubar is private;
   procedure Foob;

   procedure Foob is
     X: Fubar;
   begin ... end Foob;

   ...

   procedure Main is

     type Foo is record
       Bar: Pointer := new Hidden_Allocator;
     end record;

     procedure FB is new Foob(Foo);
     ....

   (Gee, running low on metavariables there...)

   Since, absent the pragma there is no dependence of the body of Main
on the body of Foob, the violation of the pramga must be detected
after compile time.

****************************************************************

>From the minutes of the November 1997 ARG meeting:

Erhard argues, in a separate e-mail message, against the current
position of the AI because it breaks the contract model and requires
too much link time mechanism to enforce the restriction.  Instead
enforcing the currently stated restriction of only library-level
instantiations will enforce the contract model by doing a compile-time
check.

Pascal and Robert then noted that there is a much deeper problem here.
Record components with default initialization, protected objects with
initialization of their state, default values for parameters all share
the property that allocations might happen that are not apparent at
source level.  The current semantics of No_Local_Allocation does not
cover these cases at all.  Since these types can be private, the
privateness principle will need to be broken for compile-time
checks. The group could not come up with "circumstantial" restrictions
that would otherwise ensure the absence of such implicit allocation
without being extremely and unacceptably over-restrictive.  In
passing, it was noted that the strict predicate of No_Local_Allocators
is actually value-dependent (and hence undecidable), since a
default-initialized component might be located in a non-existent
variant of a constrained record object.

There is a concern that this sets a precedence for exposing more
implementation information about types, which violates the spirit of
abstract data type information hiding (and will cause problems in some
compilers).  But the Restrictions facility is inherently
implementation focused (especially restrictions like this one that
deal with nested usage, No_Nested_Finalization and No_Task_Hierarchy
being the other ones) and therefore some exposure of the
implementation details of imported types (such as Text_IO that uses
allocated data for file_type) must be made in order to enforce the
Restrictions.  This will affect semantic analysis involving private
types because now uses of private types will need to check that they
adhere to restrictions relating to previously hidden features of the
private type.

The No_Task_Hierachy and No_Nested_Finalization restrictions share the
same problem, since components might be tasks or of controlled type.
It is not clear what the language can do about the portability of
these three pragmas and still be effective.

It was even suggested that these three restrictions should not be in
the language, after all, since the benefits do not justify the costs.
ASIS-based analysis tools were mentioned as an alternative
restriction-enforcing mechanism.

Norm then suggested to take a step back and reformulate the semantics
of the pragma from the viewpoint of intended usage, and leave the
formulation of secondary restrictions to the implementation.  He will
rewrite to emphasize usefulness over portability; he will coordinate
with Erhard on the write-up.

****************************************************************


Questions? Ask the ACAA Technical Agent