Remove type check function for repeated fields (#198)

diff --git a/protobuf/CHANGELOG.md b/protobuf/CHANGELOG.md
index 34752a5..ffba15a 100644
--- a/protobuf/CHANGELOG.md
+++ b/protobuf/CHANGELOG.md
@@ -1,10 +1,17 @@
+## 0.13.4
+
+* Add new method `pc` on BuilderInfo for adding repeated composite fields and remove redundant type check on items added
+  to a PbList.
+
+  Deprecated `BuilderInfo.pp` and `PbList.forFieldType`.
+
 ## 0.13.3
 
 * Fix issue with parsing map field entries. The values for two different keys would sometimes be
   merged.
   
 * Deprecated `PBMap.add`.
-  
+
 ## 0.13.2
 
 * Include extension fields in GeneratedMessage.toString().
diff --git a/protobuf/lib/src/protobuf/builder_info.dart b/protobuf/lib/src/protobuf/builder_info.dart
index c63c2b1..d626c16 100644
--- a/protobuf/lib/src/protobuf/builder_info.dart
+++ b/protobuf/lib/src/protobuf/builder_info.dart
@@ -113,13 +113,24 @@
   }
 
   // Repeated message, group, or enum.
+  void pc<T>(int tagNumber, String name, int fieldType,
+      [CreateBuilderFunc subBuilder,
+      ValueOfFunc valueOf,
+      List<ProtobufEnum> enumValues]) {
+    assert(_isGroupOrMessage(fieldType) || _isEnum(fieldType));
+    addRepeated<T>(tagNumber, name, fieldType, _checkNotNull, subBuilder,
+        valueOf, enumValues);
+  }
+
+  @Deprecated('Use [pc] instead. The given [check] function is ignored.'
+      'This function will be removed in the next major version.')
   void pp<T>(int tagNumber, String name, int fieldType, CheckFunc<T> check,
       [CreateBuilderFunc subBuilder,
       ValueOfFunc valueOf,
       List<ProtobufEnum> enumValues]) {
     assert(_isGroupOrMessage(fieldType) || _isEnum(fieldType));
-    addRepeated<T>(
-        tagNumber, name, fieldType, check, subBuilder, valueOf, enumValues);
+    addRepeated<T>(tagNumber, name, fieldType, _checkNotNull, subBuilder,
+        valueOf, enumValues);
   }
 
   // oneof declarations.
diff --git a/protobuf/lib/src/protobuf/field_error.dart b/protobuf/lib/src/protobuf/field_error.dart
index 7644653..0a84df7 100644
--- a/protobuf/lib/src/protobuf/field_error.dart
+++ b/protobuf/lib/src/protobuf/field_error.dart
@@ -73,29 +73,17 @@
 
 /// Returns a function for validating items in a repeated field.
 ///
-/// For enum, group, and message fields, the check is only approximate,
-/// because the exact type isn't included in [fieldType].
+/// For most types this is a not-null check, except for floats, and signed and
+/// unsigned 32 bit ints where there also is a range check.
 CheckFunc getCheckFunction(int fieldType) {
   switch (fieldType & ~0x7) {
     case PbFieldType._BOOL_BIT:
-      return _checkBool;
     case PbFieldType._BYTES_BIT:
-      return _checkBytes;
     case PbFieldType._STRING_BIT:
-      return _checkString;
-    case PbFieldType._FLOAT_BIT:
-      return _checkFloat;
     case PbFieldType._DOUBLE_BIT:
-      return _checkDouble;
-
-    case PbFieldType._INT32_BIT:
-    case PbFieldType._SINT32_BIT:
-    case PbFieldType._SFIXED32_BIT:
-      return _checkSigned32;
-
-    case PbFieldType._UINT32_BIT:
-    case PbFieldType._FIXED32_BIT:
-      return _checkUnsigned32;
+    case PbFieldType._ENUM_BIT:
+    case PbFieldType._GROUP_BIT:
+    case PbFieldType._MESSAGE_BIT:
 
     case PbFieldType._INT64_BIT:
     case PbFieldType._SINT64_BIT:
@@ -105,13 +93,19 @@
       // We always use the full range of the same Dart type.
       // It's up to the caller to treat the Int64 as signed or unsigned.
       // See: https://github.com/dart-lang/protobuf/issues/44
-      return _checkAnyInt64;
+      return _checkNotNull;
 
-    case PbFieldType._ENUM_BIT:
-      return _checkAnyEnum;
-    case PbFieldType._GROUP_BIT:
-    case PbFieldType._MESSAGE_BIT:
-      return _checkAnyMessage;
+    case PbFieldType._FLOAT_BIT:
+      return _checkFloat;
+
+    case PbFieldType._INT32_BIT:
+    case PbFieldType._SINT32_BIT:
+    case PbFieldType._SFIXED32_BIT:
+      return _checkSigned32;
+
+    case PbFieldType._UINT32_BIT:
+    case PbFieldType._FIXED32_BIT:
+      return _checkUnsigned32;
   }
   throw new ArgumentError('check function not implemented: ${fieldType}');
 }
@@ -124,60 +118,20 @@
   }
 }
 
-void _checkBool(Object val) {
-  if (val is! bool) throw _createFieldTypeError(val, 'a bool');
-}
-
-void _checkBytes(Object val) {
-  if (val is! List<int>) throw _createFieldTypeError(val, 'a List<int>');
-}
-
-void _checkString(Object val) {
-  if (val is! String) throw _createFieldTypeError(val, 'a String');
-}
-
 void _checkFloat(Object val) {
-  _checkDouble(val);
   if (!_isFloat32(val)) throw _createFieldRangeError(val, 'a float');
 }
 
