From 4bd6953b5000dec9249b04bfe7d27daa052dd7c9 Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao@microsoft.com>
Date: Mon, 13 Nov 2023 16:38:02 -0800
Subject: [PATCH 1/9] Add named path bases to cargo (v2)

Introduce shared base directories in Cargo configuration files that in turn enable base-relative path dependencies.
---
 text/0000-cargo-path-bases.md | 331 ++++++++++++++++++++++++++++++++++
 1 file changed, 331 insertions(+)
 create mode 100644 text/0000-cargo-path-bases.md

diff --git a/text/0000-cargo-path-bases.md b/text/0000-cargo-path-bases.md
new file mode 100644
index 00000000000..14f997ea1d2
--- /dev/null
+++ b/text/0000-cargo-path-bases.md
@@ -0,0 +1,331 @@
+- Feature Name: `path_bases`
+- Start Date: 2023-11-13
+- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)
+- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)
+
+# Summary
+[summary]: #summary
+
+Introduce shared base directories in Cargo configuration files that in
+turn enable base-relative `path` dependencies.
+
+# Motivation
+[motivation]: #motivation
+
+While developing locally, users may wish to specify many `path`
+dependencies that all live in the same local directory. If that local
+directory is not a short distance from the `Cargo.toml`, this can get
+unwieldy. They may end up with a `Cargo.toml` that contains
+
+```toml
+foo = { path = "/home/jon/dev/rust/foo" }
+bar = { path = "/home/jon/dev/rust/bar" }
+baz = { path = "/home/jon/dev/rust/ws/baz" }
+```
+
+This is not only frustrating to type out, but also requires many changes
+should any component of the path change. For example, if `foo`, `bar`,
+and `ws/baz` were to move under a sub-directory of `libs`, all the paths
+would have to be updated. If they are used in more than one local
+project, each project would have to be updated.
+
+As related issue arises in contexts where an external build system may
+make certain dependencies available through vendoring. Such a build
+system might place vendored packages under some complex path under a
+build-root, like
+
+```
+/home/user/workplace/feature-1/build/first-party-package/first-party-package-1.0/x86_64/dev/build/private/rust-vendored/
+```
+
+If a developer wishes to use such an auto-vendored dependency, a
+contract must be established with the build system about exactly where
+vendred dependencies will end up. And since that path may not be near
+the project's `Cargo.toml`, the user's `Cargo.toml` may end up with
+either an absolute path or a long relative path, both of which may not
+work on other hosts, and thus cannot be checked in (or must be
+overwritten in-place by the build system).
+
+The proposed mechanism aims to simplify both of these use-cases by
+introducing named "base" paths in the Cargo configuration
+(`.cargo/config.toml`). Path dependencies can then be given relative to
+those base path names, which can be set either by a local developer in
+their user-wide configuration (`~/.cargo/config.toml`), or by an
+external build system in a project-wide configuration file.
+
+This effectively makes a "group" of path dependencies available at some
+undisclosed location to `Cargo.toml`, which then only has to know the
+layout to path dependencies _within_ that directory, and not the path
+_to_ that directory.
+
+# Guide-level explanation
+[guide-level-explanation]: #guide-level-explanation
+
+If you often use path dependencies that live in a particular location,
+or if you want to avoid putting long paths in your `Cargo.toml`, you can
+define path _base directories_ in your [Cargo
+configuration](https://doc.rust-lang.org/cargo/reference/config.html).
+Your path dependencies can then be specified relative to those
+directories.
+
+For example, say you have a number of projects checked out in 
+`/home/user/dev/rust/libraries/`. Rather than use that path in your
+`Cargo.toml` files, you can define it as a "base" path in
+`~/.cargo/config.toml`:
+
+```toml
+[base_path]
+dev = "/home/user/dev/rust/libraries/"
+```
+
+Now, you can specify a path dependency on a library `foo` in that
+directory in your `Cargo.toml` using
+
+```toml
+[dependencies]
+foo = { path = "foo", base = "dev" }
+```
+
+Like with other path dependencies, keep in mind that both the base _and_
+the path must exist on any other host where you want to use the same
+`Cargo.toml` to build your project.
+
+# Reference-level explanation
+[reference-level-explanation]: #reference-level-explanation
+
+## Configuration
+
+`[base_path]`
+
+* Type: string
+* Default: see below
+* Environment: `CARGO_BASE_PATH_<name>`
+
+The `[base_path]` table defines a set of path prefixes that can be used to
+prepend the locations of `path` dependencies. Each key in the table is the name
+of the base path and the value is the actual file system path. These base paths
+can be used in a `path` dependency by setting its `base` key to the name of the
+base path to use.
+
+```toml
+[base_path]
+dev = "/home/user/dev/rust/libraries/"
+```
+
+The "dev" base path may then be referenced in a `Cargo.toml`:
+
+```toml
+[dependencies]
+foo = { path = "foo", base = "dev" }
+```
+
+To produce a `path` dependency `foo` located at
+`/home/user/dev/rust/libraries/foo`.
+
+
+## Specifying Dependencies
+
+A `path` dependency may optionally specify a base path by setting the `base` key
+to the name of a base path from the `[base_path]` table in the configuration.
+The value of that base path in the configuration is prepended to the `path`
+value to produce the actual location where Cargo will look for the dependency.
+
+If the base path is not found in the `[base_path]` table then Cargo will
+generate an error.
+
+```toml
+[dependencies]
+foo = { path = "foo", base = "dev" }
+```
+
+Given a `[base_path]` table in the configuration that contains:
+
+```toml
+[base_path]
+dev = "/home/user/dev/rust/libraries/"
+```
+
+Will then produce a `path` dependency `foo` located at
+`/home/user/dev/rust/libraries/foo`.
+
+# Drawbacks
+[drawbacks]: #drawbacks
+
+1. There is now an additional way to specify a dependency in
+   `Cargo.toml` that may not be accessible when others try to build the
+   same project. Specifically, it may now be that the other host has a
+   `path` dependency available at the same relative path to `Cargo.toml`
+   as the author of the `Cargo.toml` entry, but does not have the `base`
+   defined (or has it defined as some other value).
+
+   At the same time, this might make path dependencies _more_ re-usable
+   across hosts, since developers can dictate only which _bases_ need to
+   exist, rather than which _paths_ need to exist. This would allow
+   different developers to host their path dependencies in different
+   locations from the original author.
+2. Developers still need to know the path _within_ each path base. We
+   could instead define path "aliases", though at that point the whole
+   thing looks more like a special kind of "local path registry".
+3. This introduces yet another mechanism for grouping local
+   dependencies. We already have [local registries, directory
+   registries](https://doc.rust-lang.org/cargo/reference/source-replacement.html),
+   and the [`[paths]`
+   override](https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#paths-overrides).
+   However, those are all intended for immutable local copies of
+   dependencies where versioning is enforced, rather than as mutable
+   path dependencies.
+
+# Rationale and alternatives
+[rationale-and-alternatives]: #rationale-and-alternatives
+
+This design was primarily chosen for its simplicity — it adds very
+little to what we have today both in terms of API surface and mechanism.
+But, other approaches exist.
+
+Developers could have their `path` dependencies point to symlinks in the
+current directory, which other developers would then be told to set up
+to point to the appropriate place on their system. This approach has two
+main drawbacks: they are harder to use on Windows as they [require
+special privileges](https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links),
+and they pollute the user's project directory.
+
+For the build-system case, the build system could place vendored
+dependencies directly into the source directory at well-known locations,
+though this would mean that if the source of those dependencies were to
+change, the user would have to re-run the build system (rather than just
+run `cargo`) to refresh the vendored dependency. And this approach too
+would end up polluting the user's source directory.
+
+An earlier iteration of the design avoided adding a new field to
+dependencies, and instead inlined the base name into the path using
+`path = "base::relative/path"`. This has the advantage of not
+introducing another special keyword in `Cargo.toml`, but comes at the
+cost of making `::` illegal in paths, which was deemed too great.
+
+Alternatively, we could add support for extrapolating environment
+variables (or arbitrary configuration values?) in `Cargo.toml` values.
+That way, the path could be given as `path =
+"${base.name}/relative/path"`. While that works, it's not trivially
+backwards compatible, may be confusing when users try to extrapolate
+random other configuration variables in their paths, and _seems_ like a
+possible Pandora's box of corner-cases.
+
+The [`[paths]`
+feature](https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#paths-overrides)
+could be updated to lift its current limitations around adding
+dependencies and requiring that the dependencies be available on
+crates.io. This would allow users to avoid `path` dependencies in more
+cases, but makes the replacement more implicit than explicit. That
+change is also more likely to break existing users, and to involve
+significant refactoring of the existing mechanism.
+
+We could add another type of local registry that is explicitly declared
+in `Cargo.toml`, and from which local dependencies could then be drawn.
+Something like:
+
+```toml
+[registry.local]
+path = "/path/to/path/registry"
+```
+
+This would make specifying the dependencies somewhat nicer (`version =
+"1", registry = "local"`), and would ensure a standard layout for the
+locations of the local dependencies. However, using local dependencies
+in this manner would require more set-up to arrange for the right
+registry layout, and we would be introducing what is effectively a
+mutable registry, which Cargo has avoided thus far.
+
+Even with such an approach, there are benefits to being able to not put
+complex paths into `Cargo.toml` as they may differ on other build hosts.
+So, a mechanism for indirecting through a path name may still be
+desirable.
+
+Ultimately, by not having a mechanism to name paths that lives outside
+of `Cargo.toml`, we are forcing developers to coordinate their file
+system layouts without giving them a mechanism for doing so. Or to work
+around the lack of a mechanism by requiring developers to add symlinks
+in strategic locations, cluttering their directories. The proposed
+mechanism is simple to understand and to use, and still covers a wide
+variety of use-cases.
+
+# Prior art
+[prior-art]: #prior-art
+
+Python searches for dependencies by walking `sys.path` in definition
+order, which [is pulled
+from](https://docs.python.org/3/tutorial/modules.html#the-module-search-path)
+the current directory, `PYTHONPATH`, and a list of system-wide library
+directories. All imports are thus "relative" to every directory in
+`sys.path`. This makes it easy to inject local development dependencies
+simply by injecting a path early in `sys.path`. The path dependency is
+never made explicit anywhere in Python. We _could_ adopt a similar
+approach by declaring an environment variable `CARGO_PATHS`, where every
+`path` is considered relative to each path in `CARGO_PATHS` until a path
+that exists is found. However, this introduces additional possibilities
+for user confusion if, say, `foo` exists in multiple paths in
+`CARGO_PATHS` and the first one is picked (though maybe that could be a
+warning?).
+
+NodeJS (with npm) is very similar to Python, except that dependencies
+can also be
+[specified](https://nodejs.org/api/modules.html#modules_all_together)
+using relative paths like Cargo's `path` dependencies. For non-path
+dependencies, it searches in [`node_modules/` in every parent
+directory](https://nodejs.org/api/modules.html#modules_loading_from_node_modules_folders),
+as well as in the [`NODE_PATH` search
+path](https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders).
+There does not exist a standard mechanism to specify a path dependency
+relative to a path named elsewhere. With CommonJS modules, JavaScript
+developers are able to extrapolate variables directly into their
+`require` arguments, and can thus implement custom schemes for getting
+customizable paths.
+
+Ruby's `Gemfile` [path
+dependencies](https://bundler.io/man/gemfile.5.html#PATH) are only ever
+absolute paths or paths relative to the `Gemfile`'s location, and so are
+similar to Rust's current `path` dependencies.
+
+The same is the case for Go's `go.mod` [replacement
+dependencies](https://golang.org/doc/modules/managing-dependencies#tmp_10),
+which only allow absolute or relative paths.
+
+From this, it's clear that other major languages do not have a feature
+quite like this. This is likely because path dependencies are assumed
+to be short-lived and local, and thus having them be host-specific is
+often good enough. However, as the motivation section of this RFC
+outlines, there are still use-cases where a simple name-indirection
+could help.
+
+# Unresolved questions
+[unresolved-questions]: #unresolved-questions
+
+- What should the Cargo configuration table and dependency key be called? This
+  RFC calls the configuration table `base_path` to be explicit that it is
+  dealing with paths (as `base` would be ambiguous) but calls the key `base` to
+  keep it concise.
+- Is there other reasonable behavior we could fall back to if a `base`
+  is specified for a dependency, but no base by that name exists in the
+  current Cargo configuration? This RFC suggests that this should be an
+  error, but perhaps there is a reasonable thing to try _first_ prior to
+  yielding an error.
+
+# Future possibilities
+[future-possibilities]: #future-possibilities
+
+It seems reasonable to extend `base` to `git` dependencies, with
+something like:
+
+```toml
+[base_path]
+gh = "https://github.com/jonhoo"
+```
+
+```toml
+[dependency]
+foo = { git = "foo.git", base = "gh" }
+```
+
+However, this may get complicated if someone specifies `git`, `path`,
+_and_ `base`.
+
+It may also be useful to be able to use `base` for `patch` and `path`.

From 5ccbe52fb2f18455bb80ff7cc7a86caa23c5cf47 Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao@microsoft.com>
Date: Tue, 14 Nov 2023 10:28:14 -0800
Subject: [PATCH 2/9] Update RFC number

---
 text/{0000-cargo-path-bases.md => 3529-cargo-path-bases.md} | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
 rename text/{0000-cargo-path-bases.md => 3529-cargo-path-bases.md} (97%)

diff --git a/text/0000-cargo-path-bases.md b/text/3529-cargo-path-bases.md
similarity index 97%
rename from text/0000-cargo-path-bases.md
rename to text/3529-cargo-path-bases.md
index 14f997ea1d2..d1265cb7d13 100644
--- a/text/0000-cargo-path-bases.md
+++ b/text/3529-cargo-path-bases.md
@@ -1,6 +1,6 @@
 - Feature Name: `path_bases`
 - Start Date: 2023-11-13
-- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)
+- RFC PR: [rust-lang/rfcs#3529](https://github.com/rust-lang/rfcs/pull/3529)
 - Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)
 
 # Summary

From e9f756664595d4ca14f905387f9ecbe9af7ef099 Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao@microsoft.com>
Date: Mon, 11 Dec 2023 14:12:34 -0800
Subject: [PATCH 3/9] Rewrote motiviation

---
 text/3529-cargo-path-bases.md | 207 ++++++++++++++++++++++------------
 1 file changed, 134 insertions(+), 73 deletions(-)

diff --git a/text/3529-cargo-path-bases.md b/text/3529-cargo-path-bases.md
index d1265cb7d13..c12c8bc4a1d 100644
--- a/text/3529-cargo-path-bases.md
+++ b/text/3529-cargo-path-bases.md
@@ -12,59 +12,109 @@ turn enable base-relative `path` dependencies.
 # Motivation
 [motivation]: #motivation
 
-While developing locally, users may wish to specify many `path`
-dependencies that all live in the same local directory. If that local
-directory is not a short distance from the `Cargo.toml`, this can get
-unwieldy. They may end up with a `Cargo.toml` that contains
+As a project grows in size, it becomes necessary to split it into smaller
+sub-projects, architected into layers with well-defined boundaries.
+
+One way to enforce these boundaries is to use different Git repos (aka
+"multi-repo"). Cargo has good support for multi-repo projects using either `git`
+dependencies, or developers can use private registries if they want to
+explicitly publish code or need to preprocess their sub-projects (e.g.,
+generating code) before they can be consumed.
+
+If all of the code is kept in a single Git repo (aka "mono-repo"), then these
+boundaries must be enforced a different way: either leveraging tooling during
+the build to check layering, or requiring that sub-projects explicitly publish
+and consume from some intermediate directory. Cargo has poor support for
+mono-repos: the only viable mechanism is `path` dependencies, but these require
+relative paths (which makes refactoring and moving sub-projects very difficult)
+and don't work at all if the mono-repo requires publishing and consuming from an
+intermediate directory (as this may very per host, or per target being built).
+
+This RFC proposes a mechanism to specify `base` directories in `Config.toml` or
+`Cargo.toml` files which can be used to prepend `path` dependencies. This allows
+mono-repos to specify dependencies relative to their root directory, which
+allows the consuming project to be moved freely (no relative paths to update)
+and a simple find-and-replace to handle a producing project being moved.
+Additionally, a host-specific or target-specific intermediate directory may be
+specified as a `base`, allowing code to be consumed from there using `path`
+dependencies.
+
+### Example
+
+If we had a sub-project that depends on three others:
+
+* `foo` which is in a different layer of the mono-repo.
+* `bar_with_generated` that must be consumed from an intermediate directory
+because it contains target-specific generated code.
+* `baz` which is in the current layer.
+
+We may have a `Cargo.toml` snippet that looks like this:
 
 ```toml
-foo = { path = "/home/jon/dev/rust/foo" }
-bar = { path = "/home/jon/dev/rust/bar" }
-baz = { path = "/home/jon/dev/rust/ws/baz" }
+[dependencies]
+foo = { path = "../../../other_layer/foo" }
+bar_with_generated = { path = "../../../../intermediates/x86_64/Debug/third_layer/bar_with_generated" }
+baz = { path = "../baz" }
 ```
 
-This is not only frustrating to type out, but also requires many changes
-should any component of the path change. For example, if `foo`, `bar`,
-and `ws/baz` were to move under a sub-directory of `libs`, all the paths
-would have to be updated. If they are used in more than one local
-project, each project would have to be updated.
+This has many issues:
+
+* Moving the current sub-project may require changing all of these relative
+paths.
+* `bar_with_generated` will only work if we're building x86_64 Debug.
+* `bar_with_generated` assumes that the `intermediates` directory is a sibling
+to our source directory, and not somewhere else completely (e.g., a different
+drive for performance reasons).
+* Moving `foo` or `baz` requires searching the code for each possible relative
+path (e.g., `../../../other_layer/foo` and `../foo`) and may be error prone if
+there is some other sub-project in directory with the same name.
 
-As related issue arises in contexts where an external build system may
-make certain dependencies available through vendoring. Such a build
-system might place vendored packages under some complex path under a
-build-root, like
+Instead, if we could specify these `base` directories in a `Config.toml` (which
+may be generated by an external build system which in turn invokes Cargo):
 
+```toml
+[base-paths]
+sources = "/home/user/dev/src"
+intermediates = "/home/user/dev/intermediates/x86_64/Debug"
 ```
-/home/user/workplace/feature-1/build/first-party-package/first-party-package-1.0/x86_64/dev/build/private/rust-vendored/
+
+Then the `Cargo.toml` can use those `base` directories and avoid relative paths:
+
+```toml
+[dependencies]
+foo = { path = "other_layer/foo", base = "sources" }
+bar_with_generated = { path = "third_layer/bar_with_generated", base = "intermediates" }
+baz = { path = "this_layer/baz", base = "sources" }
 ```
 
-If a developer wishes to use such an auto-vendored dependency, a
-contract must be established with the build system about exactly where
-vendred dependencies will end up. And since that path may not be near
-the project's `Cargo.toml`, the user's `Cargo.toml` may end up with
-either an absolute path or a long relative path, both of which may not
-work on other hosts, and thus cannot be checked in (or must be
-overwritten in-place by the build system).
-
-The proposed mechanism aims to simplify both of these use-cases by
-introducing named "base" paths in the Cargo configuration
-(`.cargo/config.toml`). Path dependencies can then be given relative to
-those base path names, which can be set either by a local developer in
-their user-wide configuration (`~/.cargo/config.toml`), or by an
-external build system in a project-wide configuration file.
-
-This effectively makes a "group" of path dependencies available at some
-undisclosed location to `Cargo.toml`, which then only has to know the
-layout to path dependencies _within_ that directory, and not the path
-_to_ that directory.
+Which resolves the issues we previously had:
+
+* The current project can be moved without modifying the `Cargo.toml` at all.
+* `bar_with_generated` works for all targets (assuming the `Config.toml` is
+generated).
+* The `intermediates` directory can be placed anywhere.
+* Moving `foo` or `baz` only requires searching for the canonical form relative
+to the `base` directory.
+
+## Other uses
+
+The ability to use `base` directories for `path` dependencies is convenient for
+developers who are using a large number of `path` dependencies within the same
+root directory. Instead of repeating the same path fragment many times in their
+`Cargo.toml`, they can instead specify it once in a `Config.toml` as a `base`
+directory, then use that `base` directory in each of their `path` dependencies.
+
+Cargo can also provide built-in base paths, for example `workspace` to point to
+the root directory of the workspace. This allows workspace members to reference
+each other without first needing to `../` their way back to the workspace root.
 
 # Guide-level explanation
 [guide-level-explanation]: #guide-level-explanation
 
 If you often use path dependencies that live in a particular location,
 or if you want to avoid putting long paths in your `Cargo.toml`, you can
-define path _base directories_ in your [Cargo
-configuration](https://doc.rust-lang.org/cargo/reference/config.html).
+define path _base directories_ in your Cargo [manifest](https://doc.rust-lang.org/cargo/reference/manifest.html)
+or [configuration](https://doc.rust-lang.org/cargo/reference/config.html).
 Your path dependencies can then be specified relative to those
 directories.
 
@@ -74,7 +124,7 @@ For example, say you have a number of projects checked out in
 `~/.cargo/config.toml`:
 
 ```toml
-[base_path]
+[base-paths]
 dev = "/home/user/dev/rust/libraries/"
 ```
 
@@ -93,60 +143,71 @@ the path must exist on any other host where you want to use the same
 # Reference-level explanation
 [reference-level-explanation]: #reference-level-explanation
 
-## Configuration
+## Specifying Dependencies
 
-`[base_path]`
+### Base Paths
 
-* Type: string
-* Default: see below
-* Environment: `CARGO_BASE_PATH_<name>`
+A `path` dependency may optionally specify a base path by setting the `base` key
+to the name of a base path from the `[base-paths]` table in either the
+[manifest](https://doc.rust-lang.org/cargo/reference/manifest.html) or
+[configuration](https://doc.rust-lang.org/cargo/reference/config.html#base-paths)
+or one of the [built-in base paths](#built-in-base-paths). The value of that
+base path is prepended to the `path` value to produce the actual location where
+Cargo will look for the dependency.
 
-The `[base_path]` table defines a set of path prefixes that can be used to
-prepend the locations of `path` dependencies. Each key in the table is the name
-of the base path and the value is the actual file system path. These base paths
-can be used in a `path` dependency by setting its `base` key to the name of the
-base path to use.
+For example, if the Cargo.toml contains:
 
 ```toml
-[base_path]
-dev = "/home/user/dev/rust/libraries/"
+[dependencies]
+foo = { path = "foo", base = "dev" }
 ```
 
-The "dev" base path may then be referenced in a `Cargo.toml`:
+Given a `[base-paths]` table in the configuration that contains:
 
 ```toml
-[dependencies]
-foo = { path = "foo", base = "dev" }
+[base-paths]
+dev = "/home/user/dev/rust/libraries/"
 ```
 
-To produce a `path` dependency `foo` located at
+This will produce a `path` dependency `foo` located at
 `/home/user/dev/rust/libraries/foo`.
 
+If the base path is not found in any `[base-paths]` table or one of the built-in
+base paths then Cargo will generate an error.
 
-## Specifying Dependencies
+If the name of a base path is specified in both the manifest and configuration,
+then the value in the manifest is preferred.
 
-A `path` dependency may optionally specify a base path by setting the `base` key
-to the name of a base path from the `[base_path]` table in the configuration.
-The value of that base path in the configuration is prepended to the `path`
-value to produce the actual location where Cargo will look for the dependency.
+The name of a base path must use only [alphanumeric](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphanumeric)
+characters or `-` or `_`, and cannot be empty.
 
-If the base path is not found in the `[base_path]` table then Cargo will
-generate an error.
+#### Built-in base paths
 
-```toml
-[dependencies]
-foo = { path = "foo", base = "dev" }
-```
+Cargo provides implicit base paths that can be used without the need to specify
+them in a `[base-paths]` table.
 
-Given a `[base_path]` table in the configuration that contains:
+* `workspace` - If a project is [a workspace or workspace member](https://doc.rust-lang.org/cargo/reference/workspaces.html)
+then this base path is defined as the path to the directory containing the root
+Cargo.toml of the workspace.
 
-```toml
-[base_path]
-dev = "/home/user/dev/rust/libraries/"
-```
+If one of these built-in base paths is also specified in the manifest or
+configuration, then that value is preferred over the built-in value.
 
-Will then produce a `path` dependency `foo` located at
-`/home/user/dev/rust/libraries/foo`.
+## The Manifest Format
+
+[`[base-paths]`](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#base-paths) - Base paths for path dependencies.
+
+## Configuration
+
+`[base-paths]`
+
+* Type: string
+* Default: see below
+* Environment: `CARGO_BASE_PATHS_<name>`
+
+The `[base-paths]` table defines a set of path prefixes that can be used to
+prepend the locations of `path` dependencies. See the [specifying dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#base-paths)
+documentation for more information.
 
 # Drawbacks
 [drawbacks]: #drawbacks

From 4af121b6124909794b0187bc5fb9247176abde9a Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao@microsoft.com>
Date: Fri, 21 Jun 2024 09:44:37 -0700
Subject: [PATCH 4/9] Address PR feedback

---
 text/3529-cargo-path-bases.md | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/text/3529-cargo-path-bases.md b/text/3529-cargo-path-bases.md
index c12c8bc4a1d..0bedc6703e0 100644
--- a/text/3529-cargo-path-bases.md
+++ b/text/3529-cargo-path-bases.md
@@ -179,7 +179,8 @@ If the name of a base path is specified in both the manifest and configuration,
 then the value in the manifest is preferred.
 
 The name of a base path must use only [alphanumeric](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphanumeric)
-characters or `-` or `_`, and cannot be empty.
+characters or `-` or `_`, must start with an [alphabetic](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphabetic)
+character, and must not be empty.
 
 #### Built-in base paths
 
@@ -191,7 +192,9 @@ then this base path is defined as the path to the directory containing the root
 Cargo.toml of the workspace.
 
 If one of these built-in base paths is also specified in the manifest or
-configuration, then that value is preferred over the built-in value.
+configuration, then that value is preferred over the built-in value. This allows
+Cargo to introduce additional built-in paths in the future without compatibility
+issues, as any existing uses will shadow Cargo's built-in name.
 
 ## The Manifest Format
 
@@ -361,7 +364,7 @@ could help.
 [unresolved-questions]: #unresolved-questions
 
 - What should the Cargo configuration table and dependency key be called? This
-  RFC calls the configuration table `base_path` to be explicit that it is
+  RFC calls the configuration table `base-paths` to be explicit that it is
   dealing with paths (as `base` would be ambiguous) but calls the key `base` to
   keep it concise.
 - Is there other reasonable behavior we could fall back to if a `base`
@@ -377,7 +380,7 @@ It seems reasonable to extend `base` to `git` dependencies, with
 something like:
 
 ```toml
-[base_path]
+[base-paths]
 gh = "https://github.com/jonhoo"
 ```
 

From 247ff65973d7143ba985ca8481ebf4bad5f6ef1b Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao@microsoft.com>
Date: Fri, 21 Jun 2024 15:10:51 -0700
Subject: [PATCH 5/9] Address PR feedback

---
 text/3529-cargo-path-bases.md | 37 +++++++++++++++++++++++------------
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/text/3529-cargo-path-bases.md b/text/3529-cargo-path-bases.md
index 0bedc6703e0..3e94dff2da2 100644
--- a/text/3529-cargo-path-bases.md
+++ b/text/3529-cargo-path-bases.md
@@ -172,11 +172,9 @@ dev = "/home/user/dev/rust/libraries/"
 This will produce a `path` dependency `foo` located at
 `/home/user/dev/rust/libraries/foo`.
 
-If the base path is not found in any `[base-paths]` table or one of the built-in
-base paths then Cargo will generate an error.
-
-If the name of a base path is specified in both the manifest and configuration,
-then the value in the manifest is preferred.
+Base paths can be either absolute or relative. Relative base paths are relative
+to the parent directory of the configuration or manifest file that declared that
+base path.
 
 The name of a base path must use only [alphanumeric](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphanumeric)
 characters or `-` or `_`, must start with an [alphabetic](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphabetic)
@@ -188,17 +186,32 @@ Cargo provides implicit base paths that can be used without the need to specify
 them in a `[base-paths]` table.
 
 * `workspace` - If a project is [a workspace or workspace member](https://doc.rust-lang.org/cargo/reference/workspaces.html)
-then this base path is defined as the path to the directory containing the root
-Cargo.toml of the workspace.
+then this base path is defined as the parent directory of the root Cargo.toml of
+the workspace.
+
+#### Base paths resolution order
+
+Cargo will search for base paths in the following order:
+
+1. In the [configuration](https://doc.rust-lang.org/cargo/reference/config.html).
+1. In the [manifest](https://doc.rust-lang.org/cargo/reference/manifest.html)
+that is using the base path.
+1. In the workspace's [manifest](https://doc.rust-lang.org/cargo/reference/manifest.html).
+1. In the list of built-in base paths.
+
+If the base path is not found in during this search then Cargo will generate an
+error.
 
-If one of these built-in base paths is also specified in the manifest or
-configuration, then that value is preferred over the built-in value. This allows
-Cargo to introduce additional built-in paths in the future without compatibility
-issues, as any existing uses will shadow Cargo's built-in name.
+Once a base path is found Cargo will stop searching, thus it is possible to
+shadow a base path by declaring it earlier in the search order. This allows the
+user's configuration to override the base path in a package, or for Cargo to add
+new built-in base paths without compatibility issues (as existing uses will
+shadow the built-in name).
 
 ## The Manifest Format
 
-[`[base-paths]`](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#base-paths) - Base paths for path dependencies.
+* Dependency tables:
+  * [`[base-paths]`](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#base-paths) - Base paths for path dependencies.
 
 ## Configuration
 

From b18416d5cdf3bbe5b86a2d30f6b4da76755d25f6 Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao@microsoft.com>
Date: Mon, 24 Jun 2024 14:53:37 -0700
Subject: [PATCH 6/9] Apply suggestions from code review

Co-authored-by: Eric Huss <eric@huss.org>
---
 text/3529-cargo-path-bases.md | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/text/3529-cargo-path-bases.md b/text/3529-cargo-path-bases.md
index 3e94dff2da2..3b0673dac02 100644
--- a/text/3529-cargo-path-bases.md
+++ b/text/3529-cargo-path-bases.md
@@ -30,7 +30,8 @@ relative paths (which makes refactoring and moving sub-projects very difficult)
 and don't work at all if the mono-repo requires publishing and consuming from an
 intermediate directory (as this may very per host, or per target being built).
 
-This RFC proposes a mechanism to specify `base` directories in `Config.toml` or
+This RFC proposes a mechanism to specify `base` directories in `config.toml` or
+
 `Cargo.toml` files which can be used to prepend `path` dependencies. This allows
 mono-repos to specify dependencies relative to their root directory, which
 allows the consuming project to be moved freely (no relative paths to update)
@@ -69,7 +70,8 @@ drive for performance reasons).
 path (e.g., `../../../other_layer/foo` and `../foo`) and may be error prone if
 there is some other sub-project in directory with the same name.
 
-Instead, if we could specify these `base` directories in a `Config.toml` (which
+Instead, if we could specify these `base` directories in a `config.toml` (which
+
 may be generated by an external build system which in turn invokes Cargo):
 
 ```toml
@@ -90,7 +92,8 @@ baz = { path = "this_layer/baz", base = "sources" }
 Which resolves the issues we previously had:
 
 * The current project can be moved without modifying the `Cargo.toml` at all.
-* `bar_with_generated` works for all targets (assuming the `Config.toml` is
+* `bar_with_generated` works for all targets (assuming the `config.toml` is
+
 generated).
 * The `intermediates` directory can be placed anywhere.
 * Moving `foo` or `baz` only requires searching for the canonical form relative
@@ -101,7 +104,8 @@ to the `base` directory.
 The ability to use `base` directories for `path` dependencies is convenient for
 developers who are using a large number of `path` dependencies within the same
 root directory. Instead of repeating the same path fragment many times in their
-`Cargo.toml`, they can instead specify it once in a `Config.toml` as a `base`
+`Cargo.toml`, they can instead specify it once in a `config.toml` as a `base`
+
 directory, then use that `base` directory in each of their `path` dependencies.
 
 Cargo can also provide built-in base paths, for example `workspace` to point to

From 707870d6c7bb94ffcbcace0c7dc7561e3ff60e62 Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao@microsoft.com>
Date: Wed, 26 Jun 2024 16:29:36 -0700
Subject: [PATCH 7/9] Remove support for manifest, rename to path-base

---
 text/3529-cargo-path-bases.md | 169 +++++++++++++++++++---------------
 1 file changed, 93 insertions(+), 76 deletions(-)

diff --git a/text/3529-cargo-path-bases.md b/text/3529-cargo-path-bases.md
index 3e94dff2da2..afafa78ac3e 100644
--- a/text/3529-cargo-path-bases.md
+++ b/text/3529-cargo-path-bases.md
@@ -30,7 +30,7 @@ relative paths (which makes refactoring and moving sub-projects very difficult)
 and don't work at all if the mono-repo requires publishing and consuming from an
 intermediate directory (as this may very per host, or per target being built).
 
-This RFC proposes a mechanism to specify `base` directories in `Config.toml` or
+This RFC proposes a mechanism to specify path bases in `Config.toml` or
 `Cargo.toml` files which can be used to prepend `path` dependencies. This allows
 mono-repos to specify dependencies relative to their root directory, which
 allows the consuming project to be moved freely (no relative paths to update)
@@ -69,16 +69,16 @@ drive for performance reasons).
 path (e.g., `../../../other_layer/foo` and `../foo`) and may be error prone if
 there is some other sub-project in directory with the same name.
 
-Instead, if we could specify these `base` directories in a `Config.toml` (which
-may be generated by an external build system which in turn invokes Cargo):
+Instead, if we could specify these common paths as path bases in a `Config.toml`
+(which may be generated by an external build system which in turn invokes Cargo):
 
 ```toml
-[base-paths]
+[path-bases]
 sources = "/home/user/dev/src"
 intermediates = "/home/user/dev/intermediates/x86_64/Debug"
 ```
 
-Then the `Cargo.toml` can use those `base` directories and avoid relative paths:
+Then the `Cargo.toml` can use those path bases and avoid relative paths:
 
 ```toml
 [dependencies]
@@ -94,15 +94,15 @@ Which resolves the issues we previously had:
 generated).
 * The `intermediates` directory can be placed anywhere.
 * Moving `foo` or `baz` only requires searching for the canonical form relative
-to the `base` directory.
+to the path base.
 
 ## Other uses
 
-The ability to use `base` directories for `path` dependencies is convenient for
+The ability to use path bases for `path` dependencies is convenient for
 developers who are using a large number of `path` dependencies within the same
 root directory. Instead of repeating the same path fragment many times in their
-`Cargo.toml`, they can instead specify it once in a `Config.toml` as a `base`
-directory, then use that `base` directory in each of their `path` dependencies.
+`Cargo.toml`, they can instead specify it once in a `Config.toml` as a path
+base, then use that path base in each of their `path` dependencies.
 
 Cargo can also provide built-in base paths, for example `workspace` to point to
 the root directory of the workspace. This allows workspace members to reference
@@ -111,20 +111,20 @@ each other without first needing to `../` their way back to the workspace root.
 # Guide-level explanation
 [guide-level-explanation]: #guide-level-explanation
 
-If you often use path dependencies that live in a particular location,
+If you often use multiple path dependencies that have a common parent directory,
 or if you want to avoid putting long paths in your `Cargo.toml`, you can
-define path _base directories_ in your Cargo [manifest](https://doc.rust-lang.org/cargo/reference/manifest.html)
-or [configuration](https://doc.rust-lang.org/cargo/reference/config.html).
-Your path dependencies can then be specified relative to those
+define path _base directories_ in your
+[configuration](https://doc.rust-lang.org/cargo/reference/config.html).
+Your path dependencies can then be specified relative to those base
 directories.
 
-For example, say you have a number of projects checked out in 
+For example, say you have a number of projects checked out in
 `/home/user/dev/rust/libraries/`. Rather than use that path in your
 `Cargo.toml` files, you can define it as a "base" path in
 `~/.cargo/config.toml`:
 
 ```toml
-[base-paths]
+[path-bases]
 dev = "/home/user/dev/rust/libraries/"
 ```
 
@@ -145,14 +145,13 @@ the path must exist on any other host where you want to use the same
 
 ## Specifying Dependencies
 
-### Base Paths
+### Path Bases
 
-A `path` dependency may optionally specify a base path by setting the `base` key
-to the name of a base path from the `[base-paths]` table in either the
-[manifest](https://doc.rust-lang.org/cargo/reference/manifest.html) or
-[configuration](https://doc.rust-lang.org/cargo/reference/config.html#base-paths)
-or one of the [built-in base paths](#built-in-base-paths). The value of that
-base path is prepended to the `path` value to produce the actual location where
+A `path` dependency may optionally specify a base by setting the `base` key to
+the name of a path base from the `[path-bases]` table in either the
+[configuration](https://doc.rust-lang.org/cargo/reference/config.html#path-bases)
+or one of the [built-in path bases](#built-in-path-bases). The value of that
+path base is prepended to the `path` value to produce the actual location where
 Cargo will look for the dependency.
 
 For example, if the Cargo.toml contains:
@@ -162,67 +161,51 @@ For example, if the Cargo.toml contains:
 foo = { path = "foo", base = "dev" }
 ```
 
-Given a `[base-paths]` table in the configuration that contains:
+Given a `[path-bases]` table in the configuration that contains:
 
 ```toml
-[base-paths]
+[path-bases]
 dev = "/home/user/dev/rust/libraries/"
 ```
 
 This will produce a `path` dependency `foo` located at
 `/home/user/dev/rust/libraries/foo`.
 
-Base paths can be either absolute or relative. Relative base paths are relative
-to the parent directory of the configuration or manifest file that declared that
-base path.
+Path bases can be either absolute or relative. Relative path bases are relative
+to the parent directory of the configuration file that declared that path base.
 
-The name of a base path must use only [alphanumeric](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphanumeric)
+The name of a path base must use only [alphanumeric](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphanumeric)
 characters or `-` or `_`, must start with an [alphabetic](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphabetic)
 character, and must not be empty.
 
-#### Built-in base paths
+If the name of path base used in a dependency is neither in the configuration
+nor one of the built-in path base, then Cargo will raise an error.
 
-Cargo provides implicit base paths that can be used without the need to specify
-them in a `[base-paths]` table.
+#### Built-in path base
+
+Cargo provides implicit path bases that can be used without the need to specify
+them in a `[path-bases]` table.
 
 * `workspace` - If a project is [a workspace or workspace member](https://doc.rust-lang.org/cargo/reference/workspaces.html)
-then this base path is defined as the parent directory of the root Cargo.toml of
+then this path base is defined as the parent directory of the root Cargo.toml of
 the workspace.
 
-#### Base paths resolution order
-
-Cargo will search for base paths in the following order:
-
-1. In the [configuration](https://doc.rust-lang.org/cargo/reference/config.html).
-1. In the [manifest](https://doc.rust-lang.org/cargo/reference/manifest.html)
-that is using the base path.
-1. In the workspace's [manifest](https://doc.rust-lang.org/cargo/reference/manifest.html).
-1. In the list of built-in base paths.
-
-If the base path is not found in during this search then Cargo will generate an
-error.
-
-Once a base path is found Cargo will stop searching, thus it is possible to
-shadow a base path by declaring it earlier in the search order. This allows the
-user's configuration to override the base path in a package, or for Cargo to add
-new built-in base paths without compatibility issues (as existing uses will
-shadow the built-in name).
-
-## The Manifest Format
-
-* Dependency tables:
-  * [`[base-paths]`](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#base-paths) - Base paths for path dependencies.
+If a built-in path base name is also declared in the configuration, then Cargo
+will prefer the value in the configuration. The allows Cargo to add new built-in
+path bases without compatibility issues (as existing uses will shadow the
+built-in name).
 
 ## Configuration
 
-`[base-paths]`
+`[path-bases]`
 
 * Type: string
 * Default: see below
-* Environment: `CARGO_BASE_PATHS_<name>`
+* Environment: `CARGO_PATH_BASES_<name>`
 
-The `[base-paths]` table defines a set of path prefixes that can be used to
-prepend the locations of `path` dependencies. See the [specifying dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#base-paths)
+The `[path-bases]` table defines a set of path prefixes that can be used to
+prepend the locations of `path` dependencies. See the
+[specifying dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#path-bases)
 documentation for more information.
 
 # Drawbacks
@@ -232,7 +215,7 @@ documentation for more information.
    `Cargo.toml` that may not be accessible when others try to build the
    same project. Specifically, it may now be that the other host has a
    `path` dependency available at the same relative path to `Cargo.toml`
-   as the author of the `Cargo.toml` entry, but does not have the `base`
+   as the author of the `Cargo.toml` entry, but does not have the path base
    defined (or has it defined as some other value).
 
    At the same time, this might make path dependencies _more_ re-usable
@@ -325,6 +308,28 @@ in strategic locations, cluttering their directories. The proposed
 mechanism is simple to understand and to use, and still covers a wide
 variety of use-cases.
 
+## Support for declaring path bases in the manifest
+
+Currently path bases only support being declared in the configuration, and not
+the manifest. While it would be possible to add support for declaring path bases
+in the manifest in the future (which would require specifying if the declaration
+in the manifest or configuration is prefered, and how workspace versus members
+declarations work), it is hard to justify the additional complexity of adding of
+adding this capability to the initial implementation of the feature.
+
+An argument could be made that specifying path bases in the manifest is a
+convenience feature, allowing a common path where multiple local dependencies
+exist to be specified as a path base so that the individual path dependencies
+would be shorter. However, it would be just as easy to add a configuration file
+to some parent directory of the dependent and this would be more useful as it is
+likely that those dependencies will also be used in other local packages thus
+saving the path bases table being duplicated in multiple manifests.
+
+It could also be argued that specifying path bases in the manifest would be a
+way to set "default values" for path dependencies (e.g., to a submodule) that a
+developer could override in their local configuration file. While this may be
+useful, this scenario is already taken care of by the `patch` feature in Cargo.
+
 # Prior art
 [prior-art]: #prior-art
 
@@ -376,24 +381,34 @@ could help.
 # Unresolved questions
 [unresolved-questions]: #unresolved-questions
 
-- What should the Cargo configuration table and dependency key be called? This
-  RFC calls the configuration table `base-paths` to be explicit that it is
-  dealing with paths (as `base` would be ambiguous) but calls the key `base` to
-  keep it concise.
-- Is there other reasonable behavior we could fall back to if a `base`
-  is specified for a dependency, but no base by that name exists in the
-  current Cargo configuration? This RFC suggests that this should be an
-  error, but perhaps there is a reasonable thing to try _first_ prior to
-  yielding an error.
-
 # Future possibilities
 [future-possibilities]: #future-possibilities
 
-It seems reasonable to extend `base` to `git` dependencies, with
-something like:
+## Path bases relative to other path bases
+
+We could allow defining a path base relative to another path base:
+
+```toml
+[path-bases]
+base1 = "/dev/me"
+base2 = { base = "base1", path = "some_subdir" } # /dev/me/some_subdir
+```
+
+## Path dependency with just a base
+
+We could allow defining a path dependency with *just* `base`, making
+`cratename = { base = "thebase" }` equivalent to
+`cratename = { base = "thebase", path = "cratename" }`. This would simplify many
+common cases, where crates appear within the base in a directory named for the
+crate.
+
+## Git dependencies
+
+It seems reasonable to extend path bases to `git` dependencies, with something
+like:
 
 ```toml
-[base-paths]
+[path-bases]
 gh = "https://github.com/jonhoo"
 ```
 
@@ -402,7 +417,9 @@ gh = "https://github.com/jonhoo"
 foo = { git = "foo.git", base = "gh" }
 ```
 
-However, this may get complicated if someone specifies `git`, `path`,
-_and_ `base`.
+However, this may get complicated if someone specifies `git`, `path`, _and_
+`base`.
+
+## Support patches
 
-It may also be useful to be able to use `base` for `patch` and `path`.
+It may also be useful to be able to use path bases in `patch` and `path` tables.

From c04201c9dbb5a1c7bbf5932bb29243340c6b5da8 Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao@microsoft.com>
Date: Wed, 24 Jul 2024 16:19:25 -0700
Subject: [PATCH 8/9] Address PR feedback

---
 text/3529-cargo-path-bases.md | 93 +++++++++++++++++++++++++++--------
 1 file changed, 73 insertions(+), 20 deletions(-)

diff --git a/text/3529-cargo-path-bases.md b/text/3529-cargo-path-bases.md
index 2146ccd3217..444aae7c78f 100644
--- a/text/3529-cargo-path-bases.md
+++ b/text/3529-cargo-path-bases.md
@@ -6,8 +6,11 @@
 # Summary
 [summary]: #summary
 
-Introduce shared base directories in Cargo configuration files that in
-turn enable base-relative `path` dependencies.
+Introduce a table of path "bases" in Cargo configuration files that can be used
+to prefix the path of `path` dependencies and `patch` entries.
+
+This feature will not support declaring path bases in manifest files to avoid
+additional design complexity, though this may be added in the future.
 
 # Motivation
 [motivation]: #motivation
@@ -30,14 +33,13 @@ relative paths (which makes refactoring and moving sub-projects very difficult)
 and don't work at all if the mono-repo requires publishing and consuming from an
 intermediate directory (as this may very per host, or per target being built).
 
-This RFC proposes a mechanism to specify path bases in `config.toml` or
-`Cargo.toml` files which can be used to prepend `path` dependencies. This allows
-mono-repos to specify dependencies relative to their root directory, which
-allows the consuming project to be moved freely (no relative paths to update)
-and a simple find-and-replace to handle a producing project being moved.
-Additionally, a host-specific or target-specific intermediate directory may be
-specified as a `base`, allowing code to be consumed from there using `path`
-dependencies.
+This RFC proposes a mechanism to specify path bases in `config.toml` files which
+can be used to prepend `path` dependencies. This allows mono-repos to specify
+dependencies relative to their root directory, which allows the consuming
+project to be moved freely (no relative paths to update) and a simple
+find-and-replace to handle a producing project being moved. Additionally, a
+host-specific or target-specific intermediate directory may be specified as a
+`base`, allowing code to be consumed from there using `path` dependencies.
 
 ### Example
 
@@ -105,7 +107,7 @@ root directory. Instead of repeating the same path fragment many times in their
 `Cargo.toml`, they can instead specify it once in a `config.toml` as a path
 base, then use that path base in each of their `path` dependencies.
 
-Cargo can also provide built-in base paths, for example `workspace` to point to
+Cargo will also provide built-in base paths, for example `workspace` to point to
 the root directory of the workspace. This allows workspace members to reference
 each other without first needing to `../` their way back to the workspace root.
 
@@ -141,6 +143,10 @@ Like with other path dependencies, keep in mind that both the base _and_
 the path must exist on any other host where you want to use the same
 `Cargo.toml` to build your project.
 
+You can also use `base` along with `path` when specifying a `[patch]`.
+Specifying a `path` and `base` on a `[patch]` is equivalent to specifying just a
+`path` containing the full path including the prepended base.
+
 # Reference-level explanation
 [reference-level-explanation]: #reference-level-explanation
 
@@ -152,10 +158,11 @@ A `path` dependency may optionally specify a base by setting the `base` key to
 the name of a path base from the `[path-bases]` table in either the
 [configuration](https://doc.rust-lang.org/cargo/reference/config.html#path-bases)
 or one of the [built-in path bases](#built-in-path-bases). The value of that
-path base is prepended to the `path` value to produce the actual location where
-Cargo will look for the dependency.
+path base is prepended to the `path` value (along with a path separator if
+necessary) to produce the actual location where Cargo will look for the
+dependency.
 
-For example, if the Cargo.toml contains:
+For example, if the `Cargo.toml` contains:
 
 ```toml
 [dependencies]
@@ -188,8 +195,8 @@ Cargo provides implicit path bases that can be used without the need to specify
 them in a `[path-bases]` table.
 
 * `workspace` - If a project is [a workspace or workspace member](https://doc.rust-lang.org/cargo/reference/workspaces.html)
-then this path base is defined as the parent directory of the root Cargo.toml of
-the workspace.
+then this path base is defined as the parent directory of the root `Cargo.toml`
+of the workspace.
 
 If a built-in path base name is also declared in the configuration, then Cargo
 will prefer the value in the configuration. The allows Cargo to add new built-in
@@ -209,6 +216,30 @@ prepend the locations of `path` dependencies. See the
 [specifying dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#path-bases)
 documentation for more information.
 
+## cargo add
+
+### Synopsis
+
+`cargo add` *[options]* `--path` *path* [`--base` *base*]
+
+### Options
+
+#### Source options
+
+`--base` *base*
+
+The [path base](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#path-bases)
+to use when adding from a local crate.
+
+## Workspaces
+
+Path bases can be used in a workspace's `[dependencies]` table.
+
+If a member is inheriting a dependency (i.e., using `workspace = true`) then the
+`base` key cannot also be specified for that dependency in the member manifest.
+That is, the member will use the `path` dependency as specified in the workspace
+manifest and has no ability to override the base path being used (if any).
+
 # Drawbacks
 [drawbacks]: #drawbacks
 
@@ -382,9 +413,35 @@ could help.
 # Unresolved questions
 [unresolved-questions]: #unresolved-questions
 
+* What exact names we should use for the table (`path-bases`) and field names
+(`base`)?
+* What other built-in base paths could be useful?
+  * `package` or `current-dir` for the directory of the current project?
+  * `home` or `user_home` for the user's home directory?
+  * `sysroot` for the current rustc sysroot?
+
 # Future possibilities
 [future-possibilities]: #future-possibilities
 
+## Add support for declaring path bases in the manifest
+
+As mentioned [above](#support-for-declaring-path-bases-in-the-manifest),
+declaring path bases is only supported in the configuration.
+
+Support could be added to declare path bases in the manifest, but the following
+design questions need to be answered:
+
+* Is `[path-bases]` a package or a workspace field?
+* If it is a package field, would it support workspace inheritance? Or would we
+introduce a new mechanism (e.g., one version of the RFC introduced a "search
+order" such that Cargo would search for a path base in the package manifest,
+then the workspace manifest, then the configuration and finally the built-in
+list).
+* Would a relative path base in the workspace manifest be relative to that
+manifest, or to the package that uses it?
+* If using inheritance, should path bases be implicitly or explicitly inherited?
+(e.g., requiring `[base-paths] workspace = true`)
+
 ## Path bases relative to other path bases
 
 We could allow defining a path base relative to another path base:
@@ -420,7 +477,3 @@ foo = { git = "foo.git", base = "gh" }
 
 However, this may get complicated if someone specifies `git`, `path`, _and_
 `base`.
-
-## Support patches
-
-It may also be useful to be able to use path bases in `patch` and `path` tables.

From 87672d5f61e527d15f1865f353c290a78d099bae Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao@microsoft.com>
Date: Mon, 5 Aug 2024 12:18:53 -0700
Subject: [PATCH 9/9] Add link to tracking issue

---
 text/3529-cargo-path-bases.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/text/3529-cargo-path-bases.md b/text/3529-cargo-path-bases.md
index 444aae7c78f..eb9c9793006 100644
--- a/text/3529-cargo-path-bases.md
+++ b/text/3529-cargo-path-bases.md
@@ -1,7 +1,7 @@
 - Feature Name: `path_bases`
 - Start Date: 2023-11-13
 - RFC PR: [rust-lang/rfcs#3529](https://github.com/rust-lang/rfcs/pull/3529)
-- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)
+- Rust Issue: [rust-lang/cargo#14355](https://github.com/rust-lang/cargo/issues/14355)
 
 # Summary
 [summary]: #summary