(Ada)火花中的冰点问题

(Ada)火花中的冰点问题,ada,gnat,Ada,Gnat,我有以下套餐: ------------------- -- File: father.ads ------------------- package Father with SPARK_Mode => On is pragma Elaborate_Body; type Father_T is abstract tagged private; function Get_Field_1 (Self : Father_T) return Positive;

我有以下套餐:

-------------------
-- File: father.ads
-------------------

package Father with SPARK_Mode => On is

   pragma Elaborate_Body;
   
   type Father_T is abstract tagged private;
   
   function Get_Field_1 (Self : Father_T) return Positive;
   
   procedure Proc_1 (Self : in out Father_T; Another : Father_T) is abstract;
   
   function Func_1 (Self : Father_T) return Boolean is abstract;
   
private

   pragma SPARK_Mode (Off);
   
   type Father_T is abstract tagged record
      
      Field_1 : Positive := 1;
      
   end record;
   
end Father;

--------------------------
-- File: father-middle.ads
--------------------------

package Father.Middle with SPARK_Mode => On is

   pragma Elaborate_Body;
   
   type Middle_T is abstract new Father_T with null record; -- [L1]

   overriding procedure Proc_1 (Self : in out Middle_T; Another : Middle_T);
   
private
   
   pragma SPARK_Mode (Off);
   
   function Func_2 (Self : Middle_T) return Boolean;
   
end Father.Middle; -- [L3]

--------------------------
-- File: father-middle.adb
--------------------------

package body Father.Middle is

   ------------
   -- Proc_1 --
   ------------

   overriding procedure Proc_1 (Self : in out Middle_T; Another : Middle_T) is -- [L2]
   begin
      Self.Field_1 := Self.Field_1 + Another.Field_1;
   end Proc_1;

   ------------
   -- Func_2 --
   ------------

   function Func_2 (Self : Middle_T) return Boolean is
   begin
      return False;
   end Func_2;

end Father.Middle;

-------------------------------
-- File: father-middle-lead.ads
-------------------------------

package Father.Middle.Leaf with SPARK_Mode => On is

   pragma Elaborate_Body;
   
   type Leaf_T is new Middle_T with null record;
   
   function Create return Leaf_T;
   
   overriding function Func_1 (Self : Leaf_T) return Boolean;

end Father.Middle.Leaf;
编译器出现以下错误:

父亲中间。ads:7:04:middle类型的第一个冰点必须出现在原始体“Proc_1”(SPARK RM 7.7(8))的早期调用区域内[L1]

中间父区。ads:7:04:区域从中间父区开始。adb:7[L2]

中间父区。ads:7:04:区域结束于中间父区。adb:7[L2]

父亲中。广告:7:04:第17行的第一个冰点[L3]

如果我在Father.Middle.Leaf而不是Father.Middle中重写Proc_1,那么错误就消失了

我读过书,但我是个新手

有没有一种方法可以覆盖父中的Proc_1


我使用的是Windows 10中的GNAT Studio Community 2020。

不幸的是,我没有一个结论性的答案,但我确实怀疑早期的区域分析是否正确

我怀疑的原因是,如果您向继承自
Middle\T
Father.Middle
添加一个新的具体类型
Dummy\T
,那么突然间一切看起来都很好(如下所示)。在我看来(但我在这里可能是错的),添加这样一种类型不应改变
Proc_1
Middle_T
的早期区域分析结果;唯一的区别是,
Middle\T
的凝固点从原始代码中的包装规格末尾移到下面代码中的
Dummy\T
类型定义之前

此外,还不清楚为什么
Father.Middle
正文中的
Proc\u 1
的早期区域没有扩展到包规范中,因为pragma
detaily\u body
已在
Father.Middle
中说明。似乎(如果我理解正确的话)早期区域分析器在
Father.Middle
规范的正文开头或结尾的某个地方检测到一个不可预加工的构造。然而,那里似乎没有这样的东西。因此,在分析扩展代码时可能会出现一些错误,但这纯粹是猜测,因为早期的区域分析器没有提供任何跟踪其行为的信息。因此,很难从最终用户的角度检查分析器的推理

请再次注意,我作为终端用户的分析是假设性的。这个错误可能仍然是正确的,而我可能是错的。我只是觉得我的发现很有趣,可以分享

(GNAT参考文献:、分析仪和)

中间父亲。广告

package Father.Middle with SPARK_Mode is
   pragma Elaborate_Body;
   
   type Middle_T is abstract new Father_T with null record;

   overriding procedure Proc_1 (Self : in out Middle_T; Another : Middle_T);
   
private
   pragma SPARK_Mode (Off);
   
   function Func_2 (Self : Middle_T) return Boolean;
   
   --
   --  ??? Just add a new concrete type and all is fine now?
   --
   
   type Dummy_T is new Middle_T with null record;
   
   overriding function Func_1 (Self : Dummy_T) return Boolean is (False);
   
end Father.Middle;

你试过以下方法吗

type Middle_T is tagged;
overriding procedure Proc_1 (Self : in out Middle_T; Another : Middle_T);
type Middle_T is abstract new Father_T with null record;


有时,为了使用能够声明子程序的功能,向前声明类型会有所帮助。

错误消息的单位和行是什么?感谢您的回复。我已经更新了这个问题。您需要覆盖所有抽象操作(
Proc\u 1
Func\u 1
),以获得
Father\u T
的任何具体扩展,例如
Middle\u T
。由于您没有为
Middle\t
重写
Func\u 1
,因此您的代码有一个错误。验证程序在解释错误方面做得不是很好,但我怀疑编译器会这样做。但是中间部分被声明为抽象的。我错过什么了吗?谢谢。不,我是。我把
Middle\T
误读为一个具体的扩展,对不起。谢谢你的回复!你是对的。错误现在消失了。我不知道发生了什么事。在接受此解决方案之前,我将等待几天,以查看是否发布了新的解决方案。再次感谢。
type Middle_T;
procedure Proc_1 (Self : in out Middle_T; Another : Middle_T);
type Middle_T is abstract new Father_T with null record;