-void _checkDouble(Object val) {
-  if (val is! double) throw _createFieldTypeError(val, 'a double');
-}
-
-void _checkInt(Object val) {
-  if (val is! int) throw _createFieldTypeError(val, 'an int');
-}
-
 void _checkSigned32(Object val) {
-  _checkInt(val);
   if (!_isSigned32(val)) throw _createFieldRangeError(val, 'a signed int32');
 }
 
 void _checkUnsigned32(Object val) {
-  _checkInt(val);
   if (!_isUnsigned32(val)) {
     throw _createFieldRangeError(val, 'an unsigned int32');
   }
 }
 
-void _checkAnyInt64(Object val) {
-  if (val is! Int64) throw _createFieldTypeError(val, 'an Int64');
-}
-
-void _checkAnyEnum(Object val) {
-  if (val is! ProtobufEnum) throw _createFieldTypeError(val, 'a ProtobufEnum');
-}
-
-void _checkAnyMessage(Object val) {
-  if (val is! GeneratedMessage) {
-    throw _createFieldTypeError(val, 'a GeneratedMessage');
-  }
-}
-
-ArgumentError _createFieldTypeError(val, String wantedType) =>
-    new ArgumentError('Value ($val) is not ${wantedType}');
-
 RangeError _createFieldRangeError(val, String wantedType) =>
     new RangeError('Value ($val) is not ${wantedType}');
 
diff --git a/protobuf/lib/src/protobuf/field_type.dart b/protobuf/lib/src/protobuf/field_type.dart
index 4705895..b1f6485 100644
--- a/protobuf/lib/src/protobuf/field_type.dart
+++ b/protobuf/lib/src/protobuf/field_type.dart
@@ -67,7 +67,7 @@
 
   // Closures commonly used by initializers.
   static String _STRING_EMPTY() => '';
-  static List<int> _BYTES_EMPTY() => new PbList<int>(check: _checkInt);
+  static List<int> _BYTES_EMPTY() => <int>[];
   static bool _BOOL_FALSE() => false;
   static int _INT_ZERO() => 0;
   static double _DOUBLE_ZERO() => 0.0;
diff --git a/protobuf/lib/src/protobuf/pb_list.dart b/protobuf/lib/src/protobuf/pb_list.dart
index 7c2c1c3..e8a23e4 100644
--- a/protobuf/lib/src/protobuf/pb_list.dart
+++ b/protobuf/lib/src/protobuf/pb_list.dart
@@ -48,6 +48,8 @@
 
   PbList.from(List from) : super._from(from);
 
+  @Deprecated('Instead use the default constructor with a check function.'
+      'This constructor will be removed in the next major version.')
   PbList.forFieldType(int fieldType)
       : super._noList(check: getCheckFunction(fieldType));
 
@@ -57,7 +59,7 @@
   /// Adds [value] at the end of the list, extending the length by one.
   /// Throws an [UnsupportedError] if the list is not extendable.
   void add(E value) {
-    _validate(value);
+    check(value);
     _wrappedList.add(value);
   }
 
@@ -65,7 +67,7 @@
   /// Extends the length of the list by the length of [collection].
   /// Throws an [UnsupportedError] if the list is not extendable.
   void addAll(Iterable<E> collection) {
-    collection.forEach(_validate);
+    collection.forEach(check);
     _wrappedList.addAll(collection);
   }
 
@@ -85,7 +87,7 @@
   /// Inserts a new element in the list.
   /// The element must be valid (and not nullable) for the PbList type.
   void insert(int index, E element) {
-    _validate(element);
+    check(element);
     _wrappedList.insert(index, element);
   }
 
@@ -93,7 +95,7 @@
   ///
   /// Elements in [iterable] must be valid and not nullable for the PbList type.
   void insertAll(int index, Iterable<E> iterable) {
-    iterable.forEach(_validate);
+    iterable.forEach(check);
     _wrappedList.insertAll(index, iterable);
   }
 
@@ -102,7 +104,7 @@
   ///
   /// Elements in [iterable] must be valid and not nullable for the PbList type.
   void setAll(int index, Iterable<E> iterable) {
-    iterable.forEach(_validate);
+    iterable.forEach(check);
     _wrappedList.setAll(index, iterable);
   }
 
@@ -127,7 +129,7 @@
   void setRange(int start, int end, Iterable<E> from, [int skipCount = 0]) {
     // NOTE: In case `take()` returns less than `end - start` elements, the
     // _wrappedList will fail with a `StateError`.
-    from.skip(skipCount).take(end - start).forEach(_validate);
+    from.skip(skipCount).take(end - start).forEach(check);
     _wrappedList.setRange(start, end, from, skipCount);
   }
 
@@ -137,7 +139,7 @@
   /// Sets the objects in the range [start] inclusive to [end] exclusive to the
   /// given [fillValue].
   void fillRange(int start, int end, [E fillValue]) {
-    _validate(fillValue);
+    check(fillValue);
     _wrappedList.fillRange(start, end, fillValue);
   }
 
@@ -145,7 +147,7 @@
   /// inserts the contents of [replacement] in its place.
   void replaceRange(int start, int end, Iterable<E> replacement) {
     final values = replacement.toList();
-    replacement.forEach(_validate);
+    replacement.forEach(check);
     _wrappedList.replaceRange(start, end, values);
   }
 }
