Version 1.1.1.1 of ais/ai-00115.txt

Unformatted version of ais/ai-00115.txt version 1.1.1.1
Other versions for file ais/ai-00115.txt

!standard 03.09.01 (03)          96-07-23 AI95-00115/00
!standard 07.06(04)
!standard A(00)
!class confirmation 96-04-04
!status WG9 approved 96-12-07
!status ARG approved 7-0-1 96-06-17
!status work item 96-04-04
!status received 96-04-04
!priority High
!difficulty Medium
!subject Controlled types in language-defined generic packages
!summary 96-04-04
A language-defined generic package may be instantiated at any nesting depth.
!question 96-04-04
May an implementation declare a controlled type in its implementation of a language-defined generic package? (No.) For example, may Ada.Sequential_IO.File_Type be a controlled type? (No.)
!response 96-04-04
A language-defined generic package may be instantiated at any nesting depth. This follows from the fact that the RM does not say otherwise.
This implies that the implementation of a language-defined generic package cannot contain the declaration of a controlled type, since the accessibility rules require that controlled types be declared at library level.
If an implementation wishes to implement, say, Ada.Sequential_IO.File_Type in terms of a controlled type, it can declare the controlled type in a separate (non-generic) package, such as System.File_Implementation, and make type File_Type have a component whose type is the controlled type.
The implementation model given in A.5.2(46.a), which calls for making the Generator type of the random number packages a controlled type, is wrong. It should instead call for Generator to have a component of a controlled type, declared in a (non-generic) package.
!appendix

!section 3.9.1(03)
!subject Controlled types in language-defined generic packages
!reference RM95-3.9.1(3)
!reference RM95-7.6
!reference RM95-A.8.1
!reference RM95-A.8.4
!reference RM95-A.10.1
!reference AARM95-A.5.2(46.a)
!from Keith Thompson 95-11-15
!reference 95-5386.a Keith Thompson 95-11-15>>
!discussion

It's tempting to implement the type File_Type in the various I/O packages
as a controlled type, with a Finalize routine that closes the file.
Unfortunately, such an implementation would mean that Ada.Sequential_IO
and Ada.Direct_IO can only be instantiated at the library level, a serious
(and undocumented) incompatibility with Ada 83.  I can't find any wording
in the RM that forbids such an implementation.

To avoid incompatibilities with Ada 83, it would actually be necessary to
forbid any language-defined generic package (or at least any of the ones
that exist in Ada 83) to contain the declaration of a record extension,
either in its specification or in its body.  Any such declaration would
restrict the places at which such a package can be instantiated.

The affected generic packages that present problems for Ada 83 are:

    Ada.Text_IO.Integer_IO
    Ada.Text_IO.Float_IO
    Ada.Text_IO.Fixed_IO
    Ada.Text_IO.Enumeration_IO
    Ada.Sequential_IO
    Ada.Direct_IO

For the sake of consistency, the following generic packages should also
be considered:

    Ada.Text_IO.Modular_IO
    Ada.Text_IO.Decimal_IO
    Ada.Text_IO.Complex_IO
    Ada.Text_IO.Pictures.Edited_Output
    Ada.Storage_IO
    Ada.Numerics.Generic_Elementary_Functions
    Ada.Numerics.Generic_Complex_Types
    Ada.Numerics.Generic_Complex_Elementary_Functions
    Ada.Numerics.Discrete_Random
    Ada.Strings.Bounded.Generic_Bounded_Length
    Ada.Strings.Wide_Bounded.Generic_Bounded_Length
    Ada.Task_Attributes

plus all of the Wide_Text_IO equivalents of the above Text_IO packages.

