Version 1.4 of ai05s/ai05-0054-2.txt

Unformatted version of ai05s/ai05-0054-2.txt version 1.4
Other versions for file ai05s/ai05-0054-2.txt

!standard 3.3(13)          07-11-29 AI05-0054-2/03
!standard 13.9.1(13)
!class binding interpretation 07-10-24
!status work item 07-10-24
!status received 07-10-24
!priority Low
!difficulty Hard
!qualifier Omission
!subject Variable views of constant objects
!summary
Remove erroneousness associated with using access-to-variable values designating constants, so long as they originate at a point where the language provides a variable view of the constant.
Revise the definition of constant objects and views to make it clear that there always is a possibility of a variable view existing.
!question
The current instance of a limited type can be used to obtain a variable aliased view of a (limited) constant object.
Are runtime checks needed in order to prevent the modification of a constant?
!recommendation
No, the practice of obtaining such a variable aliased view during initialization is an existing idiom, and should be allowed to continue even if the object is declared constant. (See the discussion section for more rationale.)
!wording
Modify 3.3(13) as follows:
An object is either a constant object or a variable object. [The value of a constant object cannot be changed between its initialization and its finalization, whereas the value of a variable object can be changed.] Similarly, a view of an object is either a constant or a variable. [All views of a constant object are constant.] {A name that statically denotes a constant object denotes a constant view. A name that statically denotes a variable object denotes a variable view.} A constant view of [a variable] {an} object cannot be used to modify [the value of the variable] {its value}. The terms constant and variable by themselves refer to constant and variable views of objects.
Modify 13.9.1(13) as follows:
The dereference of an access value is erroneous if it does not designate an object of an appropriate type or a subprogram with an appropriate profile, if it designates a nonexistent object, or if it is an access-to-variable value that designates a constant object{ and it did not originate from an attribute_ reference applied to a variable view of the object}. [Redundant: [Such an]{An} access value {whose dereference is erroneous} can exist, for example, because of Unchecked_Deallocation, Unchecked_Access, or Unchecked_Conversion.]
AARM NOTE: We permit the use of access-to-variable values that designate constant objects so long as they originate from a variable view, such as during the initialization of a limited or controlled constant, when there exists a variable view of the object.
!discussion
It is always possible for an object that is declared constant to internally contain an access-to-variable component that designates a separate heap resident object, meaning that operations on the constant object can still change the state of the "overall" object.
If we were to outlaw the idiom of squirreling away an access-to-variable value during the initialization of a constant (the so-called "Rosen" trick), then the programmer would be forced to allocate a separate object in the heap to hold data that needs to be updatable. This would not provide obvious benefit to anyone, since the code would be slower, take more space, and still have exactly the same external interface, namely that an operation can change the state of a "constant."
One could argue this would be confusing for non-private types, since potentially visible components of a constant might be updatable, but if the type is non-private, then the semantics of its initialization should certainly be considered open to inspection as well, and the squirreling away of the access-to-variable value should be available for all to see.
We use the phrase "originate from an attribute_reference applied to a variable view" to allow for possible type conversions after the initial '[Unchecked_]Access that created the access-to-variable value. Hopefully that is clear enough. The key thing is that you have to have a variable view at some point, or else somebody cheated.
!ACATS test
There should be C-Tests that an access-to-variable view of a constant object works properly.
!appendix

From: Tucker Taft
Sent: Wednesday, October 24, 2007  11:26 AM

I have attached variant 2 of AI-54 [this is version /01 of the AI - ED.],
the AI dealing with the erroneousness of using an access-to-variable
value designating a constant object.  This variant
proposes to eliminate the erroneousness, so long
as the value originated from an attribute_reference
applied to a variable view of the constant.
Such a variable view is provided during initialization
for limited and controlled objects.

The basic point is that this is an existing idiom,
and that disallowing it would just force programmers
to allocate a separate heap object to hold data
that needs to be updatable, which doesn't do anybody
any favors, since you still have the same external
interface, namely that an operation can apparently change
the "state" of a constant.

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

