Auto merge of #10497 - Muscraft:rfc2906-part1, r=epage
Part 1 of RFC2906 - Packages can inherit fields from their root workspace
Tracking issue: #8415
RFC: rust-lang/rfcs#2906
All changes were heavily inspired by #8664 and #9684
A big thanks to both `@yaymukund` and `@ParkMyCar.` I pulled a lot of inspiration from their branches.
I would also like to thank `@alexcrichton` for all the feedback on the first attempt. It has brought this into a much better state.
All changes have been made according to the RFC as well as `@alexcrichton's` [comment](https://github.com/rust-lang/cargo/pull/8664#issuecomment-
704878103).
This is part 1 of many, as described by [this comment](https://github.com/rust-lang/cargo/pull/9684#issuecomment-
943567692), [this comment](https://github.com/rust-lang/cargo/pull/9684#pullrequestreview-
779070283) and redefined [by this one](https://github.com/rust-lang/cargo/pull/10497#issuecomment-
1076301312).
This PR focuses on inheriting in root package, including:
- Add `MaybeWorkspace<T>` to allow for `{ workspace = true }`
- Add a new variant to `TomlDependency` to allow inheriting dependencies from a workspace
- Add `InheritableFields` so that we have somewhere to get a value from when we `resolve` a `MaybeWorkspace<T>`
- `license_file` and `readme` are in `InheritableFields` in this part but are not `MaybeWorkspace` for reasons [described here](https://github.com/rust-lang/cargo/pull/10497#issuecomment-
1076470424)
- Add a method to `resolve` a `MaybeWorkspace<T>` into a `T` that can fail if we have nowhere to pull from or the workspace does not define that field
- Disallow inheriting from a different `Cargo.toml`
- This means that you can only inherit from inside the same `Cargo.toml`, i.e. it has both a `[workspace]` and a `[package]`
- Forcing this requirement allows us to test the implementations of `MaybeWorkspace<T>` and the new `TomlDependency` variant without having to add searching for a workspace root and the complexity with it
Remaining implementation work for the RFC
- Support inheriting in any workspace member
- Correctly inherit fields that are relative paths
- Including adding support for inheriting `license_file`, `readme`, and path-dependencies
- Path dependencies infer version directive
- Lock workspace dependencies and warn when unused
- Optimizations, as needed
- Evaluate any new fields for being inheritable (e.g. `rust-version`)
- Evaluate making users of `{ workspace = true }` define the workspace they pull from in `[package]`
Areas of concern:
- `TomlDependency` Deserialization is a mess, and I could not figure out how to do it in a cleaner way without significant headaches. I ended up having to do the same thing as last time [which was an issue](https://github.com/rust-lang/cargo/pull/9684#discussion_r728444103).
- Resolving on a `MaybeWorkspace` feels extremely verbose currently:
```rust
project.homepage.clone().map(|mw| mw.resolve(&features, "homepage", || get_ws(inheritable)?.homepage())).transpose()?,
```
This way allows for lazy resolution of inheritable fields and finding a workspace (in part 2) so you do not pay a penalty for not using this feature. The other bit of good news is `&features` will go away as it is just feature checking currently.
- This feature requires some level of duplication of code as well as remaking the original `TomlManifest` which adds extra length to the changes.
- This feature also takes a linear process and makes it potentially non-linear which adds lots of complexity (which will get worse in Part 2)
Please let me know if you have any feedback or suggestions!