Version 1.6 of ais/ai-00295.txt

Unformatted version of ais/ai-00295.txt version 1.6
Other versions for file ais/ai-00295.txt

!standard 3.07.01 (7/1)          02-09-27 AI95-00295/02
!standard 3.06 (11)
!standard 3.06 (22/1)
!standard 3.08 (18/1)
!class binding interpretation 02-05-16
!status No Action (9-0-0) 04-06-14
!status work item 02-09-27
!status received 02-05-16
!qualifier Error
!priority Medium
!difficulty Hard
!subject Another violation of constrained access subtypes
!summary
[Editor's Note: The problem of this AI is now solved in a different way by AI-363.]
3.6(11) is enforced in the private part of instances. There is a check on component_definitions in instance bodies that 3.6(11) is not violated; if it is violated, Program_Error is raised.
!question
The following illustrates a case of access subtype constraint violation which is not caught by 3.7.1(7/1):
procedure Foo is
generic type T is private; Val1, Val2 : T; type Ref is access all T; Ptr : in out Ref; package G is end G;
package body G is type A is array (Boolean) of aliased T; X : A := (others => Val1); begin Ptr := X (False)'access; X := (others => Val2); end G;
type Rec (Is_Big : Boolean := True) is record case Is_Big is when False => null; when True => Big_Field : String (1 .. 100); end case; end record;
type Ref is access all Rec; Ptr : Ref (Is_Big => True);
package I is new G (T => Rec, Val1 => (Is_Big => True, Big_Field => (others => 'B')), Val2 => (Is_Big => False), Ref => Ref, Ptr => Ptr);
begin -- at this point, Ptr.all.Is_Big = False null; end Foo;
!recommendation
(See summary.)
!wording
Add at the end of 3.6(11):
In addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit.
Replace 3.6(22/1)
The elaboration of a component_definition in an array_type_definition consists of the elaboration of the subtype_indication.
with
The elaboration of a component_definition with the reserved word ALIASED includes a check that the component subtype is either undiscriminated or constrained. The exception Program_Error is raised if this check fails (this can only occur in an instance body - see 3.6(11)). The elaboration of a component_definition in an array_type_definition consists of this check and the elaboration of the subtype_indication, in an arbitrary order.
Add at the end of 3.8(18/1)
The elaboration of a component_definition with the reserved word ALIASED also includes the check, described in 3.6, that the component subtype is either undiscriminated or constrained. The elaboration of a component_definition in a record_type_definition consists of this check and the actions described in this subclause, in an arbitrary order.
!discussion
Three solutions to this problem were considered:
An assume-the-worst rule. The idea is to adjust 3.6(11) to disallow "aliased T" in a component_definition in a generic body if T might be discriminated with defaults. We would require that 3.6(11) be enforced in the private part of a generic instance.
This is a classic assume-the-worst rule, and it would be simple and consistent with the rest of the language. However, it would be unacceptably restrictive and incompatible with existing code.
It would require rejection of the following example:
generic type T is private; package G is ... end G;
package body G is type R is record F : aliased T; ... end record; ... end G;
Thus, this alternative was rejected.
A second alternative is much more radical. The basic idea is to disallow (constrained) access subtypes for general access types. 3.6(11) would be eliminated.
This would eliminate the root cause of the problem. Indeed, we could repeal 3.3.1(9) as well, making it possible to add or remove the aliased keyword without semantic effects.
However, this would be incompatible with existing code, IF code exists which actually uses this feature. (This is somewhat questionable.)
This argument was rendered moot when it was noted that such a prohibition would be a contract model violation for generic formal access types (which can be either general or pool-specific).
We could fix the contract problem with a run-time legality check or an assume-the-worst check. But that only worsens the compatibility concern.
An alternative solution would be to disallow (constrained) access subtypes for all access types. But, as that feature goes back to Ada 83, it seems likely to cause excessive compatibility problems.
The third alternative is to adopt a run-time check similar to the accessibility check. This is ugly at best, but doesn't have any fatal flaws. So this choice was adopted.
!ACATS test
A C-Test should be constructed to check that this rule is enforced.
!appendix

From: Steve Baird
Sent: Monday, May 13, 2002  4:21 PM

The following illustrates a case of access subtype
constraint violation which is not caught by
AI-00168 and RM 3.7.1(7/1):

   procedure Foo is

     generic
         type T is private;
         Val1, Val2 : T;
         type Ref is access all T;
         Ptr : in out Ref;
     package G is
     end G;

     package body G is
         type A is array (Boolean) of aliased T;
         X : A := (others => Val1);
     begin
         Ptr := X (False)'Access;
         X := (others => Val2);
     end G;

     type Rec (Is_Big : Boolean := True) is
         record
             case Is_Big is
                 when False =>
                     null;
                 when True =>
                     Big_Field : String (1 .. 100);
             end case;
         end record;

     type Ref is access all Rec;
     Ptr : Ref (Is_Big => True);

     package I is new G (T => Rec,
                         Val1 => (Is_Big => True,
                                  Big_Field => (others => 'B')),
                         Val2 => (Is_Big => False),
                         Ref => Ref,
                         Ptr => Ptr);


   begin
     -- at this point, Ptr.all.Is_Big = False
     null;
   end Foo;

The solution typically used in cases like these (i.e. impose an
"assume the worst in a generic body" rule) seems very restrictive
in this case. Rejecting the declaration of Foo.G.A on the grounds
that its aliased component's subtype might turn out to be unconstrained
seems extreme. Should this case be checked for at runtime, as part of
the elaboration of the component subtype? I do not see an obvious
solution.

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

From: Tucker Taft
Sent: Tuesday, May 14, 2002  4:38 PM

There seem to be at least two ways to address this problem:

1) Adjust 3.6(11) to disallow "aliased T" in a component_definition
in a generic body if T might be discriminated with defaults.  (The
"assume the worst" model would suggest this.)  We would require that
3.6(11) be enforced in the private part of a generic instance.

