What if this sort of feature was enabled by having a private_members field in [workspace]. I.e.
[workspace]
members = ["path/to/public/member"]
private_members = ["path/to/private/member"]
Disallowing this for virtual manifests would probably be best, since the underlying implementation would add the content of the crate into the package of the root manifest.
Allowing only all private or all public workspaces (ignoring the root) would be analogous to the primary use case of the original proposal, though it would be possible to allow specifying workspaces with both and have various options for how to resolve which packages contained which private crates. I’d suggest just starting with the simple cases.
This seems to have the same implementation complexity (in terms of bundling multiple crates into a single package) but avoids having multiple ways of specifying the same sort of construct. cargo new and cargo init already handle workspace configuration (well, the docs claim they do), so adding a --private flag would allow people to get the right configuration without significantly changing their workflow.
I like the idea, mostly due to the benefits of crates for layering (dependency management), I just don’t want to have two completely distinct ways of specifying the same idea when adding 1 key to a config can accomplish the same thing.
Note, an alternative format could be:
[workspace]
[[members]]
path = "path/to/public/member"
[[members]]
path = "path/to/private/member"
private = true
This would result in members always being an array, either of strings or tables, but unfortunately, this would mostly just be more verbose and likely result in people confused by errors when they try to mix tables and strings or declare members twice, etc.