Skip to content

Commit 750df0a

Browse files
committed
Auto merge of #5011 - Manishearth:stealing-chickens-off-the-internet, r=alexcrichton
Implement RFC 2052: Epoches Todo: - Make epoches affect the fingerprint - Tests cc rust-lang/rust#44581 Rust PR: rust-lang/rust#48014 r? @acrichto
2 parents cac9173 + 270f6e2 commit 750df0a

File tree

7 files changed

+196
-6
lines changed

7 files changed

+196
-6
lines changed

src/cargo/core/features.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,40 @@
4040
//! we'll be sure to update this documentation!
4141
4242
use std::env;
43+
use std::fmt;
44+
use std::str::FromStr;
4345

4446
use util::errors::CargoResult;
4547

48+
/// The epoch of the compiler (RFC 2052)
49+
#[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, Eq, PartialEq)]
50+
#[derive(Serialize, Deserialize)]
51+
pub enum Epoch {
52+
/// The 2015 epoch
53+
Epoch2015,
54+
/// The 2018 epoch
55+
Epoch2018,
56+
}
57+
58+
impl fmt::Display for Epoch {
59+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60+
match *self {
61+
Epoch::Epoch2015 => f.write_str("2015"),
62+
Epoch::Epoch2018 => f.write_str("2018"),
63+
}
64+
}
65+
}
66+
impl FromStr for Epoch {
67+
type Err = ();
68+
fn from_str(s: &str) -> Result<Self, ()> {
69+
match s {
70+
"2015" => Ok(Epoch::Epoch2015),
71+
"2018" => Ok(Epoch::Epoch2018),
72+
_ => Err(())
73+
}
74+
}
75+
}
76+
4677
enum Status {
4778
Stable,
4879
Unstable,
@@ -125,6 +156,9 @@ features! {
125156

126157
// Downloading packages from alternative registry indexes.
127158
[unstable] alternative_registries: bool,
159+
160+
// Using epochs
161+
[unstable] epoch: bool,
128162
}
129163
}
130164

@@ -201,6 +235,10 @@ impl Features {
201235
bail!("{}", msg);
202236
}
203237
}
238+
239+
pub fn is_enabled(&self, feature: &Feature) -> bool {
240+
feature.is_enabled(self)
241+
}
204242
}
205243

206244
/// A parsed representation of all unstable flags that Cargo accepts.

src/cargo/core/manifest.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use serde::ser;
99
use url::Url;
1010

1111
use core::{Dependency, PackageId, Summary, SourceId, PackageIdSpec};
12-
use core::{WorkspaceConfig, Features, Feature};
12+
use core::{WorkspaceConfig, Epoch, Features, Feature};
1313
use util::Config;
1414
use util::toml::TomlManifest;
1515
use util::errors::*;
@@ -36,6 +36,7 @@ pub struct Manifest {
3636
workspace: WorkspaceConfig,
3737
original: Rc<TomlManifest>,
3838
features: Features,
39+
epoch: Epoch,
3940
im_a_teapot: Option<bool>,
4041
}
4142

@@ -269,6 +270,7 @@ impl Manifest {
269270
patch: HashMap<Url, Vec<Dependency>>,
270271
workspace: WorkspaceConfig,
271272
features: Features,
273+
epoch: Epoch,
272274
im_a_teapot: Option<bool>,
273275
original: Rc<TomlManifest>) -> Manifest {
274276
Manifest {
@@ -285,6 +287,7 @@ impl Manifest {
285287
patch: patch,
286288
workspace: workspace,
287289
features: features,
290+
epoch: epoch,
288291
original: original,
289292
im_a_teapot: im_a_teapot,
290293
}
@@ -356,6 +359,10 @@ impl Manifest {
356359
}
357360
}
358361
}
362+
363+
pub fn epoch(&self) -> Epoch {
364+
self.epoch
365+
}
359366
}
360367

