!standard 7.6(9.4/2) 08-04-09 AI05-0026-1/04 !standard B.3.3(9/2) !standard B.3.3(10/2) !class binding interpretation 06-11-13 !status WG9 Approved 08-06-20 !status ARG Approved 8-0-2 06-11-09 !status work item 06-11-13 !status received 06-11-03 !priority Medium !difficulty Easy !qualifier Omission !subject Missing rules for Unchecked_Unions !summary A variant component of an Unchecked_Union type cannot have a type that needs finalization. !question 1 - B.3.3(10/2) says that "A component declared in a variant_part of an unchecked union type shall not have a controlled, protected, or task part". This rule is wildly privacy-violating. Why don't we just assume the worst for private types (and private extensions)? Of course, for generics we would need the usual rigmarole of assuming-the-worst in the body and rechecking in the specification. 2 - The !proposal of AI95-00216 explains that "it is illegal to mention a discriminant explicitly in a component clause", which seems like a good idea. There appears to be no rule that has that effect. So is it just that we forgot to put the rule in the wording? !recommendation (See Summary.) !wording Insert after 7.6(9.4/2) - it is a partial view whose full view needs finalization; or Replace B.3.3(9/2) Any name that denotes a discriminant of an object of an unchecked union type shall occur within the declarative region of the type. with Any name that denotes a discriminant of an object of an unchecked union type shall occur within the declarative region of the type, and shall not occur within a record_representation_clause. Replace B.3.3(10/2) A component declared in a variant_part of an unchecked union type shall not have a controlled, protected, or task part. with The type of a component declared in a variant_part of an unchecked union type shall not need finalization. In addition to the places where Legality Rules normally apply (see 12.3), this rule also applies in the private part of an instance of a generic unit. For an unchecked union type declared within the body of a generic unit, or within the body of any of its descendant library units, no part of the type of a component declared in a variant_part of the unchecked union type shall be of a formal private type or formal private extension declared within the formal part of the generic unit. !discussion The 7.6 addition is needed in order to make it clear that the definition of "needs finalization" looks through privacy. In a "static semantics" section, privacy is respected by default; if we want to ignore privacy, then this must be stated explicitly. The addition to B.3.3(9/2) is in response to the second part of the question; a component_clause can only be used as part of a record_representation_clause. It is intended that the new 10/2 formulation be equivalent (for purposes of Legality Checking of Unchecked_Union pragmas) to changing the definition of "needs finalization" to conservatively assume within a generic body that a generic formal private type or private extension "needs finalization". We don't actually make this change because that would interact badly with the rules for the No_Nested_Finalization restriction. We want to treat generic formal types conservatively in one case but not the other because No_Nested_Finalization restriction checking is a post-compilation check while legality checking for an Unchecked_Union pragma is not. The requirement of B.3.3(7/2) that "All component subtypes of an unchecked union type shall be C-compatible" typically eliminates 99% of the problems in this area anyway, but we don't want to rely on that. It is intended that this wording should handle the case of a formal private type (or a formal private extension) of a formal package. Consider this example: declare generic type T is private; package G1 is end G1; generic with package I1 is new G1 (<>); package G2 is end G2; package body G2 is type U_U (D : Boolean) is record case D is when False => null; when True => F : I1.T; end case; end record; pragma Unchecked_Union (U_U); end G2; begin null; end; The pragma should be rejected even if the implementation is willing to permit I1.T as a C-compatible type (using the freedom granted by B.1(20)). !corrigendum 7.6(9.4/2) @dinsa @xbullet @dinst @xbullet !corrigendum B.3.3(9/2) @drepl Any name that denotes a discriminant of an object of an unchecked union type shall occur within the declarative region of the type. @dby Any name that denotes a discriminant of an object of an unchecked union type shall occur within the declarative region of the type, and shall not occur within a @fa. !corrigendum B.3.3(10/2) @drepl A component declared in a @fa of an unchecked union type shall not have a controlled, protected, or task part. @dby The type of a component declared in a @fa of an unchecked union type shall not need finalization. In addition to the places where Legality Rules normally apply (see 12.3), this rule also applies in the private part of an instance of a generic unit. For an unchecked union type declared within the body of a generic unit, or within the body of any of its descendant library units, no part of the type of a component declared in a @fa of the unchecked union type shall be of a formal private type or formal private extension declared within the formal part of the generic unit. !ACATS test !appendix From: Pascal Leroy Date: Monday, October 23, 2006 9:15 AM Three questions on pragma Unchecked_Union. 1 - B.3.3(10/2) says that "A component declared in a variant_part of an unchecked union type shall not have a controlled, protected, or task part". This rule is wildly privacy-violating. Why don't we just assume the worst for private types (and private extensions)? Of course, for generics we would need the usual rigmarole of assuming-the-worst in the body and rechecking in the specification. 2 - The !proposal of AI95-00216 explains that "it is illegal to mention a discriminant explicitly in a component clause", which seems like a good idea. However I can't find a rule that would have that effect. I can't find anything in the minutes that would indicate that we changed our mind. So is it just that we forgot to put the rule in the wording? 3 - B.3.3(9/2) says that "Any name that denotes a discriminant of an object of an unchecked union type shall occur within the declarative region of the type". I am not too sure what "a discriminant of an object" means. Consider an aggregate in named notation like (D => 2, C => 3.14). I would naively think that the name D denotes the discriminant of the (anonymous) object for the aggregate. In this case, the above-mentioned rule would make the aggregate illegal, which would be obnoxious. **************************************************************** From: Robert Dewar Date: Monday, October 23, 2006 9:20 AM > 1 - B.3.3(10/2) says that "A component declared in a variant_part of an > unchecked union type shall not have a controlled, protected, or task > part". This rule is wildly privacy-violating. Why don't we just assume > the worst for private types (and private extensions)? Of course, for > generics we would need the usual rigmarole of assuming-the-worst in the > body and rechecking in the specification. So what? Unchecked_Union should be regarded only as a way of interfacing to C, and C has none of this junk. Yes, I know a lot of junk has crept in already that is not C related. I objected strongly to Tuck's over- generalization here, but let's not make it even worse. The idea of unchecked unions of tasks and controlled types is truly horrible :-) **************************************************************** From: Tucker Taft Date: Monday, October 23, 2006 10:01 AM > 1 - B.3.3(10/2) says that "A component declared in a variant_part of an > unchecked union type shall not have a controlled, protected, or task > part". This rule is wildly privacy-violating. Why don't we just assume > the worst for private types (and private extensions)? Of course, for > generics we would need the usual rigmarole of assuming-the-worst in the > body and rechecking in the specification. Unchecked union is similar to a representation clause, so privacy breaking doesn't seem too bad. In some ways it would seem worse to disallow all private types from unchecked unions. I suppose we only need to disallow private types whose full type is not visible immediately within the scope where the unchecked-union type is defined. That is probably adequate, since if you really need an unchecked-union containing a private type, you can define it in the same scope where the private type is defined. > 2 - The !proposal of AI95-00216 explains that "it is illegal to mention a > discriminant explicitly in a component clause", which seems like a good > idea. However I can't find a rule that would have that effect. I can't > find anything in the minutes that would indicate that we changed our mind. > So is it just that we forgot to put the rule in the wording? Seems plausible. ;-) > 3 - B.3.3(9/2) says that "Any name that denotes a discriminant of an > object of an unchecked union type shall occur within the declarative > region of the type". I am not too sure what "a discriminant of an object" > means. Consider an aggregate in named notation like (D => 2, C => 3.14). > I would naively think that the name D denotes the discriminant of the > (anonymous) object for the aggregate. In this case, the above-mentioned > rule would make the aggregate illegal, which would be obnoxious. That was certainly not the intent. I would say that a use of a selector_name in an aggregate does *not* denote the discriminant of an *object*. It denotes the declaration of the discriminant. I believe that we should interpret "name that denotes a discriminant of an object" as a name that is used in a context where it is interpreted as the name of a value or an object, such as in an expression context, or as the prefix of a larger name. Or even simpler, if you look at the syntactic category "name" it does *not* include "selector_name." So the "D" in your aggregate above is not a "name" at all, in the sense that it is not of the syntactic category "name." (This is reminiscent of the fact that a "generic package" is not a "package" despite lexicographic appearances to the contrary.) **************************************************************** From: Pascal Leroy Date: Tuesday, October 24, 2006 2:50 AM > Unchecked union is similar to a representation clause, > so privacy breaking doesn't seem too bad. I hate privacy breaking, in part because it's hard to implement in our technology. But if we have to have a privacy breaking in this case, I would argue that it should say "needs finalization" (which is already privacy-breaking, being related to restrictions). There is no point in forcing compilers to compute a slightly different predicate for this particular rule. Not to mention that we would still need a specific assume-the-worst rule for generic formal types. > In some ways > it would seem worse to disallow all private types from > unchecked unions. I suppose we only need to disallow private > types whose full type is not visible immediately within the > scope where the unchecked-union type is defined. That is > probably adequate, since if you really need an > unchecked-union containing a private type, you can define it > in the same scope where the private type is defined. Unfortunately that's not quite true. There is an IA recommending that System.Address be a private type (13.7(37)). Having a C union containing an address doesn't seem unreasonable. But I don't think we want to force users to declare such unions in children of System... **************************************************************** From: Pascal Leroy Date: Tuesday, October 24, 2006 2:55 AM > The idea of unchecked unions of > tasks and controlled types is truly horrible :-) It is, but now that we have this rule in the RM it should be well-defined, and implementers should know what to do with private types. Only the mildly insane would want to put tasks in unchecked unions, but as I mentioned in a previous message, there is at least one private type which is of interest here, and that's System.Address. I want to know if an unchecked union with an address in it is legal or not (I realize that Dewar's rule says "of course, how could anyone think otherwise"). **************************************************************** From: Robert Dewar Date: Tuesday, October 24, 2006 6:26 AM Indeed System.Address is probably the MOST useful type in an unchecked union, so that must indeed work. **************************************************************** From: Robert Dewar Date: Tuesday, October 24, 2006 7:03 AM > Unfortunately that's not quite true. There is an IA recommending that > System.Address be a private type (13.7(37)). Having a C union containing > an address doesn't seem unreasonable. But I don't think we want to force > users to declare such unions in children of System... System.Address must be allowed in unchecked unions, and of course we can't require such unions to be in children of System (which may not even be allowed in some implementations. So this must work by the Dewar rule, and if it is necessary to fix the RM to allow this, it must be fixed, hopefully without dragging more horrible irrelevant junk into unchecked union. ****************************************************************