# Anonymous utilities crates

**URL:** <https://internals.rust-lang.org/t/anonymous-utilities-crates/22504>\
**Category:** cargo\
**Created:** [March 4, 2025, 8:05pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504 "2025-03-04T20:05:54Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [March 4, 2025, 8:05pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/1 "2025-03-04T20:05:54Z")

</div>

It seems like often when I have crates in a workspace, I run into situations where I want to use some utility code private to multiple crates, in which case I have two non-ideal options:

1. Duplicate the code in question in both crates
2. Make a 3rd crate for the shared utilities, and live with semver forever

These are typically just internal implementation details that making public only reduces flexibility. It occurred to me that it might be possible to introduce a 3rd option, by adding a 3rd kind of crate which here I am calling an "anonymous utility crate", the general idea is that it would be able to be depended upon by crates in the same workspace, but crates outside of the workspace would not be able to add a dependency to it.

With that, the consequences of making the API public would be much reduced because the ability to introduce a dependency is still reserved by the workspace.

I can only imagine this has probably come up before, but I can't recall it?

---

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [March 4, 2025, 8:12pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/2 "2025-03-04T20:12:02Z")

</div>

FYI [nested packages](https://github.com/rust-lang/rfcs/pull/3452) has been discussed but ran into issues with the Index.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [March 4, 2025, 8:29pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/3 "2025-03-04T20:29:27Z")

</div>

A concept of workspaces doesn’t (currently) exist on [crates.io](http://crates.io), so I’m not sure what mechanism could allow…

> [@ratmice](#):
>
> that it would be able to be depended upon by crates in the same workspace, but crates outside of the workspace would not be able to add a dependency to it

You aren’t trying to address problems only in the context of _local_ crates, are you?

* * *

As far as I understand the discussion in the RFC @epage linked above, that one doesn’t address use-cases where a “utility crate” is supposed to be _shared_ between multiple packages (without _effectively_ code-duplication\[1\], anyway), or am I missing something?

* * *

1. perhaps just _automated_ code duplication through the publishing process?

---

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [March 4, 2025, 8:47pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/4 "2025-03-04T20:47:21Z")

</div>

> [@steffahn](#):
>
> A concept of workspaces doesn’t (currently) exist on [crates.io](http://crates.io), so I’m not sure what mechanism could allow…
> 
> that it would be able to be depended upon by crates in the same workspace, but crates outside of the workspace would not be able to add a dependency to it

My main thought was to avoid adding a notion of workspace to [crates.io](http://crates.io) by leverage characters that weren't valid crate names in the "naming" of anonymous utility crates. That is to say to pick a random unicode character and prefix a crate name with that (perhaps even a completely random name). Then allow that name to be used in Cargo.lock but not valid to appear in dependencie section of Cargo.toml.

It occurs to me that that may not work though, because I believe at least last time I looked that crate name validity was an aspect of [crates.io](http://crates.io) and not Cargo.

> [@steffahn](#):
>
> You aren’t trying to address problems only in the context of _local_ crates, are you?
> 
> * * *

I don't exactly understand what you mean by _local_ only, I have 2 crates, _crate-a_ and _crate-b_, both are _library_ crates, and published to [crates.io](http://crates.io), and exist in a single workspace, one crate depends on the other, and both want to use the shared utilities, neither wants to expose the shared utilities as part of their public API (but I don't feel like that needs to be enforced for this to be useful).

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [March 4, 2025, 8:52pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/5 "2025-03-04T20:52:13Z")

</div>

> [@ratmice](#):
>
> I don't exactly understand what you mean by _local_ only

I just meant “situations not involving [crates.io](http://crates.io) (or other registries)” though I do suppose your mention of _semver_ should have made it clear to me already that this _is_ about crate registries 😇

---

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [March 4, 2025, 9:19pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/6 "2025-03-04T21:19:01Z")

</div>

> [@steffahn](#):
>
> As far as I understand the discussion in the RFC @epage linked above, that one doesn’t address use-cases where a “utility crate” is supposed to be _shared_ between multiple packages (without _effectively_ code-duplication[[1]](#footnote-143434-1), anyway), or am I missing something?

Yeah, that is the impression I get from the rfc, still automated code duplication would be an improvement over what I currently do (duplicate code between crates since amazingly making it public somehow manages to seem even _worse_).

But using the a the trick I mentioned above for valid crate name for _crate resolution_ but invalid crate name for _specifying dependencies_ the intent was that these utility crates would be actually shared.

---

<div class="post-metadata">

**Author:** ![CodesInChaos](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/codesinchaos/32/5211_2.png) [@CodesInChaos](https://internals.rust-lang.org/u/CodesInChaos)\
**Post date:** [March 5, 2025, 1:22pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/7 "2025-03-05T13:22:22Z")

</div>

I haven't tried it, but perhaps something like this could work to avoid duplicating the code?

```rust
#[path = "../shared/mod.rs"]
mod shared;

```

---

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [March 5, 2025, 2:53pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/8 "2025-03-05T14:53:24Z")

</div>

The only workaround that I know of that would make this work when publishing to [crates.io](http://crates.io) is to do something like `git clone` during _build.rs_, because `../shared` ends up outside the crate package source tree for at least one of the crates. I haven't considered that workaround viable though, because it has all kinds of downsides.

---

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [March 5, 2025, 3:08pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/9 "2025-03-05T15:08:47Z")

</div>

If you have a symlink, `cargo package` / `cargo publish` will follow it and include the files.

The downside being that this puts constraints on Windows contributors (must enable symlink support, ensure git has symlink support enabled)

---

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [March 5, 2025, 4:17pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/10 "2025-03-05T16:17:22Z")

</div>

It occurs to me there is another similar approach, of using multiple instances of a git submodule, which is maybe more windows friendly.

I think the inconveniences of all these solutions are likely to end up worse than just copying the code unfortunately.

---

<div class="post-metadata">

**Author:** ![carols10cents](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/carols10cents/32/98_2.png) [@carols10cents](https://internals.rust-lang.org/u/carols10cents)\
**Post date:** [March 6, 2025, 9:46pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/11 "2025-03-06T21:46:57Z")

</div>

I think it would be fine to publish a crate with a description of something like "Internal implementation details for [name of your project] only; depending on this crate directly is not recommended" and give it a semver starting with `0.`. That would strongly discourage another crate from depending on it, and it would be very clear that breakage to the public API should be expected if someone does choose to depend on it.

Is there a scenario you're concerned about that would only be solved by forbidding any dependency on the internal crate?

---

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [March 6, 2025, 10:44pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/12 "2025-03-06T22:44:09Z")

</div>

I guess the reason I hesitate to do that is because if one goes the route of reading code, copy/pasting the dependency from some code where it is intended to be used, and then some line of code they may never encounter the description or read the docs.

More than anything it is the principle of the idea that publishing a crate should come hand in hand with the participation towards compatibility guarantees, these types of crates have no intention ever being stable. So right or wrong, it feels to me like it is diluting the strength of semver by both being a crate and never participating in the stability guarantees.

In that sense I'd rather save my "I told you so's" for people clearly working around the intent by downloading the crate/building an rlib, over people who may accidentally copy/paste some internal usage, or had an AI generate code which used a crate which was intended to be internal.

---

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [March 6, 2025, 10:48pm UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/13 "2025-03-06T22:48:43Z")

</div>

> [@ratmice](#):
>
> More than anything it is the principle of the idea that publishing a crate should come hand in hand with the participation towards compatibility guarantees, these types of crates have no intention ever being stable. So right or wrong, it feels to me like it is diluting the strength of semver by both being a crate and never participating in the stability guarantees.

You'd still need to follow semver in these crates or Cargo could end up picking an incompatible version. However, semver never says you have to hit 1.0 and then never go to 2.0. Whether to keep your majors low or not is dependent on the product you are creating.

---

<div class="post-metadata">

**Author:** ![binarycat](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/binarycat/32/12210_2.png) [@binarycat](https://internals.rust-lang.org/u/binarycat)\
**Post date:** [March 7, 2025, 1:37am UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/14 "2025-03-07T01:37:48Z")

</div>

you could even give it a `0.0.x` version to emphasize that you shouldn't be using it.

---

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [March 7, 2025, 1:43am UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/15 "2025-03-07T01:43:55Z")

</div>

I guess what I would say is in our current situation, where none of this code is `pub`, and there is no separate version which is distinct from the version of crate-a and crate-b themselves is pretty ideal for our use case. inventing a nonsense version and doing a breaking change for _every_ release is still less ideal than just not making it `pub` in the first place.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [August 29, 2026, 1:44am UTC](https://internals.rust-lang.org/t/anonymous-utilities-crates/22504/16 "2026-08-29T01:44:10Z")

</div>

Closed on August 29, 2026, 1:44am UTC

This topic was automatically closed 540 days after the last reply. New replies are no longer allowed.
