Ada 2020 (50日目) - 6月13日の電子会議の結果

6月13日に行われた電子会議の議事録が公開されました。

内部イテレータ(procedural iterator)の制限

Allows_ExitParallel_Iterator はサブプログラムを指すaccess型の引数を複数持つサブプログラムには指定できなくなりました。 どの引数に対する性質かを特定できないためです。

また Parallel_Iterator が呼び出すサブプログラムが本当にリエントラントなのかチェックするための Parallel_Calls アスペクトが追加されました。

Parallel_Callsアスペクト

Parallel_Calls が指定されたサブプログラムはリエントラント(再入可能)でなければなりません。

declare
   procedure Parallel_Countdown
     (N : in Natural;
      P : not null access procedure (I : in Positive))
      with Parallel_Iterator is
   begin
      parallel for I in reverse 1 .. N loop
         P (I);
      end loop;
   end Countdown;
   X : array (1 .. 10) of Boolean := (others => False);
begin
   parallel for (I : in Positive) of Parallel_Countdown (10) loop
      X (I) := True;
   end loop;

この例はこのように展開されます。

declare
   -- 省略
   X : array (1 .. 10) of Boolean := (others => False);
   procedure Loop_Body (I : in Positive) with Parallel_Calls is
   begin
      X (I) := True;
   end Loop_Body;
begin
   Parallel_Countdown (10, Loop_Body'Access);

リエントラントかどうかのチェックはpragma Conflict_Check_Policy によります。

配列の各要素へのアクセスがどう推定されるかよく理解しておらず申し訳ないのですが、もし X 全体へのoutアクセスと見做されるなら Loop_Body の呼び出し同士が衝突してしまいますので pragma Conflict_Check_Policy (No_Conflict_Checks); で抑制することが必要になるかもしれません。

外部イテレータ(Parallel_Iterator)の制限

こちらは同じ Parallel_Iterator でも外部イテレータの方の制限です。 定義へのリンクを再掲しておきます。

チャンク有りの First/Next は例外を送出してはいけない、異なるチャンク番号に対して重複した範囲を返してはならない、等の制限が追加されました。

固定小数点型の属性

浮動小数点型にあって固定小数点型にない関数形式の属性を実装依存で実装しても良いことになりました。

'Floor'Ceiling'Rounding'Unbiased_Rounding'Machine_Rounding'Truncation が該当します。

実装依存なら勝手に実装しても良さそうなものですが、実装依存の属性は言語が定義した属性と同じ名前を使えないというルールがあります。

匿名のaccess型のdiscriminantのAccessibility_Check

匿名のaccess型を返す関数には行われていた静的な Accessibility_Check がdiscriminantに対して見逃されていたケースがあり、修正されました。

Default_Valueとoutパラメータでの変換

49日目でも触れましたように、 Default_Value を持つ型のoutパラメータは実際にはin outです。

Default_Value を持つ型の変数を変換で Default_Value を持たないout引数に渡してしまいますと Default_Value を持つ型の未初期化変数を作り出せてしまいます。

このような呼び出しの中での変換が禁止されます。

declare
   procedure Uninitialize (X : out Integer) is
   begin
      null;
   end Uninitialize;
   type D is new Integer with Default_Value => 0;
begin
   Uninitialize (Integer (D)); -- error

Uninitialize の仮引数 XDefault_Value を持たない本物のoutパラメータですので中で代入しなければ未初帰化値が返ります。

access型のnon nullの有無や指す先の制約による違いについても同様の変更が提案されていて、そちらは詰められている途中です。

delta aggregate式のタグ

タグ付き型の値をdelta aggregateで更新した場合にタグは元の値のものを使うことになっていました。

declare
   type T is tagged record
      E, F : Integer;
   end record;
   function Update_E1 (X : in out T) return T'Class is
   begin
      return (X with delta E => X.E + 1);
   end Update_E1;
   type D is new T with record
      G : Integer;
   end record;
   V : D := D'(E => 1, F => 2, G => 3);
   R : T'Class := Update_E1 (V); -- D'(E => 2, F => 2, G => 3)
begin
   if R in D then -- True
      null;
   end if;

しかし、式の代入先がclass-wide型ではない場合に型が合わなくなります。

declare
   -- 省略
   function Update_E2 (X : in out T) return T'Class is
      Temporary : T := (X with delta E => X.E + 1); -- TにDを代入しようとしている
   begin
      return Temporary;
   end Update_E2;
   -- 省略
   R : T'Class := Update_E1 (V); -- Tag_Error

このため求められている型がclass-wide型ではない場合はaggregate式自体の型になるよう修正されました。

declare
   -- 省略
   function Update_E2 (X : in out T) return T'Class is
      Temporary : T := (X with delta E => X.E + 1); -- Tになる
   begin
      return Temporary;
   end Update_E2;
   -- 省略
   R : T'Class := Update_E2 (V); -- T'(E => 2, F => 2);
begin
   if R in D then -- False
      null;
   end if;

Type_Invariant’Classの修正

Type_Invariant'Class を持つ型から派生した場合はその型を返す関数に加えてin outパラメータやout パラメータを持つ手続きも overriding しないといけません。

その際に該当するプリミティブが現在位置から不可視であっても overriding しないといけない不可能な文面になっていたのが修正されました。

値のrenames

ついに値の renames が認められてしまいました。

declare
   One renames 1.0;

え!? ここに来てこんなのぶっ込んできます!? 36日目の話はなんだったんだ……。

9日目36日目を修正しました。

Interfaces.Shift_Left​/Shift_Right​/Shift_Right_Arithmetic​/Rotate_Left​/Rotate_Right

staticになりました。

その他サンプルコード等の修正

例によってサンプルコード等の修正がひとつのAI(AI12-0379-1)で行われています。

関連AI