[compiler] More readable alias signature declarations (#33530)
Now that we have support for defining aliasing signatures in moduleTypeProvider, which uses string names for receiver/args/returns/etc, we can reuse that same form for builtin declarations. The declarations are written in the unparsed form and than parsed/validated when registered (in the addFunction/addHook call). This also required flushing out configs/schemas for more effect types. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33530). * #33571 * #33558 * #33547 * #33543 * #33533 * #33532 * __->__ #33530
Joseph Savona committed
Jun 18, 2025 at 15:47 UTC
4335f699870920932c8f30b6ad52173c3d819d16
4 files changed
+327
-166
compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts
+13
-118
@@ -5,14 +5,7 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import {
9
- Effect,
10
- GeneratedSource,
11
- makeIdentifierId,
12
- Place,
13
- ValueKind,
14
- ValueReason,
15
-} from './HIR';
8
+import {Effect, ValueKind, ValueReason} from './HIR';
9
import {
10
BUILTIN_SHAPES,
11
BuiltInArrayId,
@@ -41,18 +34,12 @@ import {
34
addFunction,
35
addHook,
36
addObject,
44
- signatureArgument,
37
} from './ObjectShape';
38
import {BuiltInType, ObjectType, PolyType} from './Types';
47
-import {
48
- AliasingEffectConfig,
49
- AliasingSignatureConfig,
50
- TypeConfig,
51
-} from './TypeSchema';
39
+import {TypeConfig} from './TypeSchema';
40
import {assertExhaustive} from '../Utils/utils';
41
import {isHookName} from './Environment';
42
import {CompilerError, SourceLocation} from '..';
55
-import {AliasingEffect, AliasingSignature} from '../Inference/AliasingEffects';
43
44
/*
45
* This file exports types and defaults for JavaScript global objects.
@@ -658,35 +645,35 @@ const REACT_APIS: Array<[string, BuiltInType]> = [
645
hookKind: 'useEffect',
646
returnValueKind: ValueKind.Frozen,
647
aliasing: {
661
- receiver: makeIdentifierId(0),
648
+ receiver: '@receiver',
649
params: [],
663
- rest: makeIdentifierId(1),
664
- returns: makeIdentifierId(2),
665
- temporaries: [signatureArgument(3)],
650
+ rest: '@rest',
651
+ returns: '@returns',
652
+ temporaries: ['@effect'],
653
effects: [
654
// Freezes the function and deps
655
{
656
kind: 'Freeze',
670
- value: signatureArgument(1),
657
+ value: '@rest',
658
reason: ValueReason.Effect,
659
},
660
// Internally creates an effect object that captures the function and deps
661
{
662
kind: 'Create',
676
- into: signatureArgument(3),
663
+ into: '@effect',
664
value: ValueKind.Frozen,
665
reason: ValueReason.KnownReturnSignature,
666
},
667
// The effect stores the function and dependencies
668
{
669
kind: 'Capture',
683
- from: signatureArgument(1),
684
- into: signatureArgument(3),
670
+ from: '@rest',
671
+ into: '@effect',
672
},
673
// Returns undefined
674
{
675
kind: 'Create',
689
- into: signatureArgument(2),
676
+ into: '@returns',
677
value: ValueKind.Primitive,
678
reason: ValueReason.KnownReturnSignature,
679
},
@@ -903,10 +890,6 @@ export function installTypeConfig(
890
}
891
}
892
case 'function': {
906
- const aliasing =
907
- typeConfig.aliasing != null
908
- ? parseAliasingSignatureConfig(typeConfig.aliasing, moduleName, loc)
909
- : null;
893
return addFunction(shapes, [], {
894
positionalParams: typeConfig.positionalParams,
895
restParam: typeConfig.restParam,
@@ -922,14 +905,10 @@ export function installTypeConfig(
905
noAlias: typeConfig.noAlias === true,
906
mutableOnlyIfOperandsAreMutable:
907
typeConfig.mutableOnlyIfOperandsAreMutable === true,
925
- aliasing,
908
+ aliasing: typeConfig.aliasing,
909
});
910
}
911
case 'hook': {
929
- const aliasing =
930
- typeConfig.aliasing != null
931
- ? parseAliasingSignatureConfig(typeConfig.aliasing, moduleName, loc)
932
- : null;
912
return addHook(shapes, {
913
hookKind: 'Custom',
914
positionalParams: typeConfig.positionalParams ?? [],
@@ -944,7 +923,7 @@ export function installTypeConfig(
923
),
924
returnValueKind: typeConfig.returnValueKind ?? ValueKind.Frozen,
925
noAlias: typeConfig.noAlias === true,
947
- aliasing,
926
+ aliasing: typeConfig.aliasing,
927
});
928
}
929
case 'object': {
@@ -987,90 +966,6 @@ export function installTypeConfig(
966
}
967
}
968
990
-function parseAliasingSignatureConfig(
991
- typeConfig: AliasingSignatureConfig,
992
- moduleName: string,
993
- loc: SourceLocation,
994
-): AliasingSignature {
995
- const lifetimes = new Map<string, Place>();
996
- function define(temp: string): Place {
997
- CompilerError.invariant(!lifetimes.has(temp), {
998
- reason: `Invalid type configuration for module`,
999
- description: `Expected aliasing signature to have unique names for receiver, params, rest, returns, and temporaries in module '${moduleName}'`,
1000
- loc,
1001
- });
1002
- const place = signatureArgument(lifetimes.size);
1003
- lifetimes.set(temp, place);
1004
- return place;
1005
- }
1006
- function lookup(temp: string): Place {
1007
- const place = lifetimes.get(temp);
1008
- CompilerError.invariant(place != null, {
1009
- reason: `Invalid type configuration for module`,
1010
- description: `Expected aliasing signature effects to reference known names from receiver/params/rest/returns/temporaries, but '${temp}' is not a known name in '${moduleName}'`,
1011
- loc,
1012
- });
1013
- return place;
1014
- }
1015
- const receiver = define(typeConfig.receiver);
1016
- const params = typeConfig.params.map(define);
1017
- const rest = typeConfig.rest != null ? define(typeConfig.rest) : null;
1018
- const returns = define(typeConfig.returns);
1019
- const temporaries = typeConfig.temporaries.map(define);
1020
- const effects = typeConfig.effects.map(
1021
- (effect: AliasingEffectConfig): AliasingEffect => {
1022
- switch (effect.kind) {
1023
- case 'Assign': {
1024
- return {
1025
- kind: 'Assign',
1026
- from: lookup(effect.from),
1027
- into: lookup(effect.into),
1028
- };
1029
- }
1030
- case 'Create': {
1031
- return {
1032
- kind: 'Create',
1033
- into: lookup(effect.into),
1034
- reason: ValueReason.KnownReturnSignature,
1035
- value: effect.value,
1036
- };
1037
- }
1038
- case 'Freeze': {
1039
- return {
1040
- kind: 'Freeze',
1041
- value: lookup(effect.value),
1042
- reason: ValueReason.KnownReturnSignature,
1043
- };
1044
- }
1045
- case 'Impure': {
1046
- return {
1047
- kind: 'Impure',
1048
- place: lookup(effect.place),
1049
- error: CompilerError.throwTodo({
1050
- reason: 'Support impure effect declarations',
1051
- loc: GeneratedSource,
1052
- }),
1053
- };
1054
- }
1055
- default: {
1056
- assertExhaustive(
1057
- effect,
1058
- `Unexpected effect kind '${(effect as any).kind}'`,
1059
- );
1060
- }
1061
- }
1062
- },
1063
- );
1064
- return {
1065
- receiver: receiver.identifier.id,
1066
- params: params.map(p => p.identifier.id),
1067
- rest: rest != null ? rest.identifier.id : null,
1068
- returns: returns.identifier.id,
1069
- temporaries,
1070
- effects,
1071
- };
1072
-}
1073
-
969
export function getReanimatedModuleType(registry: ShapeRegistry): ObjectType {
970
// hooks that freeze args and return frozen value
971
const frozenHooks = [
compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
+14
@@ -1453,6 +1453,20 @@ export const ValueKindSchema = z.enum([
1453
ValueKind.Context,
1454
]);
1455
1456
+export const ValueReasonSchema = z.enum([
1457
+ ValueReason.Context,
1458
+ ValueReason.Effect,
1459
+ ValueReason.Global,
1460
+ ValueReason.HookCaptured,
1461
+ ValueReason.HookReturn,
1462
+ ValueReason.JsxCaptured,
1463
+ ValueReason.KnownReturnSignature,
1464
+ ValueReason.Other,
1465
+ ValueReason.ReactiveFunctionArgument,
1466
+ ValueReason.ReducerState,
1467
+ ValueReason.State,
1468
+]);
1469
+
1470
// The effect with which a value is modified.
1471
export enum Effect {
1472
// Default value: not allowed after lifetime inference
compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts
+185
-46
@@ -6,14 +6,18 @@
6
*/
7
8
import {CompilerError} from '../CompilerError';
9
-import {AliasingSignature} from '../Inference/AliasingEffects';
9
+import {AliasingEffect, AliasingSignature} from '../Inference/AliasingEffects';
10
+import {assertExhaustive} from '../Utils/utils';
11
import {
12
Effect,
13
GeneratedSource,
14
+ Hole,
15
makeDeclarationId,
16
makeIdentifierId,
17
makeInstructionId,
18
Place,
19
+ SourceLocation,
20
+ SpreadPattern,
21
ValueKind,
22
ValueReason,
23
} from './HIR';
@@ -25,6 +29,7 @@ import {
29
PolyType,
30
PrimitiveType,
31
} from './Types';
32
+import {AliasingEffectConfig, AliasingSignatureConfig} from './TypeSchema';
33
34
/*
35
* This file exports types and defaults for JavaScript object shapes. These are
@@ -53,13 +58,20 @@ function createAnonId(): string {
58
export function addFunction(
59
registry: ShapeRegistry,
60
properties: Iterable<[string, BuiltInType | PolyType]>,
56
- fn: Omit<FunctionSignature, 'hookKind'>,
61
+ fn: Omit<FunctionSignature, 'hookKind' | 'aliasing'> & {
62
+ aliasing?: AliasingSignatureConfig | null | undefined;
63
+ },
64
id: string | null = null,
65
isConstructor: boolean = false,
66
): FunctionType {
67
const shapeId = id ?? createAnonId();
68
+ const aliasing =
69
+ fn.aliasing != null
70
+ ? parseAliasingSignatureConfig(fn.aliasing, '<builtin>', GeneratedSource)
71
+ : null;
72
addShape(registry, shapeId, properties, {
73
...fn,
74
+ aliasing,
75
hookKind: null,
76
});
77
return {
@@ -77,11 +89,18 @@ export function addFunction(
89
*/
90
export function addHook(
91
registry: ShapeRegistry,
80
- fn: FunctionSignature & {hookKind: HookKind},
92
+ fn: Omit<FunctionSignature, 'aliasing'> & {
93
+ hookKind: HookKind;
94
+ aliasing?: AliasingSignatureConfig | null | undefined;
95
+ },
96
id: string | null = null,
97
): FunctionType {
98
const shapeId = id ?? createAnonId();
84
- addShape(registry, shapeId, [], fn);
99
+ const aliasing =
100
+ fn.aliasing != null
101
+ ? parseAliasingSignatureConfig(fn.aliasing, '<builtin>', GeneratedSource)
102
+ : null;
103
+ addShape(registry, shapeId, [], {...fn, aliasing});
104
return {
105
kind: 'Function',
106
return: fn.returnType,
@@ -90,6 +109,129 @@ export function addHook(
109
};
110
}
111
112
+function parseAliasingSignatureConfig(
113
+ typeConfig: AliasingSignatureConfig,
114
+ moduleName: string,
115
+ loc: SourceLocation,
116
+): AliasingSignature {
117
+ const lifetimes = new Map<string, Place>();
118
+ function define(temp: string): Place {
119
+ CompilerError.invariant(!lifetimes.has(temp), {
120
+ reason: `Invalid type configuration for module`,
121
+ description: `Expected aliasing signature to have unique names for receiver, params, rest, returns, and temporaries in module '${moduleName}'`,
122
+ loc,
123
+ });
124
+ const place = signatureArgument(lifetimes.size);
125
+ lifetimes.set(temp, place);
126
+ return place;
127
+ }
128
+ function lookup(temp: string): Place {
129
+ const place = lifetimes.get(temp);
130
+ CompilerError.invariant(place != null, {
131
+ reason: `Invalid type configuration for module`,
132
+ description: `Expected aliasing signature effects to reference known names from receiver/params/rest/returns/temporaries, but '${temp}' is not a known name in '${moduleName}'`,
133
+ loc,
134
+ });
135
+ return place;
136
+ }
137
+ const receiver = define(typeConfig.receiver);
138
+ const params = typeConfig.params.map(define);
139
+ const rest = typeConfig.rest != null ? define(typeConfig.rest) : null;
140
+ const returns = define(typeConfig.returns);
141
+ const temporaries = typeConfig.temporaries.map(define);
142
+ const effects = typeConfig.effects.map(
143
+ (effect: AliasingEffectConfig): AliasingEffect => {
144
+ switch (effect.kind) {
145
+ case 'CreateFrom':
146
+ case 'Capture':
147
+ case 'Alias':
148
+ case 'Assign': {
149
+ const from = lookup(effect.from);
150
+ const into = lookup(effect.into);
151
+ return {
152
+ kind: effect.kind,
153
+ from,
154
+ into,
155
+ };
156
+ }
157
+ case 'Mutate':
158
+ case 'MutateTransitiveConditionally': {
159
+ const value = lookup(effect.value);
160
+ return {kind: effect.kind, value};
161
+ }
162
+ case 'Create': {
163
+ const into = lookup(effect.into);
164
+ return {
165
+ kind: 'Create',
166
+ into,
167
+ reason: effect.reason,
168
+ value: effect.value,
169
+ };
170
+ }
171
+ case 'Freeze': {
172
+ const value = lookup(effect.value);
173
+ return {
174
+ kind: 'Freeze',
175
+ value,
176
+ reason: effect.reason,
177
+ };
178
+ }
179
+ case 'Impure': {
180
+ const place = lookup(effect.place);
181
+ return {
182
+ kind: 'Impure',
183
+ place,
184
+ error: CompilerError.throwTodo({
185
+ reason: 'Support impure effect declarations',
186
+ loc: GeneratedSource,
187
+ }),
188
+ };
189
+ }
190
+ case 'Apply': {
191
+ const receiver = lookup(effect.receiver);
192
+ const fn = lookup(effect.function);
193
+ const args: Array<Place | SpreadPattern | Hole> = effect.args.map(
194
+ arg => {
195
+ if (typeof arg === 'string') {
196
+ return lookup(arg);
197
+ } else if (arg.kind === 'Spread') {
198
+ return {kind: 'Spread', place: lookup(arg.place)};
199
+ } else {
200
+ return arg;
201
+ }
202
+ },
203
+ );
204
+ const into = lookup(effect.into);
205
+ return {
206
+ kind: 'Apply',
207
+ receiver,
208
+ function: fn,
209
+ mutatesFunction: effect.mutatesFunction,
210
+ args,
211
+ into,
212
+ loc,
213
+ signature: null,
214
+ };
215
+ }
216
+ default: {
217
+ assertExhaustive(
218
+ effect,
219
+ `Unexpected effect kind '${(effect as any).kind}'`,
220
+ );
221
+ }
222
+ }
223
+ },
224
+ );
225
+ return {
226
+ receiver: receiver.identifier.id,
227
+ params: params.map(p => p.identifier.id),
228
+ rest: rest != null ? rest.identifier.id : null,
229
+ returns: returns.identifier.id,
230
+ temporaries,
231
+ effects,
232
+ };
233
+}
234
+
235
/*
236
* Add an object to an existing ShapeRegistry.
237
*
@@ -192,8 +334,7 @@ export type FunctionSignature = {
334
335
canonicalName?: string;
336
195
- aliasing?: AliasingSignature | null;
196
- todo_aliasing?: AliasingSignature | null;
337
+ aliasing?: AliasingSignature | null | undefined;
338
};
339
340
/*
@@ -320,24 +461,24 @@ addObject(BUILTIN_SHAPES, BuiltInArrayId, [
461
calleeEffect: Effect.Store,
462
returnValueKind: ValueKind.Primitive,
463
aliasing: {
323
- receiver: makeIdentifierId(0),
464
+ receiver: '@receiver',
465
params: [],
325
- rest: makeIdentifierId(1),
326
- returns: makeIdentifierId(2),
466
+ rest: '@rest',
467
+ returns: '@returns',
468
temporaries: [],
469
effects: [
470
// Push directly mutates the array itself
330
- {kind: 'Mutate', value: signatureArgument(0)},
471
+ {kind: 'Mutate', value: '@receiver'},
472
// The arguments are captured into the array
473
{
474
kind: 'Capture',
334
- from: signatureArgument(1),
335
- into: signatureArgument(0),
475
+ from: '@rest',
476
+ into: '@receiver',
477
},
478
// Returns the new length, a primitive
479
{
480
kind: 'Create',
340
- into: signatureArgument(2),
481
+ into: '@returns',
482
value: ValueKind.Primitive,
483
reason: ValueReason.KnownReturnSignature,
484
},
@@ -374,58 +515,56 @@ addObject(BUILTIN_SHAPES, BuiltInArrayId, [
515
noAlias: true,
516
mutableOnlyIfOperandsAreMutable: true,
517
aliasing: {
377
- receiver: makeIdentifierId(0),
378
- params: [makeIdentifierId(1)],
518
+ receiver: '@receiver',
519
+ params: ['@callback'],
520
rest: null,
380
- returns: makeIdentifierId(2),
521
+ returns: '@returns',
522
temporaries: [
523
// Temporary representing captured items of the receiver
383
- signatureArgument(3),
524
+ '@item',
525
// Temporary representing the result of the callback
385
- signatureArgument(4),
526
+ '@callbackReturn',
527
/*
528
* Undefined `this` arg to the callback. Note the signature does not
529
* support passing an explicit thisArg second param
530
*/
390
- signatureArgument(5),
531
+ '@thisArg',
532
],
533
effects: [
534
// Map creates a new mutable array
535
{
536
kind: 'Create',
396
- into: signatureArgument(2),
537
+ into: '@returns',
538
value: ValueKind.Mutable,
539
reason: ValueReason.KnownReturnSignature,
540
},
541
// The first arg to the callback is an item extracted from the receiver array
542
{
543
kind: 'CreateFrom',
403
- from: signatureArgument(0),
404
- into: signatureArgument(3),
544
+ from: '@receiver',
545
+ into: '@item',
546
},
547
// The undefined this for the callback
548
{
549
kind: 'Create',
409
- into: signatureArgument(5),
550
+ into: '@thisArg',
551
value: ValueKind.Primitive,
552
reason: ValueReason.KnownReturnSignature,
553
},
554
// calls the callback, returning the result into a temporary
555
{
556
kind: 'Apply',
416
- receiver: signatureArgument(5),
417
- args: [signatureArgument(3), {kind: 'Hole'}, signatureArgument(0)],
418
- function: signatureArgument(1),
419
- into: signatureArgument(4),
420
- signature: null,
557
+ receiver: '@thisArg',
558
+ args: ['@item', {kind: 'Hole'}, '@receiver'],
559
+ function: '@callback',
560
+ into: '@callbackReturn',
561
mutatesFunction: false,
422
- loc: GeneratedSource,
562
},
563
// captures the result of the callback into the return array
564
{
565
kind: 'Capture',
427
- from: signatureArgument(4),
428
- into: signatureArgument(2),
566
+ from: '@callbackReturn',
567
+ into: '@returns',
568
},
569
],
570
},
@@ -577,28 +716,28 @@ addObject(BUILTIN_SHAPES, BuiltInSetId, [
716
// returnValueKind is technically dependent on the ValueKind of the set itself
717
returnValueKind: ValueKind.Mutable,
718
aliasing: {
580
- receiver: makeIdentifierId(0),
719
+ receiver: '@receiver',
720
params: [],
582
- rest: makeIdentifierId(1),
583
- returns: makeIdentifierId(2),
721
+ rest: '@rest',
722
+ returns: '@returns',
723
temporaries: [],
724
effects: [
725
// Set.add returns the receiver Set
726
{
727
kind: 'Assign',
589
- from: signatureArgument(0),
590
- into: signatureArgument(2),
728
+ from: '@receiver',
729
+ into: '@returns',
730
},
731
// Set.add mutates the set itself
732
{
733
kind: 'Mutate',
595
- value: signatureArgument(0),
734
+ value: '@receiver',
735
},
736
// Captures the rest params into the set
737
{
738
kind: 'Capture',
600
- from: signatureArgument(1),
601
- into: signatureArgument(0),
739
+ from: '@rest',
740
+ into: '@receiver',
741
},
742
],
743
},
@@ -1303,30 +1442,30 @@ export const DefaultNonmutatingHook = addHook(
1442
hookKind: 'Custom',
1443
returnValueKind: ValueKind.Frozen,
1444
aliasing: {
1306
- receiver: makeIdentifierId(0),
1445
+ receiver: '@receiver',
1446
params: [],
1308
- rest: makeIdentifierId(1),
1309
- returns: makeIdentifierId(2),
1447
+ rest: '@rest',
1448
+ returns: '@returns',
1449
temporaries: [],
1450
effects: [
1451
// Freeze the arguments
1452
{
1453
kind: 'Freeze',
1315
- value: signatureArgument(1),
1454
+ value: '@rest',
1455
reason: ValueReason.HookCaptured,
1456
},
1457
// Returns a frozen value
1458
{
1459
kind: 'Create',
1321
- into: signatureArgument(2),
1460
+ into: '@returns',
1461
value: ValueKind.Frozen,
1462
reason: ValueReason.HookReturn,
1463
},
1464
// May alias any arguments into the return
1465
{
1466
kind: 'Alias',
1328
- from: signatureArgument(1),
1329
- into: signatureArgument(2),
1467
+ from: '@rest',
1468
+ into: '@returns',
1469
},
1470
],
1471
},
compiler/packages/babel-plugin-react-compiler/src/HIR/TypeSchema.ts
+115
-2
@@ -8,7 +8,12 @@
8
import {isValidIdentifier} from '@babel/types';
9
import {z} from 'zod';
10
import {Effect, ValueKind} from '..';
11
-import {EffectSchema, ValueKindSchema} from './HIR';
11
+import {
12
+ EffectSchema,
13
+ ValueKindSchema,
14
+ ValueReason,
15
+ ValueReasonSchema,
16
+} from './HIR';
17
18
export type ObjectPropertiesConfig = {[key: string]: TypeConfig};
19
export const ObjectPropertiesSchema: z.ZodType<ObjectPropertiesConfig> = z
@@ -38,23 +43,48 @@ export const LifetimeIdSchema = z.string().refine(id => id.startsWith('@'), {
43
export type FreezeEffectConfig = {
44
kind: 'Freeze';
45
value: string;
46
+ reason: ValueReason;
47
};
48
49
export const FreezeEffectSchema: z.ZodType<FreezeEffectConfig> = z.object({
50
kind: z.literal('Freeze'),
51
value: LifetimeIdSchema,
52
+ reason: ValueReasonSchema,
53
});
54
55
+export type MutateEffectConfig = {
56
+ kind: 'Mutate';
57
+ value: string;
58
+};
59
+
60
+export const MutateEffectSchema: z.ZodType<MutateEffectConfig> = z.object({
61
+ kind: z.literal('Mutate'),
62
+ value: LifetimeIdSchema,
63
+});
64
+
65
+export type MutateTransitiveConditionallyConfig = {
66
+ kind: 'MutateTransitiveConditionally';
67
+ value: string;
68
+};
69
+
70
+export const MutateTransitiveConditionallySchema: z.ZodType<MutateTransitiveConditionallyConfig> =
71
+ z.object({
72
+ kind: z.literal('MutateTransitiveConditionally'),
73
+ value: LifetimeIdSchema,
74
+ });
75
+
76
export type CreateEffectConfig = {
77
kind: 'Create';
78
into: string;
79
value: ValueKind;
80
+ reason: ValueReason;
81
};
82
83
export const CreateEffectSchema: z.ZodType<CreateEffectConfig> = z.object({
84
kind: z.literal('Create'),
85
into: LifetimeIdSchema,
86
value: ValueKindSchema,
87
+ reason: ValueReasonSchema,
88
});
89
90
export type AssignEffectConfig = {
@@ -69,6 +99,77 @@ export const AssignEffectSchema: z.ZodType<AssignEffectConfig> = z.object({
99
into: LifetimeIdSchema,
100
});
101
102
+export type AliasEffectConfig = {
103
+ kind: 'Alias';
104
+ from: string;
105
+ into: string;
106
+};
107
+
108
+export const AliasEffectSchema: z.ZodType<AliasEffectConfig> = z.object({
109
+ kind: z.literal('Alias'),
110
+ from: LifetimeIdSchema,
111
+ into: LifetimeIdSchema,
112
+});
113
+
114
+export type CaptureEffectConfig = {
115
+ kind: 'Capture';
116
+ from: string;
117
+ into: string;
118
+};
119
+
120
+export const CaptureEffectSchema: z.ZodType<CaptureEffectConfig> = z.object({
121
+ kind: z.literal('Capture'),
122
+ from: LifetimeIdSchema,
123
+ into: LifetimeIdSchema,
124
+});
125
+
126
+export type CreateFromEffectConfig = {
127
+ kind: 'CreateFrom';
128
+ from: string;
129
+ into: string;
130
+};
131
+
132
+export const CreateFromEffectSchema: z.ZodType<CreateFromEffectConfig> =
133
+ z.object({
134
+ kind: z.literal('CreateFrom'),
135
+ from: LifetimeIdSchema,
136
+ into: LifetimeIdSchema,
137
+ });
138
+
139
+export type ApplyArgConfig =
140
+ | string
141
+ | {kind: 'Spread'; place: string}
142
+ | {kind: 'Hole'};
143
+
144
+export const ApplyArgSchema: z.ZodType<ApplyArgConfig> = z.union([
145
+ LifetimeIdSchema,
146
+ z.object({
147
+ kind: z.literal('Spread'),
148
+ place: LifetimeIdSchema,
149
+ }),
150
+ z.object({
151
+ kind: z.literal('Hole'),
152
+ }),
153
+]);
154
+
155
+export type ApplyEffectConfig = {
156
+ kind: 'Apply';
157
+ receiver: string;
158
+ function: string;
159
+ mutatesFunction: boolean;
160
+ args: Array<ApplyArgConfig>;
161
+ into: string;
162
+};
163
+
164
+export const ApplyEffectSchema: z.ZodType<ApplyEffectConfig> = z.object({
165
+ kind: z.literal('Apply'),
166
+ receiver: LifetimeIdSchema,
167
+ function: LifetimeIdSchema,
168
+ mutatesFunction: z.boolean(),
169
+ args: z.array(ApplyArgSchema),
170
+ into: LifetimeIdSchema,
171
+});
172
+
173
export type ImpureEffectConfig = {
174
kind: 'Impure';
175
place: string;
@@ -82,14 +183,26 @@ export const ImpureEffectSchema: z.ZodType<ImpureEffectConfig> = z.object({
183
export type AliasingEffectConfig =
184
| FreezeEffectConfig
185
| CreateEffectConfig
186
+ | CreateFromEffectConfig
187
| AssignEffectConfig
86
- | ImpureEffectConfig;
188
+ | AliasEffectConfig
189
+ | CaptureEffectConfig
190
+ | ImpureEffectConfig
191
+ | MutateEffectConfig
192
+ | MutateTransitiveConditionallyConfig
193
+ | ApplyEffectConfig;
194
195
export const AliasingEffectSchema: z.ZodType<AliasingEffectConfig> = z.union([
196
FreezeEffectSchema,
197
CreateEffectSchema,
198
+ CreateFromEffectSchema,
199
AssignEffectSchema,
200
+ AliasEffectSchema,
201
+ CaptureEffectSchema,
202
ImpureEffectSchema,
203
+ MutateEffectSchema,
204
+ MutateTransitiveConditionallySchema,
205
+ ApplyEffectSchema,
206
]);
207
208
export type AliasingSignatureConfig = {