@@ -308,7 +310,7 @@
   /// Throws an [IndexOutOfRangeException] if [index] is out of bounds.
   @override
   void operator []=(int index, E value) {
-    _validate(value);
+    check(value);
     _wrappedList[index] = value;
   }
 
@@ -323,12 +325,4 @@
     }
     _wrappedList.length = newLength;
   }
-
-  void _validate(E val) {
-    check(val);
-    // TODO: remove after migration to check functions is finished
-    if (val is! E) {
-      throw new ArgumentError('Value ($val) is not of the correct type');
-    }
-  }
 }
diff --git a/protobuf/pubspec.yaml b/protobuf/pubspec.yaml
index c53dbc9..856e999 100644
--- a/protobuf/pubspec.yaml
+++ b/protobuf/pubspec.yaml
@@ -1,5 +1,5 @@
 name: protobuf
-version: 0.13.3
+version: 0.13.4
 author: Dart Team <misc@dartlang.org>
 description: >
   Runtime library for protocol buffers support.
diff --git a/protobuf/test/list_test.dart b/protobuf/test/list_test.dart
index 0926c4d..8352564 100755
--- a/protobuf/test/list_test.dart
+++ b/protobuf/test/list_test.dart
@@ -99,7 +99,7 @@
   });
 
   test('PbList for signed int32 validates items', () {
-    var list = new PbList.forFieldType(PbFieldType.P3);
+    List<int> list = new PbList(check: getCheckFunction(PbFieldType.P3));
 
     expect(() {
       list.add(-2147483649);
@@ -119,7 +119,7 @@
   });
 
   test('PBList for unsigned int32 validates items', () {
-    var list = new PbList.forFieldType(PbFieldType.PU3);
+    List<int> list = new PbList(check: getCheckFunction(PbFieldType.PU3));
 
     expect(() {
       list.add(-1);
@@ -139,7 +139,7 @@
   });
 
   test('PbList for float validates items', () {
-    var list = new PbList.forFieldType(PbFieldType.PF);
+    List<double> list = new PbList(check: getCheckFunction(PbFieldType.PF));
 
     expect(() {
       list.add(3.4028234663852886E39);
@@ -159,7 +159,7 @@
   });
 
   test('PbList for signed Int64 validates items', () {
-    var list = new PbList.forFieldType(PbFieldType.P6);
+    List<Int64> list = new PbList();
     expect(() {
       list.add(cast(0)); // not an Int64
     }, badArgument);
@@ -178,7 +178,7 @@
   });
 
   test('PbList for unsigned Int64 validates items', () {
-    var list = new PbList.forFieldType(PbFieldType.PU6);
+    List<Int64> list = new PbList();
     expect(() {
       list.add(cast(0)); // not an Int64
     }, badArgument);
diff --git a/protobuf/test/readonly_message_test.dart b/protobuf/test/readonly_message_test.dart
index 3b2589a..05f447a 100644
--- a/protobuf/test/readonly_message_test.dart
+++ b/protobuf/test/readonly_message_test.dart
@@ -31,7 +31,7 @@
   @override
   BuilderInfo info_ = new BuilderInfo('rec')
     ..a(1, 'value', PbFieldType.O3)
-    ..pp<Rec>(2, 'sub', PbFieldType.PM, (_) {}, Rec.create)
+    ..pc<Rec>(2, 'sub', PbFieldType.PM, Rec.create)
     ..p<int>(10, 'ints', PbFieldType.P3);
 
   int get value => $_get(0, 0);
diff --git a/protoc_plugin/CHANGELOG.md b/protoc_plugin/CHANGELOG.md
index f20d84b..b626ac3 100644
--- a/protoc_plugin/CHANGELOG.md
+++ b/protoc_plugin/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 16.0.0
+
+* Breaking change: Remove the '$checkItem' function from generated message classes and use the new method 'pc' on
+  'BuilderInfo' to add repeated composite fields.
+  Generated files require package:protobuf version 0.13.4 or newer.
+
 ## 15.0.3
 
 * Add test for frozen messages with unknown fields and update protobuf dependency to 0.13.1.
diff --git a/protoc_plugin/lib/enum_generator.dart b/protoc_plugin/lib/enum_generator.dart
index 2ff355c..f441cd6 100644
--- a/protoc_plugin/lib/enum_generator.dart
+++ b/protoc_plugin/lib/enum_generator.dart
@@ -98,10 +98,6 @@
           ' $_protobufImportPrefix.ProtobufEnum.initByValue(values);');
       out.println('static ${classname} valueOf(int value) =>'
           ' _byValue[value];');
-      out.addBlock('static void $checkItem($classname v) {', '}', () {
-        out.println('if (v is! $classname)'
-            " $_protobufImportPrefix.checkItemFailed(v, ${singleQuote(classname)});");
-      });
       out.println();
 
       out.println('const ${classname}._(int v, String n) '
diff --git a/protoc_plugin/lib/extension_generator.dart b/protoc_plugin/lib/extension_generator.dart
index aca8255..e1b6e02 100644
--- a/protoc_plugin/lib/extension_generator.dart
+++ b/protoc_plugin/lib/extension_generator.dart
@@ -83,9 +83,11 @@
           'new $_protobufImportPrefix.Extension<$dartType>.repeated(\'$_extendedFullName\','
           ' \'$name\', ${_field.number}, ${_field.typeConstant}');
       if (type.isMessage || type.isGroup) {
-        out.println(', $dartType.$checkItem, $dartType.create);');
+        out.println(
+            ', $_protobufImportPrefix.getCheckFunction(${_field.typeConstant}), $dartType.create);');
       } else if (type.isEnum) {
-        out.println(', $dartType.$checkItem, null, '
+        out.println(
+            ', $_protobufImportPrefix.getCheckFunction(${_field.typeConstant}), null, '
             '$dartType.valueOf, $dartType.values);');
       } else {
         out.println(
diff --git a/protoc_plugin/lib/message_generator.dart b/protoc_plugin/lib/message_generator.dart
index 8a3b8f1..7e3f55e 100644
--- a/protoc_plugin/lib/message_generator.dart
+++ b/protoc_plugin/lib/message_generator.dart
@@ -339,10 +339,6 @@
       out.println(
           'static ${classname} getDefault() => _defaultInstance ??= create()..freeze();');
       out.println('static ${classname} _defaultInstance;');
-      out.addBlock('static void $checkItem($classname v) {', '}', () {
-        out.println('if (v is! $classname)'
-            " $_protobufImportPrefix.checkItemFailed(v, _i.qualifiedMessageName);");
-      });
       generateFieldsAccessorsMutators(out);
       if (fullName == 'google.protobuf.Any') {
         generateAnyMethods(out);
diff --git a/protoc_plugin/lib/names.dart b/protoc_plugin/lib/names.dart
index c16ff23..5d63fe0 100644
--- a/protoc_plugin/lib/names.dart
+++ b/protoc_plugin/lib/names.dart
@@ -6,10 +6,6 @@
 import 'package:protoc_plugin/src/dart_options.pb.dart';
 import 'package:protoc_plugin/src/descriptor.pb.dart';
 
-/// A Dart function called on each item added to a repeated list
-/// to check its type and range.
-const checkItem = '\$checkItem';
-
 class MemberNames {
   List<FieldNames> fieldNames;
   List<OneofNames> oneofNames;
@@ -501,7 +497,6 @@
   'createRepeated',
   'getDefault',
   'List',
-  checkItem,
   'notSet'
 ];
 
@@ -513,5 +508,4 @@
   'List',
   'valueOf',
   'values',
-  checkItem
 ];
diff --git a/protoc_plugin/lib/protobuf_field.dart b/protoc_plugin/lib/protobuf_field.dart
index e055c01..aaf4ee5 100644
--- a/protoc_plugin/lib/protobuf_field.dart
+++ b/protoc_plugin/lib/protobuf_field.dart
@@ -144,12 +144,12 @@
 
     if (isRepeated) {
       if (baseType.isMessage || baseType.isGroup) {
-        return '..pp<$type>($number, $quotedName, $typeConstant,'
-            ' $type.$checkItem, $type.create)';
+        return '..pc<$type>($number, $quotedName, $typeConstant,'
+            '$type.create)';
       }
       if (baseType.isEnum) {
-        return '..pp<$type>($number, $quotedName, $typeConstant,'
-            ' $type.$checkItem, null, $type.valueOf, $type.values)';
+        return '..pc<$type>($number, $quotedName, $typeConstant,'
+            ' null, $type.valueOf, $type.values)';
       }
       if (typeConstant == '$_protobufImportPrefix.PbFieldType.PS') {
         return '..pPS($number, $quotedName)';
diff --git a/protoc_plugin/lib/src/dart_options.pb.dart b/protoc_plugin/lib/src/dart_options.pb.dart
index 79ab981..388ed91 100644
--- a/protoc_plugin/lib/src/dart_options.pb.dart
+++ b/protoc_plugin/lib/src/dart_options.pb.dart
@@ -65,8 +65,7 @@
 class Imports extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = new $pb.BuilderInfo('Imports',
       package: const $pb.PackageName('dart_options'))
-    ..pp<DartMixin>(
-        1, 'mixins', $pb.PbFieldType.PM, DartMixin.$checkItem, DartMixin.create)
+    ..pc<DartMixin>(1, 'mixins', $pb.PbFieldType.PM, DartMixin.create)
     ..hasRequiredFields = false;
 
   Imports() : super();
diff --git a/protoc_plugin/lib/src/descriptor.pb.dart b/protoc_plugin/lib/src/descriptor.pb.dart
index 81f7881..94c29f1 100644
--- a/protoc_plugin/lib/src/descriptor.pb.dart
+++ b/protoc_plugin/lib/src/descriptor.pb.dart
@@ -17,8 +17,8 @@
 class FileDescriptorSet extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = new $pb.BuilderInfo('FileDescriptorSet',
       package: const $pb.PackageName('google.protobuf'))
-    ..pp<FileDescriptorProto>(1, 'file', $pb.PbFieldType.PM,
-        FileDescriptorProto.$checkItem, FileDescriptorProto.create);
+    ..pc<FileDescriptorProto>(
+        1, 'file', $pb.PbFieldType.PM, FileDescriptorProto.create);
 
   FileDescriptorSet() : super();
   FileDescriptorSet.fromBuffer(List<int> i,
@@ -52,14 +52,14 @@
     ..aOS(1, 'name')
     ..aOS(2, 'package')
     ..pPS(3, 'dependency')
-    ..pp<DescriptorProto>(4, 'messageType', $pb.PbFieldType.PM,
-        DescriptorProto.$checkItem, DescriptorProto.create)
-    ..pp<EnumDescriptorProto>(5, 'enumType', $pb.PbFieldType.PM,
-        EnumDescriptorProto.$checkItem, EnumDescriptorProto.create)
-    ..pp<ServiceDescriptorProto>(6, 'service', $pb.PbFieldType.PM,
-        ServiceDescriptorProto.$checkItem, ServiceDescriptorProto.create)
-    ..pp<FieldDescriptorProto>(7, 'extension', $pb.PbFieldType.PM,
-        FieldDescriptorProto.$checkItem, FieldDescriptorProto.create)
+    ..pc<DescriptorProto>(
+        4, 'messageType', $pb.PbFieldType.PM, DescriptorProto.create)
+    ..pc<EnumDescriptorProto>(
+        5, 'enumType', $pb.PbFieldType.PM, EnumDescriptorProto.create)
+    ..pc<ServiceDescriptorProto>(
+        6, 'service', $pb.PbFieldType.PM, ServiceDescriptorProto.create)
+    ..pc<FieldDescriptorProto>(
+        7, 'extension', $pb.PbFieldType.PM, FieldDescriptorProto.create)
     ..a<FileOptions>(8, 'options', $pb.PbFieldType.OM, FileOptions.getDefault,
         FileOptions.create)
     ..a<SourceCodeInfo>(9, 'sourceCodeInfo', $pb.PbFieldType.OM,
@@ -255,29 +255,21 @@
   static final $pb.BuilderInfo _i = new $pb.BuilderInfo('DescriptorProto',
       package: const $pb.PackageName('google.protobuf'))
     ..aOS(1, 'name')
-    ..pp<FieldDescriptorProto>(2, 'field', $pb.PbFieldType.PM,
-        FieldDescriptorProto.$checkItem, FieldDescriptorProto.create)
-    ..pp<DescriptorProto>(3, 'nestedType', $pb.PbFieldType.PM,
-        DescriptorProto.$checkItem, DescriptorProto.create)
-    ..pp<EnumDescriptorProto>(4, 'enumType', $pb.PbFieldType.PM,
-        EnumDescriptorProto.$checkItem, EnumDescriptorProto.create)
-    ..pp<DescriptorProto_ExtensionRange>(
-        5,
-        'extensionRange',
-        $pb.PbFieldType.PM,
-        DescriptorProto_ExtensionRange.$checkItem,
-        DescriptorProto_ExtensionRange.create)
-    ..pp<FieldDescriptorProto>(6, 'extension', $pb.PbFieldType.PM,
-        FieldDescriptorProto.$checkItem, FieldDescriptorProto.create)
+    ..pc<FieldDescriptorProto>(
+        2, 'field', $pb.PbFieldType.PM, FieldDescriptorProto.create)
+    ..pc<DescriptorProto>(
+        3, 'nestedType', $pb.PbFieldType.PM, DescriptorProto.create)
+    ..pc<EnumDescriptorProto>(
+        4, 'enumType', $pb.PbFieldType.PM, EnumDescriptorProto.create)
+    ..pc<DescriptorProto_ExtensionRange>(5, 'extensionRange',
+        $pb.PbFieldType.PM, DescriptorProto_ExtensionRange.create)
+    ..pc<FieldDescriptorProto>(
+        6, 'extension', $pb.PbFieldType.PM, FieldDescriptorProto.create)
     ..a<MessageOptions>(7, 'options', $pb.PbFieldType.OM,
         MessageOptions.getDefault, MessageOptions.create)
-    ..pp<OneofDescriptorProto>(8, 'oneofDecl', $pb.PbFieldType.PM,
-        OneofDescriptorProto.$checkItem, OneofDescriptorProto.create)
-    ..pp<DescriptorProto_ReservedRange>(
-        9,
-        'reservedRange',
-        $pb.PbFieldType.PM,
-        DescriptorProto_ReservedRange.$checkItem,
+    ..pc<OneofDescriptorProto>(
+        8, 'oneofDecl', $pb.PbFieldType.PM, OneofDescriptorProto.create)
+    ..pc<DescriptorProto_ReservedRange>(9, 'reservedRange', $pb.PbFieldType.PM,
         DescriptorProto_ReservedRange.create)
     ..pPS(10, 'reservedName');
 
@@ -520,8 +512,8 @@
   static final $pb.BuilderInfo _i = new $pb.BuilderInfo('EnumDescriptorProto',
       package: const $pb.PackageName('google.protobuf'))
     ..aOS(1, 'name')
-    ..pp<EnumValueDescriptorProto>(2, 'value', $pb.PbFieldType.PM,
-        EnumValueDescriptorProto.$checkItem, EnumValueDescriptorProto.create)
+    ..pc<EnumValueDescriptorProto>(
+        2, 'value', $pb.PbFieldType.PM, EnumValueDescriptorProto.create)
     ..a<EnumOptions>(3, 'options', $pb.PbFieldType.OM, EnumOptions.getDefault,
         EnumOptions.create);
 
@@ -632,8 +624,8 @@
       'ServiceDescriptorProto',
       package: const $pb.PackageName('google.protobuf'))
     ..aOS(1, 'name')
-    ..pp<MethodDescriptorProto>(2, 'method', $pb.PbFieldType.PM,
-        MethodDescriptorProto.$checkItem, MethodDescriptorProto.create)
+    ..pc<MethodDescriptorProto>(
+        2, 'method', $pb.PbFieldType.PM, MethodDescriptorProto.create)
     ..a<ServiceOptions>(3, 'options', $pb.PbFieldType.OM,
         ServiceOptions.getDefault, ServiceOptions.create);
 
@@ -792,8 +784,8 @@
     ..aOS(39, 'swiftPrefix')
     ..aOS(40, 'phpClassPrefix')
     ..aOS(41, 'phpNamespace')
-    ..pp<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
-        UninterpretedOption.$checkItem, UninterpretedOption.create)
+    ..pc<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
+        UninterpretedOption.create)
     ..hasExtensions = true;
 
   FileOptions() : super();
@@ -963,8 +955,8 @@
     ..aOB(2, 'noStandardDescriptorAccessor')
     ..aOB(3, 'deprecated')
     ..aOB(7, 'mapEntry')
-    ..pp<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
-        UninterpretedOption.$checkItem, UninterpretedOption.create)
+    ..pc<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
+        UninterpretedOption.create)
     ..hasExtensions = true;
 
   MessageOptions() : super();
@@ -1044,8 +1036,8 @@
         FieldOptions_JSType.valueOf,
         FieldOptions_JSType.values)
     ..aOB(10, 'weak')
-    ..pp<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
-        UninterpretedOption.$checkItem, UninterpretedOption.create)
+    ..pc<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
+        UninterpretedOption.create)
     ..hasExtensions = true;
 
   FieldOptions() : super();
@@ -1123,8 +1115,8 @@
 class OneofOptions extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = new $pb.BuilderInfo('OneofOptions',
       package: const $pb.PackageName('google.protobuf'))
-    ..pp<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
-        UninterpretedOption.$checkItem, UninterpretedOption.create)
+    ..pc<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
+        UninterpretedOption.create)
     ..hasExtensions = true;
 
   OneofOptions() : super();
@@ -1156,8 +1148,8 @@
       package: const $pb.PackageName('google.protobuf'))
     ..aOB(2, 'allowAlias')
     ..aOB(3, 'deprecated')
-    ..pp<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
-        UninterpretedOption.$checkItem, UninterpretedOption.create)
+    ..pc<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
+        UninterpretedOption.create)
     ..hasExtensions = true;
 
   EnumOptions() : super();
@@ -1204,8 +1196,8 @@
   static final $pb.BuilderInfo _i = new $pb.BuilderInfo('EnumValueOptions',
       package: const $pb.PackageName('google.protobuf'))
     ..aOB(1, 'deprecated')
-    ..pp<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
-        UninterpretedOption.$checkItem, UninterpretedOption.create)
+    ..pc<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
+        UninterpretedOption.create)
     ..hasExtensions = true;
 
   EnumValueOptions() : super();
