Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion tsc/internal/transformers/declarations/tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,13 @@ func (s *SymbolTrackerImpl) isBoundExpando(node *ast.Node) bool {
if !(ast.IsExpandoPropertyDeclaration(node) && ast.IsPropertyAccessExpression(node.AsBinaryExpression().Left)) {
return false
}
ref := s.resolver.GetReferencedValueDeclarationUnsafe(ast.GetLeftmostExpression(node.AsBinaryExpression().Left, true))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With isolatedDeclarations on, if a type can't be inferred, the Go declaration emitter reports an error. Before reporting, it checks if the node is inside an expando assignment like f.x = …, so it doesn't report the same problem twice. This check (isBoundExpando) treated every a.b = … assignment as rooted at a name and passed that root to name lookup.

But with this.x = foo() the root is the this keyword, not a name, so the lookup's Node.Text() would just panic.

// Match transformExpandoAssignment: only an assignment rooted at an identifier (`f.x = ...`) can bind an expando
// property; `this.x = ...`, `super.x = ...`, `f().x = ...` and the like have no referenced declaration.
ns := ast.GetLeftmostAccessExpression(node.AsBinaryExpression().Left)
if !ast.IsIdentifier(ns) {
return false
}
ref := s.resolver.GetReferencedValueDeclarationUnsafe(ns)
if ref == nil {
return false
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error TS5053: Option 'allowJs' cannot be specified with option 'isolatedDeclarations'.
a.js(4,9): error TS9013: Expression type can't be inferred with --isolatedDeclarations.


!!! error TS5053: Option 'allowJs' cannot be specified with option 'isolatedDeclarations'.
==== a.js (1 errors) ====
function foo() { return 1; }
export class C {
constructor() {
this.x = foo();
~~~~~~~~~~~~~~
!!! error TS9013: Expression type can't be inferred with --isolatedDeclarations.
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//// [tests/cases/compiler/isolatedDeclarationsJsThisPropertyAssignmentInference.ts] ////

=== a.js ===
function foo() { return 1; }
>foo : Symbol(foo, Decl(a.js, 0, 0))

export class C {
>C : Symbol(C, Decl(a.js, 0, 28))

constructor() {
this.x = foo();
>this.x : Symbol(C.x, Decl(a.js, 2, 19))
>this : Symbol(C, Decl(a.js, 0, 28))
>x : Symbol(C.x, Decl(a.js, 2, 19))
>foo : Symbol(foo, Decl(a.js, 0, 0))
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//// [tests/cases/compiler/isolatedDeclarationsJsThisPropertyAssignmentInference.ts] ////

=== a.js ===
function foo() { return 1; }
>foo : () => number
>1 : 1

export class C {
>C : C

constructor() {
this.x = foo();
>this.x = foo() : number
>this.x : any
>this : this
>x : any
>foo() : number
>foo : () => number
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//// [tests/cases/compiler/isolatedDeclarationsNonIdentifierAssignmentInference.ts] ////

//// [isolatedDeclarationsNonIdentifierAssignmentInference.ts]
declare function foo(): number;
declare function bar(): { x: number };
class Base { get y(): number { return 0; } set y(v: number) {} }
export class C extends Base {
z = 0;
a = { p: (this.z = foo()) };
b = { p: (super.y = foo()) };
c = { p: (bar().x = foo()) };
}
export const d = { p: (bar().x = foo()) };




//// [isolatedDeclarationsNonIdentifierAssignmentInference.d.ts]
declare class Base {
get y(): number;
set y(v: number);
}
export declare class C extends Base {
z: number;
a: {
p: number;
};
b: {
p: number;
};
c: {
p: number;
};
}
export declare const d: {
p: number;
};
export {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//// [tests/cases/compiler/isolatedDeclarationsNonIdentifierAssignmentInference.ts] ////

=== isolatedDeclarationsNonIdentifierAssignmentInference.ts ===
declare function foo(): number;
>foo : Symbol(foo, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 0))

declare function bar(): { x: number };
>bar : Symbol(bar, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 31))
>x : Symbol(x, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 25))

class Base { get y(): number { return 0; } set y(v: number) {} }
>Base : Symbol(Base, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 38))
>y : Symbol(Base.y, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 12), Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 42))
>y : Symbol(Base.y, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 12), Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 42))
>v : Symbol(v, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 49))