2) Require that for a formal IN OUT object of a general access type
whose designated type is discriminated, the subtype of the actual must
match statically the formal nominal subtype.

(1) seems like a "normal" generalization of the assume-the-worst, and the
workaround is to move the composite type declaration up into the private part of
the generic.  (2) is a smaller change, but sounds more like yet another
wart on the language related to access subtypes.

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

From: Steve Baird
Sent: Wednesday, May 15, 2002  1:20 PM

> There seem to be at least two ways to address this problem:
> ...
> 2) Require that for a formal IN OUT object of a general access type
> whose designated type is discriminated, the subtype of the actual must
> match statically the formal nominal subtype.

I don't believe that this solves the problem.
The following variation does not involve any IN OUT objects:

  procedure Foo is
    generic
	type T is private;
	Val1, Val2 : T;
	type Ref is access all T;
    package G is
	function F return Ref;
	procedure Invalidate;
    end G;

    package body G is
	type A is array (Boolean) of aliased T;
	X : A := (others => Val1);

	function F return Ref is
	begin
	    return X (False)'Access;
	end F;

	procedure Invalidate is
	begin
	    X := (others => Val2);
	end Invalidate;
    end G;

    type Rec (Is_Big : Boolean := True) is
	record
	    case Is_Big is
		when False =>
		    null;
		when True =>
		    Big_Field : String (1 .. 100);
	    end case;
	end record;

    type Ref is access all Rec;

    package I is new G (T => Rec,
			Val1 => (Is_Big => True,
                                 Big_Field => (others => 'B')),
			Val2 => (Is_Big => False),
			Ref => Ref);

    Ptr : Ref (Is_Big => True) := I.F;
  begin
    I.Invalidate;

    -- at this point, Ptr.all.Is_Big = False
    ...

  end Foo;

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

From: Tucker Taft
Sent: Wednesday, May 15, 2002  3:48 PM

