+1 to treat crate names as identifiers and forbid hyphens. Lets take the pain now rather than live in pain forever.
I’d also advocate just removing hyphens and requiring underscores, at least for 1.0. Post-1.0, new facilities (like namespaces) could be added, and restrictions on names can be loosened if it’s determined that they are too tight, but it’d be impossible to tighten the symbol-naming restrictions post-1.0 in a backwards-compatible way. So the safe path forward seems (to me) to be using the more-restrictive option until the less-restrictive option gets more fully fleshed out.
For whatever it’s worth, I also prefer hyphens to underscores aesthetically, and I also like the ability to rename crates on import, so the status-quo isn’t that bad, for me. BUT I also feel like the current design is not that future-proof (if something like namespaces get folded in, in particular), so rather than have 1.0 block on getting the right design right now, I’d like to see the current behavior stripped to its future-proof essence, so that a better facility could be added even after 1.0 (if that’s how long it takes to design).
For esthetic reasons I prefer dashes in file names, however I agree that having crate names as valid Rust identifiers is a strong reason to disallow them. For Rust adoption in the enterprise we should add namespaces at some point and it will remove namespace as an use case for dashes.
Should I start a separate RFC for namespaces or has this already been discussed and decided upon?
+1 for forbidding dashes to stay consistent with identifiers. When I was learning Cargo I got the false impression that hyphens were a de-facto standard, and then got totally tripped up on where to use a dash vs. an underscore in the repo name, the .toml name, the name in the import statement, etc… This is part of the reason I have referred to the module system as non-obvious in some other threads. New users should not have to think about this; they should just see that everyone is using underscores everywhere, follow that, and have things “just work”.
Keep in mind that the vast majority of Rust code has never been written, most Rust users have not even tried Rust yet, and most of the code out there now will be broken before 1.0 anyway.
@retep998, thanks for being so gracious about this proposal; I hope it is both fixed AND you get a convient migration path!
What about repurposing using the
#[link] attribute (or creating a new one, if that’s confusing) to set the crate name (and presumably allowing dots too), instead of having special syntax for this?
#[link(name = "windows.data.pdf.lib")] extern crate windows_pdf;
@DanielKeep are you still working on this?
I very much support this proposal, and would be happy to pick up where you left off.
I’m partway through writing up the revised version, taking the comments into account.
The hard part is… looks around I really want hyphens to stay on in some form, but I can’t reconcile that with the overwhelming “only idents everywhere” position that is, logically, the most reasonable: no rule to have it explain is better than any rule that has to be explained.
At this point, I’m just going to have to just lie in the bed I made and work out how in the hell to transition retep’s twenty zillionty hyphenated packages.
I might leave the door open by writing it up as “no hyphens anywhere at all… at least until after 1.0”.
I would favor using hyphens in package names but simply having a convention, perhaps enforced by Cargo by default, that hyphenated package names produce underscored crate names.
You can already name the “lib” crate name for a package to whatever you want, I believe.
I think we can implement that as a lint in
Something like this:
warning: crate names with hyphens ("foo-bar") are awkward to use, #[warn(hyphenated_names)] on by default help: consider renaming the crate with #![crate_name="foo_bar"]
That’s one idea! The help might be better if it were more Cargo-oriented, since the preferred way to specify a Cargo crate (not package name) is to use
[lib] name = "whatever".
[package] name = "iron-fizzbuzz-middleware" version = "0.0.1" authors = ["Tom Jakubowski <firstname.lastname@example.org>"] [lib] name = "iron_fizzbuzz_middleware" # or even "fizzbuzz_middleware", to use pseudo package namespacing
EDIT: See better proposal below
Of course! Would something like this:
warning: crate names with hyphens ("foo-bar") are awkward to use, #[warn(hyphenated_names)] on by default help: consider renaming the crate in your Cargo.toml: [lib] name = "foo_bar" help: alternatively, add #![crate_name="foo_bar"] to the crate root
work for you? It’s hard to explain the whole fix without bloating the message too much; I think it can be tweaked more.
I want to keep it as a
rustc lint, because:
Hyphenated names are awkward in general, not just with Cargo-ified libraries;
If the user really wants a hyphenated crate name, they can silence the warning using the existing infrastructure (
-A). I don’t think there’s a good way to silence Cargo warnings (feel free to correct me on this).
Actually it would be nice if
rustc detected if it was being called by Cargo or not, and gave an appropriate suggestion based on that. Maybe an environment variable or something. But I’m not sure whether that’s worth the extra complexity in the compiler.
The more I think about it, the more I’m convinced that we should just have Cargo warn unconditionally on hyphenated crate (not package) names. Someone along the line will need to rename the crate anyway; better it be the maintainer, not the user.
People who don’t use Cargo will miss out on the warning, but I think we can live with that.
EDIT: Okay, I think I’ve got it down to a concrete proposal:
If a user invokes
cargo newwith a hyphenated name, and the
--binoption is not present, automatically apply the Jakubowski renaming trick on the crate name (not the package name).
- Rationale: Hyphenated names are bad for library crates, but for executables it doesn’t matter.
If an existing (library) package has a hyphenated crate name (not the package name), Cargo should warn every time the package is built. The warning should include a short explanation of the problem, plus a snippet that the user can paste right into their Cargo.toml.
On crates.io, reject any new uploads which would warn under part 2. This change can come after a grace period, so that everyone has a chance to be warned in Cargo first.
I came into this thread expecting to be completely against it (I’m a big believer in aesthetics) but these proposals sound eminently reasonable to me. I’d prefer if we could use hyphenated identifiers of course, but that’s a much bigger change :D
I’ve had to step away from Rust things (actually almost all things) lately, and I can’t finish up the RFC. @lfairy, as you already asked about this, I would appreciate it if you’d see it to the end.
My advice, given the rapidly approaching beta release is to go with this:
Immediately deprecate hyphens if feasible, given where the check is in the compiler. If not, forbid. This should preferably only apply to extern crates, but this can be changed backward-compatibly later for binaries.
Add renaming support to Cargo. Full dependencies can use a
link-assetting. Short dependencies could be extended to use something like:
rustc_serialize = "rustc-serialize @ ^0.1"; a word followed by
@is the renaming part.
Adjust crates.io to show this pre-renamed syntax for existing crates with hyphens.
The above should be done preferably before beta, definitely before 1.0. Other issues, like whether or not to block new hyphenated crates, etc. can be dealt with later in a backward-compatible fashion.
This also will hopefully cause a minimum of disruption: it requires only a minor front-end change to crates.io and no changes to the backend (hopefully).
Again, apologies for dropping the ball on this.
Sure thing. I’m working on it on-and-off between classes; it’s slow going but I’ve got a clear idea of what to do now.
Note that as @tomjakubowski said above, the Cargo package name and the rustc crate name are orthogonal and can be defined separately. Hyphens only present a problem in the latter. With that in mind, points 2 and 3 are unnecessary. My draft so far is actually quite short, as it only has to deal with your point 1.
As an aside, a few days ago I side-tracked into repurposing hyphens as namespace separators. But that wound up too complicated so I dropped it. I’m back to banning the things now.