@@ -1245,8 +1237,8 @@
   static final $pb.BuilderInfo _i = new $pb.BuilderInfo('ServiceOptions',
       package: const $pb.PackageName('google.protobuf'))
     ..aOB(33, 'deprecated')
-    ..pp<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
-        UninterpretedOption.$checkItem, UninterpretedOption.create)
+    ..pc<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
+        UninterpretedOption.create)
     ..hasExtensions = true;
 
   ServiceOptions() : super();
@@ -1292,8 +1284,8 @@
         MethodOptions_IdempotencyLevel.IDEMPOTENCY_UNKNOWN,
         MethodOptions_IdempotencyLevel.valueOf,
         MethodOptions_IdempotencyLevel.values)
-    ..pp<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
-        UninterpretedOption.$checkItem, UninterpretedOption.create)
+    ..pc<UninterpretedOption>(999, 'uninterpretedOption', $pb.PbFieldType.PM,
+        UninterpretedOption.create)
     ..hasExtensions = true;
 
   MethodOptions() : super();
@@ -1390,12 +1382,8 @@
 class UninterpretedOption extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = new $pb.BuilderInfo('UninterpretedOption',
       package: const $pb.PackageName('google.protobuf'))
-    ..pp<UninterpretedOption_NamePart>(
-        2,
-        'name',
-        $pb.PbFieldType.PM,
-        UninterpretedOption_NamePart.$checkItem,
-        UninterpretedOption_NamePart.create)
+    ..pc<UninterpretedOption_NamePart>(
+        2, 'name', $pb.PbFieldType.PM, UninterpretedOption_NamePart.create)
     ..aOS(3, 'identifierValue')
     ..a<Int64>(4, 'positiveIntValue', $pb.PbFieldType.OU6, Int64.ZERO)
     ..aInt64(5, 'negativeIntValue')