Good point.  I guess that argues for (1), where we assume the worst
in a generic body as far as whether we allow use of "aliased" in
a component_definition, if the type might be discriminated-with-defaults.

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

From: Steve Baird
Sent: Wednesday, May 15, 2002  4:18 PM

That seems harsh.

How about making it a runtime check?
Program_Error is raised during the elaboration of a
an aliased comonent_definition if the component subtype
is unconstrained and discriminated.

This would not be the first time that a construct
which is statically forbidden outside of an instance
body is checked for at runtime within an instance body
(e.g. accessibility violations).

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

From: Randy Brukardt
Sent: Wednesday, May 15, 2002  4:54 PM

Steve may be right. Consider what types "might be
discriminanted-with-defaults":
generic private types, generic limited private types, and various generic
derived types. The last case isn't very interesting, but the former is:

   type Priv is private;

qualifies, and that is probably the most common generic formal parameter.
It's hard to imagine that no one ever has used an aliased object or
component of a generic private type. So we're talking about potentially
breaking a lot of code.

Steve did not make clear that this doesn't require a component to occur; it
also could occur with just a stand-alone object declaration: V : aliased T;.
Moreover, it could occur in a local scope using Unchecked_Access. (Does
anyone really use 'Access anyway? I've never found an object case where I
COULD use it.) Since that is true, the "work-around" of moving it to the
private part doesn't work.

So I have to agree with Steve -- I don't think we can mandate a compile-time
check. It will have to be a run-time check as the accessibility one is (the
problem is very similar, after all).

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

From: Tucker Taft
Sent: Thursday, May 16, 2002  8:47 AM

>It's hard to imagine that no one ever has used an aliased object or
>component of a generic private type. So we're talking about potentially
>breaking a lot of code.

It only applies to declaring a composite type in a generic body with an
aliased component of such a type. It only applies to non-limited types,
since limited types don't allow assignment.

>Steve did not make clear that this doesn't require a component to occur; it
>also could occur with just a stand-alone object declaration: V : aliased T;.

No, stand-alone objects are no problem, since any aliased object is
constrained by its initial value, and any assignment would check
to be sure the discriminant wasn't changed. The problem is that
composite assignment doesn't check constraints on components.
I suppose an alternative is to require checks on constraints of
all aliased components in a composite assignment.

>Moreover, it could occur in a local scope using Unchecked_Access. (Does
>anyone really use 'Access anyway? I've never found an object case where I
>COULD use it.) Since that is true, the "work-around" of moving it to the
>private part doesn't work.

It is just the *type* definition that needs to be moved, not any object
declarations.

>So I have to agree with Steve -- I don't think we can mandate a compile-time
>check. It will have to be a run-time check as the accessibility one is (the
>problem is very similar, after all).

I find introducing additional run-time checks that are effectively enforcing
contract model violations pretty distasteful. I would see that as an
absolute last resort.

On the other hand, if we relax the rules on declaring aliased components,
and enforce constraint checks on composite assignments if any aliased
components are discriminated with defaults, we actually expand the language
rather than restrict it, and eliminate
the distinction between generic and non-generic code.

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

From: Steve Baird
Sent: Thursday, May 16, 2002  2:20 PM

> I find introducing additional run-time checks that are
> effectively enforcing contract model violations pretty
> distasteful.

It isn't pretty, I agree.

> On the other hand, if we relax the rules on declaring
> aliased  components, and enforce constraint checks on
> composite assignments if any aliased components are
> discriminated with defaults, we actually expand the
> language rather than restrict it, and eliminate
> the distinction between generic and non-generic code.

If the check is performed during the elaboration of a
an aliased component_definition, then the outcome of
the check will always be known at compile time for
a replicated-instantiation implementation. In the
non-error case, there would be no associated overhead.

The same does not hold for the "check some (but not all)
component subtypes as part of composite object assignment"
proposal.

