There is a little difference with the presented code and the general presentation.
We have included an inv(Middle) method to show that ada actually uses late-binding, but with a strong invariant signature policy.

:::::::::::::::::::::::::::::::::::::::::::::::::::::::
code
::::::::::::::::::::::::::::::::::::::::::::::::::::::
------------------------------------------------
package Top_class is
  type Top is tagged null record;
end Top_class;
------------------------------------------------
with Top_class;
package Middle_class is
   type Middle is new Top_class.Top with null record;
end Middle_class;
------------------------------------------------
with Middle_class;
package Bottom_class is
   type Bottom is new Middle_class.Middle with null record;
end Bottom_class;
------------------------------------------------
with Top_class; use Top_class;
with Middle_class; use Middle_class;
with Bottom_class; use Bottom_class;

package Up_class is

   type Up is tagged null record;
   procedure cv(This : Up; Arg : Top);
   procedure inv(This : Up; Arg : Middle);
   procedure ctv(This : Up; Arg : Bottom);

end Up_class;
------------------------------------------------
with Up_class; use Up_class;
with Middle_class; use Middle_class;

package Down_class is

   type Down is new Up with null record;
   procedure cv(This : Down; Arg : Middle);
   procedure inv(This : Down; Arg : Middle);
   procedure ctv(This : Down; Arg : Middle);

end Down_class;
------------------------------------------------
with Gnat.Io; use Gnat.Io;
with Top_class; use Top_class;
with Middle_class; use Middle_class;
with Bottom_class; use Bottom_class;

package body Up_class is

   procedure cv(This : Up; Arg : Top) is
      begin
         Put_Line("cv(Up, Top) in Up");
      end cv;

   procedure inv(This : Up; Arg : Middle) is
      begin
         Put_Line("inv(Up, Middle) in Up");
      end inv;

   procedure ctv(This : Up; Arg : Bottom) is
      begin
         Put_Line("ctv(Up, Bottom) in Up");
      end ctv;

end Up_class;
------------------------------------------------
with Gnat.Io; use Gnat.Io;
with Middle_class; use Middle_class;

package body Down_class is

   procedure cv(This : Down; Arg : Middle) is
      begin
         Put_Line("cv(Down, Middle) in Down");
      end cv;

   procedure inv(This : Down; Arg : Middle) is
      begin
         Put_Line("inv(Down, Middle) in Down");
      end inv;

   procedure ctv(This : Down; Arg : Middle) is
      begin
         Put_Line("ctv(Down, Middle) in Down");
      end ctv;

end Down_class;
------------------------------------------------
-- ::::::::::::
-- cocon ada 95
-- ::::::::::::
with Gnat.Io; use Gnat.Io;

with Up_class; use Up_class;
with Down_class; use Down_class;
with Top_class; use Top_class;
with Middle_class; use Middle_class;
with Bottom_class; use Bottom_class;

procedure Cocon is
   U : Up;
   D : Down;
   UD: Up'Class := D;
   T : Top;
   M : Middle;
   B : Bottom;
begin

   Put_Line ("-- First test suite");
   cv(This => U, Arg => T);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Down, Top) found (Up, Middle)");
--    cv(This => U, Arg => M);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Down, Top) found(Up, Bottom)");
--    cv(This => U, Arg => B);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Down, Bottom) found(Up, Top)");
--    ctv(This => U, Arg => T);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Down, Bottom) found(Up, Middle)");
--    ctv(This => U, Arg => M);
   ctv(This => U, Arg => B);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Down, Middle) found(Up, Top)");
--   inv(This => U, Arg => T);
   inv(This => U, Arg => M);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Down, Middle) found(Up, Bottom)");
--   inv(This => U, Arg => B);

   Put_Line ("-- Second test suite");
   cv(This => D, Arg => T);
   cv(This => D, Arg => M);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Up, Middle) found(Down, Bottom)");
--    cv(This => D, Arg => B);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Up, Middle) found(Down, Top)");
--    ctv(This => D, Arg => T);
   ctv(This => D, Arg => M);
   ctv(This => D, Arg => B);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Up, Middle) found(Down, Top)");
--   inv(This => D, Arg => T);
   inv(This => D, Arg => M);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Up, Middle) found(Down, Bottom)");
--   inv(This => D, Arg => B);
 

   Put_Line ("-- Third test suite");
   cv(This => UD, Arg => T);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Down, Top) found(Up, Middle)");
--    cv(This => UD, Arg => M);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Down, Top) found(Up, Bottom)");
--    cv(This => UD, Arg => B);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Down, Bottom) found(Up, Top)");
--    ctv(This => UD, Arg => T);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Down, Bottom) found(Up, Middle)");
--    ctv(This => UD, Arg => M);
   ctv(This => UD, Arg => B);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Down, Middle) found(Up, Top)");
--   inv(This => UD, Arg => T);
   inv(This => UD, Arg => M);
   Put_Line ("no candidate interpretations match the actuals: expected cv(Down, Middle) found(Up, Bottom)");
--   inv(This => UD, Arg => B);

end;

:::::::::::::::::::::::::::::::::::::::::::::::::::::::
results
::::::::::::::::::::::::::::::::::::::::::::::::::::::

-- First test suite
cv(Up, Top) in Up
no candidate interpretations match the actuals: expected cv(Down, Top) found (Up, Middle)
no candidate interpretations match the actuals: expected cv(Down, Top) found(Up, Bottom)
no candidate interpretations match the actuals: expected cv(Down, Bottom) found(Up, Top)
no candidate interpretations match the actuals: expected cv(Down, Bottom) found(Up, Middle)
ctv(Up, Bottom) in Up
no candidate interpretations match the actuals: expected cv(Down, Middle) found(Up, Top)
inv(Up, Middle) in Up
no candidate interpretations match the actuals: expected cv(Down, Middle) found(Up, Bottom)
-- Second test suite
cv(Up, Top) in Up
cv(Down, Middle) in Down
no candidate interpretations match the actuals: expected cv(Up, Middle) found(Down, Bottom)
no candidate interpretations match the actuals: expected cv(Up, Middle) found(Down, Top)
ctv(Down, Middle) in Down
ctv(Up, Bottom) in Up
no candidate interpretations match the actuals: expected cv(Up, Middle) found(Down, Top)
inv(Down, Middle) in Down
no candidate interpretations match the actuals: expected cv(Up, Middle) found(Down, Bottom)
-- Third test suite
cv(Up, Top) in Up
no candidate interpretations match the actuals: expected cv(Down, Top) found(Up, Middle)
no candidate interpretations match the actuals: expected cv(Down, Top) found(Up, Bottom)
no candidate interpretations match the actuals: expected cv(Down, Bottom) found(Up, Top)
no candidate interpretations match the actuals: expected cv(Down, Bottom) found(Up, Middle)
ctv(Up, Bottom) in Up
no candidate interpretations match the actuals: expected cv(Down, Middle) found(Up, Top)
inv(Down, Middle) in Down
no candidate interpretations match the actuals: expected cv(Down, Middle) found(Up, Bottom)