Preserve 'has bit' data in proto field types

Bug: 158623350
Change-Id: I64645af6ac40d92ffef39527b43fef59316f869a
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/RawMessageInfoDecoder.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/RawMessageInfoDecoder.java
index e4741d9..363a2de 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/RawMessageInfoDecoder.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/RawMessageInfoDecoder.java
@@ -7,6 +7,7 @@
 import static com.android.tools.r8.ir.analysis.proto.ProtoUtils.getInfoValueFromMessageInfoConstructionInvoke;
 import static com.android.tools.r8.ir.analysis.proto.ProtoUtils.getObjectsValueFromMessageInfoConstructionInvoke;
 
+import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexReference;
@@ -152,6 +153,10 @@
         int fieldNumber = infoIterator.nextIntComputeIfAbsent(this::invalidInfoFailure);
         int fieldTypeWithExtraBits = infoIterator.nextIntComputeIfAbsent(this::invalidInfoFailure);
         ProtoFieldType fieldType = factory.createField(fieldTypeWithExtraBits);
+        if (fieldType.serialize() != fieldTypeWithExtraBits) {
+          throw new CompilationError(
+              "Unexpected proto field type `" + fieldTypeWithExtraBits + "`");
+        }
 
         OptionalInt auxData;
         if (fieldType.hasAuxData(isProto2)) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoFieldType.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoFieldType.java
index 211589a..39419b4 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoFieldType.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoFieldType.java
@@ -25,24 +25,28 @@
   private static final int FIELD_ENFORCE_UTF8_MASK = 0x200;
   private static final int FIELD_NEEDS_IS_INITIALIZED_CHECK_MASK = 0x400;
   private static final int FIELD_IS_MAP_FIELD_WITH_PROTO_2_ENUM_VALUE_MASK = 0x800;
+  private static final int FIELD_HAS_HAS_BIT_MASK = 0x1000;
 
   private final int id;
   private final boolean isRequired;
   private final boolean enforceUtf8Mask;
   private final boolean needsIsInitializedCheck;
   private final boolean isMapFieldWithProto2EnumValue;
+  private final boolean hasHasBit;
 
   ProtoFieldType(
       int id,
       boolean isRequired,
       boolean enforceUtf8Mask,
       boolean needsIsInitializedCheck,
-      boolean isMapFieldWithProto2EnumValue) {
+      boolean isMapFieldWithProto2EnumValue,
+      boolean hasHasBit) {
     this.id = id;
     this.isRequired = isRequired;
     this.enforceUtf8Mask = enforceUtf8Mask;
     this.needsIsInitializedCheck = needsIsInitializedCheck;
     this.isMapFieldWithProto2EnumValue = isMapFieldWithProto2EnumValue;
+    this.hasHasBit = hasHasBit;
     assert isValid();
   }
 
@@ -54,14 +58,16 @@
           isBitInMaskSet(fieldTypeWithExtraBits, FIELD_IS_REQUIRED_MASK),
           isBitInMaskSet(fieldTypeWithExtraBits, FIELD_ENFORCE_UTF8_MASK),
           isBitInMaskSet(fieldTypeWithExtraBits, FIELD_NEEDS_IS_INITIALIZED_CHECK_MASK),
-          isBitInMaskSet(fieldTypeWithExtraBits, FIELD_IS_MAP_FIELD_WITH_PROTO_2_ENUM_VALUE_MASK));
+          isBitInMaskSet(fieldTypeWithExtraBits, FIELD_IS_MAP_FIELD_WITH_PROTO_2_ENUM_VALUE_MASK),
+          isBitInMaskSet(fieldTypeWithExtraBits, FIELD_HAS_HAS_BIT_MASK));
     } else {
       return new ProtoOneOfFieldType(
           fieldTypeWithExtraBits & FIELD_ID_MASK,
           isBitInMaskSet(fieldTypeWithExtraBits, FIELD_IS_REQUIRED_MASK),
           isBitInMaskSet(fieldTypeWithExtraBits, FIELD_ENFORCE_UTF8_MASK),
           isBitInMaskSet(fieldTypeWithExtraBits, FIELD_NEEDS_IS_INITIALIZED_CHECK_MASK),
-          isBitInMaskSet(fieldTypeWithExtraBits, FIELD_IS_MAP_FIELD_WITH_PROTO_2_ENUM_VALUE_MASK));
+          isBitInMaskSet(fieldTypeWithExtraBits, FIELD_IS_MAP_FIELD_WITH_PROTO_2_ENUM_VALUE_MASK),
+          isBitInMaskSet(fieldTypeWithExtraBits, FIELD_HAS_HAS_BIT_MASK));
     }
   }
 
@@ -156,6 +162,9 @@
     if (isMapFieldWithProto2EnumValue) {
       result |= FIELD_IS_MAP_FIELD_WITH_PROTO_2_ENUM_VALUE_MASK;
     }
+    if (hasHasBit) {
+      result |= FIELD_HAS_HAS_BIT_MASK;
+    }
     return result;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoOneOfFieldType.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoOneOfFieldType.java
index 6ddef35..1bc2ab5 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoOneOfFieldType.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoOneOfFieldType.java
@@ -15,8 +15,15 @@
       boolean isRequired,
       boolean enforceUtf8Mask,
       boolean needsIsInitializedCheck,
-      boolean isMapFieldWithProto2EnumValue) {
-    super(id, isRequired, enforceUtf8Mask, needsIsInitializedCheck, isMapFieldWithProto2EnumValue);
+      boolean isMapFieldWithProto2EnumValue,
+      boolean hasHasBit) {
+    super(
+        id,
+        isRequired,
+        enforceUtf8Mask,
+        needsIsInitializedCheck,
+        isMapFieldWithProto2EnumValue,
+        hasHasBit);
   }
 
   public ProtoFieldType getActualFieldType(ProtoFieldTypeFactory factory) {