!standard 12.7(10/2) 20-01-14 AC95-00322/00 !class confirmation 20-01-14 !status received no action 20-01-14 !status received 19-11-14 !subject Generic signature package subprogram visibility !summary !appendix From: Vincent Marcante Sent: Thursday, November 14, 2019 9:35 AM Object Ada and GNAT respond differently to the code that appears at the end of this message. Object Ada compiles and runs it as expected but GNAT indicates “no visible subprogram matches the specification for "Put" “ at the definition of package Signature_Package_Reexport_Instance A c.l.a commenter indicated that he had had this problem forever too, but was told by the GNAT and Ada experts that this was actually expected behavior - something to do with whether the user of the generic instance can see what the actual parameters were. So if you pass the signature package as a parameter in the instantiation of another generic, then you can reference the formal parameters, but if the compiler see statically what the actual parameters are, you cannot. This is a pain point when using generics. One workaround is to put a rename declaration in the generic “signature” package: but this is a pain because we have to invent a second name to designated the same thing. So, should all of the following be compilable? If the standard in fact requires disallowance, I wonder what "bad" thing is being prevented/avoided by not allowing the naturally expected, non-painful behavior. Might changing the standard to allow it - or be clear that it is allowed - be warranted? with Ada.Text_IO; package Ada_Text_IO_Adaptor is procedure Put (X : in Integer; Base : in Ada.Text_IO.Number_Base); procedure New_Line; end Ada_Text_IO_Adaptor; ------- with Ada.Integer_Text_IO; package body Ada_Text_IO_Adaptor is procedure Put (X : in Integer; Base : in Ada.Text_IO.Number_Base) is begin Ada.Integer_Text_IO.Put(Item=>X,Base=>Base); end Put; procedure New_Line is begin Ada.Text_IO.New_Line; end New_Line; end Ada_Text_IO_Adaptor; ------- generic type Number_Base is range <>; Default_Base : Number_Base; with procedure Put (X : in Integer; Base : in Number_Base := Default_Base) is <>; with procedure Put (X : in String) is <>; with procedure Put_Line (X : in String) is <>; with procedure New_Line is <>; package Signature_Package_Generic is end; ------- with Ada.Text_IO, Ada.Integer_Text_IO, Ada_Text_IO_Adaptor; use Ada.Text_IO, Ada.Integer_Text_IO, Ada_Text_IO_Adaptor; with Signature_Package_Generic; package Signature_Package_Instance is new Signature_Package_Generic (Number_Base => Ada.Text_IO.Number_Base, Default_Base => 10); ------- with Signature_Package_Generic; generic with package Instance is new Signature_Package_Generic(<>); procedure Signature_Package_Instance_Test_Generic; ------- procedure Signature_Package_Instance_Test_Generic is begin Instance.New_Line; Instance.Put_Line("Direct Instance Put_Line(""string"")"); Instance.Put ("Direct Instance Put (""string"")"); end; ------- with Signature_Package_Instance; with Signature_Package_Instance_Test_Generic; procedure Signature_Package_Instance_Test is new Signature_Package_Instance_Test_Generic (Signature_Package_Instance); --compiles and runs as expected (Put is visible) ------- with Signature_Package_Generic; generic with package Instance is new Signature_Package_Generic(<>); package Signature_Package_Reexport_Generic is subtype Number_Base is Instance.Number_Base; Default_Base : Number_Base := Instance.Default_Base; procedure Put (X : in Integer; Base : in Number_Base := Default_Base) renames Instance. Put; procedure Put (X : in String) renames Instance. Put; -- instantiation error procedure Put_Line (X : in String) renames Instance. Put_Line; procedure New_Line renames Instance. New_Line; end Signature_Package_Reexport_Generic; ------- with Signature_Package_Instance; with Signature_Package_Reexport_Generic; package Signature_Package_Reexport_Instance is new Signature_Package_Reexport_Generic (Signature_Package_Instance); --Builder results -- Signature_Package_Reexport_Instance.ads -- 108:1 instantiation error at signature_package_reexport_generic.ads:98 -- 108:1 no visible subprogram matches the specification for "Put" ------- with Signature_Package_Reexport_Instance; procedure Signature_Package_Reexport_Test is begin Signature_Package_Reexport_Instance.New_Line; Signature_Package_Reexport_Instance.Put_Line("Reexport Put_Line(""string"")"); Signature_Package_Reexport_Instance.Put ("Reexport Put (""string"")"); end; *************************************************************** From: Tucker Taft Sent: Thursday, November 14, 2019 3:07 PM This looks like a GNAT bug. If the formal package has (<>) as its actual parameter part, then all of the formal parameters are visible in the visible part of the formal package. If some of the actual parameters are specified in the declaration of the formal package, then the formal corresponding to those actuals are *not* visible. The general rule is either the actual or the formal is visible, but never both. But in this example, the actual parameter part is (<>), so all of the formals are visible. Below is the relevant section of the (annotated) Ada RM (12.7(10-10.b)). 10/2 {AI95-00317-01} The visible part of a formal package includes the first list of basic_declarative_items of the package_specification. In addition, for each actual parameter that is not required to match, a copy of the declaration of the corresponding formal parameter of the template is included in the visible part of the formal package. If the copied declaration is for a formal type, copies of the implicit declarations of the primitive subprograms of the formal type are also included in the visible part of the formal package. 10.a/2 Ramification: {AI95-00317-01} If the formal_package_actual_part is (<>), then the declarations that occur immediately within the generic_formal_part of the template for the formal package are visible outside the formal package, and can be denoted by expanded names outside the formal package. If only some of the actual parameters are given by <>, then the declaration corresponding to those parameters (but not the others) are made visible. 10.b/3 Reason: {AI05-0005-1} We always want either the actuals or the formals of an instance to be nameable from outside, but never both. If both were nameable, one would get some funny anomalies since they denote the same entity, but, in the case of types at least, they might have different and inconsistent sets of primitive operators due to predefined operator “reemergence.” Formal derived types exacerbate the difference. We want the implicit declarations of the generic_formal_part as well as the explicit declarations, so we get operations on the formal types. *************************************************************** From: Vincent Marciante Sent: Friday, November 15, 2019 7:08 AM Thankyou for your very quick response. May I quote this to comp.lang.ada? Noting your email address, may I assume that Adacore is now aware of this issue or must I also sent a report to “GNAT bugs” email address? *************************************************************** From: Tucker Taft Sent: Friday, November 15, 2019 3:27 PM You may quote me on comp.lang.ada, but as an individual. I don't "officially" speak for AdaCore ;-) Also, if you could, please report the bug yourself, with a simple, compilable "reproducer." This ensures that the bug report gets properly logged into our tracking system. *************************************************************** From: Randy Brukardt Sent: Tuesday, July 2, 2019 10:17 PM ***************************************************************