Can we at least agree that 3.6(11)'s prohibition of
"bad" aliased components ought to extend into the
private parts of instances?

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

From: Tucker Taft
Sent: Thursday, May 16, 2002  3:36 PM

> The same does not hold for the "check some (but not all)
> component subtypes as part of composite object assignment"
> proposal.

There would only be run-time overhead in those cases that
would have (or should have ;-) been illegal before.

>
> Can we at least agree that 3.6(11)'s prohibition of
> "bad" aliased components ought to extend into the
> private parts of instances?

Unless we repeal 3.6(11)... 3.7.1(7) was an attempt to
fix a problem with 3.6(11) that had to do with
private types, and now we have to fix another hole
that has to do with generic formal private types.

On the other hand, I guess a run-time check on a
composite assignment is kind of a bad time to find
out that something is wrong...

So, yes, I guess replacing 3.6(11) with a run-time
check on composite assignment is a bad idea.

Here is an alternative far out idea:
Disallow access subtypes for general access types.
This would allow us to safely repeal 3.6(11), and
recognize that aliased components can change
their discriminant values as a side-effect of
a composite assignment, or as part of a view conversion
(presuming we also allow view-converting
array-of-aliased to/from array-of-nonaliased).

In fact, we could generally allow the discriminants
of aliased objects to change, so long as they
are guaranteed to *not* be allocated in the heap.
All objects allocated in the heap would still be
constrained.  We would simply say that the dereference
of an access value is a constrained view, but an
aliased object that is a component or a stand-alone
object is not necessarily constrained.

This has the nice side-effect of allowing one to add
"aliased" on a component of a stand-alone object declaration
without breaking any existing code.

As it is now, we allow aliased components to change
discriminant values only if they happen to be declared
at a place where the component type is private.

Losing access subtypes for general access types seems
like a small price to pay for simplifications in
several other places, and less negative impact of
adding "aliased."

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

From: Randy Brukardt
Sent: Thursday, May 16, 2002  4:56 PM

> It only applies to declaring a composite type in a generic body with an
> aliased component of such a type.  It only applies to non-limited types,
> since limited types don't allow assignment.

The first is clearly wrong (see below). The second is true, but, as I said,
the most common formal type is "type P is private", and it clearly covers
that.

> >Steve did not make clear that this doesn't require a component to occur; it
> >also could occur with just a stand-alone object declaration:
> V : aliased T;.
> >
>
> No, stand-alone objects are no problem, since any aliased object is
> constrained by its initial value, and any assignment would check
> to be sure the discriminant wasn't changed.  The problem is that
> composite assignment doesn't check constraints on components.
> I suppose an alternative is to require checks on constraints of
> all aliased components in a composite assignment.

No, this is not correct. The rule (3.3.1(9)) says that the object is
constrained if the object has an "unconstrained nominal subtype". Certainly
the "nominal" subtype is constrained in this case, it can not have
constraints added to it (see 3.2(9)).

Moreover, requiring some sort of constraint check for subtypes without a
whiff of constraints would be a significant overhead in Janus/Ada. We'd have
to pass an "aliased" flag to all assignment thunks (generic or non-generic).
And we'd have to generate discriminant check code into every such thunk.

