Version 1.5 of ai05s/ai05-0192-1.txt

Unformatted version of ai05s/ai05-0192-1.txt version 1.5
Other versions for file ai05s/ai05-0192-1.txt

!standard 13.1(15.2/2)          11-03-11 AI05-0192-1/02
!standard 13.13.2(8.1/2)
!standard 13.13.2(25/2)
!standard 13.13.2(50/2)
!class binding interpretation 11-02-20
!status Amendment 2012 11-03-11
!status ARG Approved 8-0-0 11-02-20
!status work item 09-11-03
!status received 09-05-11
!priority Low
!difficulty Easy
!qualifier Error
!subject Behavior of 'Input for types with constrained first subtypes
!summary
The result of 'Input is constrained if the type is composite and the first subtype is constrained.
!question
Consider:
type T1 (D : Natural) is ... ; type T2 is new T1 (123);
X : T1 := T1 (T2'Input (...));
Is the result subtype of T2'Input constrained? (Yes.) If so, it must raise Constraint_Error is the discriminant is not 123.
13.13.2(50/2) says that it is, but 13.13.2(25/2) says that 13.1(15.2/2) applies - the aspect is derived, which would make the subtype unconstrained.
Which interpretation is correct?
Another question occurs presuming that the attribute is constrained. Is an implementation required, allowed, or forbidden to perform the constraint check as soon as the discriminant value is read from the stream? (Anywhere.) Would it be legal to defer the check until the end? (Yes.)
!recommendation
(See summary.)
!wording
Modify 13.13.2(8.1/2):
For an untagged derived type, the Write (resp. Read) attribute is inherited according to the rules given in 13.1 if the attribute is {Redundant[specified and] }available for the parent type at the point where T is declared. For a tagged derived type, these attributes are not inherited, but rather the default implementations are used.
Modify 13.13.2(25/2):
For an untagged derived type, the Output (resp. Input) attribute is inherited according to the rules given in 13.1 if the attribute is {Redundant[specified and]} available for the parent type at the point where T is declared. For a tagged derived type, these attributes are not inherited, but rather the default implementations are used.
Modify 13.13.2(50/2):
In the parameter_and_result_profiles for {the default implementations of} the stream-oriented attributes, the subtype of the Item parameter is the base subtype of T if T is a scalar type, and the first subtype otherwise. The same rule applies to the result of the Input attribute.
AARM Discussion: An inherited stream attribute has a profile as determined by the rules for inheriting primitive subprograms (see 13.1 and 3.4).
!discussion
13.1(15.2/2) says that inherited aspects of a derived type work the same way as a user-defined primitive subprogram of the type. It should be obvious that they have to work this way, as the body of the subprogram will be expecting the constraints it was defined with, not some other constraints.
13.13.2(50/2) was intended to apply to new stream aspects but not inherited ones. That means it applies to all tagged types and most other types as well. We add some wording to make that clear. Also note that we never inherit the the default implementation of the attributes; we only inherit when the attribute is specified.
With this new wording, the answer to the first question is easy: the subtype is constrained. But we get a different answer if we have an explicitly specified attribute:
type T1 (D : Natural) is ... with Input => ...;
type T2 is new T1 (123);
X : T1 := T1 (T2'Input (...));
Now the aspect is inherited, and the subtype of T2'Input is unconstrained. Note that it is possible to inherit operations that could not have been written explicitly -- but this is the way inherited subprograms work and we couldn't change it if we wanted to.
On the second question, 13.13.2(36/2) applies, and is very clear. It says "at which point" the checks are made is unspecified. So long as the exception raised by the checks is handled by the proper handler (which is required by the infamous 11.6), the implementation is correct.
One could argue that the wording of 13.13.2(36/2) is so vague that almost anything is allowed. But that is the intent: the wording specifically says that the number of stream elements read cannot be predicted. So the intent is clearly that pretty much anything sensible goes.
We could add an AARM note to the effect that we meant what we said, but that seems silly.
!corrigendum 13.13.2(8.1/2)
Replace the paragraph:
For an untagged derived type, the Write (resp. Read) attribute is inherited according to the rules given in 13.1 if the attribute is available for the parent type at the point where T is declared. For a tagged derived type, these attributes are not inherited, but rather the default implementations are used.
by:
For an untagged derived type, the Write (resp. Read) attribute is inherited according to the rules given in 13.1 if the attribute is specified and available for the parent type at the point where T is declared. For a tagged derived type, these attributes are not inherited, but rather the default implementations are used.
!corrigendum 13.13.2(25/2)
Replace the paragraph:
For an untagged derived type, the Output (resp. Input) attribute is inherited according to the rules given in 13.1 if the attribute is available for the parent type at the point where T is declared. For a tagged derived type, these attributes are not inherited, but rather the default implementations are used.
by:
For an untagged derived type, the Output (resp. Input) attribute is inherited according to the rules given in 13.1 if the attribute is specified and available for the parent type at the point where T is declared. For a tagged derived type, these attributes are not inherited, but rather the default implementations are used.
!ACATS Test
!appendix

From: Steve Baird
Sent: Monday, May 11, 2009  4:04 PM

A question was raised at AdaCore about the Input attribute of an untagged
derived type with a constrained first subtype, as in

    type T1 (D : Natural) is ... ;
    type T2 is new T1 (123);

    X : T1 := T1 (T2'Input (...));

Question #1:
   In the above example, should Constraint_Error be raised if the
   discriminant value read from the stream is not equal to 123?

The RM appears to contradict itself with respect to the definition of the result
subtype of T2'Input.

The more specific (and therefore presumably correct) applicable passage is
13.13.2(50/2), which says

     In the parameter_and_result_profiles for the stream-oriented
     attributes, the subtype of the Item parameter is the base subtype of
     T if T is a scalar type, and the first subtype otherwise. The same
     rule applies to the result of the Input attribute.

This suggests that the result subtype is constrained and that therefore
Constraint_Error should be raised. Note that the changes AI05-007 makes in this
area have no effect in the non-scalar case.

The opposing argument is based on the following chain:
    13.13.2(25/2): "For an untagged derived type, the Output
      (resp. Input) attribute is inherited according to the rules
      given in 13.1 ..."
    13.1(15.2/2): "When an aspect that is a subprogram is inherited, the
      derived type inherits the aspect in the same way that a derived
      type inherits a user-defined primitive subprogram from its parent
     (see 3.4)."
    3.4(19): "If the declaration of the derived type has neither a
      known_discriminant_part nor a record_extension_part, then the
      corresponding subtype has a constraint that corresponds (as defined
      above for the first subtype of the derived type) to that of the
      given subtype."

This suggests that the result subtype is unconstrained. I think an AARM note
resolving this apparent contradiction is all that is needed.

Question #2:
   Assuming that Constraint_Error is to be raised, is an implementation
   required, allowed, or forbidden to perform the constraint
   check as soon as the discriminant value is read from the stream?
   Would it be legal to defer the check until the end, effectively
   implementing T2'Input as something like

      function T2'Input (...) return T2 is
      begin
          return T2 (T1'Input (...));
      end T2'Input;

   ? How about an early check something like

      function T2'Input (...) return T2 is
      begin
          if Integer'Input (...) /= 123 then
               raise Constraint_Error;
          end if;
          declare
              Result : T2;
          begin
              T2'Read (Result);
              return Result;
          end;
      end T2'Input;
    ? Does any of this depend on 11.6 ?

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

From: Brad Moore
Sent: Tuesday, May 12, 2009  11:19 PM

< Question #2:
<   Assuming that Constraint_Error is to be raised, is an implementation
<   required, allowed, or forbidden to perform the constraint
<   check as soon as the discriminant value is read from the stream?
<   Would it be legal to defer the check until the end, ... ?

I would say that 13.13.2(36/2) seems to provide the answer to this question. It
states; "It is unspecified at which point and in which order these checks are
performed. In particular, if Constraint_Error is raised due to the failure of
one of these checks, it is unspecified how many stream  elements have been read
from the stream."

As to the first question, I would think people would expect the constraint error
to be raised.

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

From: Steve Baird
Sent: Wednesday, May 13, 2009  5:36 PM

> I would say that 13.13.2(36/2) seems to provide the answer to this
> question. It states; "It is unspecified at which point and in which
> order these checks are  performed. In particular, if Constraint_Error
> is raised due to the  failure of one of these checks, it is
> unspecified how many stream  elements have been read from the stream."

I tend to agree with you.
The question here is whether the freedom you described extends across a call
boundary. In 13.1(15.2/2), presumably the phrase "in the same way" means that
3.4(27/2) defines the dynamic semantics of a call to

   My_Untagged_Derived_Type'Inherited_Streaming_Attribute.

> As to the first question, I would think people would expect the
> constraint error to be raised.

Again, I agree with you.
I still think there is enough of an apparent contradiction to justify an AARM
note.

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

Questions? Ask the ACAA Technical Agent