Skip to content

Commit ad9e892

Browse files
committed
handle refs to builtin types and unions correctly
1 parent 3b43d7e commit ad9e892

File tree

12 files changed

+79
-27
lines changed

12 files changed

+79
-27
lines changed

src/Codegen/Codegen.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,9 @@ public function isArrayKeyType(): bool {
331331
}
332332

333333
public function getTypeInfo(): Typing\Type {
334+
if ($this->builder->isUniqueRef()) {
335+
return Typing\TypeSystem::alias($this->builder->getType());
336+
}
334337
return $this->builder->getTypeInfo();
335338
}
336339

src/Codegen/Constraints/UniqueRefBuilder.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public function build(): this {
7171
'type' => $codegen->getType(),
7272
'classname' => $codegen->getClassName(),
7373
'isArrayKeyType' => $codegen->isArrayKeyType(),
74+
'typeInfo' => $codegen->getTypeInfo(),
7475
);
7576
RefCache::cacheRef($this->filename, $this->cached_ref);
7677
}
@@ -97,7 +98,8 @@ public function setSuffix(string $_suffix): void {
9798
}
9899

99100
public function getTypeInfo(): Typing\Type {
100-
return Typing\TypeSystem::alias($this->getType());
101+
invariant($this->cached_ref is nonnull, 'must call `build` method before accessing type');
102+
return $this->cached_ref['typeInfo'];
101103
}
102104

103105
/**

src/Codegen/Constraints/UntypedBuilder.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,6 @@ private function codegenType(): CodegenType {
634634

635635
<<__Override>>
636636
public function getTypeInfo(): Typing\Type {
637-
invariant($this->type_info is nonnull, 'must call `build` method before accessing type info');
638-
return $this->type_info;
637+
return Typing\TypeSystem::alias($this->getType());
639638
}
640639
}

src/Codegen/RefCache.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ final class RefCache {
99
'type' => string,
1010
'classname' => string,
1111
'isArrayKeyType' => bool,
12+
'typeInfo' => Typing\Type,
1213
);
1314

1415
static private dict<string, self::TCachedRef> $generatedRefs = dict[];

src/Codegen/Typing/ConcreteType.hack

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ final class ConcreteType extends Type {
2525
return $this->generics;
2626
}
2727

28+
<<__Override>>
29+
public function getAlias(): null {
30+
return null;
31+
}
32+
2833
<<__Override>>
2934
public function hasAlias(): bool {
3035
return false;

src/Codegen/Typing/OptionalType.hack

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ final class OptionalType extends Type {
2121
return $this->type->getGenerics();
2222
}
2323

24+
<<__Override>>
25+
public function getAlias(): ?string {
26+
return $this->type->getAlias();
27+
}
28+
2429
<<__Override>>
2530
public function hasAlias(): bool {
2631
return $this->type->hasAlias();

src/Codegen/Typing/Type.hack

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ abstract class Type {
1919
*/
2020
abstract public function getGenerics(): vec<Type>;
2121

22+
/**
23+
* Alias for this type, if any.
24+
*/
25+
abstract public function getAlias(): ?string;
26+
2227
/**
2328
* Whether this type has an alias (e.g., is of form <alias> or ?<alias>).
2429
*/

src/Codegen/Typing/TypeAlias.hack

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ final class TypeAlias extends Type {
2323
return $this->getType()->getGenerics();
2424
}
2525

26+
<<__Override>>
27+
public function getAlias(): string {
28+
return $this->alias;
29+
}
30+
2631
<<__Override>>
2732
public function hasAlias(): bool {
2833
return $this->getType()->hasAlias();
@@ -35,6 +40,6 @@ final class TypeAlias extends Type {
3540

3641
<<__Override>>
3742
public function render(): string {
38-
return $this->alias;
43+
return $this->getAlias();
3944
}
4045
}

src/Codegen/Typing/TypeSystem.hack

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,7 @@ final abstract class TypeSystem {
158158
/**
159159
* Try to map the solved type to one of the passed-in type aliases.
160160
*
161-
* If a matching alias exists, it may make sense to prefer it over generating
162-
* a fresh type.
161+
* If all types are the alias or null, use the alias.
163162
*/
164163
private static function maybeUseAlias(Type $type, vec<Type> $types): Type {
165164
$equivalent_types = vec[];
@@ -173,6 +172,9 @@ final abstract class TypeSystem {
173172
}
174173
if ($candidate_ty->isEquivalent($type)) {
175174
$equivalent_types[] = $candidate_ty;
175+
} else if ($candidate_ty->getConcreteTypeName() !== ConcreteTypeName::NOTHING) {
176+
// Conflicting type which is not null — bail out.
177+
return $type;
176178
}
177179
}
178180

tests/AnyOfRefiningTest.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@ final class AnyOfRefiningTest extends BaseCodegenTestCase {
2929
$ret['codegen']->build();
3030
$ret = self::getBuilder('anyof-schema-4.json', 'AnyOfValidator4');
3131
$ret['codegen']->build();
32-
$ret = self::getBuilder('anyof-schema-strings.json', 'AnyOfValidatorStrings');
32+
$ret = self::getBuilder('anyof-schema-strings.json', 'AnyOfValidatorStrings', shape(
33+
'refs' => shape(
34+
'unique' => shape(
35+
'source_root' => __DIR__,
36+
'output_root' => __DIR__.'/examples/codegen',
37+
),
38+
),
39+
));
3340
$ret['codegen']->build();
3441
$ret = self::getBuilder('anyof-schema-nested-nullable-anyof.json', 'AnyOfValidatorNestedNullableAnyOf');
3542
$ret['codegen']->build();

0 commit comments

Comments
 (0)