NotLebedev opened a new issue, #3503:
URL: https://github.com/apache/fory/issues/3503

   ### Search before asking
   
   - [x] I had searched in the [issues](https://github.com/apache/fory/issues) 
and found no similar issues.
   
   
   ### Version
   
   Fory 0.15.0 0.16.0
   JDK 21
   
   
   ### Component(s)
   
   Java
   
   ### Minimal reproduce step
   
   Running the following example
   ```java
   import org.apache.fory.Fory;
   import org.apache.fory.config.Language;
   
   import java.io.Serializable;
   import java.util.LinkedHashMap;
   import java.util.Map;
   
   class Scratch {
     public static void main(String[] args) {
       Fory fory = Fory.builder()
               .withLanguage(Language.JAVA)
               .requireClassRegistration(false)
               .withCodegen(true)
               .build();
   
       Object m = Outer.SOMETHING;
   
       fory.deserialize(fory.serialize(m));
     }
   }
   
   class Outer {
     public static MapWrapper SOMETHING = new MapWrapper(new LinkedHashMap<>());
   
     public static class MapWrapper implements Serializable {
       private final Map<String, Inner> m;
   
       private MapWrapper(Map<String, Inner> m) {
         this.m = m;
       }
     }
   
     private static final class Inner implements Serializable {
     }
   }
   ```
   
   ### What did you expect to see?
   
   This example is expected to run without crashing.
   
   ### What did you see instead?
   
   Instead example fails with 
   ```
   /* 0001 */ import org.apache.fory.Fory;
   /* 0002 */ import org.apache.fory.memory.MemoryBuffer;
   /* 0003 */ import org.apache.fory.resolver.NoRefResolver;
   /* 0004 */ import org.apache.fory.memory.Platform;
   /* 0005 */ import org.apache.fory.resolver.TypeInfo;
   /* 0006 */ import org.apache.fory.resolver.TypeInfoHolder;
   /* 0007 */ import org.apache.fory.resolver.ClassResolver;
   /* 0008 */ import org.apache.fory.builder.Generated;
   /* 0009 */ import 
org.apache.fory.serializer.CodegenSerializer.LazyInitBeanSerializer;
   /* 0010 */ import org.apache.fory.serializer.EnumSerializer;
   /* 0011 */ import org.apache.fory.serializer.Serializer;
   /* 0012 */ import org.apache.fory.serializer.StringSerializer;
   /* 0013 */ import org.apache.fory.serializer.ObjectSerializer;
   /* 0014 */ import org.apache.fory.serializer.MetaSharedSerializer;
   /* 0015 */ import 
org.apache.fory.serializer.collection.CollectionLikeSerializer;
   /* 0016 */ import org.apache.fory.serializer.collection.MapLikeSerializer;
   /* 0017 */ import 
org.apache.fory.builder.Generated.GeneratedObjectSerializer;
   /* 0018 */ 
   /* 0019 */ public final class Outer_MapWrapperForyCodec_0 extends 
GeneratedObjectSerializer {
   /* 0020 */   private static final Class __class__Outer$Inner;
   /* 0021 */ 
   /* 0022 */   static {
   /* 0023 */     try {
   /* 0024 */       __class__Outer$Inner = 
org.apache.fory.reflect.ReflectionUtils.loadClass("Outer$Inner");
   /* 0025 */     } catch (Throwable e) {
   /* 0026 */       e.printStackTrace();
   /* 0027 */       throw new RuntimeException(e);
   /* 0028 */     }
   /* 0029 */   }
   /* 0030 */ 
   /* 0031 */   private final NoRefResolver _f_refResolver;
   /* 0032 */   private final ClassResolver _f_typeResolver;
   /* 0033 */   private final StringSerializer _f_strSerializer;
   /* 0034 */   private Fory _f_fory;
   /* 0035 */   private TypeInfo mapTypeInfo;
   /* 0036 */   private final StringSerializer stringSerializer;
   /* 0037 */   private final Serializer serializer;
   /* 0038 */   private final TypeInfoHolder map2TypeInfoHolder;
   /* 0039 */ 
   /* 0040 */   public Outer_MapWrapperForyCodec_0(Fory _f_fory, Class 
_f_classType) {
   /* 0041 */       super(_f_fory, _f_classType);
   /* 0042 */       this._f_fory = _f_fory;
   /* 0043 */       
_f_fory.getTypeResolver().setSerializerIfAbsent(_f_classType, this);
   /* 0044 */   
   /* 0045 */       org.apache.fory.resolver.RefResolver refResolver = 
_f_fory.getRefResolver();
   /* 0046 */       _f_refResolver = ((NoRefResolver)refResolver);
   /* 0047 */       _f_typeResolver = 
((ClassResolver)_f_fory.getTypeResolver());
   /* 0048 */       _f_strSerializer = _f_fory.getStringSerializer();
   /* 0049 */       mapTypeInfo = _f_typeResolver.nilTypeInfo();
   /* 0050 */       stringSerializer = 
((StringSerializer)_f_typeResolver.getRawSerializer(java.lang.String.class));
   /* 0051 */       serializer = 
_f_typeResolver.getRawSerializer(__class__Outer$Inner);
   /* 0052 */       map2TypeInfoHolder = _f_typeResolver.nilTypeInfoHolder();
   /* 0053 */   }
   /* 0054 */ 
   /* 0055 */   private MapLikeSerializer writeMapTypeInfo(java.util.Map map1, 
MemoryBuffer memoryBuffer) {
   /* 0056 */       ClassResolver _f_typeResolver = this._f_typeResolver;
   /* 0057 */       Class value = mapTypeInfo.getCls();
   /* 0058 */       Class cls = map1.getClass();
   /* 0059 */       if ((value != cls)) {
   /* 0060 */           mapTypeInfo = _f_typeResolver.getTypeInfo(cls);
   /* 0061 */       }
   /* 0062 */       _f_typeResolver.writeTypeInfo(memoryBuffer, mapTypeInfo);
   /* 0063 */       return ((MapLikeSerializer)mapTypeInfo.getSerializer());
   /* 0064 */   }
   /* 0065 */ 
   /* 0066 */   private void writeFields(MemoryBuffer memoryBuffer1, 
Outer.MapWrapper mapWrapper1) {
   /* 0067 */       StringSerializer stringSerializer = this.stringSerializer;
   /* 0068 */       Serializer serializer = this.serializer;
   /* 0069 */       Object object1 = Platform.getObject(mapWrapper1, 12L);
   /* 0070 */       java.util.Map m0 = (java.util.Map)object1;
   /* 0071 */       if ((m0 == null)) {
   /* 0072 */           memoryBuffer1.writeByte(((byte)-3));
   /* 0073 */       } else {
   /* 0074 */           memoryBuffer1.writeByte(((byte)-1));
   /* 0075 */           MapLikeSerializer mapLikeSerializer = 
this.writeMapTypeInfo(m0, memoryBuffer1);
   /* 0076 */           if (mapLikeSerializer.supportCodegenHook()) {
   /* 0077 */               java.util.Map map0 = 
mapLikeSerializer.onMapWrite(memoryBuffer1, m0);
   /* 0078 */               if ((!map0.isEmpty())) {
   /* 0079 */                   java.util.Iterator iterator = 
map0.entrySet().iterator();
   /* 0080 */                   java.util.Map.Entry entry = 
(java.util.Map.Entry)iterator.next();
   /* 0081 */                   while ((entry != null)) {
   /* 0082 */                     entry = 
mapLikeSerializer.writeNullChunkKVFinalNoRef(memoryBuffer1, entry, iterator, 
stringSerializer, serializer);
   /* 0083 */                     if ((entry != null)) {
   /* 0084 */                         String key;
   /* 0085 */                         Outer.Inner value0;
   /* 0086 */                         memoryBuffer1.writeInt16(((short)-1));
   /* 0087 */                         int chunkSizeOffset = 
memoryBuffer1.writerIndex() - 1;
   /* 0088 */                         memoryBuffer1.putByte((chunkSizeOffset - 
1), 36);
   /* 0089 */                         int chunkSize = 0;
   /* 0090 */                         while (true) {
   /* 0091 */                           key = ((String)entry.getKey());
   /* 0092 */                           value0 = entry.getValue();
   /* 0093 */                           if (((key == null) || (value0 == 
null))) {
   /* 0094 */                               break;
   /* 0095 */                           }
   /* 0096 */                           
StringSerializer.writeBytesString(memoryBuffer1, key);
   /* 0097 */                           serializer.write(memoryBuffer1, value0);
   /* 0098 */                           chunkSize = (chunkSize + 1);
   /* 0099 */                           if (iterator.hasNext()) {
   /* 0100 */                               entry = 
((java.util.Map.Entry)iterator.next());
   /* 0101 */                           } else {
   /* 0102 */                               entry = null;
   /* 0103 */                               break;
   /* 0104 */                           }
   /* 0105 */                           if ((chunkSize == 255)) {
   /* 0106 */                               break;
   /* 0107 */                           }
   /* 0108 */                         }
   /* 0109 */                         memoryBuffer1.putByte(chunkSizeOffset, 
chunkSize);
   /* 0110 */                     }
   /* 0111 */                   }
   /* 0112 */               }
   /* 0113 */               mapLikeSerializer.onMapWriteFinish(map0);
   /* 0114 */           } else {
   /* 0115 */               mapLikeSerializer.write(memoryBuffer1, m0);
   /* 0116 */           }
   /* 0117 */       }
   /* 0118 */   }
   /* 0119 */ 
   /* 0120 */   private void readMapChunks(MemoryBuffer memoryBuffer2, 
java.util.Map map3, int value2, int value3, Serializer serializer1, 
MapLikeSerializer mapLikeSerializer0, StringSerializer stringSerializer1) {
   /* 0121 */       Fory _f_fory = this._f_fory;
   /* 0122 */       while ((value2 > 0)) {
   /* 0123 */         long sizeAndHeader = 
mapLikeSerializer0.readNullChunkKVFinalNoRef(memoryBuffer2, map3, value3, 
value2, stringSerializer1, serializer1);
   /* 0124 */         value3 = ((int)(sizeAndHeader & 255));
   /* 0125 */         value2 = ((int)(sizeAndHeader >>> 8));
   /* 0126 */         if ((value2 == 0)) {
   /* 0127 */             break;
   /* 0128 */         }
   /* 0129 */         int chunkSize0 = memoryBuffer2.readUnsignedByte();
   /* 0130 */         for (int i = 0; i < chunkSize0; i+=1) {
   /* 0131 */           String string = 
_f_strSerializer.readBytesString(memoryBuffer2);
   /* 0132 */           _f_fory.incReadDepth();
   /* 0133 */           Object object0 = serializer1.read(memoryBuffer2);
   /* 0134 */           _f_fory.decDepth();
   /* 0135 */           map3.put(string, object0);
   /* 0136 */           value2 = (value2 - 1);
   /* 0137 */         }
   /* 0138 */         if ((value2 > 0)) {
   /* 0139 */             value3 = memoryBuffer2.readUnsignedByte();
   /* 0140 */         }
   /* 0141 */       }
   /* 0142 */   }
   /* 0143 */ 
   /* 0144 */   private void readFields(MemoryBuffer memoryBuffer3, 
Outer.MapWrapper mapWrapper2) {
   /* 0145 */       Fory _f_fory = this._f_fory;
   /* 0146 */       if ((memoryBuffer3.readByte() != ((byte)-3))) {
   /* 0147 */           MapLikeSerializer mapSerializer = 
(MapLikeSerializer)_f_typeResolver.readTypeInfo(memoryBuffer3, 
map2TypeInfoHolder).getSerializer();
   /* 0148 */           Object object3;
   /* 0149 */           if (mapSerializer.supportCodegenHook()) {
   /* 0150 */               java.util.Map map4 = 
mapSerializer.newMap(memoryBuffer3);
   /* 0151 */               int size = mapSerializer.getAndClearNumElements();
   /* 0152 */               int value4;
   /* 0153 */               if ((size == 0)) {
   /* 0154 */                   value4 = 0;
   /* 0155 */               } else {
   /* 0156 */                   value4 = memoryBuffer3.readUnsignedByte();
   /* 0157 */               }
   /* 0158 */               this.readMapChunks(memoryBuffer3, map4, size, 
value4, serializer, mapSerializer, stringSerializer);
   /* 0159 */               object3 = mapSerializer.onMapRead(map4);
   /* 0160 */           } else {
   /* 0161 */               _f_fory.incReadDepth();
   /* 0162 */               Object object2 = mapSerializer.read(memoryBuffer3);
   /* 0163 */               _f_fory.decDepth();
   /* 0164 */               object3 = object2;
   /* 0165 */           }
   /* 0166 */           
   /* 0167 */           Platform.putObject(mapWrapper2, 12L, 
((java.util.Map)object3));
   /* 0168 */       } else {
   /* 0169 */           Platform.putObject(mapWrapper2, 12L, null);
   /* 0170 */       }
   /* 0171 */   }
   /* 0172 */ 
   /* 0173 */   @Override public final void write(MemoryBuffer _f_buffer, 
Object _f_obj) {
   /* 0174 */       Outer.MapWrapper mapWrapper3 = (Outer.MapWrapper)_f_obj;
   /* 0175 */       this.writeFields(_f_buffer, mapWrapper3);
   /* 0176 */   }
   /* 0177 */ 
   /* 0178 */   @Override public final Object read(MemoryBuffer _f_buffer) {
   /* 0179 */       Object instance = 
Platform.newInstance(Outer$MapWrapper.class);
   /* 0180 */       Outer.MapWrapper mapWrapper4 = (Outer.MapWrapper)instance;
   /* 0181 */       _f_refResolver.reference(mapWrapper4);
   /* 0182 */       this.readFields(_f_buffer, mapWrapper4);
   /* 0183 */       return mapWrapper4;
   /* 0184 */   }
   /* 0185 */ 
   /* 0186 */ }
   
   org.apache.fory.shaded.org.codehaus.commons.compiler.CompileException File 
'/Outer_MapWrapperForyCodec_0.java', Line 92, Column 27: Assignment conversion 
not possible from type "java.lang.Object" to type "Outer$Inner"
   ```
   Running with `withCodegen(false)` works as expected. Removing `final` 
qualifier from `Inner` class works as expected.
   
   The same failure happens if `Inner` is key of map.
   
   ### Anything Else?
   
   Managed to race this problem to 
[`BaseObjectCodecBuilder.writeChunk`](https://github.com/apache/fory/blob/f4cfd62d3bd038e9028d5b0d3ed6b22df0b5ddd6/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java#L1515).
 When `Inner` class is `final`  variable `boolean valueMonomorphic = 
isMonomorphic(valueType);` is true. This changes `value` expression 
[here](https://github.com/apache/fory/blob/f4cfd62d3bd038e9028d5b0d3ed6b22df0b5ddd6/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java#L1520)
 and later inside while loop and assignment `value0 = entry.getValue();` is 
missing cast to `Outer.Inner` which results in "Assignment conversion not 
possible" error.
   
   ### Are you willing to submit a PR?
   
   - [x] I'm willing to submit a PR!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to