I’m learning SPARK, and I’m facing an error that I don’t understand. With this example I’ve written to practice dependency contracts (even if identifiers are in Spanish, I think will be easy to understand):
package Contactos
with
SPARK_Mode => On,
Abstract_State => Estado
is
type Resultado_T is (Exito, Nombre_Demasiado_Largo, Espacio_Insuficiente);
type Telefono_T is range 1 .. 999_999_999;
procedure Inicializar
with
Global => (Output => Estado),
Depends => (Estado => null);
procedure Agregar_Contacto
(Nombre : String;
Telefono : Telefono_T;
Resultado : out Resultado_T)
with
Global => (In_Out => Estado),
Depends => (Estado => +(Nombre, Telefono),
Resultado => (Nombre, Estado));
end Contactos;
package body Contactos
with
Spark_Mode => On,
Refined_State => (Estado => Array_Contactos)
is
Longitud_Nombre : constant := 64;
subtype Indice_Nombre is Positive range 1 .. Longitud_Nombre;
subtype Nombre_T is String (Indice_Nombre);
type Persona is
record
Nombre : Nombre_T;
Telefono : Telefono_T;
Usado : Boolean;
end record;
Capacidad_Array : constant := 128;
subtype Indice_Array is Positive range 1 .. Capacidad_Array;
type Array_Personas_T is array (Indice_Array) of Persona;
Array_Contactos : Array_Personas_T;
procedure Inicializar is
begin
for Contacto of Array_Contactos loop
Contacto :=
(Nombre => (others => ' '),
Telefono => Telefono_T'Last,
Usado => False);
end loop;
end Inicializar;
procedure Agregar_Contacto
(Nombre : String; Telefono : Telefono_T; Resultado : out Resultado_T)
with
Refined_Global => (In_Out => Array_Contactos),
Refined_Depends => (Array_Contactos => +(Nombre, Telefono),
Resultado => (Nombre, Array_Contactos))
is
Encontrado : Boolean := False;
begin
if Nombre'Length > Nombre_T'Length then
Resultado := Nombre_Demasiado_Largo;
else
Resultado := Espacio_Insuficiente;
for Contacto of Array_Contactos loop
if not Contacto.Usado then
Encontrado := True;
Contacto.Nombre (Contacto.Nombre'First .. Nombre'Length) := Nombre;
Contacto.Telefono := Telefono;
Contacto.Usado := True;
end if;
end loop;
end if;
if Encontrado then
Resultado := Exito;
end if;
end Agregar_Contacto;
end Contactos;
gnatprove
prints this error:
gnatprove -P contactos.gpr contactos.adb |cat
Phase 1 of 2: generation of Global contracts ...
Phase 2 of 2: flow analysis and proof ...
contactos.adb:41:26: medium: missing dependency "Resultado => Telefono"
41 | Resultado => (Nombre, Array_Contactos))
| ^~~~~~~~~
Why is it seeing a dependency between Resultado
and Telefono
? What should a SPARK programmer do in this case?