diff --git a/src/resolver.ts b/src/resolver.ts index 46d5d16570..1af41ba392 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -732,7 +732,12 @@ export class Resolver extends DiagnosticEmitter { // infer types with generic components while updating contextual types for (let i = 0; i < numParameters; ++i) { let argumentExpression = i < numArguments ? argumentNodes[i] : parameterNodes[i].initializer; - if (!argumentExpression) { // missing initializer -> too few arguments + if (!argumentExpression) { + // optional but not have initializer should be handled in the other place + if (parameterNodes[i].parameterKind == ParameterKind.OPTIONAL) { + continue; + } + // missing initializer -> too few arguments if (reportMode == ReportMode.REPORT) { this.error( DiagnosticCode.Expected_0_arguments_but_got_1, diff --git a/tests/compiler/infer-generic.debug.wat b/tests/compiler/infer-generic.debug.wat index 38de0bf265..1a6006328e 100644 --- a/tests/compiler/infer-generic.debug.wat +++ b/tests/compiler/infer-generic.debug.wat @@ -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 "inferAssert" (func $export:infer-generic/inferAssert)) (start $~start) (func $infer-generic/inferCompatible (param $0 f64) (param $1 f64) (result i32) local.get $0 @@ -2233,6 +2234,24 @@ local.get $0 call $infer-generic/inferEncapsulatedFunctionMixed ) + (func $infer-generic/inferAssert (param $0 i32) + (local $1 i32) + local.get $0 + local.tee $1 + i32.eqz + if (result i32) + i32.const 0 + i32.const 32 + i32.const 67 + i32.const 3 + call $~lib/builtins/abort + unreachable + else + local.get $1 + end + i32.load + drop + ) (func $~lib/rt/__visit_globals (param $0 i32) (local $1 i32) global.get $infer-generic/arr @@ -2421,7 +2440,7 @@ if i32.const 0 i32.const 32 - i32.const 60 + i32.const 62 i32.const 1 call $~lib/builtins/abort unreachable @@ -2464,7 +2483,7 @@ if i32.const 0 i32.const 32 - i32.const 61 + i32.const 63 i32.const 1 call $~lib/builtins/abort unreachable @@ -2562,4 +2581,20 @@ 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 + 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/inferAssert + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + ) ) diff --git a/tests/compiler/infer-generic.release.wat b/tests/compiler/infer-generic.release.wat index 6279d2b748..b1e303a597 100644 --- a/tests/compiler/infer-generic.release.wat +++ b/tests/compiler/infer-generic.release.wat @@ -1,10 +1,10 @@ (module (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) (type $i32_f32_i32_i32_=>_i32 (func (param i32 f32 i32 i32) (result i32))) (type $i32_i32_=>_none (func (param i32 i32))) (type $none_=>_i32 (func (result i32))) (type $i32_=>_i32 (func (param i32) (result i32))) - (type $i32_=>_none (func (param i32))) (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $f32_=>_f32 (func (param f32) (result f32))) @@ -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 "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) local.get $1 @@ -1458,6 +1459,43 @@ global.set $~lib/memory/__stack_pointer local.get $0 ) + (func $export:infer-generic/inferAssert (param $0 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 1684 + i32.lt_s + if + i32.const 18096 + i32.const 18144 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 1056 + i32.const 67 + i32.const 3 + call $~lib/builtins/abort + unreachable + end + local.get $0 + i32.load + drop + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + ) (func $byn-split-outlined-A$~lib/rt/itcms/__visit (param $0 i32) (local $1 i32) (local $2 i32) diff --git a/tests/compiler/infer-generic.ts b/tests/compiler/infer-generic.ts index 9df90f9147..d61fac1463 100644 --- a/tests/compiler/infer-generic.ts +++ b/tests/compiler/infer-generic.ts @@ -20,7 +20,7 @@ export function test2(arr: f32[]): f32[] { // (a: T) => R should infer T,R -function inferEncapsulatedFunction(fn: (a: T) => R): (a: T) => R { +function inferEncapsulatedFunction(fn: (a: T) => R): (a: T) => R { return fn; } @@ -30,7 +30,7 @@ export function test3(fn: (a: f32) => f64): (a: f32) => f64 { // (a: T, b: i32) => R should not bail out on non-inferred i32 -function inferEncapsulatedFunctionMixed(fn: (a: T, b: i32) => R): (a: T, b: i32) => R { +function inferEncapsulatedFunctionMixed(fn: (a: T, b: i32) => R): (a: T, b: i32) => R { return fn; } @@ -53,9 +53,16 @@ arr.reduce(((acc, cur) => acc && cur != 0), false); // should fall back to default type -class Ref { x: i32; } +class Ref { + x: i32; +} function inferDefault(a: T): T { return a; } assert(inferDefault(1) == 1); assert(inferDefault({ x: 2 }) instanceof Ref); + +// infer builtin assert generic +export function inferAssert(v: Ref | null): void { + assert(v).x; +}