@@ -1540,8 +1528,8 @@
 class SourceCodeInfo extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = new $pb.BuilderInfo('SourceCodeInfo',
       package: const $pb.PackageName('google.protobuf'))
-    ..pp<SourceCodeInfo_Location>(1, 'location', $pb.PbFieldType.PM,
-        SourceCodeInfo_Location.$checkItem, SourceCodeInfo_Location.create)
+    ..pc<SourceCodeInfo_Location>(
+        1, 'location', $pb.PbFieldType.PM, SourceCodeInfo_Location.create)
     ..hasRequiredFields = false;
 
   SourceCodeInfo() : super();
@@ -1635,11 +1623,7 @@
 class GeneratedCodeInfo extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = new $pb.BuilderInfo('GeneratedCodeInfo',
       package: const $pb.PackageName('google.protobuf'))
-    ..pp<GeneratedCodeInfo_Annotation>(
-        1,
-        'annotation',
-        $pb.PbFieldType.PM,
-        GeneratedCodeInfo_Annotation.$checkItem,
+    ..pc<GeneratedCodeInfo_Annotation>(1, 'annotation', $pb.PbFieldType.PM,
         GeneratedCodeInfo_Annotation.create)
     ..hasRequiredFields = false;
 
diff --git a/protoc_plugin/lib/src/plugin.pb.dart b/protoc_plugin/lib/src/plugin.pb.dart
index b51a5e0..0deb2e1 100644
--- a/protoc_plugin/lib/src/plugin.pb.dart
+++ b/protoc_plugin/lib/src/plugin.pb.dart
@@ -80,8 +80,8 @@
     ..aOS(2, 'parameter')
     ..a<Version>(3, 'compilerVersion', $pb.PbFieldType.OM, Version.getDefault,
         Version.create)
-    ..pp<$0.FileDescriptorProto>(15, 'protoFile', $pb.PbFieldType.PM,
-        $0.FileDescriptorProto.$checkItem, $0.FileDescriptorProto.create);
+    ..pc<$0.FileDescriptorProto>(
+        15, 'protoFile', $pb.PbFieldType.PM, $0.FileDescriptorProto.create);
 
   CodeGeneratorRequest() : super();
   CodeGeneratorRequest.fromBuffer(List<int> i,
@@ -193,12 +193,8 @@
   static final $pb.BuilderInfo _i = new $pb.BuilderInfo('CodeGeneratorResponse',
       package: const $pb.PackageName('google.protobuf.compiler'))
     ..aOS(1, 'error')
-    ..pp<CodeGeneratorResponse_File>(
-        15,
-        'file',
-        $pb.PbFieldType.PM,
-        CodeGeneratorResponse_File.$checkItem,
-        CodeGeneratorResponse_File.create)
+    ..pc<CodeGeneratorResponse_File>(
+        15, 'file', $pb.PbFieldType.PM, CodeGeneratorResponse_File.create)
     ..hasRequiredFields = false;
 
   CodeGeneratorResponse() : super();
diff --git a/protoc_plugin/pubspec.yaml b/protoc_plugin/pubspec.yaml
index b1dfb03..9de08be 100644
--- a/protoc_plugin/pubspec.yaml
+++ b/protoc_plugin/pubspec.yaml
@@ -1,5 +1,5 @@
 name: protoc_plugin
-version: 15.0.4-dev
+version: 16.0.0
 author: Dart Team <misc@dartlang.org>
 description: Protoc compiler plugin to generate Dart code
 homepage: https://github.com/dart-lang/protobuf
@@ -10,7 +10,7 @@
 dependencies:
   fixnum: ^0.10.5
   path: ^1.0.0
-  protobuf: ^0.13.2
+  protobuf: ^0.13.4
   dart_style: ^1.0.6
 
 dev_dependencies:
diff --git a/protoc_plugin/test/goldens/enum b/protoc_plugin/test/goldens/enum
index 40de719..9e9ffab 100644
--- a/protoc_plugin/test/goldens/enum
+++ b/protoc_plugin/test/goldens/enum
@@ -13,9 +13,6 @@
 
   static final Map<int, PhoneType> _byValue = $pb.ProtobufEnum.initByValue(values);
   static PhoneType valueOf(int value) => _byValue[value];
-  static void $checkItem(PhoneType v) {
-    if (v is! PhoneType) $pb.checkItemFailed(v, 'PhoneType');
-  }
 
   const PhoneType._(int v, String n) : super(v, n);
 }
diff --git a/protoc_plugin/test/goldens/grpc_service.pb b/protoc_plugin/test/goldens/grpc_service.pb
index de7da1e..6bb6b3f 100644
--- a/protoc_plugin/test/goldens/grpc_service.pb
+++ b/protoc_plugin/test/goldens/grpc_service.pb
@@ -25,8 +25,5 @@
   static $pb.PbList<Empty> createRepeated() => new $pb.PbList<Empty>();
   static Empty getDefault() => _defaultInstance ??= create()..freeze();
   static Empty _defaultInstance;
-  static void $checkItem(Empty v) {
-    if (v is! Empty) $pb.checkItemFailed(v, _i.qualifiedMessageName);
-  }
 }
 
