Skip to content

Commit

Permalink
Fix caching not complely accurate symbol (#2617)
Browse files Browse the repository at this point in the history
This PR #2603 resolved an
issue where resolving meta types would cause types to be checked too
early but this broke some late bound symbol resolution.

It would return the declaration symbol when `checkTemplateTypes` is
false but would cache it. So in some cases it would then resolve the
wrong symbol later
  • Loading branch information
timotheeguerin authored Oct 31, 2023
1 parent f1daf15 commit 2fb62e6
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@typespec/compiler",
"comment": "",
"type": "none"
}
],
"packageName": "@typespec/compiler"
}
11 changes: 6 additions & 5 deletions packages/compiler/src/core/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2152,16 +2152,17 @@ export function createChecker(program: Program): Checker {
mapper: TypeMapper | undefined,
options?: Partial<SymbolResolutionOptions> | boolean
): Sym | undefined {
if (mapper === undefined && referenceSymCache.has(node)) {
return referenceSymCache.get(node);
}

const resolvedOptions: SymbolResolutionOptions =
typeof options === "boolean"
? { ...defaultSymbolResolutionOptions, resolveDecorators: options }
: { ...defaultSymbolResolutionOptions, ...(options ?? {}) };
if (mapper === undefined && resolvedOptions.checkTemplateTypes && referenceSymCache.has(node)) {
return referenceSymCache.get(node);
}
const sym = resolveTypeReferenceSymInternal(node, mapper, resolvedOptions);
referenceSymCache.set(node, sym);
if (resolvedOptions.checkTemplateTypes) {
referenceSymCache.set(node, sym);
}
return sym;
}

Expand Down
22 changes: 22 additions & 0 deletions packages/compiler/test/checker/interface.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,28 @@ describe("compiler: interfaces", () => {
message: `Can't pass template arguments to non-templated type`,
});
});

// https://github.com/microsoft/typespec/pull/2617
it("can 'op is' a templated operation inside templated interface", async () => {
const { myBar } = (await runner.compile(`
interface Foo<A> {
bar<B>(input: A): B;
}
alias MyFoo = Foo<string>;
@test op myBar is MyFoo.bar<int32>;
`)) as {
myBar: Operation;
};

const input = myBar.parameters.properties.get("input")!.type;
strictEqual(input.kind, "Scalar" as const);
strictEqual(input.name, "string");

const returnType = myBar.returnType;
strictEqual(returnType.kind, "Scalar" as const);
strictEqual(returnType.name, "int32");
});
});

it("can decorate extended operations independently", async () => {
Expand Down

0 comments on commit 2fb62e6

Please sign in to comment.