!standard 3.10.2(12.4/2) 07-12-06 AC95-00153/01 !standard 3.10.2(5) !standard 3.10.2(7) !standard 3.10.2(15) !standard 3.10.2(16) !class confirmation 07-12-06 !status received no action 07-12-06 !status received 07-11-27 !subject Access discriminants and accessibility levels !summary !appendix !topic Access discriminants and accessibility levels !reference RM 3.10.2 !from Adam Beneschan 07-11-27 !discussion I'm having difficulty understanding how 3.10.2 works (what a surprise) in what seems like a fairly simple case. This case doesn't even seem to involve any Ada 2005 changes. I must be misunderstanding something, but I don't know what. In this example: ------------------------------------------------------------------------------- package Pak1 is type Int_Acc is access all Integer; IA : Int_Acc; type R1 is record F : aliased Integer; end record; type R2 (D : access R1) is limited null record; end Pak1; with Pak1; package Pak2 is procedure Proc (Param : in out Pak1.R2); end Pak2; package body Pak2 is procedure Proc (Param : in out Pak1.R2) is begin Pak1.IA := Param.D.F'Access; -- HERE end Proc; end Pak2; with Pak1; package Pak3 is Global_R1 : aliased Pak1.R1; Global_R2 : Pak1.R2 (Global_R1'access); procedure Test; end Pak3; with Ada.Text_IO; with Pak2; package body Pak3 is procedure Test is Local_R2 : Pak1.R2 (Global_R1'access); begin begin Pak2.Proc (Global_R2); Ada.Text_IO.Put_Line ("Proc succeeded using Global_R2"); exception when Program_Error => Ada.Text_IO.Put_Line ("Program_Error raised using Global_R2"); end; begin Pak2.Proc (Local_R2); Ada.Text_IO.Put_Line ("Proc succeeded using Local_R2"); exception when Program_Error => Ada.Text_IO.Put_Line ("Program_Error raised using Local_R2"); end; end Test; end Pak3; with Pak3; procedure Test684 is begin Pak3.Test; end Test684; ------------------------------------------------------------------------------- On the line marked "HERE", what the RM seems to be saying is: The accessibility level of F should be the same as the accessibility level of the type of Param.D, based on 3.10.2(15) and 3.10.2(16). The type of Param.D is an anonymous access-discriminant type. 3.10.2(12.4) says "The accessibility level of the anonymous access type of an access discriminant in any other context is that of the enclosing object". This should apply since the stuff in paragraphs 12 through 12.3 doesn't apply. So what's the "enclosing object"? (This term isn't defined anywhere that I can find.) It seems like it should be the actual parameter that is passed to Proc, based on 6.2(2); since the type is a by-reference type, 6.2(2) says that "Param" denotes a view of the object denoted by the actual parameter. 3.10.2(5) starts off by saying that "Each master, and each entity and view created by it, has an accessibility level". This would imply that both objects (which are entities) and views have their own accessibility levels. Param denotes a *view*, and the accessibility level of that view is the same as that of Proc, by 3.10.2(7); however, that doesn't seem relevant, since 3.10.2(12.4) talks about an enclosing *object*, not an enclosing *view* (whatever that would be). In any case, it's hard for me to think of Param as being its own object separate from the actual parameter; intuitively, at least to me, the actual parameter is the object that encloses the access discriminant (because that's the record in which the discriminant lives). So I'd therefore think that Param.D (and therefore Param.D.F) would have the accessibility level of the parameter, and that Program_Error would not be raised when Proc is called with Global_R2 as a parameter, but *would* be raised when Proc is called with Local_R2 as a parameter. GNAT, however, won't even compile the above source---it gives an error on the line "HERE". So what am I missing? Or this an error or poor wording in the RM? **************************************************************** From: Tucker Taft Sent: Tuesday, November 27, 2007 10:18 PM 3.10.2(7/2) says a parameter of a master has the same accessibility level as the master. Hence, the accessibility level of Param at HERE is that of the enclosing procedure body Proc, which is definitely not library level. So it fails the static accessibility level check. **************************************************************** From: Adam Beneschan Sent: Wednesday, November 28, 2007 9:44 AM But that begs the question. The accessibility level of Param is that of Proc; I understand that. But it also appears to me that Param is a "view" of an object, and not really an "object" in and of itself; and the RM says the accessibility level of the type of Param.D is the accessibility level of the enclosing "object" (since it is the type of an enclosing access discriminant). [And, since D is implicitly dereferenced, it's the accessibility level of D's type that is important, not the accessibility level of D itself.] So why is the accessibility level of Param the important information here, rather than the accessibility level of the actual parameter? That is, what, exactly, in the RM makes the accessibility level of Param important in this construct? **************************************************************** From: Tucker Taft Sent: Wednesday, November 28, 2007 10:06 AM Static accessibility levels are associated with views, since by definition they are the things that the compiler knows about at compile time. Run-time accessibility levels can "see through" the view to the underlying object in some cases, but not many. An access parameter is one case where it "sees through," as well as the level of the tag of a class-wide object. Access parameters are the only kind of parameter that carries along its own run-time accessibility level, so the run-time accessibility of the actual parameter is irrelevant when the formal is not an access parameter. **************************************************************** From: Adam Beneschan Sent: Wednesday, November 28, 2007 3:00 PM I think you can get around the static accessibility level issue by replacing the body of Proc in my example: procedure Proc (Param : in out Pak1.R2) is begin Pak1.IA := Param.D.F'Access; -- HERE end Proc; with this: procedure Set_IA (To : access Integer) is begin Pak1.IA := Pak1.Int_Acc (To); -- HERE2 end Set_IA; procedure Proc (Param : in out Pak1.R2) is begin Set_IA (Param.D.F'Access); end Proc; This won't be rejected by the compiler. But will the line marked HERE2 raise Program_Error when Proc is called with Global_R2 as its parameter? It does when I compile with GNAT and run it. But I still don't see how to obtain a "yes" answer from the RM; we still have the same problem, that the (run-time) accessibility level of the type of Param.D is, according to the RM, the same as the accessibility level of the "enclosing object"; and I can't see how the RM wording makes this the accessibility level of the *view* of the object denoted by Param. I also don't see how your response about static accessibility levels helps even in the original case. The way I understand the RM, there is no "static accessibility level", but an accessibility level can be "statically deeper" than another even if it wouldn't be deeper according to the non-static rules for accessibility levels. 3.10.2(16.1-21) list the cases where an accessibility level is defined to be statically deeper than another. So how would that apply here? procedure Proc (Param : in out Pak1.R2) is begin Pak1.IA := Param.D.F'Access; -- HERE end Proc; 3.10.2(18) says that Proc's level is statically deeper than library level, I think. (I won't question it.) 3.10.2(7) says that the level of a parameter has the same level as that of the master; therefore Param's level is statically deeper than library level. But the next requirement is to figure out whether Param.D's type is statically deeper than anything---and nothing in 3.10.2(16.1-21) helps us out here. We're still stuck with trying to figure out what "enclosing object" means. Despite your explanation, there's nothing in that part of the RM that says that you use a view as opposed to an actual object when figuring out whether one level is "statically deeper" than another. So my conclusion here is that I think I now understand how the accessibility levels apply in this case (of an access discriminant that is part of a subprogram parameter), but *only* because I asked (and because I trust that you're right, because nobody has contradicted you yet). I do not believe the correct answer can be obtained from the RM (or even the AARM). I have to conclude that 3.10.2(12.4) is probably in error, and that there needs to be some additional language that the accessibility level of the anonymous type of an access discriminant has something to do with the level of the view of the prefix used to select the discriminant ("prefix" as in 4.1.3(2)). **************************************************************** From: Tucker Taft Sent: Wednesday, November 28, 2007 3:23 PM This will raise Program_Error. I'm not sure at this point whether you are trying to understand the intent, or to make sure the wording in the RM correctly expresses the intent. You can trust me on the intent. You might be right that the RM has problems in this area. In fact, there are already some number of 2005 AIs associated with 3.10.2, so it is almost certain that the RM has problems in this area. One important thing to recognize is that the phrase "view of" should be inserted in front of "object" and "type" almost everywhere you see them in the manual. The compiler only knows what it learns from declarations, and declarations always define views of entities, but only sometimes define the entities themselves. **************************************************************** From: Randy Brukardt Sent: Thursday, December 6, 2007 8:06 PM > One important thing to recognize is that the > phrase "view of" should be inserted in > front of "object" and "type" almost everywhere > you see them in the manual. The compiler > only knows what it learns from declarations, > and declarations always define views of entities, > but only sometimes define the entities themselves. To expand on this a bit: It is clear from the discussion (and rejection!) of AI05-0068-1/01 at Fairfax that in Legality Rules, "object" and "type" always really mean "view of object" and "view of type". Anything else would break privacy and cause all manner of bad effects. What I don't understand is why there is such resistance to saying that in the Standard. AI-68 was trying to add "view of" into wording that clearly depends on that, and the decision was that it is "obvious". But there are a number of cases in the Standard (for instance, 10.1.1(9)) where we say "when it clear from context, we also use the term *yadayada* to mean ". It seems to me that if we're not willing to change the wording to include "view of", then we need a statement somewhere (3.1(7)?) like: "When it is clear from context, the term *object* is used in place of *view of an object*. Similarly, the term *type" is used in place of "view of a type"." or maybe "When it is clear from context, the Standard may simply refer to an entity (such as an object, type, or subprogram) to rather than a view of the entity." With an AARM note of something like: "Rules interpreted at compile-time always refer to views of entities, rather than the entities themselves. This is necessary to preserve privacy; characteristics that are not visible should not be used in compile-time rules. Thus, Static Semantics and Legality Rules always implicitly have "view of". On the other hand, run-time rules can work either way, so "view of" should not be assumed in Dynamic Semantics rules." Then when we just questions like Adam's, we can simply point the questioner at the appropriate paragraph and have them go away. Personally, I would rather use the precise wording everywhere (and we usually do in new wording), but I realize it is probably too late to go back and fix the entire RM for this problem. But what I don't like is telling questioners over and over that "of course that means *view of*" when there is no indication anywhere in the Standard (at least that I can find) that that is the case. This is way too important to understanding the Standard to not say it normatively somewhere. ****************************************************************