@jalvin/compiler 2.0.42 → 2.0.43

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":"AAYA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,EACL,aAAa,EAmBd,MAAM,kBAAkB,CAAC;AAM1B,MAAM,MAAM,KAAK,GACb;IAAE,GAAG,EAAE,KAAK,CAAA;CAAE,GACd;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GACf;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,GAChB;IAAE,GAAG,EAAE,QAAQ,CAAA;CAAE,GACjB;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,GAClB;IAAE,GAAG,EAAE,QAAQ,CAAA;CAAE,GACjB;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GACf;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GACf;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,GAChB;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GACf;IAAE,GAAG,EAAE,KAAK,CAAA;CAAE,GACd;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,GAClB;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GACjC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,KAAK,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,aAAa,CAAA;CAAE,GACzJ;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,KAAK,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GACrF;IAAE,GAAG,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CAAE,GACvD;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,GAChB;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,CAAC;AAEvB,eAAO,MAAM,KAAK,EAAE,KAAsB,CAAC;AAC3C,eAAO,MAAM,MAAM,EAAE,KAAuB,CAAC;AAC7C,eAAO,MAAM,OAAO,EAAE,KAAwB,CAAC;AAC/C,eAAO,MAAM,QAAQ,EAAE,KAAyB,CAAC;AACjD,eAAO,MAAM,MAAM,EAAE,KAA0B,CAAC;AAChD,eAAO,MAAM,QAAQ,EAAE,KAAyB,CAAC;AACjD,eAAO,MAAM,MAAM,EAAE,KAAuB,CAAC;AAC7C,eAAO,MAAM,MAAM,EAAE,KAAuB,CAAC;AAC7C,eAAO,MAAM,KAAK,EAAE,KAAsB,CAAC;AAC3C,eAAO,MAAM,SAAS,EAAE,KAA0B,CAAC;AACnD,eAAO,MAAM,OAAO,EAAE,KAAwB,CAAC;AAC/C,eAAO,MAAM,SAAS,EAAE,KAA0B,CAAC;AAcnD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,GAAG,KAAK,CAMxC;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,GAAG,KAAK,CAE9C;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,GAAG,OAAO,CAE5C;AAED,KAAK,SAAS,GAAG,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC;AAEjH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,KAAK,EAAO,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,KAAK,CAIvF;AAMD,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC;IACf,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,KAAK;IAIJ,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI;IAHzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;gBAE1B,MAAM,GAAE,KAAK,GAAG,IAAW;IAEhD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM;IAOlC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAInC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ5B,wEAAwE;IACxE,WAAW,IAAI,MAAM,EAAE;CAGxB;AAuID,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAiB;IACrC,uCAAuC;IACvC,OAAO,CAAC,KAAK,CAAQ;IACrB,6CAA6C;IAC7C,OAAO,CAAC,SAAS,CAAS;IAC1B,uCAAuC;IACvC,OAAO,CAAC,WAAW,CAAS;IAC5B,yEAAyE;IACzE,OAAO,CAAC,uBAAuB,CAAS;IACxC,mDAAmD;IACnD,QAAQ,CAAC,OAAO,qBAA4B;IAC5C;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,8BAAqC;IACjE;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAkC;IACnE;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4C;gBAE5D,IAAI,EAAE,aAAa;IAK/B,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,GAAG,IAAI;IA2BxC;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAkD9B,uDAAuD;IACvD,OAAO,CAAC,WAAW;IASnB,wFAAwF;IACxF,OAAO,CAAC,WAAW;IAQnB,4FAA4F;IAC5F,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,SAAS;IA6EjB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,iBAAiB;IAgCzB,OAAO,CAAC,YAAY;IAoBpB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,iBAAiB;IAgBzB,OAAO,CAAC,cAAc;IA4HtB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,iBAAiB;IA6BzB,OAAO,CAAC,UAAU;IA4BlB,OAAO,CAAC,SAAS;IAoDjB,OAAO,CAAC,WAAW;IAkCnB;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAsBzB;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAwB7B,OAAO,CAAC,aAAa;IAwDrB;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAwE/B,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,aAAa;IAYrB,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,KAAK;IAMhC,OAAO,CAAC,SAAS;IAmNjB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,WAAW;IAmCnB;;;;;;;;;OASG;IACH,OAAO,CAAC,uBAAuB;IA2C/B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,aAAa;IAyDrB,OAAO,CAAC,WAAW;IAyCnB,OAAO,CAAC,WAAW;IA6CnB,OAAO,CAAC,UAAU;IAwClB,OAAO,CAAC,cAAc;IAuBtB,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,UAAU;IAyhBlB;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IA0CzB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,KAAK;IAWb,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,SAAS;IAQjB,YAAY,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM;CA4B/B;AAMD,wBAAgB,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,aAAa,GAAG,WAAW,CAIhF"}
@@ -184,9 +184,11 @@ 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
187
189
  this.sym("viewModel", { tag: "func", params: [], ret: classType("ViewModel"), suspend: false });
