!standard E.2.2(9/1) 07-08-04 AI05-0060-1/00 !standard E.2.2(9.2/1) !class binding interpretation 07-08-04 !status work item 07-08-04 !status received 07-06-19 !priority Low !difficulty Hard !qualifier Omission !subject The definition of Remote access types is too limiting !summary ** TBD ** !question (1) E.2.2(9-9.2/1) define what a remote access type can designate. This does not include a class-wide interface. But an interface is very similar to an abstract tagged limited private type; neither can have visible components. A class-wide limited private type is allowed in a remote access type. Shouldn't a limited interface be allowed? (2) The definition of remote access types includes any anonymous access types that occur visibly in the remote types package. But such anonymous access types are necessarily part of another construct (access discriminants, access parameters, access components); they will not themselves be used remotely unless the containing construct is. But this rule makes significant restrictions on which anonymous access types can be used and how. For instance, an access-to-subprogram parameter is required by this rule to be passed only remote subprograms, even though the subprogram that is using the parameter is not itself a remote subprogram. Should this restriction be relaxed? (3) Should we formally say that Annex E pragmas have no effect on implementations that don't support Annex E? Doing so would allow us to declare additional packages to have Remote_Types pragmas, as we wouldn't have to worry about the effect on most implementations. !recommendation (See Summary.) !wording ** TBD ** !discussion The solution requires care, as a non-limited type can be derived from a limited interface type. That would violate the intent that a remote access type can only designate a limited object. Excluding anonymous access types also requires care: if one appears as a component of a remote type, the remote type ought to be required to have user-defined stream attributes (that is, any exclusion should not change the rules for external streaming). -- !corrigendum E.2.2(9/1) !ACATS Test !appendix From: Brad Moore Sent: Tuesday, June 19, 2007 2:29 AM I have come across a potential use for interface types that currently is not allowed in Ada 2005, yet seems like it would be a useful and natural extension to add to the language. At the very least, it seems worthy of discussion. It seems that this capability could be enabled by making only minor wording changes to Annex E to relax restrictions for remote access types. Specifically, it seems useful to be able to specify limited interfaces as remote access types. However E.2.2(9/1) states: (9/1) An access type declared in the visible part of a remote types or remote call interface library unit is called a remote access type. Such a type shall be (9.1/1) - an access-to-subprogram type, or (9.2/1) - a general access type that designates a class-wide limited private type or a class-wide private type extension all of whose ancestors are either private type extensions or limited private types. A limited interface cannot be used because of the restriction in (9.2/1) since an interface is not a private type, even though it would seem to be implicitly private since an interface type cannot have any visible record components. eg. The following code excerpt will compile if Client_Buffer_Type is declared as an abstract tagged limited private type. It does not compile if it declared as a limited interface type, due to the restriction stated in (9.2/1) above. package Buffer_Notifications is pragma Pure; -- type Client_Buffer_Type is abstract tagged limited private; type Client_Buffer_Type is limited interface; procedure Notify (Buffer_Client : access Client_Buffer_Type; Data : in String) is abstract; --private -- type Client_Buffer_Type is abstract tagged limited null record; end Buffer_Notifications; with Buffer_Notifications; use Buffer_Notifications; package Buffer_Server is pragma Remote_Call_Interface; type Buffer_Access is access all Client_Buffer_Type'Class; procedure Register (Buffer : Buffer_Access); procedure Send_To_Buffers(Data : String); No_More_IDs : exception; end Buffer_Server; It seems this could be allowed if E.2.2(9.2/1) were modified from; (9.2/1) - "a general access type that designates a class-wide limited private type or a class-wide private type extension all of whose ancestors are either private type extensions or limited private types." to state; (9.2/1) "a general access type that designates a class-wide limited interface type or a class-wide limited private type or a class-wide private type extension all of whose ancestors are private type extensions, interface types, or limited private types" Also E.2.2(14/2) would likely need to be modified from; "The primitive subprograms of the corresponding specific limited private type shall only have access parameters if they are controlling formal parameters; each non-controlling formal parameter shall support external streaming (see 13.13.2);" to something along the lines; "The primitive subprograms of the corresponding specific limited private type or limited interface type shall only have access parameters if they are controlling formal parameters; each non-controlling formal parameter shall support external streaming (see 13.13.2);" Hopefully the following questions could be considered in the discussion that might be generated; Would this be a change that would be relatively easy for vendors to implement? Is there a general feeling that this would be a useful capability? Are there reasons why limited interface types are restricted from being remote access types? Should an AI be created for this? **************************************************************** From: Tucker Taft Sent: Tuesday, June 19, 2007 1:32 PM I agree with your suggestion that we should probably allow access to class-wide limited interface as a remote access type. One niggling concern is that a non-limited type can be derived from a limited interface. I am feeling too slow-witted today to decide whether that is a real issue. **************************************************************** From: Brad Moore Sent: Wednesday, June 20, 2007 11:45 AM Thanks Tuck, for sharing your niggling concern. I share your concern, so I have revised my suggested wording changes, because it seems that the wording I originally suggested allows a private extention that is derived from a nonlimited interface. Also, just to clarify, the intent of my suggested revision to the wording is to not only allow class-wide limited interfaces as remote access types, but to also allow class-wide synchronized interfaces, class-wide protected interfaces, and class-wide task interfaces as remote access types. Since all of these are limited, I am hoping the wording is generic enough to include those others as well. Firstly, RM 7.3(6/2) defines the notion of a limited private extension, 7.3(6/2) "A private type is limited if its declaration includes the reserved word limited; a private extension is limited if its ancestor type is a limited type that is not an interface type, or if the reserved word limited or synchronized appears in its definition. If the partial view is nonlimited, then the full view shall be nonlimited. If a tagged partial view is limited, then the full view shall be limited. On the other hand, if an untagged partial view is limited, the full view may be limited or nonlimited." Also relevant is; 7.3 (8.1/2) "If the reserved word limited appears in a private_extension_declaration, the ancestor type shall be a limited type. If the reserved word synchronized appears in a private_extension_declaration, the ancestor type shall be a limited interface." It seems to help the wording if we speak of limited private extensions, rather than just private extensions, so I inserted "limited" before "private extension" in my revised suggested wording. Also, the RM defines "private extension", but does not define "private type extension", so I removed the word "type". There are many references to "private extension" throughout the RM, but "private type extension" only appears in this one paragraph. I presume that there might be value in making this minor editorial change regardless of whether any other wording changes are made to 9.2/1. New suggested wording for E.2.2 (9.2/1); E.2.2 (9.2/1) "a general access type that designates a class-wide limited interface type or a class-wide limited private type or a class-wide limited private extension." The phrase "all of whose ancestors are private type extensions, interface types, or limited private types" seems redundant to me. If the private extension is limited, all ancestor private type extensions and private types would also have to be limited. Is that correct? That is why I also removed that clause. The sentence is now simpler, but hopefully I haven't removed something that was needed. I would appreciate any feedback if anyone sees any problems or holes in the proposed wording. I realize I am probably getting ahead of myself with proposed wording changes, I am hoping only to suggest that any such wording changes needed for this change would likely be minimal. More important at this time, would be to get a sense for how others felt about the usefulness or need for being able to use class-wide limited interface types as remote access types. **************************************************************** From: Tucker Taft Sent: Wednesday, June 20, 2007 2:37 PM We cannot remove the part about: " ... all of whose ancestors are private [type] extensions, interface types, or limited private types" because we want to rule out the case where a private extension has a non-private record or record extension as an ancestor. I agree that removing "type" from "private type extension" would be more consistent. For what it's worth, my concern was that the *object* designated by the access-to-limited-interface'Class might be non-limited. I'm not sure that there is any problem with that, but it is something new. **************************************************************** From: Brad Moore Sent: Friday, June 22, 2007 1:54 AM > We cannot remove the part about: > > " ... all of whose ancestors are private [type] extensions, > interface types, or limited private types" > > because we want to rule out the case where a private extension > has a non-private record or record extension as an > ancestor. Of course you are right. I was focussing too much on the limitedness factor, at the expense of the privateness factor. Also, I now think it is better to move the word "limited" from where I originally suggested, before "private extension all of whose ancestors..." to before "interface types" in the clause that we cannot remove. ie., E.2.2 (9.2/1) "a general access type that designates a class-wide limited interface type or a class-wide limited private type or a class-wide private extension all of whose ancestors are private extensions, limited interface types, or limited private types." That seems to more neatly plug the hole in the wording I originally suggested that would allow a private extension derived from a non-limited interface to be used as a remote access type. > For what it's worth, my concern was that the *object* > designated by the access-to-limited-interface'Class > might be non-limited. I'm not sure that there is > any problem with that, but it is something new. That is something I hadn't thought of and didn't pick up from your original reply. I see that now. I also think I see why it's not easy to know offhand if there is an issue with this or not. It seems quite likely that there wouldn't be an issue, but requires some more deeper thought to think it through. On the surface this limitedness issue seems to be a similar issue to the corresponding privateness issue. That is, I believe it is possible to extend a private extension with a record extension, so that the *object* used in a remote access type could have visible components. I believe non-private object components would have been allowed in remote access type objects in Ada 95 also, and that part does not seem to have changed, so if it wasn't a problem in Ada95, it likely isn't a problem in Ada 2005 either. The new thing as a result of this suggested change would be that an object used as a class-wide remote access type could now be non-limited, in addition to possibly containing non-private components. The remote "view" of these objects would be that of a limited private type, but the local "view" could be not as restrictive. The ramification of this would mean that locally, the object could be copied, or assigned to. At this point, I don't see a problem with this, but cannot say for sure that there wouldn't be a problem with this either, or if there may be other issues that I may have overlooked. Hmmmmm. Any thoughts anyone might have on this are appreciated. **************************************************************** From: Robert A. Duff Sent: Saturday, June 30, 2007 9:27 AM There is no pragma Remote_Types in the containers packages (Ada.Containers.Vectors and friends). Is this an oversight? Is there some reason why these can't be Remote_Types? Note that Remote_Types was added after the fact to some Ada 95 packages, such as Ada.Finalization. **************************************************************** From: Pascal Leroy Sent: Wednesday, August 1, 2007 2:33 AM > There is no pragma Remote_Types in the containers packages > (Ada.Containers.Vectors and friends). Is this an oversight? > Is there some reason why these can't be Remote_Types? I see two difficulties with this. The first difficulty is the streaming of cursors. This is an issue that we discussed during the design of the containers, and we have rules (e.g., A.18.2(88/2)) to the effect that streaming a cursor raises P_E. The reason is that we could not figure out what sense it makes to stream a cursor: a cursor typically includes a pointer to a container, and surely we do not want to stream the associated container when we stream a cursor. The only alternative that I can think of would be for the cursor to record some form of network-wide identity of the associated container, but that seems awfully expensive. And I don't believe that we want to say that only some types in these library units are remote types. The second difficulty has to do with remote access types. Remember that access types declared in the visible part of a Remote_Types package are remote access types, and are subject to specific rules (see E.2.2). Now there are a number of anonymous access-to-subprogram types in the visible part of the containers, and if these types were remote access-to-subprogram types, you could only pass in remote subprograms. That seems like an unacceptable burden for the user: they would have to make all sorts of units RCI for no good reason, and to live with the associated restrictions. Not to mention that there would probably be a significant overhead in parameter passing and subprogram calls (unless the implementation is very smart and detects that the called subprogram is actually in the same partition). Overall, I'd say that it would create too much trouble for users and implementers. If someone really wants to transport containers, they'll do that explicitly by using the streaming attributes (unlike cursors, containers can be streamed, of course). **************************************************************** From: Robert A. Duff Sent: Wednesday, August 1, 2007 10:01 AM Hmm -- you're one day too late. ;-) I actually implemented it yesterday. It was not trivial -- I couldn't just add the Remote_Types pragma all over the place, because we had some internal implementation packages that needed to be turned into pragma-Pure, and that required stirring the code around quite a bit. I haven't checked it into CVS yet... ... > The first difficulty is the streaming of cursors. This is an issue that > we discussed during the design of the containers, and we have rules (e.g., > A.18.2(88/2)) to the effect that streaming a cursor raises P_E. The > reason is that we could not figure out what sense it makes to stream a > cursor: a cursor typically includes a pointer to a container, and surely > we do not want to stream the associated container when we stream a cursor. > The only alternative that I can think of would be for the cursor to record > some form of network-wide identity of the associated container, but that > seems awfully expensive. And I don't believe that we want to say that > only some types in these library units are remote types. I don't buy the first difficulty. Sure, you can't stream cursors, and you get a run-time error if you try. Shrug. The goal is to be able to send vectors and mappings and whatnot. > The second difficulty has to do with remote access types. Remember that > access types declared in the visible part of a Remote_Types package are > remote access types, and are subject to specific rules (see E.2.2). Now > there are a number of anonymous access-to-subprogram types in the visible > part of the containers, and if these types were remote > access-to-subprogram types, you could only pass in remote subprograms. > That seems like an unacceptable burden for the user: they would have to > make all sorts of units RCI for no good reason, and to live with the > associated restrictions. Not to mention that there would probably be a > significant overhead in parameter passing and subprogram calls (unless the > implementation is very smart and detects that the called subprogram is > actually in the same partition). The second, on the other hand, might be a real problem. Is it really the intent that anonymous access types are remote if they appear in a Remote_Types package? Are you saying that the following example would be illegal, if Vectors were Remote_Types, since Process is not a remote procedure? with Ada.Containers.Vectors; use Ada.Containers; procedure Example is package My_Vectors is new Vectors (Index_Type => Positive, Element_Type => Character); use My_Vectors; V : Vector := To_Vector (New_Item => 'A', Length => 10); procedure Process(Element : in out Character) is begin Element := 'x'; end Process; begin Update_Element (V, Index => 4, Process => Process'Access); end Example; In fact, GNAT does not complain about the above (using my private version that has pragma Remote_Types in all the Containers packages, except the ones that are Pure). **************************************************************** From: Tucker Taft Sent: Wednesday, August 1, 2007 11:37 AM Although it needs explicit clarification, I believe that access parameters and access discriminants should be permitted without restriction in Remote_Types packages. I believe "remote access types" are only the *named* access types declared in the visible part. Similarly, I believe our various additional sorts of anonymous access types should be permitted without restriction, except the existing restriction that all visible types that have streaming attributes must support external streaming. On the other hand, in RCI packages, access parameters have significant restrictions. It sounds like at a minimum we need an AI to clarify the rules for anonymous access types and Remote_Types packages. **************************************************************** From: Randy Brukardt Sent: Thursday, August 2, 2007 12:10 AM ... > > The first difficulty is the streaming of cursors. This is an issue that > > we discussed during the design of the containers, and we have rules (e.g., > > A.18.2(88/2)) to the effect that streaming a cursor raises P_E. The > > reason is that we could not figure out what sense it makes to stream a > > cursor: a cursor typically includes a pointer to a container, and surely > > we do not want to stream the associated container when we stream a cursor. > > I don't buy the first difficulty. Sure, you can't stream cursors, and you get > a run-time error if you try. Shrug. The type Cursor violates E.2.2(8/2) in that it doesn't support external streaming. I realize that the implementation of a containers package in Ada probably would fool the compiler into thinking it did (because there would be a user-defined stream attribute), but nothing in the definition of the description of the containers packages says or implies that these support external streaming. > The goal is to be able to send vectors and mappings and whatnot. You can stream those yourself, and you don't get into trouble with the construction of the packages if you do so. Ada doesn't allow you do define *just* those types as remote types (a much more useful definition than trying to make the entire package remoteable). **************************************************************** From: Randy Brukardt Sent: Thursday, August 2, 2007 12:19 AM > Although it needs explicit clarification, I believe > that access parameters and access discriminants should be > permitted without restriction in Remote_Types packages. > I believe "remote access types" are only the *named* access > types declared in the visible part. Similarly, I believe > our various additional sorts of anonymous access types > should be permitted without restriction, except the > existing restriction that all visible types that have > streaming attributes must support external streaming. "without restriction" is clearly wrong. You surely want the basic restrictions on remote types to apply to anonymous types used as components/discriminants (not sure about parameters). In particular, you do not want to allow: type Something (D : access Integer) is record A : Character; end record; in a Remote_Types package unless this type has user-defined stream attributes; it isn't externally streamable without that. And I doubt very much that we want to repeal that requirement just because there is an access discriminant. > On the other hand, in RCI packages, access parameters > have significant restrictions. > > It sounds like at a minimum we need an AI to clarify > the rules for anonymous access types and Remote_Types > packages. I admit that I can't quite figure out what the purpose of Remote_Types packages are supposed to be. The description seems to imply that having subprograms in the package doesn't make sense, but that doesn't seem to be the case in practice. So I can't tell what the rules for anonymous access parameters ought to be. (Other than that they shouldn't exist in the first place, but that's a discussion best had over several bottles of wine or beer. :-) **************************************************************** From: Robert Dewar Sent: Thursday, August 2, 2007 6:20 AM > You can stream those yourself, and you don't get into trouble with the > construction of the packages if you do so. Ada doesn't allow you do define > *just* those types as remote types (a much more useful definition than > trying to make the entire package remoteable). Streaming them yourself is MUCH less convenient! **************************************************************** From: Pascal Leroy Sent: Friday, August 3, 2007 1:59 AM > Hmm -- you're one day too late. ;-) I actually implemented > it yesterday. It was not trivial -- I couldn't just add the > Remote_Types pragma all over the place, because we had some > internal implementation packages that needed to be turned > into pragma-Pure, and that required stirring the code around > quite a bit. I haven't checked it into CVS yet... This is another reason why I am opposed to making these units Remote_Types. A Remote_Types unit can only depend on pure, shared passive or remote type units. This imposes all sorts of restrictions on the auxiliary units used to implement the containers, notably with respect to access types. For instance, our implementation uses an auxiliary unit to manage binary trees. This unit is, of course, full of access types. I didn't try to see what happens if I slap a categorization pragma on it, but on the surface things don't look good. In fact having to deal with pragma Preelaborate all over the place was already a significant pain. I don't see why we would make everybody's life complicated for an annex which, as far as I can tell, is only supported by one implementation. Maybe the solution is to say that the containers are Remote_Types iff the implementation supports annex E. That couldn't create portability issues: if you care about annex E, you better use GNAT anyway, so portability is moot. At any rate, we'll need to resolve the questions raised by Tuck regarding anonymous access types. **************************************************************** From: Robert Dewar Sent: Friday, August 3, 2007 4:12 PM > I don't see why we would make everybody's life complicated for an annex > which, as far as I can tell, is only supported by one implementation. > Maybe the solution is to say that the containers are Remote_Types iff the > implementation supports annex E. That couldn't create portability issues: > if you care about annex E, you better use GNAT anyway, so portability is > moot. why not do that for ALL instances of this pragma in the standard libraries? **************************************************************** From: Robert Dewar Sent: Friday, August 3, 2007 4:19 PM > This is another reason why I am opposed to making these units > Remote_Types. A Remote_Types unit can only depend on pure, shared passive > or remote type units. This imposes all sorts of restrictions on the > auxiliary units used to implement the containers, notably with respect to > access types. That's an artifact of your implementation, not a language issue (the language does not say the bodies have to be in Ada). What GNAT does to deal with MANY such problems in implementing the run time is to make categorization errors warnings when compiling run time library files, and then we suppress the warnings where needed (after verifying as is almost always the case, that the warning is a junk consequence of the RM rules that in fact does not intefere with the implementation). In your case you can completely ignore categorization errors from remote types in implementing your run time, since they are always junk if you have no Annex E. > For instance, our implementation uses an auxiliary unit to > manage binary trees. This unit is, of course, full of access types. I > didn't try to see what happens if I slap a categorization pragma on it, > but on the surface things don't look good. In fact having to deal with > pragma Preelaborate all over the place was already a significant pain. We just completely eliminated this pain by the approach above, I really cannot imagine trying to obey the silly Preelaborate categorization dependency rules in the implementation of the run time (silly because Preelaborate is a messed up gizmo which tries to be too many things to too many language features) > I don't see why we would make everybody's life complicated for an annex > which, as far as I can tell, is only supported by one implementation. Equally you don't want to make the containers difficult for users of this Annex with the implementation that *does* support this Annex. > Maybe the solution is to say that the containers are Remote_Types iff the > implementation supports annex E. That couldn't create portability issues: > if you care about annex E, you better use GNAT anyway, so portability is > moot. moot = arguable, undecided, which is not quite what you mean here. However the proposal certainly seems reasonable. It says that the Remote_Types pragmas in these units are only there if you support Annex E, so there is no portability issue anyway. Your proposal is entirely portable, so I don't understand the claim that it is moot. **************************************************************** From: Randy Brukardt Sent: Saturday, August 4, 2007 9:48 PM > > This is another reason why I am opposed to making these units > > Remote_Types. A Remote_Types unit can only depend on pure, shared passive > > or remote type units. This imposes all sorts of restrictions on the > > auxiliary units used to implement the containers, notably with respect to > > access types. > > That's an artifact of your implementation, not a language issue (the > language does not say the bodies have to be in Ada). What GNAT does > to deal with MANY such problems in implementing the run time is to > make categorization errors warnings when compiling run time library > files, and then we suppress the warnings where needed (after verifying > as is almost always the case, that the warning is a junk consequence > of the RM rules that in fact does not intefere with the implementation). I dislike this strategy [which, let me hasen to say, is perfectly legitimate]. I prefer to "eat my own dogfood" -- that is, use the compiler and language as they were designed. That's especially true for packages like the containers which are easy to write in pure Ada. If there is something in our compiler implementation that is causing pain, then it becomes a priority to fix that in someway (because it is likely to be causing pain to users as well). Similarly, if there is something in the language that is causing pain, then that should be a priority to get fixed. We enforce pure and preelaborate restrictions everywhere we can. Even our assembler makes a half-hearted attempt to enforce this restrictions (it doesn't allow library level objects in pure units, for instance). If it is necessary to end-run around the restrictions of Pure or Preelaborate to get anything done, then I have to wonder what the value of having it is. End users will have the same needs to avoid the restrictions, but they don't have the same ability to do so. [And any ability they do have is a bug in the language, not a feature.] Which suggests that either the restrictions need to be revisited (to some extent, we did that this time) or that the whole idea be dropped. Getting off of soapbox... **************************************************************** From: Robert Dewar Sent: Sunday, August 5, 2007 7:12 AM > I dislike this strategy [which, let me hasen to say, is perfectly > legitimate]. I prefer to "eat my own dogfood" -- that is, use the compiler > and language as they were designed. That's especially true for packages like > the containers which are easy to write in pure Ada. If there is something in > our compiler implementation that is causing pain, then it becomes a priority > to fix that in someway (because it is likely to be causing pain to users as > well). Similarly, if there is something in the language that is causing > pain, then that should be a priority to get fixed. Note that there is an important difference between implementing the predefined packages and applications programming. In the latter it is normal and frequent to try to make something preelaborate, and then find out there is a restriction (perhaps sensible, perhaps junk) that prevents it. You simply back off in that case (or perhaps when using GNAT, use pragma Restrictions (No_Elaboration_Code), which is probably what you wanted anyway). But in the case of the predefined libraries you can't back off in this way, so you have to kludge things. No big deal! > If it is necessary to end-run around the restrictions of Pure or > Preelaborate to get anything done, then I have to wonder what the value of > having it is. Indeed pragma Preleaborate is a seriously messed up feature in my opinion. It tries to do three things at a time, and does not get any of them quite right. **************************************************************** From: Robert Dewar Sent: Sunday, August 5, 2007 7:12 AM > I dislike this strategy [which, let me hasen to say, is perfectly > legitimate]. I prefer to "eat my own dogfood" -- that is, use the compiler > and language as they were designed. That's especially true for packages like > the containers which are easy to write in pure Ada. If there is something in > our compiler implementation that is causing pain, then it becomes a priority > to fix that in someway (because it is likely to be causing pain to users as > well). Similarly, if there is something in the language that is causing > pain, then that should be a priority to get fixed. Anyway, even if you think this, it is a VERY thin justification for removing a useful feature from the language ("sorry you can't do that, not because it is an ill-chosen feature, or not useful, but because implementing it would offend my aesthetic senses/prefernces"). **************************************************************** From: Robert A. Duff Sent: Sunday, August 5, 2007 7:45 AM > I dislike this strategy [which, let me hasen to say, is perfectly > legitimate]. I prefer to "eat my own dogfood" -- that is, use the compiler > and language as they were designed. That's especially true for packages like > the containers which are easy to write in pure Ada. In most cases, I agree. In fact, I was able to convert the containers to Remote_Types using pure Ada. I had to change an internal generic package to pragma-Pure, which required adding "for T'Storage_Size use 0;" on an access type, which required adding a new access type for allocation, and defining New_Blah and Free_Blah routines, which do new/U_D, and convert the access type back and forth, which required adding "all" to the original access type. That's what I meant by stirring the code around. It was already the case that the access type was in a unit with types (no operations), and the operations were in child units, and the children were with'ed only by bodies of the containers (so these didn't need to be Pure). On the other hand, if that's too painful, the approach outlined by Robert is perfectly reasonable. Yes, it suggests that there might be something wrong with Ada, but..., well..., nobody ever claimed Ada is perfect. >...If there is something in > our compiler implementation that is causing pain, then it becomes a priority > to fix that in someway (because it is likely to be causing pain to users as > well). Similarly, if there is something in the language that is causing > pain, then that should be a priority to get fixed. > > We enforce pure and preelaborate restrictions everywhere we can. Even our > assembler makes a half-hearted attempt to enforce this restrictions (it > doesn't allow library level objects in pure units, for instance). > > If it is necessary to end-run around the restrictions of Pure or > Preelaborate to get anything done, then I have to wonder what the value of > having it is. End users will have the same needs to avoid the restrictions, > but they don't have the same ability to do so. [And any ability they do have > is a bug in the language, not a feature.] Which suggests that either the > restrictions need to be revisited (to some extent, we did that this time) or > that the whole idea be dropped. I'd be in favor of dropping pragma Preelaborate (except for those pesky "compatibility" concerns...). > Getting off of soapbox... ;-) **************************************************************** From: Robert A. Duff Sent: Sunday, August 5, 2007 7:49 AM > Maybe the solution is to say that the containers are Remote_Types iff the > implementation supports annex E. That seems like a good compromise. In fact, I think any pragma Remote_Types appearing in the core language has to be interpreted to be not-really-there if the implementation doesn't claim to support annex E. That is, you can't write a test case that can tell whether pragma Remote_Types appears in the Containers packages, without using Annex E features, so if Annex E doesn't exist, the compiler can ignore any requirements for Remote_Types. **************************************************************** From: Pascal Leroy Sent: Monday, August 6, 2007 6:14 AM > That's an artifact of your implementation, not a language > issue (the language does not say the bodies have to be in > Ada). The containers were very carefully crafted so that their bodies could be written in Ada, and in fact there are several pure Ada implementations around. As far as I am concerned, any request to change the standard in a way that would make it impossible to write them in Ada is a no-no. One reason for this is that we wanted to leave open the possibility for 3rd parties (perhaps in the free software community) to develop additional containers (e.g., synchronized, bounded, etc.) and to be able to do so without going through insane compiler-dependent drudgery. Bob tells us that it *is* actually possible to write the containers in Ada with pragma Remote_Types. Fine. But it would be irresponsible to ignore the impact on existing implementations: if it is too high, implementers will just ignore the change. > (silly because Preelaborate is > a messed up gizmo which tries to be too many things to too > many language features) I couldn't agree more, but this is water under the bridge. **************************************************************** From: Pascal Leroy Sent: Monday, August 6, 2007 6:14 AM > On the other hand, if that's too painful, the approach > outlined by Robert is perfectly reasonable. Yes, it suggests > that there might be something wrong with Ada, but..., > well..., nobody ever claimed Ada is perfect. It suggest that folks who are not compiler writers cannot develop decent containers, which sounds very wrong to me. **************************************************************** From: Robert Dewar Sent: Monday, August 6, 2007 9:05 AM All we *might* be saying is that it might not be possible to do the exact specs in the RM, that's not the same as not being able to do decent containers. And after all from the point of view of the distribution folks, decent = remote types present! Seeing as the language does not allow people to replace the bodies of Containers UNLESS they are implementors: > 4 The implementation may restrict the replacement of language-defined > compilation units. The implementation may restrict children of > language-defined library units (other than Standard). So regardless of any discussion of pragmas, you may not be able to write your own bodies to replace the ones your vendor gives you. **************************************************************** From: Randy Brukardt Sent: Monday, August 6, 2007 7:17 PM > > ... Similarly, if there is something in the language that is causing > > pain, then that should be a priority to get fixed. > > Anyway, even if you think this, it is a VERY thin justification for > removing a useful feature from the language ("sorry you can't do that, > not because it is an ill-chosen feature, or not useful, but > because implementing it would offend my aesthetic senses/prefernces"). I'm not quite sure how you managed to leap from "priority to get fixed" to "removing a useful feature"; surely, one possible fix would be to remove the feature but clearly that is the last resort. It would make more sense to try to eliminate the source of pain, and that is what I meant by the above. For me, most of my packages could logically have a Preelaborate pragma, but they can't because (1) they depend on Text_IO or similar I/O packages; (2) they depend on Calendar or on of the other timing packages; or (3) they depend on a package that has (1) or (2). I might have more trouble with the restrictions on the code, but I've never been able to check because I never get that far. (There are possible workarounds to (2) and especially (1), but they have run-time costs that aren't always appropriate.) Obviously, the best fix would be to reduce the restrictions on Preelaborate and/or find a substitute for (1) and (2). Dropping the feature altogether wouldn't be what I would prefer to do; I'd love to be able to use it because it reduces the code needed at runtime. **************************************************************** From: Randy Brukardt Sent: Tuesday, August 7, 2007 3:51 AM ... > For me, most of my packages could logically have a Preelaborate pragma, but > they can't because (1) they depend on Text_IO or similar I/O packages; We deal with this by providing an I/O package with a useful subset of Text_IO capabilities that is Preelaborate. > Obviously, the best fix would be to reduce the restrictions on Preelaborate > and/or find a substitute for (1) and (2). Dropping the feature altogether > wouldn't be what I would prefer to do; I'd love to be able to use it because > it reduces the code needed at runtime. In GNAT, if what you are after is eliminating elaboration code, the preferable way to do it is pragma Restrictions (No_Elaboration_Code) for two reasons: 1. It is unit by unit 2. pragma Preelaborate does not ensure no elaboration code ****************************************************************