diff --git a/protoc_plugin/test/goldens/imports.pb b/protoc_plugin/test/goldens/imports.pb
index 3dd0632..917dcf8 100644
--- a/protoc_plugin/test/goldens/imports.pb
+++ b/protoc_plugin/test/goldens/imports.pb
@@ -31,9 +31,6 @@
   static $pb.PbList<M> createRepeated() => new $pb.PbList<M>();
   static M getDefault() => _defaultInstance ??= create()..freeze();
   static M _defaultInstance;
-  static void $checkItem(M v) {
-    if (v is! M) $pb.checkItemFailed(v, _i.qualifiedMessageName);
-  }
 
   M get m => $_getN(0);
   set m(M v) { setField(1, v); }
diff --git a/protoc_plugin/test/goldens/messageGenerator b/protoc_plugin/test/goldens/messageGenerator
index 4ad5dc5..b191638 100644
--- a/protoc_plugin/test/goldens/messageGenerator
+++ b/protoc_plugin/test/goldens/messageGenerator
@@ -16,9 +16,6 @@
   static $pb.PbList<PhoneNumber> createRepeated() => new $pb.PbList<PhoneNumber>();
   static PhoneNumber getDefault() => _defaultInstance ??= create()..freeze();
   static PhoneNumber _defaultInstance;
