diff --git a/src/compiler.ts b/src/compiler.ts index d9dd2df4cc..35cdf63aed 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -9237,13 +9237,10 @@ export class Compiler extends DiagnosticEmitter { // make a getter for the expression (also obtains the type) var getValue = this.compileExpression( // reports expression.operand, - contextualType.exceptVoid, + contextualType, Constraints.NONE ); - // shortcut if compiling the getter already failed - if (getExpressionId(getValue) == ExpressionId.Unreachable) return getValue; - // if the value isn't dropped, a temp. local is required to remember the original value, // except if a static overload is found, which reverses the use of a temp. (see below) var tempLocal: Local | null = null; @@ -9450,6 +9447,17 @@ export class Compiler extends DiagnosticEmitter { return module.unreachable(); } + // check assignability + var targetType = resolver.getTypeOfElement(target); + if (!targetType) targetType = Type.void; + if (!this.currentType.isStrictlyAssignableTo(targetType)) { + this.error( + DiagnosticCode.Type_0_is_not_assignable_to_type_1, + expression.range, this.currentType.toString(), targetType.toString() + ); + return module.unreachable(); + } + // simplify if dropped anyway if (!tempLocal) { return this.makeAssignment( @@ -9597,7 +9605,7 @@ export class Compiler extends DiagnosticEmitter { compound = true; expr = this.compileExpression( expression.operand, - contextualType.exceptVoid, + contextualType, Constraints.NONE ); @@ -9668,7 +9676,7 @@ export class Compiler extends DiagnosticEmitter { compound = true; expr = this.compileExpression( expression.operand, - contextualType.exceptVoid, + contextualType, Constraints.NONE ); @@ -9837,6 +9845,18 @@ export class Compiler extends DiagnosticEmitter { var resolver = this.resolver; var target = resolver.lookupExpression(expression.operand, this.currentFlow); if (!target) return module.unreachable(); + + // check assignability + var targetType = resolver.getTypeOfElement(target); + if (!targetType) targetType = Type.void; + if (!this.currentType.isStrictlyAssignableTo(targetType)) { + this.error( + DiagnosticCode.Type_0_is_not_assignable_to_type_1, + expression.range, this.currentType.toString(), targetType.toString() + ); + return module.unreachable(); + } + return this.makeAssignment( target, expr, diff --git a/tests/compiler/increment-error.json b/tests/compiler/increment-error.json new file mode 100644 index 0000000000..a375b1a570 --- /dev/null +++ b/tests/compiler/increment-error.json @@ -0,0 +1,53 @@ +{ + "asc_flags": [ + ], + "stderr": [ + "AS234: Expression does not compile to a value at runtime.", "++Foo;", + "TS2469: The '++' operator cannot be applied to type 'void'.", "++Foo;", + "AS234: Expression does not compile to a value at runtime.", "Foo += 1;", + "TS2469: The '+' operator cannot be applied to type 'void'.", "Foo += 1;", + "AS234: Expression does not compile to a value at runtime.", "Foo--;", + "TS2469: The '--' operator cannot be applied to type 'void'.", "Foo--;", + "AS234: Expression does not compile to a value at runtime.", "--Foo;", + "TS2469: The '--' operator cannot be applied to type 'void'.", "--Foo;", + "AS234: Expression does not compile to a value at runtime.", "Foo -= 1;", + "TS2469: The '-' operator cannot be applied to type 'void'.", "Foo -= 1;", + "AS234: Expression does not compile to a value at runtime.", "Array++;", + "TS2469: The '++' operator cannot be applied to type 'void'.", "Array++;", + "AS234: Expression does not compile to a value at runtime.", "++Array;", + "TS2469: The '++' operator cannot be applied to type 'void'.", "++Array;", + "AS234: Expression does not compile to a value at runtime.", "Array += 1;", + "TS2469: The '+' operator cannot be applied to type 'void'.", "Array += 1;", + "AS234: Expression does not compile to a value at runtime.", "Array--;", + "TS2469: The '--' operator cannot be applied to type 'void'.", "Array--;", + "AS234: Expression does not compile to a value at runtime.", "--Array;", + "TS2469: The '--' operator cannot be applied to type 'void'.", "--Array;", + "AS234: Expression does not compile to a value at runtime.", "Array -= 1;", + "TS2469: The '-' operator cannot be applied to type 'void'.", "Array -= 1;", + "AS234: Expression does not compile to a value at runtime.", "const a = (Foo++);", + "TS2322: Type 'i32' is not assignable to type 'void'.", "const a = (Foo++);", + "AS234: Expression does not compile to a value at runtime.", "const b = (++Foo);", + "TS2322: Type 'i32' is not assignable to type 'void'.", "const b = (++Foo);", + "AS234: Expression does not compile to a value at runtime.", "const c = (Foo += 1);", + "TS2322: Type 'i32' is not assignable to type 'void'.", "const c = (Foo += 1);", + "AS234: Expression does not compile to a value at runtime.", "const d = (Foo--);", + "TS2322: Type 'i32' is not assignable to type 'void'.", "const d = (Foo--);", + "AS234: Expression does not compile to a value at runtime.", "const e = (--Foo);", + "TS2322: Type 'i32' is not assignable to type 'void'.", "const e = (--Foo);", + "AS234: Expression does not compile to a value at runtime.", "const f = (Foo -= 1);", + "TS2322: Type 'i32' is not assignable to type 'void'.", "const f = (Foo -= 1);", + "AS234: Expression does not compile to a value at runtime.", "const g = (Array++);", + "TS2322: Type 'i32' is not assignable to type 'void'.", "const g = (Array++);", + "AS234: Expression does not compile to a value at runtime.", "const h = (++Array);", + "TS2322: Type 'i32' is not assignable to type 'void'.", "const h = (++Array);", + "AS234: Expression does not compile to a value at runtime.", "const i = (Array += 1);", + "TS2322: Type 'i32' is not assignable to type 'void'.", "const i = (Array += 1);", + "AS234: Expression does not compile to a value at runtime.", "const j = (Array--);", + "TS2322: Type 'i32' is not assignable to type 'void'.", "const j = (Array--);", + "AS234: Expression does not compile to a value at runtime.", "const k = (--Array);", + "TS2322: Type 'i32' is not assignable to type 'void'.", "const k = (--Array);", + "AS234: Expression does not compile to a value at runtime.", "const l = (Array -= 1);", + "TS2322: Type 'i32' is not assignable to type 'void'.", "const l = (Array -= 1);", + "EOF" + ] +} \ No newline at end of file diff --git a/tests/compiler/increment-error.ts b/tests/compiler/increment-error.ts new file mode 100644 index 0000000000..bbfb3e53ec --- /dev/null +++ b/tests/compiler/increment-error.ts @@ -0,0 +1,39 @@ +/* eslint-disable no-class-assign */ +/* eslint-disable no-global-assign */ + +class Foo {} + +Foo++; +++Foo; +Foo += 1; + +Foo--; +--Foo; +Foo -= 1; + +Array++; +++Array; +Array += 1; + +Array--; +--Array; +Array -= 1; + +const a = (Foo++); +const b = (++Foo); +const c = (Foo += 1); + +const d = (Foo--); +const e = (--Foo); +const f = (Foo -= 1); + + +const g = (Array++); +const h = (++Array); +const i = (Array += 1); + +const j = (Array--); +const k = (--Array); +const l = (Array -= 1); + +ERROR("EOF"); \ No newline at end of file