Version 1.4 of ai05s/ai05-0214-1.txt

Unformatted version of ai05s/ai05-0214-1.txt version 1.4
Other versions for file ai05s/ai05-0214-1.txt

!standard 3.7(9.1/2)          10-11-22 AI05-0214-1/03
!standard 3.7.2(3)
!class amendment 10-06-12
!status work item 10-06-12
!status received 10-06-12
!priority Medium
!difficulty Medium
!subject Default discriminants for limited tagged types
!summary
Discriminants for limited tagged types may have defaults.
!problem
Defaults are not allowed for discriminants of limited tagged types, including task and protected types derived from interfaces.
Ada mainly uses defaults for discriminants to indicate mutability of a type. However, that use obscures the original use for defaults: to provide a value for a discriminant in the "normal" case. If such a default is needed for a limited tagged type, there is no way to get it.
For instance, the priority of a queue object is set by a discriminant. But in many circumstances, the priority isn't important (for instance a system that doesn't use priorities); in that case, having to explicitly provide a priority is a nuisance.
This limitation should be eliminated.
!proposal
(See wording.)
!wording
Modify 3.7(9.1/2):
No default_expressions are permitted in a known_discriminant_part in a declaration of a {nonlimited} tagged type Redundant[or a generic formal type].
Modify 3.7.2(3):
A'Constrained
Yields the value True if A denotes a constant, a value, [or] a constrained variable{, or is known to be constrained}, and False otherwise.
AARM Reason: Objects that are known to be constrained, which include all tagged objects (as nonlimited tagged types cannot have discriminant defaults, and limited tagged objects are immutably limited) always are considered constrained by this attribute to avoid distributed overhead for parameters of limited classwide types, as limited tagged objects may technically be unconstrained if they use defaulted discriminants. Such objects still cannot have their discriminants changed, as assignment is not supported for them, so there is no use for this attribute that would justify the overhead of passing it with all classwide parameters.
!discussion
Discriminants for tagged types do not allow defaults as mutable types cause various semantic problems. However, limited tagged types aren't really mutable; their discriminants cannot be changed after creation as no assignment is allowed. Thus there is no problem allowing defaults for discriminants on limited tagged types.
There is one small glitch. Currently, 'Constrained is True for all tagged objects. This change threatens to change that. Unfortunately, such a change has distributed overhead as parameters of class-wide types would have to assume that there is a future extension that has defaulted discriminants, and thus the value of 'Constrained would have to be passed with the parameter. Since 'Constrained is not useful for limited types, this is pointless.
Thus we define 'Constrained to be True for all tagged objects, regardless of the form of their discriminants. We considered a more consistent rule which would define objects of nonformal limited tagged types to be constrained by their initial value, but it required too many wording changes for a "simple" change.
!example
--!corrigendum A.4.4(3)
!ACATS test
Create an ACATS C-Test(s) to check this feature.
!ASIS
There is no impact on ASIS, but ASIS users may need to take into account the new possibility of getting default discriminants for a limited tagged type.
!appendix

From: Martin Dowie
Date: Friday, May 21, 2010  2:55 AM

[From AI05-0159-1, version /07.]

...
In a number of the PTs, e.g.
"Ada.Containers.Unbounded_Synchronized_Queues", the discriminent takes a default
- is that allowed now?

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

From: Bob Duff
Date: Friday, May 21, 2010  1:29 PM

...

> In a number of the PTs, e.g.
> "Ada.Containers.Unbounded_Synchronized_Queues", the discriminent takes
> a default - is that allowed now?

Good point!  I had forgotten that this type is tagged.
I wonder if we should allow defaulted discriminants on limited types.

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

From: Gary Dismukes
Date: Friday, May 21, 2010  2:31 PM

Hmm, would be nice to relax the restriction in that case (presumably it would be
for immutably limited, not simply limited).

I guess we'd have to restrict nonlimited extensions of limited types (derived
from limited interfaces) from inheriting defaulted discriminants.

I wonder whether there are any dragons lurking (e.g., is there a privacy-
breaking issue for nonlimited derivations from a limited tagged private
extension with defaults on the full type...).

I suppose there's also the potential for maintenance problems if you wanted to
change such a limited type to nonlimited.

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

From: Gary Dismukes
Date: Friday, May 21, 2010  2:43 PM

> Hmm, would be nice to relax the restriction in that case (presumably
> it would be for immutably limited, not simply limited).

Self-correction:

