CVS difference for ai05s/ai05-0153-1.txt
--- ai05s/ai05-0153-1.txt 2009/11/04 06:26:38 1.3
+++ ai05s/ai05-0153-1.txt 2010/02/12 06:10:39 1.4
@@ -1,4 +1,4 @@
-!standard 3.2.2(2) 09-10-26 AI05-0153-1/03
+!standard 3.2.2(2) 10-02-11 AI05-0153-1/04
!class Amendment 09-05-27
!status work item 09-05-27
!status received 09-05-27
@@ -32,42 +32,64 @@
integrated into the language (but far more expensive to implement
is given in AI05-0153-2)].
+We depend on the following part of AI05-0183-1:
Replace 3.2.2(2) with:
- subtype defining_identifier is subtype_indication [predicate_clause];
+ subtype defining_identifier is subtype_indication [aspect_clause];
-[Editor's note: "predicate_clause" is intended to be similar/identical
-to that used for types and subprograms. But Tucker hasn't made a formal
-proposal on that yet, so I will explain the rules needed here.]
-predicate_clause ::= with aspect_identifier => Boolean_expression
-Informal: The only aspect_identifier supported here is "Predicate".
+Informal: We define a new aspect "Predicate". It takes a Boolean_expression.
The Boolean_expression could use the defining_identifier of the
subtype, to mean the "current instance" of the subtype (that is,
the object to test the predicate against). [Editor's note:
I'll leave the formal wording of this to Tucker's proposal. No
sense in beating my head on a wall to figure this out!]
-Most likely, the formal proposal for clauses will require an associated
-operational attribute. In this case that would be S'Predicate, a
-function with a parameter of type S'Base returning Boolean. The
-definition of that attribute is not currently shown here.
The actual predicate is the given expression anded with the predicate
(if any) of the parent subtype. (The predicate of any subtype that
does not have one can be assumed to be the boolean literal True.)
[Editor's note: The predicate has no effect on the static or
-dynamic semantics of the subtype indication except as noted here.]
+dynamic semantics of the subtype indication except as noted here. In
+particular, it has no effect on the range of scalar subtypes.]
+Bounded Errors [where to put this?? It seems related to 13.9.1 - Data validity]
+It is a bounded error to use a value or access an object of a subtype that has
+a predicate to violate the predicate (that is, for the predicate to evaluate
+to false on the value or object). If the error is detected,
+Assertions.Predicate_Error or Program_Error is raised; otherwise, the use
+of the value or access of the object proceeds normally. An implementation
+may evaluate a predicate at any such use or access in order to detect this
+[Editor's note: We allow Program_Error because all bounded errors can raise
+Program_Error. The "proceeds normally" wording is the same as 4.8(11.1/2).]
+AARM Ramification: An implementation can evaluate a predicate any time an
+object is accessed in any way, if it desires. We have to say this so that
+any side-effects of the predicate (bad practice, but surely allowed) cannot
+be depended upon. Note that this isn't the same as being allowed to check
+the predicate anywhere at all; there has to be some use of a value or object
+that has the subtype. That's necessary so that it is possible to write
+the predicate without an evaluation of itself being triggered.
+Add to the end of 3.3.1(18/2) (which describes the meaning of "initialized
+If the nominal subtype has a predicate, the predicate is applied to the
+object and Assertions.Predicate_Error is raised if the result is False.
+[Editor's note: We need to check that default initialized objects don't violate
Informally, the predicate of the corresponding subtype is that of the
subtype of the parent/progenitor type anded with the predicate of the
+derived type. The new (sub)type is considered to have a predicate (even if none
+is explicitly given).
AARM Reason: If a subprogram has parameter(s) whose subtype(s) have
defined predicate(s), the generated code of subprogram body may depend on
@@ -76,6 +98,41 @@
of the derived subprogram might not actually check the predicates, and that
would cause big trouble.
+Add as the last sentence of 3.6(9):
+An index subtype shall not statically denote a subtype with a predicate.
+Add as the last sentence of 3.6(21):
+The elaboration of an array_type_definition raises Program_Error if the index
+subtype has a predicate.
+AARM Reason: We don't want to create "holey" array types; it is very confusing
+as to whether the values for which the predicate returns False have associated
+elements. By raising Program_Error, we prevent generic contract problems. But we
+also have a legality rule so when it is statically known (outside of a generic)
+we detect the problem at compile-time.]
+Add after 4.1.2(4):
+The discrete_range of a slice shall not statically denote a subtype with
+Add as the last sentence of 4.1.2(7):
+The evaluation of a slice raises Program_Error if any discrete_range is a
+subtype with a predicate.
+AARM Reason: We don't want to create "holey" slices, especially as slices can be
+required to be passed by reference (for by-reference component types), and ignoring
+the predicate would be very confusing. By raising Program_Error, we prevent generic
+contract problems. But we also have a
+legality rule so when it is statically known (outside of a generic) we detect
+the problem at compile-time.]
The tested type is scalar, and the value of the simple_expression belongs
@@ -96,6 +153,22 @@
If the target subtype has a predicate, the predicate is applied to the value
and Assertions.Predicate_Error is raised if the result is False.
+Add after 4.6(58):
+If the target subtype of a conversion has a predicate, and the nominal subtype
+of the operand is that same subtype, an implementation may omit the application
+of a predicate to the operand.
+AARM Reason: We have to say this because (bad) predicates can have side-effects,
+and because intermediate operations can make good predicates become False. For
+instance, assignment to individual components of a record type might cause the
+value to violate a previously checked predicate.
+AARM Discussion: If the implementation does omit the check of the predicate, it
+cannot later assume that the predicate is true.
A subtype statically matches another subtype of the same type if they have
@@ -133,19 +206,22 @@
subtype Even is Integer range 1 .. 10 when Predicate => Even mod 2 = 0;
type Evens is array (Even) of Boolean; -- 5 or 10 elements?
Obj : Evens;
- Obj(1) := False; -- Raises Predicate_Error.
+ Obj(1) := False; -- Would Raise Predicate_Error.
Type Evens has length 10. Evens'range goes from 1 .. 10. However, attempting
to index component 1 will raise Predicate_Error. (That's because 1 will be converted
to subtype Even, as noted in 4.1.1(7), and that will trigger a predicate check.)
-This is a bit annoying, but it again is similar to the behavior of null exclusions:
+However, the situation gets nastier still when arrays are sliced by subtypes with a
+ Str : String := "1234567890";
- type Acc_Int is not null access Integer;
- Ptr : Acc_Int; -- Raises Constraint_Error
-In both cases, doing something stupid creates trouble. But there is no good
-reason to write either of these examples, and compilers can provide warnings
-in both cases. So it does not appear to be a significant issue.
+One might expect to have "24680" printed, but since the constraints are unchanged,
+"1234567890" would actually be printed. Because of this weird behavior, we do not
+allow predicates on index subtypes. In order to avoid breaking the contract
+model, we raise Program_Error in generic bodies if the subtype has a predicate.
@@ -157,8 +233,10 @@
(2) A predicate does not clearly define 'First or 'Last values, so calling
it a constraint on a scalar subtype brings up many nasty questions. For
- subtype Even is Integer range 1 .. 10 when Predicate => Even mod 2 = 0;
- type Evens is array (Even) of Boolean; -- 5 or 10 elements?
+ subtype Mapping is Integer range 1 .. 10 when Predicate => Map(Mapping);
+What is Even'First? Without analyzing the body of Map (which may not even have
+been written yet), we can't say. And even if we made it dynamic, Map may
+have side effects and not return the same answer each time it is called.
(3) A predicate can depend on components other than discriminants. If a
component is modified, the predicate can become false. This can happen at
arbitrary points in the program. It is especially bad when the predicate is
@@ -175,8 +253,9 @@
An alternative way of looking at predicates is to assume that all subtypes
-have a predicate of True by default, and a predicate_clause just replaces
-that with something user-defined.
+have a predicate of True by default, and a predicate aspect just replaces
+that with something user-defined. The wording would have to be very different
+in that case.
@@ -189,10 +268,11 @@
Note that predicates are only true at the point where the language does a
-subtype conversion into the subtype. Depending on the predicate, later
-operations can make the predicate False. This is not a major problem for
-the primary intended use of predicates (on formal subprogram parameters),
-but could be an issue if they are used on subtypes in other contexts.
+subtype conversion into the subtype, and immediately after default initialization.
+Depending on the predicate, later operations can make the predicate False. This
+is not a major problem for the primary intended use of predicates (on formal
+subprogram parameters), but could be an issue if they are used on subtypes
+in other contexts.
@@ -213,7 +293,8 @@
The predicate on Decimal_Rec will be checked on the aggregate at (1).
However, after the call at (2), the predicate is no longer true for Obj.
-The call at (3) will put False.
+The call at (3) will print False. Implementations are allowed to check
Questions? Ask the ACAA Technical Agent