Ada-Rapporteur-Group / User-Community-Input

Ada User Community Input Working Group - Github Mirror Prototype
27 stars 1 forks source link

User-defined Indexing: implications of unspecified aspects and inheritance. #29

Closed Richard-Wai closed 1 year ago

Richard-Wai commented 1 year ago

For user-defined indexing, the standard states (4.1.5-4/4) that "These aspects are inherited by descendants of T", but does not specifically say if the state of definition is inherited, one would assume therefore it shouldn't be. The ARM (Note 6) also makes clear that the user-defined indexing aspects of a type may not be "redefined" for a derived type, but again, defining something that is not yet defined is not "redefining" it (or is it?)

My interpretation is that if one of the two user-defined indexing aspects are specified for a type, the other (and only the other) may be specified for a derived type. However GNAT 11.3.0 disagrees, though GNAT 10.3.0 allowed it.

This approach can be useful for returning a restricted "constant" view type of a container, and a "mutable" type separately.

Further, this does not seem to cause issues in regards to class-wide types. If T1 supports one kind of indexing, and derived type T2 that defines the other, T1'Class rightfully only presents the initial single indexing approach.

` package Test_Types is X: aliased Integer := 5;

        type Target_Const_Reference (Ref: not null access constant Integer) is null record with
          Implicit_Dereference => Ref;

        type Target_Reference (Ref: not null access Integer) is null record with
          Implicit_Dereference => Ref;

        type Const_Lookup is tagged null record with
          Constant_Indexing => Constant_Reference;

        function Constant_Reference (Container: Const_Lookup; Index: Positive)
                                    return Target_Const_Reference is
          (Target_Const_Reference'(Ref => X'Access));

        type Full_Lookup is new Const_Lookup with null record with
          Variable_Indexing => Reference;

        function Reference (Container: in out Full_Lookup; Index: Positive)
                                    return Target_Reference is
          (Target_Reference'(Ref => X'Access));
  end Test_Types;

` If compiled, GNAT 11.3.0 gives the following error wrt Full_Lookup: "cannot specify indexing operation on derived type if not specified for parent".

Who is right here? And should we consider adding a new note?

ARG-Editor commented 1 year ago

Ada 2022 added a rule (as a bug fix) to prevent redefining either aspect for a derived type if one was specified. We did that because the choice of which aspect to call depends upon how they are defined. In particular, if you had a type that defined only Constant_Indexing, and then a derived type that added Variable_Indexing to that, then which function was called for a variable would depend on the view. (A view of the root type - including a class-wide view - would call the Constant_Indexing function in a variable context, while a view of the derived type would call the Variable_Indexing function for a variable context.) That would be extremely confusing, especially in dispatching contexts where the routine called might change depending on which subprogram body you were in when it was invoked.

The new rule is 4.1.6(6/5), and the associated AI is AI12-0160-1. (The Ada 2022 RM is your friend. :-)

GNAT 11.3.0 is doing the right thing.

It probably would have been better to have both of these things defined as a single aspect (as with aspect Aggregate), but it's too late to make that sort of change.

                               Randy.
Richard-Wai commented 1 year ago

Doh! I was trying to consolidate between 2012 and 2022 and I overlooked that change. I should probably move on from the Draft version of the ARM with all the edits 😅