4

I have a data structure approximately (I am unable to share the full source but can provide additional information on request) as follows:

generic
    type Item_Type is private;
package Util.Pool is
    type Pool is limited new Ada.Finalization.Limited_Controlled with private;

    procedure Get_Available (From: in out Pool; Available: out Natural);
    overriding procedure Finalize (Object: in out Pool);
private
    type Item_Array is array (Positive range <>) of Item_Type;
    type Item_Array_Access is access all Item_Array;

    Null_Item_Array: constant Item_Array_Access := null;

    protected type Protected_Pool is
        function Get_Available return Natural;
    private
        Available: Natural := 0;
        Items: Item_Array_Access := Null_Item_Array;
    end Protected_Pool;

    type Pool is limited new Ada.Finalization.Limited_Controlled with record
        List: Protected_Pool;
    end record;
end Util.Pool;

The full code compiles without errors and warnings but the SPARK prove step fails with the following:

gnatprove -PX:\Path\To\project.gpr -j0 --mode=flow --ide-progress-bar -u main.adb
Phase 1 of 2: generation of Global contracts ...
main.adb:11:05: instantiation error at util-pool.ads:34
main.adb:11:05: effectively volatile type "Protected_Pool" must be declared at library level (SPARK RM 7.1.3(3))
main.adb:11:05: instantiation error at util-pool.ads:45
main.adb:11:05: component "List" of non-volatile type "Pool" cannot be volatile
gnatprove: error during generation of Global contracts

I have read the corresponding parts of the SPARK manual but I fail to understand how to fix my code according to them. TIA.

Arets Paeglis
  • 3,856
  • 4
  • 35
  • 44

1 Answers1

7

Looks as though you’re instantiating the generic within your Main. This is not 'at library level'.

Instantiate as a library level package, should work better. This needs to go in a file (in this case) my_util_pool.ads:

with Util.Pool;
package My_Util_Pool is new Util.Pool (Integer);

main.adb now starts

with My_Util_Pool;
with ...;
procedure Main is
   ...
Simon Wright
  • 25,108
  • 2
  • 35
  • 62
  • 1
    When instantiated outside the `Main` procedure, the compilation suddenly fails with `main.adb:5:08: keyword "body" expected here [see file name]` `main.adb:20:10: missing "end Test_Pool;"` , what am I doing wrong? – Arets Paeglis Nov 06 '20 at 20:31
  • Why is the type `Protected_Pool` effectively volatile? – debater Nov 09 '20 at 17:10
  • 1
    @debater, because it is: 5th paragraph of [the SPARK reference manual 7.1.2](https://docs.adacore.com/spark2014-docs/html/lrm/packages.html#external-state). As to justification: values held within the PO might change at any time, outside the control of a particular thread (guessing here, but seems likely) – Simon Wright Nov 09 '20 at 20:22
  • @AretsPaeglis, sorry I didn’t see your comment before: hard to say, you’ve never shown us your `main.adb`, either the original or as amended. Hope you’ve fixed it up yourself. – Simon Wright Feb 10 '21 at 22:22