!topic LSN on Accessibility Checks in Generics !key LSN-1042 on Accessibility Checks in Generics !reference MS-12;4.6 !from Bob Duff $Date: 92/10/14 19:23:51 $ $Revision: 1.3 $ !discussion This Language Study Note discusses accessibility checks, and their relationship to the Ada 9X version of the generic contract model. Ada 83 originally intended to support a "contract model" of generics, in which the generic specification forms a contract between clients of the generic and the body of the generic. However, there were certain holes in the contract model. The Ada 9X requirements document directs us to address these problems. Requirement R4.4-B(1), "Dependence of Instantiations on Bodies" states that "A user must have the ability to compile a generic instantiation before compiling the corresponding generic body." Study Topic S4.4-B(2), "Tighten the Contract Model" states that "Ada 9X should ensure that compatibility of a generic instantiation with the corresponding generic body is based solely on the compatibility of each with the generic specification." Although this is a study topic, we see no way of achieving R4.4-B(1) without also achieving S4.4-B(2). Therefore, we have tried to ensure that there are no holes in the Ada 9X generic contract model. We have patched the holes of Ada 83, and avoided adding new ones related to new Ada 9X features. We agree with the Requirements document -- it is essential to have an air-tight contract model. One might think that the generic formal part would contain all the information that is necessary to determine whether an instantiation is legal. However, we have found that to be infeasible. Therefore, we have extended the contract model to include the entire specification of the generic, including the private part, if any. This means that compile-time rules are checked in the instance specification. On the other hand, compile-time rules are not checked in the instance body; instead, they are checked in an "assume the worst" manner in the generic body. Assume the worst means that we ensure that ANY instance body will be legal. In MS;4.6, certain "scope checking" rules were defined. We are now calling these "accessibility rules". These rules are intended to prevent dangling references. Here's how the Ada 9X generic contract model relates to the accessibility rules. Within a generic body, we must "assume the worst", which in this case means that we must assume that the generic will be instantiated at a place that is more nested than the generic declaration. This implies, for example, that one cannot declare a type extension in a generic body. (Type extensions must be declared at the same level as the parent type.) However, within the specification of the generic, we defer the check until instantiation time, when we know the actual nesting level. This means that if a type extension appears in a generic spec, an instantiation that appears at the same level as the generic declaration will be legal, whereas a more nested instantiation will be illegal. (Remember that the "nesting" we're talking about here does not include nesting within a package.) Here's an example: package Library_Pack_1 is generic type T is tagged private; package G is -- Note to clients: You must instantiate this at library -- level. ... private type T2 is new T with ...; end G; end Library_Pack_1; package Library_Pack_2 is ... end Library_Pack_2; package body Library_Pack_2 is package Instance is new G(...); -- Legal. procedure Nested is package Bad_Instance is new G(...); -- Illegal! begin ... end Nested; end Library_Pack_2; The programmer really wanted to declare type T2 in the body of G. However, that would be illegal. But at least there is a workaround: T2 can be declared in the private part of G. This may not be ideal, but it is the only way we have found to preserve the contract model. In practice, the restrictions are not a problem, since most instantiations can be placed at library level without difficulty. It might seem more consistent to treat the spec of G in the same way as the body. However, that would remove an important set of capabilities. Since bodies generally assume the worst, one needs a way to get around various rules -- that way is to put declarations in the private part of the generic. Given the contract model that we have chosen, it would be strange to do the accessibility checks in a different way.