diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index c85b04ddc0245..2c9f0ddb6c33d 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -1007,6 +1007,10 @@ pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: boo continue }; if json["reason"].as_str() != Some("compiler-artifact") { + if build.config.rustc_error_format.as_ref().map_or(false, |e| e == "json") { + // most likely not a cargo message, so let's send it out as well + println!("{}", line); + } continue } for filename in json["filenames"].as_array().unwrap() { diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 8ca5910a11c0d..af50ad1e96b9f 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -119,7 +119,7 @@ To learn more about a subcommand, run `./x.py -h`"); opts.optopt("", "src", "path to the root of the rust checkout", "DIR"); opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS"); opts.optflag("h", "help", "print this help message"); - opts.optflag("", "error-format", "rustc error format"); + opts.optopt("", "error-format", "rustc error format", "FORMAT"); // fn usage() let usage = |exit_code: i32, opts: &Options, subcommand_help: &str, extra_help: &str| -> ! { diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 15dd7fabfa58b..653606e5d24b5 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -480,6 +480,7 @@ impl Step for Openssl { "mips64el-unknown-linux-gnuabi64" => "linux64-mips64", "mipsel-unknown-linux-gnu" => "linux-mips32", "powerpc-unknown-linux-gnu" => "linux-ppc", + "powerpc-unknown-linux-gnuspe" => "linux-ppc", "powerpc-unknown-netbsd" => "BSD-generic32", "powerpc64-unknown-linux-gnu" => "linux-ppc64", "powerpc64le-unknown-linux-gnu" => "linux-ppc64le", diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs index 174628ccd0788..2de0ffb4b2611 100644 --- a/src/liballoc/benches/lib.rs +++ b/src/liballoc/benches/lib.rs @@ -13,7 +13,6 @@ #![feature(i128_type)] #![feature(rand)] #![feature(repr_simd)] -#![feature(slice_rotate)] #![feature(test)] extern crate rand; diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 5139e54b5604a..d250cfe1880fc 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -79,7 +79,6 @@ #![cfg_attr(test, feature(placement_in))] #![cfg_attr(not(test), feature(core_float))] #![cfg_attr(not(test), feature(exact_size_is_empty))] -#![cfg_attr(not(test), feature(slice_rotate))] #![cfg_attr(not(test), feature(generator_trait))] #![cfg_attr(test, feature(rand, test))] #![feature(allow_internal_unstable)] diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 028983de556f2..dc40062ef13df 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1460,8 +1460,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_rotate)] - /// /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; /// a.rotate_left(2); /// assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']); @@ -1470,23 +1468,15 @@ impl [T] { /// Rotating a subslice: /// /// ``` - /// #![feature(slice_rotate)] - /// /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; /// a[1..5].rotate_left(1); /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']); - /// ``` - #[unstable(feature = "slice_rotate", issue = "41891")] + /// ``` + #[stable(feature = "slice_rotate", since = "1.26.0")] pub fn rotate_left(&mut self, mid: usize) { core_slice::SliceExt::rotate_left(self, mid); } - #[unstable(feature = "slice_rotate", issue = "41891")] - #[rustc_deprecated(since = "", reason = "renamed to `rotate_left`")] - pub fn rotate(&mut self, mid: usize) { - core_slice::SliceExt::rotate_left(self, mid); - } - /// Rotates the slice in-place such that the first `self.len() - k` /// elements of the slice move to the end while the last `k` elements move /// to the front. After calling `rotate_right`, the element previously at @@ -1505,8 +1495,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_rotate)] - /// /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; /// a.rotate_right(2); /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']); @@ -1515,13 +1503,11 @@ impl [T] { /// Rotate a subslice: /// /// ``` - /// #![feature(slice_rotate)] - /// /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; /// a[1..5].rotate_right(1); /// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']); /// ``` - #[unstable(feature = "slice_rotate", issue = "41891")] + #[stable(feature = "slice_rotate", since = "1.26.0")] pub fn rotate_right(&mut self, k: usize) { core_slice::SliceExt::rotate_right(self, k); } diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 427a7adcbded1..168dbb2ce9b1f 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -23,7 +23,6 @@ #![feature(pattern)] #![feature(placement_in_syntax)] #![feature(rand)] -#![feature(slice_rotate)] #![feature(splice)] #![feature(str_escape)] #![feature(string_retain)] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 7d5aa25016bdd..59a67fff48cfe 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -634,6 +634,46 @@ $EndFeature, " } } + doc_comment! { + concat!("Checked exponentiation. Computes `self.pow(exp)`, returning `None` if +overflow occurred. + +# Examples + +Basic usage: + +``` +#![feature(no_panic_pow)] +", $Feature, "assert_eq!(8", stringify!($SelfT), ".checked_pow(2), Some(64)); +assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", +$EndFeature, " +```"), + + #[unstable(feature = "no_panic_pow", issue = "48320")] + #[inline] + pub fn checked_pow(self, mut exp: u32) -> Option { + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.checked_mul(base)?; + } + exp /= 2; + base = base.checked_mul(base)?; + } + + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + if exp == 1 { + acc = acc.checked_mul(base)?; + } + + Some(acc) + } + } + doc_comment! { concat!("Saturating integer addition. Computes `self + rhs`, saturating at the numeric bounds instead of overflowing. @@ -713,6 +753,34 @@ $EndFeature, " } } + doc_comment! { + concat!("Saturating integer exponentiation. Computes `self.pow(exp)`, +saturating at the numeric bounds instead of overflowing. + +# Examples + +Basic usage: + +``` +#![feature(no_panic_pow)] +", $Feature, "use std::", stringify!($SelfT), "; + +assert_eq!((-4", stringify!($SelfT), ").saturating_pow(3), -64); +assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(2), ", stringify!($SelfT), "::MAX); +assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT), "::MIN);", +$EndFeature, " +```"), + #[unstable(feature = "no_panic_pow", issue = "48320")] + #[inline] + pub fn saturating_pow(self, exp: u32) -> Self { + match self.checked_pow(exp) { + Some(x) => x, + None if self < 0 && exp % 2 == 1 => Self::min_value(), + None => Self::max_value(), + } + } + } + doc_comment! { concat!("Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the boundary of the type. @@ -947,6 +1015,46 @@ $EndFeature, " } } + doc_comment! { + concat!("Wrapping (modular) exponentiation. Computes `self.pow(exp)`, +wrapping around at the boundary of the type. + +# Examples + +Basic usage: + +``` +#![feature(no_panic_pow)] +", $Feature, "assert_eq!(3", stringify!($SelfT), ".wrapping_pow(4), 81); +assert_eq!(3i8.wrapping_pow(5), -13); +assert_eq!(3i8.wrapping_pow(6), -39);", +$EndFeature, " +```"), + #[unstable(feature = "no_panic_pow", issue = "48320")] + #[inline] + pub fn wrapping_pow(self, mut exp: u32) -> Self { + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + } + exp /= 2; + base = base.wrapping_mul(base); + } + + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + if exp == 1 { + acc = acc.wrapping_mul(base); + } + + acc + } + } + doc_comment! { concat!("Calculates `self` + `rhs` @@ -1202,6 +1310,56 @@ $EndFeature, " doc_comment! { concat!("Raises self to the power of `exp`, using exponentiation by squaring. +Returns a tuple of the exponentiation along with a bool indicating +whether an overflow happened. + +# Examples + +Basic usage: + +``` +#![feature(no_panic_pow)] +", $Feature, "assert_eq!(3", stringify!($SelfT), ".overflowing_pow(4), (81, false)); +assert_eq!(3i8.overflowing_pow(5), (-13, true));", +$EndFeature, " +```"), + #[unstable(feature = "no_panic_pow", issue = "48320")] + #[inline] + pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { + let mut base = self; + let mut acc: Self = 1; + let mut overflown = false; + // Scratch space for storing results of overflowing_mul. + let mut r; + + while exp > 1 { + if (exp & 1) == 1 { + r = acc.overflowing_mul(base); + acc = r.0; + overflown |= r.1; + } + exp /= 2; + r = base.overflowing_mul(base); + base = r.0; + overflown |= r.1; + } + + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + if exp == 1 { + r = acc.overflowing_mul(base); + acc = r.0; + overflown |= r.1; + } + + (acc, overflown) + } + } + + doc_comment! { + concat!("Raises self to the power of `exp`, using exponentiation by squaring. + # Examples Basic usage: @@ -1887,6 +2045,44 @@ assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);", $EndFeature, } } + doc_comment! { + concat!("Checked exponentiation. Computes `self.pow(exp)`, returning `None` if +overflow occurred. + +# Examples + +Basic usage: + +``` +#![feature(no_panic_pow)] +", $Feature, "assert_eq!(2", stringify!($SelfT), ".checked_pow(5), Some(32)); +assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", $EndFeature, " +```"), + #[unstable(feature = "no_panic_pow", issue = "48320")] + #[inline] + pub fn checked_pow(self, mut exp: u32) -> Option { + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.checked_mul(base)?; + } + exp /= 2; + base = base.checked_mul(base)?; + } + + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + if exp == 1 { + acc = acc.checked_mul(base)?; + } + + Some(acc) + } + } + doc_comment! { concat!("Saturating integer addition. Computes `self + rhs`, saturating at the numeric bounds instead of overflowing. @@ -1953,6 +2149,32 @@ assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($Se } } + doc_comment! { + concat!("Saturating integer exponentiation. Computes `self.pow(exp)`, +saturating at the numeric bounds instead of overflowing. + +# Examples + +Basic usage: + +``` +#![feature(no_panic_pow)] +", $Feature, "use std::", stringify!($SelfT), "; + +assert_eq!(4", stringify!($SelfT), ".saturating_pow(3), 64); +assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT), "::MAX);", +$EndFeature, " +```"), + #[unstable(feature = "no_panic_pow", issue = "48320")] + #[inline] + pub fn saturating_pow(self, exp: u32) -> Self { + match self.checked_pow(exp) { + Some(x) => x, + None => Self::max_value(), + } + } + } + doc_comment! { concat!("Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the boundary of the type. @@ -2147,6 +2369,44 @@ assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);", $EndFeature, " } } + doc_comment! { + concat!("Wrapping (modular) exponentiation. Computes `self.pow(exp)`, +wrapping around at the boundary of the type. + +# Examples + +Basic usage: + +``` +#![feature(no_panic_pow)] +", $Feature, "assert_eq!(3", stringify!($SelfT), ".wrapping_pow(5), 243); +assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, " +```"), + #[unstable(feature = "no_panic_pow", issue = "48320")] + #[inline] + pub fn wrapping_pow(self, mut exp: u32) -> Self { + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + } + exp /= 2; + base = base.wrapping_mul(base); + } + + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + if exp == 1 { + acc = acc.wrapping_mul(base); + } + + acc + } + } + doc_comment! { concat!("Calculates `self` + `rhs` @@ -2353,7 +2613,55 @@ assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));", $E pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) { (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) } + } + doc_comment! { + concat!("Raises self to the power of `exp`, using exponentiation by squaring. + +Returns a tuple of the exponentiation along with a bool indicating +whether an overflow happened. + +# Examples + +Basic usage: + +``` +#![feature(no_panic_pow)] +", $Feature, "assert_eq!(3", stringify!($SelfT), ".overflowing_pow(5), (243, false)); +assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, " +```"), + #[unstable(feature = "no_panic_pow", issue = "48320")] + #[inline] + pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { + let mut base = self; + let mut acc: Self = 1; + let mut overflown = false; + // Scratch space for storing results of overflowing_mul. + let mut r; + + while exp > 1 { + if (exp & 1) == 1 { + r = acc.overflowing_mul(base); + acc = r.0; + overflown |= r.1; + } + exp /= 2; + r = base.overflowing_mul(base); + base = r.0; + overflown |= r.1; + } + + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + if exp == 1 { + r = acc.overflowing_mul(base); + acc = r.0; + overflown |= r.1; + } + + (acc, overflown) + } } doc_comment! { diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index ac390313a6797..a43ed65907f83 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -211,10 +211,10 @@ pub trait SliceExt { #[stable(feature = "core", since = "1.6.0")] fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; - #[unstable(feature = "slice_rotate", issue = "41891")] + #[stable(feature = "slice_rotate", since = "1.26.0")] fn rotate_left(&mut self, mid: usize); - #[unstable(feature = "slice_rotate", issue = "41891")] + #[stable(feature = "slice_rotate", since = "1.26.0")] fn rotate_right(&mut self, k: usize); #[stable(feature = "clone_from_slice", since = "1.7.0")] diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 7954d52f6b1e3..0049ed66a102a 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -37,7 +37,6 @@ #![feature(refcell_replace_swap)] #![feature(sip_hash_13)] #![feature(slice_patterns)] -#![feature(slice_rotate)] #![feature(sort_internals)] #![feature(specialization)] #![feature(step_trait)] diff --git a/src/librustc_back/target/apple_base.rs b/src/librustc_back/target/apple_base.rs index 159f93a74c683..72173b62594e9 100644 --- a/src/librustc_back/target/apple_base.rs +++ b/src/librustc_back/target/apple_base.rs @@ -46,6 +46,7 @@ pub fn opts() -> TargetOptions { pre_link_args: LinkArgs::new(), exe_allocation_crate: super::maybe_jemalloc(), has_elf_tls: version >= (10, 7), + abi_return_struct_as_int: true, .. Default::default() } } diff --git a/src/librustc_back/target/freebsd_base.rs b/src/librustc_back/target/freebsd_base.rs index a0f84a6ab0495..291b22768998c 100644 --- a/src/librustc_back/target/freebsd_base.rs +++ b/src/librustc_back/target/freebsd_base.rs @@ -36,6 +36,7 @@ pub fn opts() -> TargetOptions { eliminate_frame_pointer: false, // FIXME 43575 relro_level: RelroLevel::Full, exe_allocation_crate: super::maybe_jemalloc(), + abi_return_struct_as_int: true, .. Default::default() } } diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index d356105e39314..be69127d8f2ab 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -143,6 +143,7 @@ supported_targets! { ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64), ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu), ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu), + ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe), ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu), ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu), ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu), @@ -345,9 +346,8 @@ pub struct TargetOptions { pub staticlib_suffix: String, /// OS family to use for conditional compilation. Valid options: "unix", "windows". pub target_family: Option, - /// Whether the target toolchain is like OpenBSD's. - /// Only useful for compiling against OpenBSD, for configuring abi when returning a struct. - pub is_like_openbsd: bool, + /// Whether the target toolchain's ABI supports returning small structs as an integer. + pub abi_return_struct_as_int: bool, /// Whether the target toolchain is like macOS's. Only useful for compiling against iOS/macOS, /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false. pub is_like_osx: bool, @@ -503,7 +503,7 @@ impl Default for TargetOptions { staticlib_prefix: "lib".to_string(), staticlib_suffix: ".a".to_string(), target_family: None, - is_like_openbsd: false, + abi_return_struct_as_int: false, is_like_osx: false, is_like_solaris: false, is_like_windows: false, @@ -758,7 +758,7 @@ impl Target { key!(staticlib_prefix); key!(staticlib_suffix); key!(target_family, optional); - key!(is_like_openbsd, bool); + key!(abi_return_struct_as_int, bool); key!(is_like_osx, bool); key!(is_like_solaris, bool); key!(is_like_windows, bool); @@ -956,7 +956,7 @@ impl ToJson for Target { target_option_val!(staticlib_prefix); target_option_val!(staticlib_suffix); target_option_val!(target_family); - target_option_val!(is_like_openbsd); + target_option_val!(abi_return_struct_as_int); target_option_val!(is_like_osx); target_option_val!(is_like_solaris); target_option_val!(is_like_windows); diff --git a/src/librustc_back/target/openbsd_base.rs b/src/librustc_back/target/openbsd_base.rs index ab421dec7807f..311e260ee3f34 100644 --- a/src/librustc_back/target/openbsd_base.rs +++ b/src/librustc_back/target/openbsd_base.rs @@ -31,7 +31,7 @@ pub fn opts() -> TargetOptions { target_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - is_like_openbsd: true, + abi_return_struct_as_int: true, pre_link_args: args, position_independent_executables: true, eliminate_frame_pointer: false, // FIXME 43575 diff --git a/src/librustc_back/target/powerpc_unknown_linux_gnuspe.rs b/src/librustc_back/target/powerpc_unknown_linux_gnuspe.rs new file mode 100644 index 0000000000000..ffcc321749b5a --- /dev/null +++ b/src/librustc_back/target/powerpc_unknown_linux_gnuspe.rs @@ -0,0 +1,35 @@ +// Copyright 2018 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. + +use LinkerFlavor; +use target::{Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::linux_base::opts(); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mspe".to_string()); + base.max_atomic_width = Some(32); + + // see #36994 + base.exe_allocation_crate = None; + + Ok(Target { + llvm_target: "powerpc-unknown-linux-gnuspe".to_string(), + target_endian: "big".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), + arch: "powerpc".to_string(), + target_os: "linux".to_string(), + target_env: "gnu".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +} diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs index cc40b8b052983..30038400f6c81 100644 --- a/src/librustc_back/target/windows_base.rs +++ b/src/librustc_back/target/windows_base.rs @@ -101,6 +101,7 @@ pub fn opts() -> TargetOptions { "rsend.o".to_string() ], custom_unwind_resume: true, + abi_return_struct_as_int: true, .. Default::default() } diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_back/target/windows_msvc_base.rs index 64df6624dd1c2..e0bf36ee4077e 100644 --- a/src/librustc_back/target/windows_msvc_base.rs +++ b/src/librustc_back/target/windows_msvc_base.rs @@ -34,6 +34,7 @@ pub fn opts() -> TargetOptions { pre_link_args: args, crt_static_allows_dylibs: true, crt_static_respected: true, + abi_return_struct_as_int: true, .. Default::default() } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f872fd475461e..6af7a23f66d73 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -139,6 +139,19 @@ pub mod target_features { const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\ md#bug-reports"; +const ICE_REPORT_COMPILER_FLAGS: &'static [&'static str] = &[ + "Z", + "C", + "crate-type", +]; +const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &'static [&'static str] = &[ + "metadata", + "extra-filename", +]; +const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &'static [&'static str] = &[ + "incremental", +]; + pub fn abort_on_err(result: Result, sess: &Session) -> T { match result { Err(CompileIncomplete::Errored(ErrorReported)) => { @@ -1431,6 +1444,57 @@ pub fn in_rustc_thread(f: F) -> Result> thread.unwrap().join() } +/// Get a list of extra command-line flags provided by the user, as strings. +/// +/// This function is used during ICEs to show more information useful for +/// debugging, since some ICEs only happens with non-default compiler flags +/// (and the users don't always report them). +fn extra_compiler_flags() -> Option<(Vec, bool)> { + let mut args = Vec::new(); + for arg in env::args_os() { + args.push(arg.to_string_lossy().to_string()); + } + + let matches = if let Some(matches) = handle_options(&args) { + matches + } else { + return None; + }; + + let mut result = Vec::new(); + let mut excluded_cargo_defaults = false; + for flag in ICE_REPORT_COMPILER_FLAGS { + let prefix = if flag.len() == 1 { "-" } else { "--" }; + + for content in &matches.opt_strs(flag) { + // Split always returns the first element + let name = if let Some(first) = content.split('=').next() { + first + } else { + &content + }; + + let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) { + name + } else { + content + }; + + if !ICE_REPORT_COMPILER_FLAGS_EXCLUDE.contains(&name) { + result.push(format!("{}{} {}", prefix, flag, content)); + } else { + excluded_cargo_defaults = true; + } + } + } + + if result.len() > 0 { + Some((result, excluded_cargo_defaults)) + } else { + None + } +} + /// Run a procedure which will detect panics in the compiler and print nicer /// error messages rather than just failing the test. /// @@ -1462,11 +1526,22 @@ pub fn monitor(f: F) { errors::Level::Bug); } - let xs = ["the compiler unexpectedly panicked. this is a bug.".to_string(), - format!("we would appreciate a bug report: {}", BUG_REPORT_URL), - format!("rustc {} running on {}", - option_env!("CFG_VERSION").unwrap_or("unknown_version"), - config::host_triple())]; + let mut xs = vec![ + "the compiler unexpectedly panicked. this is a bug.".to_string(), + format!("we would appreciate a bug report: {}", BUG_REPORT_URL), + format!("rustc {} running on {}", + option_env!("CFG_VERSION").unwrap_or("unknown_version"), + config::host_triple()), + ]; + + if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { + xs.push(format!("compiler flags: {}", flags.join(" "))); + + if excluded_cargo_defaults { + xs.push("some of the compiler flags provided by cargo are hidden".to_string()); + } + } + for note in &xs { handler.emit(&MultiSpan::new(), ¬e, diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 549919a2c8919..7c86f5a4b1a84 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -118,10 +118,13 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { match *self.as_mono_item() { MonoItem::Fn(ref instance) => { + let entry_def_id = + tcx.sess.entry_fn.borrow().map(|(id, _)| tcx.hir.local_def_id(id)); // If this function isn't inlined or otherwise has explicit // linkage, then we'll be creating a globally shared version. if self.explicit_linkage(tcx).is_some() || - !instance.def.requires_local(tcx) + !instance.def.requires_local(tcx) || + Some(instance.def_id()) == entry_def_id { return InstantiationMode::GloballyShared { may_conflict: false } } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index d7c75dea8d04e..8f308e726865c 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -849,7 +849,19 @@ fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path) args.push_str("\n"); } let file = tmpdir.join("linker-arguments"); - fs::write(&file, args.as_bytes())?; + let bytes = if sess.target.target.options.is_like_msvc { + let mut out = vec![]; + // start the stream with a UTF-16 BOM + for c in vec![0xFEFF].into_iter().chain(args.encode_utf16()) { + // encode in little endian + out.push(c as u8); + out.push((c >> 8) as u8); + } + out + } else { + args.into_bytes() + }; + fs::write(&file, &bytes)?; cmd2.arg(format!("@{}", file.display())); return cmd2.output(); diff --git a/src/librustc_trans/cabi_x86.rs b/src/librustc_trans/cabi_x86.rs index 60347ba0945f9..b14558448067c 100644 --- a/src/librustc_trans/cabi_x86.rs +++ b/src/librustc_trans/cabi_x86.rs @@ -52,8 +52,7 @@ pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // http://www.angelcode.com/dev/callconv/callconv.html // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp let t = &cx.sess().target.target; - if t.options.is_like_osx || t.options.is_like_windows - || t.options.is_like_openbsd { + if t.options.abi_return_struct_as_int { // According to Clang, everyone but MSVC returns single-element // float aggregates directly in a floating-point register. if !t.options.is_like_msvc && is_single_fp_element(cx, fty.ret.layout) { diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs index 6271dcdfb2433..00ac9d802457c 100644 --- a/src/librustc_trans/llvm_util.rs +++ b/src/librustc_trans/llvm_util.rs @@ -87,7 +87,7 @@ const X86_WHITELIST: &'static [&'static str] = &["aes", "avx", "avx2", "avx512bw "avx512cd", "avx512dq", "avx512er", "avx512f", "avx512ifma", "avx512pf", "avx512vbmi", "avx512vl", "avx512vpopcntdq", - "bmi", "bmi2", "fma", "fxsr", + "bmi1", "bmi2", "fma", "fxsr", "lzcnt", "mmx", "pclmulqdq", "popcnt", "rdrand", "rdseed", "sse", "sse2", "sse3", "sse4.1", @@ -108,6 +108,7 @@ pub fn to_llvm_feature(s: &str) -> &str { match s { "pclmulqdq" => "pclmul", "rdrand" => "rdrnd", + "bmi1" => "bmi", s => s, } } diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index f1bba0e836189..3654de6fb2ed2 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -25,7 +25,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { AdtKind::Struct => Def::Struct, AdtKind::Enum => Def::Enum, AdtKind::Union => Def::Union, - }, + } _ => panic!("Unexpected type {:?}", def_id), }; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4543b246b83ad..870b5383852b0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3428,7 +3428,11 @@ fn build_deref_target_impls(cx: &DocContext, let primitive = match *target { ResolvedPath { did, .. } if did.is_local() => continue, ResolvedPath { did, .. } => { - ret.extend(inline::build_impls(cx, did, true)); + // We set the last parameter to false to avoid looking for auto-impls for traits + // and therefore avoid an ICE. + // The reason behind this is that auto-traits don't propagate through Deref so + // we're not supposed to synthesise impls for them. + ret.extend(inline::build_impls(cx, did, false)); continue } _ => match target.primitive_type() { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 5c674cabde5d8..a94d2a856aeb1 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -96,14 +96,6 @@ } } - function onEach(arr, func) { - if (arr && arr.length > 0 && func) { - for (var i = 0; i < arr.length; i++) { - func(arr[i]); - } - } - } - function isHidden(elem) { return (elem.offsetParent === null) } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index cd4f2cfa678e6..a6630902c9794 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1189,6 +1189,10 @@ kbd { top: 19px; } +.theme-picker button { + outline: none; +} + #theme-picker { padding: 4px; width: 27px; diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index 0aa1065b3786a..f21dfc8af9298 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -13,6 +13,18 @@ var currentTheme = document.getElementById("themeStyle"); var mainTheme = document.getElementById("mainThemeStyle"); +var savedHref = []; + +function onEach(arr, func) { + if (arr && arr.length > 0 && func) { + for (var i = 0; i < arr.length; i++) { + if (func(arr[i]) === true) { + break; + } + } + } +} + function updateLocalStorage(name, value) { if (typeof(Storage) !== "undefined") { localStorage[name] = value; @@ -29,8 +41,24 @@ function getCurrentValue(name) { } function switchTheme(styleElem, mainStyleElem, newTheme) { - styleElem.href = mainStyleElem.href.replace("rustdoc.css", newTheme + ".css"); - updateLocalStorage('theme', newTheme); + var newHref = mainStyleElem.href.replace("rustdoc.css", newTheme + ".css"); + var found = false; + + if (savedHref.length === 0) { + onEach(document.getElementsByTagName("link"), function(el) { + savedHref.push(el.href); + }); + } + onEach(savedHref, function(el) { + if (el === newHref) { + found = true; + return true; + } + }); + if (found === true) { + styleElem.href = newHref; + updateLocalStorage('rustdoc-theme', newTheme); + } } -switchTheme(currentTheme, mainTheme, getCurrentValue('theme') || 'main'); +switchTheme(currentTheme, mainTheme, getCurrentValue('rustdoc-theme') || 'main'); diff --git a/src/libstd/process.rs b/src/libstd/process.rs index e25599b8bd871..e5fc33e241c89 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1080,6 +1080,15 @@ impl fmt::Display for ExitStatus { } } +/// This is ridiculously unstable, as it's a completely-punted-upon part +/// of the `?`-in-`main` RFC. It's here only to allow experimenting with +/// returning a code directly from main. It will definitely change +/// drastically before being stabilized, if it doesn't just get deleted. +#[doc(hidden)] +#[derive(Clone, Copy, Debug)] +#[unstable(feature = "process_exitcode_placeholder", issue = "43301")] +pub struct ExitCode(pub i32); + impl Child { /// Forces the child to exit. This is equivalent to sending a /// SIGKILL on unix platforms. @@ -1428,7 +1437,7 @@ impl Termination for () { } #[unstable(feature = "termination_trait_lib", issue = "43301")] -impl Termination for Result { +impl Termination for Result<(), E> { fn report(self) -> i32 { match self { Ok(val) => val.report(), @@ -1442,20 +1451,23 @@ impl Termination for Result { #[unstable(feature = "termination_trait_lib", issue = "43301")] impl Termination for ! { - fn report(self) -> i32 { unreachable!(); } + fn report(self) -> i32 { self } } #[unstable(feature = "termination_trait_lib", issue = "43301")] -impl Termination for bool { +impl Termination for Result { fn report(self) -> i32 { - if self { exit::SUCCESS } else { exit::FAILURE } + let Err(err) = self; + eprintln!("Error: {:?}", err); + exit::FAILURE } } #[unstable(feature = "termination_trait_lib", issue = "43301")] -impl Termination for i32 { +impl Termination for ExitCode { fn report(self) -> i32 { - self + let ExitCode(code) = self; + code } } diff --git a/src/test/run-make/atomic-lock-free/Makefile b/src/test/run-make/atomic-lock-free/Makefile index 63b8608afc763..a7df821f92d71 100644 --- a/src/test/run-make/atomic-lock-free/Makefile +++ b/src/test/run-make/atomic-lock-free/Makefile @@ -32,6 +32,8 @@ endif ifeq ($(filter powerpc,$(LLVM_COMPONENTS)),powerpc) $(RUSTC) --target=powerpc-unknown-linux-gnu atomic_lock_free.rs nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add + $(RUSTC) --target=powerpc-unknown-linux-gnuspe atomic_lock_free.rs + nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add $(RUSTC) --target=powerpc64-unknown-linux-gnu atomic_lock_free.rs nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add $(RUSTC) --target=powerpc64le-unknown-linux-gnu atomic_lock_free.rs diff --git a/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs b/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs index f9168a82e2259..67d8ad0b67255 100644 --- a/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs +++ b/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs @@ -36,8 +36,11 @@ fn main() { let ok = tmpdir.join("ok"); let not_ok = tmpdir.join("not_ok"); if env::var("YOU_ARE_A_LINKER").is_ok() { - match env::args().find(|a| a.contains("@")) { - Some(file) => { fs::copy(&file[1..], &ok).unwrap(); } + match env::args_os().find(|a| a.to_string_lossy().contains("@")) { + Some(file) => { + let file = file.to_str().unwrap(); + fs::copy(&file[1..], &ok).unwrap(); + } None => { File::create(¬_ok).unwrap(); } } return @@ -84,11 +87,23 @@ fn main() { continue } - let mut contents = String::new(); - File::open(&ok).unwrap().read_to_string(&mut contents).unwrap(); + let mut contents = Vec::new(); + File::open(&ok).unwrap().read_to_end(&mut contents).unwrap(); for j in 0..i { - assert!(contents.contains(&format!("{}{}", lib_name, j))); + let exp = format!("{}{}", lib_name, j); + let exp = if cfg!(target_env = "msvc") { + let mut out = Vec::with_capacity(exp.len() * 2); + for c in exp.encode_utf16() { + // encode in little endian + out.push(c as u8); + out.push((c >> 8) as u8); + } + out + } else { + exp.into_bytes() + }; + assert!(contents.windows(exp.len()).any(|w| w == &exp[..])); } break diff --git a/src/test/run-make/long-linker-command-lines/foo.rs b/src/test/run-make/long-linker-command-lines/foo.rs index e6fd6b653667f..2ac240982afc4 100644 --- a/src/test/run-make/long-linker-command-lines/foo.rs +++ b/src/test/run-make/long-linker-command-lines/foo.rs @@ -27,7 +27,8 @@ fn main() { let tmpdir = PathBuf::from(env::var_os("TMPDIR").unwrap()); let ok = tmpdir.join("ok"); if env::var("YOU_ARE_A_LINKER").is_ok() { - if let Some(file) = env::args().find(|a| a.contains("@")) { + if let Some(file) = env::args_os().find(|a| a.to_string_lossy().contains("@")) { + let file = file.to_str().expect("non-utf8 file argument"); fs::copy(&file[1..], &ok).unwrap(); } return @@ -76,11 +77,23 @@ fn main() { continue } - let mut contents = String::new(); - File::open(&ok).unwrap().read_to_string(&mut contents).unwrap(); + let mut contents = Vec::new(); + File::open(&ok).unwrap().read_to_end(&mut contents).unwrap(); for j in 0..i { - assert!(contents.contains(&format!("{}{}", lib_name, j))); + let exp = format!("{}{}", lib_name, j); + let exp = if cfg!(target_env = "msvc") { + let mut out = Vec::with_capacity(exp.len() * 2); + for c in exp.encode_utf16() { + // encode in little endian + out.push(c as u8); + out.push((c >> 8) as u8); + } + out + } else { + exp.into_bytes() + }; + assert!(contents.windows(exp.len()).any(|w| w == &exp[..])); } break diff --git a/src/test/run-pass/inlined-main.rs b/src/test/run-pass/inlined-main.rs new file mode 100644 index 0000000000000..1288c37d615cd --- /dev/null +++ b/src/test/run-pass/inlined-main.rs @@ -0,0 +1,12 @@ +// Copyright 2018 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. + +#[inline(always)] +fn main() {} diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-i32.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs similarity index 81% rename from src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-i32.rs rename to src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs index fa7cb023b447c..30ecc4e89372b 100644 --- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-i32.rs +++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs @@ -9,7 +9,10 @@ // except according to those terms. #![feature(termination_trait)] +#![feature(process_exitcode_placeholder)] -fn main() -> i32 { - 0 +use std::process::ExitCode; + +fn main() -> ExitCode { + ExitCode(0) } diff --git a/src/test/rustdoc/auto-impl-for-trait.rs b/src/test/rustdoc/auto-impl-for-trait.rs new file mode 100644 index 0000000000000..3cd6e7aa4b3d2 --- /dev/null +++ b/src/test/rustdoc/auto-impl-for-trait.rs @@ -0,0 +1,26 @@ +// Copyright 2018 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. + +// Test for https://github.com/rust-lang/rust/issues/48463 issue. + +use std::any::Any; +use std::ops::Deref; + +pub struct AnyValue { + val: Box, +} + +impl Deref for AnyValue { + type Target = Any; + + fn deref(&self) -> &Any { + &*self.val + } +} diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 0845179532224..49b054f8b9e50 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -83,6 +83,7 @@ static TARGETS: &'static [&'static str] = &[ "mipsel-unknown-linux-gnu", "mipsel-unknown-linux-musl", "powerpc-unknown-linux-gnu", + "powerpc-unknown-linux-gnuspe", "powerpc64-unknown-linux-gnu", "powerpc64le-unknown-linux-gnu", "s390x-unknown-linux-gnu", diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index e3d453a991d80..304143eaa0bff 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -736,17 +736,12 @@ fn analyze_gdb(gdb: Option) -> (Option, Option, bool) { Some(ref s) => s, }; - let version_line = Command::new(gdb) - .arg("--version") - .output() - .map(|output| { - String::from_utf8_lossy(&output.stdout) - .lines() - .next() - .unwrap() - .to_string() - }) - .ok(); + let mut version_line = None; + if let Ok(output) = Command::new(gdb).arg("--version").output() { + if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() { + version_line = Some(first_line.to_string()); + } + } let version = match version_line { Some(line) => extract_gdb_version(&line),