Skip to content

Commit 61c2134

Browse files
committed
Add RFC for structural generic instantiation
1 parent 7dd001d commit 61c2134

File tree

2 files changed

+131
-3
lines changed

2 files changed

+131
-3
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
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

meta/rfc-improved-generic-instantiations.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,12 @@ little, but is not a big step up from the last version. We will understand the
136136
true edge this feature gives us in the last step. Let's go to the next
137137
iteration
138138

139-
### Second step: Implicit instantiation of generics
139+
### Second step: Structural instantiation of generics
140140

141141
This one is the big step up, that will allow us to get one step closer to the
142-
initial intent. Using implicit instantiation of generic functions [(see RFC
143-
here (TODO))](https://TODO), we would be able to write the following:
142+
initial intent. Using structural instantiation of generics [(see RFC
143+
here)](../considered/rfc-structural-generic-instantiation.md), we would be able
144+
to write the following:
144145

145146
```ada
146147
function Sum (X: Float_Array) return Float is

0 commit comments

Comments
 (0)