Version 1.11 of ai05s/ai05-0041-1.txt

Unformatted version of ai05s/ai05-0041-1.txt version 1.11
Other versions for file ai05s/ai05-0041-1.txt

!standard 3.7.1(7/2)          08-05-15 AI05-0041-1/08
!standard 3.3(23.9/3)
!standard 3.3(23.10/3)
!standard 3.10.2(26/3)
!standard 3.10.2(27.2/2)
!standard 3.10.2(28)
!standard 4.8(6/2)
!class binding interpretation 07-03-27
!status Amendment 201Z 08-11-26
!status WG9 Approved 08-06-20
!status ARG Approved 5-0-3 08-02-09
!status work item 07-03-27
!status received 07-03-27
!priority Medium
!difficulty Hard
!qualifier Omission
!subject Derived types and partial views
!summary
For the purposes of the rules for allowing allocated unconstrained objects, any ancestor that has a constrained partial view causes the rules to apply.
In a generic body, 3.10.2(27.2/2) is checked assuming that any untagged formal private or derived type has a constrained partial view.
!question
(1) It seems that the meaning of "partial view" in 3.7.1(7/2) is either obscure or too narrow. The ACATS 2.6 test contains a subtest like the following, for which the legality is not obvious.
package B371001_1 is type T is private; private type T (D : Integer := 0) is null record; end B371001_1;
package B371001_1.Child_2 is type T is new B371001_1.T; type Ptr1 is access all T; subtype S1A is Ptr1 (1); -- ERROR: [1] private subtype S1B is Ptr1 (2); -- ERROR: [2]
type Ptr2 is access constant T; subtype S2 is Ptr2 (3); -- ERROR: [3]
type Ptr3 is access T; P3 : Ptr3 (0); -- OK [4] end B371001_1.Child_2;
The error at [1] occurs because only the partial view of B371001_1.T is visible in the visible part, and thus that is all that is derived. That view doesn't have discriminants, so the constraint is illegal.
On the other hand, the private part has more visibility into the parent, and it can see that the type has discriminants.
The errors at [2] and [3] are supposed to be because the type has defaulted discriminants; since that only applies to general access types, [4] is OK.
However, that brings up the question of whether this type has a partial view. The test writer surely expected it to behave as if it does (by expecting some constraints to be able to see the discriminants, and thus be legal). In that case, the purpose of this rule (to prevent problems with discriminant constraints that point at unconstrained objects) would require the partial view rule to be enforced. What is the intent?
Similar examples can be created using nested packages rather than child packages.
(2) There seems to be a contract-model problem with 3.10.2(27.2/2) in the case of a generic formal discriminated type as seen from within the generic body.
Consider this example:
procedure Foo is subtype Index is Integer range 0 .. 255; Smaller_Index : constant Index := 10; Larger_Index : constant Index := 20;
generic type T1 (D : Index) is private; package G is type Ref is access all T1; Smaller : aliased T1 (Smaller_Index); Ptr : Ref; end G;
package body G is begin Ptr := Smaller'access; -- Legal? (No.) end G;
package Pkg is type T2 is private; private type T2 (D : Index := 100) is record F : String (1 .. D); end record;
package I is new G (T2); end Pkg;
package body Pkg is Larger : T2 (Larger_Index); begin I.Ptr.all := Larger; end Pkg;
begin ...; end Foo;
3.10.2(27.2/2) is satisfied at the line marked "Legal?", because T1 does not have a partial view. This allows assigning a jumbo value to a not-so-jumbo object; this is not good.
An assume-the-worst rule seems to be needed. For purposes of checking 3.10.2(27.2/2) within a generic body, it should be assumed that any untagged formal discriminated type of the generic has a constrained partial view.
!recommendation
(See summary.)
!wording
Change the new text for 3.3(23.9/3) from AI05-0008-1 as follows:
* it is a dereference of a pool-specific access type, and there is no {ancestor of its type that has a constrained} partial view [of its type that is constrained].
Replace the new text for 3.3(23.10/3) from AI05-0008-1 with the following:
For the purposes of determining within a generic body whether an object is known to be constrained:
* if a subtype is a descendant of an untagged generic formal private or derived type, and the subtype is not an unconstrained array subtype, it is not considered indefinite and is considered to have a constrained partial view;
* if a subtype is a descendant of a formal access type, it is not considered pool-specific.
Change 3.7.1(7/2) as follows:
... However, in the case of an access subtype, a discriminant_ constraint is {legal only if any dereference of a value of the access type is known to be constrained (see 3.3).} [illegal if the designated type has a partial view that is constrained or, for a general access subtype, has default_expressions for its discriminants.] In addition to the places where Legality Rules normally apply (see 12.3), these rules apply also in the private part of an instance of a generic unit. [In a generic body, this rule is checked presuming all formal access types of the generic might be general access types, and all untagged discriminated formal types of the generic might have default_expressions for their discriminants.]
Change 3.10.2(26/3) as modified by AI05-0008-1 as follows:
* The view shall not be a subcomponent that depends on discriminants of an object unless the object is known to be constrained. [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.]
Change 3.10.2(27.2/2) as follows:
* D shall be discriminated in its full view and unconstrained in any partial view, and the designated subtype of A shall be unconstrained. {For the purposes of determining within a generic body whether D is unconstrained in any partial view, a discriminated subtype is considered to have a constrained partial view if it is a descendant of an untagged generic formal private or derived type.}
Change 3.10.2(28) as follows:
* The accessibility level of the view shall not be statically deeper than that of the access type A. [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.]
In addition to the places where Legality Rules normally apply (see 12.3), these requirements apply also in the private part of an instance of a generic unit.
[Editor's note: This last paragraph is not a bullet or within a bullet.]
Change 4.8(6/2) as follows:
... If the designated type is composite, then the subtype of the created object is the designated subtype when the designated subtype is constrained or there is {an ancestor of the designated type that has} a {constrained} partial view [of the designated type that is constrained]; otherwise, the created object is constrained by its initial value ...
!discussion
Clearly, the type in the question has two views (7.3.1(4/1) explicitly states that additional information can be made visible for a derived type). So, the problem that 3.7.1(7/2) is intended to prevent is present for this type. The 3.7.1(7/2) rule needs to apply.
Defining this kind of type to be a partial view would surely work, but it would trigger a number of other rules (for instance, about completions, freezing, and representation clauses) which might be harmful. As such, doing that seems to be too dangerous to contemplate, especially for a Corrigendum-level change.
Changing 3.7.1(7/2) also requires changing the matching 4.8(6/2).
This problem can get even more confused if there are multiple different partial views for a type. Consider:
package P1 is type T1 (D : Integer := 10) is private; private type T1 (D : Integer := 10) is ... end P1;
package P1.Child is type T2 is private; private type T2 is new T1; end P1.Child;
Now T2 seems to have two partial views, one constrained and one unconstrained. In this case, the unconstrained partial view is unimportant, because the child can see the full view. But that isn't always true (especially for a nested package).
The wording needs to be careful to take cases like the above and like
package P2 is type T1 (D : Integer := 10) is ... end P2;
package P2.Child is type T2 is private; private type T2 is new T1; end P2.Child;
into account. Surely the behavior of the above and of
package P2.Child2 is type T3 is private; private type T3 (D : Integer := 10) is ... end P2.Child2;
should not differ vis-a-vis the "constrained partial view" rules: an object of both T2 and T3 ought to be unconstrained if allocated with an allocator.
It also needs to be the case that generic bodies assume that every derived formal type has such a partial view, so that they cannot cause this problem to reemerge. Similarly, we need to tweak the "known to be constrained" rules so that they take into account these changes, so that renames of discriminant-dependent components of potentially unconstrained objects are illegal.
Presuming we have gotten the "known to be constrained" rules right, we now try to use the term "known to be constrained" wherever appropriate, rather than repeating rules about having constrained partial views, etc. (e.g. in 3.7.1(7/2)).
Note that we have incorporated the former AI-61, by providing updated wording for 3.10.2(27.2/2). We had hoped to use the "known to be constrained" wording here as well, as in the following:
D shall be a discriminated type, the designated subtype of A shall be unconstrained, and any dereference of a value of type A is known to be constrained (see 3.3).
However, that is more restrictive, since it disallows taking 'Access of a constrained object whenever the type has defaults for its discriminants, even when there are no constrained partial views. "Known to be constrained" is not the same as "not known to be unconstrained." There is a grey area in the middle where we don't know whether or not it is constrained, and depending on particular circumstances, we choose one or the other. For example, for the purposes of checking constraints on assignment, we presume the dereference of a general access value is constrained, even when it might designate an unconstrained object through use of 'Access. For the purposes of renaming a discriminant-dependent component, we presume the enclosing object is unconstrained unless we know it is constrained.
It might be worth defining "known to be unconstrained" so we can centralize the definition of the "assume the worst" rule for generics. If we had that, then 3.10.2(27.2/2) could become:
D shall be a discriminated type, the designated subtype of A shall be unconstrained, and any dereference of a value of type A is not known to be unconstrained (see 3.3).
A bit of a double negative, unfortunately.
The generic boilerplate has to be added to 3.10.2(27.2/2). AI05-0008-1 added it to 3.10.2(26/2). It is already in 3.10.2(28). It is better to have that apply to all of the bullets here, for consistency if for no other reason. It is weird to have some, but not all, of the rules apply to an access attribute in the private part of a generic unit.
!corrigendum 3.3(23)
!comment A fake entry to force a conflict. The real text is in the conflict file. (includes 23.9 and 23.10)
@drepl @xbullet<it is a dereference of a pool-specific access type, and there is no partial view of its type that is constrained.> @dby @xbullet<it is a dereference of a pool-specific access type, and there is no ancestor of its type that has a constrained partial view.>
!corrigendum 3.7.1(7/2)
Replace the paragraph:
A discriminant_constraint is only allowed in a subtype_indication whose subtype_mark denotes either an unconstrained discriminated subtype, or an unconstrained access subtype whose designated subtype is an unconstrained discriminated subtype. However, in the case of an access subtype, a discriminant_constraint is illegal if the designated type has a partial view that is constrained or, for a general access subtype, has default_expressions for its discriminants. In addition to the places where Legality Rules normally apply (see 12.3), these rules apply also in the private part of an instance of a generic unit. In a generic body, this rule is checked presuming all formal access types of the generic might be general access types, and all untagged discriminated formal types of the generic might have default_expressions for their discriminants.
by:
A discriminant_constraint is only allowed in a subtype_indication whose subtype_mark denotes either an unconstrained discriminated subtype, or an unconstrained access subtype whose designated subtype is an unconstrained discriminated subtype. However, in the case of an access subtype, a discriminant_constraint is legal only if any dereference of a value of the access type is known to be constrained (see 3.3). In addition to the places where Legality Rules normally apply (see 12.3), these rules apply also in the private part of an instance of a generic unit.
!corrigendum 3.10.2(26/3)
Replace the paragraph:
by:
!corrigendum 3.10.2(27.2/2)
Replace the paragraph:
by:
!corrigendum 3.10.2(28)
Replace the paragraph:
by:
In addition to the places where Legality Rules normally apply (see 12.3), these requirements apply also in the private part of an instance of a generic unit.
!corrigendum 4.8(6/2)
Replace the paragraph:
If the designated type of the type of the allocator is elementary, then the subtype of the created object is the designated subtype. If the designated type is composite, then the subtype of the created object is the designated subtype when the designated subtype is constrained or there is a partial view of the designated type that is constrained; otherwise, the created object is constrained by its initial value (even if the designated subtype is unconstrained with defaults).
by:
If the designated type of the type of the allocator is elementary, then the subtype of the created object is the designated subtype. If the designated type is composite, then the subtype of the created object is the designated subtype when the designated subtype is constrained or there is an ancestor of the designated type that has a constrained partial view; otherwise, the created object is constrained by its initial value (even if the designated subtype is unconstrained with defaults).
!ACATS test
The test case in the first question should be replaced in the ACATS 3.0 test B371001 (it has been removed until this AI is resolved).
Add an ACATS B-Test like the example in the second question.
!appendix

From: Randy Brukardt
Date: Monday, March 23, 2007  7:07 PM

It seems to me that the meaning of "partial view" in 3.7.1(7/2) [and I
believe that there are similar rules elsewhere in the language] is either
obscure or too narrow. I was updating the ACATS test for the Corrigendum
version of this rule, and I ran across the following example:

package B371001_1 is
    type T is private;
private
    type T (D : Integer := 0) is null record;
end B371001_1;

package B371001_1.Child_2 is
    pragma Elaborate_Body;

    type T is new B371001_1.T;
    type Ptr1 is access all T;
    subtype S1A is Ptr1 (1); -- ERROR: [1]
private
    subtype S1B is Ptr1 (2); -- ERROR: [2]

    type Ptr2 is access constant T;
    subtype S2 is Ptr2 (3); -- ERROR: [3]

    type Ptr3 is access T;
    P3 : Ptr3 (0); -- OK [4]

end B371001_1.Child_2;

The error at [1] occurs because only the partial view of B371001_1.T is
visible in the visible part, and thus that is all that is derived. That view
doesn't have discriminants, so the constraint is illegal.

OTOH, the private part has more visibility into the parent, and it can see
that the type has discriminants.

The errors at [2] and [3] are supposed to be because the type has defaulted
discriminants; since that only applies to general access types, [4] is OK.

However, that brings up the question of whether this type has a partial
view. The test writer surely expected it to behave as if it does (by
expecting some constraints to be able to see the discriminants, and thus be
legal). In that case, the purpose of this rule (to prevent problems with
discriminant constraints that point at unconstrained objects) would require
the partial view rule to be enforced. (Thanks to Pascal for this insight.)

However, I'm now wondering if the whole idea is wrong here. This is a
derived type, not a private type, and it doesn't get additional operations
at a later point like a private type. (Right?). In that case, this type
never would have (visible) discriminants, and all of the constraints are
illegal. I know that in type extensions, you can lose the ability to access
parent components that you can regain with a type conversion, and this seems
to be a similar case.

Probably the test ought to be structured with a new type in the private
part:

package B371001_1.Child_2 is
    pragma Elaborate_Body;

    type T is new B371001_1.T;
    type Ptr1 is access all T;
    subtype S1A is Ptr1 (1); -- ERROR: [1]
private

    type TT is new B371001_1.T;
    type Ptr2 is access all TT;
    subtype S2 is Ptr2 (2); -- ERROR: [2]

    type Ptr2 is access constant TT;
    subtype S3 is Ptr3 (3); -- ERROR: [3]

    type Ptr4 is access TT;
    P4 : Ptr4 (0); -- OK [4]

end B371001_1.Child_2;


No one can see the constrained view of TT, so then the original intent
holds, and there isn't a problem with the language wording (only the test).

Thoughts? Which of these lines of logic is correct?

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

From: Gary Dismukes
Date: Friday, March 23, 2007  7:08 PM

> However, that brings up the question of whether this type has a partial
> view. The test writer surely expected it to behave as if it does (by
> expecting some constraints to be able to see the discriminants, and thus be
> legal). In that case, the purpose of this rule (to prevent problems with
> discriminant constraints that point at unconstrained objects) would require
> the partial view rule to be enforced. (Thanks to Pascal for this insight.)

Hmm, I'm not sure whether the RM defines such a derived type to be a partial
view, but it seems that it should.  (Not obvious to me how to derive that,
so to speak, especially late on a Friday afternoon;).

> However, I'm now wondering if the whole idea is wrong here. This is a
> derived type, not a private type, and it doesn't get additional operations
> at a later point like a private type. (Right?). In that case, this type
> never would have (visible) discriminants, and all of the constraints are
> illegal. I know that in type extensions, you can lose the ability to access
> parent components that you can regain with a type conversion, and this seems
> to be a similar case.

No, derived types definitely do (or can) get additional operations at a later
point, based on what's visible from the parent type.  That's explicitly covered 
by 7.3(4/1).

> Probably the test ought to be structured with a new type in the private
> part:

You could, though it doesn't seem that you should if the rules work out OK.

Seems better to confirm whether the rules should apply to the test as
written before revising the test, rather than skirting the issue.

> package B371001_1.Child_2 is
>     pragma Elaborate_Body;
> 
>     type T is new B371001_1.T;
>     type Ptr1 is access all T;
>     subtype S1A is Ptr1 (1); -- ERROR: [1]
> private
> 
>     type TT is new B371001_1.T;
>     type Ptr2 is access all TT;
>     subtype S2 is Ptr2 (2); -- ERROR: [2]
> 
>     type Ptr2 is access constant TT;
>     subtype S3 is Ptr3 (3); -- ERROR: [3]
> 
>     type Ptr4 is access TT;
>     P4 : Ptr4 (0); -- OK [4]
> 
> end B371001_1.Child_2;
> 
> 
> No one can see the constrained view of TT, so then the original intent
> holds, and there isn't a problem with the language wording (only the test).

The revised version certainly looks correct, but I think the original
is as well (or at least I believe I can see an argument for that).

> Thoughts? Which of these lines of logic is correct?

See above.

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

From: Randy Brukardt
Date: Friday, March 23, 2007  8:38 PM

...
> Hmm, I'm not sure whether the RM defines such a derived type to be a partial
> view, but it seems that it should.  (Not obvious to me how to derive that,
> so to speak, especially late on a Friday afternoon;).

It certainly doesn't, because 7.3(4) defines partial view in terms of the
syntax entities private_type_declaration and private_extension_declaration.
So I don't think any amount of derivation (pun not intended - ED) is going to
change that, on Friday evening, Monday morning, or any other day...

> > However, I'm now wondering if the whole idea is wrong here. This is a
> > derived type, not a private type, and it doesn't get additional operations
> > at a later point like a private type. (Right?). In that case, this type
> > never would have (visible) discriminants, and all of the constraints are
> > illegal. I know that in type extensions, you can lose the ability to access
> > parent components that you can regain with a type conversion, and this seems
> > to be a similar case.
>
> No, derived types definitely do (or can) get additional operations at a later
> point, based on what's visible from the parent type.  That's explicitly covered
> by 7.3(4/1).

You mean 7.3.1(4/1), and you are right, I had forgotten about that.

That means that the definition of partial view is suspect, surely in regards
to 3.7.1(7/2), and probably other rules as well.

> > Probably the test ought to be structured with a new type in the private
> > part:
>
> You could, though it doesn't seem that you should if the rules
> work out OK.
>
> Seems better to confirm whether the rules should apply to the test as
> written before revising the test, rather than skirting the issue.

Well, actually, the rule with the ACATS is that if there is enough doubt for
it to go to the ARG, then we don't include the cases in the test suite.
There is no reason to encourage implementers to do the something that might
turn out to be the wrong thing, depending on what the ARG decides.
I can try to guess what the ARG will decide, but I'm not always going to be
right about that. I've got three tests already on a limbo list waiting for
AI05-0008 and AI05-0028 to be completed, and this test can be added to it.

Sounds like we need an AI to define that a type derived from a partial view
is a partial view if there is a place within its immediate scope where the
full view of the parent type is visible. Or something like that. Gotta worry
about the effect on other rules that depend on partial views, though (should
rep. clauses be illegal on such a type until the private part??? Etc.)

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

From: Pascal Leroy
Date: Monday, March 26, 2007  1:49 AM

> Sounds like we need an AI to define that a type derived from 
> a partial view is a partial view if there is a place within 
> its immediate scope where the full view of the parent type is 
> visible. Or something like that. Gotta worry about the effect 
> on other rules that depend on partial views, though (should 
> rep. clauses be illegal on such a type until the private part??? Etc.)

I agree that we need an AI.

My initial reaction when Randy asked that question in private email was,
of course this type has a partial view: at the place of its declaration
you don't know everything about it, and it's only in the private part that
you find out what the type really is.  So one hopes that, in the visible
part, the type is considered composite (last sentence of 3.2(4.1/2)) even
if the full view turns out to be an elementary type.

On second thoughts it is really a strange partial view, though, because it
doesn't "require completion" (in the sense of 3.11.1(1/1)) so it is
"completely defined" at birth (see 3.11.1(8)).  I wouldn't be surprised if
some rules in the RM were written with the (apparently incorrect)
assumption that "is a partial view" implies "is not completely defined".

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

From: Steven W Baird
Sent: Thursday, June 21, 2007  5:10 PM

There seems to be a contract-model problem with 3.10.2(27.2/2)
in the case of a generic formal discriminated type as seen from 
within the generic body.

This problem allows the construction of an access value which
designates an unconstrained view of a constrained object.

This in turn allows, among other things, assigning a jumbo value
to a not-so-jumbo object; things go downhill rapidly from there.

Consider this example:

  procedure Foo  is
    subtype Index is Integer range 0 .. 255;
    Smaller_Index : constant Index := 10;
    Larger_Index  : constant Index := 20;

    generic
        type T1 (D : Index) is private;
    package G is
        type Ref is access all T1;
        Smaller : aliased T1 (Smaller_Index);
        Ptr     : Ref;
    end G;

    package body G is
    begin
        Ptr := Smaller'Access;
    end G;

    package Pkg is
        type T2 is private;
    private
        type T2 (D : Index := 100) is
            record
                F : String (1 .. D);
            end record;

       package I is new G (T2);
    end Pkg;

    package body Pkg is
        Larger : T2 (Larger_Index);
    begin
        I.Ptr.all := Larger;
    end Pkg;

  begin
    ...;
  end Foo;

An assume-the-worst rule seems to be needed. For purposes of checking
3.10.2(27.2/2) within a generic body, it should be assumed that any 
untagged
formal discriminated type of the generic has a constrained partial view.

This would cause the preceding example to be rejected.

If this compile-time check is viewed as being too conservative, the 
problem
could also be solved via a new runtime check (or even a post-compilation
check). The compile-time solution seems preferable.

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

From: Tucker Taft
Sent: Thursday, June 21, 2007  6:08 PM

Alternatively, we could say that objects designated by values
of type "Ref" are constrained by their initial value.  But
if we do that, we will also have to disallow converting values of
type Ref to access types that designate objects that are *not*
constrained by their initial value.  Your solution is probably
cleaner, and avoids the question of what to do if you had
a formal access type declared similarly to Ref.

I would presume that the implementer of the generic could
move Smaller'Access into the spec, and then get instantiation-time
checking rather than having the generic body rejected.

I think this means we need the usual blather that
states that 3.10.2(27.2) is checked in the private
part of an instance, plus something like:

     For the purposes of this check in a generic body,
     an untagged formal private type is presumed to
     have a constrained partial view.

I don't think we want to restrict ourselves to
"discriminated" formals, since "(<>)" indicates
the formal is indefinite without making it
"discriminated."  But perhaps it is irrelevant
since you can't create a non-matching subtype
in that case.

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

From: Steven W Baird
Sent: Friday, June 22, 2007  2:50 PM

This sounds good except for one detail: the rule
should not be restricted to formal private types.
Formal derived types need to be included as well
because the "has a constrained partial view" property
is not preserved by derivation.

Consider the following variation on the original example:

  procedure Foo2 is
    subtype Index is Integer range 0 .. 255;
    Smaller_Index : constant Index := 10;
    Larger_Index  : constant Index := 20;

    type Has_No_Constrained_Partial_View (D : Index := 100) is
        record
            F : String (1 .. D);
        end record;

    generic
        type T1 is new Has_No_Constrained_Partial_View;
    package G is
        type Ref is access all T1;
        Smaller : aliased T1 (Smaller_Index);
        Ptr     : Ref;
    end G;

    package body G is
    begin
        Ptr := Smaller'Access;
    end G;

    package Pkg is
        type Has_A_Constrained_Partial_View is private;
    private
        type Has_A_Constrained_Partial_View is
           new Has_No_Constrained_Partial_View;

        package I is new G (Has_A_Constrained_Partial_View);
    end Pkg;

    package body Pkg is
        Larger : Has_A_Constrained_Partial_View (Larger_Index);
    begin
        I.Ptr.all := Larger;
    end Pkg;
  begin
    ...;
  end Foo2;

I'd certainly agree that this is, to quote Randy's recent
description, "another Baird anomaly that no one in their
right mind would ever try to use", but we should still
get the definition right.

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

From: Stephen W. Baird [private thread]
Date: Monday, July 16, 2007  2:36 PM

Here  is an example to add to AI05-0041.
This is an unconstrained-view-of-a-constrained-variable problem.
Should this example compile successfully?
If so, then what should happen when it executes?
--------
  procedure Derived_Ops_With_Access_Params is 
    subtype Index is Integer range 0 .. 100; 
    package Pkg1 is 
        type T1 is private; 
    private 
        type T1 (Length : Index := 50) is 
            record 
                F : String (1 .. Length); 
            end record; 
        procedure Proc (X : access T1); 
        package Pkg2 is 
            type T2 is new T1; 
        end Pkg2; 
    end Pkg1; 
    package body Pkg1 is 
        procedure Proc (X : access T1) is 
        begin 
            X.all := (Index'Last, (others => Character'First));
        end Proc; 
        package body Pkg2 is 
            type Ref is access T2; 
            Ptr : Ref := new T2; 
            X2  : T2 renames Ptr.all;  -- Is X2 constrained?
        begin 
            Proc (X2'Access); 
        end Pkg2; 
    end Pkg1; 
 begin 
    null; 
end Derived_Ops_With_Access_Params; 

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

From: Randy Brukardt
Date: Monday, July 16, 2007  3:46 PM

I'm still getting over my recent bout of pneumonia, so I might not be
making sense, but I don't see any (new) issue here. X2 should be whatever
a similar X1 would be (if you did the same sequence of declarations for T1).
[Unless you are claiming that is wrong too, in which case I wouldn't confuse
it with the derived case. But I don't *think* that is what you are saying.]

So, I would like to know what this example is supposed to illustrate that
is not covered by the AI [else I have no idea of what to add to the AI].
Or, more generally, what's your point? (My brain is not able to guess right now.)

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

From: Stephen W. Baird
Date: Monday, July 16, 2007  6:04 PM

What's new here is the interaction with parameters of anonymous access 
types.

You have an untagged unconstrained definite record type T1 which has a
primitive operation with an "access T1" parameter. You declare a derived
type T2, which is derived from T1. The two types disagree with respect to 
the "has a constrained partial view" property; in particular, T1 has the 
property and T2 does not.

This is a recipe for trouble.

When you call the derived subprogram, you can end up passing a reference
to a constrained object to a subprogram which is expecting a reference to
an unconstrained object (and which might assign a larger value to the
designated object than it is capable of holding).

Pkg1.Proc has a parameter X of type access T1.
Since T1 has a constrained partial view, this means that
X  designates an unconstrained object (ignoring the X=null case).

So there is no need for any checks in Pkg1.Proc  when it assigns a
big value to X.all.

On the other hand, type T2 lacks a constrained partial view, so
that allocated objects of type T2 are constrained.

Thus, X2 is constrained.

Note that the procedure call at the center of this whole mess,
   Proc (X2'Access);
is a call to the derived subprogram Pkg2.Proc, not to Pkg1.Proc.

Does this clarify matters?

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

From: Randy Brukardt
Date: Monday, July 16, 2007  6:45 PM

> What's new here is the interaction with parameters of anonymous access 
> types
> 
> You have an untagged unconstrained definite record type T1 which has a
> primitive operation with an "access T1" parameter. You declare a derived
> type T2, which is derived from T1. The two types disagree with respect to the
> "has a constrained partial view" property; in particular, T1 has the 
> property and T2 does not.

But this is the point of the AI: T1 and T2 *cannot* disagree on this property,
or all heck breaks loose. The original example has similar problems where you
can get nonsense results because the language isn't clear whether T2 has a
"constrained partial view". (I *do not* agree with you that it is clear that
it does not have this property; derived types inherit properties, and in the
case of child units, they have to inherit partial views as well or even Ada 95
is screwed up. This just seems to me to be a case where the wording is
insufficiently clear...)

> This is a recipe for trouble.

Yes, of course, but as I said, that is the point of the original AI. There
doesn't seem to be anything new here, other than another example of the problems
caused if T2 does not have a "constrained partial view".

> When you call the derived subprogram, you can end up passing a reference
> to a constrained object to a subprogram which is expecting a reference to
> an unconstrained object (and which might assign a larger value to the
> designated object than it is capable of holding).
> 
> Pkg1.Proc has a parameter X of type access T1.
> Since T1 has a constrained partial view, this means that
> X  designates an unconstrained object (ignoring the X=null case).
> 
> So there is no need for any checks in Pkg1.Proc  when it assigns a
> big value to X.all.
> 
> On the other hand, type T2 lacks a constrained partial view, so
> that allocated objects of type T2 are constrained.

T2 cannot "lack a constrained partial view", or there is all manner of trouble
(see the examples in the original AI). I agree there is a bug here, but it is
the same one we're already talking about.
 
> Thus, X2 is constrained.
> 
> Note that the procedure call at the center of this whole mess,
>    Proc (X2'Access);
> is a call to the derived subprogram Pkg2.Proc, not to Pkg1.Proc.
> 
> Does this clarify matters?

Yes, but I'm still confused as to why you think there is anything important
different about this example from the one in the AI. The whole point of the
AI is that types like T2 need to trigger the "constrained partial view" rules,
or all kinds of anomolies are possible.

I can believe that the AI doesn't say that very clearly, but I still don't
know what is missing from the AI. Your original note claimed that this needed
to be added to AI-41, and I still don't see why (other than in the !appendix
as another curiousity). Parameter passing into derived subprograms (with any
kind of parameter!) is why you get anomolies here. And in any case, there is
no point of loading AIs down with dozens of examples; the only issue is to
illustrate the problem. The original examples seem to do that just fine. What
(if anything) am I missing??

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

From: Pascal Leroy
Date: Tuesday, July 17, 2007  2:07 AM

Well, I am the one who suggested to Steve that he send this example to
you.  It took me some time to figure out that his example was actually
similar to the one in AI05-0041.  What I would like to see is a blurb in
the discussion saying "while the original example involved a child unit,
it is possible to run into the same problem with a nested package".  I
think this is worth pointing out because, while children and nested
packages have analogies, the differences in visibility cause derived
subprograms to pop up at different places and they don't always have the
same problems.

If you feel strongly otherwise I am not going to fight.  Incidentally, I
agree with you (and disagree with Steve): type T2 does have a partial view
for the purpose of this rule.  Note that we might not want to call it a
partial view, though, because it would cause innumerable other rules to
kick in.

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

From: Stephen W. Baird
Date: Tuesday, July 17, 2007  3:30 PM

Randy - You are right, using anonymous access parameters doesn't
really change this into a new problem.

Am I right in thinking that the presence or absence of an explicit
partial view for a derived type should always be irrelevant for
purposes of determining whether an allocated object is constrained?

I understand that the AI hasn't been written yet; I'm asking about
your understanding of the intent of the AI.

I'm interested in the case where the parent type lacks a partial
view and the derived type has one - the opposite of the case that
is illustrated in the AI.

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

From: Randy Brukardt
Date: Tuesday, July 17, 2007  4:40 PM

> Am I right in thinking that the presence or absence of an explicit
> partial view for a derived type should always be irrelevant for
> purposes of determining whether an allocated object is constrained? 

I'm not sure. I'm pretty sure that that is the case when the derived type
does not have a partial view. But...

> I understand that the AI hasn't been written yet; I'm asking about
> your understanding of the intent of the AI.

I'm not sure I have one. I have an understanding of the problem, not
so much of the solutions. I'm rather counting on Tucker to make it all
better... ;-)

> I'm interested in the case where the parent type lacks a partial
> view and the derived type has one - the opposite of the case that
> is illustrated in the AI.

I don't think that you can ignore the partial view, if there is one, on
the derived type. Otherwise, you can reintroduce the original problem.

    package P1 is
        type T1 (D : Integer := 10) is ...
    end P1;

    with P1;
    package P2 is
        type T2 is private;
    private
        type T2 is new T1;
    end P2;

The full view of T2 has defaulted discriminants, and one would hope that
allocated objects of T2 would be unconstrained (else we haven't fixed
anything with these rules). There shouldn't be a difference semantically
between the T2 given here and "type T2 (D : Integer := 0) is ...".

So I think it does matter. What's even messier is if you add a partial view
to T1 in the above example:

    package P1 is
        type T1 (D : Integer := 10) is private;
    private 
        type T1 (D : Integer := 10) is ...
    end P1;

    with P1;
    package P2 is
        type T2 is private;
    private
        type T2 is new T1;
    end P2;

Now T2 seems to have two partial views, one constrained and one
unconstrained. Yikes!

Oh, what a tangled web we weave...

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

From: Stephen W. Baird
Date: Tuesday, July 17, 2007  6:12 PM

This sounds desirable, but I'm worried about the reverse problem where
thinking (statically) that allocated objects are constrained
when (dynamically) they really aren't allows us to get in trouble.

I'm thinking of something like a rename of a discriminant-dependent 
component of an allocated object within a derivable subprogram.

On the other hand, perhaps 3.7.2(4) is broad enough to cover any such 
problems.

I'll think about it.

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

From: Randy Brukardt
Date: Tuesday, July 17, 2007  6:36 PM

> This sounds desirable, but I'm worried about the reverse problem where
> thinking (statically) that allocated objects are constrained
> when (dynamically) they really aren't allows us to get in trouble.

Is that possible? It seems that if an object of a type ought to be
allocated unconstrained because of some view, then it should be
allocated unconstrained (and everyone else should assume that).

> I'm thinking of something like a rename of a discriminant-dependent component
> of an allocated object within a derivable subprogram.

Humm.

> On the other hand, perhaps 3.7.2(4) is broad enough to cover any such 
> problems.

Might be. It would seem to always apply to parameters (and when it doesn't,
the new rule added by AI-0008 does).
 
> I'll think about it.

That scares me more than your original question. ;-)

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

From: Pascal Leroy
Date: Wednesday, July 18, 2007  1:50 AM

> Now T2 seems to have two partial views, one constrained and 
> one unconstrained. Yikes!

From these examples, it seems to me that 3.7.1(7/2) should say something
like:

"... if the designated type has an ancestor which has a partial view that
is constrained...".

In other words, if there is a type to which you can convert that is
private and doesn't expose defaulted discriminants, then the allocated
objects are effectively unconstrained, and you don't want to be able to
write an access constraint.

It this fix works, it is much simpler than changing the meaning of
"partial view".

PS: I'm sure that Tuck won't like the wording above and will change it to
something that reads better.

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

From: Stephen W Baird
Date: Wednesday, July 18, 2007  12:27 PM

> From these examples, it seems to me that 3.7.1(7/2) should say something
> like:
> 
> "... if the designated type has an ancestor which has a partial view that
> is constrained...".

This certainly sounds like an improvement on the current wording.

As I mentioned to Randy, I am a little concerned that there may be problems
in the opposite direction: 

> ... I'm worried about the reverse problem where
> thinking (statically) that allocated objects are constrained
> when (dynamically) they really aren't allows us to get in trouble.
> 
> I'm thinking of something like a rename of a discriminant-dependent component
> of an allocated object within a derivable subprogram.
> 
> On the other hand, perhaps 3.7.2(4) is broad enough to cover any 
> such problems.

I have not been able to construct any problems which 3.7.2(4) doesn't cover;
on the other hand, relying on an erroneous execution rule isn't entirely
satisfactory.

As I mentioned to Pascal, there are also problems in this area with
generic formal derived types (which can be solved with an assume-the-worst
rule, or perhaps simply by invoking 3.7.2(4)):

with Text_Io;
procedure Constrained_By_Initial_Value is
   type T1 (Is_Float : Boolean := False) is
      record
         case Is_Float is
            when False =>
               Int_Val : Integer;
            when True =>
               Float_Val : Float;
         end case;
      end record;

   generic
      type D is new T1;
   package G is
      type Ref is access D;
      Ptr : Ref := new D;
      X : D renames Ptr.all;

      function Get return Integer;
   end G;

   package body G is
      Body_Rename : Integer renames X.Int_Val;

      function Get return Integer is
      begin
         return Body_Rename;
      end Get;
   end G;

   package Pkg is
      type T2 is private;
   private
      type T2 is new T1;
      package I is new G (T2);
   end Pkg;

   package body Pkg is
   begin
      I.X := (Is_Float => True, Float_Val => 1234.5);
      -- at this point, I.Body_Rename is a dangling rename
      Text_Io.Put_Line (Integer'Image (I.Get));
   end Pkg;

begin
   null;
end Constrained_By_Initial_Value;

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

From: Randy Brukardt
Date: Wednesday, July 25, 2007  7:14 PM

...
>I have not been able to construct any problems which 3.7.2(4) doesn't cover;
>on the other hand, relying on an erroneous execution rule isn't entirely
>satisfactory.

I agree. But we've already made massive changes to this area in AI05-0008. We
might as well tweak those changes enough to cover this properly. I've done that
in /02 of this AI.

>As I mentioned to Pascal, there are also problems in this area with
>generic formal derived types (which can be solved with an assume-the-worst
>rule, or perhaps simply by invoking 3.7.2(4)):

[This example came through in HTML, and that stripped all of the indentation...]

...
>generic
>type D is new T1;
>package G is
>type Ref is access D;
>Ptr : Ref := new D;
>X : D renames Ptr.all;
...
>
>package body G is
>Body_Rename : Integer renames X.Int_Val;

This is illegal with a tweaking of the existing (AI05-0008) assume-the-worst rule
for renames ("known to be constrained"). We may need to discuss if this tweaking
is too draconian, but I doubt it personally.

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

From: Tucker Taft
Date: Monday, February 4, 2008  11:32 PM

Here is the last AI I'll be submitting before the meeting.
It attempts to follow through on the changes specified in the
minutes.  I was supposed to "try to figure out what
the rules ought to be" but I'm not sure I still
remember all of the issues.  This may take another
round of discussion. [This is version /04 - ED]

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

From: Randy Brukardt
Date: Tuesday, February 5, 2008  12:24 AM

> Here is the last AI I'll be submitting before the meeting.

Good, 'cause the deadline was 7 hours ago, and I'm about to upload
the AI package for the meeting to the web site.

> It attempts to follow through on the changes specified in the
> minutes.  I was supposed to "try to figure out what
> the rules ought to be" but I'm not sure I still
> remember all of the issues.  This may take another
> round of discussion.

My recollection was that you and Bob wanted to except (known) tagged
types from *all* of the rules about constrained partial views. Not just
for generic formal types. Maybe that isn't possible for regular tagged
types, but it would be helpful to have some proof of that.

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

From: Randy Brukardt
Date: Tuesday, February 5, 2008  12:48 AM

> Here is the last AI I'll be submitting before the meeting.

I see you were supposed to combine AI-61 into AI-41. So neither of them are
really done. Sigh.

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

From: Tucker Taft
Date: Tuesday, February 5, 2008  2:25 PM

I have attached a version 5 of AI-41 that incorporates AI-61,
in case we still want to tackle it at the meeting.  And
yes I know this is after the deadline...

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

From: Randy Brukardt
Date: Tuesday, February 5, 2008  7:35 PM

A couple of technical comments:

Humm. "Known to be constrained" is just a definition; it does not include
the Legality Rules boilerplate (about being enforced in the private part).
Thus, you shouldn't delete that from 3.7.1(7/2) (the other wording can go,
of course). The same is true for the radical proposal for 3.10.2(27.2/2) -
it would still be necessary there (but see below).

In my original writeup of AI-61, I had the following editor's note about the
boilerplate:

[Editor's note: 3.10.2(28/2) already includes the boilerplate about the
private part. I have to wonder if it would be better to have this apply to
*all* of the requirements on 'Access. (Do we really want any of these unchecked
in private parts? For instance, we appear to allow an access-to-variable type
to point at a constant in a private part.) If we make this change, we should
delete the last line of 3.10.2(28/2) and insert the following before 3.10.2(29):
   In addition to the places where Legality Rules normally apply (see 12.3), these
   requirements apply also in the private part of an instance of a generic unit.
end Editor's note.]

In particular, we'll have added the boilerplate to 3.10.2(26) [by
AI05-0008], to 3.10.2(27) [by AI05-0041], and it has always applied to
3.10.2(28). But it doesn't seem to apply to 3.10.2(25), and it seems like it
should.

