AI22-0030-1

!standard 5.5.2(6.1/4)          22-01-26 AI22-0030-1/02

!class binding interpretation 22-01-25

!status Amendment 1-2022 22-05-05

!status WG9 Approved 22-10-18

!status ARG Approved 13-0-0 22-05-05

!status work item 21-06-04

!status received 21-04-28

!submitter Stephen Baird

!priority Low

!difficulty Easy

!qualifier Omission

!subject Array iterators of slices

!summary

The object of an array or container iterator must allow renaming.

!issue

In the 8.5.1 rules for renaming, we have a special rule about slices:

A slice of an array shall not be renamed if this restriction disallows renaming of the array.

In 5.5.2(6.1/4), that seems to be missing.

Is this a problem? (Yes.)

!recommendation

(See Summary.)

!wording

Replace 5.5.2(6.1/4):

The iterator_name or iterable_name of an iterator_specification shall not denote a subcomponent that depends on discriminants of an object whose nominal subtype is unconstrained, unless the object is known to be constrained.

with:

The iterator_name or iterable_name of an iterator_specification shall denote an object for which renaming is allowed (see 8.5.1).

Replace AARM 5.5.2(6.a/4) with:

AARM Reason: This prevents the object from disappearing while the iterator is still using it.

!discussion

The wording "denotes an object for which renaming is allowed" (or a variant of it) is used in 8.5.4(5.3/5), 12.4(7), and 12.6(8.4/5). We conclude that it should be used here as well -- it makes the intent clearer and also "future-proofs" this wording as it will adjust for any future changes to the renaming rules.

!example

procedure Foo is
  subtype Index is Integer range 1 .. 100;
  type Float_Vec is array (Index) of Float;
  type Int_Vec is array (Index) of Integer;

  type Rec (Has_Ints : Boolean := True) is
     record
        case Has_Ints is
           when False => Floats : Float_Vec;
           when True => Ints : Int_Vec;
        end case;
     end record;

   
  X : Rec := (Has_Ints => True, Ints => (others => 0));
begin
  for E of X.Ints (1 ..10) loop -- (1)
     X := (Has_Ints => False, Floats => (others => 1234.5)); -- (2)
     E := E + 1;
  end loop;
end Foo;

The new rule makes (1) illegal, while the previous rule allowed (1). However, if (1) is allowed, the assignment to X means that X.Ints ceases to exist during the first iteration of the loop. Further iterations would continue to use the now nonexistent array, which would not be good.

!corrigendum 5.5.2(6.1/4)

@drepl
The @i{iterator_}@fa{name} or @i{iterable_}@fa{name} of an
@fa{iterator_specification} shall not denote a subcomponent that
depends on discriminants of an object whose nominal subtype is
unconstrained, unless the object is known to be constrained.
@dby
The @i{iterator_}@fa{name} or @i{iterable_}@fa{name} of an
@fa{iterator_specification} shall denote an object for which renaming
is allowed (see @ref{8.5.1}).

 

!ACATS test

An ACATS B-Test should test a case like the example (perhaps add this to an existing test for 5.5.2(6.1/4)).

!appendix

From: Stephen Baird [privately]

Sent: Tuesday, November 30, 2021 5:19 PM

In the 8.5.1 rules for renaming, we have a special rule about slices:

  A slice of an array shall not be renamed if this restriction disallows

  renaming of the array.

In 5.5.2(6.1), that seems to be missing.

Is this a (tiny) problem?

Note how 12.4(7) manages to deal with this via a dubious technique:

   For a generic formal object of mode in out, the actual shall be a name

   that denotes a variable for which renaming is allowed (see 8.5.1).

All of this taken together suggests to me that we ought to define the notion

of a "renamable" object name (probably in 8.5.1) and then use this term in all

three places. Or we could copy the 12.4(7) cheat in 5.5.2, but I don't much

like that idea. Although I do like it better than adding a sentence about

slices in 5.5.2 .

What do you think?

****************************************************************

From: Randy Brukardt [privately]

Sent: Wednesday, December 1, 2021 2:24 AM

I think this approach would make sense. Doesn't the prefix of 'Access follow the

same rules? What does 3.10.2 say about that (my browser just crashed, else I'd

look myself)?

****************************************************************

From: Stephen Baird [privately]

Sent: Wednesday, December 1, 2021 11:28 AM

This is not a problem for 'Access because slices are never aliased.

But I agree, if we introduce a new term then we should also use it in 3.10.2 .

****************************************************************

From: Randy Brukardt [privately]

Sent: Wednesday, December 1, 2021 3:16 PM

Do you have an example of how this could be a problem? We'll need some example

for the AI. I could probably figure it out, but it's always better to make the

questioner come up with it.

****************************************************************

From: Stephen Baird [privately]

Sent: Wednesday, December 1, 2021 4:34 PM

GNAT accepts the following example.

procedure Foo is

  subtype Index is Integer range 1 .. 100;

  type Float_Vec is array (Index) of Float;

  type Int_Vec is array (Index) of Integer;

  type Rec (Has_Ints : Boolean := True) is

     record

        case Has_Ints is

           when False => Floats : Float_Vec;

           when True => Ints : Int_Vec;

        end case;

     end record;

 

  X : Rec := (Has_Ints => True, Ints => (others => 0));

begin

  for E of X.Ints (1 ..10) loop

     X := (Has_Ints => False, Floats => (others => 1234.5));

      -- at this point X.Ints no longer exists

     E := E + 1;

  end loop;

end Foo;

If you remove the "(1 ..10)" then GNAT rejects the example with an appropriate

message:

  error: iterable name cannot be a discriminant-dependent component of a mutable object

I believe this is consistent with the current RM wording.

This is a problem - the RM should require rejecting both versions.

****************************************************************

From: Randy Brukardt [privately]

Sent: Wednesday, December 1, 2021 4:47 PM

Thanks. And agreed. I think we could fix *this* problem by adding "(or slice of

such a subcomponent)" appropriately, but it is reasonable to consider a fix that

wouldn't get broken in the future by further fixes in this area (given how many

times the underlying rules have been "fixed", it wouldn't surprise me if that

continued).

****************************************************************

From: Randy Brukardt [privately]

Sent: Tuesday, January 25, 2022 6:24 PM

> Or we could copy the 12.4(7) cheat in 5.5.2, but I don't much like that idea.

FYI, We already did that in 8.5.4(5.3/5) and 12.6(8.4/5), so there are at

least three instances of "renaming is allowed" in the RM. I conclude that *is*

the term in question, and we should use that in 5.5.3(6.1/3). Inventing a new

term would just be churn.

****************************************************************