From: Randy Brukardt
Sent: Wednesday, October 24, 2007  8:26 PM

Thanks for doing this.

I'm concerned that your AI doesn't cover tasks. Obviously, tasks in constants is a
new concept, and it seems that we don't have an allowance for that.

    task type T is 
       entry Set (A : in Integer);
       entry Get (A : out Integer);
    end T;

    task body T is
       Val : Integer := 0;
    begin
       loop
          select
              accept Set (A : in Integer) do
                 Val := A;
              end Set;
          or
              accept Get (A : out Integer) do
                 A := Val;
              end Get;
          end select;
       end loop;
    end T;

    type Lim is limited record
        Tsk : T;
    end record;

    procedure Do_It (Obj : in Lim) is
    begin
        Obj.Tsk.Set (10);
    end Do_It;

    procedure Check_It (Obj : in Lim) is
        V : Integer;
    begin
        Obj.Tsk.Get (V);
        if V /= 10 then raise Program_Error; end if;
    end Check_It;

    declare
        Obj : constant Lim := (Tsk => <>);
    begin
        Do_It (Obj);
        Check_It (Obj);
    end;

The call to Do_It causes a modification to the local data of the task Obj.Tsk, which is
a part of a constant. This surely seems to violate 3.3(13/2) "The value of a constant
object cannot be changed." (one presumes that the local values of a task are part of
the value of an object containing that task).

There doesn't seem to be any penalty for this violation, so maybe it is safe to ignore it,
but it seems odd at best.

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

From: Tucker Taft
Sent: Wednesday, October 24, 2007  9:24 PM

> I'm concerned that your AI doesn't cover tasks. Obviously, tasks in
> constants is a new concept, and it seems that we don't have an allowance for
> that.

I'm pretty surprised you are worried about this.
It has been possible to call entries of task "IN"
parameters since Ada 83, so I presumed we never
considered the local variables of a task body
as part of the "value" of a task object.

> ...
> 
> The call to Do_It causes a modification to the local data of the task
> Obj.Tsk, which is a part of a constant. This surely seems to violate
> 3.3(13/2) "The value of a constant object cannot be changed."

Well that isn't quite what 3.3 says, it says you can't
change the value between its initialization and its
finalization.  In any case, I think this is clearly
violated by the "Rosen" trick applied to a constant.
I think this AI needs to fix this paragraph as well.
Perhaps as follows:

   An object is either a constant object or a variable
   object. [The value of a constant object cannot be changed
   between its initialization and its finalization, whereas
   the value of a variable object can be changed.] Similarly,
   a view of an object is either a constant or a variable.
   [All views of a constant object are constant.] {A name
   that statically denotes a constant object is a constant
   view.  A name that statically denotes a variable object
   is a variable view.}  A constant view of [a variable]
   {an} object cannot be used to modify [the value of the
   variable] {its value}. The terms constant and variable
   by themselves refer to constant and variable views of objects.

The net effect is that "constant object" isn't a very
interesting term.  It basically means that its name
denotes a constant view, but that there might be other
views that provide a variable view of the same object.

> ... (one presumes
> that the local values of a task are part of the value of an object
> containing that task).

I don't make that presumption, and haven't since Ada 83.
Perhaps a NOTE to that effect might be friendly.

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

From: Randy Brukardt
Sent: Wednesday, October 24, 2007  9:26 PM

> > I'm concerned that your AI doesn't cover tasks. Obviously, tasks in
> > constants is a new concept, and it seems that we don't have an allowance for
> > that.
> 
> I'm pretty surprised you are worried about this.
> It has been possible to call entries of task "IN"
> parameters since Ada 83, so I presumed we never
> considered the local variables of a task body
> as part of the "value" of a task object.

An "in" parameter is a constant view of a variable object. I'm thinking about
constant objects; recall that 3.3(13/2) says that all views of a constant object
are constant. There's no variable view existing anywhere, and that's what's
different. Maybe it's hair-splitting.

