Skip to content

Commit fe098da

Browse files
committed
Add partial generic instantiations RFC
1 parent 20ffaff commit fe098da

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
- Feature Name: Partial instantiation of generics
2+
- Start Date: 2023-04-11
3+
- RFC PR: (leave this empty)
4+
- RFC Issue: (leave this empty)
5+
6+
Summary
7+
=======
8+
9+
This RFC builds up on top of [the structural generic instantiation
10+
RFC](./rfc-structural-generic-instantiation.md), and proposes to be able to
11+
infer generic actuals for structural generic instantiations, from the actuals
12+
of the subprogram call, in cases where the structural generic instantiation
13+
refers to a subprogram.
14+
15+
Motivation
16+
==========
17+
18+
This RFC is part of the bigger high-level RFC about improving generic
19+
instantiations ([here](../meta/rfc-improved-generic-instantiations.md)), so the
20+
need arises from that context, and it's useful to go read the high level RFC to
21+
understand the bigger picture.
22+
23+
However, unlike other RFCs of that series, this one is pretty orthogonal to the
24+
rest, and would provide usability benefits even if the rest of the RFCs were
25+
not to be implemented.
26+
27+
The idea is to be able to create "new" generic specifications from existing
28+
ones, by just specifying a subset of their parameters. This would simplify some
29+
uses of generics, and would make creating "specialized" instances much easier.
30+
31+
Guide-level explanation
32+
=======================
33+
34+
The idea is to be able to create "new" generic specifications from existing
35+
ones, by just specifying a subset of their parameters.
36+
37+
Here is an example with `Ada.Containers.Vectors`:
38+
39+
```ada
40+
generic
41+
type Index_Type is range <>;
42+
type Element_Type is private;
43+
44+
with function "=" (Left : in Element_Type;
45+
Right : in Element_Type)
46+
return Boolean is <>;
47+
48+
package Ada.Containers.Vectors is ...
49+
50+
generic package Vecs
51+
is Ada.Containers.Vectors (Index_Type => Positive);
52+
53+
package Float_Vectors is new Vecs (Float);
54+
```
55+
56+
In the above example, the formal part between `generic` and `package` is empty,
57+
which means that remaining params are infered from the partially instantiated
58+
specification.
59+
60+
While this can be practical in simple cases:
61+
62+
* We want to let people the ability to fully specify formals
63+
* We want to allow more complex patterns like reordering/renaming formals
64+
65+
Which leads us to the more complete syntax:
66+
67+
```ada
68+
generic
69+
type El_T is private;
70+
with function "=" (Left : in El_T; Right : in El_T) return Boolean is <>;
71+
package Vecs is Ada.Containers.Vectors
72+
(Index_Type => Positive,
73+
Element_Type => El_T,
74+
"=" => "=");
75+
```
76+
77+
While generic formal parts for standard containers are pretty simple, there
78+
were experiments by AdaCore with creating much more generic specifications for
79+
containers, in the `ada-traits-containers` library, and specializations of
80+
those packages were provided, see for example
81+
[this](https://github.com/AdaCore/ada-traits-containers/blob/master/src/conts-maps-indef_def_unbounded.ads)
82+
83+
The problem with this pattern is that:
84+
85+
* Entities from the `Impl` package are not automatically forwarded, so
86+
uses have to go through `Instantiation.Impl.`
87+
88+
* Means of forwarding are explicit (see the renamings/subtypes lower in the
89+
spec)
90+
91+
Using structural instantiations together with partial instantiations from this
92+
RFC, and anonymous subprograms, one could write:
93+
94+
```ada
95+
generic
96+
type Key_Type (<>) is private;
97+
type Element_Type is private;
98+
type Container_Base_Type is abstract tagged limited private;
99+
with function Hash (Key : Key_Type) return Hash_Type;
100+
with function "=" (Left, Right : Key_Type) return Boolean is
101+
with procedure Free (E : in out Key_Type) is null;
102+
with procedure Free (E : in out Element_Type) is null;
103+
package Conts.Maps.Indef_Def_Unbounded is
104+
Conts.Maps.Generics
105+
(Keys => Conts.Elements.Indefinite [Key_Type, Conts.Global_Pool, Free].Traits,
106+
Elements => Conts.Elements.Definite [Element_Type, Free => Free].Traits,
107+
Hash => Hash,
108+
"=" =>
109+
function (Left : Key_Type; Right : Keys.Traits.Stored) return Boolean
110+
is (Left = Right.all),
111+
Probing => Conts.Maps.Perturbation_Probing,
112+
Pool => Conts.Global_Pool,
113+
Container_Base_Type => Container_Base_Type);
114+
```
115+
116+
Alternatively, if we consider that having "inline" syntax for sub-elements is a
117+
problem - for example, because for anonymous functions, it doesn't exist yet -
118+
we can introduce a syntax to introduce declarations inbetween the formal part
119+
and the partial instantiation:
120+
121+
```ada
122+
generic
123+
type Key_Type (<>) is private;
124+
type Element_Type is private;
125+
type Container_Base_Type is abstract tagged limited private;
126+
with function Hash (Key : Key_Type) return Hash_Type;
127+
with function "=" (Left, Right : Key_Type) return Boolean is <>;
128+
with procedure Free (E : in out Key_Type) is null;
129+
with procedure Free (E : in out Element_Type) is null;
130+
declare
131+
package Keys is new Conts.Elements.Indefinite
132+
(Key_Type, Pool => Conts.Global_Pool, Free => Free);
133+
package Elements is new Conts.Elements.Definite
134+
(Element_Type, Free => Free);
135+
function "=" (Left : Key_Type; Right : Keys.Traits.Stored) return Boolean
136+
is (Left = Right.all) with Inline;
137+
package Conts.Maps.Indef_Def_Unbounded is Conts.Maps.Generics
138+
(Keys => Keys.Traits,
139+
Elements => Elements.Traits,
140+
Hash => Hash,
141+
"=" => "=",
142+
Probing => Conts.Maps.Perturbation_Probing,
143+
Pool => Conts.Global_Pool,
144+
Container_Base_Type => Container_Base_Type);
145+
```
146+
147+
Reference-level explanation
148+
===========================
149+
150+
TBD
151+
152+
Rationale and alternatives
153+
==========================
154+
155+
The rationale is contained in the high level RFC on generics.
156+
157+
Drawbacks
158+
=========
159+
160+
N/A
161+
162+
Prior art
163+
=========
164+
165+
TBD

0 commit comments

Comments
 (0)