Skip to content

Commit

Permalink
Auto merge of #5816 - dwijnand:edtion-per-target, r=alexcrichton
Browse files Browse the repository at this point in the history
Edition key should be per-target, not per-package

Fixes #5661

I've pushed this WIP PR as I'd love some early feedback on it and some tips on:

* how to best to make it fail if edition is set on a target, but the feature isn't set; and
* what tests this should include (i.e how exhaustive should I go)

Thanks!
  • Loading branch information
bors committed Jul 31, 2018
2 parents af6e295 + 67c52ff commit 4b95e8c
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 17 deletions.
8 changes: 4 additions & 4 deletions src/cargo/core/compiler/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,22 +121,22 @@ impl<'cfg> Compilation<'cfg> {
}

/// See `process`.
pub fn rustc_process(&self, pkg: &Package) -> CargoResult<ProcessBuilder> {
pub fn rustc_process(&self, pkg: &Package, target: &Target) -> CargoResult<ProcessBuilder> {
let mut p = self.fill_env(self.rustc_process.clone(), pkg, true)?;
let manifest = pkg.manifest();
if manifest.features().is_enabled(Feature::edition()) {
p.arg(format!("--edition={}", manifest.edition()));
p.arg(format!("--edition={}", target.edition()));
}
Ok(p)
}

/// See `process`.
pub fn rustdoc_process(&self, pkg: &Package) -> CargoResult<ProcessBuilder> {
pub fn rustdoc_process(&self, pkg: &Package, target: &Target) -> CargoResult<ProcessBuilder> {
let mut p = self.fill_env(process(&*self.config.rustdoc()?), pkg, false)?;
let manifest = pkg.manifest();
if manifest.features().is_enabled(Feature::edition()) {
p.arg("-Zunstable-options");
p.arg(format!("--edition={}", &manifest.edition()));
p.arg(format!("--edition={}", target.edition()));
}
Ok(p)
}
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/core/compiler/fingerprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ fn calculate<'a, 'cfg>(
deps,
local: vec![local],
memoized_hash: Mutex::new(None),
edition: unit.pkg.manifest().edition(),
edition: unit.target.edition(),
rustflags: extra_flags,
});
cx.fingerprints.insert(*unit, Arc::clone(&fingerprint));
Expand Down
4 changes: 2 additions & 2 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ fn prepare_rustc<'a, 'cfg>(
crate_types: &[&str],
unit: &Unit<'a>,
) -> CargoResult<ProcessBuilder> {
let mut base = cx.compilation.rustc_process(unit.pkg)?;
let mut base = cx.compilation.rustc_process(unit.pkg, unit.target)?;
base.inherit_jobserver(&cx.jobserver);
build_base_args(cx, &mut base, unit, crate_types)?;
build_deps_args(&mut base, cx, unit)?;
Expand All @@ -572,7 +572,7 @@ fn prepare_rustc<'a, 'cfg>(

fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult<Work> {
let bcx = cx.bcx;
let mut rustdoc = cx.compilation.rustdoc_process(unit.pkg)?;
let mut rustdoc = cx.compilation.rustdoc_process(unit.pkg, unit.target)?;
rustdoc.inherit_jobserver(&cx.jobserver);
rustdoc.arg("--crate-name").arg(&unit.target.crate_name());
add_path_args(bcx, unit, &mut rustdoc);
Expand Down
8 changes: 8 additions & 0 deletions src/cargo/core/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ pub struct Target {
doctest: bool,
harness: bool, // whether to use the test harness (--test)
for_host: bool,
edition: Edition,
}

#[derive(Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -280,6 +281,7 @@ compact_debug! {
doctest
harness
for_host
edition
)]
}
}
Expand Down Expand Up @@ -507,6 +509,7 @@ impl Target {
doctest: false,
harness: true,
for_host: false,
edition: Edition::Edition2015,
tested: true,
benched: true,
}
Expand Down Expand Up @@ -625,6 +628,7 @@ impl Target {
pub fn for_host(&self) -> bool {
self.for_host
}
pub fn edition(&self) -> Edition { self.edition }
pub fn benched(&self) -> bool {
self.benched
}
Expand Down Expand Up @@ -746,6 +750,10 @@ impl Target {
self.for_host = for_host;
self
}
pub fn set_edition(&mut self, edition: Edition) -> &mut Target {
self.edition = edition;
self
}
pub fn set_harness(&mut self, harness: bool) -> &mut Target {
self.harness = harness;
self
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/cargo_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ fn run_doc_tests(
deps,
} = doctest_info;
config.shell().status("Doc-tests", target.name())?;
let mut p = compilation.rustdoc_process(package)?;
let mut p = compilation.rustdoc_process(package, target)?;
p.arg("--test")
.arg(target.src_path())
.arg("--crate-name")
Expand Down
2 changes: 2 additions & 0 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,7 @@ impl TomlManifest {
// If we have a lib with a path, we're done
// If we have a lib with no path, use the inferred lib or_else package name
let targets = targets(
&features,
me,
package_name,
package_root,
Expand Down Expand Up @@ -1357,6 +1358,7 @@ struct TomlTarget {
harness: Option<bool>,
#[serde(rename = "required-features")]
required_features: Option<Vec<String>>,
edition: Option<String>,
}

#[derive(Clone)]
Expand Down
40 changes: 32 additions & 8 deletions src/cargo/util/toml/targets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ use std::path::{Path, PathBuf};
use std::fs::{self, DirEntry};
use std::collections::HashSet;

use core::{compiler, Edition, Target};
use util::errors::CargoResult;
use core::{compiler, Edition, Feature, Features, Target};
use util::errors::{CargoResult, CargoResultExt};
use super::{LibKind, PathValue, StringOrBool, TomlBenchTarget, TomlBinTarget, TomlExampleTarget,
TomlLibTarget, TomlManifest, TomlTarget, TomlTestTarget};

pub fn targets(
features: &Features,
manifest: &TomlManifest,
package_name: &str,
package_root: &Path,
Expand All @@ -33,6 +34,7 @@ pub fn targets(
let has_lib;

if let Some(target) = clean_lib(
features,
manifest.lib.as_ref(),
package_root,
package_name,
Expand All @@ -52,6 +54,7 @@ pub fn targets(
.ok_or_else(|| format_err!("manifest has no `package` (or `project`)"))?;

targets.extend(clean_bins(
features,
manifest.bin.as_ref(),
package_root,
package_name,
Expand All @@ -63,6 +66,7 @@ pub fn targets(
)?);

targets.extend(clean_examples(
features,
manifest.example.as_ref(),
package_root,
edition,
Expand All @@ -72,6 +76,7 @@ pub fn targets(
)?);

targets.extend(clean_tests(
features,
manifest.test.as_ref(),
package_root,
edition,
Expand All @@ -81,6 +86,7 @@ pub fn targets(
)?);

targets.extend(clean_benches(
features,
manifest.bench.as_ref(),
package_root,
edition,
Expand Down Expand Up @@ -108,6 +114,7 @@ pub fn targets(
}

fn clean_lib(
features: &Features,
toml_lib: Option<&TomlLibTarget>,
package_root: &Path,
package_name: &str,
Expand Down Expand Up @@ -183,11 +190,12 @@ fn clean_lib(
};

let mut target = Target::lib_target(&lib.name(), crate_types, path);
configure(lib, &mut target);
configure(features, lib, &mut target, edition)?;
Ok(Some(target))
}

fn clean_bins(
features: &Features,
toml_bins: Option<&Vec<TomlBinTarget>>,
package_root: &Path,
package_name: &str,
Expand Down Expand Up @@ -263,7 +271,7 @@ fn clean_bins(
};

let mut target = Target::bin_target(&bin.name(), path, bin.required_features.clone());
configure(bin, &mut target);
configure(features, bin, &mut target, edition)?;
result.push(target);
}
return Ok(result);
Expand All @@ -289,6 +297,7 @@ fn clean_bins(
}

fn clean_examples(
features: &Features,
toml_examples: Option<&Vec<TomlExampleTarget>>,
package_root: &Path,
edition: Edition,
Expand Down Expand Up @@ -324,14 +333,15 @@ fn clean_examples(
path,
toml.required_features.clone(),
);
configure(&toml, &mut target);
configure(features, &toml, &mut target, edition)?;
result.push(target);
}

Ok(result)
}

fn clean_tests(
features: &Features,
toml_tests: Option<&Vec<TomlTestTarget>>,
package_root: &Path,
edition: Edition,
Expand All @@ -357,13 +367,14 @@ fn clean_tests(
let mut result = Vec::new();
for (path, toml) in targets {
let mut target = Target::test_target(&toml.name(), path, toml.required_features.clone());
configure(&toml, &mut target);
configure(features, &toml, &mut target, edition)?;
result.push(target);
}
Ok(result)
}

fn clean_benches(
features: &Features,
toml_benches: Option<&Vec<TomlBenchTarget>>,
package_root: &Path,
edition: Edition,
Expand Down Expand Up @@ -410,7 +421,7 @@ fn clean_benches(
let mut result = Vec::new();
for (path, toml) in targets {
let mut target = Target::bench_target(&toml.name(), path, toml.required_features.clone());
configure(&toml, &mut target);
configure(features, &toml, &mut target, edition)?;
result.push(target);
}

Expand Down Expand Up @@ -682,7 +693,12 @@ fn validate_unique_names(targets: &[TomlTarget], target_kind: &str) -> CargoResu
Ok(())
}

fn configure(toml: &TomlTarget, target: &mut Target) {
fn configure(
features: &Features,
toml: &TomlTarget,
target: &mut Target,
edition: Edition,
) -> CargoResult<()> {
let t2 = target.clone();
target
.set_tested(toml.test.unwrap_or_else(|| t2.tested()))
Expand All @@ -694,7 +710,15 @@ fn configure(toml: &TomlTarget, target: &mut Target) {
(None, None) => t2.for_host(),
(Some(true), _) | (_, Some(true)) => true,
(Some(false), _) | (_, Some(false)) => false,
})
.set_edition(match toml.edition.clone() {
None => edition,
Some(s) => {
features.require(Feature::edition()).chain_err(|| "editions are unstable")?;
s.parse().chain_err(|| "failed to parse the `edition` key")?
},
});
Ok(())
}

fn target_path(
Expand Down
9 changes: 8 additions & 1 deletion src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,21 @@ cargo +nightly build --out-dir=out -Z unstable-options

You can opt in to a specific Rust Edition for your package with the `edition`
key in `Cargo.toml`. If you don't specify the edition, it will default to
2015. You need to include the appropriate `cargo-features`:
2015. You need to include the appropriate `cargo-features`.

You can also specify `edition` on a per-target level, where it will otherwise
default to the package `edition`.

```toml
cargo-features = ["edition"]

[package]
...
edition = "2018"

[[bin]]
...
edition = "2015"
```


Expand Down
Loading

0 comments on commit 4b95e8c

Please sign in to comment.