ada

Alias usage in Ada language


Package pack1 is 

  Type int_acc_type is access all integer;

End pack1;

--Local procedure
with pack1;
Procedure main is

 Int_acc : pack1.int_acc_type;
 Int_var : aliased integer;

Begin
   Int_acc := Int_var'access;

End main;

Compiler is throwing error at above access assignment saying non-local pointer cannot be assigned with local value. I don't understand why the error because I just defined the type in package, but actual object for access is defined inside the local procedure only.

I expect no error, but as per language it will error.


Solution

  • The issue is that the Access type is defined at "library level" (basically highest lifetime possible) while the variable is declared at a lower/deeper level inside a function.

    Ada forbids assigning a lower/deeper level object to a higher level type because the object will be deallocated long before the access type is out of scope. Since Ada can have some auto deallocation rules process when access types leave scope (in some cases), the language forbids assigning a lower scope object to a higher scope access type.

    It also is worried that you could potentially create an access type object at higher scope and pass that local access type object to it, which then means that higher scope object would dangle. (general case the compiler has to consider).

    In your specific case, there wouldn't be any issue, but the compiler needs to account for the general case.

    That said, the Ada language could definitely use more fine grained access type rules overhaul to allow situations like this. It's definitely technically possible to do this in the general sense, the language just doesn't support it at this time. You can definitely make a suggestion (issue) at the Ada Rapporteur Group (ARG) github user community input repo: https://github.com/Ada-Rapporteur-Group/User-Community-Input

    On your end, you can do a couple of things:

    1. Create a local access type inside the function and assign the object to a variable of that type.
    2. Create a reference type and assign the var to that, it'll do some runtime checks in addition to compile time checks.
    with Ada.Text_IO; use Ada.Text_IO;
    with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
    procedure jdoodle is
        Package pack1 is 
    
          Type int_acc_type is access all integer;
          
          -- Reference type
          type int_acc_type2(Element : not null access Integer) is limited null record
             with Implicit_Dereference => Element;
        
        End pack1;
        
        Procedure main is
        
         Int_acc : pack1.int_acc_type;
         Int_var : aliased integer;
         
         Int_acc2 : pack1.int_acc_type2(Int_Var'Access);
         
         -- Local access type
         type int_acc_type3 is access all integer;
         
         Int_acc3 : int_acc_type3;
        
        Begin
           --Int_acc := Int_var'access;
           Int_acc3 := Int_var'Access;
           null;
        End main;
    begin
        null;
    end jdoodle;