Add `UseResult` annotation to `rebuild` (#631)

This catches issues like #630 where we forgot to use return value of
`rebuild`. Since `rebuild` does not update in-place, not using the
return value is often a bug.

This adds `meta` as a dependency but it should not affect generated
code. We may also want to use `meta` in the future for things like:

- Annotating `GeneratedMessage` methods that are supposed to be used by
  the generated code with `@protected`.

- Annotating generated message classes with `@sealed`. This help with
  maintaining backwards compatibility when adding new members to
  generated messages or to `GeneratedMessage`.
diff --git a/protobuf/lib/protobuf.dart b/protobuf/lib/protobuf.dart
index e2d5cdc..f60d5ee 100644
--- a/protobuf/lib/protobuf.dart
+++ b/protobuf/lib/protobuf.dart
@@ -11,6 +11,7 @@
 import 'dart:typed_data' show TypedData, Uint8List, ByteData, Endian;
 
 import 'package:fixnum/fixnum.dart' show Int64;
+import 'package:meta/meta.dart' show UseResult;
 
 import 'src/protobuf/json_parsing_context.dart';
 import 'src/protobuf/permissive_compare.dart';
diff --git a/protobuf/lib/src/protobuf/generated_message.dart b/protobuf/lib/src/protobuf/generated_message.dart
index c9cb0a9..6fa71d7 100644
--- a/protobuf/lib/src/protobuf/generated_message.dart
+++ b/protobuf/lib/src/protobuf/generated_message.dart
@@ -545,6 +545,8 @@
   ///
   /// Makes a writable shallow copy of this message, applies the [updates] to
   /// it, and marks the copy read-only before returning it.
+  @UseResult('[GeneratedMessageGenericExtensions.rebuild] '
+      'does not update the message, returns a new message')
   T rebuild(void Function(T) updates) {
     if (!isFrozen) {
       throw ArgumentError('Rebuilding only works on frozen messages.');
diff --git a/protobuf/pubspec.yaml b/protobuf/pubspec.yaml
index 3805ee8..259c8c6 100644
--- a/protobuf/pubspec.yaml
+++ b/protobuf/pubspec.yaml
@@ -11,6 +11,7 @@
 dependencies:
   fixnum: ^1.0.0
   collection: ^1.15.0
+  meta: ^1.7.0
 
 dev_dependencies:
   test: ^1.16.0
diff --git a/protoc_plugin/test/oneof_test.dart b/protoc_plugin/test/oneof_test.dart
index de1c00a..dcd65fa 100644
--- a/protoc_plugin/test/oneof_test.dart
+++ b/protoc_plugin/test/oneof_test.dart
@@ -161,11 +161,15 @@
   test('copyWith preserves oneof state', () {
     var foo = Foo();
     expectOneofNotSet(foo);
-    var copy1 = foo.deepCopy().freeze().rebuild((_) {}) as Foo;
+    // `ignore` below to work around https://github.com/dart-lang/sdk/issues/48879
+    var copy1 =
+        foo.deepCopy().freeze().rebuild((_) {}) as Foo; // ignore: unused_result
     expectOneofNotSet(copy1);
     foo.first = 'oneof';
     expectFirstSet(foo);
-    var copy2 = foo.deepCopy().freeze().rebuild((_) {}) as Foo;
+    // `ignore` below to work around https://github.com/dart-lang/sdk/issues/48879
+    var copy2 =
+        foo.deepCopy().freeze().rebuild((_) {}) as Foo; // ignore: unused_result
     expectFirstSet(copy2);
   });