Resolve pubspec dependencies relative to the Resolved description of their containing package (#4575)

diff --git a/lib/src/command/add.dart b/lib/src/command/add.dart
index 31d4a11..fa56f21 100644
--- a/lib/src/command/add.dart
+++ b/lib/src/command/add.dart
@@ -275,7 +275,9 @@
             location: Uri.parse(entrypoint.workPackage.pubspecPath),
             overridesFileContents: overridesFileContents,
             overridesLocation: Uri.file(overridesPath),
-            containingDescription: RootDescription(entrypoint.workPackage.dir),
+            containingDescription: ResolvedRootDescription.fromDir(
+              entrypoint.workPackage.dir,
+            ),
           ),
         )
         .acquireDependencies(
@@ -566,7 +568,7 @@
       ref = cache.sdk.parseRef(
         packageName,
         argResults.sdk,
-        containingDescription: RootDescription(p.current),
+        containingDescription: ResolvedRootDescription.fromDir(p.current),
       );
     } else {
       ref = PackageRef(
@@ -652,7 +654,7 @@
             cache.sources,
             // Resolve relative paths relative to current, not where the
             // pubspec.yaml is.
-            containingDescription: RootDescription(p.current),
+            containingDescription: ResolvedRootDescription.fromDir(p.current),
           );
         } on FormatException catch (e) {
           usageException('Failed parsing package specification: ${e.message}');
diff --git a/lib/src/command/dependency_services.dart b/lib/src/command/dependency_services.dart
index fddbb1c..738fedd 100644
--- a/lib/src/command/dependency_services.dart
+++ b/lib/src/command/dependency_services.dart
@@ -480,7 +480,9 @@
           updatedPubspecs[package.dir].toString(),
           cache.sources,
           location: toUri(package.pubspecPath),
-          containingDescription: RootDescription(package.dir),
+          containingDescription: ResolvedRootDescription(
+            RootDescription(package.dir),
+          ),
         ),
       );
       // Resolve versions, this will update transitive dependencies that were
diff --git a/lib/src/command/lish.dart b/lib/src/command/lish.dart
index 804287a..a2d405f 100644
--- a/lib/src/command/lish.dart
+++ b/lib/src/command/lish.dart
@@ -395,7 +395,9 @@
           ),
         ),
         cache.sources,
-        containingDescription: RootDescription(p.dirname(archive)),
+        containingDescription: ResolvedRootDescription.fromDir(
+          p.dirname(archive),
+        ),
       );
     } on FormatException catch (e) {
       dataError('Failed to read pubspec.yaml from archive: ${e.message}');
diff --git a/lib/src/command/unpack.dart b/lib/src/command/unpack.dart
index 21d096b..9882120 100644
--- a/lib/src/command/unpack.dart
+++ b/lib/src/command/unpack.dart
@@ -144,7 +144,9 @@
         final pubspec = Pubspec.load(
           destinationDir,
           cache.sources,
-          containingDescription: RootDescription(destinationDir),
+          containingDescription: ResolvedRootDescription.fromDir(
+            destinationDir,
+          ),
         );
         final buffer = StringBuffer();
         if (pubspec.resolution != Resolution.none) {
@@ -212,7 +214,7 @@
           // Resolve relative paths relative to current, not where the
           // pubspec.yaml is.
           location: p.toUri(p.join(p.current, 'descriptor')),
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
       } on FormatException catch (e) {
         usageException('Failed parsing package specification: ${e.message}');
diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index 0f9779b..f508969 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -97,7 +97,7 @@
         pubspec = Pubspec.load(
           dir,
           cache.sources,
-          containingDescription: RootDescription(dir),
+          containingDescription: ResolvedRootDescription.fromDir(dir),
           allowOverridesFile: true,
         );
       } on FileException {
@@ -116,7 +116,9 @@
                     cache.sources,
                     expectedName: expectedName,
                     allowOverridesFile: withPubspecOverrides,
-                    containingDescription: RootDescription(path),
+                    containingDescription: ResolvedRootDescription.fromDir(
+                      path,
+                    ),
                   ),
           withPubspecOverrides: true,
         );
diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart
index e0db64f..5a30953 100644
--- a/lib/src/global_packages.dart
+++ b/lib/src/global_packages.dart
@@ -115,7 +115,7 @@
           if (path != null) 'path': path,
           if (ref != null) 'ref': ref,
         },
-        containingDescription: RootDescription(p.current),
+        containingDescription: ResolvedRootDescription.fromDir(p.current),
         languageVersion: LanguageVersion.fromVersion(sdk.version),
       );
     } on FormatException catch (e) {
diff --git a/lib/src/pubspec.dart b/lib/src/pubspec.dart
index 0923ba7..5ebc55f 100644
--- a/lib/src/pubspec.dart
+++ b/lib/src/pubspec.dart
@@ -61,7 +61,7 @@
 
   /// It is used to resolve relative paths. And to resolve path-descriptions
   /// from a git dependency as git-descriptions.
-  final Description _containingDescription;
+  final ResolvedDescription _containingDescription;
 
   /// Directories of packages that should resolve together with this package.
   late List<String> workspace = () {
@@ -279,7 +279,7 @@
     SourceRegistry sources, {
     String? expectedName,
     bool allowOverridesFile = false,
-    required Description containingDescription,
+    required ResolvedDescription containingDescription,
   }) {
     final pubspecPath = p.join(packageDir, pubspecYamlFilename);
     final overridesPath = p.join(packageDir, pubspecOverridesFilename);
@@ -324,7 +324,7 @@
       sources,
       expectedName: expectedName,
       allowOverridesFile: withPubspecOverrides,
-      containingDescription: RootDescription(dir),
+      containingDescription: ResolvedRootDescription.fromDir(dir),
     );
   }
 
@@ -362,7 +362,7 @@
        _overridesFileFields = null,
        // This is a dummy value. Dependencies should already be resolved, so we
        // never need to do relative resolutions.
-       _containingDescription = RootDescription('.'),
+       _containingDescription = ResolvedRootDescription.fromDir('.'),
        super(
          fields == null ? YamlMap() : YamlMap.wrap(fields),
          name: name,
@@ -382,7 +382,7 @@
     YamlMap? overridesFields,
     String? expectedName,
     Uri? location,
-    required Description containingDescription,
+    required ResolvedDescription containingDescription,
   }) : _overridesFileFields = overridesFields,
        _includeDefaultSdkConstraint = true,
        _givenSdkConstraints = null,
@@ -432,7 +432,7 @@
     Uri? location,
     String? overridesFileContents,
     Uri? overridesLocation,
-    required Description containingDescription,
+    required ResolvedDescription containingDescription,
   }) {
     final YamlMap pubspecMap;
     YamlMap? overridesFileMap;
@@ -576,7 +576,7 @@
   SourceRegistry sources,
   LanguageVersion languageVersion,
   String? packageName,
-  Description containingDescription, {
+  ResolvedDescription containingDescription, {
   _FileType fileType = _FileType.pubspec,
 }) {
   final dependencies = <String, PackageRange>{};
diff --git a/lib/src/source.dart b/lib/src/source.dart
index 0c3fe70..824ea5b 100644
--- a/lib/src/source.dart
+++ b/lib/src/source.dart
@@ -81,7 +81,7 @@
   PackageRef parseRef(
     String name,
     Object? description, {
-    required Description containingDescription,
+    required ResolvedDescription containingDescription,
     required LanguageVersion languageVersion,
   });
 
diff --git a/lib/src/source/cached.dart b/lib/src/source/cached.dart
index 86dbc0a..2cfa2a1 100644
--- a/lib/src/source/cached.dart
+++ b/lib/src/source/cached.dart
@@ -32,7 +32,7 @@
         packageDir,
         cache.sources,
         expectedName: id.name,
-        containingDescription: id.description.description,
+        containingDescription: id.description,
       );
     }
 
