AI22-0028-1
!standard B.3.3(22/2) 22-06-14 AI22-0028-1/04
!standard B.3.3(23/2)
!standard B.3.3(24/2)
!class binding interpretation 22-01-24
!status Corrigendum 1-2022 22-06-14
!status ARG Approved 13-0-1 22-05-05
!status work item 22-01-24
!status received 21-11-16
!priority Very_Low
!difficulty Easy
!qualifier Clarification
!subject Program_Error for unchecked union equality
Program_Error is not raised when predefined equality on a record containing an unchecked-union subcomponent is evaluated if a component with a
user-defined equality encloses the unchecked union subcomponent.
It seems that when we changed the rules on equality to make record types use
their primitive equality everywhere, we didn't adjust the rules for equality
on unchecked unions. Here are the relevant rules from B.3.3:
22/2 Program_Error is raised in the following cases:
23/2 * Evaluation of the predefined equality operator for an unchecked
union type if either of the operands lacks inferable
discriminants.
24/2 * Evaluation of the predefined equality operator for a type which
has a subcomponent of an unchecked union type whose nominal
subtype is unconstrained.
Paragraph (24/2) does not make sense if there is a user-defined equality operator for the unchecked union type itself, or if the unchecked union subcomponent is part of an enclosing subcomponent that has a user-defined equality operator. We only need to have Program_Error raised if the predefined equality operator of the unchecked union type would be "reachable" from the equality operator for the enclosing object.
(See Summary.)
Modify B.3.3(22/2):
Program_Error is raised [in the following cases:]{upon evaluation of the predefined equality operator for an unchecked union type if either of the operands lacks inferable discriminants.}
Delete B.3.3(23/2): (it’s merged above)
Delete B.3.3(24/2):
Note that the current rule requires raising Program_Error in cases where there is no problem, but does not allow anything problematic. As such, we do not want to incur any significant overhead to fix this problem.
The intent of the original rule is that it can be checked at compile-time outside of shared generic implementations (see AI95-00216-01). Ultimately, after considering various ways of accomplishing this, we opted for the easiest approach, namely deleting paragraph 24/2 completely, while leaving 23/2 as is. Dropping the part about inferable discriminants would be incompatible, as equality of constrained components would suddenly start raising Program_Error (the worst kind of incompatibility, where previously correct code would start raising an exception). Compilers can certainly provide a warning if they detect that a Program_Error is inevitable, but mandating a hard-to-define check was not deemed worthwhile.
@drepl
Program_Error is raised in the following cases:
@dby
Program_Error is raised upon evaluation of the predefined equality operator for an unchecked union type if either of the operands lacks inferable discriminants.
@ddel
@xbullet{Evaluation of the predefined equality operator for an unchecked union type if either of the operands lacks inferable discriminants.}
@ddel
@xbullet{Evaluation of the predefined equality operator for a type which has a subcomponent of an unchecked union type whose nominal subtype is unconstrained.}
An ACATS C-Test should be constructed to check that a user-defined equality for an unchecked union type (or for an enclosing record type) does not cause Program_Error to be raised.
From: Tucker Taft
Sent: Tuesday, November 16, 2021 12:27 PM
It seems that when we changed the rules on equality to make record types use
their primitive equality everywhere, we didn't adjust the rules for equality
on unchecked unions. Here are the relevant rules from B.3.3:
22/2 Program_Error is raised in the following cases:
23/2 * Evaluation of the predefined equality operator for an unchecked
union type if either of the operands lacks inferable
discriminants.
24/2 * Evaluation of the predefined equality operator for a type which
has a subcomponent of an unchecked union type whose nominal
subtype is unconstrained.
Paragraph (23/2) seems fine, but paragraph (24/2) does not make sense any more
if there is a user-defined equality operator for the unchecked union type
itself, or if the unchecked union subcomponent is part of an enclosing
subcomponent that has a user-defined equality operator. We only want to have
Program_Error if the predefined equality operator of the unchecked union type
would be "reachable" from the equality operator for the enclosing object.
I presume we wanted to allow the implementation to raise Program_Error
immediately, rather than doing some of the equality checks and then noticing
it had reached an unchecked union part of the objects being compared. But
this seems like an unnecessary permission, and trying to combine the intent of
this permission with the new rules on use of primitive equality everywhere for
record types seems just too complicated.
Looking back at the original AI on Unchecked_Union, it actually includes
discussion of paragraph (24/2), and the intent was to make this a compile-time
check (at least outside of shared generics). So perhaps we should come up
with some wording that works at compile time, but it is probably going to
require some "interesting" wording.
E.g.:
* Evaluation of the predefined equality operator for a composite type that
has a subcomponent of an unchecked union type, where the unchecked union
and each of the types that enclose it within this outer composite type
either lacks a user-defined primitive equality operator, or is an array
type;
Not great, but should be checkable at compile time...
**********************************************************************
From: Randy Brukardt
Sent: Tuesday, June 14, 2021 10:37 PM
Tucker noticed that the wording would be better if we eliminated the bullets altogether and merged the remaining text into a single sentence.
He did so by simply editing this AI; but since this AI was approved at the May meeting, he should not have modified it without an Editorial Review explanation. This note is standing in for the missing explanation.
**********************************************************************