diff --git a/src/compiler.ts b/src/compiler.ts index 0dd2b2b024..05ff1353d7 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -7107,12 +7107,20 @@ export class Compiler extends DiagnosticEmitter { switch (expression.kind) { case NodeKind.NULL: { let options = this.options; - let classReference = contextualType.classReference; - if (contextualType.is(TypeFlags.REFERENCE) && classReference !== null) { - this.currentType = classReference.type.asNullable(); - } else { - this.currentType = options.usizeType; // TODO: anyref context yields 0 + if (contextualType.is(TypeFlags.REFERENCE)) { + let classReference = contextualType.classReference; + if (classReference) { + this.currentType = classReference.type.asNullable(); + return options.isWasm64 ? module.i64(0) : module.i32(0); + } + let signatureReference = contextualType.signatureReference; + if (signatureReference) { + this.currentType = signatureReference.type.asNullable(); + return module.i32(0); + } + // TODO: anyref context yields 0 } + this.currentType = options.usizeType; return options.isWasm64 ? module.i64(0) : module.i32(0); diff --git a/tests/compiler/function-expression.optimized.wat b/tests/compiler/function-expression.optimized.wat index cb10b08592..fdeb8b08d0 100644 --- a/tests/compiler/function-expression.optimized.wat +++ b/tests/compiler/function-expression.optimized.wat @@ -7,8 +7,8 @@ (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) (memory $0 1) (data (i32.const 8) ",\00\00\00\01\00\00\00\01\00\00\00,\00\00\00f\00u\00n\00c\00t\00i\00o\00n\00-\00e\00x\00p\00r\00e\00s\00s\00i\00o\00n\00.\00t\00s") - (table $0 11 funcref) - (elem (i32.const 0) $start:function-expression~someName $start:function-expression~anonymous|0 $start:function-expression~anonymous|0 $start:function-expression~someName $start:function-expression~anonymous|2 $start:function-expression~anonymous|3 $start:function-expression~anonymous|4 $start:function-expression~anonymous|5 $start:function-expression~anonymous|3 $start:function-expression~anonymous|4 $start:function-expression~anonymous|5) + (table $0 12 funcref) + (elem (i32.const 0) $start:function-expression~someName $start:function-expression~anonymous|0 $start:function-expression~anonymous|0 $start:function-expression~someName $start:function-expression~anonymous|2 $start:function-expression~anonymous|3 $start:function-expression~anonymous|4 $start:function-expression~anonymous|5 $start:function-expression~anonymous|3 $start:function-expression~anonymous|4 $start:function-expression~anonymous|5 $start:function-expression~anonymous|2) (global $~lib/argc (mut i32) (i32.const 0)) (export "memory" (memory $0)) (start $start) diff --git a/tests/compiler/function-expression.ts b/tests/compiler/function-expression.ts index 0c27868b64..294eaee7bf 100644 --- a/tests/compiler/function-expression.ts +++ b/tests/compiler/function-expression.ts @@ -34,3 +34,12 @@ function testOmittedReturn3(): (a: i32, b: i32) => i32 { assert(testOmittedReturn1()(1, 2) == 3); assert(testOmittedReturn2()(1, 2) == 1); assert(testOmittedReturn3()(1, 2) == 42); + +function testNullable(b: boolean): (() => i32) | null { + if (b) { + return (): i32 => 1; + } else { + return null; + } +} +assert(testNullable(false) == null); diff --git a/tests/compiler/function-expression.untouched.wat b/tests/compiler/function-expression.untouched.wat index 77547bfbc6..a33e1cb206 100644 --- a/tests/compiler/function-expression.untouched.wat +++ b/tests/compiler/function-expression.untouched.wat @@ -7,8 +7,8 @@ (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) (memory $0 1) (data (i32.const 8) ",\00\00\00\01\00\00\00\01\00\00\00,\00\00\00f\00u\00n\00c\00t\00i\00o\00n\00-\00e\00x\00p\00r\00e\00s\00s\00i\00o\00n\00.\00t\00s\00") - (table $0 11 funcref) - (elem (i32.const 0) $null $start:function-expression~anonymous|0 $start:function-expression~anonymous|1 $start:function-expression~someName $start:function-expression~anonymous|2 $start:function-expression~anonymous|3 $start:function-expression~anonymous|4 $start:function-expression~anonymous|5 $function-expression/testOmittedReturn1~anonymous|0 $function-expression/testOmittedReturn2~anonymous|0 $function-expression/testOmittedReturn3~anonymous|0) + (table $0 12 funcref) + (elem (i32.const 0) $null $start:function-expression~anonymous|0 $start:function-expression~anonymous|1 $start:function-expression~someName $start:function-expression~anonymous|2 $start:function-expression~anonymous|3 $start:function-expression~anonymous|4 $start:function-expression~anonymous|5 $function-expression/testOmittedReturn1~anonymous|0 $function-expression/testOmittedReturn2~anonymous|0 $function-expression/testOmittedReturn3~anonymous|0 $function-expression/testNullable~anonymous|0) (global $function-expression/f1 (mut i32) (i32.const 1)) (global $~lib/argc (mut i32) (i32.const 0)) (global $function-expression/f2 (mut i32) (i32.const 2)) @@ -67,7 +67,21 @@ (func $function-expression/testOmittedReturn3 (; 14 ;) (type $FUNCSIG$i) (result i32) i32.const 10 ) - (func $start:function-expression (; 15 ;) (type $FUNCSIG$v) + (func $function-expression/testNullable~anonymous|0 (; 15 ;) (type $FUNCSIG$i) (result i32) + i32.const 1 + ) + (func $function-expression/testNullable (; 16 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) + local.get $0 + if + i32.const 11 + return + else + i32.const 0 + return + end + unreachable + ) + (func $start:function-expression (; 17 ;) (type $FUNCSIG$v) i32.const 1 global.set $~lib/argc i32.const 1 @@ -209,10 +223,23 @@ call $~lib/builtins/abort unreachable end + i32.const 0 + call $function-expression/testNullable + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 24 + i32.const 45 + i32.const 0 + call $~lib/builtins/abort + unreachable + end ) - (func $start (; 16 ;) (type $FUNCSIG$v) + (func $start (; 18 ;) (type $FUNCSIG$v) call $start:function-expression ) - (func $null (; 17 ;) (type $FUNCSIG$v) + (func $null (; 19 ;) (type $FUNCSIG$v) ) )