I wrote a test program (attached below), and not a single compiler that I
tried made the check on a regular private type, and only one did on the
generic private type. So there is little enforcement of this even if it is
required (by some language lawyer hoops that I can't figure out).

There is a validation test for this area (C3A0014). It uses a generic formal
derived type. It's too bad that they didn't use a generic formal private
type, because then we could have had this discussion years ago.

> >Moreover, it could occur in a local scope using Unchecked_Access. (Does
> >anyone really use 'Access anyway? I've never found an object case where I
> >COULD use it.) Since that is true, the "work-around" of moving it to the
> >private part doesn't work.
>
> It is just the *type* definition that needs to be moved, not any object
> declarations.

Sorry, it happens anywhere that "aliased" can be specified on a "nominally"
constrained type.

> On the other hand, if we relax the rules on declaring aliased components,
> and enforce constraint checks on composite assignments if any aliased
> components are discriminated with defaults, we actually expand the
> language rather than restrict it, and eliminate
> the distinction between generic and non-generic code.

That would be a good idea if it worked, but it doesn't, as the checks
currently aren't required in many cases. Adding them would be incompatible,
possibly in ways that would not show up until systems are fielded.

Later:
>Here is an alternative far out idea:
>Disallow access subtypes for general access types.
>This would allow us to safely repeal 3.6(11), and
>recognize that aliased components can change
>their discriminant values as a side-effect of
>a composite assignment, or as part of a view conversion
>(presuming we also allow view-converting
>array-of-aliased to/from array-of-nonaliased).
>
>In fact, we could generally allow the discriminants
>of aliased objects to change, so long as they
>are guaranteed to *not* be allocated in the heap.
>All objects allocated in the heap would still be
>constrained.  We would simply say that the dereference
>of an access value is a constrained view, but an
>aliased object that is a component or a stand-alone
>object is not necessarily constrained.

Right. That's already true for private types (at least in practice, if not
in the standard).

>This has the nice side-effect of allowing one to add
>"aliased" on a component of a stand-alone object declaration
>without breaking any existing code.
>
>As it is now, we allow aliased components to change
>discriminant values only if they happen to be declared
>at a place where the component type is private.

And the same for stand-alone objects.

>Losing access subtypes for general access types seems
>like a small price to pay for simplifications in
>several other places, and less negative impact of
>adding "aliased."

I agree. But that is a pretty big change to the language (at least
conceptually). It's obviously incompatible, but only at compile-time. It has
the advantage of eliminating a bunch of junk rules. I suppose it wouldn't be
too large to do in the amendment. I wonder what Robert's customers would
think of that (do they use access subtypes on general access types??)

                 Randy.


----

My test program:

with Ada.Text_IO;
procedure Tuck is
    subtype Short is Integer range 1 .. 20;

    type Tuck1 (Dumb : Short := 1) is null record;

    package P is
        type Tuck2 is private;
        C1 : constant Tuck2;
        C2 : constant Tuck2;
    private
        type Tuck2 (Dumb : Short := 1) is null record;
        C1 : constant Tuck2 := (Dumb => 1);
        C2 : constant Tuck2 := (Dumb => 2);
    end P;

    generic
        type Tuck3 is private;
        C1 : in Tuck3;
        C2 : in Tuck3;
        Code : in Character;
    package G is
        procedure Change;
    end G;

    package body G is
        procedure Change is
            V3  : Tuck3 := C1;
            AV3 : aliased Tuck3 := C1;
        begin
            V3 := C2; -- OK.
            begin
                AV3 := C2; -- ?? Might raise C_E by 3.3.1(9), but the
                           -- nominal subtype is constrained.
                Ada.Text_IO.Put_Line ("-- AV3 no C_E (" & Code & ')');
            exception
                when Constraint_Error =>
                    Ada.Text_IO.Put_Line ("-- AV3 raises C_E (" & Code & ')');
            end;
        end Change;
    end G;

    V1  :   Tuck1 := (Dumb => 1);
    V2  : P.Tuck2 := P.C1;
    AV1 : aliased   Tuck1 := (Dumb => 1);
    AV2 : aliased P.Tuck2 := P.C1;
    package GP1 is new G (Tuck1, C1 => (Dumb => 1),
                          C2 => (Dumb => 2), Code => '3');
    package GP2 is new G (P.Tuck2, P.C1, P.C2, '4');

