Version 1.1 of acs/ac-00050.txt

Unformatted version of acs/ac-00050.txt version 1.1
Other versions for file acs/ac-00050.txt

!standard 7.6(00)          02-09-25 AC95-00050/01
!class amendment 02-09-30
!status received no action 02-09-30
!subject Controlled types declared in nested scopes
!summary
!appendix

From: Steve Baird
Sent: Wednesday, September 25, 2002 1:23 PM

Controlled types, and their associated Initialize, Finalize, and
Adjust routines, cannot be declared within subprograms,
generic bodies, and other such contexts (3.9.1(3)).

The following proposal is an attempt to relax this restriction
in a completely compatible way.

The idea is to replace the "magic" package Ada.Finalization with
a "magic" generic and then have Ada.Finalization be just another
instance of this generic, with no different properties than
any user-defined instance would have. The generic could then
be instantiated in other contexts.

Tuck mentioned at the Vienna meeting that someone had suggested
this approach to him. I had thought of it too; probably many
people have.

Does this seem like a reasonable change?

--------



  Replace 7.6(3-8) with

                                Static Semantics

    The following language-defined library units exist:

        generic
        package Ada.Generic_Finalization is
            pragma Preelaborate (Generic_Finalization);
            pragma Remote_Types (Generic_Finalization);

            type Controlled is abstract tagged private;

            procedure Initialize (Object : in out Controlled);
            procedure Adjust (Object : in out Controlled);
            procedure Finalize (Object : in out Controlled);

            type Limited_Controlled is abstract tagged limited private;

            procedure Initialize (Object : in out Limited_Controlled);
            procedure Finalize (Object : in out Limited_Controlled);

        private
            ... -- not specified by the language
        end Ada.Generic_Finalization;

        with Ada.Generic_Finalization;
        pragma Elaborate (Ada.Generic_Finalization);
        package Ada.Finalization is new Ada.Generic_Finalization;
        pragma Preelaborate(Finalization);

  In 7.6(9), replace
    A controlled type is a descendant of Controlled or Limited_Controlled.
  with
    A controlled type is a descendant of either of the types Controlled or
    Limited_Controlled declared in an instance of Ada.Generic_Finalization.


--------

This would allow something like

    generic
        type T is private;
    package G is
         ...
    end G;

    with Ada.Generic_Finalization;
    package body G is
        package Root is new Ada.Generic_Finalization;

        package Pkg is
            type My_Controlled is new Root.Controlled with
                record
                    T_Component : T;
                end record;

             procedure Initialize (Object : in out My_Controlled);
             procedure Adjust (Object : in out My_Controlled);
             procedure Finalize (Object : in out My_Controlled);
        end Pkg;

        ...
    begin
        ...
    end;

.

Discussion Points:
    1) As long as we've "got the hood up", should the 3 procedures be
       declared as null procedures?
    2) Another name might be chosen instead of Generic_Finalization.
    3) Are the pragmas right on these units?

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

From: Robert A. Duff
Sent: Thursday, September 26, 2002 6:02 PM

>...
> The following proposal is an attempt to relax this restriction
> in a completely compatible way.

I think the proposal needs more explicit justification of why it's a
pain-in-the-neck as is.

>...
> Does this seem like a reasonable change?

Yes.  See below for minor comments.

>...
>     The following language-defined library units exist:
>
>         generic
>         package Ada.Generic_Finalization is

It would be useful to point out that the following text is exactly what
previously existed in Ada.Finalization.

> Discussion Points:
>     1) As long as we've "got the hood up", should the 3 procedures be
>        declared as null procedures?

Yes.  (If *that* AI passes.)

>     2) Another name might be chosen instead of Generic_Finalization.

Seems OK to me.

>     3) Are the pragmas right on these units?

The latest RM (with corrigendum) has pragma Remote_Types
on Ada.Finalization.  Is that inherited from the generic
(I don't remember the rules).

I don't see why "pragma Elaborate (Ada.Generic_Finalization);"
is needed on package Ada.Finalization.  They're both Preelaborate
anyway.  (And if it does need Elaborate, why isn't it Elaborate_All?)

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

From: Randy Brukardt
Sent: Thursday, September 26, 2002 8:14 PM

> Is there an AI associated with this proposal?

Not yet, we always wait until the discussion is complete before we decide
whether a proposal is worth an AI.

What I'm wondering is what is the justification for this? This doesn't seem
to happen in practice. Early in the development of Claw, we tried to derive
a controlled type in a library level package body, and three out of four
compilers tried crashed. I suppose compilers are better now, but I'd still
expect it to happen very rarely. In the example given, moving the
declaration to the private part makes the generic legal, which doesn't seem
to be a major difficultly.

I also would be very concerned about the impact on implementations which
were designed knowing that they did not have to worry about displays or
static links when handling finalization. For instance, when the task
supervisor in Janus/Ada does finalization, it doesn't necessarily have the
display of the task available. Similarly, it is necessary in Janus's shared
generic bodies to change displays when calling out. It's not clear to me
whether it would be necessary to change the display back when doing
finalization. We also do some finalization on-behalf-of called routines --
that would not be possible in this model. I don't have any examples of
problems to show (thinking about having to change finalization in generic
bodies makes my head hurt); I doubt I'd actually find the problems until I
went to implement this, which of course is too late.

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

From: Randy Brukardt
Sent: Friday, January 17, 2003

Private discussion on this proposal led me to write the following. I've
attached it here so as to help explain why this is a very bad idea:

---

> And I think that, in the interest of future generations, you should put a
> detailed explanation of why this doesn't work for shared generics (it's
> not obvious to me).

Because the calling convention of subprograms is different in a generic body
than elsewhere (there is a generic descriptor parameter). The only way to
handle this is to build a thunk at instantiation time. But you can't do this
without looking into the body -- and essentially you are no longer sharing if
you do.

The fact is that you can't create a tag in a generic body for any type that
might EVER be called outside of the generic. And finalizations are
generally implemented with a library subprogram, so they're outside the
generic. Similarly, any object that was passed outside of the generic (such as
on a access to class-wide list) could be finalized outside the generic. The
current accessibility rules have this result almost by accident, but it's a
critical property to any generic sharing that doesn't look into the body. (And
my opinion is that sharing that does look into the body isn't generic sharing
at all; it's simply an as-if optimization that could be done on any subprogram
in the program. And it sure as heck doesn't need any help from the language
rules.)

We could diffuse this by limiting the proposal to generic specs, but I think
that would be hard to explain (you can do this anywhere except in a generic
body??!!), and the other issues with it still would be around. For instance,
this proposal means that the task supervisor can no longer 'proxy'
finalizations, because the context would now matter (you'd have to have the
correct display or static links). I'd think that would make 'abort' and task
termination a lot messier to implement.

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


Questions? Ask the ACAA Technical Agent