If that's the case, it seems bizarre to give the same sentence in four
consecutive bullets; it would be better to factor it out (perhaps even give
it it's own bullet). Something like:

* In addition to the places where Legality Rules normally apply (see 12.3),
these four requirements apply also in the private part of an instance of a
generic unit.

and then take it out of 3.10.2(26), 3.10.2(27.2), and 3.10.2(28).
["requirements" echos the lead-in in 3.10.2(24)]

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

From: Randy Brukardt
Date: Friday, February 22, 2008  9:17 PM

The wording we approved in St. Pete Beach seems to not quite cover all of
the cases. Or I've missed something.

The old wording of 3.7.1(7/2) has:

In a generic body, this rule is checked presuming all formal access types
of the generic might be general access types, and all untagged
discriminated formal types of the generic might have default_expressions
for their discriminants.

This text was deleted; the idea being that it was folded into the definition
of "known to be constrained".

The new definition of "known to be constrained" says:

For the purposes of determining within a generic body whether an
object is known to be constrained:

* if a subtype is a descendant of an untagged generic formal
derived type, and the subtype is not an unconstrained array
subtype, it is not considered indefinite and is considered to
have a constrained partial view;

* if a subtype is a descendant of a formal access type, it is not
considered pool-specific.

This wording makes a special case for untagged generic formal derived types,
and it covers the cases mentioned by the old wording (although rather
differently).

But "untagged discriminated formal types" include untagged generic formal
private types. The new wording doesn't seem to include them. I think they
need to be included; indeed, the question (2) gives an example that includes
a generic formal private type. So I don't think the wording as proposed
actually fixes question (2).

This is easily fixed (I think) by adding "or private" to the wording:

* if a subtype is a descendant of an untagged generic formal
derived {or private} type, and the subtype is not an unconstrained array
subtype, it is not considered indefinite and is considered to
have a constrained partial view;

But perhaps there is a better wording. An alternative would be:

* if a subtype is a descendant of an untagged generic formal
composite type, and the subtype is not an unconstrained array
subtype, it is not considered indefinite and is considered to
have a constrained partial view;

since any interesting type would need to be composite. We don't need this to
apply to a generic formal derived integer type.

What wording should be used? Other suggestions welcome.

Does anyone want to reconsider this AI? In the absence of a request for
reconsideration, I'll just mention this topic in the minutes in an "after
the meeting" box in the minutes.

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

From: Tucker Taft
Date: Monday, February 25, 2008  7:11 AM

I guess I would go with "derived or private" since
"generic composite" type is not a term we have
used elsewhere, as far as I know.

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

From: Randy Brukardt
Date: Monday, February 225 2008  1:33 PM

You're right. In fact, the same AI uses "generic formal private or
derived type" in the wording of 3.10.2(27.2/2). So that's what we should
use.

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

Questions? Ask the ACAA Technical Agent