Version 1.2 of acs/ac-00153.txt

Unformatted version of acs/ac-00153.txt version 1.2
Other versions for file acs/ac-00153.txt

!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 <something that is not
quite a yadayada>". 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.

****************************************************************

From: Adam Beneschan
Sent: Friday, December 7, 2007  11:45 AM

> 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.

I'd like to make a couple points in this regard:

(1) The original sentence that caused me confusion (3.10.2(12.4)) was
    in a "Static Semantics" section, not a "Legality Rules".  Perhaps
    what you're saying applies to both.

(2) With regards to this suggestion:

    "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"."

    I think I could live with something like this anywhere in the RM
    *except* 3.10.2 (maybe there's a few other places).  One reason is
    simply that 3.10.2 is so difficult (for me) to understand that
    when I read it, I try read it very carefully to make sure I'm
    getting it right; and I tend to go more into my "take everything
    literally" mode, or perhaps you could call it "fine-toothed comb"
    mode, to make sure I understand what's going on.  Simply because
    of that, from my point of view this is probably the wrong section
    of the RM to rely on things being "clear from context".  Another
    particular issue with 3.10.2 is that 3.10.2(5), which introduces
    the section I had the problem with, says:

    "Each master, and each entity and view created by it, has an
    accessibility level:"

    Since an object is an entity, this would seem to say that
    *objects* per se have their own accessibility levels, and the view
    of an object would have its own accessibility level---and the two
    don't necessarily match.  This introductory sentence suggests, by
    itself, that in this section, it should never be assumed that
    "object" means "view of an object".

So even if it's decided that it's too much work to make all the
wording precise everywhere in the RM, I'd like to suggest that 3.10.2,
or at least paragraphs 5-22, do need to be precise, and not rely on
anything being "clear from context".

****************************************************************

From: Randy Brukardt
Sent: Friday, December 7, 2007  11:01 PM

> (1) The original sentence that caused me confusion (3.10.2(12.4)) was
>     in a "Static Semantics" section, not a "Legality Rules".  Perhaps
>     what you're saying applies to both.

The AARM note that I proposed said exactly that.

> (2) With regards to this suggestion:
>
>     "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"."
>
>     I think I could live with something like this anywhere in the RM
>     *except* 3.10.2 (maybe there's a few other places).
...
> So even if it's decided that it's too much work to make all the
> wording precise everywhere in the RM, I'd like to suggest that 3.10.2,
> or at least paragraphs 5-22, do need to be precise, and not rely on
> anything being "clear from context".

I personally think that it is *hardly ever* clear from context, and that any
wording that confuses anyone reasonably knowledgeable with the Standard should
be made explicit. (That certainly was true of 3.9.3(4/2), since neither Pascal
nor I realized it was "obvious" that that rule applied to views of types rather
than just types. You get nonsense results otherwise, but it takes a while to
figure that out, and surely that shouldn't be a criteria for determining
wording. But the full ARG felt otherwise.)

But I've tilted at that particular windmill a number of times, and I don't
think it makes sense to waste any more of my time (or the ARA's money)
continuing to do so. Unless you can convince other ARG members (who come to
meetings!!) of the need for a wording change, there is no point in progressing
your request.

What bothers me is that the Standard has no indication that you might need to
stick "view of" in front of various entities in rules. I don't know how you are
supposed to read that into the current wording of the Standard, whether or not
it is "clear from context" (which is a point that always can be argued).
Depending on the "font of Ada intent" (that is Tucker) is not a good plan for a
Standard!!

Unless this is corrected, most wording that doesn't have "view of" is wrong.
And thus needs to be fixed.

****************************************************************

Questions? Ask the ACAA Technical Agent