begin
    V1 := (Dumb => 2); -- OK.
    V2 := P.C2; -- OK.
    begin
        AV1 := (Dumb => 2); -- Raises C_E by 3.3.1(9)
        Ada.Text_IO.Put_Line ("** AV1 missed");
    exception
        when Constraint_Error =>
            null;
    end;
    begin
        AV2 := P.C2; -- ?? Might raise C_E by 3.3.1(9), but the
                     -- nominal subtype is constrained.
        Ada.Text_IO.Put_Line ("-- AV2 no C_E");
    exception
        when Constraint_Error =>
            Ada.Text_IO.Put_Line ("-- AV2 raises C_E");
    end;
    GP1.Change;
    GP2.Change;
end Tuck;

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

From: Steve Baird
Sent: Monday, May 20, 2002  3:07 PM

As I read it, the problem illustrated by Randy's example
is that in a case like

    package P is
        type T is private;
    private
        type T (D : Integer := 10) is record ... end record;
    end P;

    X : aliased P.T;

, the actual subtype of X is thought to be unconstrained.

It is claimed that 3.3.1(9) does not apply in this case
because the nominal subtype of X is constrained.

This boils down to a question whether 3.3.1(9) refers to the
full view of P.T (which is unconstrained) or to the
partial view that is visible at the point of the
object declaration (which is not).

Clearly X must be constrained in this example, and if
3.3.1(9) does not already imply this, then it needs to be
fixed. I don't see any problem here - Dynamic Semantics
rules generally ignore privacy - but it wouldn't hurt
to state this explicitly.

In any case, this issue is completely separate from the
problem with aliased component subtypes in instance bodies
that began this thread.

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

From: Randy Brukardt
Sent: Friday, May 24, 2002  7:05 PM

> Clearly X must be constrained in this example, and if
> 3.3.1(9) does not already imply this, then it needs to be
> fixed. I don't see any problem here - Dynamic Semantics
> rules generally ignore privacy - but it wouldn't hurt
> to state this explicitly.

Well, this is messy and expensive to implement in a generic code shared
environment, because it means that assignment operations (thunks) can't be
composed, or that you have to pass quite a bit of information about the context
of the use at runtime. Either option seems like another nail in the coffin of
useful code sharing (that's getting to be quite a bed of nails...), since to
avoid it you have to know the body of the generic. And this is to support a
rather rare case, and one for a rule which is quite obnoxious to begin with.

> In any case, this issue is completely separate from the
> problem with aliased component subtypes in instance bodies
> that began this thread.

Not at all. I wanted to show that there were more problems with this rule than
just your original one. Tucker's radical solution of repealing 3.3.1(9) (thus
eliminating your original problem), and then eliminating the cause of the
problems that led to it in the first place, seems like a useful simplification
of the language.

The only question is whether it would be too incompatible. Do people actually
use access subtypes on general access types?

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

From: Robert Dewar
Sent: Friday, May 24, 2002  9:45 PM

Perhaps it is time to declare general generic code sharing to be dead.

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

From: Randy Brukardt
Sent: Friday, May 24, 2002  10:02 PM

Why the heck doesn't anybody answer the important question of whether making
access subtype illegal on general access types is too incompatible?

Because if we have to keep them, we're going to have to adopt a very obnoxious
assume-the-worst rule or an obnoxious run-time check. It seems better to kill
off 3.3.1(9), which is a pain in the butt anyway (because it prevents
adding "aliased" to an unconstrained variable).

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

From: Robert Dewar
Sent: Friday, May 24, 2002  10:07 PM

If current compilers allow this, then making it illegal has unknown
consequences. The effort of finding out these consequences in advance
is huge.

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

From: Randy Brukardt
Sent: Friday, May 24, 2002  10:32 PM

Of course, but it is relatively easy to disprove the assertion that no one uses
access subtypes on general access types. Simply provide a significant example.
Proving the assertion is much harder, of course, but I'd like to know whether
we need to put some effort in here.

After all, the consequences of abandoning the possibility of any generic code
sharing(*) in the Ada language also are huge. It is likely that many, possibly
all compilers make assumptions about generics which would no longer be true in
this model. (one presumes that most of the rules specifically inserted for
generic sharing reasons would be repealed).