diff --git a/lib/src/source/git.dart b/lib/src/source/git.dart
index 7bed62f..d5236b6 100644
--- a/lib/src/source/git.dart
+++ b/lib/src/source/git.dart
@@ -37,7 +37,7 @@
   PackageRef parseRef(
     String name,
     Object? description, {
-    Description? containingDescription,
+    ResolvedDescription? containingDescription,
     required LanguageVersion languageVersion,
   }) {
     String url;
@@ -86,7 +86,7 @@
       }
     }
 
-    final containingDir = switch (containingDescription) {
+    final containingDir = switch (containingDescription?.description) {
       RootDescription(path: final path) => path,
       PathDescription(path: final path) => path,
       _ => null,
@@ -267,7 +267,7 @@
       return Pubspec.parse(
         await _showFileAtRevision(resolvedDescription, 'pubspec.yaml', cache),
         cache.sources,
-        containingDescription: description,
+        containingDescription: resolvedDescription,
       ).name;
     });
   }
@@ -338,16 +338,26 @@
   /// Since we don't have an easy way to read from a remote Git repo, this
   /// just installs [id] into the system cache, then describes it from there.
   @override
-  Future<Pubspec> describeUncached(PackageId id, SystemCache cache) {
+  Future<Pubspec> describeUncached(PackageId id, SystemCache cache) async {
     final description = id.description;
     if (description is! ResolvedGitDescription) {
       throw StateError('Called with wrong ref');
     }
-    return _pool.withResource(
+    final pubspec = await _pool.withResource(
       () => _describeUncached(id.toRef(), description.resolvedRef, cache),
     );
+    if (pubspec.version != id.version) {
+      throw PackageNotFoundException(
+        'Expected ${id.name} version ${id.version} '
+        'at commit ${description.resolvedRef}, '
+        'found ${pubspec.version}.',
+      );
+    }
+    return pubspec;
   }
 
+  final Map<(PackageRef, String), Pubspec> _pubspecAtRevisionCache = {};
+
   /// Like [describeUncached], but takes a separate [ref] and Git [revision]
   /// rather than a single ID.
   Future<Pubspec> _describeUncached(
@@ -359,18 +369,16 @@
     if (description is! GitDescription) {
       throw ArgumentError('Wrong source');
     }
-    await _ensureRevision(description, revision, cache);
-
-    return Pubspec.parse(
-      await _showFileAtRevision(
-        ResolvedGitDescription(description, revision),
-        'pubspec.yaml',
-        cache,
-      ),
-      cache.sources,
-      expectedName: ref.name,
-      containingDescription: ref.description,
-    );
+    return _pubspecAtRevisionCache[(ref, revision)] ??= await () async {
+      await _ensureRevision(description, revision, cache);
+      final resolvedDescription = ResolvedGitDescription(description, revision);
+      return Pubspec.parse(
+        await _showFileAtRevision(resolvedDescription, 'pubspec.yaml', cache),
+        cache.sources,
+        expectedName: ref.name,
+        containingDescription: resolvedDescription,
+      );
+    }();
   }
 
   /// Clones a Git repo to the local filesystem.
diff --git a/lib/src/source/hosted.dart b/lib/src/source/hosted.dart
index 1956d9a..925309a 100644
--- a/lib/src/source/hosted.dart
+++ b/lib/src/source/hosted.dart
@@ -229,7 +229,7 @@
   PackageRef parseRef(
     String name,
     Object? description, {
-    required Description containingDescription,
+    required ResolvedDescription containingDescription,
     required LanguageVersion languageVersion,
   }) {
     return PackageRef(
@@ -416,17 +416,22 @@
       if (pubspecData is! Map) {
         throw const FormatException('pubspec must be a map');
       }
+
+      final archiveSha256 = map['archive_sha256'];
+      if (archiveSha256 != null && archiveSha256 is! String) {
+        throw const FormatException('archive_sha256 must be a String');
+      }
+      final parsedContentHash = _parseContentHash(archiveSha256 as String?);
       final pubspec = Pubspec.fromMap(
         pubspecData,
         cache.sources,
         expectedName: ref.name,
         location: location,
-        containingDescription: description,
+        containingDescription: ResolvedHostedDescription(
+          description,
+          sha256: parsedContentHash,
+        ),
       );
-      final archiveSha256 = map['archive_sha256'];
-      if (archiveSha256 != null && archiveSha256 is! String) {
-        throw const FormatException('archive_sha256 must be a String');
-      }
       final archiveUrl = map['archive_url'];
       if (archiveUrl is! String) {
         throw const FormatException('archive_url must be a String');
@@ -463,7 +468,7 @@
         pubspec,
         Uri.parse(archiveUrl),
         status,
-        _parseContentHash(archiveSha256 as String?),
+        parsedContentHash,
       );
     }).toList();
   }
@@ -1640,7 +1645,7 @@
           containingDescription:
           // Dummy description. As we never use the dependencies, they don't
           // need to be resolved.
-          RootDescription('.'),
+          ResolvedRootDescription.fromDir('.'),
         );
         final errors = pubspec.dependencyErrors;
         if (errors.isNotEmpty) {
diff --git a/lib/src/source/path.dart b/lib/src/source/path.dart
index 46b6981..f395ba0 100644
--- a/lib/src/source/path.dart
+++ b/lib/src/source/path.dart
@@ -54,7 +54,7 @@
   PackageRef parseRef(
     String name,
     Object? description, {
-    required Description containingDescription,
+    required ResolvedDescription containingDescription,
     LanguageVersion? languageVersion,
   }) {
     if (description is! String) {
@@ -64,30 +64,32 @@
     // Resolve the path relative to the containing file path, and remember
     // whether the original path was relative or absolute.
     final isRelative = p.isRelative(dir);
-
-    if (containingDescription is PathDescription) {
+    if (containingDescription is ResolvedPathDescription) {
       return PackageRef(
         name,
         PathDescription(
           isRelative
-              ? p.join(p.absolute(containingDescription.path), dir)
+              ? p.join(p.absolute(containingDescription.description.path), dir)
               : dir,
           isRelative,
         ),
       );
-    } else if (containingDescription is RootDescription) {
+    } else if (containingDescription is ResolvedRootDescription) {
       return PackageRef(
         name,
         PathDescription(
           isRelative
               ? p.normalize(
-                p.join(p.absolute(containingDescription.path), description),
+                p.join(
+                  p.absolute(containingDescription.description.path),
+                  description,
+                ),
               )
               : description,
           isRelative,
         ),
       );
-    } else if (containingDescription is GitDescription) {
+    } else if (containingDescription is ResolvedGitDescription) {
       if (!isRelative) {
         throw FormatException(
           '"$description" is an absolute path, '
@@ -95,7 +97,10 @@
         );
       }
       final resolvedPath = p.url.normalize(
-        p.url.joinAll([containingDescription.path, ...p.posix.split(dir)]),
+        p.url.joinAll([
+          containingDescription.description.path,
+          ...p.posix.split(dir),
+        ]),
       );
       if (!(p.isWithin('.', resolvedPath) || p.equals('.', resolvedPath))) {
         throw FormatException(
@@ -106,9 +111,10 @@
       return PackageRef(
         name,
         GitDescription.raw(
-          url: containingDescription.url,
-          relative: containingDescription.relative,
-          ref: containingDescription.ref,
+          url: containingDescription.description.url,
+          relative: containingDescription.description.relative,
+          // Always refer to the same commit as the containing pubspec.
+          ref: containingDescription.resolvedRef,
           path: resolvedPath,
         ),
       );
@@ -193,12 +199,9 @@
     }
     // There's only one package ID for a given path. We just need to find the
     // version.
-    final pubspec = _loadPubspec(ref, cache);
-    final id = PackageId(
-      ref.name,
-      pubspec.version,
-      ResolvedPathDescription(description),
-    );
+    final resolvedDescription = ResolvedPathDescription(description);
+    final pubspec = _loadPubspec(ref, resolvedDescription, cache);
+    final id = PackageId(ref.name, pubspec.version, resolvedDescription);
     // Store the pubspec in memory if we need to refer to it again.
     cache.cachedPubspecs[id] = pubspec;
     return [id];
@@ -206,14 +209,18 @@
 
   @override
   Future<Pubspec> doDescribe(PackageId id, SystemCache cache) async =>
-      _loadPubspec(id.toRef(), cache);
+      _loadPubspec(
+        id.toRef(),
+        id.description as ResolvedPathDescription,
+        cache,
+      );
 
-  Pubspec _loadPubspec(PackageRef ref, SystemCache cache) {
-    final description = ref.description;
-    if (description is! PathDescription) {
-      throw ArgumentError('Wrong source');
-    }
-    final dir = _validatePath(ref.name, description);
+  Pubspec _loadPubspec(
+    PackageRef ref,
+    ResolvedPathDescription description,
+    SystemCache cache,
+  ) {
+    final dir = _validatePath(ref.name, description.description);
     return Pubspec.load(
       dir,
       cache.sources,
diff --git a/lib/src/source/root.dart b/lib/src/source/root.dart
index d6f971a..9a178d0 100644
--- a/lib/src/source/root.dart
+++ b/lib/src/source/root.dart
@@ -66,7 +66,7 @@
   PackageRef parseRef(
     String name,
     Object? description, {
-    required Description containingDescription,
+    required ResolvedDescription containingDescription,
     required LanguageVersion languageVersion,
   }) {
     throw UnsupportedError('Trying to parse a root package description.');
@@ -78,6 +78,7 @@
   RootDescription get description => super.description as RootDescription;
 
   ResolvedRootDescription(RootDescription super.description);
+  ResolvedRootDescription.fromDir(String dir) : super(RootDescription(dir));
 
   @override
   Object? serializeForLockfile({required String? containingDir}) {
diff --git a/lib/src/source/sdk.dart b/lib/src/source/sdk.dart
index daaca09..536c29b 100644
--- a/lib/src/source/sdk.dart
+++ b/lib/src/source/sdk.dart
@@ -29,7 +29,7 @@
   PackageRef parseRef(
     String name,
     Object? description, {
-    required Description containingDescription,
+    required ResolvedDescription containingDescription,
     LanguageVersion? languageVersion,
   }) {
     if (description is! String) {
@@ -91,7 +91,9 @@
       _verifiedPackagePath(ref),
       cache.sources,
       expectedName: ref.name,
-      containingDescription: ref.description,
+      containingDescription: ResolvedSdkDescription(
+        ref.description as SdkDescription,
+      ),
     );
 
     /// Validate that there are no non-sdk dependencies if the SDK does not
diff --git a/lib/src/source/unknown.dart b/lib/src/source/unknown.dart
index 50102ea..a151e9e 100644
--- a/lib/src/source/unknown.dart
+++ b/lib/src/source/unknown.dart
@@ -37,7 +37,7 @@
   PackageRef parseRef(
     String name,
     Object? description, {
-    required Description containingDescription,
+    required ResolvedDescription containingDescription,
     LanguageVersion? languageVersion,
   }) => PackageRef(name, UnknownDescription(description, this));
 
diff --git a/test/pubspec_test.dart b/test/pubspec_test.dart
index 60db310..a3e2ba3 100644
--- a/test/pubspec_test.dart
+++ b/test/pubspec_test.dart
@@ -26,7 +26,7 @@
       void Function(Pubspec) fn, {
       String? expectedContains,
       String? hintContains,
-      Description? containingDescription,
+      ResolvedDescription? containingDescription,
     }) {
       var expectation = const TypeMatcher<SourceSpanApplicationException>();
       if (expectedContains != null) {
@@ -47,7 +47,8 @@
       final pubspec = Pubspec.parse(
         contents,
         sources,
-        containingDescription: containingDescription ?? RootDescription('.'),
+        containingDescription:
+            containingDescription ?? ResolvedRootDescription.fromDir('.'),
       );
       expect(() => fn(pubspec), throwsA(expectation));
     }
@@ -57,7 +58,7 @@
       Pubspec.parse(
         'version: not a semver',
         sources,
-        containingDescription: RootDescription('.'),
+        containingDescription: ResolvedRootDescription.fromDir('.'),
       );
     });
 
@@ -68,7 +69,7 @@
           'name: foo',
           sources,
           expectedName: 'bar',
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         ),
         throwsPubspecException,
       );
@@ -81,7 +82,7 @@
           '{}',
           sources,
           expectedName: 'bar',
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         ),
         throwsPubspecException,
       );
@@ -98,7 +99,7 @@
     version: ">=1.2.3 <3.4.5"
 ''',
         sources,
-        containingDescription: RootDescription('.'),
+        containingDescription: ResolvedRootDescription.fromDir('.'),
       );
 
       final foo = pubspec.dependencies['foo']!;
@@ -119,7 +120,7 @@
     version: ">=1.2.3 <0.0.0"
 ''',
         sources,
-        containingDescription: RootDescription('.'),
+        containingDescription: ResolvedRootDescription.fromDir('.'),
       );
 
       final foo = pubspec.dependencies['foo']!;
@@ -133,7 +134,7 @@
 dependencies:
 ''',
         sources,
-        containingDescription: RootDescription('.'),
+        containingDescription: ResolvedRootDescription.fromDir('.'),
       );
 
       expect(pubspec.dependencies, isEmpty);
@@ -150,7 +151,7 @@
     version: ">=1.2.3 <3.4.5"
 ''',
         sources,
-        containingDescription: RootDescription('.'),
+        containingDescription: ResolvedRootDescription.fromDir('.'),
       );
 
       final foo = pubspec.devDependencies['foo']!;
@@ -166,7 +167,7 @@
 dev_dependencies:
 ''',
         sources,
-        containingDescription: RootDescription('.'),
+        containingDescription: ResolvedRootDescription.fromDir('.'),
       );
 
       expect(pubspec.devDependencies, isEmpty);
@@ -183,7 +184,7 @@
     version: ">=1.2.3 <3.4.5"
 ''',
         sources,
-        containingDescription: RootDescription('.'),
+        containingDescription: ResolvedRootDescription.fromDir('.'),
       );
 
       final foo = pubspec.dependencyOverrides['foo']!;
@@ -199,7 +200,7 @@
 dependency_overrides:
 ''',
         sources,
-        containingDescription: RootDescription('.'),
+        containingDescription: ResolvedRootDescription.fromDir('.'),
       );
 
       expect(pubspec.dependencyOverrides, isEmpty);
@@ -213,7 +214,7 @@
     unknown: blah
 ''',
         sources,
-        containingDescription: RootDescription('.'),
+        containingDescription: ResolvedRootDescription.fromDir('.'),
       );
 
       final foo = pubspec.dependencies['foo']!;
@@ -229,7 +230,7 @@
     version: 1.2.3
 ''',
         sources,
-        containingDescription: RootDescription('.'),
+        containingDescription: ResolvedRootDescription.fromDir('.'),
       );
 
       final foo = pubspec.dependencies['foo']!;
@@ -344,7 +345,7 @@
 workspace: ['a', 'b', 'c']
 ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         ).workspace,
         ['a', 'b', 'c'],
       );
@@ -359,7 +360,7 @@
 resolution: workspace
 ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         ).resolution,
         Resolution.workspace,
       );
@@ -393,7 +394,7 @@
 resolution: workspace
 ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         ).name,
         'foo',
       );
@@ -451,7 +452,7 @@
 # See https://dart.dev/tools/pub/cmd for details
 ''',
         sources,
-        containingDescription: RootDescription('.'),
+        containingDescription: ResolvedRootDescription.fromDir('.'),
       );
       expect(pubspec.version, equals(Version.none));
       expect(pubspec.dependencies, isEmpty);
@@ -464,13 +465,15 @@
 dependencies:
   from_path: {path: non_local_path}
 ''',
-        containingDescription: HostedDescription('foo', 'https://pub.dev'),
+        containingDescription: ResolvedHostedDescription(
+          HostedDescription('foo', 'https://pub.dev'),
+          sha256: null,
+        ),
         (pubspec) => pubspec.dependencies,
         expectedContains:
             'Invalid description in the "pkg" pubspec on the "from_path" '
-            'dependency: "non_local_path" is a relative path, '
-            'but this isn\'t a '
-            'local pubspec.',
+            'dependency: "non_local_path" is a path, but '
+            'this isn\'t a local pubspec.',
       );
     });
 
@@ -486,7 +489,7 @@
       name: bar
 ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
 
         final foo = pubspec.dependencies['foo']!;
@@ -513,7 +516,7 @@
       url: https://example.org/pub/
 ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
 
         final foo = pubspec.dependencies['foo']!;
@@ -539,7 +542,7 @@
     hosted: https://example.org/pub/
 ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
 
         final foo = pubspec.dependencies['foo']!;
@@ -565,7 +568,7 @@
     hosted: bar
 ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
 
         final foo = pubspec.dependencies['foo']!;
@@ -593,7 +596,7 @@
     hosted: https://example.org/pub/
 ''',
             sources,
-            containingDescription: RootDescription('.'),
+            containingDescription: ResolvedRootDescription.fromDir('.'),
           );
 
           expect(
@@ -617,7 +620,7 @@
   foo:
 ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
 
         final foo = pubspec.dependencies['foo']!;
@@ -715,7 +718,7 @@
         final pubspec = Pubspec.parse(
           'name: testing',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
         expect(
           pubspec.dartSdkConstraint.effectiveConstraint,
@@ -730,7 +733,7 @@
         final pubspec = Pubspec.parse(
           '',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
         expect(
           pubspec.dartSdkConstraint.effectiveConstraint,
@@ -748,7 +751,7 @@
     sdk: ">1.0.0"
   ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
         expect(
           pubspec.dartSdkConstraint.effectiveConstraint,
@@ -766,7 +769,7 @@
     sdk: ">3.0.0"
   ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
         expect(
           pubspec.sdkConstraints,
@@ -795,7 +798,7 @@
   fuchsia: ^5.6.7
 ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
         expect(
           pubspec.sdkConstraints,
@@ -859,7 +862,7 @@
         final pubspec = Pubspec.parse(
           '',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
         expect(pubspec.publishTo, isNull);
       });
@@ -877,7 +880,7 @@
 publish_to: http://example.com
 ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
         expect(pubspec.publishTo, equals('http://example.com'));
       });
@@ -888,7 +891,7 @@
 publish_to: none
 ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
         expect(pubspec.publishTo, equals('none'));
       });
@@ -913,7 +916,7 @@
         final pubspec = Pubspec.parse(
           '',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
         expect(pubspec.executables, isEmpty);
       });
@@ -925,7 +928,7 @@
   abcDEF-123_: "abc DEF-123._"
 ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
         expect(pubspec.executables['abcDEF-123_'], equals('abc DEF-123._'));
       });
