Version 1.4 of ai12s/ai12-0328-1.txt
!standard 4.5.2(28.1/4) 19-05-09 AI12-0328-1/04
!standard 4.5.2(4.1/4)
!standard 4.5.2(15/3)
!class binding interpretation 19-04-10
!status Amendment 1-2012 19-05-09
!status ARG Approved 9-0-0 19-05-09
!status work item 19-04-05
!status received 19-03-28
!priority Low
!difficulty Easy
!subject Meaning of limited type and record type in 4.5.2(28.1/4)
!summary
Membership test on a type with a limited partial view with a
user-defined primitive "=" is illegal in the scope of the full type,
if the full type is nonlimited.
!question
4.5.2(28-28.1/4) (A Dynamic Semantics rule) reads:
An individual membership test yields the result True if:
* The membership_choice is a choice_simple_expression, and the
tested_simple_expression is equal to the value of the membership_choice.
If the tested type is a record type or a limited type, the test uses the
primitive equality for the type; otherwise, the test uses predefined
equality.
How does this work if the tested type is private? Does it depend on the
view of the type? (No, presuming it is legal on both views -- we make it
illegal on the full view in some cases)
!wording
Modify 4.5.2(4.1/4):
If a membership test includes one or more choice_simple_expressions
and the tested type of the membership test is limited, then the tested
type of the membership test shall have a visible primitive equality
operator{; if the tested type of the membership test is nonlimited
with a user-defined primitive equality operator that is defined at a point
where the type is limited, the tested type shall be a record type or
record extension}.
AARM Reason: We make the membership test on the nonlimited view of a type
illegal if it would use a different equality operator than what
would be used for a limited view of the same type (and such a limited view
exists).
Modify 4.5.2(15/3):
For a private type, if its full type is a record type {or record extension},
predefined equality is defined in terms of the primitive equals operator of
the full type; otherwise, predefined equality for the private type is that
of its full type.
Modify 4.5.2(28.1/4):
* The membership_choice is a choice_simple_expression, and the
tested_simple_expression is equal to the value of the
membership_choice. If the tested type is a record type or a [limited
type]{record extension, or is limited at the point where the
membership test occurs}, the test uses the primitive equality for
the type; otherwise, the test uses predefined equality.
AARM Reason: Note that if the membership test occurs where the
type is nonlimited, and not a record type or record extension, we
use the predefined equality operator, presuming the usage is legal.
!discussion
We want to be sure that you get the same result from a membership test
applied to the full view and the partial view, if both are legal.
Similarly, if the type is limited and then at a later point it becomes
nonlimited, we want to get the same answer. What we do is make it
illegal to perform a membership test on a nonlimited type if there is
place where it is limited and has a visible primitive equality operator,
unless that type is a record type or a record extension (since those use
the primitive equality operator everywhere.)
Making the dynamic semantics give different values depending on the view
is frowned upon, especially for an expression that could conceivably be
used in a default expression, where the default expression in the body
would see the nonlimited view, while the default expression in the spec
would see the limited view. For this special case, we make such a
membership test illegal where the nonlimited view is in scope. The
membership test can easily be replaced by a use of one or more equality
tests, in which case the same (primitive) equality operator would be
used independent of view, so there is an easy workaround in a case where
the membership test is made illegal by this change.
In rewording 4.5.2(28.1/4), it was noticed that a record extension is not
a record type. Thus, we have to mention both. We also have to change the
similar wording in 4.5.2(15/3), so that a case like the following gets the
correct result for the private view:
package P1 is
type Priv is tagged private;
private
type Priv is new Controlled with null record;
end P1;
(Note that if Priv was a private extension, then 4.5.2(14/3) would apply.)
Again, this is necessary so that result of equality is not view-specific.
!corrigendum 4.5.2(4.1/4)
Replace the paragraph:
If a membership test includes one or more choice_simple_expressions
and the tested type of the membership test is limited, then the
tested type of the membership test shall have a visible
primitive equality operator.
by:
If a membership test includes one or more choice_simple_expressions
and the tested type of the membership test is limited, then the
tested type of the membership test shall have a visible
primitive equality operator; if the tested type of the membership test is nonlimited
with a user-defined primitive equality operator that is defined at a point
where the type is limited, the tested type shall be a record type or
record extension.
!corrigendum 4.5.2(15/3)
Replace the paragraph:
For a private type, if its full type is a record type, predefined equality
is defined in terms of the primitive equals operator of the full type;
otherwise, predefined equality for the private type is that of its full type.
by:
For a private type, if its full type is a record type or a record extension,
predefined equality is defined in terms of the primitive equals operator of
the full type; otherwise, predefined equality for the private type is that
of its full type.
!corrigendum 4.5.2(28.1/4)
Replace the paragraph:
- The membership_choice is a choice_simple_expression, and
the tested_simple_expression is equal to the value of the
membership_choice. If the tested type is a record type or a limited type,
the test uses the primitive equality for the type; otherwise, the test uses
predefined equality.
by:
- The membership_choice is a choice_simple_expression, and
the tested_simple_expression is equal to the value of the
membership_choice. If the tested type is a record type or a record extension,
or is limited at the point where the membership test occurs,
the test uses the primitive equality for the type; otherwise, the test uses
predefined equality.
!ASIS
No ASIS effect.
!ACATS test
ACATS tests C452004, C452005, and C452006 test various cases like these.
!appendix
From: Randy Brukardt
Sent: Thursday, march 28, 2019 10:32 PM
I'm spending a couple of days working on ACATS tests.
RM 4.5.2(28-28.1/4) (A Dynamic Semantics rule) reads:
An individual membership test yields the result True if:
* The membership_choice is a choice_simple_expression, and the
tested_simple_expression is equal to the value of the membership_choice.
If the tested type is a record type or a limited type, the test uses the
primitive equality for the type; otherwise, the test uses predefined
equality.
AARM 3.1(7.d/3) says: "On the other hand, run-time rules can work either way,
so "view of" should not be assumed in Dynamic Semantics rules." The above
rule does not say "view of", so I presume that it ignores privacy.
This makes sense for records, as we want memberships to use the same "="
that is used for composition of equality. So in a case like:
package P1 is
type P is private;
function "=" (Left, Right : P) return Boolean;
private
type P is record ...
end P1;
We want the membership operation to use the primitive (user-defined) "=", not
the predefined one. (The version of GNAT I have gets this wrong on the new
ACATS test. Hope that's already been fixed.)
It's a bit weird that which equality is used for an array depends on whether
the array type is limited, but of course there's no choice in the limited case
(there's no predefined "=" to use), and the nonlimited case is consistent with
composition and generic formal private types. And user-defined equality on
array types isn't used that much.
Which brings us to my question. Consider (as in my new C452006 test):
package P2 is
type LP is private;
function "=" (Left, Right : LP) return Boolean;
private
type LP is access ...
end P2;
Here we have a type that is limited at the point of the membership, but the
full view is nonlimited (and elementary).
The rule as written seems to imply that we ignore privacy and use the full
view. In that case, the user-defined "=" is ignored by a membership operation,
and the (hidden) predefined equality is used.
However, that is mighty strange; the programmer may have declared the type
limited in the first place to ensure that the predefined equality wasn't used.
They're not likely to be happy that it reappeared.
Note that there isn't any such existing case that's not pathological (unlike
the array case): generic formal limited private types do not have "=", and
there is no predefined equality for limited types, so there is no composition
case to worry about. This sort of thing could happen only if a nested package
declared a composite type with a component of the limited private type; in
that case, the full view of the that type would have "="
and it would use the predefined "=" of the type -- but that "=" could only be
used in the body of the (outer) package -- clients could never see it. (I
consider this sort of case a pathology; Ada 83 should have banned it somehow
rather than adopting a bunch of messy rules to make it work in an unexpected
way, but of course it's way too late for that now.)
Also note that in the case where there is no visible "=", the membership is
illegal. So we don't have to worry about *that* case.
I suspect that it would make more sense for the rule to be written in terms of
whether the view of the type is visible. Of course, in that case, a membership
in the body of P2 would act differently than the same membership elsewhere.
Which I guess means we can't win. :-)
An alternative would be to write the rule in terms of immutably limited types
to make it clearer that privacy is ignored. But in that case, we'd probably
have to disallow writing a membership on a type whose full type is limited but
not immutably limited. (Which would be incompatible.)
<Some time passes> I just read all of the discussion and minutes on the
original AI, and didn't find anything about limited types other than Steve's
"obvious" observation that we shouldn't be using "=" that doesn't exist or
isn't visible (associated with adding the Legality Rule mentioned above).
Nothing about the Dynamic Semantics and views.
Thoughts on all of this?
****************************************************************
Questions? Ask the ACAA Technical Agent