Mini RFC - merge `cargo-edit` into cargo, and allow both `_` and `-` in `Cargo.toml` dependency names

NOTE rewritten from earlier version.

Explanation

Currently, if you type in a crate name like proc-macro2 as proc_macro2 you will get an error, with a message suggesting the correct combination of - and _ (in this case proc-macro2). This is a paper-cut, as no packages are allowed on crates.io that are equivalent to proc-macro2 w.r.t. swapping -s and _s. I’m going to say that two crates are equivalent if you can make one from another by swapping -s and _s.

This RFC proposes to

  1. When cargo finds a crate in Cargo.toml that is equivalent to another crate, it uses that crate and emits a warning.

For implementation, I would expect that the name is fixed as part of writing Cargo.lock, and that within cargo the name has already been resolved. Otherwise, you need custom impl of == for crate names, which would be more work. The warning would also encourage users to fix their Cargo.toml.

Arguments for

  1. This is a paper-cut that is mildly annoying and inconvenient, with an easy fix.

Arguments against

  1. It needs implementing. Crate names in Cargo.lock may not match Cargo.toml

Alternatives

  • Merge cargo-edit into cargo. We could still do this, but I think currently no cargo tools will rewrite your Cargo.toml file. This would change if these commands were added. I think some users will still prefer the choice of how to add their own dependencies, like with package.json and npm add --save.
  • Implement the equivalence between crate names throughout cargo.

Questions

  • Should cargo-edit be merged into cargo as well?
  • Should we encourage one style of package name (either with -s or _s)?
1 Like

I agree that we should just treat - and _ as identical through the entire stack. It’s more consistent imho, as they’re considered equivalent on crates-io.

I don’t agree on normalizing everything to _ – I prefer - personally, and you can have very useful conventions for semantics between the two (e.g. the package wow-use_this containing the crate use_this).

The big thing to keep in mind is that package.name != lib.name. So arguing the package name based on the lib name restrictions is a broken argument.

I think the best solution is just to consider them equivalent but not lint either way.

4 Likes

All sounds very sensible. Would you allow publishing with a variation on the name? I’m guessing that there is no need, because the only way to spell it differently is to change it in the name of your Cargo.toml, so its your own fault.

I would say yes, and crates-io should display as whatever you most recently published as (unless maybe when viewing a specific version). But I think I’m less supported in that position than just in basic equivalency. There’s currently no way to change this, if you e.g. decide on a -/_ policy for your crate family after publishing some that don’t match up.

But the situation with cargo-edit is about what I’d expect. When you cargo add wow-use-this, it’ll warn that it’s adding wow-use_this instead, but it’ll go so and just work. Because of this, it’s not been a noticable pain point for me recently.

3 Likes

Yup, cargo-edit is great and already fixes _/-. It should be built-in :slight_smile:

1 Like

Background, I made the PR adding the warning message. We consider doing more; the concern at the time was 2 fold:

  1. There are a lot of places in Cargos code that may assume that the package names have to be identical in order to match, It will be a lot of work to find them all and add tests.
  2. Older Cargos will not be able to build projects or use packages that have this change.

Each can be solved:

  1. By someone willing to put in more work then I was.
  2. By a role out period.

It fixes it if you use cargo add, but not if you add a dependency directly to Cargo.toml. I would argue that using the wrong _/- in Cargo.toml should be allowed as well, except emitting a warning.

Older version:

Currently, there is a sort of equivalence relation within crate names. A crate is equal to another crate if its name is equal, except for the characters - and _, where either can be used interchangeably. Only one crate can be on crates.io using this equivalence relation, but when used it must be spelled exactly, with the correct usage of - and _. I propose to

  1. Accept either spellings in Cargo.toml, so a crate named proc-macro2 can be used like
    [dependencies]
    proc_macro2 = "0.4"
    
    and cargo will use proc-macro2. Currently this errors, with a “did you mean” message.
  2. (More controversial) Make crates in the same equivalence class completely equivalent. Allow a cargo crate called my-crate_with-both to be published where the local name is anything equivalent to this (for example my_crate_with-both). Choose a canonical form to display on crates.io (I propose all _ so it matches what you write in code).
  3. (Still more controversial) Emit a warning when - is used, encouraging everyone to move to the canonical representation.

I couldn’t find any prior RFC for this, although it’s such an obvious idea that it may have been presented already. In that case I apologize for duplicating.

I’m interested to see what other people think about this. It seems odd to me that a_crate and a-crate are equivalent in the exclusion sense (only one of them can be on crates.io), but not in any other sense, but there may be reasons for the way things are currently. I’d like to hear them!

Arguments for

  1. Simpler for new users - everything uses the same pattern. It’s confusing when you always write crate_name in code, but sometimes (but not always) crate-name in Cargo.toml.
  2. No paper-cut when you use the wrong form (you used proc_macro2 when it’s proc-macro2).

Arguments against

  1. It’s more effort than doing nothing.
  2. Maybe having the two forms is equally/more confusing than the current situation.
  3. The warnings might be annoying because you prefer using the crate-name form, and you’d have to change the name everywhere to get rid of the warnings.

Questions

What happens when you’re not using cargo? Should rustc except --extern with either form?

EDIT typos, arguments and questions

I’m fully in favor of allowing both - and _ in Cargo.toml, but how does this relate to cargo-edit?

Sure cargo-edit implements the resolving logic, but doesn’t it otherwise only ever edit Cargo.toml? As far as I can tell cargo-edit implements this logic purely by fetching from crates.io, a fairly simple bit of code, and I see the majority of the work in cargo being in managing the relationship between Cargo.toml and Cargo.lock.

I’m against merging cargo-edit for unrelated reasons (mostly it being opinionated in ways builtin tools currently aren’t), but even if it were available people would still edit their Cargo.tomls manually and mess things up.

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