Version 1.4 of 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