Skip to content

Commit 3b194da

Browse files
committed
Rewrite RFC
* Allow hyphens in the package name (but not the crate) * De-quotify crate renaming syntax
1 parent 2baf8d3 commit 3b194da

File tree

1 file changed

+31
-64
lines changed

1 file changed

+31
-64
lines changed

text/0000-hyphens-considered-harmful.md

Lines changed: 31 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5,110 +5,77 @@
55

66
# Summary
77

8-
Disallow hyphens in package and crate names. Propose a clear transition path for existing packages.
8+
Disallow hyphens in Rust crate names, but continue allowing them in Cargo packages.
99

1010
# Motivation
1111

12-
Currently, Cargo packages and Rust crates both allow hyphens in their names. This is not good, for two reasons:
12+
This RFC aims to reconcile two conflicting points of view.
1313

14-
1. **Usability**: Since hyphens are not allowed in identifiers, anyone who uses such a crate must rename it on import:
14+
First: hyphens in crate names are awkward to use, and inconsistent with the rest of the language. Anyone who uses such a crate must rename it on import:
1515

16-
```rust
17-
extern crate "rustc-serialize" as rustc_serialize;
18-
```
19-
20-
This boilerplate confers no additional meaning, and is a common source of confusion for beginners.
21-
22-
2. **Consistency**: Nowhere else do we allow hyphens in names, so having them in crates is inconsistent with the rest of the language.
23-
24-
For these reasons, we should work to remove this feature before the beta.
25-
26-
However, as of January 2015 there are 589 packages with hyphens on crates.io. It is unlikely that simply removing hyphens from the syntax will work, given all the code that depends on them. In particular, we need a plan that:
16+
```rust
17+
extern crate "rustc-serialize" as rustc_serialize;
18+
```
2719

28-
* Is easy to implement and understand;
20+
An earlier version of this RFC aimed to solve this issue by removing hyphens entirely.
2921

30-
* Accounts for the existing packages on crates.io; and
22+
However, there is a large amount of precedent for keeping `-` in package names. Systems as varied as GitHub, npm, RubyGems and Debian all have an established convention of using hyphens. Disallowing them would go against this precedent, causing friction with the wider community.
3123

32-
* Gives as much time as possible for users to fix their code.
24+
Fortunately, Cargo presents us with a solution. It already separates the concepts of *package name* (used by Cargo and crates.io) and *crate name* (used by rustc and `extern crate`). We can disallow hyphens in the crate name only, while still accepting them in the outer package. This solves the usability problem, while keeping with the broader convention.
3325

3426
# Detailed design
3527

36-
1. On **crates.io**:
37-
38-
+ Reject all further uploads for hyphenated names. Packages with hyphenated *dependencies* will still be allowed though.
39-
40-
+ On the server, migrate all existing hyphenated packages to underscored names. Keep the old packages around for compatibility, but hide them from search. To keep things simple, only the `name` field will change; dependencies will stay as they are.
41-
42-
2. In **Cargo**:
28+
## Disallow hyphens in crates (only)
4329

44-
+ Continue allowing hyphens in package names, but treat them as having underscores internally. Warn the user when this happens.
30+
In **Cargo**, continue allowing hyphens in package names. But unless the `Cargo.toml` says otherwise, the inner crate name will have all hyphens replaced with underscores.
4531

46-
This applies to both the package itself and its dependencies. For example, imagine we have an `apple-fritter` package that depends on `rustc-serialize`. When Cargo builds this package, it will instead fetch `rustc_serialize` and build `apple_fritter`.
32+
For example, if I had a package named `apple-fritter`, its crate will be named `apple_fritter` instead.
4733

48-
3. In **rustc**:
34+
In **rustc**, enforce that all crate names are valid identifiers. With the changes in Cargo, existing hyphenated packages should continue to build unchanged.
4935

50-
+ As with Cargo, continue allowing hyphens in `extern crate`, but rewrite them to underscores in the parser. Warn the user when this happens.
36+
## Identify `-` and `_` on crates.io
5137

52-
+ Do *not* allow hyphens in other contexts, such as the `#[crate_name]` attribute or `--crate-name` and `--extern` options.
38+
Right now, crates.io compares package names case-insensitively. This means, for example, you cannot upload a new package named `RUSTC-SERIALIZE` because `rustc-serialize` already exists.
5339

54-
> Rationale: These options are usually provided by external tools, which would break in strange ways if rustc chooses a different name.
40+
Under this proposal, we will extend this logic to identify `-` and `_` as well.
5541

56-
4. Announce the change on the users forum and /r/rust. Tell users to update to the latest Cargo and rustc, and to begin transitioning their packages to the new system. Party.
42+
## Remove the quotes from `extern crate`
5743