> > ...
> > 
> > The call to Do_It causes a modification to the local data of the task
> > Obj.Tsk, which is a part of a constant. This surely seems to violate
> > 3.3(13/2) "The value of a constant object cannot be changed."
> 
> Well that isn't quite what 3.3 says, it says you can't
> change the value between its initialization and its
> finalization.  In any case, I think this is clearly
> violated by the "Rosen" trick applied to a constant.
> I think this AI needs to fix this paragraph as well.
> Perhaps as follows:
> 
>    An object is either a constant object or a variable
>    object. [The value of a constant object cannot be changed
>    between its initialization and its finalization, whereas
>    the value of a variable object can be changed.] Similarly,
>    a view of an object is either a constant or a variable.
>    [All views of a constant object are constant.] {A name
>    that statically denotes a constant object is a constant
>    view.  A name that statically denotes a variable object
>    is a variable view.}  A constant view of [a variable]
>    {an} object cannot be used to modify [the value of the
>    variable] {its value}. The terms constant and variable
>    by themselves refer to constant and variable views of objects.
> 
> The net effect is that "constant object" isn't a very
> interesting term.  It basically means that its name
> denotes a constant view, but that there might be other
> views that provide a variable view of the same object.

That would satisfy my concern.

> > ... (one presumes
> > that the local values of a task are part of the value of an object
> > containing that task).
> 
> I don't make that presumption, and haven't since Ada 83.
> Perhaps a NOTE to that effect might be friendly.

Well, they certainly aren't part of the enclosing object in our implementation.
But I can't find anything in the language semantics that says that. Just
because we all think something is true does not make it true!

But I do prefer your rewording of 3.3(13/2), because it will help avoid
misconceptions.

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

From: Tucker Taft
Sent: Wednesday, October 24, 2007  11:08 PM

>> I'm pretty surprised you are worried about this.
>> It has been possible to call entries of task "IN"
>> parameters since Ada 83, so I presumed we never
>> considered the local variables of a task body
>> as part of the "value" of a task object.
> 
> An "in" parameter is a constant view of a variable object. I'm thinking
> about constant objects; recall that 3.3(13/2) says that all views of a
> constant object are constant. There's no variable view existing anywhere,
> and that's what's different. Maybe it's hair-splitting.

But the more fundamental part of 3.3 is the part that
says you can't use a constant view to modify an object.
But you *can* call an entry on a constant view of a task
object (even in Ada 83), so clearly calling an entry is
*not* considered "modifying" a task object.  Hence the
local variables of a task body must clearly not be
considered part of the "value" of a task object.  I don't
think we need any hand waving to prove that, based on
semantics that have existed since Ada 83.

>>> ...
>>>
>>> The call to Do_It causes a modification to the local data of the task
>>> Obj.Tsk, which is a part of a constant. This surely seems to violate
>>> 3.3(13/2) "The value of a constant object cannot be changed."
>> Well that isn't quite what 3.3 says, it says you can't
>> change the value between its initialization and its
>> finalization.  In any case, I think this is clearly
>> violated by the "Rosen" trick applied to a constant.
>> I think this AI needs to fix this paragraph as well.
>> Perhaps as follows:
>>
>>    An object is either a constant object or a variable
>>    object. [The value of a constant object cannot be changed
>>    between its initialization and its finalization, whereas
>>    the value of a variable object can be changed.] Similarly,
>>    a view of an object is either a constant or a variable.
>>    [All views of a constant object are constant.] {A name
>>    that statically denotes a constant object is a constant
>>    view.  A name that statically denotes a variable object
>>    is a variable view.}  A constant view of [a variable]
>>    {an} object cannot be used to modify [the value of the
>>    variable] {its value}. The terms constant and variable
>>    by themselves refer to constant and variable views of objects.
>>
>> The net effect is that "constant object" isn't a very
>> interesting term.  It basically means that its name
>> denotes a constant view, but that there might be other
>> views that provide a variable view of the same object.
> 
> That would satisfy my concern.

