Use better context scope for class constructor implementation signatures (#58168)

This commit is contained in:
Wesley Wigham 2024-04-12 12:52:14 -07:00 committed by GitHub
parent 585a9af830
commit a9b0d1ee53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 392 additions and 1 deletions

View File

@ -34814,7 +34814,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (candidate.typeParameters) {
// If we are *inside the body of candidate*, we need to create a clone of `candidate` with differing type parameter identities,
// so our inference results for this call doesn't pollute expression types referencing the outer type parameter!
if (candidate.declaration && findAncestor(node, a => a === candidate.declaration)) {
const paramLocation = candidate.typeParameters[0].symbol.declarations?.[0]?.parent;
const candidateParameterContext = paramLocation || (candidate.declaration && isConstructorDeclaration(candidate.declaration) ? candidate.declaration.parent : candidate.declaration);
if (candidateParameterContext && findAncestor(node, a => a === candidateParameterContext)) {
candidate = getImplementationSignature(candidate);
}
let typeArgumentTypes: readonly Type[] | undefined;

View File

@ -0,0 +1,73 @@
//// [tests/cases/compiler/inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts] ////
//// [inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts]
// simple example
export class Test<A, B> {
constructor(public a: A, public b: B) { }
test<C>(c: C): Test<B, C> {
return new Test(this.b, c);
}
}
// complicated one
interface Supervisor<out T> {
zip<A>(right: Supervisor<A>): Supervisor<[T, A]>;
}
export class Zip<out T0, out T1> implements Supervisor<readonly [T0, T1]> {
constructor(
readonly left: Supervisor<T0>,
readonly right: Supervisor<T1>,
) { }
zip<A>(right: Supervisor<A>): Supervisor<[[T0, T1], A]> {
return new Zip(this, right);
}
}
// indirect
type Assign<T, U> = Omit<T, keyof U> & U;
class Base<T> {
constructor(public t: T) { }
}
export class Foo<T> extends Base<T> {
update(): Foo<Assign<T, { x: number }>> {
const v: Assign<T, { x: number }> = Object.assign(this.t, { x: 1 });
return new Foo(v);
}
}
//// [inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.js]
// simple example
export class Test {
constructor(a, b) {
this.a = a;
this.b = b;
}
test(c) {
return new Test(this.b, c);
}
}
export class Zip {
constructor(left, right) {
this.left = left;
this.right = right;
}
zip(right) {
return new Zip(this, right);
}
}
class Base {
constructor(t) {
this.t = t;
}
}
export class Foo extends Base {
update() {
const v = Object.assign(this.t, { x: 1 });
return new Foo(v);
}
}

View File

@ -0,0 +1,138 @@
//// [tests/cases/compiler/inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts] ////
=== inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts ===
// simple example
export class Test<A, B> {
>Test : Symbol(Test, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 0, 0))
>A : Symbol(A, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 1, 18))
>B : Symbol(B, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 1, 20))
constructor(public a: A, public b: B) { }
>a : Symbol(Test.a, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 2, 16))
>A : Symbol(A, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 1, 18))
>b : Symbol(Test.b, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 2, 28))
>B : Symbol(B, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 1, 20))
test<C>(c: C): Test<B, C> {
>test : Symbol(Test.test, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 2, 45))
>C : Symbol(C, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 4, 9))
>c : Symbol(c, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 4, 12))
>C : Symbol(C, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 4, 9))
>Test : Symbol(Test, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 0, 0))
>B : Symbol(B, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 1, 20))
>C : Symbol(C, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 4, 9))
return new Test(this.b, c);
>Test : Symbol(Test, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 0, 0))
>this.b : Symbol(Test.b, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 2, 28))
>this : Symbol(Test, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 0, 0))
>b : Symbol(Test.b, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 2, 28))
>c : Symbol(c, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 4, 12))
}
}
// complicated one
interface Supervisor<out T> {
>Supervisor : Symbol(Supervisor, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 7, 1))
>T : Symbol(T, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 10, 21))
zip<A>(right: Supervisor<A>): Supervisor<[T, A]>;
>zip : Symbol(Supervisor.zip, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 10, 29))
>A : Symbol(A, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 11, 8))
>right : Symbol(right, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 11, 11))
>Supervisor : Symbol(Supervisor, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 7, 1))
>A : Symbol(A, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 11, 8))
>Supervisor : Symbol(Supervisor, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 7, 1))
>T : Symbol(T, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 10, 21))
>A : Symbol(A, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 11, 8))
}
export class Zip<out T0, out T1> implements Supervisor<readonly [T0, T1]> {
>Zip : Symbol(Zip, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 12, 1))
>T0 : Symbol(T0, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 14, 17))
>T1 : Symbol(T1, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 14, 24))
>Supervisor : Symbol(Supervisor, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 7, 1))
>T0 : Symbol(T0, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 14, 17))
>T1 : Symbol(T1, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 14, 24))
constructor(
readonly left: Supervisor<T0>,
>left : Symbol(Zip.left, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 15, 16))
>Supervisor : Symbol(Supervisor, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 7, 1))
>T0 : Symbol(T0, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 14, 17))
readonly right: Supervisor<T1>,
>right : Symbol(Zip.right, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 16, 38))
>Supervisor : Symbol(Supervisor, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 7, 1))
>T1 : Symbol(T1, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 14, 24))
) { }
zip<A>(right: Supervisor<A>): Supervisor<[[T0, T1], A]> {
>zip : Symbol(Zip.zip, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 18, 9))
>A : Symbol(A, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 20, 8))
>right : Symbol(right, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 20, 11))
>Supervisor : Symbol(Supervisor, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 7, 1))
>A : Symbol(A, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 20, 8))
>Supervisor : Symbol(Supervisor, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 7, 1))
>T0 : Symbol(T0, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 14, 17))
>T1 : Symbol(T1, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 14, 24))
>A : Symbol(A, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 20, 8))
return new Zip(this, right);
>Zip : Symbol(Zip, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 12, 1))
>this : Symbol(Zip, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 12, 1))
>right : Symbol(right, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 20, 11))
}
}
// indirect
type Assign<T, U> = Omit<T, keyof U> & U;
>Assign : Symbol(Assign, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 23, 1))
>T : Symbol(T, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 26, 12))
>U : Symbol(U, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 26, 14))
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 26, 12))
>U : Symbol(U, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 26, 14))
>U : Symbol(U, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 26, 14))
class Base<T> {
>Base : Symbol(Base, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 26, 41))
>T : Symbol(T, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 28, 11))
constructor(public t: T) { }
>t : Symbol(Base.t, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 29, 16))
>T : Symbol(T, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 28, 11))
}
export class Foo<T> extends Base<T> {
>Foo : Symbol(Foo, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 30, 1))
>T : Symbol(T, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 32, 17))
>Base : Symbol(Base, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 26, 41))
>T : Symbol(T, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 32, 17))
update(): Foo<Assign<T, { x: number }>> {
>update : Symbol(Foo.update, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 32, 37))
>Foo : Symbol(Foo, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 30, 1))
>Assign : Symbol(Assign, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 23, 1))
>T : Symbol(T, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 32, 17))
>x : Symbol(x, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 33, 29))
const v: Assign<T, { x: number }> = Object.assign(this.t, { x: 1 });
>v : Symbol(v, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 34, 13))
>Assign : Symbol(Assign, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 23, 1))
>T : Symbol(T, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 32, 17))
>x : Symbol(x, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 34, 28))
>Object.assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
>this.t : Symbol(Base.t, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 29, 16))
>this : Symbol(Foo, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 30, 1))
>t : Symbol(Base.t, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 29, 16))
>x : Symbol(x, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 34, 67))
return new Foo(v);
>Foo : Symbol(Foo, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 30, 1))
>v : Symbol(v, Decl(inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts, 34, 13))
}
}

