如何使用子包/通用包实例化中的类型

How to use a type from a child package / generic package instantiation

我可以使一个类型的原始子程序直接可见 use all type 像这样:

package Type_Package is
   type T is null record;
   procedure Action(X: T) is null;
end Type_Package;

with Type_Package;
procedure Use_Type is
   use all type Type_Package.T;
   X: Type_Package.T;
begin
   Action(X);
end Use_Type;

但是我把Type_Package移到里面好像不行 Use_Type.

procedure Use_Type is
   package Type_Package is
      type T is null record;
      procedure Action(X: T) is null;
   end Type_Package;
   use all type Type_Package.T;
   X: Type_Package.T;
begin
   Action(X);
end Use_Type;

我明白了

gcc -c use_type.adb
use_type.adb:9:04: "Action" is not visible
use_type.adb:9:04: non-visible declaration at line 4
gnatmake: "use_type.adb" compilation error

当我实例化一个通用包时,同样的事情发生了。为了 例如,当我想使用 Ada.Containers.

中的数据类型时
package Element_Set is
   new Ada.Containers.Hashed_Sets(Element_Type, Hash, "=");
use all type Element_Set.Set;

这里的use type子句好像没有作用

在子包或子包中声明类型时如何使用类型 通用包的实例化?

我不确定这是一个编译器错误(更新: Simon Wright 确认这是一个错误)还是有意为之,但您的解决方法包括:

对整个包使用 "use Type_Package" - 可能是最简单但最繁琐的

使用一些 procedure/function 重命名子句 - 这需要更多的工作,但不会使整个包可见。例如:

procedure Hello is
    package Type_Package is
        type T is null record;
        procedure Action(X: T) is null;
    end Type_Package;

    use all type Type_Package.T;
    X: Type_Package.T;

    procedure Action(X : Type_Package.T) renames Type_Package.Action;

begin
    Action(X);
end Hello;

对于通用包,在库级别声明它们 - 这对嵌套包没有帮助,但对通用包有用。您可以对单个通用包执行以下操作:

Type_Package.ads

with Use_All_Type;
package Type_Package is new Use_All_Type;

Use_All_Type.ads

generic
package Use_All_Type is

   type T is null record;
   procedure Action(X: T) is null;

end Use_All_Type;

或多个通用包:

Type_Package.ads

with Use_All_Type;
package Type_Package is 
   package UAT is new Use_All_Type;
   subtype T is UAT.T;
   use all type UAT.T;

   -- repeat for other generics
end Type_Package;

Use_All_Type.ads

generic
package Use_All_Type is

   type T is null record;
   procedure Action(X: T) is null;

end Use_All_Type;

这两种方法都适用于以下主程序:

with Type_Package;

procedure Main is

   use all type Type_Package.T;
   X: Type_Package.T;

begin
   Action(X);
end Main;

旁注:如果这里没有人明确回答这是否有意,您可以考虑向 AdaCore 发送错误报告。

您确实发现了一个编译器错误。

有一组测试(Ada Conformity Assessment Test Suite, ACATS - also here),其中 "B series" 旨在检查编译器是否捕获错误。

其中一个测试 B840003 开始时与您的问题类似:经过精简和稍微修改后的版本表现如下:

 1. procedure B840003 is
 2. begin
 3.
 4.    declare
 5.       package Pkg_1 is
 6.          type Enum is (Aaa, Bbb, Ccc);
 7.          procedure Prim_Proc (X : Enum := Aaa) is null;
 8.          function Prim_Func return Enum is (Bbb);
 9.
10.          package Nested is
11.             procedure Nonprim_Proc (X : Enum := Bbb) is null;
12.             function Nonprim_Func return Enum is (Ccc);
13.          end Nested;
14.
15.       end Pkg_1;
16.
17.    begin
18.       declare
19.          use all type Pkg_1.Enum;
20.       begin
21.          if Prim_Func /= Bbb then                                  -- OK.
22.             null;
23.          end if;
24.          if Nonprim_Func (Ccc) /= Ccc then                         -- ERROR:
                |
    >>> "Nonprim_Func" is not visible
    >>> non-visible declaration at line 12

25.             null;
26.          end if;
27.          Prim_Proc;                                                -- OK.
28.          Nonprim_Proc (Aaa);                                       -- ERROR:
             |
    >>> "Nonprim_Proc" is not visible
    >>> non-visible declaration at line 11

29.       end;
30.    end;
31.
32. end B840003;

(见第 27 行)而一个更像你的例子(将包声明拉到子程序的声明区域)这样做:

 1. procedure B840003_Mod is
 2.    package Pkg_1 is
 3.       type Enum is (Aaa, Bbb, Ccc);
 4.       procedure Prim_Proc (X : Enum := Aaa) is null;
 5.       function Prim_Func return Enum is (Bbb);
 6.
 7.       package Nested is
 8.          procedure Nonprim_Proc (X : Enum := Bbb) is null;
 9.          function Nonprim_Func return Enum is (Ccc);
10.       end Nested;
11.
12.    end Pkg_1;
13.
14.    use all type Pkg_1.Enum;
15. begin
16.    if Prim_Func /= Bbb then                                  -- OK.
17.       null;
18.    end if;
19.    if Nonprim_Func (Ccc) /= Ccc then                         -- ERROR:
          |
    >>> "Nonprim_Func" is not visible
    >>> non-visible declaration at line 9

20.       null;
21.    end if;
22.    Prim_Proc;                                                -- OK.
       |
    >>> "Prim_Proc" is not visible
    >>> non-visible declaration at line 4

23.    Nonprim_Proc (Aaa);                                       -- ERROR:
       |
    >>> "Nonprim_Proc" is not visible
    >>> non-visible declaration at line 8

24.
25. end B840003_Mod;

参见第 22 行(过程调用;第 16 行的函数调用正常!)。

这值得向 AdaCore 报告错误(尽管我不希望他们放弃所有内容并急于修复它)。


有趣的是,早期版本的编译器例如GNAT CE 2018) 发现 BbbCcc 不可见。