diff --git a/AyCode.Core.Serializers.SourceGenerator/AcBinarySourceGenerator.cs b/AyCode.Core.Serializers.SourceGenerator/AcBinarySourceGenerator.cs
index 35a4b01..dbc9369 100644
--- a/AyCode.Core.Serializers.SourceGenerator/AcBinarySourceGenerator.cs
+++ b/AyCode.Core.Serializers.SourceGenerator/AcBinarySourceGenerator.cs
@@ -53,6 +53,33 @@ public class AcBinarySourceGenerator : IIncrementalGenerator
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);
+ ///
+ /// ACCORE-BIN-I-T7K3 compile-time guard: a property declared as System.Object requires
+ /// polymorphic-prefix emit (ObjectWithTypeName) so the deserializer can resolve the
+ /// concrete runtime type. When is false, the prefix is
+ /// suppressed and the wire silently corrupts on round-trip (FixObj slot byte against
+ /// typeof(object) at read-time → 0-byte object wrapper → reader position drifts →
+ /// downstream DECIMAL_DRIFT / IndexOutOfRangeException).
+ ///
+ /// Surface the misconfiguration at build time so the silent corruption is structurally
+ /// impossible. Three escape hatches for the developer:
+ /// 1. Enable the polymorphic feature ( = true, or — once the
+ /// planned [AcBinarySerializable(EnablePolymorphicFeature = true)] flag lands — set
+ /// it on the type).
+ /// 2. Change the property type to a concrete type (no polymorphism needed).
+ /// 3. Mark the property with [AcBinaryIgnore] — ignored properties are filtered
+ /// out at property enumeration, so this diagnostic does not fire for them.
+ ///
+ private static readonly DiagnosticDescriptor PolymorphicPropertyWithFeatureDisabledError = new(
+ id: "ACBIN002",
+ title: "Polymorphic property requires polymorphic feature enabled",
+ messageFormat: "Type '{0}' contains property '{1}' declared as System.Object, but polymorphic serialization in the source generator is disabled (UsePolymorphType=false). " +
+ "The generated writer would silently corrupt the wire on round-trip. " +
+ "To fix: (1) enable polymorphic serialization, (2) change '{1}' to a concrete type, or (3) exclude it with [AcBinaryIgnore].",
+ category: "AcBinarySerializer",
+ defaultSeverity: DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var classDeclarations = context.SyntaxProvider
@@ -406,6 +433,7 @@ public class AcBinarySourceGenerator : IIncrementalGenerator
if (valid.Count == 0) return;
DetectAndReportCycles(valid, context);
+ DetectAndReportPolymorphicMisuse(valid, context);
foreach (var ci in valid)
{
@@ -416,6 +444,30 @@ public class AcBinarySourceGenerator : IIncrementalGenerator
context.AddSource("AcBinaryGeneratedWriters_Init.g.cs", SourceText.From(GenInit(valid), Encoding.UTF8));
}
+ ///
+ /// ACCORE-BIN-I-T7K3 guard: emits
+ /// (ACBIN002) for every System.Object-declared property on any
+ /// [AcBinarySerializable] type while is false.
+ /// Short-circuits when the feature is enabled — no per-property work needed.
+ ///
+ private static void DetectAndReportPolymorphicMisuse(List classes, SourceProductionContext spc)
+ {
+ if (UsePolymorphType) return; // Feature enabled → polymorphic prefix is emitted, no misuse possible.
+
+ foreach (var ci in classes)
+ {
+ foreach (var p in ci.Properties)
+ {
+ if (p.IsObjectDeclaredType)
+ {
+ spc.ReportDiagnostic(Diagnostic.Create(
+ PolymorphicPropertyWithFeatureDisabledError, Location.None,
+ ci.ClassName, p.Name));
+ }
+ }
+ }
+ }
+
///
/// Detects circular reference chains among [AcBinarySerializable] types at compile time
/// and reports ACBIN001 warnings. Uses DFS with 3-color marking to find back-edges.