export class C extends Base {
>C : Symbol(C, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 64))
>Base : Symbol(Base, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 38))

z = 0;
>z : Symbol(C.z, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 3, 29))

a = { p: (this.z = foo()) };
>a : Symbol(C.a, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 4, 10))
>p : Symbol(p, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 5, 9))
>this.z : Symbol(C.z, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 3, 29))
>this : Symbol(C, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 64))
>z : Symbol(C.z, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 3, 29))
>foo : Symbol(foo, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 0))

b = { p: (super.y = foo()) };
>b : Symbol(C.b, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 5, 32))
>p : Symbol(p, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 6, 9))
>super.y : Symbol(Base.y, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 12), Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 42))
>super : Symbol(Base, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 38))
>y : Symbol(Base.y, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 12), Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 42))
>foo : Symbol(foo, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 0))

c = { p: (bar().x = foo()) };
>c : Symbol(C.c, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 6, 33))
>p : Symbol(p, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 7, 9))
>bar().x : Symbol(x, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 25))
>bar : Symbol(bar, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 31))
>x : Symbol(x, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 25))
>foo : Symbol(foo, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 0))
}
export const d = { p: (bar().x = foo()) };
>d : Symbol(d, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 9, 12))
>p : Symbol(p, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 9, 18))
>bar().x : Symbol(x, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 25))
>bar : Symbol(bar, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 31))
>x : Symbol(x, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 25))
>foo : Symbol(foo, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 0))

Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//// [tests/cases/compiler/isolatedDeclarationsNonIdentifierAssignmentInference.ts] ////

=== isolatedDeclarationsNonIdentifierAssignmentInference.ts ===
declare function foo(): number;
>foo : () => number

declare function bar(): { x: number };
>bar : () => { x: number; }
>x : number

class Base { get y(): number { return 0; } set y(v: number) {} }
>Base : Base
>y : number
>0 : 0
>y : number
>v : number

export class C extends Base {
>C : C
>Base : Base

z = 0;
>z : number
>0 : 0

a = { p: (this.z = foo()) };
>a : { p: number; }
>{ p: (this.z = foo()) } : { p: number; }
>p : number
>(this.z = foo()) : number
>this.z = foo() : number
>this.z : number
>this : this
>z : number
>foo() : number
>foo : () => number

b = { p: (super.y = foo()) };
>b : { p: number; }
>{ p: (super.y = foo()) } : { p: number; }
>p : number
>(super.y = foo()) : number
>super.y = foo() : number
>super.y : number
>super : Base
>y : number
>foo() : number
>foo : () => number

c = { p: (bar().x = foo()) };
>c : { p: number; }
>{ p: (bar().x = foo()) } : { p: number; }
>p : number
>(bar().x = foo()) : number
>bar().x = foo() : number
>bar().x : number
>bar() : { x: number; }
>bar : () => { x: number; }
>x : number
>foo() : number
>foo : () => number
}
export const d = { p: (bar().x = foo()) };
>d : { p: number; }
>{ p: (bar().x = foo()) } : { p: number; }
>p : number
>(bar().x = foo()) : number
>bar().x = foo() : number
>bar().x : number
>bar() : { x: number; }
>bar : () => { x: number; }
>x : number
>foo() : number
>foo : () => number

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
isolatedDeclarationsNonIdentifierAssignmentInference.ts(6,15): error TS9013: Expression type can't be inferred with --isolatedDeclarations.
isolatedDeclarationsNonIdentifierAssignmentInference.ts(7,15): error TS9013: Expression type can't be inferred with --isolatedDeclarations.
isolatedDeclarationsNonIdentifierAssignmentInference.ts(8,15): error TS9013: Expression type can't be inferred with --isolatedDeclarations.
isolatedDeclarationsNonIdentifierAssignmentInference.ts(10,24): error TS9013: Expression type can't be inferred with --isolatedDeclarations.


