@jalvin/compiler 2.0.43 → 2.0.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"typechecker.d.ts","sourceRoot":"","sources":["../src/typechecker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"typechecker.d.ts","sourceRoot":"","sources":["../src/typechecker.ts"],"names":[],"mappings":"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"}
@@ -184,11 +184,9 @@ class TypeEnv {
184
184
  // State & MVVM
185
185
  this.sym("mutableStateOf", { tag: "func", params: [exports.T_UNKNOWN], paramNames: ["value"], ret: classType("MutableState", [exports.T_UNKNOWN]), suspend: false });
186
186
  this.sym("remember", { tag: "func", params: [{ tag: "func", params: [], ret: exports.T_UNKNOWN, suspend: false }], paramNames: ["calculation"], ret: exports.T_UNKNOWN, suspend: false });
187
- this.sym("useViewModel", { tag: "func", params: [exports.T_STRING, { tag: "func", params: [], ret: exports.T_UNKNOWN, suspend: false }], paramNames: ["key", "factory"], ret: classType("ViewModel"), suspend: false });
188
- // Keep old `viewModel` alias for source compat
189
187
  this.sym("viewModel", { tag: "func", params: [], ret: classType("ViewModel"), suspend: false });
190
188
  this.sym("collectAsState", { tag: "func", params: [exports.T_UNKNOWN], paramNames: ["flow"], ret: exports.T_UNKNOWN, suspend: false });
191
- // React effect hooks
189
+ // UI effect hooks
192
190
  const effectDepsType = classType("List", [exports.T_UNKNOWN]);
193
191
  this.sym("LaunchedEffect", { tag: "func", params: [effectDepsType, { tag: "func", params: [], ret: exports.T_UNIT, suspend: true }], paramNames: ["deps", "block"], ret: exports.T_UNIT, suspend: false });
194
192
  this.sym("DisposableEffect", { tag: "func", params: [effectDepsType, { tag: "func", params: [], ret: exports.T_UNIT, suspend: false }], paramNames: ["deps", "block"], ret: exports.T_UNIT, suspend: false });
@@ -243,6 +241,10 @@ class TypeChecker {
243
241
  inSuspend = false;
244
242
  /** Whether we're inside a component */
245
243
  inComponent = false;
244
+ /** Nesting depth where component-only APIs would violate stable call order. */
245
+ componentCallOrderDepth = 0;
246
+ /** Context stack describing where call-order nesting was introduced. */
247
+ componentCallOrderContextStack = [];
246
248
  /** Whether the program has a wildcard import from a @jalvin/* package */
247
249
  hasWildcardJalvinImport = false;
248
250
  /** Map from node to resolved type (for IDE use) */
@@ -797,12 +799,14 @@ class TypeChecker {
797
799
  this.checkWhileStmt(stmt);
798
800
  break;
799
801
  case "DoWhileStmt": {
800
- this.checkBlock(stmt.body);
801
- this.checkExpr(stmt.condition);
802
+ this.withComponentOrderNesting("do-while loop", () => {
803
+ this.checkBlock(stmt.body);
804
+ this.checkExpr(stmt.condition);
805
+ });
802
806
  break;
803
807
  }
804
808
  case "TryCatchStmt":
805
- this.checkTryCatch(stmt);
809
+ this.withComponentOrderNesting("try/catch statement", () => this.checkTryCatch(stmt));
806
810
  break;
807
811
  case "LabeledStmt":
808
812
  this.checkStmt(stmt.body);
@@ -810,41 +814,43 @@ class TypeChecker {
810
814
  }
811
815
  }
812
816
  checkIfStmt(stmt) {
813
- const condType = this.checkExpr(stmt.condition);
814
- this.assertAssignable(stmt.condition.span, condType, exports.T_BOOL);
815
- // Smart cast: if (x is T) { ... } narrows x to T inside the then branch
816
- const narrowings = this.extractSmartCasts(stmt.condition);
817
- const thenScope = new Scope(this.scope);
818
- for (const [name, type] of narrowings) {
819
- const existing = this.scope.lookup(name);
820
- if (existing) {
821
- thenScope.define({ ...existing, type });
822
- }
823
- }
824
- this.withScope(thenScope, () => this.checkBlock(stmt.then));
825
- if (stmt.else) {
826
- const elseNarrowings = this.extractElseSmartCasts(stmt.condition);
827
- if (elseNarrowings.size > 0) {
828
- const elseScope = new Scope(this.scope);
829
- for (const [name, type] of elseNarrowings) {
830
- const existing = this.scope.lookup(name);
831
- if (existing)
832
- elseScope.define({ ...existing, type });
817
+ this.withComponentOrderNesting("if statement", () => {
818
+ const condType = this.checkExpr(stmt.condition);
819
+ this.assertAssignable(stmt.condition.span, condType, exports.T_BOOL);
820
+ // Smart cast: if (x is T) { ... } narrows x to T inside the then branch
821
+ const narrowings = this.extractSmartCasts(stmt.condition);
822
+ const thenScope = new Scope(this.scope);
823
+ for (const [name, type] of narrowings) {
824
+ const existing = this.scope.lookup(name);
825
+ if (existing) {
826
+ thenScope.define({ ...existing, type });
833
827
  }
834
- this.withScope(elseScope, () => {
828
+ }
829
+ this.withScope(thenScope, () => this.checkBlock(stmt.then));
830
+ if (stmt.else) {
831
+ const elseNarrowings = this.extractElseSmartCasts(stmt.condition);
832
+ if (elseNarrowings.size > 0) {
833
+ const elseScope = new Scope(this.scope);
834
+ for (const [name, type] of elseNarrowings) {
835
+ const existing = this.scope.lookup(name);
836
+ if (existing)
837
+ elseScope.define({ ...existing, type });
838
+ }
839
+ this.withScope(elseScope, () => {
840
+ if (stmt.else.kind === "Block")
841
+ this.checkBlock(stmt.else);
842
+ else if (stmt.else.kind === "IfStmt")
843
+ this.checkIfStmt(stmt.else);
844
+ });
845
+ }
846
+ else {
835
847
  if (stmt.else.kind === "Block")
836
848
  this.checkBlock(stmt.else);
837
849
  else if (stmt.else.kind === "IfStmt")
838
850
  this.checkIfStmt(stmt.else);
839
- });
840
- }
841
- else {
842
- if (stmt.else.kind === "Block")
843
- this.checkBlock(stmt.else);
844
- else if (stmt.else.kind === "IfStmt")
845
- this.checkIfStmt(stmt.else);
851
+ }
846
852
  }
847
- }
853
+ });
848
854
  }
849
855
  /**
850
856
  * Extract smart-cast bindings from an `is`-check condition.
@@ -909,61 +915,63 @@ class TypeChecker {
909
915
  return result;
910
916
  }
911
917
  checkWhenStmt(stmt) {
912
- const subjectType = stmt.subject ? this.checkExpr(stmt.subject.expr) : null;
913
- // Bind `when (val x = expr)` into each branch scope
914
- for (const branch of stmt.branches) {
915
- const branchScope = stmt.subject?.binding
916
- ? new Scope(this.scope)
917
- : this.scope;
918
- if (stmt.subject?.binding && subjectType) {
919
- branchScope.define({
920
- name: stmt.subject.binding,
921
- type: subjectType,
922
- mutable: false,
923
- span: stmt.subject.span,
924
- });
925
- }
926
- this.withScope(branchScope, () => {
927
- // Smart cast narrowing: for single `is Type` condition, narrow subject type
928
- if (stmt.subject?.binding &&
929
- subjectType &&
930
- branch.conditions.length === 1 &&
931
- branch.conditions[0].kind === "WhenIsCondition" &&
932
- !branch.conditions[0].negated) {
933
- const isC = branch.conditions[0];
934
- const narrowedType = this.resolveTypeRef(isC.type);
935
- const narrowScope = new Scope(branchScope);
936
- narrowScope.define({
918
+ this.withComponentOrderNesting("when statement", () => {
919
+ const subjectType = stmt.subject ? this.checkExpr(stmt.subject.expr) : null;
920
+ // Bind `when (val x = expr)` into each branch scope
921
+ for (const branch of stmt.branches) {
922
+ const branchScope = stmt.subject?.binding
923
+ ? new Scope(this.scope)
924
+ : this.scope;
925
+ if (stmt.subject?.binding && subjectType) {
926
+ branchScope.define({
937
927
  name: stmt.subject.binding,
938
- type: narrowedType,
928
+ type: subjectType,
939
929
  mutable: false,
940
- span: isC.span,
930
+ span: stmt.subject.span,
941
931
  });
942
- this.withScope(narrowScope, () => {
932
+ }
933
+ this.withScope(branchScope, () => {
934
+ // Smart cast narrowing: for single `is Type` condition, narrow subject type
935
+ if (stmt.subject?.binding &&
936
+ subjectType &&
937
+ branch.conditions.length === 1 &&
938
+ branch.conditions[0].kind === "WhenIsCondition" &&
939
+ !branch.conditions[0].negated) {
940
+ const isC = branch.conditions[0];
941
+ const narrowedType = this.resolveTypeRef(isC.type);
942
+ const narrowScope = new Scope(branchScope);
943
+ narrowScope.define({
944
+ name: stmt.subject.binding,
945
+ type: narrowedType,
946
+ mutable: false,
947
+ span: isC.span,
948
+ });
949
+ this.withScope(narrowScope, () => {
950
+ if (branch.body.kind === "Block")
951
+ this.checkBlock(branch.body);
952
+ else
953
+ this.checkExpr(branch.body);
954
+ });
955
+ }
956
+ else {
957
+ for (const cond of branch.conditions) {
958
+ if (cond.kind === "WhenExprCondition")
959
+ this.checkExpr(cond.expr);
960
+ else if (cond.kind === "WhenInCondition")
961
+ this.checkExpr(cond.expr);
962
+ }
943
963
  if (branch.body.kind === "Block")
944
964
  this.checkBlock(branch.body);
945
965
  else
946
966
  this.checkExpr(branch.body);
947
- });
948
- }
949
- else {
950
- for (const cond of branch.conditions) {
951
- if (cond.kind === "WhenExprCondition")
952
- this.checkExpr(cond.expr);
953
- else if (cond.kind === "WhenInCondition")
954
- this.checkExpr(cond.expr);
955
967
  }
956
- if (branch.body.kind === "Block")
957
- this.checkBlock(branch.body);
958
- else
959
- this.checkExpr(branch.body);
960
- }
961
- });
962
- }
963
- // Exhaustiveness check for sealed classes
964
- if (subjectType) {
965
- this.checkWhenExhaustiveness(stmt.span, stmt.branches, subjectType);
966
- }
968
+ });
969
+ }
970
+ // Exhaustiveness check for sealed classes
971
+ if (subjectType) {
972
+ this.checkWhenExhaustiveness(stmt.span, stmt.branches, subjectType);
973
+ }
974
+ });
967
975
  }
968
976
  /**
969
977
  * If `subjectType` is a sealed class or enum, verify all variants are
@@ -1030,17 +1038,21 @@ class TypeChecker {
1030
1038
  }
1031
1039
  }
1032
1040
  checkForStmt(stmt) {
1033
- const iterType = this.checkExpr(stmt.iterable);
1034
- const elemType = this.elementTypeOf(iterType);
1035
- const childScope = new Scope(this.scope);
1036
- if (typeof stmt.binding === "string") {
1037
- childScope.define({ name: stmt.binding, type: elemType, mutable: false, span: stmt.span });
1038
- }
1039
- this.withScope(childScope, () => this.checkBlock(stmt.body));
1041
+ this.withComponentOrderNesting("for loop", () => {
1042
+ const iterType = this.checkExpr(stmt.iterable);
1043
+ const elemType = this.elementTypeOf(iterType);
1044
+ const childScope = new Scope(this.scope);
1045
+ if (typeof stmt.binding === "string") {
1046
+ childScope.define({ name: stmt.binding, type: elemType, mutable: false, span: stmt.span });
1047
+ }
1048
+ this.withScope(childScope, () => this.checkBlock(stmt.body));
1049
+ });
1040
1050
  }
1041
1051
  checkWhileStmt(stmt) {
1042
- this.checkExpr(stmt.condition);
1043
- this.checkBlock(stmt.body);
1052
+ this.withComponentOrderNesting("while loop", () => {
1053
+ this.checkExpr(stmt.condition);
1054
+ this.checkBlock(stmt.body);
1055
+ });
1044
1056
  }
1045
1057
  checkTryCatch(stmt) {
1046
1058
  this.checkBlock(stmt.body);
@@ -1178,29 +1190,35 @@ class TypeChecker {
1178
1190
  case "LambdaExpr": return this.checkLambda(expr);
1179
1191
  case "IfExpr": return this.checkIfExpr(expr);
1180
1192
  case "WhenExpr": {
1181
- const subjectType = expr.subject ? this.checkExpr(expr.subject.expr) : null;
1182
- const branchTypes = [];
1183
- for (const b of expr.branches) {
1184
- for (const c of b.conditions) {
1185
- if (c.kind === "WhenExprCondition")
1186
- this.checkExpr(c.expr);
1187
- else if (c.kind === "WhenInCondition")
1188
- this.checkExpr(c.expr);
1193
+ let resultType = exports.T_UNKNOWN;
1194
+ this.withComponentOrderNesting("when expression", () => {
1195
+ const subjectType = expr.subject ? this.checkExpr(expr.subject.expr) : null;
1196
+ const branchTypes = [];
1197
+ for (const b of expr.branches) {
1198
+ for (const c of b.conditions) {
1199
+ if (c.kind === "WhenExprCondition")
1200
+ this.checkExpr(c.expr);
1201
+ else if (c.kind === "WhenInCondition")
1202
+ this.checkExpr(c.expr);
1203
+ }
1204
+ branchTypes.push(b.body.kind === "Block" ? (this.checkBlock(b.body), exports.T_UNIT) : this.checkExpr(b.body));
1189
1205
  }
1190
- branchTypes.push(b.body.kind === "Block" ? (this.checkBlock(b.body), exports.T_UNIT) : this.checkExpr(b.body));
1191
- }
1192
- // Exhaustiveness: when-expr on a sealed class MUST be exhaustive
1193
- if (subjectType) {
1194
- this.checkWhenExhaustiveness(expr.span, expr.branches, subjectType);
1195
- }
1196
- return this.unify(branchTypes);
1206
+ // Exhaustiveness: when-expr on a sealed class MUST be exhaustive
1207
+ if (subjectType) {
1208
+ this.checkWhenExhaustiveness(expr.span, expr.branches, subjectType);
1209
+ }
1210
+ resultType = this.unify(branchTypes);
1211
+ });
1212
+ return resultType;
1197
1213
  }
1198
1214
  case "TryCatchExpr": {
1199
- this.checkBlock(expr.body);
1200
- for (const c of expr.catches)
1201
- this.checkBlock(c.body);
1202
- if (expr.finally)
1203
- this.checkBlock(expr.finally);
1215
+ this.withComponentOrderNesting("try/catch expression", () => {
1216
+ this.checkBlock(expr.body);
1217
+ for (const c of expr.catches)
1218
+ this.checkBlock(c.body);
1219
+ if (expr.finally)
1220
+ this.checkBlock(expr.finally);
1221
+ });
1204
1222
  return exports.T_UNKNOWN;
1205
1223
  }
1206
1224
  case "TypeCheckExpr": {
@@ -1239,14 +1257,14 @@ class TypeChecker {
1239
1257
  }
1240
1258
  const prevSuspend = this.inSuspend;
1241
1259
  this.inSuspend = true;
1242
- this.checkBlock(expr.body);
1260
+ this.withComponentOrderNesting("launch block", () => this.checkBlock(expr.body));
1243
1261
  this.inSuspend = prevSuspend;
1244
1262
  return classType("Job");
1245
1263
  }
1246
1264
  case "AsyncExpr": {
1247
1265
  const prevSuspend = this.inSuspend;
1248
1266
  this.inSuspend = true;
1249
- this.checkBlock(expr.body);
1267
+ this.withComponentOrderNesting("async block", () => this.checkBlock(expr.body));
1250
1268
  this.inSuspend = prevSuspend;
1251
1269
  return classType("Deferred", [exports.T_UNKNOWN]);
1252
1270
  }
@@ -1395,6 +1413,27 @@ class TypeChecker {
1395
1413
  return null;
1396
1414
  }
1397
1415
  checkCallExpr(expr) {
1416
+ const componentOnlyName = this.getComponentOnlyCalleeName(expr.callee);
1417
+ if (componentOnlyName) {
1418
+ if (!this.inComponent) {
1419
+ this.diag.error(expr.span, diagnostics_js_1.E_COMPONENT_CONTEXT_REQUIRED, `'${componentOnlyName}' can only be called inside a component function`);
1420
+ }
1421
+ else if (this.componentCallOrderDepth > 0) {
1422
+ const context = this.currentComponentOrderContext();
1423
+ this.diag.error(expr.span, diagnostics_js_1.E_COMPONENT_CALL_ORDER, `'${componentOnlyName}' must be called unconditionally at the top level of a component function`, [
1424
+ {
1425
+ span: null,
1426
+ message: context
1427
+ ? `Invalid call occurs inside ${context}`
1428
+ : "Invalid call occurs inside nested control flow",
1429
+ },
1430
+ {
1431
+ span: null,
1432
+ message: "Move this call to the top-level component body",
1433
+ },
1434
+ ]);
1435
+ }
1436
+ }
1398
1437
  const calleeType = this.checkExpr(expr.callee);
1399
1438
  for (const arg of expr.args)
1400
1439
  this.checkExpr(arg.value);
@@ -1439,6 +1478,53 @@ class TypeChecker {
1439
1478
  this.diag.error(expr.span, diagnostics_js_1.E_NOT_A_FUNCTION, `Type '${this.typeToString(calleeType)}' is not callable`);
1440
1479
  return exports.T_ERROR;
1441
1480
  }
1481
+ /**
1482
+ * Runtime APIs that are only valid in component functions.
1483
+ * We key by callee name to keep checks fast and diagnostics clear.
1484
+ */
1485
+ isComponentOnlyApi(name) {
1486
+ return name === "mutableStateOf" ||
1487
+ name === "remember" ||
1488
+ name === "rememberMutableStateOf" ||
1489
+ name === "collectAsState" ||
1490
+ name === "useViewModel" ||
1491
+ name === "LaunchedEffect" ||
1492
+ name === "DisposableEffect" ||
1493
+ name === "SideEffect" ||
1494
+ name === "useMutableInteractionSource" ||
1495
+ name === "useIsHovered" ||
1496
+ name === "useIsFocused" ||
1497
+ name === "useIsPressed";
1498
+ }
1499
+ getComponentOnlyCalleeName(callee) {
1500
+ if (callee.kind === "NameExpr" && this.isComponentOnlyApi(callee.name)) {
1501
+ return callee.name;
1502
+ }
1503
+ if ((callee.kind === "MemberExpr" || callee.kind === "SafeMemberExpr") && this.isComponentOnlyApi(callee.member)) {
1504
+ return callee.member;
1505
+ }
1506
+ return null;
1507
+ }
1508
+ currentComponentOrderContext() {
1509
+ if (this.componentCallOrderContextStack.length === 0)
1510
+ return null;
1511
+ return this.componentCallOrderContextStack[this.componentCallOrderContextStack.length - 1];
1512
+ }
1513
+ withComponentOrderNesting(context, fn) {
1514
+ if (!this.inComponent) {
1515
+ fn();
1516
+ return;
1517
+ }
1518
+ this.componentCallOrderDepth++;
1519
+ this.componentCallOrderContextStack.push(context);
1520
+ try {
1521
+ fn();
1522
+ }
1523
+ finally {
1524
+ this.componentCallOrderContextStack.pop();
1525
+ this.componentCallOrderDepth--;
1526
+ }
1527
+ }
1442
1528
  checkLambda(expr, expectedParamTypes) {
1443
1529
  const childScope = new Scope(this.scope);
1444
1530
  // If the lambda has no explicit params, synthesise an `it` binding.
@@ -1467,12 +1553,14 @@ class TypeChecker {
1467
1553
  }
1468
1554
  let retType = exports.T_UNIT;
1469
1555
  this.withScope(childScope, () => {
1470
- for (const stmt of expr.body) {
1471
- if (stmt.kind === "ExprStmt")
1472
- retType = this.checkExpr(stmt.expr);
1473
- else
1474
- this.checkStmt(stmt);
1475
- }
1556
+ this.withComponentOrderNesting("lambda body", () => {
1557
+ for (const stmt of expr.body) {
1558
+ if (stmt.kind === "ExprStmt")
1559
+ retType = this.checkExpr(stmt.expr);
1560
+ else
1561
+ this.checkStmt(stmt);
1562
+ }
1563
+ });
1476
1564
  });
1477
1565
  const paramTypes = expr.params.length > 0
1478
1566
  ? expr.params.map((p) => (p.type ? this.resolveTypeRef(p.type) : exports.T_UNKNOWN))
@@ -1480,42 +1568,46 @@ class TypeChecker {
1480
1568
  return { tag: "func", params: paramTypes, ret: retType, suspend: false };
1481
1569
  }
1482
1570
  checkIfExpr(expr) {
1483
- this.checkExpr(expr.condition);
1484
- // Apply smart casts in the `then` branch
1485
- const narrowings = this.extractSmartCasts(expr.condition);
1486
- const thenScope = new Scope(this.scope);
1487
- for (const [name, type] of narrowings) {
1488
- const existing = this.scope.lookup(name);
1489
- if (existing)
1490
- thenScope.define({ ...existing, type });
1491
- }
1492
- const thenType = this.withScope(thenScope, () => expr.then.kind === "Block"
1493
- ? (this.checkBlock(expr.then), exports.T_UNIT)
1494
- : this.checkExpr(expr.then));
1495
- // Apply narrowings for the else branch (e.g. `x !is T` → else: x IS T)
1496
- const elseNarrowings = this.extractElseSmartCasts(expr.condition);
1497
- let elseType;
1498
- if (elseNarrowings.size > 0) {
1499
- const elseScope = new Scope(this.scope);
1500
- for (const [name, type] of elseNarrowings) {
1571
+ let resultType = exports.T_UNKNOWN;
1572
+ this.withComponentOrderNesting("if expression", () => {
1573
+ this.checkExpr(expr.condition);
1574
+ // Apply smart casts in the `then` branch
1575
+ const narrowings = this.extractSmartCasts(expr.condition);
1576
+ const thenScope = new Scope(this.scope);
1577
+ for (const [name, type] of narrowings) {
1501
1578
  const existing = this.scope.lookup(name);
1502
1579
  if (existing)
1503
- elseScope.define({ ...existing, type });
1580
+ thenScope.define({ ...existing, type });
1581
+ }
1582
+ const thenType = this.withScope(thenScope, () => expr.then.kind === "Block"
1583
+ ? (this.checkBlock(expr.then), exports.T_UNIT)
1584
+ : this.checkExpr(expr.then));
1585
+ // Apply narrowings for the else branch (e.g. `x !is T` → else: x IS T)
1586
+ const elseNarrowings = this.extractElseSmartCasts(expr.condition);
1587
+ let elseType;
1588
+ if (elseNarrowings.size > 0) {
1589
+ const elseScope = new Scope(this.scope);
1590
+ for (const [name, type] of elseNarrowings) {
1591
+ const existing = this.scope.lookup(name);
1592
+ if (existing)
1593
+ elseScope.define({ ...existing, type });
1594
+ }
1595
+ elseType = this.withScope(elseScope, () => expr.else.kind === "Block"
1596
+ ? (this.checkBlock(expr.else), exports.T_UNIT)
1597
+ : expr.else.kind === "IfExpr"
1598
+ ? this.checkIfExpr(expr.else)
1599
+ : this.checkExpr(expr.else));
1504
1600
  }
1505
- elseType = this.withScope(elseScope, () => expr.else.kind === "Block"
1506
- ? (this.checkBlock(expr.else), exports.T_UNIT)
1507
- : expr.else.kind === "IfExpr"
1508
- ? this.checkIfExpr(expr.else)
1509
- : this.checkExpr(expr.else));
1510
- }
1511
- else {
1512
- elseType = expr.else.kind === "Block"
1513
- ? (this.checkBlock(expr.else), exports.T_UNIT)
1514
- : expr.else.kind === "IfExpr"
1515
- ? this.checkIfExpr(expr.else)
1516
- : this.checkExpr(expr.else);
1517
- }
1518
- return this.unify([thenType, elseType]);
1601
+ else {
1602
+ elseType = expr.else.kind === "Block"
1603
+ ? (this.checkBlock(expr.else), exports.T_UNIT)
1604
+ : expr.else.kind === "IfExpr"
1605
+ ? this.checkIfExpr(expr.else)
1606
+ : this.checkExpr(expr.else);
1607
+ }
1608
+ resultType = this.unify([thenType, elseType]);
1609
+ });
1610
+ return resultType;
1519
1611
  }
1520
1612
  // ── Type resolution ────────────────────────────────────────────────────────
1521
1613
  lookupType(nameParts) {