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 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

!summary

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.

!issue

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.

!recommendation

(See Summary.)

!wording

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):

!discussion

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.

!corrigendum B.3.3(22/2)

@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.

!corrigendum B.3.3(23/2)

@ddel

@xbullet{Evaluation of the predefined equality operator for an unchecked union type if either of the operands lacks inferable discriminants.}

!corrigendum B.3.3(24/2)

@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.}

!ACATS test

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.

!appendix

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.

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