Fix equality and hashcode for the sdk descriptors (#3367)

* Fix equality and hashcode for the sdk descriptors

* == and hashcode will now throw if not overridden
diff --git a/lib/src/source.dart b/lib/src/source.dart
index b6faba6..e331da1 100644
--- a/lib/src/source.dart
+++ b/lib/src/source.dart
@@ -169,6 +169,13 @@
   ///
   /// Paths are always relative to current dir.
   String format();
+
+  @override
+  bool operator ==(other) =>
+      throw UnimplementedError('Subclasses must override');
+
+  @override
+  int get hashCode => throw UnimplementedError('Subclasses must override');
 }
 
 /// A resolved description is a [Description] plus whatever information you need
@@ -193,6 +200,13 @@
   ///
   /// Paths are always relative to current dir.
   String format() => description.format();
+
+  @override
+  bool operator ==(other) =>
+      throw UnimplementedError('Subclasses must override');
+
+  @override
+  int get hashCode => throw UnimplementedError('Subclasses must override');
 }
 
 /// Metadata about a [PackageId].
diff --git a/lib/src/source/sdk.dart b/lib/src/source/sdk.dart
index f06e833..fe10eb4 100644
--- a/lib/src/source/sdk.dart
+++ b/lib/src/source/sdk.dart
@@ -141,6 +141,14 @@
 
   @override
   Source get source => SdkSource.instance;
+
+  @override
+  int get hashCode => sdk.hashCode;
+
+  @override
+  bool operator ==(Object other) {
+    return other is SdkDescription && other.sdk == sdk;
+  }
 }
 
 class ResolvedSdkDescription extends ResolvedDescription {
@@ -153,4 +161,12 @@
   Object? serializeForLockfile({required String? containingDir}) {
     return description.sdk;
   }
+
+  @override
+  int get hashCode => description.hashCode;
+
+  @override
+  bool operator ==(Object other) {
+    return other is ResolvedSdkDescription && other.description == description;
+  }
 }
diff --git a/test/version_solver_test.dart b/test/version_solver_test.dart
index 25212a7..128ed73 100644
--- a/test/version_solver_test.dart
+++ b/test/version_solver_test.dart
@@ -2937,4 +2937,25 @@
       ),
     );
   });
+
+  test('diamond sdk deps', () async {
+    await d.dir('flutter', [
+      d.dir('bin/cache/pkg', [
+        d.dir(
+            'baz', [d.libDir('baz', 'foo 0.0.1'), d.libPubspec('baz', '0.0.1')])
+      ]),
+      d.file('version', '1.2.3')
+    ]).create();
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {
+        'baz': {'sdk': 'flutter'}
+      })
+      ..serve('bar', '1.0.0', deps: {
+        'baz': {'sdk': 'flutter'}
+      });
+    await d.appDir({'foo': 'any', 'bar': 'any'}).create();
+    await expectResolves(
+      environment: {'FLUTTER_ROOT': p.join(d.sandbox, 'flutter')},
+    );
+  });
 }