And not solving the problem isn't really an option, either. It's a rather nasty
hole which exists only with a particular bad combination of features.

So I fear we're going to have to do something "huge" here.

         Randy.

(*) I say "any generic code sharing" because I don't consider any sharing which
requires analysis of the body as well as the actual parameters and
specification to be "generic code sharing". Such post-compilation sharing can
be done on any code sequences that happen to be similar, and really has nothing
to do with generics. Indeed, we used to do something much like that in the
early days of Janus/Ada in order to get it to fit in 56K Z-80 machines.

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

From: Robert Dewar
Sent: Saturday, May 25, 2002  8:28 AM

<<Of course, but it is relatively easy to disprove the assertion that no one
uses access subtypes on general access types. Simply provide a significant
example. Proving the assertion is much harder, of course, but I'd like to
know whether we need to put some effort in here.>>

That's the wrong point of view. If current compilers are allowing this,
then programs may or may not be using significant or insignificant
examples of this usage. I know this is FUD, but we have to be very
sure that it is worth while making something illegal that was previously
legal, since it can be a huge pain.

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

From: Randy Brukardt
Sent: Friday, June 7, 2002  6:54 PM

No, that is the correct point of view, because I am already convinced that it
is worthwhile to make this change. (The alternatives being much worse, IMHO,
and it fixes other problems at the same time.) That may not be true for others.
The main question in my mind is whether it is too incompatible -- that is, does
it break too many existing programs.

If no one can disprove the assertion, then I would probably spend the "huge"
(as you put it) effort to try to find out, by creating a tool that can be run
on large volumes of code by users to determine the usage of this (and probably
other) features, and then distributing it as widely as possible. However, if
there are significant uses of the feature such that there would be a lot of
opposition to the change, I'd rather spend the time on something productive
(like my resume :-).

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

From: Steve Baird
Sent: Monday, September 9, 2002  5:06 PM

The Minutes of the June 2002 (Vienna) ARG meeting mention
three possible solutions to the problem described in AI-295:

     1) An "assume the worst" rule in generic bodies.
     2) A new runtime check.
     3) Make general access subtypes illegal.

 #1 -
     To recap, this is Tuck's description of this approach (taken from the AI):
       Adjust 3.6(11) to disallow "aliased T" in a component_definition
       in a generic body if T might be discriminated with defaults.  (The
       "assume the worst" model would suggest this.)  We would require that
       3.6(11) be enforced in the private part of a generic instance.

     This would be, in some sense, the cleanest, most consistent solution to
     the problem. It would be straightforward to define and easy to implement.

     I believe that it would be unacceptably restrictive.

     It would require rejection of the following example:

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

         package body G is
             type R is
               record
                 F : aliased T;
                 ...
               end record;
             ...
          end G;

     I feel that this would be a bad idea even if compatibility were not
     a concern; compatibility considerations reenforce this position.

     In my opinion, no further discussion of this approach is needed.

 #2 -
     To recap, this is my description of this approach (taken from the AI):
       Program_Error is raised during the elaboration of a
       an aliased comonent_definition if the component subtype
       is unconstrained and discriminated.

       3.6(11)'s prohibition of "bad" aliased components ought to
       extend into the private parts of instances.

     There is general agreement with Tuck's point that checking at runtime
     for a construct which is statically forbidden outside of an instance
     body is "pretty distasteful". On the other hand, accessibility
     checking is already defined in this way.

 #3 -
     To recap, this is Tuck's description of this approach (taken from the AI):
         Disallow (constrained) access subtypes for general access types.

     It appeared at first that there were no significant language
     definition issues with this approach; the only important question
     seemed to be whether this restriction was too incompatible.

     However, the Vienna minutes conclude with:

         After the meeting, Tucker and Randy discussed this, and Tuck realized
         that this would be a contract model violation on formal access types
         (which can match both pool-specific and general access types).
         So option 3 is out.