188
190
  this.sym("collectAsState", { tag: "func", params: [exports.T_UNKNOWN], paramNames: ["flow"], ret: exports.T_UNKNOWN, suspend: false });
189
- // UI effect hooks
191
+ // React effect hooks
190
192
  const effectDepsType = classType("List", [exports.T_UNKNOWN]);
191
193
  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 });
192
194
  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 });
@@ -241,10 +243,6 @@ class TypeChecker {
241
243
  inSuspend = false;
242
244
  /** Whether we're inside a component */
243
245
  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 = [];
248
246
  /** Whether the program has a wildcard import from a @jalvin/* package */
249
247
  hasWildcardJalvinImport = false;
250
248
  /** Map from node to resolved type (for IDE use) */
@@ -799,14 +797,12 @@ class TypeChecker {
799
797
  this.checkWhileStmt(stmt);
800
798
  break;
801
799
  case "DoWhileStmt": {
802
- this.withComponentOrderNesting("do-while loop", () => {
803
- this.checkBlock(stmt.body);
804
- this.checkExpr(stmt.condition);
805
- });
800
+ this.checkBlock(stmt.body);
801
+ this.checkExpr(stmt.condition);
806
802
  break;
807
803
  }
808
804
  case "TryCatchStmt":
809
- this.withComponentOrderNesting("try/catch statement", () => this.checkTryCatch(stmt));
805
+ this.checkTryCatch(stmt);
810
806
  break;
811
807
  case "LabeledStmt":
812
808
  this.checkStmt(stmt.body);
@@ -814,43 +810,41 @@ class TypeChecker {
814
810
  }
815
811
  }
816
812
  checkIfStmt(stmt) {
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 });
827
- }
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
- });
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 });
845
833
  }
846
- else {
834
+ this.withScope(elseScope, () => {
847
835
  if (stmt.else.kind === "Block")
848
836
  this.checkBlock(stmt.else);
849
837
  else if (stmt.else.kind === "IfStmt")
850
838
  this.checkIfStmt(stmt.else);
851
- }
839
+ });
852
840
  }
853
- });
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);
846
+ }
847
+ }
854
848
  }
