Using build.rustflags
as an example (Configuration - The Cargo Book) â this configuration option is documented as having "Type: string or array of strings", with the following being treated equivalently by Cargo:
# .cargo/config.toml
[build]
rustflags = ["-C", "target-cpu=native"]
# .cargo/config.toml
[build]
rustflags = "-C target-cpu=native"
Except, surprisingly they are not equivalent!
The first one can only be appended to by other configurations. It cannot be overwritten. The second one can only be overwritten by other configurations. It cannot be appended to.
With rustflags = [...]
:
$ cargo check --config='build.rustflags=["--cfg=repro"]' --verbose # APPEND
Running `/path/to/bin/rustc ... -C target-cpu=native --cfg=repro`
$ cargo check --config='build.rustflags="--cfg=repro"' --verbose # FAIL
error: failed to merge --config key `build` into `.cargo/config.toml`
Caused by:
failed to merge key `rustflags` between .cargo/config.toml and --config cli option
Caused by:
failed to merge config value from `--config cli option` into `.cargo/config.toml`: expected array, but found string
With rustflags = "..."
:
$ cargo check --config='build.rustflags="--cfg=repro"' --verbose # OVERWRITE
Running `/path/to/bin/rustc ... --cfg=repro`
$ cargo check --config='build.rustflags=["--cfg=repro"]' --verbose # FAIL
error: failed to merge --config key `build` into `.cargo/config.toml`
Caused by:
failed to merge key `rustflags` between .cargo/config.toml and --config cli option
Caused by:
failed to merge config value from `--config cli option` into `.cargo/config.toml`: expected string, but found array
This distinction between append-only rustflags and replace-only rustflags seems like too much subtlety to attach to what, to the user, almost certainly seems like an insignificant syntactic difference between writing flags as an array of strings vs space-separated string.
Most recently, this has caused problems for me in GitHub - dtolnay/cargo-docs-rs: Imitate the documentation build that docs.rs would do which needs to set --cfg=docsrs
and --extern-html-root-takes-precedence
in build.rustdocflags
. If the user arbitrarily chose to use string syntax in their config.toml, then they get a confusing failure because I cannot append to it. At best, I could reimplement all of Cargo's configuration merging logic in my subcommand, but this definitely doesn't seem like something I should have to do in order to append flags.
Should we make rustflags = ["-C", "target-cpu=native"]
and rustflags = "-C target-cpu=native"
actually equivalent, by giving them both append-only behavior?