Skip to content
21 changes: 18 additions & 3 deletions src/compiler.ts
Original file line number Diff line number Diff line change
@@ -5596,8 +5596,11 @@ export class Compiler extends DiagnosticEmitter {
}
return this.module.unreachable();
}
assert(indexedSet.signature.parameterTypes.length == 2); // parser must guarantee this
targetType = indexedSet.signature.parameterTypes[1]; // 2nd parameter is the element
let parameterTypes = indexedSet.signature.parameterTypes;

assert(parameterTypes.length == 2); // parser must guarantee this
targetType = parameterTypes[1]; // 2nd parameter is the element

if (indexedSet.hasDecorator(DecoratorFlags.UNSAFE)) this.checkUnsafe(expression);
if (!isUnchecked && this.options.pedantic) {
this.pedantic(
@@ -5788,7 +5791,19 @@ export class Compiler extends DiagnosticEmitter {
thisType,
Constraints.CONV_IMPLICIT | Constraints.IS_THIS
);
let elementExpr = this.compileExpression(assert(indexExpression), Type.i32, Constraints.CONV_IMPLICIT);
let setterIndexType = setterInstance.signature.parameterTypes[0];
let getterIndexType = getterInstance.signature.parameterTypes[0];
if (!setterIndexType.equals(getterIndexType)) {
this.errorRelated(
DiagnosticCode.Index_signature_accessors_in_type_0_differ_in_types,
getterInstance.identifierAndSignatureRange,
setterInstance.identifierAndSignatureRange,
classInstance.internalName,
);
this.currentType = tee ? getterInstance.signature.returnType : Type.void;
return module.unreachable();
}
let elementExpr = this.compileExpression(assert(indexExpression), setterIndexType, Constraints.CONV_IMPLICIT);
let elementType = this.currentType;
if (tee) {
let tempTarget = flow.getTempLocal(thisType);
1 change: 1 addition & 0 deletions src/diagnosticMessages.json
Original file line number Diff line number Diff line change
@@ -48,6 +48,7 @@
"Expression does not compile to a value at runtime.": 234,
"Only variables, functions and enums become WebAssembly module exports.": 235,
"Literal '{0}' does not fit into 'i64' or 'u64' types.": 236,
"Index signature accessors in type '{0}' differ in types.": 237,

"Importing the table disables some indirect call optimizations.": 901,
"Exporting the table disables some indirect call optimizations.": 902,
544 changes: 515 additions & 29 deletions tests/compiler/std/operator-overloading.debug.wat

Large diffs are not rendered by default.

3,106 changes: 1,755 additions & 1,351 deletions tests/compiler/std/operator-overloading.release.wat

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions tests/compiler/std/operator-overloading.ts
Original file line number Diff line number Diff line change
@@ -330,3 +330,41 @@ aii1++; // 2, 3
var aii2 = new TesterInlineInstance(2, 3);
var aii = aii1 + aii2;
assert(aii.x == 4 && aii.y == 6);

// test custom element access overloading with string keys
class TesterElementAccess {
[key: string]: number;
constructor(
public x: i32,
public y: i32
) {}
@operator("[]")
__get(key: string): i32 {
return key == "x"
? this.x
: this.y;
}
@operator("[]=")
__set(key: string, value: i32): void {
key == "x"
? this.x = value
: this.y = value;
}
}

var tea = new TesterElementAccess(1, 2);

tea["x"] = -1;
tea["y"] = -2;

assert(tea.x == -1);
assert(tea["x"] == -1);

assert(tea.y == -2);
assert(tea["y"] == -2);

tea["x"]++;
--tea["y"];

assert(tea["x"] == 0);
assert(tea["y"] == -3);