!standard 13.13.2 08-03-05 AC95-00158/01 !class Amendment 08-03-05 !status received no action 08-03-05 !status received 08-02-06 !subject !summary !appendix !topic Availability of stream attributes !reference RM 13.13.2 !from Adam Beneschan 08-02-06 !discussion I'm having some difficulty understanding the rules about availability of stream attributes. As I understand it: package Pak1 is type T1 is limited record F1 : Integer; end record; private procedure Read_Proc (...); for T1'Read use Read_Proc; end Pak1; It is illegal to call T1'Read except in places where the private part of Pak1 is visible (i.e. the body of Pak1, or the private part or body of a child of Pak1). Right? But if T1 is not limited: package Pak1 is type T1 is record F1 : Integer; end record; private procedure Read_Proc (...); for T1'Read use Read_Proc; end Pak1; T1'Read can be called from anywhere, and always results in a call to Read_Proc even in places where the private part of Pak1 isn't visible. Am I right so far? What happens here? package Pak2 is type T2 is limited record F2 : Integer; end record; procedure Read_T2 (...); for T2'Read use Read_T2; end Pak2; with Pak2; package Pak3 is type T3 is new Pak2.T2; private procedure Read_T3 (...); for T3'Read use Read_T3; end Pak3; with Pak3; procedure Proc4 is Obj : Pak3.T3; begin ... Pak3.T3'Read (Some_Stream'access, Obj); end; If I understand the rules correctly (good luck with that), the 'Read attribute is inherited for T3 in the visible part of Pak3, and then overridden in the private part; but when T3'Read is called in Proc4, since the private part of Pak3 is not visible, the result is that the inherited version of the attribute is called, which means that Read_T2 will be called. As I understand the discussion in AI-195, we don't want Read_T3 to be called for a limited type, in places where the private part of Pak3 isn't visible, because doing so would break privacy. But does any of this change if the word "limited" is removed from T2's declaration? Would T3'Read call Read_T2, or Read_T3? The reason this is a bit confusing is that in the case where a type is not limited and not derived, if I've understood the rules correctly in the first part of this post, an attribute specification in the private part still has an effect even when the private part is not visible. But if a type is *derived* and not limited, then I'm not clear on whether the attribute specification in the private part has a similar effect or not, if there is also an inherited attribute. I realize this is all pretty obscure and may not have an effect on any real-life programs, but as an implementor I do want to make sure I understand the impact of the rules correctly. Thanks for any help you can provide. **************************************************************** From: Gary Dismukes Date: Wednesday, February 6, 2008 6:03 PM > I'm having some difficulty understanding the rules about availability > of stream attributes. > > As I understand it: > > package Pak1 is > type T1 is limited record > F1 : Integer; > end record; > private > procedure Read_Proc (...); > for T1'Read use Read_Proc; > end Pak1; > > It is illegal to call T1'Read except in places where the private part > of Pak1 is visible (i.e. the body of Pak1, or the private part or body > of a child of Pak1). Right? Right. > But if T1 is not limited: > > package Pak1 is > type T1 is record > F1 : Integer; > end record; > private > procedure Read_Proc (...); > for T1'Read use Read_Proc; > end Pak1; > > T1'Read can be called from anywhere, and always results in a call to > Read_Proc even in places where the private part of Pak1 isn't > visible. Am I right so far? Also right. > > What happens here? > > package Pak2 is > type T2 is limited record > F2 : Integer; > end record; > procedure Read_T2 (...); > for T2'Read use Read_T2; > end Pak2; > > with Pak2; > package Pak3 is > type T3 is new Pak2.T2; > private > procedure Read_T3 (...); > for T3'Read use Read_T3; > end Pak3; > > with Pak3; > procedure Proc4 is > Obj : Pak3.T3; > begin > ... > Pak3.T3'Read (Some_Stream'access, Obj); > end; > > If I understand the rules correctly (good luck with that), the 'Read > attribute is inherited for T3 in the visible part of Pak3, and then > overridden in the private part; but when T3'Read is called in Proc4, > since the private part of Pak3 is not visible, the result is that the > inherited version of the attribute is called, which means that Read_T2 > will be called. As I understand the discussion in AI-195, we don't > want Read_T3 to be called for a limited type, in places where the > private part of Pak3 isn't visible, because doing so would break > privacy. The "overriding" Read_T3 should be called in that case AFAIK. I don't see where in AI-195 that specific case is discussed (but I might have missed it, it's a long AI). The behavior in such cases shouldn't depend on whether the type is limited or not. If there's an explicitly specified stream attribute, that's the one that should be used, assuming the attribute is available. > But does any of this change if the word "limited" is removed from T2's > declaration? Would T3'Read call Read_T2, or Read_T3? No, that shouldn't affect this case, the subprogram for the specified attribute one should be called in either case. I'm not sure that's clearly derivable from the rules however (what a surprise with stream attributes...), so clarification may be in order. I don't even see where the RM defines that a specified stream attribute gets called instead of the default or inherited version, though I may just be missing it. > The reason this is a bit confusing is that in the case where a type is > not limited and not derived, if I've understood the rules correctly in > the first part of this post, an attribute specification in the private > part still has an effect even when the private part is not visible. > But if a type is *derived* and not limited, then I'm not clear on > whether the attribute specification in the private part has a similar > effect or not, if there is also an inherited attribute. Regardless of what the rules say (or don't say), I don't think that's the desired behavior. That is, I believe that an inherited stream attribute should always be superseded by a specified one, whether or not the latter is in the visible or private part. I don't see that as privacy breaking, because the specified attribute subprogram is defining the implementation of the attribute, and it would be very confusing if the attribute behaved differently depending on where the attribute is referenced. > I realize this is all pretty obscure and may not have an effect on any > real-life programs, but as an implementor I do want to make sure I > understand the impact of the rules correctly. I agree it's important to understand these rules, and I don't even find this all that obscure to be asking about (but then I'm an implementor:-). **************************************************************** From: Robert A. Duff Date: Wednesday, February 6, 2008 6:26 PM >... As I understand the discussion in AI-195, we don't > want Read_T3 to be called for a limited type, in places where the > private part of Pak3 isn't visible, because doing so would break > privacy. Gary answered your questions, but I'll add one comment: "Privacy breaking" is a purely compile-time concept. We try to avoid cases where the compiler would have to peek into the private part in order to determine whether some client is legal. But run time is an entirely different story. For example, the compiler has to look at the private part to know whether it is allowed to pass parameters by reference or by copy. The question of which thing should be called is a run-time issue, and therefore cannot break privacy. **************************************************************** From: Adam Beneschan Date: Wednesday, February 6, 2008 7:01 PM ... > The "overriding" Read_T3 should be called in that case AFAIK. I don't > see where in AI-195 that specific case is discussed (but I might have > missed it, it's a long AI). The behavior in such cases shouldn't depend > on whether the type is limited or not. If there's an explicitly specified > stream attribute, that's the one that should be used, assuming the > attribute is available. > > Regardless of what the rules say (or don't say), I don't think that's > the desired behavior. That is, I believe that an inherited stream > attribute should always be superseded by a specified one, whether > or not the latter is in the visible or private part. I don't see > that as privacy breaking, because the specified attribute subprogram > is defining the implementation of the attribute, and it would be > very confusing if the attribute behaved differently depending on > where the attribute is referenced. OK, thanks for straightening me out. I may have been confusing this with subprograms are inherited. package Pak5 is type T5 is ...; procedure Proc (X : T5); end Pak5; package Pak6 is type T6 is new Pak5.T5; private procedure Proc (X : T6); end Pak6; When you call Proc on an object of type T6, you may get either the inherited one or the overriding one depending on what's visible at the point of the call. But I guess inherited stream attributes don't work the same way. That's fine---I just wasn't sure. Thanks, Gary and Bob, for your help. **************************************************************** From: Tucker Taft Date: Wednesday, February 6, 2008 7:49 PM Stream attributes are more like dispatching operations, in that visibility determines whether the operation is available at all, but you *always* invoke the overriding even if it is not visible. If the operation has formal parameter names and defaults, those always follow visibility rules, but you can't use named notation or defaults when calling an attribute subprogram anyway. The relevant piece of the RM that indicates that you always get the overriding is 13.3(18.1): If an operational aspect is specified for an entity (meaning that it is either directly specified or inherited), then that aspect of the entity is as specified. Sounds kind of redundant, but the key thing in this context is that it doesn't matter whether the operational item happens in the private part. The aspect is as specified. On the other hand, for limited types, whether the operation is "available" at all is based on visibility. ****************************************************************