58-
5. Some time between the beta and 1.0 release, remove support for hyphens from Cargo and rustc.
44+
Change the syntax of `extern crate` so that the crate name is no longer in quotes (e.g. `extern crate photo_finish as photo;`). This is viable now that all crate names are valid identifiers.
5945

60-
## C dependency (`*-sys`) packages
61-
62-
[RFC 403] introduced a `*-sys` convention for wrappers around C libraries. Under this proposal, we will use `*_sys` instead.
63-
64-
[RFC 403]: https://github.com/rust-lang/rfcs/blob/master/text/0403-cargo-build-command.md
46+
To ease the transition, keep the old `extern crate` syntax around, transparently mapping any hyphens to underscores. For example, `extern crate "silver-spoon" as spoon;` will be desugared to `extern crate silver_spoon as spoon;`. This syntax will be deprecated, and removed before 1.0.
6547

6648
# Drawbacks
6749

68-
## Code churn
50+
## Inconsistency between packages and crates
6951

70-
While most code should not break from these changes, there will be much churn as maintainers fix their packages. However, the work should not amount to more than a simple find/replace. Also, because old packages are migrated automatically, maintainers can delay fixing their code until they need to publish a new version.
52+
This proposal makes package and crate names inconsistent: the former will accept hyphens while the latter will not.
7153

72-
## Loss of hyphens
54+
However, this drawback may not be an issue in practice. As hinted in the motivation, most other platforms have different syntaxes for packages and crates/modules anyway. Since the package system is orthogonal to the language itself, there is no need for consistency between the two.
7355

74-
There are two advantages to keeping hyphens around:
56+
## Inconsistency between `-` and `_`
7557

76-
* Aesthetics: Hyphens do look nicer than underscores.
58+
Quoth @P1start:
7759

78-
* Namespacing: Hyphens are often used for pseudo-namespaces. For example in Python, the Django web framework has a wealth of addon packages, all prefixed with `django-`.
60+
> ... it's also annoying to have to choose between `-` and `_` when choosing a crate name, and to remember which of `-` and `_` a particular crate uses.
7961
80-
The author believes the disadvantages of hyphens outweigh these benefits.
62+
I believe, like other naming issues, this problem can be addressed by conventions.
8163

8264
# Alternatives
8365

8466
## Do nothing
8567

8668
As with any proposal, we can choose to do nothing. But given the reasons outlined above, the author believes it is important that we address the problem before the beta release.
8769

88-
## Disallow hyphens in crates, but allow them in packages
89-
90-
What we often call "crate name" is actually two separate concepts: the *package name* as seen by Cargo and crates.io, and the *crate name* used by rustc and `extern crate`. While the two names are usually equal, Cargo lets us set them separately.
91-
92-
For example, if we have a package named `lily-valley`, we can rename the inner crate to `lily_valley` as follows:
93-
94-
```toml
95-
[package]
96-
name = "lily-valley" # Package name
97-
# ...
98-
99-
[lib]
100-
name = "lily_valley" # Crate name
101-
```
102-
103-
This will let us import the crate as `extern crate lily_valley` while keeping the hyphenated name in Cargo.
70+
## Disallow hyphens in package names as well
10471

105-
But while this solution solves the usability problem, it still leaves the package and crate names inconsistent. Given the few use cases for hyphens, it is unclear whether this solution is better than just disallowing them altogether.
72+
An earlier version of this RFC proposed to disallow hyphens in packages as well. The drawbacks of this idea are covered in the motivation.
10673

10774
## Make `extern crate` match fuzzily
10875

109-
Alternatively, we can have the compiler consider hyphens and underscores as equal while looking up a crate. In other words, the crate `flim-flam` would match both `extern crate flim_flam` and `extern crate "flim-flam" as flim_flam`. This will let us keep the hyphenated names, without having to rename them on import.
76+
Alternatively, we can have the compiler consider hyphens and underscores as equal while looking up a crate. In other words, the crate `flim-flam` would match both `extern crate flim_flam` and `extern crate "flim-flam" as flim_flam`.
11077

111-
The drawback to this solution is complexity. We will need to add this special case to the compiler, guard against conflicting packages on crates.io, and explain this behavior to newcomers. That's too much work to support a marginal use case.
78+
This involves much more magic than the original proposal, and it is not clear what advantages it has over it.
11279

11380
## Repurpose hyphens as namespace separators
11481

@@ -131,7 +98,7 @@ mod hoity {
13198
}
13299
```
133100

134-
However, on prototyping this proposal, the author found it too complex and fraught with edge cases. Banning hyphens outright would be much easier to implement and understand.
101+
However, on prototyping this proposal, the author found it too complex and fraught with edge cases. For these reasons the author chose not to push this solution.
135102

136103
# Unresolved questions
137104

0 commit comments

Comments
 (0)