@@ -979,7 +982,7 @@
   command:
 ''',
           sources,
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
         expect(pubspec.executables['command'], equals('command'));
       });
@@ -998,7 +1001,7 @@
           sources,
           overridesFileContents: overridesContents,
           overridesLocation: Uri.parse('file:///pubspec_overrides.yaml'),
-          containingDescription: RootDescription('.'),
+          containingDescription: ResolvedRootDescription.fromDir('.'),
         );
       }
 
diff --git a/test/version_solver_test.dart b/test/version_solver_test.dart
index c0ec370..dcf5a42 100644
--- a/test/version_solver_test.dart
+++ b/test/version_solver_test.dart
@@ -520,26 +520,34 @@
 
   test('mismatched sources', () async {
     await d.dir('shared', [d.libPubspec('shared', '1.0.0')]).create();
-
-    await servePackages()
-      ..serve('foo', '1.0.0', deps: {'shared': '1.0.0'})
-      ..serve(
+    await d.dir('bar', [
+      d.libPubspec(
         'bar',
         '1.0.0',
         deps: {
           'shared': {'path': p.join(d.sandbox, 'shared')},
         },
-      )
+      ),
+    ]).create();
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'shared': '1.0.0'})
       ..serve('shared', '1.0.0');
 
-    await d.appDir(dependencies: {'foo': '1.0.0', 'bar': '1.0.0'}).create();
+    await d
+        .appDir(
+          dependencies: {
+            'foo': '1.0.0',
+            'bar': {'path': '../bar'},
+          },
+        )
+        .create();
     await expectResolves(
       error: equalsIgnoringWhitespace('''
