From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,330ec86e1824a689 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2002-08-30 15:54:46 PST Newsgroups: comp.lang.ada Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!logbridge.uoregon.edu!uunet!sea.uu.net!ash.uu.net!world!news From: Robert A Duff Subject: Re: Run-Time Type Assignment Sender: news@world.std.com (Mr Usenet Himself) Message-ID: Date: Fri, 30 Aug 2002 22:54:08 GMT References: <5ee5b646.0208280304.614d11fc@posting.google.com> NNTP-Posting-Host: shell01.theworld.com Organization: The World Public Access UNIX, Brookline, MA X-Newsreader: Gnus v5.7/Emacs 20.7 Xref: archiver1.google.com comp.lang.ada:28612 Date: 2002-08-30T22:54:08+00:00 List-Id: "Ben Brosgol" writes: > Hmm, I try not to say too many silly things (unless I flag them with > smileys) so I guess I need to give some additional explanation for my > comment. OK, Ben, I apologize for the "silly" accusation. I shouldn't use such inflamatory rhetoric. But I stand by my claims: 'Unrestricted_Access is not safe, and not portable. > First, I was not claiming that 'Unrestricted_Access is a completely safe > construct. Obviously you can create dangling references. Which is why I said 'Unrestricted_Access is "unsafe". > But lots of programs have no need for the generality of stuffing a (pointer > to a) subprogram in a data structure, or assigning it to a variable; they > only need to pass subprograms as run-time parameters. For such programs it > will be perfectly safe to use 'Unrestricted_Access to pass a nested > subprogram as a parameter; there is no danger of dangling references, and > you still get the other checks that 'Access entails. (Phrased differently: > the context of the original discussion was whether anything that could be > done in Pascal could be done in Ada. So if you have a Pascal program that > passes a procedure or function as a parameter, and then convert the program > to Ada, there is no lack of safety in using Unrestricted_Access.) Well, that's not Ada, that's GNAT Ada, but still... >... I see > this as different from the array indexing case. It is hard, if all you want > to do is pass a subprogram as a parameter, to accidentally store it into a > data structure. True. However, it is perfectly reasonable to save procedure pointers into globals -- that's what the Ada 95 features of access-to-procedure and P'Access are for. So suppose we have a procedure: type Proc is access procedure; procedure Mumble(X: Proc); I'm not going to show you the body of Mumble, because that would be cheating. Now is it OK to pass Nested_Proc'Unrestricted_Access to Mumble? There's no way to tell. (Well, you can look at the comments, but you can't claim that as language support.) >... It is easy to make a programming error and accidentally > have an array index out of bounds. > > > >...(I.e., > > > Unrestricted_Access still entails the other checks required by the > language; > > > e.g. static subtype conformance for corresponding formals, matching > > > conventions.) For example: > > > Well, it's nice that it detects *some* errors (it detects misspellings > > like 'Unrestricted_Acess, too!), but it doesn't detect dangling > > pointers. > > It's not clear when to do the detection (see below). It's quite clear to me. We need a new kind of access-to-procedure type, a "limited" one that doesn't allow assignment. Then passing nested procedures to the limited type is OK, and assignment is illegal (that is, the detection happens when you try to assign (or return, etc)). At least, that's *one* safe design. There are others. > > > declare > > > procedure Q is begin null; end Q; > > > begin > > > Ref := Q'Unrestricted_Access; -- OK > > > > That's the problem (the above "OK"). If you call Ref.all later, you're > > in trouble. GNAT thinks it's OK, but it is *not* OK. > > Might or might not be OK; depends on your definition of "later". You're OK > if the call is only from the block that declares Q. (And you're probably > still OK even if the call is from an outer scope, if (as is the case here) Q > does not make any up-level references to stack variables.) By "later", I meant, "after that block is left". In most real examples, Q *does* make up-level refs -- that's why it is nested. Anyway, whether or not Q refers to globals, calling Q when it no longer exists should be considered an error -- and GNAT does not detect this error. > But the point is not that Unrestricted_Access can lead to dangling > references. I disagree -- the point (I was trying to make) is exactly that 'Unrestricted_Access is unsafe in that it can cause dangling pointers, which is not possible for the corresponding feature in Pascal. The key point to understanding this issue is to see that the Pascal feature is a different feature from Ada 95's access-to-procedure. 'Unrestricted_Access tries to combine them into one -- there lies the trouble. The Pascal feature is to allow procedures to be passed inward, but not assigned or returned. That's what I call "downward closures". The Ada 95 feature is to allow top level procedures to be passed around and returned and assigned into global variables -- and then called much later. That's what I call "callbacks". Both features are useful; they're not the same feature. Both can be supported safely. It's unfortunate, IMHO, that Ada 95 supports only one of them, and that GNAT supports the other unsafely. >...It's that you still get the checks as for 'Access except for > scope accessibility, and that you don't need that check if you are only > passing a subprogram as a parameter and not assigning it to a variable. If you pass it as a parameter, it could be assigned to a global variable. That's the problem. > -Ben - Bob