==== isolatedDeclarationsNonIdentifierAssignmentInference.ts (4 errors) ====
declare function foo(): number;
declare function bar(): { x: number };
class Base { get y(): number { return 0; } set y(v: number) {} }
export class C extends Base {
z = 0;
a = { p: (this.z = foo()) };
~~~~~~~~~~~~~~
!!! error TS9013: Expression type can't be inferred with --isolatedDeclarations.
!!! related TS9029 isolatedDeclarationsNonIdentifierAssignmentInference.ts:6:5: Add a type annotation to the property a.
!!! related TS9035 isolatedDeclarationsNonIdentifierAssignmentInference.ts:6:15: Add satisfies and a type assertion to this expression (satisfies T as T) to make the type explicit.
b = { p: (super.y = foo()) };
~~~~~~~~~~~~~~~
!!! error TS9013: Expression type can't be inferred with --isolatedDeclarations.
!!! related TS9029 isolatedDeclarationsNonIdentifierAssignmentInference.ts:7:5: Add a type annotation to the property b.
!!! related TS9035 isolatedDeclarationsNonIdentifierAssignmentInference.ts:7:15: Add satisfies and a type assertion to this expression (satisfies T as T) to make the type explicit.
c = { p: (bar().x = foo()) };
~~~~~~~~~~~~~~~
!!! error TS9013: Expression type can't be inferred with --isolatedDeclarations.
!!! related TS9029 isolatedDeclarationsNonIdentifierAssignmentInference.ts:8:5: Add a type annotation to the property c.
!!! related TS9035 isolatedDeclarationsNonIdentifierAssignmentInference.ts:8:15: Add satisfies and a type assertion to this expression (satisfies T as T) to make the type explicit.
}
export const d = { p: (bar().x = foo()) };
~~~~~~~~~~~~~~~
!!! error TS9013: Expression type can't be inferred with --isolatedDeclarations.
!!! related TS9027 isolatedDeclarationsNonIdentifierAssignmentInference.ts:10:14: Add a type annotation to the variable d.
!!! related TS9035 isolatedDeclarationsNonIdentifierAssignmentInference.ts:10:24: Add satisfies and a type assertion to this expression (satisfies T as T) to make the type explicit.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//// [tests/cases/compiler/isolatedDeclarationsNonIdentifierAssignmentInference.ts] ////

=== isolatedDeclarationsNonIdentifierAssignmentInference.ts ===
declare function foo(): number;
>foo : Symbol(foo, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 0))

declare function bar(): { x: number };
>bar : Symbol(bar, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 31))
>x : Symbol(x, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 25))

class Base { get y(): number { return 0; } set y(v: number) {} }
>Base : Symbol(Base, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 38))
>y : Symbol(Base.y, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 12), Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 42))
>y : Symbol(Base.y, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 12), Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 42))
>v : Symbol(v, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 49))

export class C extends Base {
>C : Symbol(C, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 64))
>Base : Symbol(Base, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 38))

z = 0;
>z : Symbol(C.z, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 3, 29))

a = { p: (this.z = foo()) };
>a : Symbol(C.a, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 4, 10))
>p : Symbol(p, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 5, 9))
>this.z : Symbol(C.z, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 3, 29))
>this : Symbol(C, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 64))
>z : Symbol(C.z, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 3, 29))
>foo : Symbol(foo, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 0))

b = { p: (super.y = foo()) };
>b : Symbol(C.b, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 5, 32))
>p : Symbol(p, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 6, 9))
>super.y : Symbol(Base.y, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 12), Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 42))
>super : Symbol(Base, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 38))
>y : Symbol(Base.y, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 12), Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 2, 42))
>foo : Symbol(foo, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 0))

c = { p: (bar().x = foo()) };
>c : Symbol(C.c, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 6, 33))
>p : Symbol(p, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 7, 9))
>bar().x : Symbol(x, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 25))
>bar : Symbol(bar, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 31))
>x : Symbol(x, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 25))
>foo : Symbol(foo, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 0))
}
export const d = { p: (bar().x = foo()) };
>d : Symbol(d, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 9, 12))
>p : Symbol(p, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 9, 18))
>bar().x : Symbol(x, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 25))
>bar : Symbol(bar, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 31))
>x : Symbol(x, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 1, 25))
>foo : Symbol(foo, Decl(isolatedDeclarationsNonIdentifierAssignmentInference.ts, 0, 0))

Loading