From b979d41ec5d1a28658dafa1fb188dd51e52126b3 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 30 Aug 2026 01:56:01 +0000 Subject: [PATCH 1/4] Fix ShapeTag generation to omit '?' suffix for non-blittable types --- src/ZeroSerializerGenerator.cs | 7 ++++++- tests/ShapeTagAndHashTests.cs | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index 53c9e9a..ab4dbf1 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1736,7 +1736,12 @@ private static void CreateShapeTag(ITypeSymbol typeSymbol, StringBuilder shapeTa { var underlying = nullableType.TypeArguments[0]; CreateShapeTag(underlying, shapeTagBuilder); - shapeTagBuilder.Append('?'); + if (underlying is not INamedTypeSymbol namedUnderlying + || namedUnderlying.TypeKind != TypeKind.Struct + || TryGetBlittableStructByteCount(namedUnderlying, out _)) + { + shapeTagBuilder.Append('?'); + } return; } diff --git a/tests/ShapeTagAndHashTests.cs b/tests/ShapeTagAndHashTests.cs index 6a7e9bb..e2b07e5 100644 --- a/tests/ShapeTagAndHashTests.cs +++ b/tests/ShapeTagAndHashTests.cs @@ -48,7 +48,7 @@ public void EnumClassViewTest() [Fact] public void SchemaSignatureTestsModelViewTest() { - string schemaSignatureExpected = "v1/{blittable{int,enum:short},{int,enum:byte},blittable{int,enum:short}[],{},blittable{},{enum:byte,enum:short}?,enum:byte[],enum:ulong[],int?,bool?}"; + string schemaSignatureExpected = "v1/{blittable{int,enum:short},{int,enum:byte},blittable{int,enum:short}[],{},blittable{},{enum:byte,enum:short},enum:byte[],enum:ulong[],int?,bool?}"; Assert.Equal(SchemaSignatureTestsModelView.ShapeTag, schemaSignatureExpected); Assert.Equal(SchemaSignatureTestsModelView.ShapeHash, XXHash32.HashToUInt32(schemaSignatureExpected)); } From 47710296f450026c26ec96d00a8e88239bdc4547 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 30 Aug 2026 02:07:06 +0000 Subject: [PATCH 2/4] Refactor ShapeTag nullable struct check to target blittable structs --- src/ZeroSerializerGenerator.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index ab4dbf1..836f8d8 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1736,9 +1736,14 @@ private static void CreateShapeTag(ITypeSymbol typeSymbol, StringBuilder shapeTa { var underlying = nullableType.TypeArguments[0]; CreateShapeTag(underlying, shapeTagBuilder); - if (underlying is not INamedTypeSymbol namedUnderlying - || namedUnderlying.TypeKind != TypeKind.Struct - || TryGetBlittableStructByteCount(namedUnderlying, out _)) + if (underlying is INamedTypeSymbol namedUnderlying && namedUnderlying.TypeKind == TypeKind.Struct) + { + if (TryGetBlittableStructByteCount(namedUnderlying, out _)) + { + shapeTagBuilder.Append('?'); + } + } + else { shapeTagBuilder.Append('?'); } From 12580ebca6be6a116097286862c0091f75180149 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 30 Aug 2026 02:10:02 +0000 Subject: [PATCH 3/4] Refactor ShapeTag nullable check to explicitly detect non-blittable structs --- src/ZeroSerializerGenerator.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index 836f8d8..3d46316 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1736,14 +1736,7 @@ private static void CreateShapeTag(ITypeSymbol typeSymbol, StringBuilder shapeTa { var underlying = nullableType.TypeArguments[0]; CreateShapeTag(underlying, shapeTagBuilder); - if (underlying is INamedTypeSymbol namedUnderlying && namedUnderlying.TypeKind == TypeKind.Struct) - { - if (TryGetBlittableStructByteCount(namedUnderlying, out _)) - { - shapeTagBuilder.Append('?'); - } - } - else + if (!IsNonBlittableStruct(underlying)) { shapeTagBuilder.Append('?'); } @@ -1810,6 +1803,13 @@ private static void CreateShapeTag(ITypeSymbol typeSymbol, StringBuilder shapeTa shapeTagBuilder.Append(UnknownShapeTagType); } + private static bool IsNonBlittableStruct(ITypeSymbol typeSymbol) + { + return typeSymbol.TypeKind == TypeKind.Struct + && GetPrimitiveKeyword(typeSymbol).Length == 0 + && !TryGetFixedTypeByteCount(typeSymbol, new HashSet(SymbolEqualityComparer.Default), out _); + } + private static string GetPrimitiveKeyword(ITypeSymbol? typeSymbol) { return typeSymbol?.SpecialType switch From 41801cc9ec7902c879e19a915717b8be21ea90c9 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 30 Aug 2026 02:17:53 +0000 Subject: [PATCH 4/4] Simplify ShapeTag nullable check for non-blittable structs --- src/ZeroSerializerGenerator.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index 3d46316..af0151e 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1736,10 +1736,11 @@ private static void CreateShapeTag(ITypeSymbol typeSymbol, StringBuilder shapeTa { var underlying = nullableType.TypeArguments[0]; CreateShapeTag(underlying, shapeTagBuilder); - if (!IsNonBlittableStruct(underlying)) + if (underlying is INamedTypeSymbol named && named.TypeKind == TypeKind.Struct && !TryGetBlittableStructByteCount(named, out _)) { - shapeTagBuilder.Append('?'); + return; } + shapeTagBuilder.Append('?'); return; } @@ -1803,13 +1804,6 @@ private static void CreateShapeTag(ITypeSymbol typeSymbol, StringBuilder shapeTa shapeTagBuilder.Append(UnknownShapeTagType); } - private static bool IsNonBlittableStruct(ITypeSymbol typeSymbol) - { - return typeSymbol.TypeKind == TypeKind.Struct - && GetPrimitiveKeyword(typeSymbol).Length == 0 - && !TryGetFixedTypeByteCount(typeSymbol, new HashSet(SymbolEqualityComparer.Default), out _); - } - private static string GetPrimitiveKeyword(ITypeSymbol? typeSymbol) { return typeSymbol?.SpecialType switch