* Indirect visibility of private part in child packages @ 2009-06-04 5:45 Hibou57 (Yannick Duchêne) 2009-06-04 7:50 ` Ludovic Brenta 2009-06-04 16:06 ` Adam Beneschan 0 siblings, 2 replies; 7+ messages in thread From: Hibou57 (Yannick Duchêne) @ 2009-06-04 5:45 UTC (permalink / raw) Hi all, I've meet a tortuous question with a set of packages I'm converting from Pascal (as I use Ada now, I'm taking the opportunity to re-create a nicer design). The question I'm facing deals with visibility of private part in child package. More precisely, an indirect visibility of a private part. An exemple will better show the case: This can be reduced to three package (specs and bodies) The root package: >>>>> -------------------------------------------------- package P1 is type T1_Type is tagged private; -- Some primitives on T1_Type are specified here ... private type T1_Type is tagged record Low_Level_Data : Some_Type; end record; -- T1_Type end P1; <<<<< -------------------------------------------------- The first child package (with this one, every thing's Ok): >>>>> -------------------------------------------------- package P1.P2 is type T2_Type is new T1_Type with private; -- Some primitives on T2_Type are specified here ... procedure A_Primitive (Item : out T2_Type); private type T2_Type is new T1_Type with null record; end P1.P2; package body P1.P2 is procedure A_Primitive (Item : out T2_Type) is begin Item.Low_Level_Data := ...; -- It works, beceause P1.P2 is a child -- package with a view on P1's private part end A_Primitive; end P1.P2; <<<<< -------------------------------------------------- The second child package (the one which turns into a subtile doubt): >>>>> -------------------------------------------------- with P1.P2; package P1.P3 is type T3_Type is new P1.P2.T2_Type with private; -- Some primitives on T2_Type are specified here ... procedure A_Primitive (Item : out T3_Type); private type T3_Type is new P1.P2.T2_Type with null record; end P1.P3; package body P1.P3 is procedure A_Primitive (Item : out T3_Type) is begin Item.Low_Level_Data := ...; -- It fails : the compiler complains there is no -- selector "Low_Level_Data" defined for T3_Type end A_Primitive; end P1.P3; <<<<< -------------------------------------------------- As said in the last comment, it seems P1.P3 cannot see the T1_Type.Low_Level_Data member. But as P3 is a child package of P1, it has a view on P1's private part, and there is indeed no trouble about it with P2. P3 know P2.T2_Type is derived from P1.T1_Type, and P3 has a view on T1_Type privates. But it seems the compiler does not care about it. There may be interpretation matter here : does the private specification, means "disallow access to private part" or does it means "do not provide an access to the private part". If it means "disallow access to private part", then it ill explain why P3 cannot access T1_Type.Low_Level_Data member. But if it means "do no provide an access to private" part, then P3 should still be able to access T1.Low_Level_Data, beceause it has an access to this as a child package of P1. What does long experienced lawyers think about it ? I've try to look in section 8 of the "RM 2005", but either the answer was not there or else, I missed it. Note #1: I hope my exemple is clear enought. If it is not, please, tell me, so that I can attempt to reword it. Note #2: I do not want to make P3 a child package of P2, beceause it does not need to access any internals of T2_Type. I want to have some types, extending each others, and doing so only relying on either public interface or on the sole common private part defined in P1. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Indirect visibility of private part in child packages 2009-06-04 5:45 Indirect visibility of private part in child packages Hibou57 (Yannick Duchêne) @ 2009-06-04 7:50 ` Ludovic Brenta 2009-06-04 11:47 ` Hibou57 (Yannick Duchêne) 2009-06-04 16:06 ` Adam Beneschan 1 sibling, 1 reply; 7+ messages in thread From: Ludovic Brenta @ 2009-06-04 7:50 UTC (permalink / raw) Maybe you can solve your problem like this: package body P1.P3 is procedure A_Primitive (Item : out T3_Type) is begin T1_Type (Item).Low_Level_Data := ...; end A_Primitive; end P1.P3; I am undecided whether the compiler is correct or wrong about the visibility of Low_Level_Data. On the one hand, P1.P3 cannot see the full declaration of T2_Type; on the other hand, it can see that T2_Type publicly inherits from T1_Type and can also see the full declaration of T1_Type. It seems that the public (partial) view of T2_Type hides the full declaration of T1_Type. So, I think my solution would work by removing T2_Type out of the way. Another solution, which enforces encapsulation better, would be: package P1 is type T1_Type is tagged private; private type Some_Type is ...; type T1_Type is tagged record Low_Level_Data : Some_Type; end record; procedure Set (Item : out T1_Type; Data : in Some_Type); end P1; package body P1.P3 is procedure A_Primitive (Item : out T3_Type) is begin Set (Item, Data => ...); -- OK, calls inherited primitive operation end A_Primitive; end P1.P3; HTH -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Indirect visibility of private part in child packages 2009-06-04 7:50 ` Ludovic Brenta @ 2009-06-04 11:47 ` Hibou57 (Yannick Duchêne) 2009-06-04 13:22 ` Robert A Duff 0 siblings, 1 reply; 7+ messages in thread From: Hibou57 (Yannick Duchêne) @ 2009-06-04 11:47 UTC (permalink / raw) Bonjour Ludovic, and thanks for your reply :) On 4 juin, 09:50, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote: > Maybe you can solve your problem like this: > > package body P1.P3 is > procedure A_Primitive (Item : out T3_Type) is > begin > T1_Type (Item).Low_Level_Data := ...; > end A_Primitive; > end P1.P3; I've just tried it, and it does not work better. The compiler complains there are not selector Low_Level_Data for T1_Type. > I am undecided whether the compiler is correct or wrong about the > visibility of Low_Level_Data. On the one hand, P1.P3 cannot see the > full declaration of T2_Type; on the other hand, it can see that > T2_Type publicly inherits from T1_Type and can also see the full > declaration of T1_Type. This is exactly the same think in my mind. Perhaps the semantic is ambigous here. > It seems that the public (partial) view of T2_Type hides the full > declaration of T1_Type. So, I think my solution would work by removing > T2_Type out of the way. T2_Type is required ;) The purpose is to have T2_Type and T3_Type, and may be later some others, beside of each other. > Another solution, which enforces encapsulation better, would be: > > package P1 is > type T1_Type is tagged private; > private > type Some_Type is ...; > type T1_Type is tagged record > Low_Level_Data : Some_Type; > end record; > procedure Set (Item : out T1_Type; Data : in Some_Type); > end P1; > > package body P1.P3 is > procedure A_Primitive (Item : out T3_Type) is > begin > Set (Item, Data => ...); -- OK, calls inherited primitive > operation > end A_Primitive; > end P1.P3; > > HTH I will try it soon and tell about the result. But at first sight, I think that the compiler gonna complain that Set is a primitive of T1_Type and thus that it must be defined in the public part. Further more, I think Set would habe to be redefined for each T2_Type, T3_Type and etc. Will try and tell later Have a nice day ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Indirect visibility of private part in child packages 2009-06-04 11:47 ` Hibou57 (Yannick Duchêne) @ 2009-06-04 13:22 ` Robert A Duff 2009-06-04 14:04 ` Hibou57 (Yannick Duchêne) 0 siblings, 1 reply; 7+ messages in thread From: Robert A Duff @ 2009-06-04 13:22 UTC (permalink / raw) "Hibou57 (Yannick Duch�ne)" <yannick_duchene@yahoo.fr> writes: > On 4 juin, 09:50, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote: >> Maybe you can solve your problem like this: >> >> package body P1.P3 is >> � �procedure A_Primitive (Item : out T3_Type) is >> � �begin >> � � � T1_Type (Item).Low_Level_Data := ...; >> � �end A_Primitive; >> end P1.P3; > > I've just tried it, and it does not work better. The compiler > complains there are not selector Low_Level_Data for T1_Type. Are you sure? Converting to T1_Type should work. P3 can see that T1_Type has a Low_Level_Data component. The reason your original example didn't work is that the components of T2_Type are "nailed down" at the point where it's declared, and P3 can't see that. It can, however, see that it's derived from T1_Type, so converting should work. >> � �procedure Set (Item : out T1_Type; Data : in Some_Type); >> end P1; >> >> package body P1.P3 is >> � �procedure A_Primitive (Item : out T3_Type) is >> � �begin >> � � � Set (Item, Data => ...); -- OK, calls inherited primitive >> operation >> � �end A_Primitive; >> end P1.P3; >> >> HTH > > I will try it soon and tell about the result. But at first sight, I > think that the compiler gonna complain that Set is a primitive of > T1_Type and thus that it must be defined in the public part. Further > more, I think Set would habe to be redefined for each T2_Type, T3_Type > and etc. You could make Set class-wide. - Bob ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Indirect visibility of private part in child packages 2009-06-04 13:22 ` Robert A Duff @ 2009-06-04 14:04 ` Hibou57 (Yannick Duchêne) 0 siblings, 0 replies; 7+ messages in thread From: Hibou57 (Yannick Duchêne) @ 2009-06-04 14:04 UTC (permalink / raw) On 4 juin, 15:22, Robert A Duff <bobd...@shell01.TheWorld.com> wrote: > >> Maybe you can solve your problem like this: > > >> package body P1.P3 is > >> procedure A_Primitive (Item : out T3_Type) is > >> begin > >> T1_Type (Item).Low_Level_Data := ...; > >> end A_Primitive; > >> end P1.P3; > > > I've just tried it, and it does not work better. The compiler > > complains there are not selector Low_Level_Data for T1_Type. > > Are you sure? Converting to T1_Type should work. P3 can see that > T1_Type has a Low_Level_Data component. I sware, it is rejected. I agree this is strange. A GNAT bug ? If it is, perhaps this is the answer to the other question as well (the question about the visibility). ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Indirect visibility of private part in child packages 2009-06-04 5:45 Indirect visibility of private part in child packages Hibou57 (Yannick Duchêne) 2009-06-04 7:50 ` Ludovic Brenta @ 2009-06-04 16:06 ` Adam Beneschan 2009-06-04 16:33 ` Hibou57 (Yannick Duchêne) 1 sibling, 1 reply; 7+ messages in thread From: Adam Beneschan @ 2009-06-04 16:06 UTC (permalink / raw) On Jun 3, 10:45 pm, Hibou57 (Yannick Duchêne) <yannick_duch...@yahoo.fr> wrote: > Hi all, > > I've meet a tortuous question with a set of packages I'm converting > from Pascal (as I use Ada now, I'm taking the opportunity to re-create > a nicer design). > > The question I'm facing deals with visibility of private part in child > package. More precisely, an indirect visibility of a private part. An > exemple will better show the case: > > This can be reduced to three package (specs and bodies) > > The root package: > > >>>>> -------------------------------------------------- > > package P1 is > type T1_Type is tagged private; > -- Some primitives on T1_Type are specified here ... > private > type T1_Type is tagged record > Low_Level_Data : Some_Type; > end record; -- T1_Type > end P1; > <<<<< -------------------------------------------------- > > The first child package (with this one, every thing's Ok):>>>>> -------------------------------------------------- > > package P1.P2 is > type T2_Type is new T1_Type with private; > -- Some primitives on T2_Type are specified here ... > procedure A_Primitive (Item : out T2_Type); > private > type T2_Type is new T1_Type with null record; > end P1.P2; > > package body P1.P2 is > procedure A_Primitive (Item : out T2_Type) is > begin > Item.Low_Level_Data := ...; > -- It works, beceause P1.P2 is a child > -- package with a view on P1's private part > end A_Primitive; > end P1.P2; > <<<<< -------------------------------------------------- > > The second child package (the one which turns into a subtile doubt):>>>>> -------------------------------------------------- > > with P1.P2; > package P1.P3 is > type T3_Type is new P1.P2.T2_Type with private; > -- Some primitives on T2_Type are specified here ... > procedure A_Primitive (Item : out T3_Type); > private > type T3_Type is new P1.P2.T2_Type with null record; > end P1.P3; > > package body P1.P3 is > procedure A_Primitive (Item : out T3_Type) is > begin > Item.Low_Level_Data := ...; > -- It fails : the compiler complains there is no > -- selector "Low_Level_Data" defined for T3_Type > end A_Primitive; > end P1.P3; > <<<<< -------------------------------------------------- > > As said in the last comment, it seems P1.P3 cannot see the > T1_Type.Low_Level_Data member. But as P3 is a child package of P1, it > has a view on P1's private part, and there is indeed no trouble about > it with P2. P3 know P2.T2_Type is derived from P1.T1_Type, and P3 has > a view on T1_Type privates. But it seems the compiler does not care > about it. > > There may be interpretation matter here : does the private > specification, means "disallow access to private part" or does it > means "do not provide an access to the private part". If it means > "disallow access to private part", then it ill explain why P3 cannot > access T1_Type.Low_Level_Data member. But if it means "do no provide > an access to private" part, then P3 should still be able to access > T1.Low_Level_Data, beceause it has an access to this as a child > package of P1. > > What does long experienced lawyers think about it ? Here's why it doesn't work: The "operation" of providing a selector Low_Level_Data for T1_Type is made visible in the private part of P1. When T2_Type is declared as derived from T1_Type, the operation of providing the selector Low_Level_Data is inherited from T1_Type, but it only becomes visible where the original operation becomes visible. Since the original operation is visible in the private part of P1, the inherited operation becomes visible in the private part of P1.P2, which is the first place that the private part of P1 is visible. (It's not relevant that T2_Type is a private extension; I believe it would work the same if T2_Type were fully declared in the visible part.) When T3_Type is declared as derived as T2_Type, the operation of providing the selector Low_Level_Data is inherited from T2_Type, but it only becomes visible where the original operation (on T2_Type!!) becomes visible, which is... nowhere, because there isn't anywhere in P1.P3 that is able to access P1.P2's private part (and according to the above paragraph, that's where the operation on T2_Type is made visible---in P1.P2's private part). That's why Low_Level_Data isn't available for T3_Type. So the compiler is correct to reject your original program. However, I think Ludovic's fix (using a type conversion, actually a view conversion) should work, and it's a compiler bug if that is rejected. One could argue that this rule is anomalous, and that if a type is visibly derived from a grandparent (or great-grandparent, etc.) type in a situation like this, then operations that are indirectly inherited from the grandparent (etc.) type should be visible if they're visible for the grandparent, even if the inheritance comes indirectly through a non-visible part of some other package. There could be a privacy problem if the operation could be overridden in the non-visible part, but that isn't possible here---there's nothing P1.P2 can do to change the meaning of the Low_Level_Data selector. This issue is related to AI05-125, but although a couple of us think there's a flaw in the language, others believe that it can't be fixed without making things even more confusing. In any event, it's not all that important here since the view conversion is an adequate workaround, assuming your compiler isn't broken. > I've try to look in section 8 of the "RM 2005", but either the answer > was not there or else, I missed it. I think 7.3.1 and particularly 7.3.1(4) is the important rule here, although I have to admit that that section uses a lot of slightly fuzzy generalities that I've had problems interpreting occasionally. -- Adam ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Indirect visibility of private part in child packages 2009-06-04 16:06 ` Adam Beneschan @ 2009-06-04 16:33 ` Hibou57 (Yannick Duchêne) 0 siblings, 0 replies; 7+ messages in thread From: Hibou57 (Yannick Duchêne) @ 2009-06-04 16:33 UTC (permalink / raw) On 4 juin, 18:06, Adam Beneschan <a...@irvine.com> wrote: > So the compiler is correct to reject your original program. However, > I think Ludovic's fix (using a type conversion, actually a view > conversion) should work, and it's a compiler bug if that is rejected. I've done an error in my prior : T1_Type(Item).Low_Level_Data finally works fine. By the way, thanks for this clean explanation (and I gonna have a further look at 7.3x) ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-06-04 16:33 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-06-04 5:45 Indirect visibility of private part in child packages Hibou57 (Yannick Duchêne) 2009-06-04 7:50 ` Ludovic Brenta 2009-06-04 11:47 ` Hibou57 (Yannick Duchêne) 2009-06-04 13:22 ` Robert A Duff 2009-06-04 14:04 ` Hibou57 (Yannick Duchêne) 2009-06-04 16:06 ` Adam Beneschan 2009-06-04 16:33 ` Hibou57 (Yannick Duchêne)
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox