Version 1.5 of ais/ai-00311.txt

Unformatted version of ais/ai-00311.txt version 1.5
Other versions for file ais/ai-00311.txt

!standard 4.9 (31)          04-12-02 AI95-00311/03
!standard 4.9.1 (01)
!class binding interpretation 02-09-26
!status Amendment 200Y 04-12-02
!status ARG Approved 9-0-1 04-11-21
!status work item 02-09-26
!status received 02-08-28
!qualifier Omission
!priority Low
!difficulty Easy
!subject Static matching of scalar formal subtypes
!summary
If T1 is a generic formal scalar type, T1 does not statically match T1'Base.
!question
Is the following legal?
generic type T1 is range <>; package Pak1 is procedure P1 (Left : T1); end Pak1;
package body Pak1 is procedure P1 (Left : T1'Base) is -- Legal? (No.) begin null; end P1; end Pak1;
If T1 is considered to have a null constraint, then the subtypes T1 and T1'Base statically match and the above example is legal; if T1's constraint is nonstatic, then the constraints do not statically match by 4.9.1(2), and thus the example is illegal.
!recommendation
(See summary.)
!wording
Add after 4.9(31):
In any case, the constraint of the first subtype of a scalar formal type is neither static nor null.
Replace 4.9.1(1) by:
A constraint statically matches another constraint if:
o both are null constraints; o both are static and have equal corresponding bounds or discriminant values; o both are nonstatic and result from the same elaboration of a constraint of
a subtype_indication or the same evaluation of a range of a discrete_subtype_definition; or
o both are nonstatic and both come from the same formal_type_declaration.
!discussion
Intuitively, T1's constraint should be nonstatic by definition, since it is not known what the actual constraint will be and the actual subtype can have any legal constraint whatsoever. However, the standard does not say this.
Note that the wording is intended to allow the following:
generic type T1 is range <>; package Pak1 is subtype S1 is T1; procedure P1 (Left : T1); end Pak1;
package body Pak1 is procedure P1 (Left : S1) is -- Legal begin null; end P1; end Pak1;
That's because the constraints on S1 and T1 "come from the same formal_type_declaration".
!corrigendum 4.9(31)
Insert after the paragraph:
the new paragraph:
In any case, the constraint of the first subtype of a scalar formal type is neither static nor null.
!corrigendum 4.9.1(1)
Replace the paragraph:
A constraint statically matches another constraint if both are null constraints, both are static and have equal corresponding bounds or discriminant values, or both are nonstatic and result from the same elaboration of a constraint of a subtype_indication or the same evaluation of a range of a discrete_subtype_definition.
by:
A constraint statically matches another constraint if:
!ACATS test
A B-Test should possibly be created to check this case.
!appendix

!topic Constraint of formal scalar type
!reference RM95 12.5.2, 4.9(27), 4.9.1(2), 6.3(4), 6.3.1(17-18)
!from Adam Beneschan 08-30-02
!discussion

In this fragment:

    generic
        type T1 is range <>;
    package pak1 is ...

What is the status of T1's constraint?  Is it null, static, nonstatic,
unknown, or what?

The reason this matters is because I can't figure out whether this is
legal:

    generic
        type T1 is range <>;
    package Pak1 is
        procedure P1 (Left : T1);
    end Pak1;

    package body Pak1 is
        procedure P1 (Left : T1'Base) is
        begin
            null;
        end P1;
    end Pak1;

If T1 is considered to have a null constraint, then the subtypes T1
and T1'Base statically match and the above example is legal; if T1's
constraint is nonstatic, then I believe the constraints to not
statically match by 4.9.1(2), and thus the example is illegal.

Intuitively, it seems to me that T1's constraint should be nonstatic
by definition, since it is not known what the actual constraint will
be and the actual subtype can have any legal constraint whatsoever.
However, I can't find support in the RM for this.  Perhaps something
should be added to 4.9 or 4.9.1 to indicate that the constraint on a
generic formal first subtype is considered to be nonstatic?

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

From: Robert A Duff
Sent: Friday, September 6, 2002  4:36 PM

> The reason this matters is because I can't figure out whether this is
> legal:

This should be illegal, IMHO, since the actual for T1 might impose a
constraint, which makes the body a lie.  Whether the RM says so, I don't
know.  Can I invoke Robert's Rule, which says that no matter what the RM
says, it "really" says what we mean?  ;-)

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

From: Tucker Taft
Sent: Friday, September 6, 2002  9:18 PM

>If T1 is considered to have a null constraint, then the subtypes T1
>and T1'Base statically match and the above example is legal; if T1's
>constraint is nonstatic, then I believe the constraints to not
>statically match by 4.9.1(2), and thus the example is illegal.

Neither T1 nor T1'Base is static, according to 4.9(25-26).  They don't
match because they aren't the result of the elaboration of the same
constraint or range (cf. 4.9.1(1)).

>Intuitively, it seems to me that T1's constraint should be nonstatic
>by definition, since it is not known what the actual constraint will
>be and the actual subtype can have any legal constraint whatsoever.
>However, I can't find support in the RM for this.  Perhaps something
>should be added to 4.9 or 4.9.1 to indicate that the constraint on a
>generic formal first subtype is considered to be nonstatic?

I don't see any hole here.

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

From: Adam Beneschan
Sent: Monday, September 9, 2002  1:45 PM

It still looks like a hole to me.  The important thing here isn't
whether the subtypes are static, but whether the subtypes statically
match (6.3.1(17)).  So 4.9(26) isn't relevant here.

4.9(25) isn't relevant either.  It  says "A static range is a _range_
whose bounds are static expressions ...".  The definition of a _range_
in 3.5(3) is either two expressions with .. in between, or a 'Range
attribute; "<>" is not a _range_, by this definition, and thus 4.9(25)
doesn't apply.

The key question here, I believe, is: what, exactly, *is* the
constraint on T1 (particularly for the purposes of applying 4.9.1(1))?
"range <>" doesn't meet the definition of a _constraint_ given in
3.2.2(5), so it doesn't appear to be technically correct to call
"range <>" a constraint; but if this isn't a constraint, then the
generic formal T1 has a null constraint (since I can't find anything
in the RM that decrees otherwise), and thus it would seem to say that
T1 and T1'Base do statically match, since their constraints are both
null constraints and thus match by 4.9.1(1).

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

From: Tucker Taft
Sent: Monday, September 9, 2002  3:19 PM

In general, the properties of a formal (sub)type
are determined by the range of potential
properties of the allowed actual subtypes.
Given that the actual subtype might or might not be
constrained, it is not determined at compile-time
whether a formal scalar type is constrained or unconstrained.
I realize that is a bit of an uncomfortable position to be in,
but it doesn't actually affect legality except in the case
of statically matching subtypes, as you point out.  The
RM explicitly says the base range is non-static, and we
know that T1'Base is unconstrained, but T1 itself might
or might not be constrained.

It would seem there are two possibilities, either we
assume the "best" in the spec and then recheck upon
instantiation, or we say that they clearly don't
statically match, even though they might dynamically
match.

So I guess I agree with you now that there is a hole,
and we need to specify which possibility is to be
chosen.  It seems clear that in the body, the two
subtypes don't statically match.  But in the spec,
there seems some case for saying that the static
matching check is deferred until instantiation time.
With my implementation hat on I will have to say "yuck"... ;-)

Note that a similar situation arises with formal access
subtypes, where it is not known at compile time whether
the actual will be constrained or unconstrained.  However,
since there is no 'Base attribute, this particular problem
doesn't arise.  However, since it is illegal to apply a
constraint to an already-constrained access subtype, the
legality of applying a constraint would seem to depend on
an unknown-at-compile-time characteristic, bringing up
the same assume-the-best vs. assume-the-worst situation.
I wonder how we have handled that case?  It sounds familiar...

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

From: Randy Brukardt
Sent: Thursday, September 26, 2002  9:56 PM

Tucker wrote:

> So I guess I agree with you now that there is a hole,
> and we need to specify which possibility is to be
> chosen.  It seems clear that in the body, the two
> subtypes don't statically match.  But in the spec,
> there seems some case for saying that the static
> matching check is deferred until instantiation time.
> With my implementation hat on I will have to say "yuck"... ;-)

I'm strongly in favor of this always not matching, unless someone can find an
example where matching would be valuable in practice. Certainly Adam's example
isn't it. :-)

> Note that a similar situation arises with formal access
> subtypes, where it is not known at compile time whether
> the actual will be constrained or unconstrained.  However,
> since there is no 'Base attribute, this particular problem
> doesn't arise.  However, since it is illegal to apply a
> constraint to an already-constrained access subtype, the
> legality of applying a constraint would seem to depend on
> an unknown-at-compile-time characteristic, bringing up
> the same assume-the-best vs. assume-the-worst situation.
> I wonder how we have handled that case?  It sounds familiar...

That's AI-34, which is a confirmation. (Wow!) It says that the check is not
performed in the body of the generic, because legality rules don't apply there.
I suppose the check is performed in the private part on instantiation, but no
check is ever done in the body. Thus, its possible to doubly constrain an
access subtype; supposedly the meaning is that the original constraint is
dropped. There is no runtime check, either.

I'm *certain* we don't want to follow this model here!

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

From: Tucker Taft
Sent: Monday, October 6, 2003  12:02 PM

I think we discussed this once, but it just
came up in a compiler problem I was diagnosing,
and I can't remember the resolution.

4.9 (static expressions, etc.) talks about
"descendants of a formal scalar type" which does
not include a formal derived type whose ancestor
is scalar.  I think that is intentional, in general,
since the base subtype of a scalar formal derived
type is known, and will generally be static (since
all base subtypes are static, except for
those of "formal scalar types").

Now the question comes up is whether the
*constraint* of a scalar formal derived type
is static, and just what it is.  It seems that
it should be considered always nonstatic, since
12.5.1 only requires that the actual be statically
*compatible* with the ancestor.  This implies that
the actual subtype range need not be the same as
that of the ancestor; it can be a narrower range.

Hence, given a formal derived type:

   generic
     type T is new Positive;
     ...

   T'Base is a static unconstrained subtype
   T      is a nonstatic constrained subtype

   T'Base'First is a static expression, = Positive'Base'First
   T'First is nonstatic, but is known to be >= Positive'First

Does that sound right?

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

From: Gary Dismukes
Sent: Monday, October 6, 2003  12:10 PM

Yes, that looks exactly right.

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

From: Robert A. Duff
Sent: Monday, October 6, 2003  1:40 PM

I agree.

If T'First were static, then what would its value be?
Surely it can't be 1, because the Actual_Subtype'First
might not be 1.

And if T'First is nonstatic, then surely T is not a static subtype!

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

From: Randy Brukardt
Sent: Monday, October 6, 2003  11:13 PM

I believe this is AI-311, which was on the agenda (Pascal had updated it),
but not discussed. Please check it to see if it handles the case you're
worried about.

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

From: Tucker Taft
Sent: Tuesday, October 7, 2003  5:11 AM

Now here is my next question.  What about
static compatibility...:

     generic
        type T1 is new Positive;
     package Gen1 is ...;

     generic
        type T2 is new Positive;
     package Gen2 is
        package Inst1 is new Gen1(T2);  -- legal?
     end Gen2;

Is this legal?  It would be nice, but the
rules for static compatibility, as written, would
probably say it was *not* legal, since T2 is not
statically compatible with Positive, according
to my reading of 4.9.1, since T2 has a non-static
constraint (based on the earlier messages), and a non-static
constraint can only be statically compatible if it
statically matches the other constraint, and we know the
constraint of T2 is not necessarily Positive'Range.

On the other hand, we know that any actual type for T2
must be statically compatible with T2's ancestor,
i.e. Positive, so it seems like T2 ought to be
a special case.  Namely, the constraint of
a formal derived subtype should be considered statically
compatible with its ancestor subtype (and anything
that statically matches its ancestor subtype).

So I think we have two holes: we need to specify that
the constraint of a formal derived type is *not* static,
but that it *is* statically compatible with its
ancestor.  Alternatively, we could express it
recursively, saying that the constraint of a formal
derived subtype is statically compatible if the constraint
of its ancestor subtype is statically compatible (that
would be more flexible).  The same would *not* apply
for static matching, presumably.

By the way, this came up in real code written
by a REAL programmer (guess who ... his initials
are R.A.D. ;-).

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

From: Robert I. Eachus
Sent: Tuesday, October 7, 2003  8:11 AM

> Is this legal?  It would be nice, but the
> rules for static compatibility, as written, would
> probably say it was *not* legal...

I think this comes under the Robert Dewar rule that any silly ramification of
the rules is wrong.  Can T2 be statically compatible with Positive on line 6,
and not statically compatible with Positive on line 8?  That seems to stretch
the definition of STATICALLY compatible completely out of shape.  I'm not all
that sure that I like the implementation implications of such a rule in
general, but I think that this is the only special case that has to be dealt
with--a legality check in the defining instance of a derived (sub)type.  So
subsequent checks can be made the way Tucker envisions.  (A generic formal type
must be statically compatible with its parent subtype, so in later uses of the
type, it is okay for the formal type to be used where it needs to be statically
compatible with its original parent.)

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

From: Tucker Taft
Sent: Tuesday, October 7, 2003  11:06 AM

Unfortunately, 311 doesn't really address the whole problem.
It mostly talks about formal scalar types, rather than scalar
formal derived types.  It also doesn't mention static compatibility.
I think the "fix" for static matching looks good for both kinds of
scalar formal types, but we also need a fix to static compatibility.

As mentioned in my earlier note, I suggest we fix static compatibility
by saying that the constraint of a scalar formal derived type is
statically compatible with anything that its parent subtype is
statically compatible with.

We also need to add something to make clear that the constraint
of a scalar formal derived type is not static.

It seems reasonable to add both of these to AI-311.

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

From: Randy Brukardt
Sent: Thursday, December 4, 2003  6:54 PM

I agree about the static compatibility (well, actually I don't agree it is
worth changing this, but certainly the AI doesn't cover it and it is worth
discussion), but I don't have a clue why you think that a scalar formal derived
type could have a static constraint given the wording proposed in the AI.

The AI proposes to add after 4.9(31):

  In any case, the constraint of a generic formal type is neither static nor
  null.

Certainly this covers a scalar formal derived type! This covers ANY generic
formal type.

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

From: Tucker Taft
Sent: Thursday, December 4, 2003  10:06 PM

> The AI proposes to add after 4.9(31):
>
>   In any case, the constraint of a generic formal type is neither static nor
> null.

This seems to be going too far and is gratuitously
upward incompatible.  Why can't the constraint
of a formal array type be static?  For a formal derived
composite type, there seems no problem inheriting the
staticness from the ancestor type.  It is only a formal
derived scalar type that allows the constraints to differ
between the ancestor and the actual, so that is the
one we should be worrying about.

> Certainly this covers a scalar formal derived type! This covers ANY generic
> formal type.

And it shouldn't.

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

From: Randy Brukardt
Sent: Thursday, December 4, 2003  11:15 PM

> This seems to be going too far and is gratuitously
> upward incompatible.  Why can't the constraint
> of a formal array type be static?

I could probably come up with a number of reasons if I cared to think about it,
but I don't right now.

> For a formal derived
> composite type, there seems no problem inheriting the
> staticness from the ancestor type.  It is only a formal
> derived scalar type that allows the constraints to differ
> between the ancestor and the actual, so that is the
> one we should be worrying about.

Huh? The original problem of AI-311 was with a regular generic formal scalar
type. Clearly this has to apply at a minimum to all generic formal types which
are scalar. (That should be generally true in the RM - it's unfortunate that
generic formal xxx type does not include generic derived types which are xxx,
because they are implemented in exactly the same way, and have the same
semantics except for additional operations. Any rule on generic formal xxx
should also apply to generic formal derived xxx types, unless it has to do with
primitive operations.)

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

From: Tucker Taft
Sent: Friday, December 5, 2003  7:06 AM

I wasn't debating that.  I was debating the blanket statement
that *all* formal types, including access and composite
types,  have non-static constraints.  That seems incompatible
and unnecessary.

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


Questions? Ask the ACAA Technical Agent