From dac37f4148f5e9afd7ef029c65b993548da35bbe Mon Sep 17 00:00:00 2001 From: Christian Stewart Date: Mon, 24 Aug 2026 04:28:18 -0700 Subject: [PATCH] fix(compiler): repair generic dictionary dispatch for pointer-constraint receivers Interface-constraint generic methods lowered a property-keyed dispatch lambda that called the method directly on the receiver value. When the caller converted the address of a variable to the constraint's pointer type-set element, the runtime receiver was a VarRef wrapper, so the call failed with TypeError: is not a function. Unwrap struct receivers through pointerValue in the dictionary lambdas; class instances pass through unchanged. Interface descriptors keep their existing shape. The same chain exposed a second lowering gap: an explicit instantiation that leaves trailing type parameters to constraint inference, such as decodeLocalPairing[*pairingOffer] over [M localPairingMessage[T], T any], emitted type arguments only for the explicitly written parameter, so the body resolved T's zero value as null and dispatched on nil. Read the full argument list recorded by go/types Instances when explicit arguments run out. Bump compilerSemanticsVersion so cached artifacts recompile with the new dispatch shape. Signed-off-by: Christian Stewart --- compiler/compiler-cache.go | 2 +- compiler/gotest/runner.go | 1 - compiler/lowering.go | 44 ++++++++- .../factory_async_callback/dep/dep.gs.ts | 2 +- .../generic_constrained_slice_clone.gs.ts | 2 +- .../generic_constructor_field_typeinfo.gs.ts | 4 +- .../generic_cross_package_receiver_args.gs.ts | 2 +- .../generic_interface_context_parent.gs.ts | 4 +- .../generic_interface_descriptor_bridge.gs.ts | 6 +- ...eric_interface_embedded_method_calls.gs.ts | 2 +- .../expected.log | 2 + ...eric_pointer_constraint_method_dispatch.go | 48 ++++++++++ ...c_pointer_constraint_method_dispatch.gs.ts | 95 +++++++++++++++++++ .../index.ts | 3 + .../tsconfig.json | 22 +++++ .../generic_receiver_method_calls.gs.ts | 2 +- .../generic_receiver_type_param_method.gs.ts | 4 +- .../tests/generics_basic/generics_basic.gs.ts | 2 +- .../interface_async_method_call.gs.ts | 2 +- .../package_import_errors.gs.ts | 4 +- .../package_import_protobuf_equalvt.gs.ts | 4 +- .../reflect_implements.gs.ts | 2 +- .../reflect_typefor/reflect_typefor.gs.ts | 2 +- 23 files changed, 233 insertions(+), 28 deletions(-) create mode 100644 tests/tests/generic_pointer_constraint_method_dispatch/expected.log create mode 100644 tests/tests/generic_pointer_constraint_method_dispatch/generic_pointer_constraint_method_dispatch.go create mode 100644 tests/tests/generic_pointer_constraint_method_dispatch/generic_pointer_constraint_method_dispatch.gs.ts create mode 100644 tests/tests/generic_pointer_constraint_method_dispatch/index.ts create mode 100644 tests/tests/generic_pointer_constraint_method_dispatch/tsconfig.json diff --git a/compiler/compiler-cache.go b/compiler/compiler-cache.go index f0a86e087..4e333c482 100644 --- a/compiler/compiler-cache.go +++ b/compiler/compiler-cache.go @@ -27,7 +27,7 @@ const compilerCacheSchema = "goscript-package-artifact-v1" // compilerSemanticsVersion versions emitted-output semantics. Bump this value // with every behavior-changing compiler commit so artifacts cached by an // older binary miss and rebuild instead of replaying stale bytes. -const compilerSemanticsVersion = "1" +const compilerSemanticsVersion = "2" type compilerCacheEntryKind string diff --git a/compiler/gotest/runner.go b/compiler/gotest/runner.go index 02af134e2..159767c0d 100644 --- a/compiler/gotest/runner.go +++ b/compiler/gotest/runner.go @@ -240,7 +240,6 @@ func packageExecutionFanout( var group errgroup.Group group.SetLimit(max(parallelism, 1)) for _, idx := range indexes { - idx := idx group.Go(func() error { select { case <-ctx.Done(): diff --git a/compiler/lowering.go b/compiler/lowering.go index 3de4590ec..f2333fead 100644 --- a/compiler/lowering.go +++ b/compiler/lowering.go @@ -11745,6 +11745,7 @@ func (o *LoweringOwner) lowerValueForTargetTypes( } return value } + func (o *LoweringOwner) lowerInterfaceValueExpr( ctx lowerFileContext, targetType types.Type, @@ -13769,12 +13770,15 @@ func (o *LoweringOwner) genericTypeArgsExpr(ctx lowerFileContext, callee ast.Exp return "undefined" } typeParams := signature.TypeParams() + instanceArgs := instantiatedTypeArgs(ctx, callee) entries := make([]string, 0, typeParams.Len()) for idx := range typeParams.Len() { - if idx >= len(typeArgExprs) { - break + var typ types.Type + if idx < len(typeArgExprs) { + typ = ctx.semPkg.source.TypesInfo.TypeOf(typeArgExprs[idx]) + } else if instanceArgs != nil && idx < instanceArgs.Len() { + typ = instanceArgs.At(idx) } - typ := ctx.semPkg.source.TypesInfo.TypeOf(typeArgExprs[idx]) if typ == nil { continue } @@ -13786,6 +13790,30 @@ func (o *LoweringOwner) genericTypeArgsExpr(ctx lowerFileContext, callee ast.Exp return o.genericTypeArgsLiteral(entries) } +// instantiatedTypeArgs resolves the full type argument list recorded for an +// explicit generic instantiation, including trailing arguments Go inferred +// through constraint core types rather than explicit syntax. +func instantiatedTypeArgs(ctx lowerFileContext, callee ast.Expr) *types.TypeList { + if ctx.semPkg == nil || ctx.semPkg.source == nil { + return nil + } + instances := ctx.semPkg.source.TypesInfo.Instances + if instances == nil { + return nil + } + switch typed := callee.(type) { + case *ast.Ident: + if instance, ok := instances[typed]; ok { + return instance.TypeArgs + } + case *ast.SelectorExpr: + if instance, ok := instances[typed.Sel]; ok { + return instance.TypeArgs + } + } + return nil +} + func (o *LoweringOwner) inferredGenericTypeArgsExpr( ctx lowerFileContext, signature *types.Signature, @@ -13924,12 +13952,20 @@ func (o *LoweringOwner) genericMethodDescriptorsForType( } genericArgs := o.genericReceiverTypeArgsExprForMethod(ctx, method, methodSetType) if namedStructType(named) != nil || isInterfaceType(named) { + // A struct receiver may arrive as a VarRef when the caller + // converted the address of a variable to the constraint's + // pointer type-set element, so unwrap it before the + // property-keyed call. Instances pass through unchanged. + receiverExpr := "receiver" + if namedStructType(named) != nil { + receiverExpr = o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) + "(receiver)" + } callArgs := make([]string, 0, 2) if genericArgs != "" { callArgs = append(callArgs, genericArgs) } callArgs = append(callArgs, "..."+o.runtimeOwner.QualifiedHelper(RuntimeHelperStripGenericTypeArgs)+"(args)") - methods = append(methods, method.Name()+": (receiver: any, ...args: any[]) => receiver."+method.Name()+"("+strings.Join(callArgs, ", ")+")") + methods = append(methods, method.Name()+": (receiver: any, ...args: any[]) => "+receiverExpr+"."+method.Name()+"("+strings.Join(callArgs, ", ")+")") continue } receiver := "receiver" diff --git a/tests/tests/factory_async_callback/dep/dep.gs.ts b/tests/tests/factory_async_callback/dep/dep.gs.ts index a96203d77..40feffdc5 100644 --- a/tests/tests/factory_async_callback/dep/dep.gs.ts +++ b/tests/tests/factory_async_callback/dep/dep.gs.ts @@ -72,5 +72,5 @@ export async function NewFactory(b: Bus): globalThis.Promise { let ch: $.Channel<{}> | null = $.makeChannel<{}>(1, {}, "both") await $.chanSend(ch, {}) await $.chanRecv(ch) - return $.namedValueInterfaceValue(new factory(), "*dep.factory", {GetConfigID: (receiver: any, ...args: any[]) => receiver.GetConfigID({[$.genericTypeArgsMarker]: true, T: { type: "dep.Bus", zero: () => $.markAsStructValue(new Bus()) }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "dep.factory" }, [{ name: "GetConfigID", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "string" } }] }]) + return $.namedValueInterfaceValue(new factory(), "*dep.factory", {GetConfigID: (receiver: any, ...args: any[]) => $.pointerValue(receiver).GetConfigID({[$.genericTypeArgsMarker]: true, T: { type: "dep.Bus", zero: () => $.markAsStructValue(new Bus()) }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "dep.factory" }, [{ name: "GetConfigID", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "string" } }] }]) } diff --git a/tests/tests/generic_constrained_slice_clone/generic_constrained_slice_clone.gs.ts b/tests/tests/generic_constrained_slice_clone/generic_constrained_slice_clone.gs.ts index b32d6abb5..1f202ea5e 100644 --- a/tests/tests/generic_constrained_slice_clone/generic_constrained_slice_clone.gs.ts +++ b/tests/tests/generic_constrained_slice_clone/generic_constrained_slice_clone.gs.ts @@ -67,7 +67,7 @@ export async function cloneSlice(__typeArgs: $.GenericTypeArgs | undefined, i export async function main(): globalThis.Promise { let items: $.Slice | null> = $.arrayToSlice | null>([new item({value: "first"}), new item({value: "second"})]) - let cloned: $.Slice | null> = (await cloneSlice({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Pointer, elemType: "main.item" }, zero: () => null, methods: {CloneVT: (receiver: any, ...args: any[]) => receiver.CloneVT(...$.stripGenericTypeArgs(args))} }}, items) as $.Slice | null>) + let cloned: $.Slice | null> = (await cloneSlice({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Pointer, elemType: "main.item" }, zero: () => null, methods: {CloneVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).CloneVT(...$.stripGenericTypeArgs(args))} }}, items) as $.Slice | null>) await $.println($.len(cloned), $.pointerValue($.arrayIndex(cloned!, 0)).value, $.pointerValue($.arrayIndex(cloned!, 1)).value, $.pointerEqual($.arrayIndex(cloned!, 0), $.arrayIndex(items!, 0))) } diff --git a/tests/tests/generic_constructor_field_typeinfo/generic_constructor_field_typeinfo.gs.ts b/tests/tests/generic_constructor_field_typeinfo/generic_constructor_field_typeinfo.gs.ts index 0ec326547..f4a75fc51 100644 --- a/tests/tests/generic_constructor_field_typeinfo/generic_constructor_field_typeinfo.gs.ts +++ b/tests/tests/generic_constructor_field_typeinfo/generic_constructor_field_typeinfo.gs.ts @@ -110,10 +110,10 @@ export async function main(): globalThis.Promise { let bt: blockType | $.VarRef | null = (NewBlockType(undefined, "sample", $.functionValue((): sampleBlock | $.VarRef | null => { return new sampleBlock() }, ({ kind: $.TypeKind.Function, params: [], results: [{ kind: $.TypeKind.Pointer, elemType: "main.sampleBlock" }] } as $.FunctionTypeInfo))) as blockType | $.VarRef | null) - let blk = await blockType.prototype.Constructor.call(bt, {[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Pointer, elemType: "main.sampleBlock" }, zero: () => null, methods: {MarshalBlock: (receiver: any, ...args: any[]) => receiver.MarshalBlock(...$.stripGenericTypeArgs(args)), UnmarshalBlock: (receiver: any, ...args: any[]) => receiver.UnmarshalBlock(...$.stripGenericTypeArgs(args))} }}) + let blk = await blockType.prototype.Constructor.call(bt, {[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Pointer, elemType: "main.sampleBlock" }, zero: () => null, methods: {MarshalBlock: (receiver: any, ...args: any[]) => $.pointerValue(receiver).MarshalBlock(...$.stripGenericTypeArgs(args)), UnmarshalBlock: (receiver: any, ...args: any[]) => $.pointerValue(receiver).UnmarshalBlock(...$.stripGenericTypeArgs(args))} }}) let __goscriptTuple0: any = await $.pointerValue>(blk).MarshalBlock() let data: $.Slice = __goscriptTuple0[0] - await $.println(blockType.prototype.GetBlockTypeID.call(bt, {[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Pointer, elemType: "main.sampleBlock" }, zero: () => null, methods: {MarshalBlock: (receiver: any, ...args: any[]) => receiver.MarshalBlock(...$.stripGenericTypeArgs(args)), UnmarshalBlock: (receiver: any, ...args: any[]) => receiver.UnmarshalBlock(...$.stripGenericTypeArgs(args))} }}), $.len(data)) + await $.println(blockType.prototype.GetBlockTypeID.call(bt, {[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Pointer, elemType: "main.sampleBlock" }, zero: () => null, methods: {MarshalBlock: (receiver: any, ...args: any[]) => $.pointerValue(receiver).MarshalBlock(...$.stripGenericTypeArgs(args)), UnmarshalBlock: (receiver: any, ...args: any[]) => $.pointerValue(receiver).UnmarshalBlock(...$.stripGenericTypeArgs(args))} }}), $.len(data)) } if ($.isMainScript(import.meta)) { diff --git a/tests/tests/generic_cross_package_receiver_args/generic_cross_package_receiver_args.gs.ts b/tests/tests/generic_cross_package_receiver_args/generic_cross_package_receiver_args.gs.ts index 2d3a5b2bd..7803c34ff 100644 --- a/tests/tests/generic_cross_package_receiver_args/generic_cross_package_receiver_args.gs.ts +++ b/tests/tests/generic_cross_package_receiver_args/generic_cross_package_receiver_args.gs.ts @@ -76,7 +76,7 @@ export function setConcrete(w: dep.Wrapper | $.VarRef | null): stri export async function main(): globalThis.Promise { let impl: wrapper | $.VarRef | null = new wrapper({Impl: new dep.Impl({Item: 7})}) - await $.println("interface:", await read({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }, E: { type: { kind: $.TypeKind.Basic, name: "string" }, zero: () => "" }}, $.namedValueInterfaceValue(impl, "*main.wrapper", {Other: (receiver: any, ...args: any[]) => receiver.Other({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }, E: { type: { kind: $.TypeKind.Basic, name: "string" }, zero: () => "" }}, ...$.stripGenericTypeArgs(args)), Value: (receiver: any, ...args: any[]) => receiver.Value({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.wrapper" }, [{ name: "Other", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "string" } }] }, { name: "Value", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]))) + await $.println("interface:", await read({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }, E: { type: { kind: $.TypeKind.Basic, name: "string" }, zero: () => "" }}, $.namedValueInterfaceValue(impl, "*main.wrapper", {Other: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Other({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }, E: { type: { kind: $.TypeKind.Basic, name: "string" }, zero: () => "" }}, ...$.stripGenericTypeArgs(args)), Value: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Value({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.wrapper" }, [{ name: "Other", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "string" } }] }, { name: "Value", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]))) let keyed: dep.Wrapper | $.VarRef | null = new dep.Wrapper({Keyed: new dep.Keyed()}) await $.println("generic empty:", $.stringEqual(setGeneric({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }, U: { type: { kind: $.TypeKind.Basic, name: "string" }, zero: () => "" }}, keyed, 7), "")) await $.println("concrete empty:", $.stringEqual(setConcrete(keyed), "")) diff --git a/tests/tests/generic_interface_context_parent/generic_interface_context_parent.gs.ts b/tests/tests/generic_interface_context_parent/generic_interface_context_parent.gs.ts index 622e4df8e..e194db0d2 100644 --- a/tests/tests/generic_interface_context_parent/generic_interface_context_parent.gs.ts +++ b/tests/tests/generic_interface_context_parent/generic_interface_context_parent.gs.ts @@ -138,7 +138,7 @@ export class genericValue { } export async function main(): globalThis.Promise { - let resolver: Resolver | null = $.namedValueInterfaceValue(new genericResolver(), "*main.genericResolver", {Resolve: (receiver: any, ...args: any[]) => receiver.Resolve({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.genericResolver" }, [{ name: "Resolve", args: [{ name: "ctx", type: "context.Context" }, { name: "handler", type: "main.Handler" }], returns: [{ name: "_r0", type: "error" }] }]) + let resolver: Resolver | null = $.namedValueInterfaceValue(new genericResolver(), "*main.genericResolver", {Resolve: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Resolve({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.genericResolver" }, [{ name: "Resolve", args: [{ name: "ctx", type: "context.Context" }, { name: "handler", type: "main.Handler" }], returns: [{ name: "_r0", type: "error" }] }]) { let err = await $.pointerValue>(resolver).Resolve(context.Background(), $.interfaceValue($.markAsStructValue(new handler()), "main.handler", "main.handler")) if (err != null) { @@ -148,7 +148,7 @@ export async function main(): globalThis.Promise { } await $.println("resolve ok") let g = $.markAsStructValue(new genericValue({value: 7})) - let reader: ValueReader | null = $.namedValueInterfaceValue($.markAsStructValue($.cloneStructValue(g)), "main.genericValue", {Get: (receiver: any, ...args: any[]) => receiver.Get({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args))}, "main.genericValue", [{ name: "Get", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]) + let reader: ValueReader | null = $.namedValueInterfaceValue($.markAsStructValue($.cloneStructValue(g)), "main.genericValue", {Get: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Get({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args))}, "main.genericValue", [{ name: "Get", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]) g.value = 9 if (await $.pointerValue>(reader).Get() != 7) { await $.println("value copy failed") diff --git a/tests/tests/generic_interface_descriptor_bridge/generic_interface_descriptor_bridge.gs.ts b/tests/tests/generic_interface_descriptor_bridge/generic_interface_descriptor_bridge.gs.ts index 1c551b4e5..a69ea7511 100644 --- a/tests/tests/generic_interface_descriptor_bridge/generic_interface_descriptor_bridge.gs.ts +++ b/tests/tests/generic_interface_descriptor_bridge/generic_interface_descriptor_bridge.gs.ts @@ -112,13 +112,13 @@ export async function main(): globalThis.Promise { let [ctx, cancel] = context.WithCancel($.pointerValueOrNil(context.Background())!) await cancel!() - let genericGeneric: GenericWaiter | null = $.namedValueInterfaceValue(new genericBox(), "*main.genericBox", {Count: (receiver: any, ...args: any[]) => receiver.Count({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args)), Wait: (receiver: any, ...args: any[]) => receiver.Wait({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.genericBox" }, [{ name: "Count", args: [{ name: "ctx", type: "context.Context" }, { name: "values", type: { kind: $.TypeKind.Slice, elemType: { kind: $.TypeKind.Basic, name: "int" } } }], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }, { name: "Wait", args: [{ name: "ctx", type: "context.Context" }, { name: "old", type: { kind: $.TypeKind.Basic, name: "int" } }], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]) + let genericGeneric: GenericWaiter | null = $.namedValueInterfaceValue(new genericBox(), "*main.genericBox", {Count: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Count({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args)), Wait: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Wait({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.genericBox" }, [{ name: "Count", args: [{ name: "ctx", type: "context.Context" }, { name: "values", type: { kind: $.TypeKind.Slice, elemType: { kind: $.TypeKind.Basic, name: "int" } } }], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }, { name: "Wait", args: [{ name: "ctx", type: "context.Context" }, { name: "old", type: { kind: $.TypeKind.Basic, name: "int" } }], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]) await $.println("generic-generic", await $.callInterfaceMethod($.pointerValue>(genericGeneric), "Wait", {[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ctx, 7), await $.callInterfaceMethod($.pointerValue>(genericGeneric), "Count", {[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ctx, $.arrayToSlice([1, 2]))) - let genericPlain: IntWaiter | null = $.namedValueInterfaceValue(new genericBox(), "*main.genericBox", {Count: (receiver: any, ...args: any[]) => receiver.Count({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args)), Wait: (receiver: any, ...args: any[]) => receiver.Wait({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.genericBox" }, [{ name: "Count", args: [{ name: "ctx", type: "context.Context" }, { name: "values", type: { kind: $.TypeKind.Slice, elemType: { kind: $.TypeKind.Basic, name: "int" } } }], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }, { name: "Wait", args: [{ name: "ctx", type: "context.Context" }, { name: "old", type: { kind: $.TypeKind.Basic, name: "int" } }], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]) + let genericPlain: IntWaiter | null = $.namedValueInterfaceValue(new genericBox(), "*main.genericBox", {Count: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Count({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args)), Wait: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Wait({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.genericBox" }, [{ name: "Count", args: [{ name: "ctx", type: "context.Context" }, { name: "values", type: { kind: $.TypeKind.Slice, elemType: { kind: $.TypeKind.Basic, name: "int" } } }], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }, { name: "Wait", args: [{ name: "ctx", type: "context.Context" }, { name: "old", type: { kind: $.TypeKind.Basic, name: "int" } }], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]) await $.println("generic-plain", await $.pointerValue>(genericPlain).Wait(ctx, 8), await $.pointerValue>(genericPlain).Count(ctx, $.arrayToSlice([1, 2, 3]))) - let plainGeneric: GenericWaiter | null = $.namedValueInterfaceValue(new intBox(), "*main.intBox", {Count: (receiver: any, ...args: any[]) => receiver.Count(...$.stripGenericTypeArgs(args)), Wait: (receiver: any, ...args: any[]) => receiver.Wait(...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.intBox" }, [{ name: "Count", args: [{ name: "ctx", type: "context.Context" }, { name: "values", type: { kind: $.TypeKind.Slice, elemType: { kind: $.TypeKind.Basic, name: "int" } } }], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }, { name: "Wait", args: [{ name: "ctx", type: "context.Context" }, { name: "old", type: { kind: $.TypeKind.Basic, name: "int" } }], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]) + let plainGeneric: GenericWaiter | null = $.namedValueInterfaceValue(new intBox(), "*main.intBox", {Count: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Count(...$.stripGenericTypeArgs(args)), Wait: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Wait(...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.intBox" }, [{ name: "Count", args: [{ name: "ctx", type: "context.Context" }, { name: "values", type: { kind: $.TypeKind.Slice, elemType: { kind: $.TypeKind.Basic, name: "int" } } }], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }, { name: "Wait", args: [{ name: "ctx", type: "context.Context" }, { name: "old", type: { kind: $.TypeKind.Basic, name: "int" } }], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]) await $.println("plain-generic", await $.callInterfaceMethod($.pointerValue>(plainGeneric), "Wait", {[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ctx, 9), await $.callInterfaceMethod($.pointerValue>(plainGeneric), "Count", {[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ctx, $.arrayToSlice([1, 2, 3, 4]))) let plainPlain: IntWaiter | null = $.interfaceValue(new intBox(), "*main.intBox", { kind: $.TypeKind.Pointer, elemType: "main.intBox" }) let retypedPlainGeneric: GenericWaiter | null = (plainPlain as GenericWaiter | null) diff --git a/tests/tests/generic_interface_embedded_method_calls/generic_interface_embedded_method_calls.gs.ts b/tests/tests/generic_interface_embedded_method_calls/generic_interface_embedded_method_calls.gs.ts index 76b751242..9e953056d 100644 --- a/tests/tests/generic_interface_embedded_method_calls/generic_interface_embedded_method_calls.gs.ts +++ b/tests/tests/generic_interface_embedded_method_calls/generic_interface_embedded_method_calls.gs.ts @@ -85,7 +85,7 @@ export async function read(__typeArgs: $.GenericTypeArgs | undefined, d: derived export async function main(): globalThis.Promise { let i: impl | $.VarRef | null = new impl({value: 7, other: "ok"}) - await $.println(await read({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }, E: { type: { kind: $.TypeKind.Basic, name: "string" }, zero: () => "" }}, $.namedValueInterfaceValue(i, "*main.impl", {Other: (receiver: any, ...args: any[]) => receiver.Other({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }, E: { type: { kind: $.TypeKind.Basic, name: "string" }, zero: () => "" }}, ...$.stripGenericTypeArgs(args)), Value: (receiver: any, ...args: any[]) => receiver.Value({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }, E: { type: { kind: $.TypeKind.Basic, name: "string" }, zero: () => "" }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.impl" }, [{ name: "Other", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "string" } }] }, { name: "Value", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]))) + await $.println(await read({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }, E: { type: { kind: $.TypeKind.Basic, name: "string" }, zero: () => "" }}, $.namedValueInterfaceValue(i, "*main.impl", {Other: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Other({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }, E: { type: { kind: $.TypeKind.Basic, name: "string" }, zero: () => "" }}, ...$.stripGenericTypeArgs(args)), Value: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Value({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }, E: { type: { kind: $.TypeKind.Basic, name: "string" }, zero: () => "" }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.impl" }, [{ name: "Other", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "string" } }] }, { name: "Value", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]))) } if ($.isMainScript(import.meta)) { diff --git a/tests/tests/generic_pointer_constraint_method_dispatch/expected.log b/tests/tests/generic_pointer_constraint_method_dispatch/expected.log new file mode 100644 index 000000000..9abfe2131 --- /dev/null +++ b/tests/tests/generic_pointer_constraint_method_dispatch/expected.log @@ -0,0 +1,2 @@ +decoded:hi +encoded: note diff --git a/tests/tests/generic_pointer_constraint_method_dispatch/generic_pointer_constraint_method_dispatch.go b/tests/tests/generic_pointer_constraint_method_dispatch/generic_pointer_constraint_method_dispatch.go new file mode 100644 index 000000000..1bc5b97c0 --- /dev/null +++ b/tests/tests/generic_pointer_constraint_method_dispatch/generic_pointer_constraint_method_dispatch.go @@ -0,0 +1,48 @@ +package main + +// localPairingMessage mirrors the spacewave sdk/session pairing constraint: a +// pointer type-set element plus VT codec methods. +type localPairingMessage[T any] interface { + *T + MarshalVT() ([]byte, error) + UnmarshalVT(data []byte) error +} + +type pairingOffer struct { + Note string +} + +func (o *pairingOffer) MarshalVT() ([]byte, error) { + return []byte(o.Note), nil +} + +func (o *pairingOffer) UnmarshalVT(data []byte) error { + o.Note = "decoded:" + string(data) + return nil +} + +func decodeLocalPairing[M localPairingMessage[T], T any](data []byte) (T, error) { + var msg T + err := M(&msg).UnmarshalVT(data) + return msg, err +} + +func encodeLocalPairing[M localPairingMessage[T], T any](msg M) ([]byte, error) { + return msg.MarshalVT() +} + +func main() { + msg, err := decodeLocalPairing[*pairingOffer]([]byte("hi")) + if err != nil { + println("decode error") + return + } + println(msg.Note) + + encoded, err := encodeLocalPairing[*pairingOffer](&pairingOffer{Note: "note"}) + if err != nil { + println("encode error") + return + } + println("encoded:", string(encoded)) +} diff --git a/tests/tests/generic_pointer_constraint_method_dispatch/generic_pointer_constraint_method_dispatch.gs.ts b/tests/tests/generic_pointer_constraint_method_dispatch/generic_pointer_constraint_method_dispatch.gs.ts new file mode 100644 index 000000000..6fc8d4419 --- /dev/null +++ b/tests/tests/generic_pointer_constraint_method_dispatch/generic_pointer_constraint_method_dispatch.gs.ts @@ -0,0 +1,95 @@ +// Generated file based on generic_pointer_constraint_method_dispatch.go +// Updated when compliance tests are re-run, DO NOT EDIT! + +import * as $ from "@goscript/builtin/index.js" + +export type localPairingMessage = { + MarshalVT(__typeArgs: $.GenericTypeArgs | undefined): [$.Slice, $.GoError] + UnmarshalVT(__typeArgs: $.GenericTypeArgs | undefined, data: $.Slice): $.GoError +} + +$.registerInterfaceType( + "main.localPairingMessage", + null, + [{ name: "MarshalVT", args: [], returns: [{ type: { kind: $.TypeKind.Slice, elemType: { kind: $.TypeKind.Basic, name: "uint8" } } }, { type: "error" }] }, { name: "UnmarshalVT", args: [{ type: { kind: $.TypeKind.Basic, name: "unknown" } }], returns: [{ type: "error" }] }] +); + +export class pairingOffer { + public get Note(): string { + return this._fields.Note.value + } + public set Note(value: string) { + this._fields.Note.value = value + } + + public _fields: { + Note: $.VarRef + } + + constructor(init?: Partial<{Note?: string}>) { + this._fields = { + Note: $.varRef(init?.Note ?? ("" as string)) + } + } + + public clone(): pairingOffer { + const cloned = new pairingOffer() + cloned._fields = { + Note: $.varRef(this._fields.Note.value) + } + return $.markAsStructValue(cloned) + } + + public MarshalVT(): [$.Slice, $.GoError] { + const o: pairingOffer | $.VarRef | null = this + return [$.stringToBytes($.pointerValue(o).Note), null] + } + + public UnmarshalVT(data: $.Slice): $.GoError { + let o: pairingOffer | $.VarRef | null = this + $.pointerValue(o).Note = "decoded:" + $.bytesToString(data) + return null + } + + static __typeInfo = $.registerStructType( + "main.pairingOffer", + () => new pairingOffer(), + [{ name: "MarshalVT", args: [], returns: [{ type: { kind: $.TypeKind.Slice, elemType: { kind: $.TypeKind.Basic, name: "uint8" } } }, { type: "error" }] }, { name: "UnmarshalVT", args: [{ type: { kind: $.TypeKind.Basic, name: "unknown" } }], returns: [{ type: "error" }] }], + pairingOffer, + [{ name: "Note", key: "Note", type: { kind: $.TypeKind.Basic, name: "string" } }] + ) +} + +export async function decodeLocalPairing(__typeArgs: $.GenericTypeArgs | undefined, data: $.Slice): globalThis.Promise<[any, $.GoError]> { + let msg: $.VarRef = $.varRef($.genericZero(__typeArgs, "T", null)) + let err = await $.callGenericMethod(__typeArgs, "M", "UnmarshalVT", $.interfaceValue(msg, "*T", { kind: $.TypeKind.Pointer, elemType: { kind: $.TypeKind.Interface, methods: [] } }), data) + return [msg.value, err] +} + +export async function encodeLocalPairing(__typeArgs: $.GenericTypeArgs | undefined, msg: any): globalThis.Promise<[$.Slice, $.GoError]> { + return $.callGenericMethod(__typeArgs, "M", "MarshalVT", msg) +} + +export async function main(): globalThis.Promise { + let __goscriptTuple0: any = await decodeLocalPairing({[$.genericTypeArgsMarker]: true, M: { type: { kind: $.TypeKind.Pointer, elemType: "main.pairingOffer" }, zero: () => null, methods: {MarshalVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).MarshalVT(...$.stripGenericTypeArgs(args)), UnmarshalVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).UnmarshalVT(...$.stripGenericTypeArgs(args))} }, T: { type: "main.pairingOffer", zero: () => $.markAsStructValue(new pairingOffer()) }}, new Uint8Array([104, 105])) + let msg = (__goscriptTuple0[0] as pairingOffer) + let err = __goscriptTuple0[1] + if (err != null) { + await $.println("decode error") + return + } + await $.println(msg.Note) + + let __goscriptTuple1: any = await encodeLocalPairing({[$.genericTypeArgsMarker]: true, M: { type: { kind: $.TypeKind.Pointer, elemType: "main.pairingOffer" }, zero: () => null, methods: {MarshalVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).MarshalVT(...$.stripGenericTypeArgs(args)), UnmarshalVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).UnmarshalVT(...$.stripGenericTypeArgs(args))} }, T: { type: "main.pairingOffer", zero: () => $.markAsStructValue(new pairingOffer()) }}, new pairingOffer({Note: "note"})) + let encoded: $.Slice = __goscriptTuple1[0] + err = __goscriptTuple1[1] + if (err != null) { + await $.println("encode error") + return + } + await $.println("encoded:", $.bytesToString(encoded)) +} + +if ($.isMainScript(import.meta)) { + await main() +} diff --git a/tests/tests/generic_pointer_constraint_method_dispatch/index.ts b/tests/tests/generic_pointer_constraint_method_dispatch/index.ts new file mode 100644 index 000000000..f9972f04c --- /dev/null +++ b/tests/tests/generic_pointer_constraint_method_dispatch/index.ts @@ -0,0 +1,3 @@ +export type { localPairingMessage } from "./generic_pointer_constraint_method_dispatch.gs.ts" +export { pairingOffer } from "./generic_pointer_constraint_method_dispatch.gs.ts" +import "./generic_pointer_constraint_method_dispatch.gs.ts" diff --git a/tests/tests/generic_pointer_constraint_method_dispatch/tsconfig.json b/tests/tests/generic_pointer_constraint_method_dispatch/tsconfig.json new file mode 100644 index 000000000..78dda35f9 --- /dev/null +++ b/tests/tests/generic_pointer_constraint_method_dispatch/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "paths": { + "*": [ + "./*" + ], + "@goscript/*": [ + "../../../tests/tests/generic_pointer_constraint_method_dispatch/run/output/@goscript/*", + "../../../gs/*", + "../../../tests/deps/*" + ], + "@goscript/github.com/s4wave/goscript/tests/tests/generic_pointer_constraint_method_dispatch/*": [ + "./*" + ] + } + }, + "extends": "../../../tests/tsconfig.base.json", + "include": [ + "generic_pointer_constraint_method_dispatch.gs.ts", + "index.ts" + ] +} diff --git a/tests/tests/generic_receiver_method_calls/generic_receiver_method_calls.gs.ts b/tests/tests/generic_receiver_method_calls/generic_receiver_method_calls.gs.ts index be8b8fbe1..33a812ec8 100644 --- a/tests/tests/generic_receiver_method_calls/generic_receiver_method_calls.gs.ts +++ b/tests/tests/generic_receiver_method_calls/generic_receiver_method_calls.gs.ts @@ -112,7 +112,7 @@ export async function methodExpression(__typeArgs: $.GenericTypeArgs | undefined export async function main(): globalThis.Promise { let b: box | $.VarRef | null = new box({value: 7}) await $.println("direct:", direct({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, b)) - await $.println("interface:", await throughInterface({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, $.namedValueInterfaceValue(b, "*main.box", {Value: (receiver: any, ...args: any[]) => receiver.Value({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.box" }, [{ name: "Value", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]))) + await $.println("interface:", await throughInterface({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, $.namedValueInterfaceValue(b, "*main.box", {Value: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Value({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.box" }, [{ name: "Value", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Basic, name: "int" } }] }]))) await $.println("promoted:", promoted({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, new holder({box: $.markAsStructValue($.cloneStructValue($.pointerValue(b)))}))) await $.println("expression:", await methodExpression({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Basic, name: "int" }, zero: () => 0 }}, b)) } diff --git a/tests/tests/generic_receiver_type_param_method/generic_receiver_type_param_method.gs.ts b/tests/tests/generic_receiver_type_param_method/generic_receiver_type_param_method.gs.ts index 639f5f20e..e09789f6a 100644 --- a/tests/tests/generic_receiver_type_param_method/generic_receiver_type_param_method.gs.ts +++ b/tests/tests/generic_receiver_type_param_method/generic_receiver_type_param_method.gs.ts @@ -96,9 +96,9 @@ export function __goscript_set_curve(__goscriptValue: nistCurve | $.VarRef { - let p: point | $.VarRef | null = (await nistCurve.prototype.Add.call(curve, {[$.genericTypeArgsMarker]: true, Point: { type: { kind: $.TypeKind.Pointer, elemType: "main.point" }, zero: () => null, methods: {Add: (receiver: any, ...args: any[]) => receiver.Add(...$.stripGenericTypeArgs(args))} }}, new point({N: 2}), new point({N: 3})) as point | $.VarRef | null) + let p: point | $.VarRef | null = (await nistCurve.prototype.Add.call(curve, {[$.genericTypeArgsMarker]: true, Point: { type: { kind: $.TypeKind.Pointer, elemType: "main.point" }, zero: () => null, methods: {Add: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Add(...$.stripGenericTypeArgs(args))} }}, new point({N: 2}), new point({N: 3})) as point | $.VarRef | null) await $.println("sum:", $.pointerValue(p).N) - if (nistCurve.prototype.Zero.call(curve, {[$.genericTypeArgsMarker]: true, Point: { type: { kind: $.TypeKind.Pointer, elemType: "main.point" }, zero: () => null, methods: {Add: (receiver: any, ...args: any[]) => receiver.Add(...$.stripGenericTypeArgs(args))} }}) == null) { + if (nistCurve.prototype.Zero.call(curve, {[$.genericTypeArgsMarker]: true, Point: { type: { kind: $.TypeKind.Pointer, elemType: "main.point" }, zero: () => null, methods: {Add: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Add(...$.stripGenericTypeArgs(args))} }}) == null) { await $.println("zero") } } diff --git a/tests/tests/generics_basic/generics_basic.gs.ts b/tests/tests/generics_basic/generics_basic.gs.ts index 123ec5072..1ce78bcb9 100644 --- a/tests/tests/generics_basic/generics_basic.gs.ts +++ b/tests/tests/generics_basic/generics_basic.gs.ts @@ -286,7 +286,7 @@ export async function main(): globalThis.Promise { await $.println("=== Interface constraint ===") let items: $.Slice | null> = $.arrayToSlice | null>([new Item({Name: "alpha"}), new Item({Name: "beta"})]) - let clones: $.Slice | null> = (await CloneAll({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Pointer, elemType: "main.Item" }, zero: () => null, methods: {Clone: (receiver: any, ...args: any[]) => receiver.Clone(...$.stripGenericTypeArgs(args))} }}, items) as $.Slice | null>) + let clones: $.Slice | null> = (await CloneAll({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Pointer, elemType: "main.Item" }, zero: () => null, methods: {Clone: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Clone(...$.stripGenericTypeArgs(args))} }}, items) as $.Slice | null>) await $.println("clone:", $.pointerValue($.arrayIndex(clones!, 0)).Name, $.pointerValue($.arrayIndex(clones!, 1)).Name, $.pointerEqual($.arrayIndex(clones!, 0), $.arrayIndex(items!, 0))) await $.println("=== Generic struct with map field ===") diff --git a/tests/tests/interface_async_method_call/interface_async_method_call.gs.ts b/tests/tests/interface_async_method_call/interface_async_method_call.gs.ts index 5a4a44c85..6d79de645 100644 --- a/tests/tests/interface_async_method_call/interface_async_method_call.gs.ts +++ b/tests/tests/interface_async_method_call/interface_async_method_call.gs.ts @@ -181,7 +181,7 @@ export async function processViaInterface(processor: AsyncProcessor | null, inpu } export function newGenericStore(__typeArgs: $.GenericTypeArgs | undefined, value: any): GenericStore | null { - return $.namedValueInterfaceValue(new GenericChannelStore({ch: $.makeChannel(1, $.genericZero(__typeArgs, "V", null), "both"), value: value}), "*main.GenericChannelStore", {Load: (receiver: any, ...args: any[]) => receiver.Load({[$.genericTypeArgsMarker]: true, V: __typeArgs?.["V"] ?? { type: { kind: $.TypeKind.Interface, methods: [] }, zero: () => null }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.GenericChannelStore" }, [{ name: "Load", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Interface, methods: [] } }] }]) + return $.namedValueInterfaceValue(new GenericChannelStore({ch: $.makeChannel(1, $.genericZero(__typeArgs, "V", null), "both"), value: value}), "*main.GenericChannelStore", {Load: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Load({[$.genericTypeArgsMarker]: true, V: __typeArgs?.["V"] ?? { type: { kind: $.TypeKind.Interface, methods: [] }, zero: () => null }}, ...$.stripGenericTypeArgs(args))}, { kind: $.TypeKind.Pointer, elemType: "main.GenericChannelStore" }, [{ name: "Load", args: [], returns: [{ name: "_r0", type: { kind: $.TypeKind.Interface, methods: [] } }] }]) } export async function loadGenericStore(store: GenericStore | null): globalThis.Promise { diff --git a/tests/tests/package_import_errors/package_import_errors.gs.ts b/tests/tests/package_import_errors/package_import_errors.gs.ts index 71260278b..dd68ada15 100644 --- a/tests/tests/package_import_errors/package_import_errors.gs.ts +++ b/tests/tests/package_import_errors/package_import_errors.gs.ts @@ -114,14 +114,14 @@ export async function main(): globalThis.Promise { await $.println("nilErr == nil:", nilErr == null) let typedErr: customErr | $.VarRef | null = new customErr({msg: "typed error"}) - let __goscriptTuple0: any = errors.AsType({[$.genericTypeArgsMarker]: true, E: { type: { kind: $.TypeKind.Pointer, elemType: "main.customErr" }, zero: () => null, methods: {Error: (receiver: any, ...args: any[]) => receiver.Error(...$.stripGenericTypeArgs(args))} }}, $.interfaceValue<$.GoError>($.markAsStructValue(new wrappedErr({err: $.interfaceValue<$.GoError>(typedErr, "*main.customErr", { kind: $.TypeKind.Pointer, elemType: "main.customErr" })})), "main.wrappedErr", "main.wrappedErr")) + let __goscriptTuple0: any = errors.AsType({[$.genericTypeArgsMarker]: true, E: { type: { kind: $.TypeKind.Pointer, elemType: "main.customErr" }, zero: () => null, methods: {Error: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Error(...$.stripGenericTypeArgs(args))} }}, $.interfaceValue<$.GoError>($.markAsStructValue(new wrappedErr({err: $.interfaceValue<$.GoError>(typedErr, "*main.customErr", { kind: $.TypeKind.Pointer, elemType: "main.customErr" })})), "main.wrappedErr", "main.wrappedErr")) let matched: customErr | $.VarRef | null = (__goscriptTuple0[0] as customErr | $.VarRef | null) let ok = __goscriptTuple0[1] await $.println("AsType matched:", ok) if (ok) { await $.println("AsType message:", $.pointerValue(matched).msg) } - let __goscriptTuple1: any = errors.AsType({[$.genericTypeArgsMarker]: true, E: { type: { kind: $.TypeKind.Pointer, elemType: "main.customErr" }, zero: () => null, methods: {Error: (receiver: any, ...args: any[]) => receiver.Error(...$.stripGenericTypeArgs(args))} }}, $.pointerValueOrNil(err1)!) + let __goscriptTuple1: any = errors.AsType({[$.genericTypeArgsMarker]: true, E: { type: { kind: $.TypeKind.Pointer, elemType: "main.customErr" }, zero: () => null, methods: {Error: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Error(...$.stripGenericTypeArgs(args))} }}, $.pointerValueOrNil(err1)!) ok = __goscriptTuple1[1] await $.println("AsType missing:", ok) diff --git a/tests/tests/package_import_protobuf_equalvt/package_import_protobuf_equalvt.gs.ts b/tests/tests/package_import_protobuf_equalvt/package_import_protobuf_equalvt.gs.ts index d6067d9d3..406ee9a6c 100644 --- a/tests/tests/package_import_protobuf_equalvt/package_import_protobuf_equalvt.gs.ts +++ b/tests/tests/package_import_protobuf_equalvt/package_import_protobuf_equalvt.gs.ts @@ -106,13 +106,13 @@ export function state_String(s: state): string { export async function main(): globalThis.Promise { let original: msg | $.VarRef | null = new msg({v: 7}) - let cloned: msg | $.VarRef | null = (protobuf_go_lite.CloneVTValue({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Pointer, elemType: "main.msg" }, zero: () => null, methods: {CloneMessageVT: (receiver: any, ...args: any[]) => receiver.CloneMessageVT(...$.stripGenericTypeArgs(args)), CloneVT: (receiver: any, ...args: any[]) => receiver.CloneVT(...$.stripGenericTypeArgs(args)), EqualVT: (receiver: any, ...args: any[]) => receiver.EqualVT(...$.stripGenericTypeArgs(args)), MarshalToSizedBufferVT: (receiver: any, ...args: any[]) => receiver.MarshalToSizedBufferVT(...$.stripGenericTypeArgs(args)), MarshalVT: (receiver: any, ...args: any[]) => receiver.MarshalVT(...$.stripGenericTypeArgs(args)), Reset: (receiver: any, ...args: any[]) => receiver.Reset(...$.stripGenericTypeArgs(args)), SizeVT: (receiver: any, ...args: any[]) => receiver.SizeVT(...$.stripGenericTypeArgs(args)), UnmarshalVT: (receiver: any, ...args: any[]) => receiver.UnmarshalVT(...$.stripGenericTypeArgs(args))} }}, original) as msg | $.VarRef | null) + let cloned: msg | $.VarRef | null = (protobuf_go_lite.CloneVTValue({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Pointer, elemType: "main.msg" }, zero: () => null, methods: {CloneMessageVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).CloneMessageVT(...$.stripGenericTypeArgs(args)), CloneVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).CloneVT(...$.stripGenericTypeArgs(args)), EqualVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).EqualVT(...$.stripGenericTypeArgs(args)), MarshalToSizedBufferVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).MarshalToSizedBufferVT(...$.stripGenericTypeArgs(args)), MarshalVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).MarshalVT(...$.stripGenericTypeArgs(args)), Reset: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Reset(...$.stripGenericTypeArgs(args)), SizeVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).SizeVT(...$.stripGenericTypeArgs(args)), UnmarshalVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).UnmarshalVT(...$.stripGenericTypeArgs(args))} }}, original) as msg | $.VarRef | null) await $.println("clone:", !$.pointerEqual(cloned, original), msg.prototype.EqualVT.call(cloned, original)) await $.println("clone-slice:", !$.pointerEqual($.arrayIndex(protobuf_go_lite.CloneVTSlice($.arrayToSlice | null>([original]))!, 0), original)) let enumSlice: $.Slice = $.arrayToSlice([$.int(1, 32), $.int(0, 32)]) let clonedEnumSlice: $.Slice = (protobuf_go_lite.CloneSlice(enumSlice) as $.Slice) await $.println("clone-enum-slice:", $.int($.arrayIndex(clonedEnumSlice!, 0), 32), $.int($.arrayIndex(clonedEnumSlice!, 1), 32)) - await $.println("equal:", protobuf_go_lite.IsEqualVT({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Pointer, elemType: "main.msg" }, zero: () => null, methods: {CloneMessageVT: (receiver: any, ...args: any[]) => receiver.CloneMessageVT(...$.stripGenericTypeArgs(args)), CloneVT: (receiver: any, ...args: any[]) => receiver.CloneVT(...$.stripGenericTypeArgs(args)), EqualVT: (receiver: any, ...args: any[]) => receiver.EqualVT(...$.stripGenericTypeArgs(args)), MarshalToSizedBufferVT: (receiver: any, ...args: any[]) => receiver.MarshalToSizedBufferVT(...$.stripGenericTypeArgs(args)), MarshalVT: (receiver: any, ...args: any[]) => receiver.MarshalVT(...$.stripGenericTypeArgs(args)), Reset: (receiver: any, ...args: any[]) => receiver.Reset(...$.stripGenericTypeArgs(args)), SizeVT: (receiver: any, ...args: any[]) => receiver.SizeVT(...$.stripGenericTypeArgs(args)), UnmarshalVT: (receiver: any, ...args: any[]) => receiver.UnmarshalVT(...$.stripGenericTypeArgs(args))} }}, original, new msg({v: 7}))) + await $.println("equal:", protobuf_go_lite.IsEqualVT({[$.genericTypeArgsMarker]: true, T: { type: { kind: $.TypeKind.Pointer, elemType: "main.msg" }, zero: () => null, methods: {CloneMessageVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).CloneMessageVT(...$.stripGenericTypeArgs(args)), CloneVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).CloneVT(...$.stripGenericTypeArgs(args)), EqualVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).EqualVT(...$.stripGenericTypeArgs(args)), MarshalToSizedBufferVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).MarshalToSizedBufferVT(...$.stripGenericTypeArgs(args)), MarshalVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).MarshalVT(...$.stripGenericTypeArgs(args)), Reset: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Reset(...$.stripGenericTypeArgs(args)), SizeVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).SizeVT(...$.stripGenericTypeArgs(args)), UnmarshalVT: (receiver: any, ...args: any[]) => $.pointerValue(receiver).UnmarshalVT(...$.stripGenericTypeArgs(args))} }}, original, new msg({v: 7}))) await $.println("equal-slice-implicit:", protobuf_go_lite.EqualVTSliceImplicit($.arrayToSlice | null>([null, original]), $.arrayToSlice | null>([new msg(), new msg({v: 7})]), $.functionValue((): msg | $.VarRef | null => { return new msg() }, ({ kind: $.TypeKind.Function, params: [], results: [{ kind: $.TypeKind.Pointer, elemType: "main.msg" }] } as $.FunctionTypeInfo)))) diff --git a/tests/tests/reflect_implements/reflect_implements.gs.ts b/tests/tests/reflect_implements/reflect_implements.gs.ts index eef5e1723..b11ec5589 100644 --- a/tests/tests/reflect_implements/reflect_implements.gs.ts +++ b/tests/tests/reflect_implements/reflect_implements.gs.ts @@ -47,7 +47,7 @@ export class MyType { } export async function main(): globalThis.Promise { - let t = reflect.TypeFor({[$.genericTypeArgsMarker]: true, T: { type: "main.MyType", zero: () => $.markAsStructValue(new MyType()), methods: {String: (receiver: any, ...args: any[]) => receiver.String(...$.stripGenericTypeArgs(args))} }}) + let t = reflect.TypeFor({[$.genericTypeArgsMarker]: true, T: { type: "main.MyType", zero: () => $.markAsStructValue(new MyType()), methods: {String: (receiver: any, ...args: any[]) => $.pointerValue(receiver).String(...$.stripGenericTypeArgs(args))} }}) let ptr = reflect.PointerTo($.pointerValueOrNil(t)!) let iface = reflect.TypeFor({[$.genericTypeArgsMarker]: true, T: { type: "main.Stringer", zero: () => null, methods: {String: (receiver: any, ...args: any[]) => receiver.String(...$.stripGenericTypeArgs(args))} }}) diff --git a/tests/tests/reflect_typefor/reflect_typefor.gs.ts b/tests/tests/reflect_typefor/reflect_typefor.gs.ts index 0730568f5..e6af43bf2 100644 --- a/tests/tests/reflect_typefor/reflect_typefor.gs.ts +++ b/tests/tests/reflect_typefor/reflect_typefor.gs.ts @@ -83,7 +83,7 @@ export async function main(): globalThis.Promise { await $.println("TypeFor int kind:", await $.pointerValue>(t3).Kind() == reflect.Int) // Test TypeFor with imported and cross-file named struct types - let t4 = reflect.TypeFor({[$.genericTypeArgsMarker]: true, T: { type: "time.Time", zero: () => $.markAsStructValue(new time.Time()), methods: {Add: (receiver: any, ...args: any[]) => receiver.Add(...$.stripGenericTypeArgs(args)), AddDate: (receiver: any, ...args: any[]) => receiver.AddDate(...$.stripGenericTypeArgs(args)), After: (receiver: any, ...args: any[]) => receiver.After(...$.stripGenericTypeArgs(args)), AppendBinary: (receiver: any, ...args: any[]) => receiver.AppendBinary(...$.stripGenericTypeArgs(args)), AppendFormat: (receiver: any, ...args: any[]) => receiver.AppendFormat(...$.stripGenericTypeArgs(args)), AppendText: (receiver: any, ...args: any[]) => receiver.AppendText(...$.stripGenericTypeArgs(args)), Before: (receiver: any, ...args: any[]) => receiver.Before(...$.stripGenericTypeArgs(args)), Clock: (receiver: any, ...args: any[]) => receiver.Clock(...$.stripGenericTypeArgs(args)), Compare: (receiver: any, ...args: any[]) => receiver.Compare(...$.stripGenericTypeArgs(args)), Date: (receiver: any, ...args: any[]) => receiver.Date(...$.stripGenericTypeArgs(args)), Day: (receiver: any, ...args: any[]) => receiver.Day(...$.stripGenericTypeArgs(args)), Equal: (receiver: any, ...args: any[]) => receiver.Equal(...$.stripGenericTypeArgs(args)), Format: (receiver: any, ...args: any[]) => receiver.Format(...$.stripGenericTypeArgs(args)), GoString: (receiver: any, ...args: any[]) => receiver.GoString(...$.stripGenericTypeArgs(args)), GobEncode: (receiver: any, ...args: any[]) => receiver.GobEncode(...$.stripGenericTypeArgs(args)), Hour: (receiver: any, ...args: any[]) => receiver.Hour(...$.stripGenericTypeArgs(args)), ISOWeek: (receiver: any, ...args: any[]) => receiver.ISOWeek(...$.stripGenericTypeArgs(args)), In: (receiver: any, ...args: any[]) => receiver.In(...$.stripGenericTypeArgs(args)), IsDST: (receiver: any, ...args: any[]) => receiver.IsDST(...$.stripGenericTypeArgs(args)), IsZero: (receiver: any, ...args: any[]) => receiver.IsZero(...$.stripGenericTypeArgs(args)), Local: (receiver: any, ...args: any[]) => receiver.Local(...$.stripGenericTypeArgs(args)), Location: (receiver: any, ...args: any[]) => receiver.Location(...$.stripGenericTypeArgs(args)), MarshalBinary: (receiver: any, ...args: any[]) => receiver.MarshalBinary(...$.stripGenericTypeArgs(args)), MarshalJSON: (receiver: any, ...args: any[]) => receiver.MarshalJSON(...$.stripGenericTypeArgs(args)), MarshalText: (receiver: any, ...args: any[]) => receiver.MarshalText(...$.stripGenericTypeArgs(args)), Minute: (receiver: any, ...args: any[]) => receiver.Minute(...$.stripGenericTypeArgs(args)), Month: (receiver: any, ...args: any[]) => receiver.Month(...$.stripGenericTypeArgs(args)), Nanosecond: (receiver: any, ...args: any[]) => receiver.Nanosecond(...$.stripGenericTypeArgs(args)), Round: (receiver: any, ...args: any[]) => receiver.Round(...$.stripGenericTypeArgs(args)), Second: (receiver: any, ...args: any[]) => receiver.Second(...$.stripGenericTypeArgs(args)), String: (receiver: any, ...args: any[]) => receiver.String(...$.stripGenericTypeArgs(args)), Sub: (receiver: any, ...args: any[]) => receiver.Sub(...$.stripGenericTypeArgs(args)), Truncate: (receiver: any, ...args: any[]) => receiver.Truncate(...$.stripGenericTypeArgs(args)), UTC: (receiver: any, ...args: any[]) => receiver.UTC(...$.stripGenericTypeArgs(args)), Unix: (receiver: any, ...args: any[]) => receiver.Unix(...$.stripGenericTypeArgs(args)), UnixMicro: (receiver: any, ...args: any[]) => receiver.UnixMicro(...$.stripGenericTypeArgs(args)), UnixMilli: (receiver: any, ...args: any[]) => receiver.UnixMilli(...$.stripGenericTypeArgs(args)), UnixNano: (receiver: any, ...args: any[]) => receiver.UnixNano(...$.stripGenericTypeArgs(args)), Weekday: (receiver: any, ...args: any[]) => receiver.Weekday(...$.stripGenericTypeArgs(args)), Year: (receiver: any, ...args: any[]) => receiver.Year(...$.stripGenericTypeArgs(args)), YearDay: (receiver: any, ...args: any[]) => receiver.YearDay(...$.stripGenericTypeArgs(args)), Zone: (receiver: any, ...args: any[]) => receiver.Zone(...$.stripGenericTypeArgs(args)), ZoneBounds: (receiver: any, ...args: any[]) => receiver.ZoneBounds(...$.stripGenericTypeArgs(args)), absSec: (receiver: any, ...args: any[]) => receiver.absSec(...$.stripGenericTypeArgs(args)), appendFormat: (receiver: any, ...args: any[]) => receiver.appendFormat(...$.stripGenericTypeArgs(args)), appendFormatRFC3339: (receiver: any, ...args: any[]) => receiver.appendFormatRFC3339(...$.stripGenericTypeArgs(args)), appendStrictRFC3339: (receiver: any, ...args: any[]) => receiver.appendStrictRFC3339(...$.stripGenericTypeArgs(args)), appendTo: (receiver: any, ...args: any[]) => receiver.appendTo(...$.stripGenericTypeArgs(args)), locabs: (receiver: any, ...args: any[]) => receiver.locabs(...$.stripGenericTypeArgs(args))} }}) + let t4 = reflect.TypeFor({[$.genericTypeArgsMarker]: true, T: { type: "time.Time", zero: () => $.markAsStructValue(new time.Time()), methods: {Add: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Add(...$.stripGenericTypeArgs(args)), AddDate: (receiver: any, ...args: any[]) => $.pointerValue(receiver).AddDate(...$.stripGenericTypeArgs(args)), After: (receiver: any, ...args: any[]) => $.pointerValue(receiver).After(...$.stripGenericTypeArgs(args)), AppendBinary: (receiver: any, ...args: any[]) => $.pointerValue(receiver).AppendBinary(...$.stripGenericTypeArgs(args)), AppendFormat: (receiver: any, ...args: any[]) => $.pointerValue(receiver).AppendFormat(...$.stripGenericTypeArgs(args)), AppendText: (receiver: any, ...args: any[]) => $.pointerValue(receiver).AppendText(...$.stripGenericTypeArgs(args)), Before: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Before(...$.stripGenericTypeArgs(args)), Clock: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Clock(...$.stripGenericTypeArgs(args)), Compare: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Compare(...$.stripGenericTypeArgs(args)), Date: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Date(...$.stripGenericTypeArgs(args)), Day: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Day(...$.stripGenericTypeArgs(args)), Equal: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Equal(...$.stripGenericTypeArgs(args)), Format: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Format(...$.stripGenericTypeArgs(args)), GoString: (receiver: any, ...args: any[]) => $.pointerValue(receiver).GoString(...$.stripGenericTypeArgs(args)), GobEncode: (receiver: any, ...args: any[]) => $.pointerValue(receiver).GobEncode(...$.stripGenericTypeArgs(args)), Hour: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Hour(...$.stripGenericTypeArgs(args)), ISOWeek: (receiver: any, ...args: any[]) => $.pointerValue(receiver).ISOWeek(...$.stripGenericTypeArgs(args)), In: (receiver: any, ...args: any[]) => $.pointerValue(receiver).In(...$.stripGenericTypeArgs(args)), IsDST: (receiver: any, ...args: any[]) => $.pointerValue(receiver).IsDST(...$.stripGenericTypeArgs(args)), IsZero: (receiver: any, ...args: any[]) => $.pointerValue(receiver).IsZero(...$.stripGenericTypeArgs(args)), Local: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Local(...$.stripGenericTypeArgs(args)), Location: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Location(...$.stripGenericTypeArgs(args)), MarshalBinary: (receiver: any, ...args: any[]) => $.pointerValue(receiver).MarshalBinary(...$.stripGenericTypeArgs(args)), MarshalJSON: (receiver: any, ...args: any[]) => $.pointerValue(receiver).MarshalJSON(...$.stripGenericTypeArgs(args)), MarshalText: (receiver: any, ...args: any[]) => $.pointerValue(receiver).MarshalText(...$.stripGenericTypeArgs(args)), Minute: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Minute(...$.stripGenericTypeArgs(args)), Month: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Month(...$.stripGenericTypeArgs(args)), Nanosecond: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Nanosecond(...$.stripGenericTypeArgs(args)), Round: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Round(...$.stripGenericTypeArgs(args)), Second: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Second(...$.stripGenericTypeArgs(args)), String: (receiver: any, ...args: any[]) => $.pointerValue(receiver).String(...$.stripGenericTypeArgs(args)), Sub: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Sub(...$.stripGenericTypeArgs(args)), Truncate: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Truncate(...$.stripGenericTypeArgs(args)), UTC: (receiver: any, ...args: any[]) => $.pointerValue(receiver).UTC(...$.stripGenericTypeArgs(args)), Unix: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Unix(...$.stripGenericTypeArgs(args)), UnixMicro: (receiver: any, ...args: any[]) => $.pointerValue(receiver).UnixMicro(...$.stripGenericTypeArgs(args)), UnixMilli: (receiver: any, ...args: any[]) => $.pointerValue(receiver).UnixMilli(...$.stripGenericTypeArgs(args)), UnixNano: (receiver: any, ...args: any[]) => $.pointerValue(receiver).UnixNano(...$.stripGenericTypeArgs(args)), Weekday: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Weekday(...$.stripGenericTypeArgs(args)), Year: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Year(...$.stripGenericTypeArgs(args)), YearDay: (receiver: any, ...args: any[]) => $.pointerValue(receiver).YearDay(...$.stripGenericTypeArgs(args)), Zone: (receiver: any, ...args: any[]) => $.pointerValue(receiver).Zone(...$.stripGenericTypeArgs(args)), ZoneBounds: (receiver: any, ...args: any[]) => $.pointerValue(receiver).ZoneBounds(...$.stripGenericTypeArgs(args)), absSec: (receiver: any, ...args: any[]) => $.pointerValue(receiver).absSec(...$.stripGenericTypeArgs(args)), appendFormat: (receiver: any, ...args: any[]) => $.pointerValue(receiver).appendFormat(...$.stripGenericTypeArgs(args)), appendFormatRFC3339: (receiver: any, ...args: any[]) => $.pointerValue(receiver).appendFormatRFC3339(...$.stripGenericTypeArgs(args)), appendStrictRFC3339: (receiver: any, ...args: any[]) => $.pointerValue(receiver).appendStrictRFC3339(...$.stripGenericTypeArgs(args)), appendTo: (receiver: any, ...args: any[]) => $.pointerValue(receiver).appendTo(...$.stripGenericTypeArgs(args)), locabs: (receiver: any, ...args: any[]) => $.pointerValue(receiver).locabs(...$.stripGenericTypeArgs(args))} }}) await $.println("TypeFor imported struct:", await $.pointerValue>(t4).String()) let t5 = reflect.TypeFor({[$.genericTypeArgsMarker]: true, T: { type: "main.OtherStruct", zero: () => $.markAsStructValue(new __goscript_other.OtherStruct()) }}) await $.println("TypeFor cross-file struct:", await $.pointerValue>(t5).String())