-  static void $checkItem(PhoneNumber v) {
-    if (v is! PhoneNumber) $pb.checkItemFailed(v, _i.qualifiedMessageName);
-  }
 
   String get number => $_getS(0, '');
   set number(String v) { $_setString(0, v); }
diff --git a/protoc_plugin/test/goldens/messageGeneratorEnums b/protoc_plugin/test/goldens/messageGeneratorEnums
index 157bfe1..9efb67e 100644
--- a/protoc_plugin/test/goldens/messageGeneratorEnums
+++ b/protoc_plugin/test/goldens/messageGeneratorEnums
@@ -13,9 +13,6 @@
 
   static final Map<int, PhoneNumber_PhoneType> _byValue = $pb.ProtobufEnum.initByValue(values);
   static PhoneNumber_PhoneType valueOf(int value) => _byValue[value];
-  static void $checkItem(PhoneNumber_PhoneType v) {
-    if (v is! PhoneNumber_PhoneType) $pb.checkItemFailed(v, 'PhoneNumber_PhoneType');
-  }
 
   const PhoneNumber_PhoneType._(int v, String n) : super(v, n);
 }
diff --git a/protoc_plugin/test/goldens/oneMessage.pb b/protoc_plugin/test/goldens/oneMessage.pb
index ea0cb37..45c0e48 100644
--- a/protoc_plugin/test/goldens/oneMessage.pb
+++ b/protoc_plugin/test/goldens/oneMessage.pb
@@ -27,9 +27,6 @@
   static $pb.PbList<PhoneNumber> createRepeated() => new $pb.PbList<PhoneNumber>();
   static PhoneNumber getDefault() => _defaultInstance ??= create()..freeze();
   static PhoneNumber _defaultInstance;
