Skip to content

Commit bc0e1b5

Browse files
committed
type erasure tests
1 parent 6369ab3 commit bc0e1b5

File tree

150 files changed

+265
-1583
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

150 files changed

+265
-1583
lines changed

README.md

Lines changed: 132 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515

1616
## How it works
1717

18-
In general:
18+
In a nutshell:
1919
+ parse generics classes;
20-
+ generate concrete classes based on them;
20+
+ generate concrete classes based on them (you can choose `monomorphization` or `type-erasure`);
2121
+ autoload concrete classes instead of generics classes.
2222

2323
For example, you need to add several PHP files:
@@ -134,26 +134,55 @@ composer.json
134134

135135
A new class is generated for each generic argument combination.
136136

137-
![](./doc/monomorphization.png)
137+
Before `monomorphization`:
138+
```php
139+
<?php
138140

139-
### Command
140-
```bash
141-
composer dump-generics
141+
namespace App;
142+
143+
class Box<T> {
144+
145+
private ?T $data = null;
146+
147+
public function set(T $data): void
148+
{
149+
$this->data = $data;
150+
}
151+
152+
public function get(): ?T
153+
{
154+
return $this->data;
155+
}
156+
}
142157
```
143158

144-
### Where in class can generics be used?
159+
After `monomorphization`:
160+
```php
161+
<?php
162+
163+
namespace App;
145164

146-
+ extends
147-
+ implements
148-
+ trait use
149-
+ property type
150-
+ method argument type
151-
+ method return type
152-
+ instanceof
153-
+ new
154-
+ class constants
165+
class BoxForInt {
155166

156-
An example of class that uses generics:
167+
private ?int $data = null;
168+
169+
public function set(int $data) : void
170+
{
171+
$this->data = $data;
172+
}
173+
174+
public function get() : ?int
175+
{
176+
return $this->data;
177+
}
178+
}
179+
```
180+
#### Command
181+
```bash
182+
composer dump-generics
183+
```
184+
185+
#### Where in class can generics be used?
157186
```php
158187
<?php
159188

@@ -163,66 +192,49 @@ use App\Entity\Cat;
163192
use App\Entity\Bird;
164193
use App\Entity\Dog;
165194

