diff --git a/src/resolver.ts b/src/resolver.ts index 07d8758a53..6da2495006 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -836,20 +836,21 @@ export class Resolver extends DiagnosticEmitter { } else if (node.kind == NodeKind.FUNCTIONTYPE) { // foo(bar: (baz: T) => i32)) let functionTypeNode = node; let parameterNodes = functionTypeNode.parameters; - if (parameterNodes && parameterNodes.length > 0) { - let signatureReference = type.signatureReference; - if (signatureReference) { - let parameterTypes = signatureReference.parameterTypes; - let thisType = signatureReference.thisType; - if (parameterTypes.length == parameterNodes.length && !thisType == !functionTypeNode.explicitThisType) { - for (let i = 0, k = parameterTypes.length; i < k; ++i) { - this.propagateInferredGenericTypes(parameterNodes[i].type, parameterTypes[i], ctxElement, ctxTypes, typeParameterNames); - } - this.propagateInferredGenericTypes(functionTypeNode.returnType, signatureReference.returnType, ctxElement, ctxTypes, typeParameterNames); - if (thisType) this.propagateInferredGenericTypes(functionTypeNode.explicitThisType!, thisType, ctxElement, ctxTypes, typeParameterNames); - return; - } + let signatureReference = type.signatureReference; + if (signatureReference) { + let parameterTypes = signatureReference.parameterTypes; + for (let i = 0, k = min(parameterTypes.length, parameterNodes.length) ; i < k; ++i) { + this.propagateInferredGenericTypes(parameterNodes[i].type, parameterTypes[i], ctxElement, ctxTypes, typeParameterNames); + } + if (signatureReference.returnType != Type.void) { + this.propagateInferredGenericTypes(functionTypeNode.returnType, signatureReference.returnType, ctxElement, ctxTypes, typeParameterNames); + } + let thisType = signatureReference.thisType; + let explicitThisType = functionTypeNode.explicitThisType; + if (thisType && explicitThisType) { + this.propagateInferredGenericTypes(explicitThisType, thisType, ctxElement, ctxTypes, typeParameterNames); } + return; } } } diff --git a/tests/compiler/infer-generic.debug.wat b/tests/compiler/infer-generic.debug.wat index 831cbdc183..fd9d96bd59 100644 --- a/tests/compiler/infer-generic.debug.wat +++ b/tests/compiler/infer-generic.debug.wat @@ -29,9 +29,9 @@ (global $~lib/rt/tlsf/ROOT (mut i32) (i32.const 0)) (global $~lib/native/ASC_LOW_MEMORY_LIMIT i32 (i32.const 0)) (global $~lib/rt/__rtti_base i32 (i32.const 592)) - (global $~lib/memory/__data_end i32 (i32.const 660)) - (global $~lib/memory/__stack_pointer (mut i32) (i32.const 17044)) - (global $~lib/memory/__heap_base i32 (i32.const 17044)) + (global $~lib/memory/__data_end i32 (i32.const 668)) + (global $~lib/memory/__stack_pointer (mut i32) (i32.const 17052)) + (global $~lib/memory/__heap_base i32 (i32.const 17052)) (memory $0 1) (data (i32.const 12) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00 \00\00\00i\00n\00f\00e\00r\00-\00g\00e\00n\00e\00r\00i\00c\00.\00t\00s\00\00\00\00\00\00\00\00\00\00\00\00\00") (data (i32.const 76) "\1c\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0c\00\00\00\00\00\80?\00\00\00@\00\00@@") @@ -45,7 +45,7 @@ (data (i32.const 444) ",\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\14\00\00\00~\00l\00i\00b\00/\00r\00t\00.\00t\00s\00\00\00\00\00\00\00\00\00") (data (i32.const 496) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") (data (i32.const 524) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\1e\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00t\00l\00s\00f\00.\00t\00s\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") - (data (i32.const 592) "\08\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\02\19\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") + (data (i32.const 592) "\t\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\02\19\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") (table $0 2 2 funcref) (elem $0 (i32.const 1) $start:infer-generic~anonymous|0) (export "test1" (func $infer-generic/test1)) @@ -53,6 +53,7 @@ (export "test2" (func $export:infer-generic/test2)) (export "test3" (func $export:infer-generic/test3)) (export "test4" (func $export:infer-generic/test4)) + (export "test5" (func $export:infer-generic/test5)) (export "inferAssert" (func $export:infer-generic/inferAssert)) (start $~start) (func $infer-generic/inferCompatible (param $a f64) (param $b f64) (result i32) @@ -2220,17 +2221,24 @@ local.get $arr call $infer-generic/inferEncapsulatedClass ) - (func $infer-generic/inferEncapsulatedFunction (param $fn i32) (result i32) + (func $infer-generic/inferEncapsulatedFunctionNull (param $fn i32) (result i32) local.get $fn ) (func $infer-generic/test3 (param $fn i32) (result i32) + local.get $fn + call $infer-generic/inferEncapsulatedFunctionNull + ) + (func $infer-generic/inferEncapsulatedFunction (param $fn i32) (result i32) + local.get $fn + ) + (func $infer-generic/test4 (param $fn i32) (result i32) local.get $fn call $infer-generic/inferEncapsulatedFunction ) (func $infer-generic/inferEncapsulatedFunctionMixed (param $fn i32) (result i32) local.get $fn ) - (func $infer-generic/test4 (param $fn i32) (result i32) + (func $infer-generic/test5 (param $fn i32) (result i32) local.get $fn call $infer-generic/inferEncapsulatedFunctionMixed ) @@ -2242,7 +2250,7 @@ if (result i32) i32.const 0 i32.const 32 - i32.const 67 + i32.const 75 i32.const 3 call $~lib/builtins/abort unreachable @@ -2303,6 +2311,17 @@ local.get $1 call $~lib/function/Function<%28bool%2Cf32%2Ci32%2C~lib/array/Array%29=>bool>#__visit ) + (func $~lib/function/Function<%28%29=>f64>#__visit (param $this i32) (param $cookie i32) + local.get $this + i32.load offset=4 + local.get $cookie + call $~lib/rt/itcms/__visit + ) + (func $~lib/function/Function<%28%29=>f64>~visit (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + call $~lib/function/Function<%28%29=>f64>#__visit + ) (func $~lib/function/Function<%28f32%29=>f64>#__visit (param $this i32) (param $cookie i32) local.get $this i32.load offset=4 @@ -2329,37 +2348,43 @@ block $invalid block $~lib/function/Function<%28f32%2Ci32%29=>f64> block $~lib/function/Function<%28f32%29=>f64> - block $infer-generic/Ref - block $~lib/function/Function<%28bool%2Cf32%2Ci32%2C~lib/array/Array%29=>bool> - block $~lib/array/Array - block $~lib/arraybuffer/ArrayBufferView - block $~lib/string/String - block $~lib/arraybuffer/ArrayBuffer - local.get $0 - i32.const 8 - i32.sub - i32.load - br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $~lib/array/Array $~lib/function/Function<%28bool%2Cf32%2Ci32%2C~lib/array/Array%29=>bool> $infer-generic/Ref $~lib/function/Function<%28f32%29=>f64> $~lib/function/Function<%28f32%2Ci32%29=>f64> $invalid + block $~lib/function/Function<%28%29=>f64> + block $infer-generic/Ref + block $~lib/function/Function<%28bool%2Cf32%2Ci32%2C~lib/array/Array%29=>bool> + block $~lib/array/Array + block $~lib/arraybuffer/ArrayBufferView + block $~lib/string/String + block $~lib/arraybuffer/ArrayBuffer + local.get $0 + i32.const 8 + i32.sub + i32.load + br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $~lib/array/Array $~lib/function/Function<%28bool%2Cf32%2Ci32%2C~lib/array/Array%29=>bool> $infer-generic/Ref $~lib/function/Function<%28%29=>f64> $~lib/function/Function<%28f32%29=>f64> $~lib/function/Function<%28f32%2Ci32%29=>f64> $invalid + end + return end return end + local.get $0 + local.get $1 + call $~lib/arraybuffer/ArrayBufferView~visit return end local.get $0 local.get $1 - call $~lib/arraybuffer/ArrayBufferView~visit + call $~lib/array/Array~visit return end local.get $0 local.get $1 - call $~lib/array/Array~visit + call $~lib/function/Function<%28bool%2Cf32%2Ci32%2C~lib/array/Array%29=>bool>~visit return end - local.get $0 - local.get $1 - call $~lib/function/Function<%28bool%2Cf32%2Ci32%2C~lib/array/Array%29=>bool>~visit return end + local.get $0 + local.get $1 + call $~lib/function/Function<%28%29=>f64>~visit return end local.get $0 @@ -2412,7 +2437,7 @@ if i32.const 0 i32.const 32 - i32.const 46 + i32.const 54 i32.const 1 call $~lib/builtins/abort unreachable @@ -2440,7 +2465,7 @@ if i32.const 0 i32.const 32 - i32.const 62 + i32.const 70 i32.const 1 call $~lib/builtins/abort unreachable @@ -2483,7 +2508,7 @@ if i32.const 0 i32.const 32 - i32.const 63 + i32.const 71 i32.const 1 call $~lib/builtins/abort unreachable @@ -2581,6 +2606,25 @@ global.set $~lib/memory/__stack_pointer local.get $1 ) + (func $export:infer-generic/test5 (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 + local.get $0 + call $infer-generic/test5 + local.set $1 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $1 + ) (func $export:infer-generic/inferAssert (param $0 i32) global.get $~lib/memory/__stack_pointer i32.const 4 diff --git a/tests/compiler/infer-generic.release.wat b/tests/compiler/infer-generic.release.wat index 36339efcc2..cd77aa33a3 100644 --- a/tests/compiler/infer-generic.release.wat +++ b/tests/compiler/infer-generic.release.wat @@ -19,7 +19,7 @@ (global $~lib/rt/itcms/white (mut i32) (i32.const 0)) (global $~lib/rt/itcms/fromSpace (mut i32) (i32.const 0)) (global $~lib/rt/tlsf/ROOT (mut i32) (i32.const 0)) - (global $~lib/memory/__stack_pointer (mut i32) (i32.const 18068)) + (global $~lib/memory/__stack_pointer (mut i32) (i32.const 18076)) (memory $0 1) (data (i32.const 1036) "<") (data (i32.const 1048) "\01\00\00\00 \00\00\00i\00n\00f\00e\00r\00-\00g\00e\00n\00e\00r\00i\00c\00.\00t\00s") @@ -39,7 +39,7 @@ (data (i32.const 1480) "\01\00\00\00\14\00\00\00~\00l\00i\00b\00/\00r\00t\00.\00t\00s") (data (i32.const 1548) "<") (data (i32.const 1560) "\01\00\00\00\1e\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00t\00l\00s\00f\00.\00t\00s") - (data (i32.const 1616) "\08\00\00\00 \00\00\00\00\00\00\00 ") + (data (i32.const 1616) "\t\00\00\00 \00\00\00\00\00\00\00 ") (data (i32.const 1644) "\02\19") (data (i32.const 1660) " ") (table $0 2 2 funcref) @@ -49,6 +49,7 @@ (export "test2" (func $export:infer-generic/test2)) (export "test3" (func $export:infer-generic/test2)) (export "test4" (func $export:infer-generic/test2)) + (export "test5" (func $export:infer-generic/test2)) (export "inferAssert" (func $export:infer-generic/inferAssert)) (start $~start) (func $start:infer-generic~anonymous|0 (param $0 i32) (param $1 f32) (param $2 i32) (param $3 i32) (result i32) @@ -778,7 +779,7 @@ local.set $0 loop $while-continue|0 local.get $0 - i32.const 18068 + i32.const 18076 i32.lt_u if local.get $0 @@ -878,7 +879,7 @@ unreachable end local.get $0 - i32.const 18068 + i32.const 18076 i32.lt_u if local.get $0 @@ -901,7 +902,7 @@ i32.const 4 i32.add local.tee $0 - i32.const 18068 + i32.const 18076 i32.ge_u if global.get $~lib/rt/tlsf/ROOT @@ -1266,7 +1267,7 @@ i32.const 8 i32.sub i32.load - br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $folding-inner1 $folding-inner1 $folding-inner0 $infer-generic/Ref $folding-inner0 $folding-inner0 $invalid + br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $folding-inner1 $folding-inner1 $folding-inner0 $infer-generic/Ref $folding-inner0 $folding-inner0 $folding-inner0 $invalid end return end @@ -1304,7 +1305,7 @@ global.set $~lib/memory/__stack_pointer block $folding-inner0 global.get $~lib/memory/__stack_pointer - i32.const 1684 + i32.const 1692 i32.lt_s br_if $folding-inner0 global.get $~lib/memory/__stack_pointer @@ -1359,7 +1360,7 @@ memory.size i32.const 16 i32.shl - i32.const 18068 + i32.const 18076 i32.sub i32.const 1 i32.shr_u @@ -1394,7 +1395,7 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 1684 + i32.const 1692 i32.lt_s br_if $folding-inner0 global.get $~lib/memory/__stack_pointer @@ -1441,7 +1442,7 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 1684 + i32.const 1692 i32.lt_s if i32.const 18096 @@ -1467,7 +1468,7 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 1684 + i32.const 1692 i32.lt_s if i32.const 18096 @@ -1485,7 +1486,7 @@ if i32.const 0 i32.const 1056 - i32.const 67 + i32.const 75 i32.const 3 call $~lib/builtins/abort unreachable @@ -1541,7 +1542,7 @@ if i32.const 0 local.get $1 - i32.const 18068 + i32.const 18076 i32.lt_u local.get $1 i32.load offset=8 diff --git a/tests/compiler/infer-generic.ts b/tests/compiler/infer-generic.ts index d61fac1463..6270d04739 100644 --- a/tests/compiler/infer-generic.ts +++ b/tests/compiler/infer-generic.ts @@ -18,13 +18,21 @@ export function test2(arr: f32[]): f32[] { return inferEncapsulatedClass(arr); } +// () => R should infer R +function inferEncapsulatedFunctionNull(fn: () => R): () => R { + return fn; +} +export function test3(fn: () => f64): () => f64 { + return inferEncapsulatedFunctionNull(fn); +} + // (a: T) => R should infer T,R function inferEncapsulatedFunction(fn: (a: T) => R): (a: T) => R { return fn; } -export function test3(fn: (a: f32) => f64): (a: f32) => f64 { +export function test4(fn: (a: f32) => f64): (a: f32) => f64 { return inferEncapsulatedFunction(fn); } @@ -34,7 +42,7 @@ function inferEncapsulatedFunctionMixed(fn: (a: T, b: i32) => R): (a: T, b return fn; } -export function test4(fn: (a: f32, b: i32) => f64): (a: f32, b: i32) => f64 { +export function test5(fn: (a: f32, b: i32) => f64): (a: f32, b: i32) => f64 { return inferEncapsulatedFunctionMixed(fn); }