Как использовать тип из дочернего пакета / экземпляра пакета generi c - PullRequest
2 голосов
/ 16 февраля 2020

Я могу сделать примитивные подпрограммы типа непосредственно видимыми с помощью 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

То же самое происходит, когда я создаю экземпляр универсального c пакета. Например, когда я хочу использовать типы данных в Ada.Containers.

package Element_Set is
   new Ada.Containers.Hashed_Sets(Element_Type, Hash, "=");
use all type Element_Set.Set;

Предложение use type здесь, кажется, не имеет никакого эффекта.

Как использовать тип, когда тип объявлен в дочернем пакете или в экземпляре универсального c пакета?

Ответы [ 2 ]

3 голосов
/ 17 февраля 2020

Вы действительно обнаружили ошибку компилятора.

Существует набор тестов ( Ada Conformity Assessment Test Suite , ACATS - также здесь ), в которых «Серия B» предназначена для проверки того, что компиляторы ловят ошибки.

Один из этих тестов, 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 (хотя я бы не ожидал, что они все отбросят и ru sh исправят это ).


Интересно, что более ранние версии компилятора, например, GNAT CE 2018) находят Bbb, Ccc невидимым.

2 голосов
/ 16 февраля 2020

Я не уверен, является ли это ошибкой компилятора ( Обновление: Саймон Райт подтвердил это как ошибку) или предназначено, но ваши варианты обхода включают:

Использование «использовать Type_Package» для всего пакета - возможно, самый простой, но самый сложный

Использовать некоторые пункты процедуры / переименования функций - это требует больше работы, но не делает весь видимый пакет. EX:

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;

для пакетов generi c, объявите их на уровне библиотеки - это не поможет с вложенными пакетами, но будет полезно для generi c. Вы можете сделать это для одного универсального пакета c, выполнив следующее:

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;

или для нескольких универсальных c пакетов:

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;

Примечание: вы можете рассмотреть возможность отправки A daCore сообщение об ошибке, если здесь никто не дает однозначного ответа на вопрос, предназначено это или нет.

...