872
reason: new Set([ValueReason.Other]),
873
context: new Set(),
874
};
875
+
876
+ for (const element of instrValue.elements) {
877
+ if (element.kind === 'Spread') {
878
+ state.referenceAndRecordEffects(
879
+ freezeActions,
880
+ element.place,
881
+ isArrayType(element.place.identifier)
882
+ ? Effect.Capture
883
+ : Effect.ConditionallyMutate,
884
+ ValueReason.Other,
885
+ );
886
+ } else if (element.kind === 'Identifier') {
887
+ state.referenceAndRecordEffects(
888
+ freezeActions,
889
+ element,
890
+ Effect.Capture,
891
+ ValueReason.Other,
892
+ );
893
+ } else {
894
+ let _: 'Hole' = element.kind;
895
+ }
896
+ }
897
+ state.initialize(instrValue, valueKind);
898
+ state.define(instr.lvalue, instrValue);
899
+ instr.lvalue.effect = Effect.Store;
900
continuation = {
876
- kind: 'initialize',
877
- valueKind,
878
- effect: {kind: Effect.Capture, reason: ValueReason.Other},
879
- lvalueEffect: Effect.Store,
901
+ kind: 'funeffects',
902
};
903
break;
904
}
1263
for (let i = 0; i < instrValue.args.length; i++) {
1264
const arg = instrValue.args[i];
1265
const place = arg.kind === 'Identifier' ? arg : arg.place;
1244
- if (effects !== null) {
1245
- state.referenceAndRecordEffects(
1246
- freezeActions,
1247
- place,
1248
- effects[i],
1249
- ValueReason.Other,
1250
- );
1251
- } else {
1252
- state.referenceAndRecordEffects(
1253
- freezeActions,
1254
- place,
1255
- Effect.ConditionallyMutate,
1256
- ValueReason.Other,
1257
- );
1258
- }
1266
+ state.referenceAndRecordEffects(
1267
+ freezeActions,
1268
+ place,
1269
+ getArgumentEffect(effects != null ? effects[i] : null, arg),
1270
+ ValueReason.Other,
1271
+ );
1272
hasCaptureArgument ||= place.effect === Effect.Capture;
1273
}
1274
if (signature !== null) {
1320
signature !== null
1321
? {
1322
kind: signature.returnValueKind,
1310
- reason: new Set([ValueReason.Other]),
1323
+ reason: new Set([
1324
+ signature.returnValueReason ??
1325
+ ValueReason.KnownReturnSignature,
1326
+ ]),
1327
context: new Set(),
1328
}
1329
: {
1372
for (let i = 0; i < instrValue.args.length; i++) {
1373
const arg = instrValue.args[i];
1374
const place = arg.kind === 'Identifier' ? arg : arg.place;
1359
- if (effects !== null) {
1360
- /*
1361
- * If effects are inferred for an argument, we should fail invalid
1362
- * mutating effects
1363
- */
1364
- state.referenceAndRecordEffects(
1365
- freezeActions,
1366
- place,
1367
- effects[i],
1368
- ValueReason.Other,
1369
- );
1370
- } else {
1371
- state.referenceAndRecordEffects(
1372
- freezeActions,
1373
- place,
1374
- Effect.ConditionallyMutate,
1375
- ValueReason.Other,
1376
- );
1377
- }
1375
+ /*
1376
+ * If effects are inferred for an argument, we should fail invalid
1377
+ * mutating effects
1378
+ */
1379
+ state.referenceAndRecordEffects(
1380
+ freezeActions,
1381
+ place,
1382
+ getArgumentEffect(effects != null ? effects[i] : null, arg),
1383
+ ValueReason.Other,
1384
+ );
1385
hasCaptureArgument ||= place.effect === Effect.Capture;
1386
}
1387
if (signature !== null) {
2056
}
2057
return true;
2058
}
2059
+
2060
+function getArgumentEffect(
2061
+ signatureEffect: Effect | null,
2062
+ arg: Place | SpreadPattern,
2063
+): Effect {
2064
+ if (signatureEffect != null) {
2065
+ if (arg.kind === 'Identifier') {
2066
+ return signatureEffect;
2067
+ } else if (
2068
+ signatureEffect === Effect.Mutate ||
2069
+ signatureEffect === Effect.ConditionallyMutate
2070
+ ) {
2071
+ return signatureEffect;
2072
+ } else {
2073
+ // see call-spread-argument-mutable-iterator test fixture
2074
+ if (signatureEffect === Effect.Freeze) {
2075
+ CompilerError.throwTodo({
2076
+ reason: 'Support spread syntax for hook arguments',
2077
+ loc: arg.place.loc,
2078
+ });
2079
+ }
2080
+ // effects[i] is Effect.Capture | Effect.Read | Effect.Store
2081
+ return Effect.ConditionallyMutate;
2082
+ }
2083
+ } else {
2084
+ return Effect.ConditionallyMutate;
2085
+ }
2086
+}