!standard 13.1(10/4) 20-04-17 AI12-0376-1/01 !class Amendment 20-04-17 !status work item 20-04-17 !status received 20-03-31 !priority Low !difficulty Easy !subject Representation changes finally allowed for untagged derived types !summary An untagged derived type can have a different representation from its parent type even if it has primitive operations, but not if it has by-reference parts. !problem Default_Value is a representation aspect. Therefore, it is not allowed to have different defaults for a derived type and the parent type. This sometimes is a useful capability and it has been used in practice (using a compiler that failed to enforce the requirement). !proposal (See Summary.) !wording Replace 13.1(10/4): For an untagged derived type, it is illegal to specify a type-related representation aspect if the parent type is a by-reference type, or has any user-defined primitive subprograms. Similarly, it is illegal to specify a nonconfirming type-related representation aspect for an untagged by-reference type after one or more types have been derived from it. with: It is illegal to specify a nonconfirming type-related representation aspect for an untagged by-reference type if it is derived from a by-reference type, or if one or more types have been derived from it prior to the specification of the aspect. !discussion For by-reference types, it is clear that the rule is necessary; it's not practical to change the representation as noted in AI95-0246-1. Thus, the by-reference part of the rule is needed. However, the part about primitive subprogram is essentially a methodological restriction. If the conversion is between two types with the same value set but different representations, there is no semantic problem. The main purpose here is to prevent expensive implementation conversions. Methodological restrictions are always questionable, as they merely prevent a programmer from doing something that they may actually need to do. After all, there are plenty of operations that can be quite expensive in practice (controlled types, equality of composites, and so on). Generally, it's better to let knowledgable users write the code that they need (especially given that 13.6 recommends this approach for representation conversions), and give warnings if that leads to overly expensive code. 13.1(10/3) is intended to require explicitly converting between two different representations. That seems admirable, until one realizes that the effect is to require the elimination of all primitive operations of a (record) type in order to use Ada-language conversions. That means that the standard organization of putting a type and its operations together in a package cannot be followed - the operations have to placed somewhere else in order to take advantage of compiler-generated representation change. For many types (especially ones in packages already in use for which moving operations would require changes to many clients), the net effect is that derivation is infeasible and the representation changes end up getting written manually by the user, with all of the potential for mistakes and higher execution costs that entails. The question of AI12-0109-1 shows that users have been clever in finding ways around this restriction. Moreover, the technique of AI12-0109-1 provides a way to end-run 13.1(10/4), much like generics provided a way to end-run the ban on redefinition of "=" in Ada 83. When we considered AI12-0109-1, we didn't have the backbone to eliminate this methodological restriction; but now we have another example of it causing problems. So we finally eliminate this nuisance (about 30 years late in the author's opinion). Note that there can be a minor semantic issue with in out parameters, in that there can be precision loss if a derived type has more precision than its parent type. For instance, in: type Dollars is delta 0.01 with Small => 1.0; procedure Munge (Val : in out Dollars) is null; type Cents is new Dollars with Small => 0.01; --(A) -- Inherits Munge. declare Obj : Cents := 0.55; begin Munge (Obj); -- Obj = 1.0 here! end; The implicit conversion of Obj to Dollars causes the value to be rounded to 1.0, and it will stay 1.0 on the reverse conversion, even though Munge itself never touches the parameter. Luckily (??), this case [specifically, the declaration of (A)] is illegal by 3.5.10(2/5), which only allows specifying Small for "nonderived ordinary fixed point types". So we don't have to worry about this. This could still happen for floating point types, but only if the implementation allows a derived type to use a different representation. There's no requirement to support nonconfirming size clauses for floating point types. As such, we can ignore this concern. If an implementation wants to make trouble for itself, it can, but we don't want to prevent useful things simply because someone could cause a problem with a badly thought out type declaration and a permissive implementation. The rules of AI12-0074-1 also may need some adjustment, but as several issues with those rules have been brought up, we'll handle that AI separately with the knowledge that 13.1(10/4) will no longer apply to types with Default_Value and Default_Component_Value. --- There is a minor change to the rules for by-reference types, in that we now allow confirming representation clauses for such types. This is consistent with our Language Design Principle that confirming aspects are always allowed and do not affect the semantics (a principle that wasn't always followed in Ada 95 rules such as this one). This expansion only allows more specifications of aspects, so there isn't a compatibility concern. Since it depends on confirming values, which are almost always implementation-defined, it does potentially raise a portability concern, but certainly no more than any other specification of a representation aspect. !corrigendum 13.1(10/4) @drepl For an untagged derived type, it is illegal to specify a type-related representation aspect if the parent type is a by-reference type, or has any user-defined primitive subprograms. Similarly, it is illegal to specify a nonconfirming type-related representation aspect for an untagged by-reference type after one or more types have been derived from it. @dby It is illegal to specify a nonconfirming type-related representation aspect for an untagged by-reference type if it is derived from a by-reference type, or if one or more types have been derived from it prior to the specification of the aspect. !ASIS No ASIS effect. !ACATS test Various existing B-Tests need modification. An ACATS C-Test is needed to check that a derived type with a different representation than its parent and with primitive operations works as expected. !appendix Editor's note: Here is a listing of AIs (including e-mail threads) that mention 13.1(10) - in any of its various forms. The first matching text snippet is shown, followed by a summary and sometimes commentary. (Note: I've skipped No Action AIs, and for Ada 202x AIs, any that aren't finished or on hold.) [Note: If an AI mentions 13.1(10) with some non-standard syntax, I may have missed it. There are enough hits here as it is.] All of the important conclusions are including in the !discussion of this AI. One only needs to read this if they want to convince themselves that every known problem has been considered. ---------- AI-00031.TXT It is forbidden by 13.1(10): "For an untagged derived type, no [This AI asks if 13.6 only works if there are no derived subprograms, which of course follows from 13.1(10).] ---------- AI-00051-2.TXT Note also RM 13.1(10) which imposes the "no-inherited subprograms" rule for [This seems tangential to the actual discussion (about 'Size). Not relevant.] ---------- AI-00108.TXT "tagged" occurs: in 13.1(10) and 13.1(11). And it is those rules that [Just an off-hand reference that has nothing to do with the AI.] ---------- AI-00137.TXT 13.1(10) says: 13.1(10) seems to forbid the following example: The intent of 13.1(10) is to forbid two types from having different ... [Here, 13.1(10) was one of the motivating reasons for introducing "operational aspects". Since it no longer applies to such aspects, that's not interesting going forward.] ---------- AI-00195.TXT says that 13.1(10) does not apply to stream attributes. This would just be > says that 13.1(10) does not apply to stream attributes. This would just be Yes, I agree, since 13.1(10) does not apply to stream attributes, we [This AI is about stream attributes, and these references are referring to AI-00137.TXT.] ---------- AI-00246.TXT However, 13.1(10) prevents these sorts of problems for type-related aspects of 13.1(10.b) explains that this rule exists precisely to prevent this sort of ... [This one is important. This AI notes that we don't have to worry about type conversions between related types as 13.1(10) prevents trouble by preventing change of representation for untagged by-reference types. This demonstrates that the by-reference part of the rule has to be retained. (I think we already knew that, but here is the confirmation.) ------ AI-00291-2.TXT not a multiple of the parent type's alignment (13.1(10) allows this; [This notes that 13.1(10) doesn't prevent a derived type from having a different alignment.] ---------- AI05-0083-1.TXT similar to 13.1(10): "For a composite derived type, no subtype-related [This AI discusses Alignment again, and this just notes that 13.1(10) doesn't apply.] ---------- AI05-0106-1.TXT This appears to be legal, as 13.1(10) does not apply, and T is considered to be [This is about generic formal derived types, not relevant to the need for 13.1(10).] ---------- AI05-0229-1.TXT means we cannot run afoul of 13.1(10).] The inabilility to derive also means we cannot run afoul of 13.1(10).] derive also means we cannot run afoul of 13.1(10).] also means we cannot run afoul of 13.1(10).] [This notes that task and private aspects don't run into 13.1(10) since such types can't be derived. Not relevant here.] ---------- AI05-0295-1.TXT !standard 13.1(10) Modify 13.1(10): Update the AARM notes 13.1(10.a/1) and 13.1(10.b/3). [This updates the wording of 13.1(10), so it's already captured. The AI is the presentation rewrite of 13.1.] ---------- AI12-0027-1.TXT I read 13.1(10/3) as supporting this change - it suggests that it was intended 13.1(10/3) doesn't do this. It just says > I read 13.1(10/3) as supporting this change - it suggests that it was the problem is that in the current case, 13.1(10/3) provides no protection, > 13.1(10/3) doesn't do this. It just says illegal (see 13.1(11/3), so I don't think we ever get to 13.1(10/3) in that is no possibility of something like 13.1(10/3) to save us). >> 13.1(10/3) doesn't do this. It just says > to 13.1(10/3) in that case. How else could this happen? BTW, note that changing 13.1(10/3) as you suggest would be wildly incompatible, a by-reference type was supposed to be prevented by 13.1(10/3): 13.1(10/3), quoted above, gets this point wrong - > 13.1(10/3): ban this (I'd rather repeal 13.1(10/3), which is a pain in the neck as it That would be the case if 13.1(10/3) did not exist, but since it does, it's > That would be the case if 13.1(10/3) did not exist, but since it does, [This AI makes the copying implicit in a value conversion explicit in order to avoid the creation of dangling access values. 13.1(10) is used here to justify not allowing copies in many cases, but it also was used to justify likelyhood of incompatibilities. In the end, 13.1(10) doesn't figure into the result. There's also some discussion that gets covered in a later AI.] ---------- AI12-0074-1.TXT as 13.1(10) ensures that the Default_Value aspect is the same for the derived type because of the infamous 13.1(10/3). Any case where the programmer wrote this [This is the infamous view conversion is illegal for many unrelated types AI. We already have a request to abandon most of this AI. 13.1(10) is important in allowing the rule for Default_Value to not include related types. Repealing 13.1(10) would invalidate some the assumptions used in this AI, and thus we would have to revisit this AI if we do that (regardless of any other requests).] ---------- AI12-0109-1.TXT !standard 13.1(10/3) 15-01-20 AI12-0109-1/03 (1) There appears to be a hole related to 13.1(10/3). situation that 13.1(10/3) is intended to prevent. Add at the end of 13.1(10/3): ... [This AI adds the second sentence to 13.1(10/4), which prevents problems with by-reference types. This clearly will have to stay in any repeal. We looked at repealing 13.1(10), but got no traction, in particular because of FUD that I'm trying to combat by doing this document.] ---------- AI12-0352-1.TXT of the useful cases are banned by 13.1(10). And almost all of the rest of them [Just a note that untagged derivation isn't as useful as it should be, not really relevant to the need for 13.1(10).] **************************************************************** From: Tucker Taft Sent: Tuesday, March 31, 2020 8:47 AM As AdaCore has been tightening some of the restrictions associated with Default_Value and Default_Component_Value, we have run into a number of places where customer code is affected by these restrictions. Below I mentioned the issue with access-type-related problems in AI12-0074-1. Another comes from Default_Value and Default_Component_Value being considered representation aspects. There seems some justification for Default_Value, in that it affects the size of OUT parameters, but I could not find any justification for making Default_Component_Value a representation aspect. So I think we should re-open the discussion on that, so that Default_Component_Value can be specified on derived types, even when they have user-defined primitives, as specified in 13.1(10). It also may be time to consider eliminating the user-defined-primitive-related restriction part of 13.1(10). Clearly if something must be passed by reference, expecting a representation change is not practical. On the other hand, the rule disallowing a change of representation when there are inherited subprograms seems like it might be a fix that is worse than the disease. Yes, there is some overhead in changing representation, but so what? If the inherited subprogram does something useful, why disallow the representation change and the associated implicit conversion. Generally there was a desire to make expensive operations visible, but one wonders whether this particular rule is really worth the added user complexity. Finally, the freezing associated with specifying a Default_Value has come up for the case of enumeration literals. One wonders whether we need a more general exception for Default_Value so it can be specified without freezing the type being defined. Using T'First or T'Last in the specification of Default_Value seems like a common thing to want to do, and so probably should be allowed. **************************************************************** From: Arnaud Charlet Sent: Tuesday, March 31, 2020 1:21 PM For the record, this was found in the context of ACATS test B360001 and testing the changes in our customer testsuite. So when we make Tuck's suggested changes, B360001 will also need to be revised. **************************************************************** From: Randy Brukardt Sent: Tuesday, March 31, 2020 3:10 PM > As AdaCore has been tightening some of the restrictions associated > with Default_Value and Default_Component_Value, we have run into a > number of places where customer code is affected by these > restrictions. Below I mentioned the issue > with access-type-related problems in AI12-0074-1. Another > comes from Default_Value and Default_Component_Value being considered > representation aspects. There seems some justification for > Default_Value, in that it affects the size of OUT parameters, but I > could not find any justification for making Default_Component_Value a > representation aspect. So I think we should re-open the discussion on > that, so that Default_Component_Value can be specified on derived > types, even when they have user-defined primitives, as specified in > 13.1(10). You've said that you believe that there are only two kinds of type-related aspects, and I don't think that Default_Component_Value makes much sense as an operational aspect. (Do we want to allow Default_Component_Value on a partial view?? I think not.) Besides... > It also may be time to consider eliminating the > user-defined-primitive-related restriction part of 13.1(10). That time was 1992. :-) > Clearly if something must be passed by reference, expecting a > representation change is not practical. On the other hand, the rule > disallowing a change of representation when there are inherited > subprograms seems like it might be a fix that is worse than the > disease. Yes, there is some overhead in changing representation, but > so what? If the inherited subprogram does something useful, why > disallow the representation change and the associated implicit > conversion. Exactly. If there's too much overhead, then don't do that. Why should the compiler prevent something useful because someone might abuse it? We do need to be careful, however, since there have been several rules over the years where 13.1(10) avoided pestilence. We'd need to find those and put in the needed rules to avoid trouble (still a better choice than preventing useful untagged derived types). There also was a concern about precision loss in fixed point types if the smalls vary. Not sure if we need to worry about that or not (I don't use fixed point enough to have an opinion). > Generally there was a desire to make expensive operations visible, > but one wonders whether this particular rule is really worth the added > user complexity. It appears to me that if we did this, then it isn't a problem to keep Default_Component_Size as a representation aspect. Explain if wrong. > Finally, the freezing associated with specifying a Default_Value has > come up for the case of enumeration literals. One wonders whether we > need a more general exception for Default_Value so it can be specified > without freezing the type being defined. Using T'First or T'Last in > the specification of Default_Value seems like a common thing to want > to do, and so probably should be allowed. We just discussed this on this list, and I included the case 'First in my write-up, yet no one wanted to make a change. Not quite sure what changed here. Anyway, completely removing freezing would not work. The freezing rule prevents nonsense like: type Fooey is range 1 .. 10 with Default_Value => Fooey'Size; or worse type Fooey is range 1 .. 10 with Default_Value => Sub'Alignment; subtype Sub is Fooey; I could see punching some additional holes into the freezing specifically for Default_Value, but removing it in a blanket way would open the door to lots of problems that would be hard to fix without inventing something new that's much like freezing. (Let's not do that!) **************************************************************** From: Tucker Taft Sent: Tuesday, March 31, 2020 3:34 PM >> ... > > You've said that you believe that there are only two kinds of > type-related aspects, and I don't think that Default_Component_Value > makes much sense as an operational aspect. (Do we want to allow > Default_Component_Value on a partial view?? I think not.) Besides... I don't see a problem, since it is only permitted on array types. But perhaps if we get rid of 13.1(10) it doesn't matter. >> It also may be time to consider eliminating the >> user-defined-primitive-related restriction part of 13.1(10). > > ... > > We do need to be careful, however, since there have been several rules > over the years where 13.1(10) avoided pestilence. We'd need to find > those and put in the needed rules to avoid trouble (still a better > choice than preventing useful untagged derived types). Interesting. I don't remember such rules, but alas, that doesn't prove much... ... >> Generally there was a desire to make expensive operations visible, >> but one wonders whether this particular rule is really worth the >> added user complexity. > > It appears to me that if we did this, then it isn't a problem to keep > Default_Component_Size as a representation aspect. Explain if wrong. I think you are right. I don't think it will matter either way at that point. >> Finally, the freezing associated with specifying a Default_Value has >> come up for the case of enumeration literals. One wonders whether we >> need a more general exception for Default_Value so it can be >> specified without freezing the type being defined. Using T'First or >> T'Last in the specification of Default_Value seems like a common >> thing to want to do, and so probably should be allowed. > > We just discussed this on this list, and I included the case 'First in > my write-up, yet no one wanted to make a change. Not quite sure what > changed here. I don't think I understood all of the implications. > Anyway, completely removing freezing would not work. The freezing rule > prevents nonsense like: > > type Fooey is range 1 .. 10 with Default_Value => Fooey'Size; > > or worse > > type Fooey is range 1 .. 10 with Default_Value => Sub'Alignment; > subtype Sub is Fooey; I agree we don't want to allow use of representation attributes in defining Default_Value. But many other attributes seem fair game. We could perhaps specifically allow 'First and 'Last when static. That would probably cover most interesting cases. > I could see punching some additional holes into the freezing > specifically for Default_Value, but removing it in a blanket way would > open the door to lots of problems that would be hard to fix without > inventing something new that's much like freezing. (Let's not do > that!) Agreed. **************************************************************** From: Randy Brukardt Sent: Tuesday, March 31, 2020 4:04 PM ... > > ... > > > > We do need to be careful, however, since there have been several > > rules over the years where 13.1(10) avoided pestilence. We'd need to > > find those and put in the needed rules to avoid trouble (still a > > better choice than preventing useful untagged derived types). > > Interesting. I don't remember such rules, but alas, that doesn't > prove much... I was just reading an old AI that mentioned that last week. Now, if you were to ask to me to remember what I was reading last week, that I wouldn't know. :-) I'm not sure of the best way to search for that, but I'll think about it. **************************************************************** From: Tucker Taft Sent: Tuesday, March 31, 2020 4:19 PM It is sort of hard to imagine what could be the problem, because clearly you can simulate what an inherited subprogram does by inserting explicit conversions at the call site. Perhaps we claimed that 'Access would work on an inherited subprogram without having to create a wrapper. Now that wrappers are needed in a number of cases, this problem might no longer be considered that big of a deal. **************************************************************** From: Arnaud Charlet Sent: Wednesday, April 1, 2020 3:40 AM > > There also was a concern about precision loss in fixed point types > > if the smalls vary. Not sure if we need to worry about that or not > > (I don't use fixed point enough to have an opinion). > > > >> Generally there was a desire to make expensive operations visible, > >> but one wonders whether this particular rule is really worth the > >> added user complexity. > > > > It appears to me that if we did this, then it isn't a problem to > > keep Default_Component_Size as a representation aspect. Explain if wrong. > > I think you are right. I don't think it will matter either way at that point. Agreed as well, assuming we get rid of 13.1(10) then we can keep Default_Component_Value as a representation aspect. > > Anyway, completely removing freezing would not work. The freezing > > rule prevents nonsense like: > > > > type Fooey is range 1 .. 10 with Default_Value => Fooey'Size; > > > > or worse > > > > type Fooey is range 1 .. 10 with Default_Value => Sub'Alignment; > > subtype Sub is Fooey; > > I agree we don't want to allow use of representation attributes in defining > Default_Value. But many other attributes seem fair game. We could perhaps > specifically allow 'First and 'Last when static. That would probably cover > most interesting cases. I'm curious, why would it be a problem to allow the use of 'Size or 'Alignment? FWIW GNAT has no troubles with the above code. I don't think we want to add a special case here, so to me it should be all or nothing. **************************************************************** From: Tucker Taft Sent: Wednesday, April 1, 2020 7:11 AM >>> ... >> >> I agree we don't want to allow use of representation attributes in defining >> Default_Value. But many other attributes seem fair game. We could perhaps >> specifically allow 'First and 'Last when static. That would probably cover >> most interesting cases. > > I'm curious, why would it be a problem to allow the use of 'Size or > 'Alignment? FWIW GNAT has no troubles with the above code. The concern is that the presence of a Default_Value might affect some aspect of the representation, such as 'Size or 'Alignment of the type. Because it is considered a representation aspect, its presence or absence, or its particular value, might have such an effect. > I don't think we want to add a special case here, so to me it should > be all or nothing. There are already some special cases for Default_Value, for enumeration types. So this would not be without precedent. But agreed that special cases do add complexity. It would be useful to know whether the current regressions would be solved by allowing 'First and 'Last, or if it is a more general problem. **************************************************************** From: Arnaud Charlet Sent: Wednesday, April 1, 2020 7:24 AM > > I'm curious, why would it be a problem to allow the use of 'Size or > > 'Alignment? FWIW GNAT has no troubles with the above code. > > The concern is that the presence of a Default_Value might affect some aspect > of the representation, such as 'Size or 'Alignment of the type. Because it > is considered a representation aspect, its presence or absence, or its > particular value, might have such an effect. Still, I don't see the issue, a compiler should be able to handle that these days (as shown by GNAT), it's not like we care anymore about e.g. one pass compilers at this stage, or is that the concern? Because Ada 2020 is not implementable with a one pass compiler in any case. > > I don't think we want to add a special case here, so to me it should > > be all or nothing. > > There are already some special cases for Default_Value, for enumeration > types. So this would not be without precedent. But agreed that special > cases do add complexity. It would be useful to know whether the current > regressions would be solved by allowing 'First and 'Last, or if it is a > more general problem. No, the regressions wouldn't improve with allowing 'First/'Last at all. The regressions are all related to the rule we now all agree we want to get rid of (13.1(10), the part about parent types with primitive operations), so we should be fine on this front. **************************************************************** From: Tucker Taft Sent: Wednesday, April 1, 2020 7:36 AM > Still, I don't see the issue, a compiler should be able to handle that > these days (as shown by GNAT), it's not like we care anymore about > e.g. one pass compilers at this stage, or is that the concern? Because > Ada 2020 is not implementable with a one pass compiler in any case. Freezing issues are not related to one pass or two. It is more circularity, where the value of the new aspect affects the value of the aspect used to define it. E.g.: type T is range 0 .. 31 with Default_Value => T'Object_Size; where a choice between 16 and 32 for Object_Size would clearly affect the legality, and conceivably the presence of the Default_Value might affect this choice. >>> I don't think we want to add a special case here, so to me it should >>> be all or nothing. >> >> There are already some special cases for Default_Value, for enumeration >> types. So this would not be without precedent. But agreed that special >> cases do add complexity. It would be useful to know whether the current >> regressions would be solved by allowing 'First and 'Last, or if it is a >> more general problem. > > No, the regressions wouldn't improve with allowing 'First/'Last at all. Ah, OK. I thought you had some examples of uses of 'First or 'Last in customer code. > The regressions are all related to the rule we now all agree we want > to get rid of (13.1(10), the part about parent types with primitive > operations), so we should be fine on this front. OK, so let's focus on this derived-type issue and separate out the concern about Default_Value using 'First or 'Last. **************************************************************** From: Arnaud Charlet Sent: Wednesday, April 1, 2020 9:58 AM > Freezing issues are not related to one pass or two. It is more circularity, > where the value of the new aspect affects the value of the aspect used to > define it. E.g.: > > type T is range 0 .. 31 with Default_Value => T'Object_Size; > > where a choice between 16 and 32 for Object_Size would clearly affect the > legality, and conceivably the presence of the Default_Value might affect > this choice. OK. I still don't see the issue FWIW, but I guess we can keep the status quo for now. > > No, the regressions wouldn't improve with allowing 'First/'Last at all. > > Ah, OK. I thought you had some examples of uses of 'First or 'Last in > customer code. No, the issues were only part of the ACATS test b360001, so completely artificial. > > The regressions are all related to the rule we now all agree we want > > to get rid of (13.1(10), the part about parent types with primitive > > operations), so we should be fine on this front. > > OK, so let's focus on this derived-type issue and separate out the concern > about Default_Value using 'First or 'Last. Seems fine for the time being. **************************************************************** From: Randy Brukardt Sent: Wednesday, April 1, 2020 4:59 PM > OK. I still don't see the issue FWIW, but I guess we can keep the status > quo for now. For Janus/Ada at least, all of the aspects and attribute definition clauses for a type being frozen are evaluated before any determination of representation is done. So, while specified aspects could presumably be handled (although finding an order would be difficult), the default values aren't determined until all of the specified aspects are known (since those specifications can change the default - for instance, specifying Size can change the default Object_Size). Additionally, when subtypes are involved, those won't have been frozen yet when the base type is determined. Consider something like: type T is range 0 .. 31 with Default_Value => S'Object_Size; subtype S is T'Base range 0 .. 2**12-1; One has to freeze T before one can freeze S, and freezing T will determine the Default_Value. You could create a separate set of rules just for Default_Value (say allowing T'Object_Size but not S'Object_Size), but that seems like a way guaranteed to cause never ending work for the ARG and for implementers to plug new holes as they are found. **************************************************************** From: Arnaud Charlet Sent: Thursday, April 2, 2020 2:41 AM ... > Consider something like: > > type T is range 0 .. 31 with Default_Value => S'Object_Size; > subtype S is T'Base range 0 .. 2**12-1; > > One has to freeze T before one can freeze S, and freezing T will > determine the Default_Value. Isn't the above already illegal in any case? GNAT certainly rejects it with: 2. type T is range 0 .. 31 with Default_Value => S'Object_Size; | >>> type "S" cannot be used before end of its declaration even without involving any freezing rule. **************************************************************** From: Arnaud Charlet Sent: Thursday, April 2, 2020 3:53 AM > > The regressions are all related to the rule we now all agree we want > > to get rid of (13.1(10), the part about parent types with primitive > > operations), so we should be fine on this front. > > OK, so let's focus on this derived-type issue and separate out the concern > about Default_Value using 'First or 'Last. FWIW, only one acats test is impacted in the version of ACATS we're running, bxb3004: --- expected +++ output @@ -126,4 +126,2 @@ 114. type Bad_Der is new Not_UU with Unchecked_Union; -- ERROR: (D) ->>> type-related representation item not permitted <<< ->>> parent type "Not_UU" has primitive operations <<< 115. @@ -175,3 +173,3 @@ 157. -158 lines: 11 errors +158 lines: 9 errors ###>> DONE which is as expected. Also interestingly, GNAT already has a warning to inform the customer when a change of representation (potentially costly) is involved. This warning is now triggering in cases where previously code was rejected before we try to relax 13.1(10), e.g: -convert_record.adb:20:03: type-related representation item not permitted -convert_record.adb:20:03: parent type "R" has primitive operations +convert_record.adb:23:10: warning: change of representation required with Ada.Text_IO; procedure convert_record is package P is type R is record c: Character; a, b: Integer; end record; function foo(x: R) return Integer; end P; package body P is function foo(x: R) return Integer is begin return x.a + x.b; end foo; end P; type R2 is new P.R; pragma pack(R2); x: R2 := (a => 1, b => 2, c =>'c'); begin if foo(x) = 3 then Ada.Text_IO.Put_Line("Passed"); else Ada.Text_IO.Put_Line("Failed"); end if; end convert_record; in other words, relaxing the rule allows the above code to now compile and run successfully, and inform the user of what's happening behind the scene, letting him choose what he wants (the runtime hit, or rewrite his code for more efficiency). This seems to be the best option at this stage and remember that this change of representation is in any case already required in other cases, so it's not like this requires a new mechanism for the compiler. **************************************************************** From: Randy Brukardt Sent: Thursday, April 2, 2020 2:17 PM The only reason that you couldn't "use S before the end of its declaration" would be because T was getting frozen during the declaration of S. Otherwise, you would have evaluated the aspect later at some other freezing point. That probably happened because I used a range. If I had simply said: subtype S is T'Base; then the declaration of S should not involve any freezing. Sorry about botching the example. **************************************************************** From: Randy Brukardt Sent: Tuesday, April 21, 2020 7:27 PM > OK, so let's focus on this derived-type issue and separate > out the concern about Default_Value using 'First or 'Last. Attached find the AI I created to repeal the annoying part of 13.1(10/3). It has been reviewed by Steve and Tucker. Tucker suggested making the remaining part of the rule only apply to nonconfirming specifications of aspects, so that's why the wording was totally reorganized. I researched every occurrence of 13.1(10) in every existing AI in order to see if there were any other AIs to change. The only AI with a substantial relevance is AI95-0246-1, in which it is discovered that one needs to ban changing representations of by-reference types. (We're keeping that part of the rule.) AI12-0074-1 also seems to depend on the rule, but we had already been asked to revisit that AI.) I also noticed that the concern about precision loss does not happen even with this repeal, unless an implementation wants to make trouble for itself. (In particular, Small cannot be specified on a derived type, so the portable way to cause issues is illegal.) As always, comments welcome. ****************************************************************