!standard 4.3(3/5) 19-02-04 AI12-0307-1/01 !class Amendment 19-02-04 !status work item 19-02-04 !status received 19-01-22 !priority Low !difficulty Easy !subject Resolution of aggregates !summary Resolution of all aggregates work the same; anything that could be a legal aggregate is allowed for resolution purposes. !problem 4.3(3/2) was revised by AI12-0212-1 to read: The expected type for a delta_aggregate shall be a single array type, or a single descendant of a record type or of a record extension. The expected type for an array_aggregate, a record_aggregate, or an extension_aggregate shall be a single array type, record type, or record extension. The expected type for a container_aggregate shall be a single array type or a single type with the Aggregate aspect specified. The syntax of array_aggregate was also extended to allow square brackets. However, this leaves the resolution of an aggregate like: [1, 2] ambiguous. It could be either a container_aggregate or an array_aggregate, and the type it resolves to determines which. However, if resolved as an array_aggregate, a record type is considered, and if resolved as a container_aggregate, a record type is not considered. So there exist cases where whether or not resolution will succeed is unknown: procedure P (V : Vector); procedure P (R : My_Rec); P ([1, 2]); -- OK? Ambiguous? (Illegal.) This needs to be fixed. !proposal (See Summary.) !wording Replace 4.3.3(3/5) with: The expected type for an aggregate shall be a single array type, a single type with the Aggregate aspect specified, or a single descendant of a record type or of a record extension. !discussion There are four reasonable solutions, ranked in ascending order of incompatibility: (1) parens or brackets changes the resolution: The expected type for a delta_aggregate shall be a single array type, or a single descendant of a record type or of a record extension. The expected type for an array_aggregate surrounded with parentheses, a record_aggregate, or an extension_aggregate shall be a single array type, record type, or record extension. The expected type for a container_aggregate or an array_aggregate surrounded with brackets shall be a single array type or a single type with the Aggregate aspect specified. (2) Only delta aggregates are treated specially: The expected type for a delta_aggregate shall be a single array type, or a single descendant of a record type or of a record extension. The expected type for any other aggregate shall be a single array type, single record type, single record extension, or a single type with the Aggregate aspect specified. (3) All aggregates are resolved the same: The expected type for an aggregate shall be a single array type, a single type with the Aggregate aspect specified, or a single descendant of a record type or of a record extension. (4) We use the least information possible. The expected type for an aggregate shall be a single composite type. (1) is unusual in the syntax of the aggregate determines the resolution. And the syntax difference in question is subtle (especially in some fonts). We would prefer that all array aggregates resolve the same way. However, all of the remaining options are incompatible. For such an incompatibility to happen, we need a subprogram that takes a parameter that is an aggregate, and we need an overloaded version of that subprogram that has a parameter of a second type that doesn't currently have aggregates but will in Ada 2020. In that case, a call that resolves in Ada 2012 will become ambiguous in Ada 2020. For instance, all of (2) through (4) are incompatible in a case like: procedure P (V : Vector); -- From an instance of Ada.Containers.Vectors. procedure P (A : Int_Array); -- Some array with integer components. P ((1, 2)); -- OK in Ada 2012, Ambiguous in Ada 2020. Clearly, overloading like this is not very common. So the incompatibility is probably tolerable. All of the proposed wordings (except (1), of course) have this problem if the second type is a container type (almost *any* container type, except holders, queues, and trees). Some users use containers extensively. On the other hand, the second type for (3) and (4) can also be a private type that has visible non-discriminant components. While such types can exist, they are rare in practice. Typically, a type is private until such a point where the components become visible (meaning that the last declaration is a record extension, which has allowed aggregates since Ada 95, and thus isn't involved in the incompatibility.) Thus, if we're going to allow any incompatibility, we might as well allow the delta aggregate incompatibility as well, as it is far less likely than the container incompatibility. Therefore, we select option (3). We don't select option (4), as it means that the second type could be any private type. Private types are quite common in Ada, and since we don't actually allow any aggregates to be fully private types, we aren't gaining anything from this addition risk of incompatibility. If we were designing Ada from scratch, this is the option we would choose, since we don't want resolution to be "too smart". But it seems too late to be introducing unnecessary incompatibilities. !ASIS No effect. !ACATS test ACATS B-Tests are be needed to check that newly incompatible cases are properly detected. !appendix From: Randy Brukardt Sent: Tuesday, January 22, 2019 5:54 PM 4.3(3/2) was revised by AI12-0212-1 to read: The expected type for a delta_aggregate shall be a single array type, or a single descendant of a record type or of a record extension. The expected type for [any other aggregate] {an array_aggregate, a record_aggregate, or an extension_aggregate} shall be a single array type, record type, or record extension. {The expected type for a container_aggregate shall be a single array type or a single type with the Aggregate aspect specified.} The syntax of array_aggregate was also extended to allow square brackets. So how does an aggregate like: [1, 2] get resolved? It could be either a container_aggregate or an array_aggregate, and the type it resolves to determines that. (Remember, aggregates have a weird resolution, where the rule I give above determines how they are resolved from the outside, and then there are more specific rules that determine what kind of aggregate one has and how the inside is resolved.) Consider: procedure P (V : Vector); procedure P (R : My_Rec); P ([1, 2]); -- OK? Ambiguous? In this case, we have a routine overloaded on a container and a vector. If we assume the aggregate is a container_aggregate, this resolves (the record type isn't considered). If we assume the aggregate is an array_aggregate (which it could be syntactically), this does not resolve (the record type is considered). I wonder if the author (Tuck??) was thinking of having separate rules for aggregates surrounded by square brackets rather than round brackets. If that's the case, though, we can't use the syntactic category for array_aggregate alone, and rather need to say something about the brackets/parens: The expected type for a delta_aggregate shall be a single array type, or a single descendant of a record type or of a record extension. The expected type for [any other aggregate] {an array_aggregate surrounded with parentheses, a record_aggregate, or an extension_aggregate} shall be a single array type, record type, or record extension. {The expected type for a container_aggregate or an array_aggregate surrounded with brackets shall be a single array type or a single type with the Aggregate aspect specified.} However, Bob likes to say that resolution shouldn't be too smart. And the presence or absence of brackets seems a bit dodgy to use for resolution. Using the above wording, consider: procedure P (A : My_Array); procedure P (R : My_Rec); P ([1, 2]); -- OK. P ((1, 2)); -- Ambiguous. So perhaps it would be better to forget having separate rules and just mash them all up (returning to wording much more similar to the original): The expected type for a delta_aggregate shall be a single array type, or a single descendant of a record type or of a record extension. The expected type for any other aggregate shall be a single array type, record type, [or] record extension{, or a single type with the Aggregate aspect specified}. This does have a bit of a compatibility problem, as the most of the existing Ada.Containers will have the Aggregate aspect. So with the above rule: package My_Vectors is new Ada.Containers.Vectors (....); procedure P (V : My_Vectors.Vector); procedure P (R : My_Rec); P ((1, 2)); -- OK in Ada 2012, Ambiguous in Ada 2020. We cared enough about compatibility to separate out delta aggregates just so that private parents would be allowed for them and not for other aggregates. That's a lot less likely than the above. So I guess the shorter rule given above doesn't work, either. So it looks to me like we need to use the rule with the brackets/parens mentioned. Any other ideas? If not, I'll write up a clean-up AI for this wording. **************************************************************** From: Edmond Schonberg Sent: Tuesday, January 22, 2019 6:55 PM ... > However, Bob likes to say that resolution shouldn't be too smart. Fully agree, the resolution of aggregates is complex enough, and users have known for two decades that when in doubt you qualify. ... > This does have a bit of a compatibility problem, as the most of the > existing Ada.Containers will have the Aggregate aspect. So with the above rule: > > package My_Vectors is new Ada.Containers.Vectors (....); > procedure P (V : My_Vectors.Vector); > procedure P (R : My_Rec); > > P ((1, 2)); -- OK in Ada 2012, Ambiguous in Ada 2020. But the same will be true with two overloaded procedures that take different containers with Add_Unnamed, so qualification will be necessary. I don’t think that the above is reason enough to complicate the rules. In particular […] and (…) should be treated in the same way. > > We cared enough about compatibility to separate out delta aggregates > just so that private parents would be allowed for them and not for other > aggregates. That's a lot less likely than the above. So I guess the > shorter rule given above doesn't work, either. > > So it looks to me like we need to use the rule with the > brackets/parens mentioned. Unnecessary complication, small incompatibility is much more acceptable IMHO. **************************************************************** From: Randy Brukardt Sent: Tuesday, January 22, 2019 7:32 PM > Unnecessary complication, small incompatibility is much more > acceptable IMHO. If we're OK with this incompatibility, we should revisit the decision for delta aggregates (where the incompatibility is even less likely). That would let us have a much simpler overall rule: The expected type for an aggregate shall be a single array type, a single type with the Aggregate aspect specified, or a single descendant of a record type or of a record extension. which is the union of all of the possibilities. Containers and types with some private components (private types or private extensions) would be newly allowed (and could cause incompatibilities -- but only if there is some overloading). I note that the delta aggregate rule came from not wanting to introduce any incompatibility. The minutes of meeting 58 is the only place this came up, and there wasn't any discussion of whether we could just allow the incompatibility (at least not any that was recorded). P.S. We've still got the Winter Storm Warning, but the expected snow hasn't really appeared yet (there's a dusting of snow, but hardly the 6-8 inches forecast). Thus I'm in the office. Of course, the snow could appear at any time. Will work until the end of the usual working day or it really starts to snow. **************************************************************** From: Edmond Schonberg Sent: Tuesday, January 22, 2019 8:07 PM > If we're OK with this incompatibility, we should revisit the decision > for delta aggregates (where the incompatibility is even less likely). > That would let us have a much simpler overall rule: > > The expected type for an aggregate shall be a single array type, a > single type with the Aggregate aspect specified, or a single > descendant of a record type or of a record extension. > > which is the union of all of the possibilities. Containers and types > with some private components (private types or private extensions) > would be newly allowed (and could cause incompatibilities -- but only > if there is some overloading). No objections to this, although it is easy to justify a different rule for delta aggregates because they have a visibly different syntax: we know what it is without having to look at choices and expressions. Speaking of which, Can the presence of key-value pairs be used for resolution ( suppose not) ? > I note that the delta aggregate rule came from not wanting to > introduce any incompatibility. The minutes of meeting 58 is the only > place this came up, and there wasn't any discussion of whether we > could just allow the incompatibility (at least not any that was recorded). > > P.S. We've still got the Winter Storm Warning, but the expected snow > hasn't really appeared yet (there's a dusting of snow, but hardly the > 6-8 inches forecast). Thus I'm in the office. Of course, the snow > could appear at any time. Will work until the end of the usual working > day or it really starts to snow. Keep warm! **************************************************************** From: Randy Brukardt Sent: Tuesday, January 22, 2019 8:28 PM > No objections to this, although it is easy to justify a different rule > for delta aggregates because they have a visibly different syntax: we > know what it is without having to look at choices and expressions. You can make the exact same argument for [] vs. (). Make up your mind! :-) > Speaking of which, Can the presence of key-value pairs be used > for resolution ( suppose not) ? Nope. Not in Ada before 2020 nor in Ada 2020. ... > > P.S. We've still got the Winter Storm Warning, but the expected snow > > hasn't really appeared yet (there's a dusting of snow, but hardly > > the > > 6-8 inches forecast). Thus I'm in the office. Of course, the snow > > could appear at any time. Will work until the end of the usual > > working day or it really starts to snow. > > Keep warm! *That's* going to be challenging. The Friday and Saturday forecasts have a high of 0 (Fahrenheit), with lows of -13 and -17. I'd rather have the snow; modern cars get better gas mileage in part because they make less waste heat == takes longer to warm up the engine/cabin. In those sorts of temperatures, I'll get home before the engine gets warm. And then it takes a long time to recover. **************************************************************** From: Tucker Taft Sent: Tuesday, January 22, 2019 9:22 PM >> No objections to this, although it is easy to justify a different >> rule for delta aggregates because they have a visibly different >> syntax: we know what it is without having to look at choices and >> expressions. > > You can make the exact same argument for [] vs. (). Make up your > mind! :-) The [] vs. () is pretty subtle, and I would not recommending it being used for resolution (at least not yet -- maybe some day). I see no reason to backtrack on delta aggregates. So I would accept the modest incompatibility with container aggregates, and leave delta aggregates as somewhat more complex to avoid incompatibility. But I could also accept the mild incompatibility with delta aggregates to simplify the rules. I don't think anyone is going to bump into this problem. So anyone else feel strongly about delta aggregates either way? I'm willing to let our editor make the decision, perhaps based on how many inches of snow fall in Wisconsin ... ;-) **************************************************************** From: John Barnes Sent: Wednesday, January 23, 2019 1:55 AM It's cold here in England as well. We had about two millimetres of snow yesterday. And the temperature has plunged to minus 2 Celsius. Let the editor decide on the parens. **************************************************************** From: Edmond Schonberg Sent: Wednesday, January 23, 2019 8:46 AM >> No objections to this, although it is easy to justify a different >> rule for delta aggregates because they have a visibly different >> syntax: we know what it is without having to look at choices and >> expressions. > > You can make the exact same argument for [] vs. (). Make up your > mind! :-) Not my mind, my eyes: if the screen is not bright enough I’ll have troubles between [()], (()). [[]]. etc (the ADA should have something to say about that!). A “with” jumps out, but I’ll go for the simplest: all aggregates are objects of some composite type whose expected type is determined from context. >> Speaking of which, Can the presence of key-value pairs be used >> for resolution ( suppose not) ? > > Nope. Not in Ada before 2020 nor in Ada 2020. Great! ****************************************************************