|
| 1 | +- Feature Name: Structural generic instantiation |
| 2 | +- Start Date: 2023-03-03 |
| 3 | +- RFC PR: (leave this empty) |
| 4 | +- RFC Issue: (leave this empty) |
| 5 | + |
| 6 | +Summary |
| 7 | +======= |
| 8 | + |
| 9 | +This RFC proposes to allow "structural" instantiation of generics, that is to |
| 10 | +be able to reference an implicit instance of a generic, that is denoted only by |
| 11 | +its actual parameters, rather than by its name. |
| 12 | + |
| 13 | +Motivation |
| 14 | +========== |
| 15 | + |
| 16 | +The expected benefits of this feature are: |
| 17 | + |
| 18 | +1. Expressivity. Combined with other features that can be found in the [meta |
| 19 | + RFC](../meta/rfc-improved-generic-instantiations.md), we hope to make |
| 20 | + generic subprograms much more usable, and unblock potential use cases that |
| 21 | + would otherwise require language support to be expressive (Ada 2022's |
| 22 | + `Reduce` comes to mind). |
| 23 | + |
| 24 | +2. Be able to refer to a "unique", structural instance of a generic. For |
| 25 | + example there will be a unique instance of `Ada.Containers.Vectors |
| 26 | + (Positive, Positive)`, and all people refering to it will refer to the same |
| 27 | + instance, which solves a long standing problem in generics, which is the |
| 28 | + ability to structurally reference unique entities. |
| 29 | + |
| 30 | +See the high level RFC for examples. |
| 31 | + |
| 32 | +Guide-level explanation |
| 33 | +======================= |
| 34 | + |
| 35 | +You can structurally refer to an implicit instantiation of a generic by naming |
| 36 | +it. The (tentative) syntax for naming it is the following: |
| 37 | + |
| 38 | +```ada |
| 39 | +Ada.Unchecked_Deallocation [Integer, Integer_Access] (My_Int_Access); |
| 40 | +``` |
| 41 | + |
| 42 | +By naming the generic, it will be implicitly instantiated, a key point being |
| 43 | +that there is only one generic corresponding to `Ada.Unchecked_Deallocation |
| 44 | +[Integer, Integer_Access]` at a high level, and every reference to it |
| 45 | +references the same entity. |
| 46 | + |
| 47 | +> *Note* |
| 48 | +> |
| 49 | +> It's not clear that we can actually guarantee that it will be compiled only |
| 50 | +> once with a separate compilation model, which is why it is not mentioned |
| 51 | +> above, but the goal is clearly to ensure that when possible, and when it's |
| 52 | +> not, to minimize the number of instances actually generated. |
| 53 | +
|
| 54 | +This syntax does also allow naming parameters: |
| 55 | + |
| 56 | +```ada |
| 57 | +Ada.Unchecked_Deallocation [Object => Integer, Name => Integer_Access] (My_Int_Access); |
| 58 | +
|
| 59 | +Ada.Unchecked_Deallocation [Name => Integer_Access] (My_Int_Access); |
| 60 | +-- NOTE: This relies on parameter inference |
| 61 | +``` |
| 62 | + |
| 63 | +and empty parameter lists: |
| 64 | + |
| 65 | +```ada |
| 66 | +generic procedure Foo (A : Integer) is null; |
| 67 | +
|
| 68 | +Foo [] (12); |
| 69 | +
|
| 70 | +Ada.Unchecked_Deallocation [] (My_Int_Access); |
| 71 | +-- NOTE: This relies on inference from name & type resolution context |
| 72 | +``` |
| 73 | + |
| 74 | +> *Note* |
| 75 | +> |
| 76 | +> Do we want to allow `Ada.Unchecked_Deallocation (My_Int_Access)` - so, |
| 77 | +> without any explicit syntactic instantiation indication ? Seems nifty and |
| 78 | +> possible, but maybe too implicit. |
| 79 | +
|
| 80 | +Reference-level explanation |
| 81 | +=========================== |
| 82 | + |
| 83 | +This is clearly not complete, we expect this draft to be completed during |
| 84 | +prototyping. |
| 85 | + |
| 86 | +### Syntax changes |
| 87 | + |
| 88 | +Add the following syntax rule: |
| 89 | + |
| 90 | +``` |
| 91 | +structural_generic_instantiation_reference ::= |
| 92 | + name [generic_actual_part] |
| 93 | +``` |
| 94 | + |
| 95 | +And alter the `name` rule to include `structural_generic_instantiation_reference` |
| 96 | + |
| 97 | +### Semantic changes |
| 98 | + |
| 99 | +* Each `structural_generic_instantiation_reference` references a structural |
| 100 | + generic instantiation. |
| 101 | + |
| 102 | +* This structural generic instantiation is semantically unique accross all |
| 103 | + units of the closure, so all references refer to the same instantiation. |
| 104 | + |
| 105 | +* As soon as there exists one reference to a given structural instantiation, |
| 106 | + then it will be instantiated. |
| 107 | + |
| 108 | +Rationale and alternatives |
| 109 | +========================== |
| 110 | + |
| 111 | +The rationale is contained in the high level RFC on generics. |
| 112 | + |
| 113 | +Drawbacks |
| 114 | +========= |
| 115 | + |
| 116 | +N/A |
| 117 | + |
| 118 | +Prior art |
| 119 | +========= |
| 120 | + |
| 121 | +Most languages with generics also have structural instantiation of them. In |
| 122 | +fact it is pretty much the default paradigm for generics in most languages |
| 123 | +(C++, C#, Java, Rust, Haskell, OCaml, etc), which makes it difficult to |
| 124 | +identify the feature with such a specific name, because it is usually just |
| 125 | +called "generics". |
| 126 | + |
| 127 | +TODO: Try to fill out this section nonetheless |
0 commit comments