Version 1.7 of ai05s/ai05-0007-1.txt

Unformatted version of ai05s/ai05-0007-1.txt version 1.7
Other versions for file ai05s/ai05-0007-1.txt

!standard 13.13.2(50/2)          07-05-15 AI05-0007-1/04
!standard 13.13.2(51/2)
!class binding interpretation 06-03-17
!status Amendment 201Z 08-11-26
!status WG9 Approved 07-06-29
!status ARG Approved 9-0-1 06-11-18
!status work item 06-03-17
!status received 05-10-13
!priority Medium
!difficulty Easy
!qualifier Clarification
!subject Stream 'Read and private scalar types
!summary
(See recommendation.)
!question
Presume that we have a limited private type, and we want to define a visible 'Read attribute on it. If the full type is a scalar type, 13.13.2(51/2) requires us to define the attribute using the base subtype. But we can't use 'Base on the partial view, since it is not scalar.
package P is type Lim is limited private; procedure Read(S : access Root_Stream_Type'Class; Obj : out Lim); for Lim'Read use Read; private type Lim is new Positive; end P;
Is this requirement correct? (No.) If it is, how can we define a visible attribute of a private type?
!recommendation
Relax the requirement for the base subtype. Allow the first subtype rather than the base subtype as the formal parameter type in the specified attribute subprogram.
!wording
Modify 13.13.2(51/2) as follows:
For an attribute_definition_clause specifying one of these attributes, the subtype of the Item parameter shall be the {first subtype or the} base subtype if scalar, and the first subtype [otherwise] {if not scalar}. The same rule applies to the result of the Input function.
!discussion
There seems no strong reason to require the use of the base subtype in user-defined stream attribute subprograms. The language rule now uses the size of the first subtype rather than the base subtype to determine the default stream size, so there is no guarantee that all values of the base subtype will be streamable. Although the formal parameter subtype of the attribute is still the base subtype, there is no particular implementation burden in performing the first subtype constraint check when calling a user-defined subprogram that specifies the first subtype. Because the convention of the stream attributes is Intrinsic (per 6.3.1(9)), there is no danger that someone will use 'Access with an attribute that requires the additional constraint check. For shared generics there is potentially some burden in creating a wrapper for the stream attributes, but presumably thunks for these operations must be created in general if they are not user specified, so creating one when they are seems an acceptable overhead.
Once we make this change, the problem with partial views disappears. Without this change, one could argue that the check is made at the location of the attribute definition clause. Since Lim is not scalar at that point, the 'Base attribute is not required. But this interpretation causes trouble for formal private types. Consider:
generic type Lim is limited private; package G is type My_Lim is new Lim; procedure Read(S : access Root_Stream_Type'Class; Obj : out My_Lim); for My_Lim'Read use Read; end G;
By the legality rules for a generic instance (12.3(11)), the legality rules are rechecked in an instance based on the properties of the actual. Thus, if the instantiation is:
package Int_G is new G (My_Lim => Integer);
the instantiation is illegal, as the attribute definition clause is illegal by 13.13.2(51/2). This is an unnecessary limitation on the use of formal private types; it essentially prevents the creation of mix-in generics that define stream attributes for all types (as such a mix-in would not work for scalar types).
In addition to eliminating this problem with formal generic types and partial views, making this change will also simplify the job for the user. An extremely common mistake when writing these stream attributes is to forget to use 'Base, which is required even for types defined as "new Integer". Requiring that the attribute subprograms handle 'Base rather than simply the first subtype seems of little value, and clearly if the user makes use of subtypes "wider" than the first subtype, they can always take care to use 'Base when defining the stream attributes.
!corrigendum 13.13.2(51/2)
Replace the paragraph:
For an attribute_definition_clause specifying one of these attributes, the subtype of the Item parameter shall be the base subtype if scalar, and the first subtype otherwise. The same rule applies to the result of the Input function.
by:
For an attribute_definition_clause specifying one of these attributes, the subtype of the Item parameter shall be the first subtype or the base subtype if scalar, and the first subtype if not scalar. The same rule applies to the result of the Input function.
!ACATS test
An ACATS C-Test should be created to test these cases.
!appendix

From: Tucker Taft
Date: Thursday, October 13, 2005  5:25 AM

Here is an interesting problem we encountered
recently.  We have a limited private type, and
we want to define a visible 'Read attribute on it.
But it turns out the full type is a scalar type.
That requires us to define the attribute using
the base subtype.  How are these two things are
incompatible.  The 'Base attribute cannot be
used on a private type, but the 'Base attribute
must be used on a scalar 'Read attribute.

Is the 'Base requirement waived for types with
a partial view that is not scalar?  Should it
be?

Example:

     type Lim is limited private;
     procedure Read(S : access Root_Stream_Type'Class; Obj : out Lim);
     for Lim'Read use Read;

private

     type Lim is new Positive;
     -- Oops, Lim'Read is not defined on Lim'Base as is required
     -- by 13.13.2(51/2) (or the old paragraph 38)

I suppose my instinct would be to fix 50/2 and 51/2 so that they
require the base subtype unless there is a partial view that is
non-scalar, in which case they require the first subtype.
Not pretty, but at least well defined.

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

From: Pascal Leroy
Date: Friday, October 14, 2005  5:53 AM

I guess I don't see the problem.  I have always assumed that 13.13.2(51/2)
was checked using the properties that you see at the place of the
attribute_definition_clause.  At this place Lim is not scalar, so you must
use the first subtype.  I don't see how you would get an error later on
the completion, which is what your example seems to indicate.

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

From: Tucker Taft
Date: Friday, October 14, 2005  6:51 AM

Ok with me, though perhaps an AARM note would be helpful.
I wonder what happens if you have a non-limited private type T,
where the implicit 'Read on the partial view presumably has
parameter subtype T, while the 'Read on the full view,
presuming it is scalar, has parameter subtype T'Base.
The placement of the attribute definition clause, if any, seems
even more critical in that case, since using your suggested
rule, you must specify a Read procedure with T or T'Base
depending on where the attribute definition clause is.

I suppose I also wonder about specifying the 'Read on
a type derived from a formal private type T.  Do we require
a recheck on instantiation that the actual type is *not*
scalar?  Is it impossible to specify 'Read for such
a type?

I would be tempted to change the rule to *allow* the
use of the first subtype always for 'Read, while also
allowing the use of the base subtype if the associated
type is scalar.  That way the user can choose whether to
provide an operation that can handle values outside the
first subtype.  Since the rules no longer require the
stream_size to accommodate the base range, requiring its
use in the specification of the 'Read attribute seems
unnecessary.

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


Questions? Ask the ACAA Technical Agent