(I *think* these lists are complete, but I won't guarantee it.)

Note, however, that implementations are advised to implement
Ada.Numerics.Discrete_Random.Generator as a controlled type.

If restrictions are imposed on declaring controlled types (or, more
generally, record extensions) in language-defined generic packages,
it actually shouldn't be too much of a burden on implementers.
For example, the type Ada.Sequential_IO.File_Type, or even
Ada.Numerics.Discrete_Random.Generator, could be declared as a
record containing a component of a controlled type declared in an
implementation-defined library package.

(The "!reference" headers above are incomplete, since I'm too lazy to
track down the RM references for all the packages affected.)

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

!section 3.9.1(03)
!subject Controlled types in language-defined generic packages
!reference RM95-3.9.1(3)
!reference RM95-7.6
!reference RM95-A.8.1
!reference RM95-A.8.4
!reference RM95-A.10.1
!reference AARM95-A.5.2(46.a)
!reference 95-5386.a Keith Thompson 95-11-15
!from Ted Baker 95-11-16
!reference 95-5387.a Ted Baker  95-11-16>>
!discussion

I ran into similar problems with the library-level only
restriction when I used controlled types to implement user-defined
task attributes.

It occurs to me that a compiler might provide a flag/pragma that
would allow implementors of language-defined packages to violate
the library-level-only rule, provided the implementation of
controlled types does not rely on it.

--Ted Baker

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

!section 3.9.1(03)
!subject Controlled types in language-defined generic packages
!reference RM95-3.9.1(3)
!reference RM95-7.6
!reference RM95-A.8.1
!reference RM95-A.8.4
!reference RM95-A.10.1
!reference AARM95-A.5.2(46.a)
!reference 95-5386.a Keith Thompson 95-11-15
!from Robert I. Eachus 95-11-16
!reference 95-5388.a Robert I. Eachus 95-11-16>>

!discussion

   I agree with most of what Keith says, but:

  > Note, however, that implementations are advised to implement
  > Ada.Numerics.Discrete_Random.Generator as a controlled type.

   is misleading.   The RM says:

  "Any storage associated with an object of type Generator should be
reclaimed on exit from the scope of the object."

   Since other requirements seem to make it necessary (if you stay
within standard Ada) for objects of type Generator to be access values
or contain access values, it is not the Generators, but the designated
objects that need to be reclaimed.  This can be done by garbage
collection, for example.

   However, there is a neater implementation that can be used in GNAT.
Put the state information in the Generator object, and go "outside the
language" to write to the object.  (I think this can be done portably
in GNAT with 'Unchecked_Access.)  This is probably the most sensible
implementation if the size of the state object is small.  The same
technique can be used with File_Type, again if the size is reasonable.

    Now the question arises, what if someone chooses to declare a
constant of type Generator?  (Notice that this is not a problem with
File_Type, since Create and Open take in out parameters.)  Currently,
it seems that this should not affect the operation of Discrete_Random
and therefore must be supported.  No problem, as long as there is no
requirement that the be preelaboratable.  I think it is clear that
implementations are allowed to make generators non-preelaboratable.


                                        Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...

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

!section 3.9.1(03)
!subject Controlled types in language-defined generic packages
!reference RM95-3.9.1(3)
!reference RM95-7.6
!reference RM95-A.8.1
!reference RM95-A.8.4
!reference RM95-A.10.1
!reference AARM95-A.5.2(46.a)
!reference 95-5386.a Keith Thompson 95-11-15
!from Tucker Taft  95-11-16
!reference 95-5389.a Tucker Taft 95-11-16>>
!discussion

> It's tempting to implement the type File_Type in the various I/O packages
> as a controlled type, with a Finalize routine that closes the file.
> Unfortunately, such an implementation would mean that Ada.Sequential_IO
> and Ada.Direct_IO can only be instantiated at the library level, a serious
> (and undocumented) incompatibility with Ada 83.  I can't find any wording
> in the RM that forbids such an implementation.

I don't believe we have to include such wording.  Anything not disallowed
by the RM is allowed.  Hence, there is no permission to define
Ada.Sequential_IO in a way that precludes it being instantiated
in nested contexts.

In any case, you can use controlled types without running into this problem.
The solution is to declare a controlled type in a non-generic package,
and then have make a component of File_Type be of that controlled type.

> To avoid incompatibilities with Ada 83, it would actually be necessary to
> forbid any language-defined generic package (or at least any of the ones
> that exist in Ada 83) to contain the declaration of a record extension,
> either in its specification or in its body.  Any such declaration would
> restrict the places at which such a package can be instantiated.

Again, I don't believe we need such wording explicitly.  Of course,
a "NOTE" wouldn't hurt ;-).

> ...
> If restrictions are imposed on declaring controlled types (or, more
> generally, record extensions) in language-defined generic packages,
> it actually shouldn't be too much of a burden on implementers.
> For example, the type Ada.Sequential_IO.File_Type, or even
> Ada.Numerics.Discrete_Random.Generator, could be declared as a
> record containing a component of a controlled type declared in an
> implementation-defined library package.

Right.  We might want to add a NOTE to this effect as well.

-Tuck

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

!section 3.9.1(03)
!subject Controlled types in language-defined generic packages
!reference RM95-3.9.1(3)
!reference RM95-7.6
!reference RM95-A.8.1
!reference RM95-A.8.4
!reference RM95-A.10.1
!reference AARM95-A.5.2(46.a)
!reference 95-5386.a Keith Thompson 95-11-15
!reference 95-5387.a Ted Baker  95-11-16
!reference 95-5388.a Robert I. Eachus 95-11-16
!reference RM95-3.9.1(4)
!from Keith Thompson 95-11-17
!reference 95-5390.a Keith Thompson 95-11-17>>
!discussion

I wrote:

> To avoid incompatibilities with Ada 83, it would actually be necessary to
> forbid any language-defined generic package (or at least any of the ones
> that exist in Ada 83) to contain the declaration of a record extension,
> either in its specification or in its body.

Actually, bodies are not a problem.  RM95-3.9.1(4) forbids the declaration
of a type extension in a generic body if the parent type is declared
outside that body.

Robert Eachus wrote:

> I agree with most of what Keith says, but:
> 
> > Note, however, that implementations are advised to implement
> > Ada.Numerics.Discrete_Random.Generator as a controlled type.
> 
>  is misleading.   The RM says:
> 
> "Any storage associated with an object of type Generator should be
> reclaimed on exit from the scope of the object."

But the following paragraph in the AARM, A.5.2(46.a), says:

    46.a   Ramification:  A level of indirection is implicit in the
    semantics of the operations, given that they all take parameters of
    mode in.  This implies that the full type of Generator probably
    should be a controlled type, with appropriate finalization to reclaim
    any heap-allocated storage.

Tucker Taft wrote:

> I don't believe we have to include such wording.  Anything not disallowed
> by the RM is allowed.  Hence, there is no permission to define
> Ada.Sequential_IO in a way that precludes it being instantiated
> in nested contexts.

On the other hand, the wording about Ada.Numerics.Discrete_Random
seems to establish the precedent that an implementation *may* preclude
instantiations in nested contexts, particularly for generic packages
that don't raise Ada 83 compatibility issues.

I agree that it should be possible to instantiate any language-defined
generic package in a nested context, but I'm not convinced this
requirement can be inferred from the RM, particularly given paragraph
46.a, quoted above.

(Avoiding the declaration of type extensions in generics is probably a
good style guide for user code.)

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

!section 3.9.1(03)
!subject Controlled types in language-defined generic packages
!reference RM95-3.9.1(3)
!reference RM95-7.6
!reference RM95-A.8.1
!reference RM95-A.8.4
!reference RM95-A.10.1
!reference AARM95-A.5.2(46.a)
!reference 95-5386.a Keith Thompson 95-11-15
!reference 95-5388.a Robert I. Eachus 95-11-16
!from Bob Duff
!reference 95-5396.a Robert A Duff 95-11-26>>

!discussion

>    I agree with most of what Keith says, but:

Well, I think Tucker correctly answered Keith's comment, but:

>    However, there is a neater implementation that can be used in GNAT.
> Put the state information in the Generator object, and go "outside the
> language" to write to the object.  (I think this can be done portably
> in GNAT with 'Unchecked_Access.)  This is probably the most sensible
> implementation if the size of the state object is small.  The same
> technique can be used with File_Type, again if the size is reasonable.

'Unchecked_Access won't quite work, since the parameter is of mode 'in',
so you can't construct an access-to-variable value pointing to it.
GNAT could use 'Unchecked_Access followed by an unchecked conversion.
Or, the GNAT implementation-defined attribute 'Unrestricted_Access
could be used.  Both of those require pass-by-reference, so the full
type would have to be a limited record.

Alternatively, Tucker's suggestion -- putting the controlled type in a
package with-ed by the generic -- works, and seems more elegant, though
probably less efficient.

>     Now the question arises, what if someone chooses to declare a
> constant of type Generator? ...

Generator is a limited type, so you can't declare a constant object.
You could have a constant view, such as an 'in' parameter, but we
already know the 'in' parameter is some sort of reference to
a *variable*, and the variable can of course be modified.

- Bob

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

!section 3.9.1(03)
!subject Controlled types in language-defined generic packages
!reference RM95-3.9.1(3)
!reference RM95-7.6
!reference RM95-A.8.1
!reference RM95-A.8.4
!reference RM95-A.10.1
!reference AARM95-A.5.2(46.a)
!reference 95-5386.a Keith Thompson 95-11-15
!reference 95-5388.a Robert I. Eachus 95-11-16
!reference 95-5396.a Bob Duff 95-11-27
!reference 95-5397.a Robert I. Eachus 95-11-27>>

!discussion

  (Basically, just agreeing...)

  Bob Duff said:

  > 'Unchecked_Access won't quite work, since the parameter is of mode 'in',
  > so you can't construct an access-to-variable value pointing to it.
  > GNAT could use 'Unchecked_Access followed by an unchecked conversion.

  That's what I had in mind, convert an access to constant to an
access to variable.

  > Or, the GNAT implementation-defined attribute 'Unrestricted_Access
  > could be used.  Both of those require pass-by-reference, so the full
  > type would have to be a limited record.

  Yep.

  > Generator is a limited type, so you can't declare a constant object.

    The case I was worried about is a "bastard" child package of
Float_Random or Discrete_Random.  I concluded that the auther gets
either what they expect, or what they deserve. ;-)


                                        Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...

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

Questions? Ask the ACAA Technical Agent