Since Bob was only talking about tagged limited in any case (since that's where
the restriction applies), there was no need for mentioning immutably limited.

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

From: Bob Duff
Date: Friday, May 21, 2010  3:03 PM

> I guess we'd have to restrict nonlimited extensions of limited types
> (derived from limited interfaces) from inheriting defaulted discriminants.

I'm having trouble picturing what you're getting at, here.
Can you give an example (written in Ada instead of English)?

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

From: Gary Dismukes
Date: Friday, May 21, 2010  6:00 PM

> I'm having trouble picturing what you're getting at, here.
> Can you give an example (written in Ada instead of English)?

Well, I think there's not much point in giving an example, because it looks like
the case I was thinking of isn't possible.

I was incorrectly thinking that nonlimited descendants of limited tagged types
were possible whenever there's a limited interface ancestor, when in fact that
can only occur for direct descendants of a limited interface (and of course
interfaces themselves can't have discriminants).

So never mind, and sorry for the noise! :-(

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

From: Randy Brukardt
Date: Friday, May 21, 2010  6:01 PM

> Hmm, would be nice to relax the restriction in that case (presumably
> it would be for immutably limited, not simply limited).

I thought we *did* allow such discriminants on immutably limited types (which
this is), and always have. 3.7(10/3).

Oh, I see, you guys are talking about 3.7(9.1/2) [which originally was
3.7(11)]: "No default_expressions are permitted in a known_discriminant_part in
a declaration of a tagged type [or a generic formal type]."

This whole scheme doesn't work without the default (having to always provide a
priority in a system that doesn't use them would be a massive pain - I have no
idea what the numeric priority of my tasks is or how to find it out...). So we
need to look at an alternative.

The supposed reason for the restriction is so that " that every object of a
tagged type is constrained". I'm not sure that really matters for limited tagged
types: the discriminants can't change after the initial object declaration. Does
anyone care that they are not technically constrained?? (The same holds for any
immutably limited type, I think.) More importantly, would anything in the
language fail if they are not constrained? Functionally it would be the same as
constrained-by-initial-value.

The only thing I can think of that might differ is the value of 'Constrained. We
could even fix that if it was considered a hardship by saying that all
discriminated objects of immutably limited types are
constrained-by-initial-value.

Someone ought to think about this in detail, and propose a relaxation.

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

From: Bob Duff
Date: Friday, May 21, 2010  6:32 PM

> I thought we *did* allow such discriminants on immutably limited types
> (which this is), and always have. 3.7(10/3).

That para has something to do with access discrims, which is not relevant here.

> Oh, I see, you guys are talking about 3.7(9.1/2) [which originally was
> 3.7(11)]: "No default_expressions are permitted in a
> known_discriminant_part in a declaration of a tagged type [or a generic formal type]."

Yes, that's the relevant para.  The "surprise" is that the protected type in
this AI is tagged.  (Of course it is, since it's derived from an interface, but
I missed that.)

> This whole scheme doesn't work without the default (having to always
> provide a priority in a system that doesn't use them would be a
> massive pain - I have no idea what the numeric priority of my tasks is
> or how to find it out...).

Well, if we don't have a default, the obvious ceiling to choose is
System.Priority'Last (i.e. the default I was trying to use). That is, any
non-interrupt-level code should be able to call this thing.

So I think "This whole scheme doesn't work..." is an overstatement, but I agree
it would be convenient to allow defaults here.

>... So we need to look at an alternative.
>
> The supposed reason for the restriction is so that " that every object
> of a tagged type is constrained". I'm not sure that really matters for
> limited tagged types: the discriminants can't change after the initial
> object declaration. Does anyone care that they are not technically constrained??
> (The same holds for any immutably limited type, I think.) More
> importantly, would anything in the language fail if they are not constrained?
> Functionally it would be the same as constrained-by-initial-value.

Right.  During Ada 9X, Tucker and I kept running into all manner of semantic
anomalies caused by tagged objects whose discriminants could be modified (by
whole-object assignment).  So, after much running around in circles, we ended up
deciding to outlaw that case.