361368
impl VirtualManifest {

src/cargo/core/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
pub use self::dependency::Dependency;
2-
pub use self::features::{Features, Feature, CliUnstable};
2+
pub use self::features::{Epoch, Features, Feature, CliUnstable};
33
pub use self::manifest::{EitherManifest, VirtualManifest};
44
pub use self::manifest::{Manifest, Target, TargetKind, Profile, LibKind, Profiles};
55
pub use self::package::{Package, PackageSet};

src/cargo/ops/cargo_rustc/fingerprint.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use serde::ser::{self, Serialize};
99
use serde::de::{self, Deserialize};
1010
use serde_json;
1111

12-
use core::{Package, TargetKind};
12+
use core::{Epoch, Package, TargetKind};
1313
use util;
1414
use util::{Fresh, Dirty, Freshness, internal, profile};
1515
use util::errors::{CargoResult, CargoResultExt};
@@ -145,6 +145,7 @@ pub struct Fingerprint {
145145
#[serde(skip_serializing, skip_deserializing)]
146146
memoized_hash: Mutex<Option<u64>>,
147147
rustflags: Vec<String>,
148+
epoch: Epoch,
148149
}
149150

150151
fn serialize_deps<S>(deps: &[(String, Arc<Fingerprint>)], ser: S)
@@ -170,6 +171,7 @@ fn deserialize_deps<'de, D>(d: D) -> Result<Vec<(String, Arc<Fingerprint>)>, D::
170171
features: String::new(),
171172
deps: Vec::new(),
172173
memoized_hash: Mutex::new(Some(hash)),
174+
epoch: Epoch::Epoch2015,
173175
rustflags: Vec::new(),
174176
}))
175177
}).collect())
@@ -252,6 +254,9 @@ impl Fingerprint {
252254
if self.local.len() != old.local.len() {
253255
bail!("local lens changed");
254256
}
257+
if self.epoch != old.epoch {
258+
bail!("epoch changed")
259+
}
255260
for (new, old) in self.local.iter().zip(&old.local) {
256261
match (new, old) {
257262
(&LocalFingerprint::Precalculated(ref a),
@@ -315,9 +320,10 @@ impl hash::Hash for Fingerprint {
315320
ref deps,
316321
ref local,
317322
memoized_hash: _,
323+
epoch,
318324
ref rustflags,
319325
} = *self;
320-
(rustc, features, target, path, profile, local, rustflags).hash(h);
326+
(rustc, features, target, path, profile, local, epoch, rustflags).hash(h);
321327

322328
h.write_usize(deps.len());
323329
for &(ref name, ref fingerprint) in deps {
@@ -416,6 +422,7 @@ fn calculate<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>)
416422
deps: deps,
417423
local: vec![local],
418424
memoized_hash: Mutex::new(None),
425+
epoch: unit.pkg.manifest().epoch(),
419426
rustflags: extra_flags,
420427
});
421428
cx.fingerprints.insert(*unit, Arc::clone(&fingerprint));
@@ -468,6 +475,7 @@ pub fn prepare_build_cmd<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>)
468475
deps: Vec::new(),
469476
local: local,
470477
memoized_hash: Mutex::new(None),
478+
epoch: Epoch::Epoch2015,
471479
rustflags: Vec::new(),
472480
};
473481
let compare = compare_old_fingerprint(&loc, &fingerprint);

src/cargo/ops/cargo_rustc/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::sync::Arc;
99
use same_file::is_same_file;
1010
use serde_json;
1111

12-
use core::{Package, PackageId, PackageSet, Target, Resolve};
12+
use core::{Feature, Package, PackageId, PackageSet, Target, Resolve};
1313
use core::{Profile, Profiles, Workspace};
1414
use core::manifest::Lto;
1515
use core::shell::ColorChoice;
@@ -804,6 +804,11 @@ fn build_base_args<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,
804804
cmd.arg("-C").arg(format!("panic={}", panic));
805805
}
806806
}
807+
let manifest = unit.pkg.manifest();
808+
809+
if manifest.features().is_enabled(Feature::epoch()) {
810+
cmd.arg(format!("-Zepoch={}", manifest.epoch()));
811+
}
807812

808813
// Disable LTO for host builds as prefer_dynamic and it are mutually
809814
// exclusive.

src/cargo/util/toml/mod.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use url::Url;
1414

1515
use core::{SourceId, Profiles, PackageIdSpec, GitReference, WorkspaceConfig, WorkspaceRootConfig};
1616
use core::{Summary, Manifest, Target, Dependency, PackageId};
17-
use core::{EitherManifest, VirtualManifest, Features, Feature};
17+
use core::{EitherManifest, Epoch, VirtualManifest, Features, Feature};
1818
use core::dependency::{Kind, Platform};
1919
use core::manifest::{LibKind, Profile, ManifestMetadata, Lto};
2020
use sources::CRATES_IO;
@@ -441,6 +441,7 @@ pub struct TomlProject {
441441
license_file: Option<String>,
442442
repository: Option<String>,
443443
metadata: Option<toml::Value>,
444+
rust: Option<String>,
444445
}
445446