-      Because every version of bar depends on shared from path and every
-        version of foo depends on shared from hosted, bar is incompatible with
-        foo.
-      So, because myapp depends on both foo 1.0.0 and bar 1.0.0, version
-        solving failed.
+ Because every version of bar from path depends on shared
+ from path and every version of foo depends on shared from hosted,
+ bar from path is incompatible with foo.
+So, because myapp depends on both foo 1.0.0 and bar from path,
+version solving failed.
     '''),
     );
   });
@@ -888,7 +896,7 @@
   // dependencies are traversed breadth-first (all of myapps's immediate deps
   // before any other their deps).
   //
-  // This means it doesn't discover the source conflict until after selecting
+  // This means it doesn't discover the version conflict until after selecting
   // c. When that happens, it should backjump past c instead of trying older
   // versions of it since they aren't related to the conflict.
   test('successful backjump to conflicting source', () async {
@@ -896,21 +904,18 @@
 
     await servePackages()
       ..serve('a', '1.0.0')
+      ..serve('a', '2.0.0')
       ..serve('b', '1.0.0', deps: {'a': 'any'})
-      ..serve(
-        'b',
-        '2.0.0',
-        deps: {
-          'a': {'path': p.join(d.sandbox, 'a')},
-        },
-      )
+      ..serve('b', '2.0.0', deps: {'a': '^2.0.0'})
       ..serve('c', '1.0.0')
       ..serve('c', '2.0.0')
       ..serve('c', '3.0.0')
       ..serve('c', '4.0.0')
       ..serve('c', '5.0.0');
 
-    await d.appDir(dependencies: {'a': 'any', 'b': 'any', 'c': 'any'}).create();
+    await d
+        .appDir(dependencies: {'a': '1.0.0', 'b': 'any', 'c': 'any'})
+        .create();
     await expectResolves(result: {'a': '1.0.0', 'b': '1.0.0', 'c': '5.0.0'});
   });
 
@@ -945,29 +950,39 @@
   // fail in this case with no backtracking.
   test('failing backjump to conflicting source', () async {
     await d.dir('a', [d.libPubspec('a', '1.0.0')]).create();
-
-    await servePackages()
-      ..serve('a', '1.0.0')
-      ..serve(
+    await d.dir('b', [
+      d.libPubspec(
         'b',
         '1.0.0',
         deps: {
           'a': {'path': p.join(d.sandbox, 'shared')},
         },
-      )
+      ),
+    ]).create();
+
+    await servePackages()
+      ..serve('a', '1.0.0')
       ..serve('c', '1.0.0')
       ..serve('c', '2.0.0')
       ..serve('c', '3.0.0')
       ..serve('c', '4.0.0')
       ..serve('c', '5.0.0');
 
-    await d.appDir(dependencies: {'a': 'any', 'b': 'any', 'c': 'any'}).create();
+    await d
+        .appDir(
+          dependencies: {
+            'a': 'any',
+            'b': {'path': '../b'},
+            'c': 'any',
+          },
+        )
+        .create();
     await expectResolves(
       error: equalsIgnoringWhitespace('''
-      Because every version of b depends on a from path and myapp depends on
-        a from hosted, b is forbidden.
-      So, because myapp depends on b any, version solving failed.
-    '''),
+Because every version of b from path depends on a from path 
+and myapp depends on a from hosted, b from path is forbidden.
+So, because myapp depends on b from path, version solving failed.
+'''),
     );
   });
 
@@ -1983,7 +1998,7 @@
   final resultPubspec = Pubspec.fromMap(
     {'dependencies': result},
     registry,
-    containingDescription: RootDescription('.'),
+    containingDescription: ResolvedRootDescription.fromDir('.'),
   );
 
   final ids = {...lockFile.packages};