Thus, options #1 and #3 are fatally flawed, while #2 is only ugly; I
advocate #2.

 The following is proposed RM wording for proposal #2:

     Add at the end of 3.6(11):
         In addition to the places where Legality Rules normally apply
         (see 12.3), this rule applies also in the private part of an instance
         of a generic unit.

     Replace 3.6(22/1)
         The elaboration of a component_definition in an array_type_definition
         consists of the elaboration of the subtype_indication.
     with
         The elaboration of a component_definition with the reserved word ALIASED
         includes a check that the component subtype is either undiscriminated
         or constrained. The exception Program_Error is raised if this check fails
         (this can only occur in an instance body - see 3.6(11)).
         The elaboration of a component_definition in an array_type_definition
         consists of this check and the elaboration of the subtype_indication,
         in an arbitrary order. The elaboration of a component_definition in a
         record_type_definition consists of this check and the actions described
         in 3.8, in an arbitrary order.

     Add at the end of 3.8(18/1)
         The elaboration of a component_definition with the reserved word ALIASED
         also includes the check, described in 3.6, that the component subtype
         is either undiscriminated or constrained.

 I'm not very happy with this wording, but the other alternatives that came to
 mind all involved even more extensive overriding of one section of the RM
 by another (e.g. a rule like "In addition to what is stated elsewhere,
 the elaboration of a component_definition with the reserved word ALIASED
 also includes a check that ... ").

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

From: Randy Brukardt
Sent: Friday, September 27, 2002

One possible improvement would be to avoid trying to have a single
definition of the check. It doesn't seem long enough to bother with that.
Moreover, I'd make the 3.8(18) part a separate paragraph - 3.8(18/1) is way
too long already. So perhaps something like the following would be better:

Replace 3.6(22/1)
     The elaboration of a component_definition in an array_type_definition
     consists of the elaboration of the subtype_indication.
with
     The elaboration of a component_definition in an array_type_definition
     consists of the elaboration of the subtype_indication and a check that
     the component subtype is either undiscriminated or constrained if the
     component_definition includes the reserved keyword ALIASED, in an
     arbitrary order. The exception Program_Error is raised if this check
     fails (this can only occur in an instance body - see 3.6(11)).

Add as a new paragraph after 3.8(18/1)
     The elaboration of a component_definition in a record_type_definition
     consists of the actions described elsewhere in this subclause and a check
     that the component subtype is either undiscriminated or constrained if the
     component_definition contains the reserved keyword ALIASED, in an
     arbitrary order. The exception Program_Error is raised if this check
     fails (this can only occur in an instance body - see 3.6(11)).

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

From: Erhard Ploedereder
Date: Sunday, October 10, 2002, 11:46 AM


Ignore this, unless AI-275 or AI-295 are on your plate.

Here are fixed-up versions of program examples in the two AIs, which
I compiled at the meeting.

Erhard
-----------------------------


[See !appendix of AI-00275 for Test275. - Editor]

procedure test295 is
  procedure Foo is

     generic
         type T is private;
         Val1, Val2 : T;
         type Ref is access all T;
         Ptr : in out Ref;
     package G is
     end G;

     package body G is
         type A is array (Boolean) of aliased T;
         X : A := (others => Val1);
     begin
         Ptr := X (False)'Access;
         X := (others => Val2);
     end G;

     type Rec (Is_Big : Boolean := True) is
         record
             case Is_Big is
                 when False =>
                     null;
                 when True =>
                     Big_Field : String (1 .. 100);
             end case;
         end record;

     type Ref is access all Rec;
     Ptr : Ref(Is_Big => True);

     package I is new G (T => Rec,
                         Val1 => (Is_Big => True,
                                  Big_Field => (others => 'B')),
                         Val2 => (Is_Big => False),
                         Ref => Ref,
                         Ptr => Ptr);


   begin
     -- at this point, Ptr.all.Is_Big = False
     null;
   end Foo;
begin
   null;
end test295;

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


Questions? Ask the ACAA Technical Agent