Glad to hear it.

> 
>>> ... (one presumes
>>> that the local values of a task are part of the value of an object
>>> containing that task).
>> I don't make that presumption, and haven't since Ada 83.
>> Perhaps a NOTE to that effect might be friendly.
> 
> Well, they certainly aren't part of the enclosing object in our
> implementation. But I can't find anything in the language semantics that
> says that. Just because we all think something is true does not make it
> true!

No, but see my rationale given above.

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

From: Jean-Pierre Rosen
Sent: Thursday, October 25, 2007  7:27 AM

> The call to Do_It causes a modification to the local data of the task
> Obj.Tsk, which is a part of a constant. This surely seems to violate
> 3.3(13/2) "The value of a constant object cannot be changed." (one presumes
> that the local values of a task are part of the value of an object
> containing that task).
> 
> There doesn't seem to be any penalty for this violation, so maybe it is safe
> to ignore it, but it seems odd at best.
 
Well, a constant can include a pointer to a variable, whose value can 
also be changed. Not exactly the same thing, but I think close enough 
that we don't have to care about it.

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

From: Erhard Ploedereder
Sent: Sunday, February  3, 2008  6:29 PM

My original intent to constrain legitimizing assignments to constants via
the Rosen trick to constants of private type fell prey to generic contract
issues, as the minutes already opined. (Or else I would have to impose so
much load on implementing the variable-views-to-constants that the proposal
would be flat on its face anyhow). Instead of revising AI-54 in ways that
have not been discussed at a meeting, I am submitting a comment on the AI,
since I have several issues with this AI-54/02.....

The modification of 3.3(14) with its new notion of "updating a variable" may
be technically opportune (and work), but it violates the "least surprise"
principle of language design. "If the value of a variable changes by any
operation, the variable has been updated" is something that 100% of computer
scientists will sign as a true statement. It would no longer hold in
Ada. Instead, the notion that "updating a variable" by assignment is
dependent on the view of the type of a component whose value is changed is
completely counter to the common interpretation of what updating a variable
means. (Besides, I still am uncertain about all the ramification that are
implied by "... the variable if its type is not a descendent of a partial
view of a full or actual type"; I claim that max. 50% of the ARG and 0,x% of
the Ada users understand the implications.)

----
Side remarks: 
1. assuredly, this needs to say "object" instead of "variable" (or else the
   intended effect for the modification of constants is not achieved);
2. "its type" binds ambiguously both to "part" and "variable".
-----

I fell into this trap, too, since for the longest time, I then assumed
that now assigning to said excepted parts would be allowed. But no, it 
isn't: Assigment semantics also requires a variable view. Consider

  procedure Foo(X: in T) is 
  begin
     null;
     X.M.Gen.Z := 8; -- Rosen trick; X.M.Gen is an acc-to-var view of X
     X.Z := 8; -- still illegal, since X is not a variable view
  end Foo;

and assume that Obj.M.Gen is always initialized such that it self-references
Obj for any Obj. Assume further that all object-declarations in the universe
carry a "constant" keyword.

I had a large example prepared to show how the latter assignment causes 
problems, but then I found out that it was illegal by this other rule in
5.2. So, let's get this straight as per the revised 3.3(14):

"The first assigment does not update X, although it changes the value of the
Z component of X, but it updates Z. The second assignment would change the
value of the Z component of X and thus update Z and X, but it is illegal to
do so."

Technically correct, but changing the same component by two different
syntaxes has two different semantics? That is very interesting.  How does
one teach that to anyone?