166-
class Test extends GenericClass<Cat> implements GenericInterface<Bird> {
195+
class Test extends GenericClass<Cat> implements GenericInterface<Bird> { // <-- extends/implements
167196

168-
use GenericTrait<Dog>;
197+
use GenericTrait<Dog>; // <-- trait use
169198

170-
private GenericClass<int>|GenericClass<Dog> $var;
199+
private GenericClass<int>|GenericClass<Dog> $var; // <-- property type
171200

172-
public function test(GenericInterface<int>|GenericInterface<Dog> $var): GenericClass<string>|GenericClass<Bird> {
173-
174-
var_dump($var instanceof GenericInterface<int>);
201+
public function test(GenericInterface<int>|GenericInterface<Dog> $var): GenericClass<string>|GenericClass<Bird> { // <-- method argument/return type
175202

176-
var_dump(GenericClass<int>::class);
203+
var_dump($var instanceof GenericInterface<int>); // <-- instanceof
177204

178-
var_dump(GenericClass<array>::CONSTANT);
205+
var_dump(GenericClass<int>::class); // <-- class constants
206+
var_dump(GenericClass<array>::CONSTANT); // <-- class constants
179207

180-
return new GenericClass<float>();
208+
return new GenericClass<float>(); // <-- new
181209
}
182210
}
183211
```
184212

185-
### Where in generic class can parameters be used?
186-
187-
+ extends
188-
+ implements
189-
+ trait use
190-
+ property type
191-
+ method argument type
192-
+ method return type
193-
+ instanceof
194-
+ new
195-
+ class constants
196-
197-
And example of generic class:
213+
#### Where in generic class can parameters be used?
198214
```php
199215
<?php
200216

201217
namespace App;
202218

203-
class Test<T,V> extends GenericClass<T> implements GenericInterface<V> {
219+
class Test<T,V> extends GenericClass<T> implements GenericInterface<V> { // <-- extends/implements
204220

205-
use GenericTrait<T>;
206-
use T;
221+
use GenericTrait<T>; // <-- trait use
222+
use T; // <-- trait use
207223

208-
private T|GenericClass<V> $var;
224+
private T|GenericClass<V> $var; // <-- property type
209225

210-
public function test(T|GenericInterface<V> $var): T|GenericClass<V> {
211-
212-
var_dump($var instanceof GenericInterface<V>);
226+
public function test(T|GenericInterface<V> $var): T|GenericClass<V> { // <-- method argument/return type
213227

214-
var_dump($var instanceof T);
228+
var_dump($var instanceof GenericInterface<V>); // <-- instanceof
229+
var_dump($var instanceof T); // <-- instanceof
215230

216-
var_dump(GenericClass<T>::class);
231+
var_dump(GenericClass<T>::class); // <-- class constants
232+
var_dump(T::class); // <-- class constants
233+
var_dump(GenericClass<T>::CONSTANT); // <-- class constants
234+
var_dump(T::CONSTANT); // <-- class constants
217235

218-
var_dump(T::class);
219-
220-
var_dump(GenericClass<T>::CONSTANT);
221-
222-
var_dump(T::CONSTANT);
223-
224-
$obj1 = new T();
225-
$obj2 = new GenericClass<V>();
236+
$obj1 = new T(); // <-- new
237+
$obj2 = new GenericClass<V>(); // <-- new
226238

227239
return $obj2;
228240
}
@@ -235,26 +247,56 @@ class Test<T,V> extends GenericClass<T> implements GenericInterface<V> {
235247

236248
A new class is generated without generics arguments.
237249

238-
![](./doc/type-erasure.png)
250+
Before `type erasure`:
251+
```php
252+
<?php
253+
254+
namespace App;
239255

240-
### Command
241-
```bash
242-
composer dump-generics --type=type-erasure
256+
class Box<T> {
257+
258+
private ?T $data = null;
259+
260+
public function set(T $data): void
261+
{
262+
$this->data = $data;
263+
}
264+
265+
public function get(): ?T
266+
{
267+
return $this->data;
268+
}
269+
}
243270
```
244271

245-
### Where in class can generics be used?
272+
After `type erasure`:
273+
```php
274+
<?php
275+
276+
namespace App;
246277

247-
+ extends
248-
+ implements
249-
+ trait use
250-
+ property type
251-
+ method argument type
252-
+ method return type
253-
+ instanceof
254-
+ new
255-
+ class constants
278+
class Box {
256279

257-
An example of class that uses generics:
280+
private $data = null;
281+
282+
public function set($data) : void
283+
{
284+
$this->data = $data;
285+
}
286+
287+
public function get()
288+
{
289+
return $this->data;
290+
}
291+
}
292+
```
293+
294+
#### Command
295+
```bash
296+
composer dump-generics --type=type-erasure
297+
```
298+
299+
#### Where in class can generics be used?
258300
```php
259301
<?php
260302

@@ -264,62 +306,50 @@ use App\Entity\Cat;
264306
use App\Entity\Bird;
265307
use App\Entity\Dog;
266308

267-
class Test extends GenericClass<Cat> implements GenericInterface<Bird> {
309+
class Test extends GenericClass<Cat> implements GenericInterface<Bird> { // <-- extends/implements
268310

269-
use GenericTrait<Dog>;
311+
use GenericTrait<Dog>; // <-- trait use
270312

271-
private GenericClass<int>|GenericClass<Dog> $var;
313+
private GenericClass<int>|GenericClass<Dog> $var; // <-- property type
272314

273-
public function test(GenericInterface<int>|GenericInterface<Dog> $var): GenericClass<string>|GenericClass<Bird> {
315+
public function test(GenericInterface<int>|GenericInterface<Dog> $var): GenericClass<string>|GenericClass<Bird> { // <-- method argument/return type
274316

275-
var_dump($var instanceof GenericInterface<int>);
317+
var_dump($var instanceof GenericInterface<int>); // <-- instanceof
276318

277-
var_dump(GenericClass<int>::class);
319+
var_dump(GenericClass<int>::class); // <-- class constants
320+
var_dump(GenericClass<array>::CONSTANT); // <-- class constants
278321

279-
var_dump(GenericClass<array>::CONSTANT);
280-
281-
return new GenericClass<float>();
322+
return new GenericClass<float>(); // <-- new
282323
}
283324
}
284325
```
285326

286-
:blue_book: You can read more about `type-erasure` [here](https://dev.to/mrsuh/generics-implementation-approaches-3bf0).
287-
288-
### Where in generic class can parameters be used?
289-
290-
+ extends
291-
+ implements
292-
+ property type
293-
+ method argument type
294-
+ method return type
295-
296-
And example of generic class:
327+
#### Where in generic class can parameters be used?
297328
```php
298329
<?php
299330

300331
namespace App;
301332

302-
class Test<T,V> extends GenericClass<T> implements GenericInterface<V> {
333+
class Test<T,V> extends GenericClass<T> implements GenericInterface<V> { // <-- extends/implements
303334

304-
use GenericTrait<T>;
335+
use GenericTrait<T>; // <-- trait use
305336

306-
private GenericClass<V> $var;
337+
private GenericClass<V> $var; // <-- property type
307338

308-
public function test(T|GenericInterface<V> $var): T|GenericClass<V> {
339+
public function test(T|GenericInterface<V> $var): T|GenericClass<V> { // <-- method argument/return type
309340

310-
var_dump($var instanceof GenericInterface<V>);
341+
var_dump($var instanceof GenericInterface<V>); // <-- instanceof
311342

312-
var_dump(GenericClass<T>::class);
343+
var_dump(GenericClass<T>::class); // <-- class constants
344+
var_dump(GenericClass<T>::CONSTANT); // <-- class constants
313345

314-
var_dump(GenericClass<T>::CONSTANT);
315-
316-
$obj2 = new GenericClass<V>();
317-
318-
return $obj2;
346+
return new GenericClass<V>(); // <-- new
319347
}
320348
}
321349
```
322350

351+
:blue_book: You can read more about `type-erasure` [here](https://dev.to/mrsuh/generics-implementation-approaches-3bf0).
352+
323353
## Features
324354

325355
#### What syntax is used?

doc/monomorphization.png

-118 KB
Binary file not shown.

doc/type-erasure.png

-114 KB
Binary file not shown.

0 commit comments

Comments
 (0)