Version 1.1 of ai22s/ai22-0030-1.txt
!standard 5.5.2(6.1/4) 22-01-25 AI22-0030-1/01
!class binding interpretation 22-01-25
!status work item 21-06-04
!status received 21-04-28
!priority Low
!difficulty Easy
!qualifier Omission
!subject Array iterators of slices
!summary
The object of an array or container iterator must allow renaming.
!question
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.
!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)m 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 --
X := (Has_Ints => False, Floats => (others => 1234.5)); --
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)
Replace the paragraph:
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.
by:
The iterator_name or iterable_name of an
iterator_specification shall denote an object for which renaming
is allowed.
!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.
****************************************************************
Questions? Ask the ACAA Technical Agent