View File

@ -0,0 +1,139 @@
//// [tests/cases/compiler/inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts] ////
=== inferenceOuterResultNotIncorrectlyInstantiatedWithInnerResult.ts ===
// simple example
export class Test<A, B> {
>Test : Test<A, B>
> : ^^^^^^^^^^
constructor(public a: A, public b: B) { }
>a : A
> : ^
>b : B
> : ^
test<C>(c: C): Test<B, C> {
>test : <C>(c: C) => Test<B, C>
> : ^ ^^ ^^ ^^^^^
>c : C
> : ^
return new Test(this.b, c);
>new Test(this.b, c) : Test<B, C>
> : ^^^^^^^^^^
>Test : typeof Test
> : ^^^^^^^^^^^
>this.b : B
> : ^
>this : this
> : ^^^^
>b : B
> : ^
>c : C
> : ^
}
}
// complicated one
interface Supervisor<out T> {
zip<A>(right: Supervisor<A>): Supervisor<[T, A]>;
>zip : <A>(right: Supervisor<A>) => Supervisor<[T, A]>
> : ^ ^^ ^^ ^^^^^
>right : Supervisor<A>
> : ^^^^^^^^^^^^^
}
export class Zip<out T0, out T1> implements Supervisor<readonly [T0, T1]> {
>Zip : Zip<T0, T1>
> : ^^^^^^^^^^^
constructor(
readonly left: Supervisor<T0>,
>left : Supervisor<T0>
> : ^^^^^^^^^^^^^^
readonly right: Supervisor<T1>,
>right : Supervisor<T1>
> : ^^^^^^^^^^^^^^
) { }
zip<A>(right: Supervisor<A>): Supervisor<[[T0, T1], A]> {
>zip : <A>(right: Supervisor<A>) => Supervisor<[[T0, T1], A]>
> : ^ ^^ ^^ ^^^^^
>right : Supervisor<A>
> : ^^^^^^^^^^^^^
return new Zip(this, right);
>new Zip(this, right) : Zip<[T0, T1], A>
> : ^^^^^^^^^^^^^^^^
>Zip : typeof Zip
> : ^^^^^^^^^^
>this : this
> : ^^^^
>right : Supervisor<A>
> : ^^^^^^^^^^^^^
}
}
// indirect
type Assign<T, U> = Omit<T, keyof U> & U;
>Assign : Assign<T, U>
> : ^^^^^^^^^^^^
class Base<T> {
>Base : Base<T>
> : ^^^^^^^
constructor(public t: T) { }
>t : T
> : ^
}
export class Foo<T> extends Base<T> {
>Foo : Foo<T>
> : ^^^^^^
>Base : Base<T>
> : ^^^^^^^
update(): Foo<Assign<T, { x: number }>> {
>update : () => Foo<Assign<T, { x: number; }>>
> : ^^^^^^
>x : number
> : ^^^^^^
const v: Assign<T, { x: number }> = Object.assign(this.t, { x: 1 });
>v : Assign<T, { x: number; }>
> : ^^^^^^^^^^^^^^^ ^^^^
>x : number
> : ^^^^^^
>Object.assign(this.t, { x: 1 }) : T & { x: number; }
> : ^^^^^^^^^^^^^^^^^^
>Object.assign : { <T_1 extends {}, U>(target: T_1, source: U): T_1 & U; <T_2 extends {}, U_1, V>(target: T_2, source1: U_1, source2: V): T_2 & U_1 & V; <T_3 extends {}, U_2, V_1, W>(target: T_3, source1: U_2, source2: V_1, source3: W): T_3 & U_2 & V_1 & W; (target: object, ...sources: any[]): any; }
> : ^^^ ^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^^ ^^^^^^^^^
>Object : ObjectConstructor
> : ^^^^^^^^^^^^^^^^^
>assign : { <T_1 extends {}, U>(target: T_1, source: U): T_1 & U; <T_2 extends {}, U_1, V>(target: T_2, source1: U_1, source2: V): T_2 & U_1 & V; <T_3 extends {}, U_2, V_1, W>(target: T_3, source1: U_2, source2: V_1, source3: W): T_3 & U_2 & V_1 & W; (target: object, ...sources: any[]): any; }
> : ^^^ ^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^^ ^^^^^^^^^
>this.t : T
> : ^
>this : this
> : ^^^^
>t : T
> : ^
>{ x: 1 } : { x: number; }
> : ^^^^^^^^^^^^^^
>x : number
> : ^^^^^^
>1 : 1
> : ^
return new Foo(v);
>new Foo(v) : Foo<Assign<T, { x: number; }>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>Foo : typeof Foo
> : ^^^^^^^^^^
>v : Assign<T, { x: number; }>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^
}
}

View File

@ -0,0 +1,39 @@
// @target: es6
// simple example
export class Test<A, B> {
constructor(public a: A, public b: B) { }
test<C>(c: C): Test<B, C> {
return new Test(this.b, c);
}
}
// complicated one
interface Supervisor<out T> {
zip<A>(right: Supervisor<A>): Supervisor<[T, A]>;
}
export class Zip<out T0, out T1> implements Supervisor<readonly [T0, T1]> {
constructor(
readonly left: Supervisor<T0>,
readonly right: Supervisor<T1>,
) { }
zip<A>(right: Supervisor<A>): Supervisor<[[T0, T1], A]> {
return new Zip(this, right);
}
}
// indirect
type Assign<T, U> = Omit<T, keyof U> & U;
class Base<T> {
constructor(public t: T) { }
}
export class Foo<T> extends Base<T> {
update(): Foo<Assign<T, { x: number }>> {
const v: Assign<T, { x: number }> = Object.assign(this.t, { x: 1 });
return new Foo(v);
}
}