Version 1.4 of si99s/si99-0045-1.txt
!standard 17.1 09-05-07 SI99-0045-1/04
!class binding interpretation 08-10-21
!status ARG Approved 7-0-2 09-02-21
!status work item 08-10-21
!status received 08-10-21
!priority Low
!difficulty Easy
!qualifier Omission
!subject The meaning of Corresponding_Expression_Type
!summary
If Corresponding_Expression_Type is applied to an expression with a named
nominal subtype, it returns the declaration for the subtype mark in the
definition of the nominal subtype, regardless of any constraint or null
exclusion that might appear.
If the subtype mark in the definition is a Base attribute reference, the
declaration of the prefix of the attribute is returned.
Corresponding_Expression_Type returns Nil_Element if applied to a
named_number, a numeric literal, a null literal, or an object of an
anonymous or class-wide type. It also returns Nil_Element if applied to
an expression representing something without a type, such as a package
or an exception.
The result is implementation-defined for attribute references,
aggregates, and other expressions that are not syntactically "names."
!question
Corresponding_Expression_Type (17.1) insists on not "unwinding"
subtypes. What should be returned by Corresponding_Expression_Type(Var),
if the declaration of Var is as follows:
Var : Integer range 1..10;
There is no declaration for the subtype of Var.
More generally, an expression has a type, but no subtype. There should be
an explanation about what is returned. Presumably:
- For a variable or a constant: the subtype used in the declaration (but
see above)
- For a function call: the subtype used in the function declaration
- For named number, a numeric literal: perhaps Nil? Universal types have no
declaration.
What is the intent? (See summary.)
!recommendation
(See summary.)
!wording
Replace the wording of 17.1 as follows:
function Corresponding_Expression_Type (Expression : in Asis.Expression)
return Asis.Declaration;
Expression specifies the expression to query.
Returns the declaration for the subtype named by the subtype mark in the
definition of the nominal subtype of the expression. If the
subtype mark in the definition is a Base attribute reference, the
declaration of the prefix of the attribute is returned.
Returns an implementation-defined result if the expression is an
attribute reference other than Base, aggregate, string literal, allocator,
membership test, short-circuit operation, or the invocation of a predefined
operator.
For a slice, the result is the same as for the prefix of the slice. For
an invocation of a user-defined operator, the result is the same as for
the equivalent function call. For a parenthesized expression, it is the
same as for the enclosed expression.
Returns a Nil_Element if the expression is of an anonymous or classwide
type, or is a named number, a numeric literal, or a null literal.
Returns a Nil_Element if the expression denotes an entity that does not
have a type, such as a package or an exception.
NOTE:
This query does not "unwind" subtypes or derived types to get
to the first subtype or parent subtype declarations, but it does ignore
explicit constraints or null exclusions in the definition of the nominal
subtype. For example, for the following program text:
type Int is range -5_000 .. 5_000;
type My_Int is new Int;
type Good_Int is new My_Int;
Var: Good_Int range -2_000 .. 2_000;
for Corresponding_Expression_Type of an expression denoting Var, the
declaration for Good_Int should be returned. No further "unwinding"
should occur. The declaration for either My_Int or Int should not be
returned.
!discussion
This is a very strange function, as it would lose some constraints (or
return Nil for things that have perfectly useful values). It would be
useful to give you the type, but it doesn't do that. What does it do
for anonymous arrays?
We don't want to change the meaning of this function, because it would
be hard to find bugs caused by such a change. We should define that things
that don't have definitions would give the first thing that does have a
definition: such as Integer'Base would return Integer.
However, for anonymous types, it would not make sense to return some
type that is part of the definition. For instance, for anonymous access types,
this would lose the fact that it is an access type. So we just return
nil_element. If the actual type is important, the semantic subsystem should
be used.
Note that the case of a class-wide type is already defined as returning a
Nil_Element.
It seems logical to handle singleton protected objects like singleton task
objects, since "this query is limited, on purpose" (sic). This requires
no special wording as the task or protected type in such cases is anonymous.
However, for tasks and protected objects of a named type, we see no reason
not to return the declaration of the appropriate named subtype.
We have allowed the result to be implementation-defined for constructs
without a well-defined nominal subtype, since we don't want implementations
to have to change what they currently return for these. A program that wants
a well-defined answer for these cases ought to use the semantic subsystem.
!appendix
From: Jean-Pierre Rosen
Sent: Sunday, February 22, 2009 2:26 AM
Some notes about this: ["This" is version /o2 of the SI - ED.]
In the !summary
"If Corresponding_Expression_Type is applied to an *object* with a named nominal subtype"
"object" should be "expression". The !wording is correct.
Basing this SI on nominal subtypes avoids a lot of special cases, but something should
be said about expressions that do not seem to have a nominal subtype (at least from the
index):
- slices. 4.1.2(6) talks only about their type. Presumably, for slices, the query
should return the same value as for the prefix.
- Aggregates: the new proposal says nil_element is returned, but it was unspecified
in the original wording, except for the aggregate of an enum rep clause. This would
imply that something (the expected type?) was returned previously.
- Short-circuit and membership operations: I guess the declaration for Standard.Boolean
should be returned. What if the expected type is another boolean type?
- Parenthesized expression: same as the corresponding_expression_type of the content.
- Allocators: expected type, or Nil_Element?
In general, the query is defined to return the type of its argument, /not/ the expected
type. From a user's point of view, the expected type is generally what you need (and more
useful than nil_element!)
It should also be noted somewhere that this query can now return task types, when applied
to task objects (the old one returned nil-element "on purpose").
****************************************************************
From: Tucker Taft
Sent: Sunday, February 22, 2009 5:00 AM
Thanks for the very helpful feedback. During the discussion, we agreed to make
Corresponding_Expression_Type on attribute-references and aggregates implementation-defined,
rather than requiring it to return Nil_Element.
****************************************************************
From: Tucker Taft
Sent: Sunday, February 22, 2009 11:30 PM
Here is a version of the writeup for Corresponding_Expr_Type that incorporates comments from
JP Rosen. [This is version /03 - ED.]
****************************************************************
Questions? Ask the ACAA Technical Agent