855
849
  /**
856
850
  * Extract smart-cast bindings from an `is`-check condition.
@@ -915,63 +909,61 @@ class TypeChecker {
915
909
  return result;
916
910
  }
917
911
  checkWhenStmt(stmt) {
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({
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({
927
937
  name: stmt.subject.binding,
928
- type: subjectType,
938
+ type: narrowedType,
929
939
  mutable: false,
930
- span: stmt.subject.span,
940
+ span: isC.span,
931
941
  });
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
- }
942
+ this.withScope(narrowScope, () => {
963
943
  if (branch.body.kind === "Block")
964
944
  this.checkBlock(branch.body);
965
945
  else
966
946
  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);
967
955
  }
968
- });
969
- }
970
- // Exhaustiveness check for sealed classes
971
- if (subjectType) {
972
- this.checkWhenExhaustiveness(stmt.span, stmt.branches, subjectType);
973
- }
974
- });
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
+ }
975
967
  }
976
968
  /**
977
969
  * If `subjectType` is a sealed class or enum, verify all variants are
@@ -1038,21 +1030,17 @@ class TypeChecker {
1038
1030
  }
1039
1031
  }
1040
1032
  checkForStmt(stmt) {
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
- });
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));
1050
1040
  }
1051
1041
  checkWhileStmt(stmt) {
1052
- this.withComponentOrderNesting("while loop", () => {
1053
- this.checkExpr(stmt.condition);
1054
- this.checkBlock(stmt.body);
1055
- });
1042
+ this.checkExpr(stmt.condition);
1043
+ this.checkBlock(stmt.body);
1056
1044
  }
1057
1045
  checkTryCatch(stmt) {
1058
1046
  this.checkBlock(stmt.body);
@@ -1190,35 +1178,29 @@ class TypeChecker {
1190
1178
  case "LambdaExpr": return this.checkLambda(expr);
1191
1179
  case "IfExpr": return this.checkIfExpr(expr);
1192
1180
  case "WhenExpr": {
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));
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);
1205
1189
  }
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;
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);
1213
1197
  }
1214
1198
  case "TryCatchExpr": {
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
- });
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);
1222
1204
  return exports.T_UNKNOWN;
1223
1205
  }
1224
1206
  case "TypeCheckExpr": {
@@ -1257,14 +1239,14 @@ class TypeChecker {
1257
1239
  }
1258
1240
  const prevSuspend = this.inSuspend;
1259
1241
  this.inSuspend = true;
1260
- this.withComponentOrderNesting("launch block", () => this.checkBlock(expr.body));
1242
+ this.checkBlock(expr.body);
1261
1243
  this.inSuspend = prevSuspend;
1262
1244
  return classType("Job");
1263
1245
  }
1264
1246
  case "AsyncExpr": {
1265
1247
  const prevSuspend = this.inSuspend;
1266
1248
  this.inSuspend = true;
1267
- this.withComponentOrderNesting("async block", () => this.checkBlock(expr.body));
1249
+ this.checkBlock(expr.body);
1268
1250
  this.inSuspend = prevSuspend;
1269
1251
  return classType("Deferred", [exports.T_UNKNOWN]);
1270
1252
  }
@@ -1413,27 +1395,6 @@ class TypeChecker {
1413
1395
  return null;
1414
1396
  }
1415
1397
  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
- }
1437
1398
  const calleeType = this.checkExpr(expr.callee);
1438
1399
  for (const arg of expr.args)
1439
1400
  this.checkExpr(arg.value);
@@ -1478,53 +1439,6 @@ class TypeChecker {
1478
1439
  this.diag.error(expr.span, diagnostics_js_1.E_NOT_A_FUNCTION, `Type '${this.typeToString(calleeType)}' is not callable`);
1479
1440
  return exports.T_ERROR;
1480
1441
  }
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
- }
1528
1442
  checkLambda(expr, expectedParamTypes) {
1529
1443
  const childScope = new Scope(this.scope);
1530
1444
  // If the lambda has no explicit params, synthesise an `it` binding.
@@ -1553,14 +1467,12 @@ class TypeChecker {
1553
1467
  }
1554
1468
  let retType = exports.T_UNIT;
1555
1469
  this.withScope(childScope, () => {
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
- });
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
+ }
1564
1476
  });
1565
1477
  const paramTypes = expr.params.length > 0
1566
1478
  ? expr.params.map((p) => (p.type ? this.resolveTypeRef(p.type) : exports.T_UNKNOWN))
@@ -1568,46 +1480,42 @@ class TypeChecker {
1568
1480
  return { tag: "func", params: paramTypes, ret: retType, suspend: false };
1569
1481
  }
1570
1482
  checkIfExpr(expr) {
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) {
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) {
1578
1501
  const existing = this.scope.lookup(name);
1579
1502
  if (existing)
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));
1600
- }
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);
1503
+ elseScope.define({ ...existing, type });
1607
1504
  }
1608
- resultType = this.unify([thenType, elseType]);
1609
- });
1610
- return resultType;
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]);
1611
1519
  }
1612
1520
  // ── Type resolution ────────────────────────────────────────────────────────
1613
1521
  lookupType(nameParts) {