Version 1.4 of ai12s/ai12-0325-1.txt

Unformatted version of ai12s/ai12-0325-1.txt version 1.4
Other versions for file ai12s/ai12-0325-1.txt

!standard 4.2(6)          19-04-09 AI12-0325-1/09
!standard 4.2(10)
!standard 4.2(11)
!standard 4.2.1(0)
!reference AI12-0249-1
!reference AI12-0295-1
!class Amendment 19-04-01
!status Amendment 1-2012 19-04-01
!status ARG Approved 10-0-0 19-04-09
!status work item 19-04-01
!status received 15-03-20
!priority Low
!difficulty Easy
!subject Various issues with user-defined literals
!summary
A universal type "covers" types that have the appropriate kind of _Literal aspect specified.
The definition of qualified expressions is modified so that it provides an expected type.
"String Type" is defined as in Ada 2012. In particular, a type with a specified String_Literal aspect is not a string type.
!problem
There are a number of issues with definition of user-defined literals.
(1) 4.2(8) says that integer literals have type universal integer (and similarly for real literals). There doesn't seem to be any rule that allows these literals to match a type with the appropriate Integer_Literal or Real_Literal aspect.
(2) Bounded Errors are runtime issues. 4.2.1(9/5) says that one of the possible consequences of an action at run time is that the unit might not compile. This seems confused.
(3) Various rules (both old and new) in 4.2 talk about the "expected type" of a literal. However, there are contexts that don't identify a specific expected type, and the expression of a qualified expression does not have an expected type at all (it "shall resolve" to the specified type).
(4) AI12-0295-1 defines "String type" to include types that have a defined String_Literal aspect. This causes a number of issues:
(A) We don't change "numeric type" this way, so the wording in 4.2 and 4.2.1 is oddly different for numeric and string literals.
(B) There are many rules that we only want to apply to Ada 2012 string types. For instance, we don't want static expressions of types with user-defined string literals. This leads to rather convoluted descriptions of rules, such as the proposed 4.2(11/5):
The evaluation of a string_literal that is a primary and has an expected type that is a one-dimensional array type with a character type as its component type, yields an array value ...
!proposal
(See Summary.)
!wording
[Author's note: This wording is relative to the Ada 2012 wording plus the AI12-0249-1 wording, not the changed wording from AI12-0295-1. All of the wording is to fix Problem (4) unless otherwise noted.]
[Editor's note: These changes are found in Draft 19 of the RM.]
There is no change to 3.6.3(1) (unlike AI12-0295-1).
Modify 3.4.1(9): [Problem (1)]
A class-wide or universal type is said to cover all of the types in its class. {In addition, universal_integer covers a type that has a specified Integer_Literal aspect, while universal_real covers a type that has a specified a Real_Literal aspect (see 4.2.1).} A specific type covers only itself.
Modify 4.2(4):
The expected type for a primary that is a string_literal shall be a single string type{ or a type with a specified String_Literal aspect (see 4.2.1)}.
[Author's note: This is the only new wording change; all of the others are simplifications.]
Modify 4.2(6):
{If the expected type for a string_literal is a string type, then} [F]{f}or each character of [a]{the} string_literal [with a given expected string type,] there shall be a corresponding defining_character_literal of the component type of the expected string type.
Modify 4.2(10):
The evaluation of a string_literal that is a primary {and has an expected type that is a string type,} yields an array value containing the value of each character of the sequence of characters of the string_literal, as defined in 2.6. The bounds of this array value are determined according to the rules for positional_array_aggregates (see 4.3.3), except that for a null string literal, the upper bound is the predecessor of the lower bound. {Redundant[In other cases, the effect of evaluating a string_literal is determined by the String_Literal aspect that applies (see 4.2.1).]}
[Author's note: The last sentence echoes one found in 4.2(9); it was missing from AI12-0295-1 and reviewers complained about that.]
Modify 4.2(11):
For the evaluation of a string_literal of {a string} type T, a check is made that the value of each character of the string_literal belongs to the component subtype of T. For the evaluation of a null string literal {of a string type}, a check is made that its lower bound is greater than the lower bound of the base range of the index type. The exception Constraint_Error is raised if either of these checks fails.
[Author's note: The part about restricting the check for null string literals to (Ada 2012) string types is missing from AI12-0295-1. It certainly can't apply to types with String_Literal aspects, as those probably are not arrays and thus have no bounds.]
4.2.1(5/5) and 4.2.1(9/5) are unchanged from the AI12-0295-1 versions.
The AI12-0295-1 4.2.1(6/5) paragraph is omitted.
In 4.2.1(7/5), replace the String_Literal sentence with:
The String_Literal aspect shall not be specified for a type T if the full view of T is a string type.
In 4.2.1(7/5) and 4.2.1(8/5) replace: [wording cleanup related to Problem (3)]
...an integer literal with its expected type having an Integer_Literal aspect specified...
with:
...an integer literal that has an expected type with a specified Integer_Literal aspect...
replacing "integer" with "real" and "string" as needed.
Replace 4.2.1(10/5) (the Bounded Error) with: [Problem (2)]
It is a bounded error if the evaluation of a literal that has an expected type with a specified Integer_Literal, Real_Literal, or String_Literal aspect, propagates an exception. Either Program_Error or the exception propagated by the evaluation is raised at the point of use of the value of the literal. If it is recognized prior to run time that evaluation of such a literal will inevitably (if executed) result in such a bounded error, then this may be reported as an error prior to run time.
Modify 4.7(3): [Problem (3)]
The {expected type for the} operand (the expression or aggregate) {is} [shall resolve to be of the type] determined by the subtype_mark[, or a universal type that covers it].{ Furthermore, the operand shall resolve to be either the specified expected type or a universal type that covers it.}
AARM Reason: The first sentence defines the expected type for rules that assume one is defined. The second sentence prevents the use of the various implicit conversions that are usually allowed for expected types (except the one for numeric literals). The intent is that a qualified expression is similar to an assertion about the subtype of the operand, and thus implicit conversions would interfere with that intent.
There is no change to 4.9(26/3) (unlike AI12-0295-1).
!discussion
We take the opportunity to rephrase the wording describing types that have some _Literal aspect. The old wording was rather clunky.
The resolution change for qualified expressions is thought to make no change in whether or not an Ada program resolves.
Lots of wording in the Standard assumes that an expression has a well-defined expected type. This has always led to questions about what the meaning is when that is not true, as in a qualified expression. The Problem 3 change will at least eliminate that issue (although questions when the expected type is not specific may continue).
The wording changes for problem 4 do not make any semantic change to the features defined in AI12-0295-1.
!corrigendum 3.4.1(9)
Replace the paragraph:
A class-wide or universal type is said to cover all of the types in its class. A specific type covers only itself.
by:
A class-wide or universal type is said to cover all of the types in its class. In addition, universal_integer covers a type that has a specified Integer_Literal aspect, while universal_real covers a type that has a specified Real_Literal aspect (see 4.2.1). A specific type covers only itself.
!corrigendum 4.2(4)
Replace the paragraph:
The expected type for a primary that is a string_literal shall be a single string type.
by:
The expected type for a primary that is a string_literal shall be a single string type or a type with a specified String_Literal aspect (see 4.2.1).
!corrigendum 4.2(6)
Replace the paragraph:
For each character of a string_literal with a given expected string type, there shall be a corresponding defining_character_literal of the component type of the expected string type.
by:
If the expected type for a string_literal is a string type, then for each character of the string_literal there shall be a corresponding defining_character_literal of the component type of the expected string type.
!corrigendum 4.2(10)
Replace the paragraph:
The evaluation of a string_literal that is a primary yields an array value containing the value of each character of the sequence of characters of the string_literal, as defined in 2.6. The bounds of this array value are determined according to the rules for positional_array_aggregates (see 4.3.3), except that for a null string literal, the upper bound is the predecessor of the lower bound.
by:
The evaluation of a string_literal that is a primary and has an expected type that is a string type, yields an array value containing the value of each character of the sequence of characters of the string_literal, as defined in 2.6. The bounds of this array value are determined according to the rules for positional_array_aggregates (see 4.3.3), except that for a null string literal, the upper bound is the predecessor of the lower bound. In other cases, the effect of evaluating a string_literal is determined by the String_Literal aspect that applies (see 4.2.1).
!corrigendum 4.2(11)
Replace the paragraph:
For the evaluation of a string_literal of type T, a check is made that the value of each character of the string_literal belongs to the component subtype of T. For the evaluation of a null string literal, a check is made that its lower bound is greater than the lower bound of the base range of the index type. The exception Constraint_Error is raised if either of these checks fails.
by:
For the evaluation of a string_literal of a string type T, a check is made that the value of each character of the string_literal belongs to the component subtype of T. For the evaluation of a null string literal of a string type, a check is made that its lower bound is greater than the lower bound of the base range of the index type. The exception Constraint_Error is raised if either of these checks fails.
!corrigendum 4.2.1(0)
Insert new clause:
Just enough to cause a conflict; the real changes are in the conflict file.
!corrigendum 4.7(3)
Replace the paragraph:
The operand (the expression or aggregate) shall resolve to be of the type determined by the subtype_mark, or a universal type that covers it.
by:
The expected type for the operand (the expression or aggregate) is determined by the subtype_mark. Furthermore, the operand shall resolve to be either the specified expected type or a universal type that covers it.
!ASIS
None here, since this is just changing the presentation of the change.
!ACATS test
No tests needed for this AI, since this is just a presentation change.
!appendix

From: Steve Baird
Sent: Thursday, March 7, 2019  3:51 PM

[Part of Steve's RM review - Editor.]

3.6.3 - ok
  We've got "There are three predefined String types", which would be
  confusing (does that mean "at least three" or "exactly three" ?) if some
  other predefined package defined a type with the String_Literal aspect
  specified, but that does not appear to be the case. 

4.2 ...

   In 9/5, we've got
   " In other cases, the effect of evaluating a numeric literal is determined
   by the Integer_Literal or Real_Literal aspect that applies (see 4.2.1)."
   That seems good, but there is no analogous text for string literals.

   It seems messy having three slightly-different uses of "one-dimensional
   array type" in this section. Similarly, the rule in 4.2 about
   "T is a string type (in the absence of the String_Literal aspect
   specification)." seems awkward. It looks like we need a term corresponding
   to the *old* definition of "string type".

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

From: Randy Brukardt
Sent: Wednesday, March 20, 2019  12:08 AM

...
>3.6.3 - ok
>  We've got "There are three predefined String types", which would be
>  confusing (does that mean "at least three" or "exactly three" ?) if some
>  other predefined package defined a type with the String_Literal aspect
>  specified, but that does not appear to be the case. 

I griped about calling types with a String_Literal aspect a "string type", 
since most of the properties of a string type don't apply. Tucker seemed to
feel strongly the other way, since he changed all of those other places 
instead of getting rid of this silly definition after my complaint.

As such, we're living with this, and it's hard to get too worked up about how 
many string types there actually are.

...

>   In 9/5, we've got
>   " In other cases, the effect of evaluating a numeric literal is determined
>   by the Integer_Literal or Real_Literal aspect that applies (see 4.2.1)."
>   That seems good, but there is no analogous text for string literals.

That happens because any type with a String_Literal is a string type, so 
there's no sane way to write such a rule. As noted above, I think that is 
madness but I lost that discussion. In any case, we don't need to say anything 
here. (The 9/5 rule could and probably should be marked Redundant[]).

>   It seems messy having three slightly-different uses of "one-dimensional
>   array type" in this section. Similarly, the rule in 4.2 about
>   "T is a string type (in the absence of the String_Literal aspect
>   specification)." seems awkward. It looks like we need a term corresponding
>   to the *old* definition of "string type".

No, we *only* need the old definition of "string type". There's no reason that 
I can see to have a term for types that have user-defined literals. And we are 
just fine not changing the definition of numeric types, why are strings (and 
characters, in the AI we didn't adopt) different?? But again, I lost that 
argument previously and I am uninterested in trying to argue it again, 
especially as the AI needed would be nearly as big as the original
AI12-0295-1 (*all* of the wording in AI12-0295-1 would need to change). If you 
want to propose such an AI, go ahead, but I don't have the time or energy to 
do so.

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

From: Steve Baird
Sent: Thursday, March 21, 2019  8:07 PM

...
> I griped about calling types with a String_Literal aspect a "string 
> type", since most of the properties of a string type don't apply. 
> Tucker seemed to feel strongly the other way, since he changed all of 
> those other places instead of getting rid of this silly definition after my complaint.
> 
> As such, we're living with this, and it's hard to get too worked up 
> about how many string types there actually are.

Insufficiently broken. Let's stick with what we have now.

...

> No, we *only* need the old definition of "string type". There's no reason that 
> I can see to have a term for types that have user-defined literals. And we are 
> just fine not changing the definition of numeric types, why are strings (and 
> characters, in the AI we didn't adopt) different?? But again, I lost that 
> argument previously and I am uninterested in trying to argue it again, 
> especially as the AI needed would be nearly as big as the original
> AI12-0295-1 (*all* of the wording in AI12-0295-1 would need to change). If you 
> want to propose such an AI, go ahead, but I don't have the time or energy to 
> do so.

I do not plan to propose any such AI.

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

From: Tucker Taft
Sent: Sunday, March 24, 2019  11:56 PM

> I griped about calling types with a String_Literal aspect a "string 
> type", since most of the properties of a string type don't apply. 
> Tucker seemed to feel strongly the other way, since he changed all of 
> those other places instead of getting rid of this silly definition after my 
> complaint.

I don't feel as strongly as you imply.  In fact, I don't remember reading your 
complaint, so I might have just missed it, or not fully appreciated the 
implications.

> As such, we're living with this, and it's hard to get too worked up 
> about how many string types there actually are.

I am amenable to *not* generalizing the notion of a "string type."  I felt it 
simplified things, but if in fact it complicates things, then let's get rid 
of it.

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

[Editor's note: After reading the above, Steve changed his position and
(privately) asked for an AI to be created with these changes.]

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

From: Randy Brukardt
Sent: Monday, April 1, 2019  9:37 PM

There is no resolution rule for numeric literals in 4.2; rather 4.2(8/2) says 
that they have type universal integer or universal real by fiat.

4.2.1 has Legality and Dynamic Semantics rules for types with Integer_Literal 
aspects, but no resolution rule. So how does one figure out that one can match
a literal of type universal_integer to a type like Big_Int that has a specified
Integer_Literal aspect?? 

Cricket and frog sounds. :-)

Something needs to be done here, although I'm not certain what. Easiest would 
be to add to 4.2 a Resolution Rule like:

The type of an integer_literal is universal_integer or a type with a specified 
Integer_Literal aspect. The type of a real_literal is universal_real or a type 
with a specified Real_Literal aspect.

But I'm not sure that actually works, since it seems to work both ways at once 
(it's using the incoming type in the case of a type with the aspect, and 
forcing a result otherwise).

Ideas??

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

From: Tucker Taft
Sent: Monday, April 1, 2019  11:27 PM

Interesting question.  My presumption was that the literals remained of a 
universal type, but that we were changing the rules for their implicit 
conversion into the appropriate non-universal numeric type.  Hence, we might 
make a change to 3.4.1(9):

  A class-wide or universal type is said to cover all of the types in its 
  class. {In addition, universal_integer covers a type with an Integer_Literal 
  aspect, while universal_real covers a type with a Real_Literal aspect (see 
  X.Y).} A specific type covers only itself.

If we redefine "cover" this way, then I believe overload resolution as defined 
by 8.6(24) will do the right thing:

  *  to a universal type that covers T; or

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

From: Randy Brukardt
Sent: Monday, April 1, 2019  11:42 PM

I wasn't expecting any answers for this until Thursday at the earliest. :-)

I think this idea works, it would have helped if you had written it down 
sometime in the past. :-) Anyway, I'll try to write something up for the 
upcoming meeting.

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

From: Randy Brukardt
Sent: Monday, April 1, 2019  9:20 PM

The wording for user-defined literals includes:

For the evaluation of an integer literal with its expected type having an 
Integer_Literal aspect specified, 

So how does evaluation of integer literals work when there is no expected type?

[Note: 4.2 also uses wording like this, mostly in new wording, but also in the 
resolution rule 4.2(4).]

In particular, recall that the operand of a qualified expression uses "shall 
resolve to"; there is no expected type (since expected types include implicit 
type conversions, which we don't want in this context). So, taking the wording
of 4.2 and 4.2.1 literally, it appears that the execution of the literal 1 in:

    Some_Type'(1)

is not defined, since 1 does not have an expected type.

At a minimum, we ought to add a To Be Honest for this case, but since we've 
been quite careful to avoid this problem in the past, it seems that it would 
be better to fix it.

4.1(9/3) uses "if the type of the name in a dereference is ..."; perhaps some 
form like that would be better.

One possibility would be something like:

For the evaluation of an integer literal whose type has a specified 
Integer_Literal aspect, 

or maybe:

For the evaluation of an integer literal that has a type with a specified 
Integer_Literal aspect, 

Thoughts?? (If I get some in time I can put this into the already open 
clean-up AI for this text.)

Note: 4.2(4) has said for decades:

  The expected type for a primary that is a string_literal shall be a single 
  string type. 

so apparently one cannot use a string literal in a qualified expression where 
there is no expected type. ;-)

4.2(3) and 4.2(5) also talks about expected types for character literals.
End Note.


Aside: I find the original wording clunky anyway. There seems to need to be 
some word to tie the expected type to the literal and to clarify that the 
association is:

an integer literal with (its expected type having an Integer_Literal aspect)

and not

(an integer literal with its expected type) having an Integer_Literal aspect

[since this latter puts the aspect on the literal, not the type]

Tucker used no word at all, and I find that just doesn't parse cleanly:

For the evaluation of an integer literal with expected type having an 
Integer_Literal aspect specified, 

But I don't like any of the words I tried either:

For the evaluation of an integer literal with an expected type having an 
Integer_Literal aspect specified, 

For the evaluation of an integer literal with the expected type having an 
Integer_Literal aspect specified, 

For the evaluation of an integer literal with its expected type having an 
Integer_Literal aspect specified, 

A more radical change would be better:

For the evaluation of an integer literal whose expected type has a specified 
Integer_Literal aspect, 

or

For the evaluation of an integer literal that has an expected type with a 
specified Integer_Literal aspect, 

I used forms of these in the proposal above.
End Aside.

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

From: Tucker Taft
Sent: Monday, April 1, 2019  11:54 PM

> In particular, recall that the operand of a qualified expression uses 
> "shall resolve to"; there is no expected type (since expected types 
> include implicit type conversions, which we don't want in this 
> context). So, taking the wording of 4.2 and 4.2.1 literally, it 
> appears that the execution of the literal 1 in:
> 
>    Some_Type'(1)
> 
> is not defined, since 1 does not have an expected type.

In my earlier e-mail, I suggested re-defining "cover" to say that 
universal_integer covers any type with an Integer_Literal aspect, and a 
corresponding rule for universal_real.  That also helps with the resolution 
specified in 4.7(3) for qualified expressions:

  The operand (the expression or aggregate) shall resolve to be of the type
  determined by the subtype_mark, or a universal type that covers it. 

We could rephrase this to say that the specified type is also the expected type:

  The expected type for the operand (the expression or aggregate) is determined
  by the subtype_mark.  Furthermore, the operand shall resolve to be either of the
  specified expected type or a universal type that covers it.

This would ensure that we can continue to use "expected type" in various other 
contexts without always having to worry about the qualified-expression special 
case.

...
> One possibility would be something like:
> 
> For the evaluation of an integer literal whose type has a specified 
> Integer_Literal aspect,
> 
> or maybe:
> 
> For the evaluation of an integer literal that has a type with a 
> specified Integer_Literal aspect,
> 
> Thoughts?? (If I get some in time I can put this into the already open 
> clean-up AI for this text.)

I don't like these.  The type of numeric literals should remain universal in 
my view.  See my earlier e-mail.

> Note: 4.2(4) has said for decades:
> 
>  The expected type for a primary that is a string_literal shall be a 
> single string type.
> 
> so apparently one cannot use a string literal in a qualified 
> expression where there is no expected type. ;-)

See my proposal above.

... 
> A more radical change would be better:
> 
> For the evaluation of an integer literal whose expected type has a 
> specified Integer_Literal aspect,
> 
> or
> 
> For the evaluation of an integer literal that has an expected type 
> with a specified Integer_Literal aspect,
> 
> I used forms of these in the proposal above.

Either of these last two seem fine.  I slightly prefer the second one.

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


Questions? Ask the ACAA Technical Agent