Did you believe the first quoted statement? It actually is wrong and again,
I fell into that trap. If X happens to be passed by value, then X.M.Gen.Z
still refers to the Z component of the actual, while X.Z refers to the Z
component of the formal copied from the actual. Only if X is passed by
reference are the Zs the same (which is the case for the Rosen trick with
limited or tagged types, but not necessarily any more if merely an
access-to-variable of a constant has been obtained and squirreled away
elsewhere, i.e., not in an access discriminant.  Note that the permission to
use access-to-variable views on constant objects (as per the modified
13.9.1(13)) is not restricted to limited or by-reference types. 
Built-in-place extended results as initializations of constants are a case 
in point. They need not be limited, yet any access value obtained in the
process would be legitimate.

On a secondary note, this AI, if approved, would make code optimization or
any program analyses incorrect that assume equal values of a constant entity
at all places after its declaration.  This is completely counter-intuitive
and may require major compiler, analyzer and backend reworks, let alone
rewiring of people's brains.

For every one of these three reasons, a different way to legitimize the
Rosen trick needs to be found if legitimizing is really desirable.
(Personally, I find the conceptual and real costs of legitimizing the
 idiom much too high in anything that I have seen so far.)

note bene: I am not opposed to making the constant/variable view notion
more explicit, as it is done with the 3.3(13) rewrite and with the add-on 
after 3.3(14). I am merely opposed to have constant views that somehow can
be perverted into lasting variable views (and dead set against perverting
notions like "updating a variable" to special needs).  

--- Another side remark ---
If the add-on after 3.3(14) is kept in the final AI, it also needs
to mention Pragma Volatile on constants as an exception.
---------------------------

Solutions ?:

One possibility is to "upgrade" the access-to-variable modification of
a constant to be a bounded error rather than erroneous: For subsequent
uses of the constant either the assigned value or the old value is
used.  While not a deterministic semantics, it gets rid of the
erroneousness.  It also reflects the "actual events" of today, i.e.,
the cacheing of constant values at compile- or runtime.

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

From: Randy Brukardt
Sent: Monday, February  4, 2008  11:06 PM

...
Instead of revising AI-54 in ways that
> have not been discussed at a meeting, I am submitting a comment on the AI,
> since I have several issues with this AI-54/02.....
> 
> The modification of 3.3(14) with its new notion of "updating a variable" may
> be technically opportune (and work), but it violates the "least surprise"
> principle of language design.

Huh? There is no modification to 3.3(14) in any latest version of AI05-0054-1
or AI05-0054-2. And I don't see any way that the proposed change to 3.3(13)
would have any effect. Ada has always had constant views of variable objects,
so nothing new there.

>"If the value of a variable changes by any operation, the variable has been
> updated" is something that 100% of computer scientists will sign as a true
> statement. It would no longer hold in Ada. Instead, the notion that
> "updating a variable" by assignment is dependent on the view of the type
> of a component whose value is changed is completely counter to the
> common interpretation of what updating a variable
> means. (Besides, I still am uncertain about all the ramification that are
> implied by "... the variable if its type is not a descendent of a partial
> view of a full or actual type"; I claim that max. 50% of the ARG and 0,x% of
> the Ada users understand the implications.)

This makes no sense. There is no wording like "... the variable if its type
is not a descendent of a partial view of a full or actual type" in any of the
AIs. What are you reading???

...
> note bene: I am not opposed to making the constant/variable view notion
> more explicit, as it is done with the 3.3(13) rewrite and with the add-on 
> after 3.3(14). I am merely opposed to have constant views that somehow can
> be perverted into lasting variable views (and dead set against perverting
> notions like "updating a variable" to special needs).  

There is no "add-on after 3.3(14)" in any version of the AI that I've seen.
Perhaps that is adding confusion where none is necessary...

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

From: Tucker Taft
Sent: Monday, February  4, 2008  11:40 PM

I'll admit I didn't follow all of what Erhard
wrote, but I agree that we should change the second
sentence of 3.3(14) as follows:

    ... The value of [a variable] {an object} is updated when
    an assignment is performed to any part of the [variable]
    {object}, or when an assignment is performed to an enclosing
    object.

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


Questions? Ask the ACAA Technical Agent