It makes some sense: the Tag of an object can never change, and the Tag is sort
of like a discriminant, and we want all discriminants to match (as to whether
they're mutable), which kind of implies that discriminants of tagged types
shouldn't be mutable.

But the situation for immutably LIMITED tagged types is different. The
limitedness means the discriminants are immutable, even if they have defaults.
(Please don't be confused by the two different uses of [im]mutable here!)

That is, for limited types, a default on a discriminant is just a
cigar^H^H^H^H^Hdefault; there's no implication of mutability, so we can allow
defaults in the limited tagged case.

> The only thing I can think of that might differ is the value of
> 'Constrained. We could even fix that if it was considered a hardship
> by saying that all discriminated objects of immutably limited types
> are constrained-by-initial-value.

Shrug.  I guess I suggest we leave 'Constrained well enough alone.  The only
sensible use is to determine at run time whether you can change the discrims of
an [in]out parameter, and for limited, the answer is statically "no".

> Someone ought to think about this in detail, and propose a relaxation.

I think it's simple.  Change this:

    No default_expressions are permitted in a known_discriminant_part in a
    declaration of a tagged type [or a generic formal type].

to be "nonlimited tagged" instead of "tagged".

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

From: Randy Brukardt
Date: Friday, May 21, 2010  6:54 PM

That's easy. But it hasn't passed the Baird test. You know, the one about the
problems with the coextensions of sprouted generics in a limited view. ;-)

Humm. Playing the role of Steve Baird, all incomplete types are considered
limited. A tagged incomplete type is considered tagged. So the above would allow
defaults on a tagged incomplete type, which isn't so good if completed by a
nonlimited type. Humm. I suppose that's not a real problem because either the
completion is illegal (nonlimited tagged with defaults) or the completion
doesn't conform (and is therefore illegal).

I guess I'll let Steve play the role of Steve for now...

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

From: Bob Duff
Date: Friday, May 21, 2010  7:18 PM

> Humm. Playing the role of Steve Baird, all incomplete types are
> considered limited. A tagged incomplete type is considered tagged. So
> the above would allow defaults on a tagged incomplete type, which
> isn't so good if completed by a nonlimited type. Humm. I suppose
> that's not a real problem because either the completion is illegal
> (nonlimited tagged with defaults) or the completion doesn't conform (and is
> therefore illegal).

I pondered all that stuff pretty carefully, and concluded there's no problem.

> I guess I'll let Steve play the role of Steve for now...

Sure, Steve might well out-ponder me.  ;-)

If there's a problem, I'll eat my hat, without cat soup.

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

From: Steve Baird
Date: Friday, May 21, 2010  9:35 PM

I discussed this with Gary and we don't see any language definition problems
here (you certainly want to continue to disallow defaults for all forms of
formal types, but the proposed wording change does that).

It means that build-in-place functions have one new situation to deal with (an
unconstrained component), but I don't think that would be a big deal for most
implementations.

There is one minor point. With no other changes, implementations would have to
add an implicit parameter in order to correctly implement the 'Constrained
attribute for parameters. I think we would want to add a rule defining the
'Constrained attribute to always be true for a limited (or perhaps only
immutably limited) object. Without this, we would have distributed overhead
because the parameter profile (at the implementation level, not the source level
- I'm talking about an implicit parameter here) would have to match up in the
case of overriding where the extension type has defaulted discriminants and the
parent type does not (perhaps the parent type has no discriminants at all).

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

From: Randy Brukardt
Date: Friday, May 21, 2010  10:22 PM

That was what I was thinking about when I mentioned 'Constrained.
Implementing it correctly requires passing the value along with any "in out" or
"out" parameters. I hadn't thought of the distributed overhead part of the
problem, but that is a deal-breaker if not fixed somehow: especially given that
'Constrained is useless for a limited parameter.

What did you think of my idea of declaring that objects of non-formal limited
tagged types are "constrained by their initial value"? They surely are in
practice, in that the discriminants can't be changed ever. That would fix the
problem with 'Constrained (it would always be True for a tagged type, even with
the defaults), as well as your concern about build-in-place. I don't think it
would have any other dynamic effect (because those effects are all on
assignment, which is already illegal).

[I had said "immutably limited", but that doesn't quite work, as not all limited
tagged types are "immutably limited" (although we may decide to fix that, Adam
has complained). Moreover, "immutably limited" would sweep up various untagged
types, which probably would be a bad idea, although maybe there would be no
problem.]

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

From: Steve Baird
Date: Monday, May 24, 2010  4:55 PM

This general approach sounds good.
A similar situation is already handled this way in 4.8(6/3), so this would be
consistent.

I don't think this change would have any effect one way or the other on the
implementation of build-in-place, but that's ok.

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


Questions? Ask the ACAA Technical Agent