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=unavailable autolearn_force=no version=3.4.4 Path: buffer2.nntp.dca1.giganews.com!border2.nntp.dca1.giganews.com!nntp.giganews.com!usenet.blueworldhosting.com!feeder01.blueworldhosting.com!reality.xs3.de!news.jacob-sparre.dk!loke.jacob-sparre.dk!pnx.dk!.POSTED!not-for-mail From: "Randy Brukardt" Newsgroups: comp.lang.ada Subject: Re: Ada design bug or GNAT bug? Date: Fri, 3 Jul 2015 12:33:07 -0500 Organization: Jacob Sparre Andersen Research & Innovation Message-ID: References: <4lrj5zz2u2z.u8x9cf7xzic6.dlg@40tude.net> <1oyc7ksu2lrwz.1h4pqchzcyfzt.dlg@40tude.net> NNTP-Posting-Host: rrsoftware.com X-Trace: loke.gir.dk 1435944788 13048 24.196.82.226 (3 Jul 2015 17:33:08 GMT) X-Complaints-To: news@jacob-sparre.dk NNTP-Posting-Date: Fri, 3 Jul 2015 17:33:08 +0000 (UTC) X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2900.5931 X-RFC2646: Format=Flowed; Original X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.6157 Xref: number.nntp.giganews.com comp.lang.ada:193889 Date: 2015-07-03T12:33:07-05:00 List-Id: "Dmitry A. Kazakov" wrote in message news:1oyc7ksu2lrwz.1h4pqchzcyfzt.dlg@40tude.net... > On Thu, 2 Jul 2015 17:22:08 -0500, Randy Brukardt wrote: > >> "Dmitry A. Kazakov" wrote in message >> news:ykiyl6yc44or$.19365hv76bzoi.dlg@40tude.net... >>> On Mon, 22 Jun 2015 12:39:16 -0500, Randy Brukardt wrote: >>> >>>> We don't have a choice about allowing hidden controlling results and >>>> controlling access results (unless, of course, we want to abandon real >>>> privacy, which we're not going to do). >>> >>> If function is invisible it is, and its result is as well. >> >> Not really, because you can still dispatch to it (if the dispatching is >> somewhere that the private function is visible); dispatching does not >> respect privacy (as privacy is only a compile-time, not runtime, >> concept). > > I don't see a scenario where you could dispatch on an invisible primitive > operation. First you must get into a context where you would have a view > of > your type having that operation. This context cannot exist without another > context where the type gets derived. In that context you must have > overridden the operation. Where is a problem? Is it related to MI? [But > Ada > does not respect privacy, when it checks inherited stuff, it does this as > if in a full view of the type, which is another language bug, but still no > problem.] This seeems confused, and you ask the right question later... >> I realize that you hate redispatching (a point that I tend to agree with >> you >> on), but it's possible, and it's needed some part of the time (maybe 10% >> or >> even less, but more than 0%), so it exists and has to be taken into >> account. > > But even if you convert to the class-wide you don't get visibility of the > operation. In the scenario: > > type T3 is new T1 with private; > private > type T3 is new T2 with null record; -- Legal! > > a public client could not convert a T3 object to T2'Class. Could it? No, but a private client can, and if you have a public type T4 derived from T3, it would not have the function operation. package P2 is type T3 is new T1 with private; procedure Do_It (X : inT3); private type T3 is new T2 with null record; -- Legal! end P2; with P2; package P3 is type T4 is new P2.T3 with C : Character; end record; -- No defined F here. end P3; with P2, P3; procedure Main is Obj : P3.T4; begin Obj.Do_It; -- Calls Do_It with a T4 operation, does not have F. end Main; package body P2 is procedure Do_It (X : in T3) is begin if T2'Class(X) = F then -- Dispatching call to F, tag is T4, but there is no F for T4. Ouch. ... end if; end Do_It; end P2; >>>> have the feature at all (which is where I would stand). >>> >>> I don't see connection to anonymous access types, the rule applies to >>> tagged results as well: >>> >>> package P1 is >>> type T1 is tagged null record; >>> type T2 is new T1 with null record; >>> function Foo return T2; >>> end P1; >>> >>> with P1; use P1; >>> package P2 is >>> type T3 is new T1 with private; >>> private >>> type T3 is new T2 with null record; -- Legal! >> >> This is only legal because of a hack, which I was very much against >> introducing. If you have an extension component, this is illegal: >> >> type T4 is new T2 with record C : Character := '1'; end record; -- >> Illegal!!! > > Yes, the hack you mean is contravariance of an out argument or result > based > on a guess about the type implementation (null extension). It is wrong > from > the strong typing POV. > >>> end P2; >> >> I have tried to find a way to avoid this maintenance hazard (it's >> especially >> bad for mix-in generics), but I haven't gotten any traction to date. We >> could (if all of the extension components have defaults) automatically do >> this as we do for null record, but the problem is that making overriding >> required often detects bugs (failure to create a proper overriding). Plus >> the problem of incompatibility (only in obscure cases). > > No. I know you don't believe in science and proofs but still, > conravariance > in outputs is just wrong (under type extension). > > Instead of ugly hacks we better have had some delegation/body-composition > methods at the declaration place to be able to tell that the overriding is > basically the parent's implementation. We already allowed such stuff, e.g. > > procedure Foo (...) is null; > > We have ugly executable precondition code at the declaration side. Why not > to allow this for functions? I don't understand what you mean. An expression function can be given as the overriding, but that doesn't help if you don't have the needed visibility to see the components in question (an aggregate is only legal if no private types are involved -- we tried to find a way to relax that for Ada 2005, but it just got way too messy). >>> with P1; use P1; >>> package P2 is >>> type T3 is new T1 with private; >>> private >>> type T3 is new T2 with null record; >>> overriding function Foo return T3; -- ILLEGAL! >>> end P2; >>> >>> As such the rule does not make any sense. You shall under no >>> circumstance >>> prohibit overriding of inherited operations. >> >> That's only possible if you prohibit any extensions of T3. (Otherwise, >> you >> get the dispatching problems that I noted previously, or you have to >> break >> privacy by making the derived type illegal for something that is not >> visible.) We've talked a bit about having such an aspect, but it is >> messy. > > Could you provide an example of dispatching problems you have in mind? Done, see above. >> To summarize: it's a bad interaction between privacy and things that >> require >> overriding (abstract subprograms follow the same rules for the same >> reasons). There's no real solution, else you could call abstract >> subprograms -- and then what?? > > Honestly I never understood how that could happen. The dispatching table > must be defined for any non-abstract instance. This is statically > enforced, > isn't it? Right -- that's why you get the rule requiring visible operations. Statically enforcing it otherwise would require breaking privacy, which we won't do (outside of representation clauses, for which privacy doesn't make any sense anyway). Randy.