Skip to content

Commit

Permalink
special handling for Completion/NormalCompletion
Browse files Browse the repository at this point in the history
  • Loading branch information
bakkot committed Sep 17, 2024
1 parent 0e610e6 commit 5a93027
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 7 deletions.
37 changes: 32 additions & 5 deletions src/type-logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,15 @@ export function meet(a: Type, b: Type): Type {
// union is join. meet distributes over join.
return a.of.map(t => meet(t, b)).reduce(join);
}
if (
(a.kind === 'list' && b.kind === 'list') ||
(a.kind === 'normal completion' && b.kind === 'normal completion')
) {
return { kind: a.kind, of: meet(a.of, b.of) };
if (a.kind === 'list' && b.kind === 'list') {
return { kind: 'list', of: meet(a.of, b.of) };
}
if (a.kind === 'normal completion' && b.kind === 'normal completion') {
const inner = meet(a.of, b.of);
if (inner.kind === 'never') {
return { kind: 'never' };
}
return { kind: 'normal completion', of: inner };
}
return { kind: 'never' };
}
Expand Down Expand Up @@ -398,6 +402,29 @@ export function typeFromExpr(expr: Expr, biblio: Biblio): Type {
}
const calleeName = callee[0].contents;

// special case: `Completion` is identity on completions
if (expr.name === 'call' && calleeName === 'Completion' && expr.arguments.length === 1) {
const inner = typeFromExpr(expr.arguments[0], biblio);
if (!isCompletion(inner)) {
// probably unknown, we might as well refine to "some completion"
return {
kind: 'union',
of: [
{ kind: 'normal completion', of: { kind: 'unknown' } },
{ kind: 'abrupt completion' },
],
};
}
}
// special case: `NormalCompletion` wraps its input
if (
expr.name === 'call' &&
calleeName === 'NormalCompletion' &&
expr.arguments.length === 1
) {
return { kind: 'normal completion', of: typeFromExpr(expr.arguments[0], biblio) };
}

const biblioEntry = biblio.byAoid(calleeName);
if (biblioEntry?.signature?.return == null) {
break;
Expand Down
11 changes: 9 additions & 2 deletions test/typecheck.js
Original file line number Diff line number Diff line change
Expand Up @@ -1511,7 +1511,7 @@ describe('type system', () => {
await assertTypeError(
'an ECMAScript language value',
'NormalCompletion(42)',
'argument type (a normal completion) does not look plausibly assignable to parameter type (ECMAScript language value)',
'argument type (a normal completion containing 42) does not look plausibly assignable to parameter type (ECMAScript language value)',
[completionBiblio],
);

Expand All @@ -1535,7 +1535,14 @@ describe('type system', () => {
await assertTypeError(
'a Boolean',
'NormalCompletion(*false*)',
'argument type (a normal completion) does not look plausibly assignable to parameter type (Boolean)',
'argument type (a normal completion containing false) does not look plausibly assignable to parameter type (Boolean)',
[completionBiblio],
);

await assertTypeError(
'a normal completion containing a Number',
'NormalCompletion(*false*)',
'argument type (a normal completion containing false) does not look plausibly assignable to parameter type (a normal completion containing Number)',
[completionBiblio],
);

Expand Down

0 comments on commit 5a93027

Please sign in to comment.