diff --git a/src/compiler.ts b/src/compiler.ts index 710b778736..f3660f9a71 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -5990,11 +5990,8 @@ export class Compiler extends DiagnosticEmitter { if (!target) return module.unreachable(); let thisExpression = this.resolver.currentThisExpression; - let signature: Signature | null; - let functionArg: ExpressionRef; + // handle direct call switch (target.kind) { - - // direct call: concrete function case ElementKind.FunctionPrototype: { let functionPrototype = target; if (functionPrototype.hasDecorator(DecoratorFlags.Builtin)) { @@ -6024,128 +6021,35 @@ export class Compiler extends DiagnosticEmitter { constraints ); } + } - // indirect call: first-class function (non-generic, can't be inlined) - case ElementKind.Local: { - let local = target; - signature = local.type.signatureReference; - if (signature) { - if (local.parent != flow.targetFunction) { - // TODO: closures - this.error( - DiagnosticCode.Not_implemented_0, - expression.range, - "Closures" - ); - return module.unreachable(); - } - if (local.is(CommonFlags.Inlined)) { - let inlinedValue = local.constantIntegerValue; - if (this.options.isWasm64) { - functionArg = module.i64(i64_low(inlinedValue), i64_high(inlinedValue)); - } else { - assert(!i64_high(inlinedValue)); - functionArg = module.i32(i64_low(inlinedValue)); - } - } else { - functionArg = module.local_get(local.index, this.options.sizeTypeRef); - } - break; - } - this.error( - DiagnosticCode.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, - expression.range, local.type.toString() - ); - return module.unreachable(); - } - case ElementKind.Global: { - let global = target; - signature = global.type.signatureReference; - if (signature) { - functionArg = module.global_get(global.internalName, global.type.toRef()); - break; - } - this.error( - DiagnosticCode.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, - expression.range, global.type.toString() + // handle indirect call + let functionArg = this.compileExpression(expression.expression, Type.auto); + let signature = this.currentType.getSignature(); + if (signature) { + return this.compileCallIndirect( + signature, + functionArg, + expression.args, + expression, + 0, + contextualType == Type.void + ); + } + this.error( + DiagnosticCode.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, + expression.range, this.currentType.toString() + ); + if (target.kind == ElementKind.PropertyPrototype) { + let getterPrototype = (target).getterPrototype; + if (getterPrototype) { + this.infoRelated( + DiagnosticCode.This_expression_is_not_callable_because_it_is_a_get_accessor_Did_you_mean_to_use_it_without, + expression.range, getterPrototype.identifierNode.range ); - return module.unreachable(); - } - case ElementKind.PropertyPrototype: { - let propertyInstance = this.resolver.resolveProperty(target); - if (!propertyInstance) return module.unreachable(); - target = propertyInstance; - // fall-through - } - case ElementKind.Property: { - let propertyInstance = target; - let getterInstance = propertyInstance.getterInstance; - let type = assert(this.resolver.getTypeOfElement(target)); - - if (!getterInstance) { - this.error( - DiagnosticCode.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, - expression.range, type.toString() - ); - return module.unreachable(); - } - - let thisArg: ExpressionRef = 0; - if (propertyInstance.is(CommonFlags.Instance)) { - thisArg = this.compileExpression( - assert(thisExpression), - assert(getterInstance.signature.thisType), - Constraints.ConvImplicit | Constraints.IsThis - ); - } - functionArg = this.compileCallDirect(getterInstance, [], expression.expression, thisArg); - signature = this.currentType.signatureReference; - if (!signature) { - this.error( - DiagnosticCode.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, - expression.range, this.currentType.toString() - ); - return module.unreachable(); - } - break; - } - case ElementKind.Class: { - let classInstance = target; - let typeArguments = classInstance.getTypeArgumentsTo(this.program.functionPrototype); - if (typeArguments && typeArguments.length > 0) { - let ftype = typeArguments[0]; - signature = ftype.getSignature(); - functionArg = this.compileExpression(expression.expression, ftype, Constraints.ConvImplicit); - break; - } - // fall-through - } - - // not supported - default: { - let type = this.resolver.getTypeOfElement(target); - if (type) { - this.error( - DiagnosticCode.Type_0_has_no_call_signatures, - expression.range, type.toString() - ); - } else { - this.error( - DiagnosticCode.Expression_cannot_be_represented_by_a_type, - expression.range - ); - } - return module.unreachable(); } } - return this.compileCallIndirect( - assert(signature), // FIXME: bootstrap can't see this yet - functionArg, - expression.args, - expression, - 0, - contextualType == Type.void - ); + return module.unreachable(); } /** Compiles the given arguments like a call expression according to the specified context. */ diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index a93ceb4eeb..87edc3d34d 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -199,6 +199,7 @@ "File '{0}' not found.": 6054, "Numeric separators are not allowed here.": 6188, "Multiple consecutive numeric separators are not permitted.": 6189, + "This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'?": 6234, "'super' must be called before accessing 'this' in the constructor of a derived class.": 17009, "'super' must be called before accessing a property of 'super' in the constructor of a derived class.": 17011 } diff --git a/src/resolver.ts b/src/resolver.ts index 14578b718e..4396b2094a 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -2441,9 +2441,13 @@ export class Resolver extends DiagnosticEmitter { ) { return this.resolveExpression(node.args[0], ctxFlow, ctxType, reportMode); } - let instance = this.maybeInferCall(node, functionPrototype, ctxFlow, reportMode); - if (!instance) return null; - return instance.signature.returnType; + let functionInstance = this.maybeInferCall(node, functionPrototype, ctxFlow, reportMode); + if (!functionInstance) return null; + target = functionInstance; + // fall-through + } + case ElementKind.Function: { + return (target).signature.returnType; } case ElementKind.PropertyPrototype: { let propertyInstance = this.resolveProperty(target, reportMode); @@ -2451,25 +2455,18 @@ export class Resolver extends DiagnosticEmitter { target = propertyInstance; // fall-through } - case ElementKind.Global: - case ElementKind.Local: - case ElementKind.Property: { - let varType = (target).type; - let varElement = this.getElementOfType(varType); - if (!varElement || varElement.kind != ElementKind.Class) { - break; - } - target = varElement; + default: { + if (!isTypedElement(target.kind)) break; + let targetElement = this.getElementOfType((target).type); + if (!targetElement || targetElement.kind != ElementKind.Class) break; + target = targetElement; // fall-through } case ElementKind.Class: { let typeArguments = (target).getTypeArgumentsTo(this.program.functionPrototype); - if (typeArguments && typeArguments.length > 0) { - let ftype = typeArguments[0]; - let signatureReference = assert(ftype.signatureReference); - return signatureReference.returnType; - } - break; + if (!(typeArguments && typeArguments.length)) break; + let signature = assert(typeArguments[0].getSignature()); + return signature.returnType; } } if (reportMode == ReportMode.Report) { diff --git a/tests/compiler/assert-nonnull.debug.wat b/tests/compiler/assert-nonnull.debug.wat index 2f8dc9a77b..d09f7d1f41 100644 --- a/tests/compiler/assert-nonnull.debug.wat +++ b/tests/compiler/assert-nonnull.debug.wat @@ -69,9 +69,21 @@ i32.load $0 offset=4 ) (func $assert-nonnull/testFn (type $i32_=>_i32) (param $fn i32) (result i32) + (local $1 i32) i32.const 0 global.set $~argumentsLength local.get $fn + local.tee $1 + if (result i32) + local.get $1 + else + i32.const 32 + i32.const 96 + i32.const 35 + i32.const 10 + call $~lib/builtins/abort + unreachable + end i32.load $0 call_indirect $0 (type $none_=>_i32) ) @@ -79,14 +91,6 @@ local.get $this i32.load $0 offset=4 ) - (func $assert-nonnull/testObjFn (type $i32_=>_i32) (param $foo i32) (result i32) - i32.const 0 - global.set $~argumentsLength - local.get $foo - call $assert-nonnull/Foo#get:baz - i32.load $0 - call_indirect $0 (type $none_=>_i32) - ) (func $~stack_check (type $none_=>_none) global.get $~lib/memory/__stack_pointer global.get $~lib/memory/__data_end @@ -538,6 +542,7 @@ (func $assert-nonnull/testRet (type $i32_=>_i32) (param $fn i32) (result i32) (local $1 i32) (local $2 i32) + (local $3 i32) global.get $~lib/memory/__stack_pointer i32.const 4 i32.sub @@ -550,8 +555,55 @@ i32.const 0 global.set $~argumentsLength local.get $fn + local.tee $1 + if (result i32) + local.get $1 + else + i32.const 32 + i32.const 96 + i32.const 44 + i32.const 10 + call $~lib/builtins/abort + unreachable + end i32.load $0 call_indirect $0 (type $none_=>_i32) + local.tee $2 + i32.store $0 + local.get $2 + if (result i32) + local.get $2 + else + i32.const 32 + i32.const 96 + i32.const 44 + i32.const 10 + call $~lib/builtins/abort + unreachable + end + local.set $3 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $3 + ) + (func $assert-nonnull/testObjFn (type $i32_=>_i32) (param $foo i32) (result i32) + (local $1 i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store $0 + i32.const 0 + global.set $~argumentsLength + global.get $~lib/memory/__stack_pointer + local.get $foo + call $assert-nonnull/Foo#get:baz local.tee $1 i32.store $0 local.get $1 @@ -560,11 +612,13 @@ else i32.const 32 i32.const 96 - i32.const 44 + i32.const 48 i32.const 10 call $~lib/builtins/abort unreachable end + i32.load $0 + call_indirect $0 (type $none_=>_i32) local.set $2 global.get $~lib/memory/__stack_pointer i32.const 4 @@ -575,21 +629,21 @@ (func $assert-nonnull/testObjRet (type $i32_=>_i32) (param $foo i32) (result i32) (local $1 i32) (local $2 i32) + (local $3 i32) global.get $~lib/memory/__stack_pointer - i32.const 4 + i32.const 8 i32.sub global.set $~lib/memory/__stack_pointer call $~stack_check global.get $~lib/memory/__stack_pointer - i32.const 0 - i32.store $0 + i64.const 0 + i64.store $0 global.get $~lib/memory/__stack_pointer i32.const 0 global.set $~argumentsLength + global.get $~lib/memory/__stack_pointer local.get $foo call $assert-nonnull/Foo#get:baz - i32.load $0 - call_indirect $0 (type $none_=>_i32) local.tee $1 i32.store $0 local.get $1 @@ -603,12 +657,27 @@ call $~lib/builtins/abort unreachable end - local.set $2 + i32.load $0 + call_indirect $0 (type $none_=>_i32) + local.tee $2 + i32.store $0 offset=4 + local.get $2 + if (result i32) + local.get $2 + else + i32.const 32 + i32.const 96 + i32.const 52 + i32.const 10 + call $~lib/builtins/abort + unreachable + end + local.set $3 global.get $~lib/memory/__stack_pointer - i32.const 4 + i32.const 8 i32.add global.set $~lib/memory/__stack_pointer - local.get $2 + local.get $3 ) (func $export:assert-nonnull/testVar (type $i32_=>_i32) (param $0 i32) (result i32) (local $1 i32) diff --git a/tests/compiler/assert-nonnull.release.wat b/tests/compiler/assert-nonnull.release.wat index 0615c5a72b..86cf8d7170 100644 --- a/tests/compiler/assert-nonnull.release.wat +++ b/tests/compiler/assert-nonnull.release.wat @@ -571,6 +571,16 @@ local.get $0 i32.store $0 local.get $0 + i32.eqz + if + i32.const 1056 + i32.const 1120 + i32.const 35 + i32.const 10 + call $~lib/builtins/abort + unreachable + end + local.get $0 i32.load $0 call_indirect $0 (type $none_=>_i32) drop @@ -635,48 +645,36 @@ i32.const 4 i32.sub global.set $~lib/memory/__stack_pointer - block $folding-inner0 - global.get $~lib/memory/__stack_pointer - i32.const 1404 - i32.lt_s - br_if $folding-inner0 - global.get $~lib/memory/__stack_pointer - local.tee $1 - local.get $0 - i32.store $0 - local.get $1 - i32.const 4 - i32.sub - global.set $~lib/memory/__stack_pointer - global.get $~lib/memory/__stack_pointer - i32.const 1404 - i32.lt_s - br_if $folding-inner0 - global.get $~lib/memory/__stack_pointer - i32.const 0 - i32.store $0 - local.get $0 - i32.load $0 - call_indirect $0 (type $none_=>_i32) - drop - unreachable - end - i32.const 34192 - i32.const 34240 - i32.const 1 - i32.const 1 - call $~lib/builtins/abort - unreachable - ) - (func $export:assert-nonnull/testObjFn (type $i32_=>_i32) (param $0 i32) (result i32) - global.get $~lib/memory/__stack_pointer - i32.const 4 - i32.sub - global.set $~lib/memory/__stack_pointer - global.get $~lib/memory/__stack_pointer - i32.const 1404 - i32.lt_s - if + block $folding-inner1 + block $folding-inner0 + global.get $~lib/memory/__stack_pointer + i32.const 1404 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + local.tee $1 + local.get $0 + i32.store $0 + local.get $1 + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1404 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store $0 + local.get $0 + i32.eqz + br_if $folding-inner1 + local.get $0 + i32.load $0 + call_indirect $0 (type $none_=>_i32) + drop + unreachable + end i32.const 34192 i32.const 34240 i32.const 1 @@ -684,17 +682,14 @@ call $~lib/builtins/abort unreachable end - global.get $~lib/memory/__stack_pointer - local.get $0 - i32.store $0 - local.get $0 - i32.load $0 offset=4 - i32.load $0 - call_indirect $0 (type $none_=>_i32) - drop + i32.const 1056 + i32.const 1120 + i32.const 44 + i32.const 10 + call $~lib/builtins/abort unreachable ) - (func $export:assert-nonnull/testObjRet (type $i32_=>_i32) (param $0 i32) (result i32) + (func $export:assert-nonnull/testObjFn (type $i32_=>_i32) (param $0 i32) (result i32) (local $1 i32) global.get $~lib/memory/__stack_pointer i32.const 4 @@ -718,10 +713,25 @@ i32.lt_s br_if $folding-inner0 global.get $~lib/memory/__stack_pointer + local.tee $1 i32.const 0 i32.store $0 + local.get $1 local.get $0 i32.load $0 offset=4 + local.tee $0 + i32.store $0 + local.get $0 + i32.eqz + if + i32.const 1056 + i32.const 1120 + i32.const 48 + i32.const 10 + call $~lib/builtins/abort + unreachable + end + local.get $0 i32.load $0 call_indirect $0 (type $none_=>_i32) drop @@ -734,4 +744,60 @@ call $~lib/builtins/abort unreachable ) + (func $export:assert-nonnull/testObjRet (type $i32_=>_i32) (param $0 i32) (result i32) + (local $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + block $folding-inner1 + block $folding-inner0 + global.get $~lib/memory/__stack_pointer + i32.const 1404 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + local.tee $1 + local.get $0 + i32.store $0 + local.get $1 + i32.const 8 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1404 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + local.tee $1 + i64.const 0 + i64.store $0 + local.get $1 + local.get $0 + i32.load $0 offset=4 + local.tee $0 + i32.store $0 + local.get $0 + i32.eqz + br_if $folding-inner1 + local.get $0 + i32.load $0 + call_indirect $0 (type $none_=>_i32) + drop + unreachable + end + i32.const 34192 + i32.const 34240 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 1056 + i32.const 1120 + i32.const 52 + i32.const 10 + call $~lib/builtins/abort + unreachable + ) ) diff --git a/tests/compiler/std/array-access.debug.wat b/tests/compiler/std/array-access.debug.wat index c564b8b000..4e2912860a 100644 --- a/tests/compiler/std/array-access.debug.wat +++ b/tests/compiler/std/array-access.debug.wat @@ -10,6 +10,7 @@ (global $~lib/shared/runtime/Runtime.Minimal i32 (i32.const 1)) (global $~lib/shared/runtime/Runtime.Incremental i32 (i32.const 2)) (global $~lib/native/ASC_SHRINK_LEVEL i32 (i32.const 0)) + (global $~argumentsLength (mut i32) (i32.const 0)) (global $~lib/memory/__data_end i32 (i32.const 284)) (global $~lib/memory/__stack_pointer (mut i32) (i32.const 33052)) (global $~lib/memory/__heap_base i32 (i32.const 33052)) @@ -26,6 +27,7 @@ (export "stringArrayMethodCall" (func $export:std/array-access/stringArrayMethodCall)) (export "stringArrayArrayPropertyAccess" (func $export:std/array-access/stringArrayArrayPropertyAccess)) (export "stringArrayArrayMethodCall" (func $export:std/array-access/stringArrayArrayMethodCall)) + (export "functionArrayElementCall" (func $export:std/array-access/functionArrayElementCall)) (func $~lib/array/Array<~lib/array/Array>#get:length_ (type $i32_=>_i32) (param $this i32) (result i32) local.get $this i32.load $0 offset=12 @@ -249,6 +251,24 @@ local.get $this i32.load $0 offset=4 ) + (func $~lib/array/Array<%28i32%29=>i32>#get:length_ (type $i32_=>_i32) (param $this i32) (result i32) + local.get $this + i32.load $0 offset=12 + ) + (func $~lib/array/Array<%28i32%29=>i32>#get:dataStart (type $i32_=>_i32) (param $this i32) (result i32) + local.get $this + i32.load $0 offset=4 + ) + (func $std/array-access/functionArrayElementCall (type $i32_=>_i32) (param $a i32) (result i32) + i32.const 123 + i32.const 1 + global.set $~argumentsLength + local.get $a + i32.const 0 + call $~lib/array/Array<%28i32%29=>i32>#__get + i32.load $0 + call_indirect $0 (type $i32_=>_i32) + ) (func $~stack_check (type $none_=>_none) global.get $~lib/memory/__stack_pointer global.get $~lib/memory/__data_end @@ -592,6 +612,62 @@ global.set $~lib/memory/__stack_pointer local.get $3 ) + (func $~lib/array/Array<%28i32%29=>i32>#__get (type $i32_i32_=>_i32) (param $this i32) (param $index i32) (result i32) + (local $value i32) + (local $3 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store $0 + local.get $index + local.get $this + call $~lib/array/Array<%28i32%29=>i32>#get:length_ + i32.ge_u + if + i32.const 32 + i32.const 96 + i32.const 114 + i32.const 42 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.get $this + call $~lib/array/Array<%28i32%29=>i32>#get:dataStart + local.get $index + i32.const 2 + i32.shl + i32.add + i32.load $0 + local.tee $value + i32.store $0 + i32.const 1 + drop + i32.const 0 + i32.eqz + drop + local.get $value + i32.eqz + if + i32.const 144 + i32.const 96 + i32.const 118 + i32.const 40 + call $~lib/builtins/abort + unreachable + end + local.get $value + local.set $3 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $3 + ) (func $export:std/array-access/i32ArrayArrayElementAccess (type $i32_=>_i32) (param $0 i32) (result i32) (local $1 i32) global.get $~lib/memory/__stack_pointer @@ -687,4 +763,23 @@ global.set $~lib/memory/__stack_pointer local.get $1 ) + (func $export:std/array-access/functionArrayElementCall (type $i32_=>_i32) (param $0 i32) (result i32) + (local $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store $0 + local.get $0 + call $std/array-access/functionArrayElementCall + local.set $1 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $1 + ) ) diff --git a/tests/compiler/std/array-access.release.wat b/tests/compiler/std/array-access.release.wat index 864a44ce47..b13d3e74ac 100644 --- a/tests/compiler/std/array-access.release.wat +++ b/tests/compiler/std/array-access.release.wat @@ -13,12 +13,14 @@ (data (i32.const 1160) "\01\00\00\00^\00\00\00E\00l\00e\00m\00e\00n\00t\00 \00t\00y\00p\00e\00 \00m\00u\00s\00t\00 \00b\00e\00 \00n\00u\00l\00l\00a\00b\00l\00e\00 \00i\00f\00 \00a\00r\00r\00a\00y\00 \00i\00s\00 \00h\00o\00l\00e\00y") (data (i32.const 1276) "\1c") (data (i32.const 1288) "\01") + (table $0 1 1 funcref) (export "memory" (memory $0)) (export "i32ArrayArrayElementAccess" (func $export:std/array-access/i32ArrayArrayElementAccess)) (export "stringArrayPropertyAccess" (func $export:std/array-access/stringArrayPropertyAccess)) (export "stringArrayMethodCall" (func $export:std/array-access/stringArrayMethodCall)) (export "stringArrayArrayPropertyAccess" (func $export:std/array-access/stringArrayArrayPropertyAccess)) (export "stringArrayArrayMethodCall" (func $export:std/array-access/stringArrayArrayMethodCall)) + (export "functionArrayElementCall" (func $export:std/array-access/functionArrayElementCall)) (func $~lib/string/String#startsWith (type $i32_=>_i32) (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -489,4 +491,32 @@ call $~lib/builtins/abort unreachable ) + (func $export:std/array-access/functionArrayElementCall (type $i32_=>_i32) (param $0 i32) (result i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1308 + i32.lt_s + if + i32.const 34096 + i32.const 34144 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store $0 + i32.const 123 + local.get $0 + i32.const 0 + call $~lib/array/Array<~lib/array/Array>#__get + i32.load $0 + call_indirect $0 (type $i32_=>_i32) + drop + unreachable + ) ) diff --git a/tests/compiler/std/array-access.ts b/tests/compiler/std/array-access.ts index 944edf6740..26729d4ffc 100644 --- a/tests/compiler/std/array-access.ts +++ b/tests/compiler/std/array-access.ts @@ -17,3 +17,9 @@ export function stringArrayArrayPropertyAccess(a: string[][]): i32 { export function stringArrayArrayMethodCall(a: string[][]): i32 { return a[0][1].startsWith(""); } + +// FIXME: Parenthesizing signature types is not supported +type T = (x: i32) => i32 +export function functionArrayElementCall(a: T[]): i32 { + return a[0](123); +}