!standard 3.3.1(9/2) 10-06-12 AI05-0214-1/01 !standard 3.7(9.1/2) !standard 4.8(6/3) !standard 6.5(5.9/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 such be eliminated. !proposal (See wording.) !wording Modify 3.3.1(9/2): If a composite object declared by an object_declaration has an unconstrained nominal subtype, then if this subtype is indefinite{, is nonformal limited tagged} or the object is constant the actual subtype of this object is constrained. The constraint is determined by the bounds or discriminants (if any) of its initial value; the object is said to be constrained by its initial value. ... Modify 3.7(9.1/2): No default_expressions are permitted in a known_discriminant_part in a declaration of a {nonlimited} tagged type [or a generic formal type]. Modify 4.8(6/3): (As modified by AI05-0041-1) 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 nonformal limited tagged} or there is an ancestor of the designated type that has a constrained a partial view of the designated type that is constrained; otherwise, the created always constrained; if the designated subtype is constrained, then it provides the constraint of the created object; otherwise, the object is constrained by its initial value [(even if the designated subtype is unconstrained with defaults)]. Modify 6.5(5.9/3): (As modified by AI05-0032-1) ... If the nominal subtype is indefinite {or nonformal limited tagged}, the return object is constrained by its initial value. ... !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 objects of nonformal limited tagged types to be constrained by their initial value. (We don't use "immutably limited" as that would be incompatible -- changing the value of 'Constrained in useless changes -- and it does not cover all limited tagged types [although we may decide to fix that.] !example --!corrigendum A.4.4(3) !ACATS test Create an ACATS C-Test(s) to check this feature. !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. **************************************************************** From: Bob Duff Date: Friday, May 21, 2010 1:29 PM **************************************************************** From: Bob Duff Date: Friday, May 21, 2010 1:29 PM **************************************************************** From: Bob Duff Date: Friday, May 21, 2010 1:29 PM **************************************************************** From: Bob Duff Date: Friday, May 21, 2010 1:29 PM **************************************************************** From: Bob Duff Date: Friday, May 21, 2010 1:29 PM ****************************************************************