-  static void $checkItem(PhoneNumber v) {
-    if (v is! PhoneNumber) $pb.checkItemFailed(v, _i.qualifiedMessageName);
-  }
 
   String get number => $_getS(0, '');
   set number(String v) { $_setString(0, v); }
diff --git a/protoc_plugin/test/goldens/service.pb b/protoc_plugin/test/goldens/service.pb
index 42fcd73..11bbd11 100644
--- a/protoc_plugin/test/goldens/service.pb
+++ b/protoc_plugin/test/goldens/service.pb
@@ -26,9 +26,6 @@
   static $pb.PbList<Empty> createRepeated() => new $pb.PbList<Empty>();
   static Empty getDefault() => _defaultInstance ??= create()..freeze();
   static Empty _defaultInstance;
-  static void $checkItem(Empty v) {
-    if (v is! Empty) $pb.checkItemFailed(v, _i.qualifiedMessageName);
-  }
 }
 
 class TestApi {
diff --git a/protoc_plugin/test/goldens/topLevelEnum.pbenum b/protoc_plugin/test/goldens/topLevelEnum.pbenum
index bb618eb..6026295 100644
--- a/protoc_plugin/test/goldens/topLevelEnum.pbenum
+++ b/protoc_plugin/test/goldens/topLevelEnum.pbenum
@@ -23,9 +23,6 @@
 
   static final Map<int, PhoneType> _byValue = $pb.ProtobufEnum.initByValue(values);
   static PhoneType valueOf(int value) => _byValue[value];
-  static void $checkItem(PhoneType v) {
-    if (v is! PhoneType) $pb.checkItemFailed(v, 'PhoneType');
-  }
 
   const PhoneType._(int v, String n) : super(v, n);
 }
diff --git a/protoc_plugin/test/repeated_field_test.dart b/protoc_plugin/test/repeated_field_test.dart
index 77e97ed..9885155 100644
--- a/protoc_plugin/test/repeated_field_test.dart
+++ b/protoc_plugin/test/repeated_field_test.dart
@@ -9,61 +9,29 @@
 import 'package:test/test.dart';
 
 import '../out/protos/google/protobuf/unittest.pb.dart';
-import 'test_util.dart';
 
 // Suppress an analyzer warning for a deliberate type mismatch.
 cast(x) => x;
 
 void main() {
-  test("checkItems works for messages", () {
-    expect(() {
-      TestAllTypes.$checkItem(new TestAllTypes());
-    }, returnsNormally);
-
-    expect(() {
-      TestAllTypes.$checkItem(cast(new TestAllTypes_NestedMessage()));
-    }, throwsATypeError);
-  });
-
-  test("checkItems works for groups", () {
-    expect(() {
-      TestAllTypes_RepeatedGroup.$checkItem(new TestAllTypes_RepeatedGroup());
-    }, returnsNormally);
-
-    expect(() {
-      TestAllTypes_RepeatedGroup.$checkItem(
-          cast(new TestAllTypes_OptionalGroup()));
-    }, throwsATypeError);
-  });
-
-  test("checkItems works for enums", () {
-    expect(() {
-      TestAllTypes_NestedEnum.$checkItem(TestAllTypes_NestedEnum.FOO);
-    }, returnsNormally);
-
-    expect(() {
-      TestAllTypes_NestedEnum.$checkItem(cast(ForeignEnum.FOREIGN_FOO));
-    }, throwsATypeError);
-  });
-
   test("check properties are initialized for repeated fields", () {
     var msg = new TestAllTypes();
     expect(
         (msg.info_.byName["repeatedNestedMessage"]
                 as FieldInfo<TestAllTypes_NestedMessage>)
             .check,
-        same(TestAllTypes_NestedMessage.$checkItem));
+        isNotNull);
 
     expect(
         (msg.info_.byName["repeatedGroup"]
                 as FieldInfo<TestAllTypes_RepeatedGroup>)
             .check,
-        same(TestAllTypes_RepeatedGroup.$checkItem));
+        isNotNull);
 
     expect(
         (msg.info_.byName["repeatedNestedEnum"]
                 as FieldInfo<TestAllTypes_NestedEnum>)
             .check,
-        same(TestAllTypes_NestedEnum.$checkItem));
+        isNotNull);
   });
 }