Skip to content
Open
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
80b9ddf
Create 0000-nested-publish.md
kpreid Jul 1, 2023
126b2b4
Clarify some terms and discuss workspaces and normalization
kpreid Jul 1, 2023
ef9a157
Discuss trait coherence relaxation
kpreid Jul 1, 2023
a1d4425
Reposition footnote-links
kpreid Jul 1, 2023
35184e0
Add PR number
kpreid Jul 1, 2023
c4dd372
Clarify `path` behavior and existing dev-dependency behavior
kpreid Jul 1, 2023
e71a953
Avoid "lockstep" and discuss a version duplication hazard
kpreid Jul 1, 2023
3da9eeb
Add Definitions section.
kpreid Jul 6, 2023
7f9c09f
Discuss more alternatives for marking packages; define "nested package"
kpreid Jul 6, 2023
130ceb0
Clarify “is private”
kpreid Jul 6, 2023
42bdb61
Require dependencies to be explicitly nested.
kpreid Feb 5, 2024
25d86b1
More motivation and drawbacks.
kpreid Feb 5, 2024
743d531
Define “nested publishing”.
kpreid Feb 5, 2024
34a19dc
Discuss postponed RFC 2224 as prior art.
kpreid Feb 5, 2024
b75a519
Mention vendoring.
kpreid Feb 5, 2024
d7e8dea
Discuss “subcrate dependencies” in prior art.
kpreid Feb 5, 2024
6670428
Discuss “Inline crates” in prior art.
kpreid Feb 5, 2024
da547de
Rewrite reference-level explanation to focus more on effects than cha…
kpreid Feb 5, 2024
b4923ac
Expand alternatives and move inline-crates discussion there.
kpreid Feb 5, 2024
68ad634
Move license and version ideas.
kpreid Feb 11, 2024
33d1c6e
Specify that package names must be unique.
kpreid Feb 11, 2024
680709c
Typo
kpreid Feb 11, 2024
2af4921
Mention feature flattening.
kpreid Feb 11, 2024
0deba10
Discuss workspace inheritance.
kpreid Feb 11, 2024
b999976
Move `dependencies.*.publish = false` to future possibilities.
kpreid Feb 11, 2024
3edb308
Replace `package.publish = "nested"` with `package.publish.nested = t…
kpreid Feb 11, 2024
dd90f20
Refine explanation of `package.publish` being a table.
kpreid Feb 11, 2024
07b058d
Rephrase name conflict rule to avoid "transitive closure".
kpreid Mar 11, 2024
2c220ee
Always error on `workspace.dependencies.*.publish`.
kpreid Mar 11, 2024
4bc77cb
Rewrite feature flattening section.
kpreid Mar 11, 2024
e470314
Rationale for name uniqueness.
kpreid Mar 13, 2024
2a5474e
Polishing.
kpreid Mar 13, 2024
db9e7fa
Update comparison with packages-as-namespaces given that that RFC has…
kpreid Mar 13, 2024
4817861
Explicitly state that nested names are non-unique *outside* of the pa…
kpreid Mar 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
More motivation and drawbacks.
  • Loading branch information
kpreid committed Feb 5, 2024
commit 25d86b106c946308b495b4e954ed8002faf9cfd2
11 changes: 9 additions & 2 deletions text/0000-nested-publish.md
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A minor question: If a Git repository contains a package with nested packages, can the other package depends on any of those nested packages as a Git dependency? Currently Git dependency searches packages whose name matches recursively inside the repository.

Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ Currently, developers must publish these packages separately. This has several d

This RFC will allow developers to avoid all of these inconveniences and hazards by publishing a single package.

Additionally, it may sometimes be desirable to share a small amount of code between some published packages, without making the shared code a separately published library with an appropriate public API.
There are also some uses which are not strictly cases of one library package versus multiple library packages:

* It may sometimes be desirable to share a small amount of code between some published packages, without making the shared code a separately published library with an appropriate public API subject to semver.
* A package intended to distribute a binary or binaries may have a library target for internal purposes (such as sharing modules between multiple binaries, or testing), but not intend for that library to be usable by other packages as a dependency.

# Definitions
[definitions]: #definitions
Expand Down Expand Up @@ -129,6 +132,7 @@ The following changes must be made across Cargo and `crates.io`:
* the named package declares `package.publish = "nested"`.

The path must not contain any upward traversal (`../`) or other hazardous or non-portable components.
* The package index does not explicitly represent nested packages; instead, nested packages' dependencies are flattened into the dependencies of the parent package. This accurately reflects what can be expected when using the parent package.
* No changes are needed to the `crates.io` index, because nested packages are an implementation detail of their parent package.
* **Build process**
* Probably some messages will need to be adjusted; currently, `path` dependencies' full paths are always printed in progress messages, but they would be long noise here (`/home/alice/.cargo/registry/src/index.crates.io-6f17d22bba15001f/...`). Perhaps progress for sub-packages could look something like “`Compiling foo/macros v0.1.0`”.
Expand All @@ -139,10 +143,13 @@ The presence or absence of a `[workspace]` has no effect on the new behavior, ju
[drawbacks]: #drawbacks

* This increases the number of differences between “Cargo package (on disk)” from “Cargo package (that may be published in a registry, or downloaded as a unit)” in a way which may be confusing; it would be good if we have different words for these two entities, but we don't.
* If Cargo were to add support for multiple library targets per package, that would be largely redundant with this feature.
* It is not possible to publish a bug fix to a nested package without republishing the entire parent package; this is the cost we pay for the benefit of not needing to take care with versioning for nested packages.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, for the proc-macro case, = version requirements are frequently used and so both would need to be published anyways in that case.

* Suppose `foo` has a nested package `foo-core`. Multiple major versions of `foo` cannot share the same instance of `foo-core` as they could if `foo-core` were separately published and the `foo`s depended on the same version of `foo-core`. Thus, choosing nested publication may lead to type incompatibilities (and greater compile times) that would not occur if the same libraries had been separately published.
* If this situation comes up, it can be recovered from by newly publishing `foo-core` separately (as would have been done if nested publishing were not used) and using the [semver trick](https://github.com/dtolnay/semver-trick) to maintain compatibility.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semver trick does solve this problem, but only when those package bumps their MSRV, so this feature won't get adopted until some point. Some popular crates using proc-macros hold a relatively conservative MSRV. The adoption rate might be mild annoying in the short-mid term.
(Granted, other alternatives would have the same issue)

* Support for duplicative nested publication (that is, nested packages that are nested within more than one parent package) has the following consequences:
* May increase the amount of source code duplicated between different published packages, increasing download sizes and compilation time. It's currently possible to duplicate code into multiple packages via symlinks, but this would make it an “official feature”.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Along with this, as a side effect, this might provide an easier route for people to vendor code more than it was. The Rust ecosystem is different from 5 years ago, but the initial idea of Cargo/crates.io is to encourage everybody to publish and share codes. And whenever possible, play nice and help fix bugs in upstream.

Again, Rust is not Rust anymore. The old rules might not suitable nowadays since enterprise and other large projects starts using it more. Regardless, the potential consequence of paradigm shift is something we need to be aware of.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Along with this, as a side effect, this might provide an easier route for people to vendor code more than it was.

At first I wasn't too concerned about it but then I thought of what insta had to do to vendor yaml-rust. They have to copy the code in, merge any dependencies, and update any crate:: relative references.

With this feature, its copy the package directory in, mark it as nested, and you are done.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking over #2224, two of the participants specifically called out wanting to use it for private forks :/

* If packages A and B are separately published with nested package C, and A also depends on B, then A may see two copies of C's items, one direct and one transitive. This may cause a set of packages to fail to compile due to type/trait mismatches when published. [RFC 3516 public/private dependencies](https://rust-lang.github.io/rfcs/3516-public-private-dependencies.html) may be able to reduce problems of this type if we encourage, by documentation and lint, authors to think twice before allowing a multiply-used nested dependency to also be a RFC 3516 public dependency.
* Build and packaging systems that replace or wrap Cargo (e.g. mapping Cargo packages into Linux distribution packages) may have 1 library:1 package assumptions that are broken by this change.

# Rationale and alternatives
[rationale-and-alternatives]: #rationale-and-alternatives
Expand Down