!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 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) @drepl For an @fa 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. @dby For an @fa specifying one of these attributes, the subtype of the @i 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. ****************************************************************