Function with controlling result type not inherited after derivation?

Hi,
I do not understand how derivation works.
In the following, the only line that poses trouble is the body of the “Appointment” function.
I read:

je-appointments.adb:19:13: error: expected private type “Ada.Containers.Indefinite_Holders.Holder” from instance at je-appointments.ads:29
je-appointments.ads:29:1: error: expected private type “Ada.Containers.Indefinite_Holders.Holder” from instance at je-appointments.ads:29
je-appointments.ads:31:1: error: found type “SHolder” defined at je-appointments.ads:31

with Ada.Calendar, Ada.Streams.Stream_IO, Ada.Containers.Indefinite_Holders;
use  Ada.Calendar, JE.Times, Ada.Streams.Stream_IO;

procedure Test is
package JE.Appointments is
type Appointment_Type is private;
function Details (Appt : Appointment_Type) return String;
function Appointment (Date    : Time_Type;
                     Details : String)    return Appointment_Type;
private
package SH is new Ada.Containers.Indefinite_Holders (String);
type SHolder is new SH.Holder with null record with
 Input => HINput, Output => HOuput;
function HINput (Stream : not null access Ada.Streams.Root_Stream_Type'Class) return SHolder;
procedure HOuput (Stream : not null access Ada.Streams.Root_Stream_Type'Class; T : SHolder);
type Appointment_Type is
  record
     Time    : Time_Type;
     Details : SH.Holder;
  end record;
end JE.Appointments;

package body Appointments is
function Details (Appt : Appointment_Type) return String is
 (Appt.Details.Element);
function Appointment (Date : Time_Type; Details : String) return Appointment_Type is
 (Date, To_Holder (Details));  
function HINput (Stream : not null access Ada.Streams.Root_Stream_Type'Class) return SHolder is
 (To_Holder (String'Input (Stream)));
procedure HOuput (Stream : not null access Ada.Streams.Root_Stream_Type'Class; T : SHolder) is
begin
  String'Output (Stream, T.Element);
end HOuput;
end JE.Appointments;
begin
null;
end Test;

Actually your problem is that it is inherited. Take a look at the problem area:

   function Appointment 
      (Date : Time_Type; 
       Details : String) 
       return Appointment_Type 
   is (Date, To_Holder (Details));  

You are returning “To_Holder” which is an inherited subprogram for your new type SHolder. However your appointment type is looking for the base type SH.Holder. So you are calling the inherited function to initialize the base type, which will not work. You need both types to match. Here are two potential solutions:

  1. Change the call of To_Holder to SH.To_Holder:
   function Appointment 
      (Date : Time_Type; 
       Details : String) 
       return Appointment_Type 
   is (Date, SH.To_Holder (Details));  -- Changed from To_Holder

OR

  1. Change your appointment variable to use your new inherited type as well:
   type Appointment_Type is
      record
         Time    : Time_Type;
         Details : SHolder;  -- Changed from SH.Holder
   end record;
1 Like

oh crap, why can’t I see it ?! I can’t help but make blunders like this.

Well… As Jean-Pierre said during the Ada Workshop (taken from memory):
“I would rather know that something failed than not. Yes, now I have to deal with a failure, but at least I can deal with it”.

Ada has been designed just for that! Don’t feel discouraged! Just because we may not see these kinds of errors in other langs, does not mean we don’t make them!

3 Likes