确保在编译时覆盖异常

Ensure exception coverage at compile time

有没有办法让 GNAT 确保处理所有异常情况?

举个例子:

   package IO renames Ada.Text_IO;
   package EIO renames Ada.IO_Exceptions;

   procedure Open_File (File : in out IO.File_Type) is
   begin
      IO.Open (File, IO.In_File, "example.txt");
   exception
      when EIO.Use_Error =>
         IO.Put_Line ("Use!");
      when EIO.Device_Error =>
         IO.Put_Line ("Device!");
   end Open_File;

Open 也可以提高 Name_Error 所以我希望 GNAT 警告这个案例还没有被处理。

我找到了 pragma Restrictions (No_Exception_Propagation),但这似乎也将检查应用于标准库调用,因此 Open 变得不可用,因为它本身会传播异常。如果我将此应用于我的示例,我得到:

14:07: warning: pragma Restrictions (No_Exception_Propagation) in effect
14:07: warning: this handler can never be entered, and has been removed
16:07: warning: pragma Restrictions (No_Exception_Propagation) in effect
16:07: warning: this handler can never be entered, and has been removed

举例说明我想从另一种语言中得到什么; Nim 有一个 raises pragma 来注释过程可以引发哪些异常,这是编译器强制执行的。该列表可以为空,即。 raises: [],并且编译器将要求处理所有异常而不传播。 Ada 中是否有与此等效的内容?

如果你想处理所有可用的异常,你可以在exception部分使用when others。您的示例将如下所示:

package IO renames Ada.Text_IO;
package EIO renames Ada.IO_Exceptions;

procedure Open_File (File : in out IO.File_Type) is
begin
   IO.Open (File, IO.In_File, "example.txt");
exception
   when An_Exception : others =>
      IO.Put_Line (EIO.Exception_Message(An_Exception));
end Open_File;

如果您想以单独的方式处理每个异常,则必须单独列出每个异常(如您的示例所示)。但是编译器不会警告您缺少异常处理程序。

这在 Ada 中是不可能的。

Nim 能够做到这一点,因为 raises pragma 是函数签名的一部分。因此,对于任何调用,可以静态知道可以引发哪些异常。在 Ada 中不是这样。

如果您认为编译器可以隐式地找出任何子例程可以引发哪些异常,那是对的,但不能解决问题,因为 Ada 允许分派调用和函数指针。对于这两个,您静态地不知道将被调用的函数(无论如何都没有指针分析,这超出了大多数编译器的范围),因此无法知道可能引发的异常(因为它们不是一部分签名)。