diff --git a/RELEASES.md b/RELEASES.md index 5815cb0f97260..2979ffe136c90 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -170,7 +170,7 @@ Compatibility Notes [`slice::sort_unstable_by_key`]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_unstable_by_key [`slice::sort_unstable_by`]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_unstable_by [`slice::sort_unstable`]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_unstable -[`ste::from_boxed_utf8_unchecked`]: https://doc.rust-lang.org/std/str/fn.from_boxed_utf8_unchecked.html +[`str::from_boxed_utf8_unchecked`]: https://doc.rust-lang.org/std/str/fn.from_boxed_utf8_unchecked.html [`str::as_bytes_mut`]: https://doc.rust-lang.org/std/primitive.str.html#method.as_bytes_mut [`str::from_utf8_mut`]: https://doc.rust-lang.org/std/str/fn.from_utf8_mut.html [`str::from_utf8_unchecked_mut`]: https://doc.rust-lang.org/std/str/fn.from_utf8_unchecked_mut.html diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 05d59e7d59565..2ca65396b3594 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -365,6 +365,9 @@ impl Step for Rustc { // tiny morsel of metadata is used by rust-packaging let version = build.rust_version(); t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + if let Some(sha) = build.rust_sha() { + t!(t!(File::create(overlay.join("git-commit-hash"))).write_all(sha.as_bytes())); + } // On MinGW we've got a few runtime DLL dependencies that we need to // include. The first argument to this script is where to put these DLLs @@ -844,6 +847,9 @@ impl Step for PlainSourceTarball { // Create the version file write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes()); + if let Some(sha) = build.rust_sha() { + write_file(&plain_dst_src.join("git-commit-hash"), sha.as_bytes()); + } // If we're building from git sources, we need to vendor a complete distribution. if build.rust_info.is_git() { @@ -1157,6 +1163,9 @@ impl Step for Extended { install(&build.src.join("LICENSE-MIT"), &overlay, 0o644); let version = build.rust_version(); t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + if let Some(sha) = build.rust_sha() { + t!(t!(File::create(overlay.join("git-commit-hash"))).write_all(sha.as_bytes())); + } install(&etc.join("README.md"), &overlay, 0o644); // When rust-std package split from rustc, we needed to ensure that during @@ -1164,7 +1173,10 @@ impl Step for Extended { // the std files during uninstall. To do this ensure that rustc comes // before rust-std in the list below. let mut tarballs = vec![rustc_installer, cargo_installer, rls_installer, - analysis_installer, docs_installer, std_installer]; + analysis_installer, std_installer]; + if build.config.docs { + tarballs.push(docs_installer); + } if target.contains("pc-windows-gnu") { tarballs.push(mingw_installer.unwrap()); } diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 89690e444d1f6..608924c9c28d1 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -200,7 +200,7 @@ install!((self, builder, _config), builder.ensure(dist::Src); install_src(builder, self.stage); }, ONLY_BUILD; - Rustc, "src/librustc", _config.extended, only_hosts: true, { + Rustc, "src/librustc", true, only_hosts: true, { builder.ensure(dist::Rustc { compiler: builder.compiler(self.stage, self.target), }); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index f21b382619d0a..67791e8758c0b 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -797,6 +797,11 @@ impl Build { self.rust_info.version(self, channel::CFG_RELEASE_NUM) } + /// Return the full commit hash + fn rust_sha(&self) -> Option<&str> { + self.rust_info.sha() + } + /// Returns the `a.b.c` version that the given package is at. fn release_num(&self, package: &str) -> String { let mut toml = String::new(); diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 8173903c03440..9b09a8554e12d 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -366,7 +366,7 @@ impl Step for Openssl { if !ok { panic!("failed to download openssl source") } - let mut shasum = if target.contains("apple") { + let mut shasum = if target.contains("apple") || build.build.contains("netbsd") { let mut cmd = Command::new("shasum"); cmd.arg("-a").arg("256"); cmd @@ -386,7 +386,7 @@ impl Step for Openssl { let dst = build.openssl_install_dir(target).unwrap(); drop(fs::remove_dir_all(&obj)); drop(fs::remove_dir_all(&dst)); - build.run(Command::new("tar").arg("xf").arg(&tarball).current_dir(&out)); + build.run(Command::new("tar").arg("zxf").arg(&tarball).current_dir(&out)); let mut configure = Command::new(obj.join("Configure")); configure.arg(format!("--prefix={}", dst.display())); @@ -416,6 +416,7 @@ impl Step for Openssl { "powerpc64-unknown-linux-gnu" => "linux-ppc64", "powerpc64le-unknown-linux-gnu" => "linux-ppc64le", "s390x-unknown-linux-gnu" => "linux64-s390x", + "sparc64-unknown-netbsd" => "BSD-sparc64", "x86_64-apple-darwin" => "darwin64-x86_64-cc", "x86_64-linux-android" => "linux-x86_64", "x86_64-unknown-freebsd" => "BSD-x86_64", @@ -435,6 +436,15 @@ impl Step for Openssl { configure.arg("-mandroid"); configure.arg("-fomit-frame-pointer"); } + if target == "sparc64-unknown-netbsd" { + // Need -m64 to get assembly generated correctly for sparc64. + configure.arg("-m64"); + if build.build.contains("netbsd") { + // Disable sparc64 asm on NetBSD builders, it uses + // m4(1)'s -B flag, which NetBSD m4 does not support. + configure.arg("no-asm"); + } + } // Make PIE binaries // Non-PIE linker support was removed in Lollipop // https://source.android.com/security/enhancements/enhancements50 diff --git a/src/etc/platform-intrinsics/powerpc.json b/src/etc/platform-intrinsics/powerpc.json index d615037b632d7..6268438184254 100644 --- a/src/etc/platform-intrinsics/powerpc.json +++ b/src/etc/platform-intrinsics/powerpc.json @@ -156,6 +156,69 @@ "llvm": "vupkh{1.kind}{1.data_type_short}", "ret": "s(16-32)", "args": ["0N"] + }, + { + "intrinsic": "madds", + "width": [128], + "llvm": "vmhaddshs", + "ret": "s16", + "args": ["0", "0", "0"] + }, + { + "intrinsic": "msumu{1.data_type_short}m", + "width": [128], + "llvm": "vmsumu{1.data_type_short}m", + "ret": "u32", + "args": ["u(8-16)", "1", "u32"] + }, + { + "intrinsic": "msummbm", + "width": [128], + "llvm": "vmsummbm", + "ret": "s32", + "args": ["s8", "u8", "s32"] + }, + { + "intrinsic": "msumshm", + "width": [128], + "llvm": "vmsumshm", + "ret": "s32", + "args": ["s16", "s16", "s32"] + }, + { + "intrinsic": "msum{0.kind}hs", + "width": [128], + "llvm": "vmsum{0.kind}hs", + "ret": "i32", + "args": ["0N", "0N", "0"] + }, + { + "intrinsic": "sum2s", + "width": [128], + "llvm": "vsum2sws", + "ret": "s32", + "args": ["0", "0"] + }, + { + "intrinsic": "sum4{0.kind}bs", + "width": [128], + "llvm": "vsum4{0.kind}bs", + "ret": "i32", + "args": ["0NN", "0"] + }, + { + "intrinsic": "sum4shs", + "width": [128], + "llvm": "vsum4shs", + "ret": "s32", + "args": ["0N", "0"] + }, + { + "intrinsic": "sums", + "width": [128], + "llvm": "vsumsws", + "ret": "s32", + "args": ["0", "0"] } ] } diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 7787ace944119..2045d5ddd972d 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -671,10 +671,25 @@ impl [T] { /// # Examples /// /// ``` - /// let v = [10, 40, 30, 20, 50]; - /// let (v1, v2) = v.split_at(2); - /// assert_eq!([10, 40], v1); - /// assert_eq!([30, 20, 50], v2); + /// let v = [1, 2, 3, 4, 5, 6]; + /// + /// { + /// let (left, right) = v.split_at(0); + /// assert!(left == []); + /// assert!(right == [1, 2, 3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_at(2); + /// assert!(left == [1, 2]); + /// assert!(right == [3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_at(6); + /// assert!(left == [1, 2, 3, 4, 5, 6]); + /// assert!(right == []); + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -695,26 +710,16 @@ impl [T] { /// # Examples /// /// ``` - /// let mut v = [1, 2, 3, 4, 5, 6]; - /// + /// let mut v = [1, 0, 3, 0, 5, 6]; /// // scoped to restrict the lifetime of the borrows /// { - /// let (left, right) = v.split_at_mut(0); - /// assert!(left == []); - /// assert!(right == [1, 2, 3, 4, 5, 6]); - /// } - /// - /// { /// let (left, right) = v.split_at_mut(2); - /// assert!(left == [1, 2]); - /// assert!(right == [3, 4, 5, 6]); - /// } - /// - /// { - /// let (left, right) = v.split_at_mut(6); - /// assert!(left == [1, 2, 3, 4, 5, 6]); - /// assert!(right == []); + /// assert!(left == [1, 0]); + /// assert!(right == [3, 0, 5, 6]); + /// left[1] = 2; + /// right[1] = 4; /// } + /// assert!(v == [1, 2, 3, 4, 5, 6]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index ec6525485f7a1..dc1f2981a50ad 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -481,6 +481,30 @@ pub trait Ord: Eq + PartialOrd { where Self: Sized { if self <= other { self } else { other } } + + /// Returns max if self is greater than max, and min if self is less than min. + /// Otherwise this will return self. + /// + /// # Examples + /// + /// ``` + /// #![feature(clamp)] + /// + /// assert!((-3).clamp(-2, 1) == -2); + /// assert!(0.clamp(-2, 1) == 0); + /// assert!(2.clamp(-2, 1) == 1); + /// ``` + /// + /// # Panics + /// Panics if min > max. + #[unstable(feature = "clamp", issue = "44095")] + fn clamp(self, min: Self, max: Self) -> Self + where Self: Sized { + assert!(min <= max); + if self < min { min } + else if self > max { max } + else { self } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index ce183389a8083..83f8f9988f448 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -531,15 +531,13 @@ macro_rules! unreachable { /// A standardized placeholder for marking unfinished code. /// -/// It panics with the message `"not yet implemented"` when executed. -/// /// This can be useful if you are prototyping and are just looking to have your /// code typecheck, or if you're implementing a trait that requires multiple /// methods, and you're only planning on using one of them. /// /// # Panics /// -/// This macro always panics. +/// This will always [panic!](macro.panic.html) /// /// # Examples /// diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index f353770a736e4..f93564c2849f5 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -121,7 +121,6 @@ macro_rules! from_str_float_impl { /// * '-3.14' /// * '2.5E10', or equivalently, '2.5e10' /// * '2.5E-10' - /// * '.' (understood as 0) /// * '5.' /// * '.5', or, equivalently, '0.5' /// * 'inf', '-inf', 'NaN' diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 7f76e1bf770bf..78daff9f67aa5 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -93,10 +93,19 @@ impl serialize::UseSpecializedDecodable for CrateNum { /// /// Since the DefIndex is mostly treated as an opaque ID, you probably /// don't have to care about these ranges. -#[derive(Clone, Debug, Eq, Ord, PartialOrd, PartialEq, RustcEncodable, +#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable, RustcDecodable, Hash, Copy)] pub struct DefIndex(u32); +impl fmt::Debug for DefIndex { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, + "DefIndex({}:{})", + self.address_space().index(), + self.as_array_index()) + } +} + impl DefIndex { #[inline] pub fn new(x: usize) -> DefIndex { diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 3f8070fb3aa31..b2572b2d0aba6 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -606,14 +606,20 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { _location: Location) { if *local == RETURN_POINTER { match self.destination { - Lvalue::Local(l) => *local = l, + Lvalue::Local(l) => { + *local = l; + return; + }, ref lval => bug!("Return lvalue is {:?}, not local", lval) } } let idx = local.index() - 1; if idx < self.args.len() { match self.args[idx] { - Operand::Consume(Lvalue::Local(l)) => *local = l, + Operand::Consume(Lvalue::Local(l)) => { + *local = l; + return; + }, ref op => bug!("Arg operand `{:?}` is {:?}, not local", idx, op) } } diff --git a/src/librustc_platform_intrinsics/powerpc.rs b/src/librustc_platform_intrinsics/powerpc.rs index 1a2e8e9c5d868..a9c56309aa8ba 100644 --- a/src/librustc_platform_intrinsics/powerpc.rs +++ b/src/librustc_platform_intrinsics/powerpc.rs @@ -337,6 +337,66 @@ pub fn find(name: &str) -> Option { output: &::I32x4, definition: Named("llvm.ppc.altivec.vupkhsh") }, + "_vec_madds" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 3] = [&::I16x8, &::I16x8, &::I16x8]; &INPUTS }, + output: &::I16x8, + definition: Named("llvm.ppc.altivec.vmhaddshs") + }, + "_vec_msumubm" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 3] = [&::U8x16, &::U8x16, &::U32x4]; &INPUTS }, + output: &::U32x4, + definition: Named("llvm.ppc.altivec.vmsumubm") + }, + "_vec_msumuhm" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 3] = [&::U16x8, &::U16x8, &::U32x4]; &INPUTS }, + output: &::U32x4, + definition: Named("llvm.ppc.altivec.vmsumuhm") + }, + "_vec_msummbm" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 3] = [&::I8x16, &::U8x16, &::I32x4]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vmsummbm") + }, + "_vec_msumshm" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 3] = [&::I16x8, &::I16x8, &::I32x4]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vmsumshm") + }, + "_vec_msumshs" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 3] = [&::I16x8, &::I16x8, &::I32x4]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vmsumshs") + }, + "_vec_msumuhs" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 3] = [&::U16x8, &::U16x8, &::U32x4]; &INPUTS }, + output: &::U32x4, + definition: Named("llvm.ppc.altivec.vmsumuhs") + }, + "_vec_sum2s" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vsum2sws") + }, + "_vec_sum4sbs" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I32x4]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vsum4sbs") + }, + "_vec_sum4ubs" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U32x4]; &INPUTS }, + output: &::U32x4, + definition: Named("llvm.ppc.altivec.vsum4ubs") + }, + "_vec_sum4shs" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I32x4]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vsum4shs") + }, + "_vec_sums" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vsumsws") + }, _ => return None, }) } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index fc241c023cdaf..65900dc3f36e7 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -207,7 +207,29 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected: Ty<'tcx>) -> Option { match (&expected.sty, &checked_ty.sty) { - (&ty::TyRef(_, _), &ty::TyRef(_, _)) => None, + (&ty::TyRef(_, exp), &ty::TyRef(_, check)) => match (&exp.ty.sty, &check.ty.sty) { + (&ty::TyStr, &ty::TyArray(arr, _)) | + (&ty::TyStr, &ty::TySlice(arr)) if arr == self.tcx.types.u8 => { + if let hir::ExprLit(_) = expr.node { + let sp = self.sess().codemap().call_span_if_macro(expr.span); + if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(sp) { + return Some(format!("try `{}`", &src[1..])); + } + } + None + }, + (&ty::TyArray(arr, _), &ty::TyStr) | + (&ty::TySlice(arr), &ty::TyStr) if arr == self.tcx.types.u8 => { + if let hir::ExprLit(_) = expr.node { + let sp = self.sess().codemap().call_span_if_macro(expr.span); + if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(sp) { + return Some(format!("try `b{}`", src)); + } + } + None + } + _ => None, + }, (&ty::TyRef(_, mutability), _) => { // Check if it can work when put into a ref. For example: // diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 0135cd0a588cf..69ca77f54b44a 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -1080,6 +1080,32 @@ impl f32 { 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() } + /// Returns max if self is greater than max, and min if self is less than min. + /// Otherwise this returns self. + /// + /// # Examples + /// + /// ``` + /// #![feature(clamp)] + /// use std::f32::NAN; + /// assert!((-3.0f32).clamp(-2.0f32, 1.0f32) == -2.0f32); + /// assert!((0.0f32).clamp(-2.0f32, 1.0f32) == 0.0f32); + /// assert!((2.0f32).clamp(-2.0f32, 1.0f32) == 1.0f32); + /// assert!((NAN).clamp(-2.0f32, 1.0f32).is_nan()); + /// ``` + /// + /// # Panics + /// Panics if min > max, min is NaN, or max is NaN. + #[unstable(feature = "clamp", issue = "44095")] + #[inline] + pub fn clamp(self, min: f32, max: f32) -> f32 { + assert!(min <= max); + let mut x = self; + if x < min { x = min; } + if x > max { x = max; } + x + } + /// Raw transmutation to `u32`. /// /// Converts the `f32` into its raw memory representation, @@ -1751,4 +1777,22 @@ mod tests { assert_ne!(nan_masked & QNAN_MASK, 0); assert!(nan_masked_fl.is_nan()); } + + #[test] + #[should_panic] + fn test_clamp_min_greater_than_max() { + 1.0f32.clamp(3.0, 1.0); + } + + #[test] + #[should_panic] + fn test_clamp_min_is_nan() { + 1.0f32.clamp(NAN, 1.0); + } + + #[test] + #[should_panic] + fn test_clamp_max_is_nan() { + 1.0f32.clamp(3.0, NAN); + } } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index d73d7cd2c7bd1..6ec633bfaaac1 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -970,6 +970,32 @@ impl f64 { 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() } + /// Returns max if self is greater than max, and min if self is less than min. + /// Otherwise this returns self. + /// + /// # Examples + /// + /// ``` + /// #![feature(clamp)] + /// use std::f64::NAN; + /// assert!((-3.0f64).clamp(-2.0f64, 1.0f64) == -2.0f64); + /// assert!((0.0f64).clamp(-2.0f64, 1.0f64) == 0.0f64); + /// assert!((2.0f64).clamp(-2.0f64, 1.0f64) == 1.0f64); + /// assert!((NAN).clamp(-2.0f64, 1.0f64).is_nan()); + /// ``` + /// + /// # Panics + /// Panics if min > max, min is NaN, or max is NaN. + #[unstable(feature = "clamp", issue = "44095")] + #[inline] + pub fn clamp(self, min: f64, max: f64) -> f64 { + assert!(min <= max); + let mut x = self; + if x < min { x = min; } + if x > max { x = max; } + x + } + // Solaris/Illumos requires a wrapper around log, log2, and log10 functions // because of their non-standard behavior (e.g. log(-n) returns -Inf instead // of expected NaN). @@ -1642,4 +1668,22 @@ mod tests { assert_approx_eq!(f64::from_bits(0x4094e40000000000), 1337.0); assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25); } + + #[test] + #[should_panic] + fn test_clamp_min_greater_than_max() { + 1.0f64.clamp(3.0, 1.0); + } + + #[test] + #[should_panic] + fn test_clamp_min_is_nan() { + 1.0f64.clamp(NAN, 1.0); + } + + #[test] + #[should_panic] + fn test_clamp_max_is_nan() { + 1.0f64.clamp(3.0, NAN); + } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 33bf0d68126d4..433499a90a405 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -249,6 +249,7 @@ #![feature(cfg_target_vendor)] #![feature(char_error_internals)] #![feature(char_internals)] +#![feature(clamp)] #![feature(collections_range)] #![feature(compiler_builtins_lib)] #![feature(const_fn)] diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs index dea406efe6ca9..6c071afd42d05 100644 --- a/src/libstd/sys/redox/time.rs +++ b/src/libstd/sys/redox/time.rs @@ -12,6 +12,7 @@ use cmp::Ordering; use fmt; use sys::{cvt, syscall}; use time::Duration; +use convert::TryInto; const NSEC_PER_SEC: u64 = 1_000_000_000; @@ -40,8 +41,12 @@ impl Timespec { } fn add_duration(&self, other: &Duration) -> Timespec { - let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64); - let mut secs = secs.expect("overflow when adding duration to time"); + let mut secs = other + .as_secs() + .try_into() // <- target type would be `i64` + .ok() + .and_then(|secs| self.t.tv_sec.checked_add(secs)) + .expect("overflow when adding duration to time"); // Nano calculations can't overflow because nanos are <1B which fit // in a u32. @@ -53,16 +58,19 @@ impl Timespec { } Timespec { t: syscall::TimeSpec { - tv_sec: secs as i64, + tv_sec: secs, tv_nsec: nsec as i32, }, } } fn sub_duration(&self, other: &Duration) -> Timespec { - let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64); - let mut secs = secs.expect("overflow when subtracting duration \ - from time"); + let mut secs = other + .as_secs() + .try_into() // <- target type would be `i64` + .ok() + .and_then(|secs| self.t.tv_sec.checked_sub(secs)) + .expect("overflow when subtracting duration from time"); // Similar to above, nanos can't overflow. let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; @@ -73,7 +81,7 @@ impl Timespec { } Timespec { t: syscall::TimeSpec { - tv_sec: secs as i64, + tv_sec: secs, tv_nsec: nsec as i32, }, } diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index a1ad94872de5c..c1bea95ce91ab 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -13,6 +13,7 @@ use libc; use time::Duration; pub use self::inner::{Instant, SystemTime, UNIX_EPOCH}; +use convert::TryInto; const NSEC_PER_SEC: u64 = 1_000_000_000; @@ -41,8 +42,12 @@ impl Timespec { } fn add_duration(&self, other: &Duration) -> Timespec { - let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64); - let mut secs = secs.expect("overflow when adding duration to time"); + let mut secs = other + .as_secs() + .try_into() // <- target type would be `libc::time_t` + .ok() + .and_then(|secs| self.t.tv_sec.checked_add(secs)) + .expect("overflow when adding duration to time"); // Nano calculations can't overflow because nanos are <1B which fit // in a u32. @@ -54,16 +59,19 @@ impl Timespec { } Timespec { t: libc::timespec { - tv_sec: secs as libc::time_t, + tv_sec: secs, tv_nsec: nsec as libc::c_long, }, } } fn sub_duration(&self, other: &Duration) -> Timespec { - let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64); - let mut secs = secs.expect("overflow when subtracting duration \ - from time"); + let mut secs = other + .as_secs() + .try_into() // <- target type would be `libc::time_t` + .ok() + .and_then(|secs| self.t.tv_sec.checked_sub(secs)) + .expect("overflow when subtracting duration from time"); // Similar to above, nanos can't overflow. let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; @@ -74,7 +82,7 @@ impl Timespec { } Timespec { t: libc::timespec { - tv_sec: secs as libc::time_t, + tv_sec: secs, tv_nsec: nsec as libc::c_long, }, } diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs index ef8ed606526da..1be29b5139a55 100644 --- a/src/libstd/sys/windows/time.rs +++ b/src/libstd/sys/windows/time.rs @@ -16,6 +16,7 @@ use sys::c; use sys::cvt; use sys_common::mul_div_u64; use time::Duration; +use convert::TryInto; const NANOS_PER_SEC: u64 = 1_000_000_000; const INTERVALS_PER_SEC: u64 = NANOS_PER_SEC / 100; @@ -173,9 +174,11 @@ impl From for SystemTime { } fn dur2intervals(d: &Duration) -> i64 { - d.as_secs().checked_mul(INTERVALS_PER_SEC).and_then(|i| { - i.checked_add(d.subsec_nanos() as u64 / 100) - }).expect("overflow when converting duration to intervals") as i64 + d.as_secs() + .checked_mul(INTERVALS_PER_SEC) + .and_then(|i| i.checked_add(d.subsec_nanos() as u64 / 100)) + .and_then(|i| i.try_into().ok()) + .expect("overflow when converting duration to intervals") } fn intervals2dur(intervals: u64) -> Duration { diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs index 5b893505b34d2..291def3e64661 100644 --- a/src/libstd/time/mod.rs +++ b/src/libstd/time/mod.rs @@ -382,6 +382,17 @@ impl fmt::Debug for SystemTime { /// [`SystemTime`] instance to represent another fixed point in time. /// /// [`SystemTime`]: ../../std/time/struct.SystemTime.html +/// +/// # Examples +/// +/// ```no_run +/// use std::time::{SystemTime, UNIX_EPOCH}; +/// +/// match SystemTime::now().duration_since(UNIX_EPOCH) { +/// Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()), +/// Err(_) => panic!("SystemTime before UNIX EPOCH!"), +/// } +/// ``` #[stable(feature = "time2", since = "1.8.0")] pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH); @@ -498,7 +509,7 @@ mod tests { let dur = dur.duration(); assert!(a > b); assert_almost_eq!(b + dur, a); - assert_almost_eq!(b - dur, a); + assert_almost_eq!(a - dur, b); } } diff --git a/src/libstd_unicode/u_str.rs b/src/libstd_unicode/u_str.rs index 1274b0625875b..0046e3f7bd093 100644 --- a/src/libstd_unicode/u_str.rs +++ b/src/libstd_unicode/u_str.rs @@ -26,7 +26,7 @@ use core::str::Split; /// [`split_whitespace`]: ../../std/primitive.str.html#method.split_whitespace /// [`str`]: ../../std/primitive.str.html #[stable(feature = "split_whitespace", since = "1.1.0")] -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct SplitWhitespace<'a> { inner: Filter, IsNotEmpty>, } diff --git a/src/test/compile-fail/issue-22706.rs b/src/test/compile-fail/issue-22706.rs new file mode 100644 index 0000000000000..3d9ec0a6581d6 --- /dev/null +++ b/src/test/compile-fail/issue-22706.rs @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn is_copy::Copy>() {} +//~^ ERROR type parameters are not allowed on this type [E0109] +fn main() {} diff --git a/src/test/mir-opt/validate_1.rs b/src/test/mir-opt/validate_1.rs index ae9dcf8b7352d..f9833ffecc280 100644 --- a/src/test/mir-opt/validate_1.rs +++ b/src/test/mir-opt/validate_1.rs @@ -30,7 +30,7 @@ fn main() { // END RUST SOURCE // START rustc.node12.EraseRegions.after.mir // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(5) => validate_1/8cd878b::{{impl}}[0]::foo[0] }, BrAnon(0)) Test, _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(5) => validate_1/8cd878b::{{impl}}[0]::foo[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(0:5) => validate_1/8cd878b::{{impl}}[0]::foo[0] }, BrAnon(0)) Test, _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(0:5) => validate_1/8cd878b::{{impl}}[0]::foo[0] }, BrAnon(1)) mut i32]); // return; // } // END rustc.node12.EraseRegions.after.mir @@ -57,7 +57,7 @@ fn main() { // START rustc.node50.EraseRegions.after.mir // fn main::{{closure}}(_1: &ReErased [closure@NodeId(50)], _2: &ReErased mut i32) -> i32 { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483663) => validate_1/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483663) => validate_1/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:15) => validate_1/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:15) => validate_1/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); // _3 = _2; // StorageLive(_4); diff --git a/src/test/mir-opt/validate_4.rs b/src/test/mir-opt/validate_4.rs index 2ee459d6809c5..cd5beae8e91fb 100644 --- a/src/test/mir-opt/validate_4.rs +++ b/src/test/mir-opt/validate_4.rs @@ -48,8 +48,8 @@ fn main() { // START rustc.node22.EraseRegions.after.mir // fn write_42::{{closure}}(_1: &ReErased [closure@NodeId(22)], _2: *mut i32) -> () { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483659) => validate_4/8cd878b::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]); -// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483659) => validate_4/8cd878b::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:11) => validate_4/8cd878b::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]); +// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:11) => validate_4/8cd878b::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]); // StorageLive(_3); // _3 = _2; // (*_3) = const 23i32; @@ -61,8 +61,8 @@ fn main() { // START rustc.node31.EraseRegions.after.mir // fn test(_1: &ReErased mut i32) -> () { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(4) => validate_4/8cd878b::test[0] }, BrAnon(0)) mut i32]); -// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(4) => validate_4/8cd878b::test[0] }, BrAnon(0)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(0:4) => validate_4/8cd878b::test[0] }, BrAnon(0)) mut i32]); +// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(0:4) => validate_4/8cd878b::test[0] }, BrAnon(0)) mut i32]); // _3 = const write_42(_4) -> bb1; // } // bb1: { @@ -74,8 +74,8 @@ fn main() { // START rustc.node60.EraseRegions.after.mir // fn main::{{closure}}(_1: &ReErased [closure@NodeId(60)], _2: &ReErased mut i32) -> bool { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483663) => validate_4/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483663) => validate_4/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); -// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483663) => validate_4/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483663) => validate_4/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:15) => validate_4/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:15) => validate_4/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:15) => validate_4/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:15) => validate_4/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); // _0 = const write_42(_4) -> bb1; // } diff --git a/src/test/mir-opt/validate_5.rs b/src/test/mir-opt/validate_5.rs index ef2073dcc4b0f..dc3daee7ad3a4 100644 --- a/src/test/mir-opt/validate_5.rs +++ b/src/test/mir-opt/validate_5.rs @@ -36,7 +36,7 @@ fn main() { // START rustc.node17.EraseRegions.after.mir // fn test(_1: &ReErased mut i32) -> () { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(4) => validate_5/8cd878b::test[0] }, BrAnon(0)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(0:4) => validate_5/8cd878b::test[0] }, BrAnon(0)) mut i32]); // Validate(Release, [_3: bool, _4: *mut i32]); // _3 = const write_42(_4) -> bb1; // } @@ -45,7 +45,7 @@ fn main() { // START rustc.node46.EraseRegions.after.mir // fn main::{{closure}}(_1: &ReErased [closure@NodeId(46)], _2: &ReErased mut i32) -> bool { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483660) => validate_5/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(2147483660) => validate_5/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:12) => validate_5/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:12) => validate_5/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); // _3 = _2; // StorageLive(_4); diff --git a/src/test/run-fail/issue-44216-add.rs b/src/test/run-fail/issue-44216-add.rs new file mode 100644 index 0000000000000..18bacd0459b2d --- /dev/null +++ b/src/test/run-fail/issue-44216-add.rs @@ -0,0 +1,18 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:overflow when + +use std::time::{Instant, Duration}; + +fn main() { + let now = Instant::now(); + let _ = now + Duration::from_secs(u64::max_value()); +} diff --git a/src/test/run-fail/issue-44216-sub.rs b/src/test/run-fail/issue-44216-sub.rs new file mode 100644 index 0000000000000..551401c51bbec --- /dev/null +++ b/src/test/run-fail/issue-44216-sub.rs @@ -0,0 +1,18 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:overflow when + +use std::time::{Instant, Duration}; + +fn main() { + let now = Instant::now(); + let _ = now - Duration::from_secs(u64::max_value()); +} diff --git a/src/test/run-pass/issue-23338-ensure-param-drop-order.rs b/src/test/run-pass/issue-23338-ensure-param-drop-order.rs index 9d0612f2a8daa..42c72e647fd2e 100644 --- a/src/test/run-pass/issue-23338-ensure-param-drop-order.rs +++ b/src/test/run-pass/issue-23338-ensure-param-drop-order.rs @@ -64,8 +64,7 @@ fn test<'a>(log: d::Log<'a>) { d::println(&format!("result {}", result)); } -// FIXME(#33490) Remove the double braces when old trans is gone. -fn foo<'a>(da0: D<'a>, de1: D<'a>) -> D<'a> {{ +fn foo<'a>(da0: D<'a>, de1: D<'a>) -> D<'a> { d::println("entered foo"); let de2 = de1.incr(); // creates D(de_2, 2) let de4 = { @@ -74,7 +73,7 @@ fn foo<'a>(da0: D<'a>, de1: D<'a>) -> D<'a> {{ }; d::println("eval tail of foo"); de4.incr().incr() // creates D(de_5, 6) and D(de_6, 7) -}} +} // This module provides simultaneous printouts of the dynamic extents // of all of the D values, in addition to logging the order that each diff --git a/src/test/run-pass/issue-33185.rs b/src/test/run-pass/issue-33185.rs new file mode 100644 index 0000000000000..f12e65323bc95 --- /dev/null +++ b/src/test/run-pass/issue-33185.rs @@ -0,0 +1,26 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +#[macro_export] +macro_rules! state { + ( $( $name:ident : $field:ty )* ) => ( + #[derive(Default)] + struct State { + $($name : $field),* + } + ) +} + +state! { x: i64 } + +pub fn main() { +} diff --git a/src/test/run-pass/issue-35376.rs b/src/test/run-pass/issue-35376.rs new file mode 100644 index 0000000000000..25895cd0753e4 --- /dev/null +++ b/src/test/run-pass/issue-35376.rs @@ -0,0 +1,51 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(specialization)] + +fn main() {} + +pub trait Alpha { } + +pub trait Beta { + type Event; +} + +pub trait Delta { + type Handle; + fn process(&self); +} + +pub struct Parent(A, T); + +impl Delta for Parent +where A: Alpha, + T: Delta, + T::Handle: Beta::Event> { + type Handle = Handle; + default fn process(&self) { + unimplemented!() + } +} + +impl Delta for Parent +where A: Alpha + Alpha, + T: Delta, + T::Handle: Beta::Event> { + fn process(&self) { + unimplemented!() + } +} + +pub struct Handle; + +impl Beta for Handle { + type Event = (); +} \ No newline at end of file diff --git a/src/test/run-pass/overloaded-autoderef-order.rs b/src/test/run-pass/overloaded-autoderef-order.rs index 7433494dec677..8ea8b375b17b4 100644 --- a/src/test/run-pass/overloaded-autoderef-order.rs +++ b/src/test/run-pass/overloaded-autoderef-order.rs @@ -75,7 +75,6 @@ pub fn main() { assert_eq!(Rc::new(nested).x, true); let nested_priv = priv_test::DerefWrapperHideX::new(true, DerefWrapper {x: 0, y: 1}); - // FIXME(eddyb) #12808 should skip private fields. - // assert_eq!(nested_priv.x, 0); + assert_eq!(nested_priv.x, 0); assert_eq!((*nested_priv).x, 0); } diff --git a/src/test/ui/str-lit-type-mismatch.rs b/src/test/ui/str-lit-type-mismatch.rs new file mode 100644 index 0000000000000..0fd7d3a9d869e --- /dev/null +++ b/src/test/ui/str-lit-type-mismatch.rs @@ -0,0 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +fn main() { + let x: &[u8] = "foo"; + let y: &[u8; 4] = "baaa"; + let z: &str = b"foo"; +} diff --git a/src/test/ui/str-lit-type-mismatch.stderr b/src/test/ui/str-lit-type-mismatch.stderr new file mode 100644 index 0000000000000..47418522df8ac --- /dev/null +++ b/src/test/ui/str-lit-type-mismatch.stderr @@ -0,0 +1,32 @@ +error[E0308]: mismatched types + --> $DIR/str-lit-type-mismatch.rs:13:20 + | +13 | let x: &[u8] = "foo"; + | ^^^^^ expected slice, found str + | + = note: expected type `&[u8]` + found type `&'static str` + = help: try `b"foo"` + +error[E0308]: mismatched types + --> $DIR/str-lit-type-mismatch.rs:14:23 + | +14 | let y: &[u8; 4] = "baaa"; + | ^^^^^^ expected array of 4 elements, found str + | + = note: expected type `&[u8; 4]` + found type `&'static str` + = help: try `b"baaa"` + +error[E0308]: mismatched types + --> $DIR/str-lit-type-mismatch.rs:15:19 + | +15 | let z: &str = b"foo"; + | ^^^^^^ expected str, found array of 3 elements + | + = note: expected type `&str` + found type `&'static [u8; 3]` + = help: try `"foo"` + +error: aborting due to 3 previous errors + diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index e2be021e7cc39..0e91fa9c6022b 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -113,6 +113,7 @@ struct Manifest { #[derive(Serialize)] struct Package { version: String, + git_commit_hash: Option, target: BTreeMap, } @@ -167,6 +168,9 @@ struct Builder { rust_version: String, cargo_version: String, rls_version: String, + rust_git_commit_hash: Option, + cargo_git_commit_hash: Option, + rls_git_commit_hash: Option, } fn main() { @@ -194,6 +198,9 @@ fn main() { rust_version: String::new(), cargo_version: String::new(), rls_version: String::new(), + rust_git_commit_hash: None, + cargo_git_commit_hash: None, + rls_git_commit_hash: None, }.build(); } @@ -202,18 +209,16 @@ impl Builder { self.rust_version = self.version("rust", "x86_64-unknown-linux-gnu"); self.cargo_version = self.version("cargo", "x86_64-unknown-linux-gnu"); self.rls_version = self.version("rls", "x86_64-unknown-linux-gnu"); + self.rust_git_commit_hash = self.git_commit_hash("rust", "x86_64-unknown-linux-gnu"); + self.cargo_git_commit_hash = self.git_commit_hash("cargo", "x86_64-unknown-linux-gnu"); + self.rls_git_commit_hash = self.git_commit_hash("rls", "x86_64-unknown-linux-gnu"); self.digest_and_sign(); let manifest = self.build_manifest(); - let filename = format!("channel-rust-{}.toml", self.rust_release); - self.write_manifest(&toml::to_string(&manifest).unwrap(), &filename); - - let filename = format!("channel-rust-{}-date.txt", self.rust_release); - self.write_date_stamp(&manifest.date, &filename); + self.write_channel_files(&self.rust_release, &manifest); if self.rust_release != "beta" && self.rust_release != "nightly" { - self.write_manifest(&toml::to_string(&manifest).unwrap(), "channel-rust-stable.toml"); - self.write_date_stamp(&manifest.date, "channel-rust-stable-date.txt"); + self.write_channel_files("stable", &manifest); } } @@ -249,6 +254,7 @@ impl Builder { let mut pkg = Package { version: self.cached_version("rust").to_string(), + git_commit_hash: self.cached_git_commit_hash("rust").clone(), target: BTreeMap::new(), }; for host in HOSTS { @@ -342,6 +348,7 @@ impl Builder { dst.insert(pkgname.to_string(), Package { version: self.cached_version(pkgname).to_string(), + git_commit_hash: self.cached_git_commit_hash(pkgname).clone(), target: targets, }); } @@ -375,6 +382,16 @@ impl Builder { } } + fn cached_git_commit_hash(&self, component: &str) -> &Option { + if component == "cargo" { + &self.cargo_git_commit_hash + } else if component == "rls" || component == "rls-preview" { + &self.rls_git_commit_hash + } else { + &self.rust_git_commit_hash + } + } + fn version(&self, component: &str, target: &str) -> String { let mut cmd = Command::new("tar"); let filename = self.filename(component, target); @@ -382,14 +399,33 @@ impl Builder { .arg(self.input.join(&filename)) .arg(format!("{}/version", filename.replace(".tar.gz", ""))) .arg("-O"); - let version = t!(cmd.output()); - if !version.status.success() { + let output = t!(cmd.output()); + if !output.status.success() { panic!("failed to learn version:\n\n{:?}\n\n{}\n\n{}", cmd, - String::from_utf8_lossy(&version.stdout), - String::from_utf8_lossy(&version.stderr)); + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr)); + } + String::from_utf8_lossy(&output.stdout).trim().to_string() + } + + fn git_commit_hash(&self, component: &str, target: &str) -> Option { + let mut cmd = Command::new("tar"); + let filename = self.filename(component, target); + cmd.arg("xf") + .arg(self.input.join(&filename)) + .arg(format!("{}/git-commit-hash", filename.replace(".tar.gz", ""))) + .arg("-O"); + let output = t!(cmd.output()); + if output.status.success() { + Some(String::from_utf8_lossy(&output.stdout).trim().to_string()) + } else { + // This is always called after `.version()`. + // So if that didn’t fail but this does, + // that’s very probably because the tarball is valid + // but does not contain a `git-commit-hash` file. + None } - String::from_utf8_lossy(&version.stdout).trim().to_string() } fn hash(&self, path: &Path) -> String { @@ -425,16 +461,16 @@ impl Builder { assert!(t!(child.wait()).success()); } - fn write_manifest(&self, manifest: &str, name: &str) { - let dst = self.output.join(name); - t!(t!(File::create(&dst)).write_all(manifest.as_bytes())); - self.hash(&dst); - self.sign(&dst); + fn write_channel_files(&self, channel_name: &str, manifest: &Manifest) { + self.write(&toml::to_string(&manifest).unwrap(), channel_name, ".toml"); + self.write(&manifest.date, channel_name, "-date.txt"); + self.write(manifest.pkg["rust"].git_commit_hash.as_ref().unwrap(), + channel_name, "-git-commit-hash.txt"); } - fn write_date_stamp(&self, date: &str, name: &str) { - let dst = self.output.join(name); - t!(t!(File::create(&dst)).write_all(date.as_bytes())); + fn write(&self, contents: &str, channel_name: &str, suffix: &str) { + let dst = self.output.join(format!("channel-rust-{}{}", channel_name, suffix)); + t!(t!(File::create(&dst)).write_all(contents.as_bytes())); self.hash(&dst); self.sign(&dst); }