446447
#[derive(Debug, Deserialize, Serialize)]
@@ -715,6 +716,19 @@ impl TomlManifest {
715716
Some(VecStringOrBool::Bool(false)) => Some(vec![]),
716717
None | Some(VecStringOrBool::Bool(true)) => None,
717718
};
719+
720+
let epoch = if let Some(ref epoch) = project.rust {
721+
features.require(Feature::epoch()).chain_err(|| {
722+
"epoches are unstable"
723+
})?;
724+
if let Ok(epoch) = epoch.parse() {
725+
epoch
726+
} else {
727+
bail!("the `rust` key must be one of: `2015`, `2018`")
728+
}
729+
} else {
730+
Epoch::Epoch2015
731+
};
718732
let mut manifest = Manifest::new(summary,
719733
targets,
720734
exclude,
@@ -727,6 +741,7 @@ impl TomlManifest {
727741
patch,
728742
workspace_config,
729743
features,
744+
epoch,
730745
project.im_a_teapot,
731746
Rc::clone(me));
732747
if project.license_file.is_some() && project.license.is_some() {

tests/package.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,3 +887,120 @@ fn package_two_kinds_of_deps() {
887887
assert_that(p.cargo("package").arg("--no-verify"),
888888
execs().with_status(0));
889889
}
890+
891+
#[test]
892+
fn test_epoch() {
893+
let p = project("foo")
894+
.file("Cargo.toml", r#"
895+
cargo-features = ["epoch"]
896+
[package]
897+
name = "foo"
898+
version = "0.0.1"
899+
authors = []
900+
rust = "2018"
901+
"#)
902+
.file("src/lib.rs", r#" "#)
903+
.build();
904+
905+
assert_that(p.cargo("build").arg("-v")
906+
.masquerade_as_nightly_cargo(),
907+
execs()
908+
// -Zepoch is still in flux and we're not passing -Zunstable-options
909+
// from Cargo so it will probably error. Only partially match the output
910+
// until stuff stabilizes
911+
.with_stderr_contains(format!("\
912+
[COMPILING] foo v0.0.1 ({url})
913+
[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
914+
--emit=dep-info,link -Zepoch=2018 -C debuginfo=2 \
915+
-C metadata=[..] \
916+
--out-dir [..] \
917+
-L dependency={dir}[/]target[/]debug[/]deps`
918+
", dir = p.root().display(), url = p.url())));
919+
}
920+
921+
#[test]
922+
fn test_epoch_missing() {
923+
// no epoch = 2015
924+
let p = project("foo")
925+
.file("Cargo.toml", r#"
926+
cargo-features = ["epoch"]
927+
[package]
928+
name = "foo"
929+
version = "0.0.1"
930+
authors = []
931+
"#)
932+
.file("src/lib.rs", r#" "#)
933+
.build();
934+
935+
assert_that(p.cargo("build").arg("-v")
936+
.masquerade_as_nightly_cargo(),
937+
execs()
938+
// -Zepoch is still in flux and we're not passing -Zunstable-options
939+
// from Cargo so it will probably error. Only partially match the output
940+
// until stuff stabilizes
941+
.with_stderr_contains(format!("\
942+
[COMPILING] foo v0.0.1 ({url})
943+
[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
944+
--emit=dep-info,link -Zepoch=2015 -C debuginfo=2 \
945+
-C metadata=[..] \
946+
--out-dir [..] \
947+
-L dependency={dir}[/]target[/]debug[/]deps`
948+
", dir = p.root().display(), url = p.url())));
949+
}
950+
951+
#[test]
952+
fn test_epoch_malformed() {
953+
let p = project("foo")
954+
.file("Cargo.toml", r#"
955+
cargo-features = ["epoch"]
956+
[package]
957+
name = "foo"
958+
version = "0.0.1"
959+
authors = []
960+
rust = "chicken"
961+
"#)
962+
.file("src/lib.rs", r#" "#)
963+
.build();
964+
965+
assert_that(p.cargo("build").arg("-v")
966+
.masquerade_as_nightly_cargo(),
967+
execs()
968+
.with_status(101)
969+
.with_stderr(format!("\
970+
error: failed to parse manifest at `[..]`
971+
972+
Caused by:
973+
the `rust` key must be one of: `2015`, `2018`
974+
")));
975+
}
976+
977+
978+
#[test]
979+
fn test_epoch_nightly() {
980+
let p = project("foo")
981+
.file("Cargo.toml", r#"
982+
[package]
983+
name = "foo"
984+
version = "0.0.1"
985+
authors = []
986+
rust = "2015"
987+
"#)
988+
.file("src/lib.rs", r#" "#)
989+
.build();
990+
991+
assert_that(p.cargo("build").arg("-v")
992+
.masquerade_as_nightly_cargo(),
993+
execs()
994+
.with_status(101)
995+
.with_stderr(format!("\
996+
error: failed to parse manifest at `[..]`
997+
998+
Caused by:
999+
epoches are unstable
1000+
1001+
Caused by:
1002+
feature `epoch` is required
1003+
1004+
consider adding `cargo-features = [\"epoch\"]` to the manifest
1005+
")));
1006+
}

0 commit comments

Comments
 (0)