CVS difference for ais/ai-10318.txt
--- ais/ai-10318.txt 2004/07/27 23:01:09 1.4
+++ ais/ai-10318.txt 2004/07/31 04:28:13 1.5
@@ -1,4 +1,5 @@
-!standard 03.10.02(13) 04-07-02 AI95-00318-02/03
+!standard 03.10.02(13) 04-07-282 AI95-00318-02/04
+!standard 03.09(14)
!standard 06.01(13)
!standard 06.03.01(16)
!standard 06.05(02)
@@ -25,7 +26,8 @@
!standard 06.05(24)
!standard 08.01(4)
!class amendment 02-10-09
-!status Amendment 200Y 04-07-02
+!status work item 04-07-28
+!comment !status Amendment 200Y 04-07-02
!status ARG Approved 9-0-2 04-06-17
!status work item 03-05-23
!status received 02-10-09
@@ -152,6 +154,11 @@
!wording
+Add before 3.9(14):
+
+If a record_type_declaration includes the reserved word limited, it is called
+a *limited record*.
+
Add after 3.10.2(13):
* The accessibility level of the anonymous access type of an access result
@@ -316,7 +323,15 @@
The new rule added before 7.5(2) by AI-287 should say:
...unless it is an aggregate, a function_call, or a parenthesized...
-Similarly, the new rule added after 7.5(8) and the replacement note of 7.5(9)
+The following should be added to the new rule added after 7.5(8) by AI-287:
+
+For a function_call of a type with a part that is of a task, protected, or
+limited record type that is used to initialize an object as allowed above, the
+implementation shall not create a separate return object (see 6.5) for the
+function_call. The function_call shall be constructed directly in the
+new object.
+
+Similarly, the replacement note of 7.5(9)
of AI-287 should say "aggregate or function_call" in each occurrence.
Add after 8.1(4):
@@ -548,7 +563,35 @@
an extended return statement. Once restored to its initial state, there
seems no harm in starting over in another extended_return_statement.
+THE BUILD-IN-PLACE IMPLEMENTATION REQUIREMENT
+
+The intent of this feature is that there never is copying of a "really" limited
+object. We have added an Implementation Requirement to insure that that is
+really the case.
+
+It has been argued that this requirement is not needed because any such copies
+are semantically neutral. But no copies of a self-referencing object could
+every really be semantically neutral. Moreover, the definition of object
+creation in 3.3(19) says that the subcomponents are assigned from the
+expression already evaluated. This clearly must be superceded.
+
+In addition, we want to tell the reader (Ada user and implementers alike) that
+function calls have changed. In Ada up to this point, function calls were
+always about copying (at least logically, 7.6(21) allows omitting the copy).
+That is emphatically not the case in the Amendment; indeed in a similar case
+for aggregates, we included such a requirement in the Corrigendum.
+
+!corrigendum 3.9(14)
+
+@dinsb
+The @fa<component_definition> of a @fa<component_declaration> defines the
+(nominal) subtype of the component. If the reserved word @b<aliased> appears
+in the @fa<component_definition>, then the component is aliased (see 3.10).
+@dinst
+If a @fa<record_type_declaration> includes the reserved word @b<limited>, it
+is called a @i<limited record>.
+
!corrigendum 3.10.2(13)
@dinsa
@@ -840,10 +883,10 @@
@dinst
@i<@s8<Implementation Requirements>>
-For a @fa<function_call> of a by-reference type whose full view
-is limited used to initialize an object as allowed above, the implementation
-shall not create a separate return object (see 6.5) for the @fa<function_call>.
-The @fa<function_call> shall be constructed directly in the
+For a @fa<function_call> of a type with a part that is of a task, protected, or
+limited record type that is used to initialize an object as allowed above, the
+implementation shall not create a separate return object (see 6.5) for the
+@fa<function_call>. The @fa<function_call> shall be constructed directly in the
new object.
!corrigendum 7.5(9)
@@ -1224,6 +1267,190 @@
Would resolve to the two different meanings. It might require some
changes to existing code, but not that much, and it would of course, be
caught at compile time.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, July 29, 2004, 1:06 AM
+
+AI-10318 includes the following rule:
+
+ Legality Rules
+
+ If the result subtype of a function is limited at the point where the
+ function is frozen (see 13.14), the result subtype shall be constrained.
+
+This was intended to make the implementation of limited build-in-place
+functions easier.
+
+At the Palma meeting, Pascal pointed out that this is incompatible with
+existing generic units that have generic limited private type parameters. He
+asked me to add the example of ACATS foundation FDD2A00, which this rule
+makes illegal -- and it doesn't raise Program_Error in use. (This example is
+not quite as compelling as it could be, as the foundation in question was
+created by "PHL". :-)
+
+However, I noticed that this foundation is testing stream attributes. The
+problem is caused by 'Input being a function. Indeed, that shows that the
+above legality rule has additional compatibility problems and as well needs
+help to cover stream attributes.
+
+Let's look at an example.
+
+ package Ugh is
+ type Lim_Tagged is limited tagged private;
+ function My_Input (Stream : access Root_Stream_Type'Class)
+ return Lim_Tagged;
+ -- Legal only if the type doesn't have any discriminants.
+ for Lim_Tagged'Input use My_Input;
+ function My_Class_Input (Stream : access Root_Stream_Type'Class)
+ return Lim_Tagged'Class;
+ -- Never legal (T'Class is never constrained).
+ for Lim_Tagged'Class'Input use My_Class_Input;
+ procedure Do_Something (Object : Lim_Tagged'Class);
+ task type Tsk is ...
+ function My_Tsk_Input (Stream : access Root_Stream_Type'Class)
+ return Tsk;
+ -- Legal.
+ for Tsk'Input use My_Tsk_Input;
+ type Tsk_Array is array (Positive range <>) of Tsk;
+ -- Tsk_Array'Input is available by the Corrigendum and AI-195.
+ procedure Do_Something_Else (Object : Tsk_Array);
+ private
+ ...
+ end Ugh;
+
+ with Ugh;
+ package Factory is
+ function Constructor (...) return Ugh.Lim_Tagged'Class;
+ -- A "factory" constructor.
+ -- Never legal (T'Class is never constrained)
+ end Factory;
+
+ with Ugh;
+ procedure Test is
+ Obj : Ugh.Lim_Tagged'Class := Ugh.Lim_Tagged'Class'Input (A_Stream);
+ -- This is clearly legal if we don't try to redefine the
+ -- attribute. But it is returning a clearly unconstrained (new)
+ -- object, and it will require build-in-place semantics.
+ TObj : Ugh.Tsk_Array := Ugh.Tsk_Array'Input (A_Stream);
+ -- This also is clearly legal.
+ begin
+ Ugh.Do_Something (Ugh.Lim_Tagged'Class'Input (A_Stream));
+ -- Legal now in Ada 95+Corr.
+ Ugh.Do_Something_Else (Ugh.Tsk_Array'Input (A_Stream));
+ -- Legal now in Ada 95+Corr if Tsk_Array'Input overridden.
+ end Test;
+
+The first problem to note is incompatibility. With this legality rule, we
+aren't allowed to declare a function to be used as a user defined 'Input for
+Tsk_Array and Lim_Tagged'Class. Ada 95 certainly allows that. Tucker has
+argued privately that it would be nearly impossible to write a useful
+user-defined routine in this case, because of the return-by-reference
+rules -- returning an existing object is never what you want.
+
+The second problem is the language defines stream attributes for all types -
+including unconstrained limited types. Moreover, we've made (limited)
+function calls legal in many circumstances with build-in-place semantics.
+So, these stream attributes are legal in calls like the above (and the
+Do_Something calls are perfectly useful in existing Ada 95+Corr code). That
+means that we still have to implement unconstrained function calls, just the
+user can't write them. That's obviously silly.
+
+We're also giving much less than meets the eye here. It's not allowed to
+write a class-wide constructor (of which T'Class'Input is just a single
+example). That's a significant loss. The workaround of using an anonymous
+(or named) access type puts the burden of storage management on the user -
+reducing a key advantage of Ada. And it means that it won't be possible to
+convert non-limited tagged types which were non-limited only to get
+functions and constructors to limited tagged types.
+
+---
+
+Anyway, the second problem has to be solved somehow. It's of no help to
+implementers to limit users from writing unconstrained functions if the
+system still has to do it. There are three basic solutions.
+
+The more ugly rules solution: We could make T'Input "unavailable" if T is
+limited and unconstrained. This is messy, though, because we wouldn't want
+to prevent the use of T'Input for (untagged) types that aren't really
+limited (and thus allow the declaration of functions); that would be a
+bigger compatibility problem. Unfortunately, figuring out whether types are
+"really" limited breaks privateness, and Mr. Private is sure to object to a
+legality rule depending on privateness.
+
+And, of course, this rule would completely undo all of the work which makes
+streaming for limited tagged types useful, leaving such types as
+second-class citizens.
+
+An alternative is the
+New ugly rule solution: The real problem is that we need to prevent making
+*calls* to functions that we can't handle, not the functions themselves. So
+we could drop the above rule altogether (possibly leaving an implementation
+permission for an implementation to reject a function that cannot be
+called), and replace it by rule on calls:
+
+ If the result subtype of a function_call is limited at the point of the
+ call, the result subtype shall be constrained.
+
+This solves the problem cleanly, and also reduces the problems with generics
+(as now only internal calls would be made illegal; calls from outside the
+instance would determine from the actual type if they are legal.
+
+But again this covers too much. And trying to make it tighter again will
+break privateness and also be a contract problem in generics.
+
+The final alternative is the
+Too much work solution: drop these silly restrictions intended to make the
+implementation easier (and which by definition harm the user) and get to
+work. Tucker explained how to implement this long ago, and although it looks
+painful, it's only a short-term pain -- rather than inflicting this pain on
+users forever. It also is much less incompatible, as there are no problems
+with existing generics with limited private formal types.
+
+Still, this didn't fly in the past, and I don't expect it to fly now.
+
+---
+
+To me, this looks like a giant tease. We tease programmers by claiming that
+you can now do almost everything with limited types that you can do with
+non-limited types, but in return some of your generics are now going to be
+illegal (with no meaningful workaround), you can't use class-wide functions
+(meaning no factories of any kind), and even class-wide streaming isn't
+allowed. This, to steal one of Tucker's favorite phrases, is just moving the
+bump under the rug. This is a self-inflicted bump; if we were willing to do
+the additional work to move the furniture, this bump would be gone. (The
+analogy comes true in the carpet here in my office; since we didn't move all
+of my furniture in the last flood, the carpet repair guy left a large bump
+next to my desk...)
+
+There is also a safety issue here that we haven't really discussed. Objects
+returned by return-by-reference functions have a limited lifetime: it's not
+possible for the caller to hang onto them forever. That makes it possible to
+do storage management and resource locking (although the language doesn't
+support this well). However, anonymous access types can be converted to
+other types, and via 'Unchecked_Access, held onto forever. (Sure, the
+programmer is responsible that the 'Unchecked_Access value is destroyed
+before the object is. But if the programmer *knows* [by peeking at the
+source] that the actual objects are at library-level or in a heap, the use
+is OK vis-a-vis the language -- even though it may not be part of the
+"contract" of the function. And 'Unchecked_Access is so common that it isn't
+going to be a red flag to anyone - I don't know if I've ever found a useful
+case where I could use 'Access on an object -- I don't even try anymore.) So
+we've reduced the safety of the language a bit.
+
+Anyway, to draw an actual conclusion. :-)
+
+I don't believe that an AI that purports to give limited types equal footing
+with non-limited ones can deny a major benefit of OOP programming to limited
+types. Restrictions on class-wide programming are simply unacceptable in my
+view -- if limited tagged types are going to remain useless, we might as
+well not bother with lots of work and incompatibility.
+
+So I would vote for accepting the short-term pain and making this useful to
+all. However, if that is unacceptable to the majority, then (in the absence
+of a better idea) I would rather drop the AI completely rather than give
+users another (but different) crippled version of limited types.
****************************************************************
Questions? Ask the ACAA Technical Agent