From 3e7a4ca2f1d576a4a23e8c541cb5c0c420b108de Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 17 Dec 2018 16:47:26 +0100 Subject: [PATCH 01/36] Remove a wrong multiplier on relocation offset computation --- src/librustc_mir/interpret/memory.rs | 8 ++++---- src/test/ui/consts/promoted_regression.rs | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/consts/promoted_regression.rs diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 420fe26426321..65347a02be0c7 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -707,10 +707,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { new_relocations.extend( relocations .iter() - .map(|&(offset, reloc)| { - (offset + dest.offset - src.offset + (i * size * relocations.len() as u64), - reloc) - }) + .map(|&(offset, reloc)| ( + offset + dest.offset - src.offset + (i * size), + reloc, + )) ); } diff --git a/src/test/ui/consts/promoted_regression.rs b/src/test/ui/consts/promoted_regression.rs new file mode 100644 index 0000000000000..68b9a20ecf90b --- /dev/null +++ b/src/test/ui/consts/promoted_regression.rs @@ -0,0 +1,9 @@ +// compile-pass + +fn main() { + let _ = &[("", ""); 3]; +} + +const FOO: &[(&str, &str)] = &[("", ""); 3]; +const BAR: &[(&str, &str); 5] = &[("", ""); 5]; +const BAA: &[[&str; 12]; 11] = &[[""; 12]; 11]; From e7e17f9d1b008a1f06ad8b4ef06c443b4b879bc4 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Mon, 17 Dec 2018 03:17:59 +0000 Subject: [PATCH 02/36] static eval: Do not ICE on layout size overflow Layout size overflow and typeck eval errors are reported. Trigger a bug only when the eval error is strictly labeled as TooGeneric. --- src/librustc_mir/const_eval.rs | 12 ++++++++---- src/test/ui/issues/issue-56762.rs | 18 ++++++++++++++++++ src/test/ui/issues/issue-56762.stderr | 4 ++++ 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/issues/issue-56762.rs create mode 100644 src/test/ui/issues/issue-56762.stderr diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 248c5d2db4917..d5bc83aba7b99 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -692,12 +692,16 @@ pub fn const_eval_raw_provider<'a, 'tcx>( let err = error_to_const_error(&ecx, error); // errors in statics are always emitted as fatal errors if tcx.is_static(def_id).is_some() { - let err = err.report_as_error(ecx.tcx, "could not evaluate static initializer"); - // check that a static never produces `TooGeneric` + let reported_err = err.report_as_error(ecx.tcx, + "could not evaluate static initializer"); + // Ensure that if the above error was either `TooGeneric` or `Reported` + // an error must be reported. if tcx.sess.err_count() == 0 { - span_bug!(ecx.tcx.span, "static eval failure didn't emit an error: {:#?}", err); + tcx.sess.delay_span_bug(err.span, + &format!("static eval failure did not emit an error: {:#?}", + reported_err)); } - err + reported_err } else if def_id.is_local() { // constant defined in this crate, we can figure out a lint level! match tcx.describe_def(def_id) { diff --git a/src/test/ui/issues/issue-56762.rs b/src/test/ui/issues/issue-56762.rs new file mode 100644 index 0000000000000..97b66b2c7c923 --- /dev/null +++ b/src/test/ui/issues/issue-56762.rs @@ -0,0 +1,18 @@ +// only-x86_64 +const HUGE_SIZE: usize = !0usize / 8; + + +pub struct TooBigArray { + arr: [u8; HUGE_SIZE], +} + +impl TooBigArray { + pub const fn new() -> Self { + TooBigArray { arr: [0x00; HUGE_SIZE], } + } +} + +static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new(); +static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE]; + +fn main() { } diff --git a/src/test/ui/issues/issue-56762.stderr b/src/test/ui/issues/issue-56762.stderr new file mode 100644 index 0000000000000..83d5dc62e6161 --- /dev/null +++ b/src/test/ui/issues/issue-56762.stderr @@ -0,0 +1,4 @@ +error: the type `[u8; 2305843009213693951]` is too big for the current architecture + +error: aborting due to previous error + From 6130fc884bc1dff9bb835894a7bb2042c110b011 Mon Sep 17 00:00:00 2001 From: Clar Fon Date: Mon, 17 Dec 2018 17:16:39 -0500 Subject: [PATCH 03/36] Add --progress to git submodule commands --- src/bootstrap/bootstrap.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d143dffb24be5..09c87fdd1a84c 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -678,10 +678,10 @@ def update_submodule(self, module, checked_out, recorded_submodules): print("Updating submodule", module) - run(["git", "submodule", "-q", "sync", module], + run(["git", "submodule", "-q", "sync", "--progress", module], cwd=self.rust_root, verbose=self.verbose) run(["git", "submodule", "update", - "--init", "--recursive", module], + "--init", "--recursive", "--progress", module], cwd=self.rust_root, verbose=self.verbose) run(["git", "reset", "-q", "--hard"], cwd=module_path, verbose=self.verbose) From e36b62873fb6787d521fbc4e0bd89915e28ed0f1 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Mon, 17 Dec 2018 16:41:48 -0800 Subject: [PATCH 04/36] rename div_euc -> div_euclid, and mod_euc -> rem_euclid logic is written up in https://github.com/rust-lang/rust/issues/49048 Also, update the documentation slightly --- src/libcore/num/mod.rs | 172 ++++++++++++++++------------ src/libcore/tests/num/int_macros.rs | 4 +- src/libcore/tests/num/mod.rs | 26 ++--- src/libstd/f32.rs | 30 ++--- src/libstd/f64.rs | 30 ++--- 5 files changed, 141 insertions(+), 121 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index f1df1f2856ed6..cedee1c8e5f99 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -673,7 +673,7 @@ $EndFeature, " } doc_comment! { - concat!("Checked Euclidean division. Computes `self.div_euc(rhs)`, + concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if `rhs == 0` or the division results in overflow. # Examples @@ -683,17 +683,17 @@ Basic usage: ``` #![feature(euclidean_division)] assert_eq!((", stringify!($SelfT), -"::min_value() + 1).checked_div_euc(-1), Some(", stringify!($Max), ")); -assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euc(-1), None); -assert_eq!((1", stringify!($SelfT), ").checked_div_euc(0), None); +"::min_value() + 1).checked_div_euclid(-1), Some(", stringify!($Max), ")); +assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euclid(-1), None); +assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn checked_div_euc(self, rhs: Self) -> Option { + pub fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { - Some(self.div_euc(rhs)) + Some(self.div_euclid(rhs)) } } } @@ -726,8 +726,8 @@ $EndFeature, " } doc_comment! { - concat!("Checked Euclidean modulo. Computes `self.mod_euc(rhs)`, returning `None` if -`rhs == 0` or the division results in overflow. + concat!("Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` +if `rhs == 0` or the division results in overflow. # Examples @@ -737,17 +737,17 @@ Basic usage: #![feature(euclidean_division)] use std::", stringify!($SelfT), "; -assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(2), Some(1)); -assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(0), None); -assert_eq!(", stringify!($SelfT), "::MIN.checked_mod_euc(-1), None); +assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1)); +assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); +assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn checked_mod_euc(self, rhs: Self) -> Option { + pub fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { - Some(self.mod_euc(rhs)) + Some(self.rem_euclid(rhs)) } } } @@ -1089,7 +1089,7 @@ $EndFeature, " } doc_comment! { - concat!("Wrapping Euclidean division. Computes `self.div_euc(rhs)`, + concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`, wrapping around at the boundary of the type. Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value @@ -1106,13 +1106,13 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(100", stringify!($SelfT), ".wrapping_div_euc(10), 10); -assert_eq!((-128i8).wrapping_div_euc(-1), -128); +assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); +assert_eq!((-128i8).wrapping_div_euclid(-1), -128); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn wrapping_div_euc(self, rhs: Self) -> Self { - self.overflowing_div_euc(rhs).0 + pub fn wrapping_div_euclid(self, rhs: Self) -> Self { + self.overflowing_div_euclid(rhs).0 } } @@ -1145,8 +1145,8 @@ $EndFeature, " } doc_comment! { - concat!("Wrapping Euclidean modulo. Computes `self.mod_euc(rhs)`, wrapping around at the -boundary of the type. + concat!("Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around +at the boundary of the type. Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value for the type). In this case, this method returns 0. @@ -1161,13 +1161,13 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(100", stringify!($SelfT), ".wrapping_mod_euc(10), 0); -assert_eq!((-128i8).wrapping_mod_euc(-1), 0); +assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); +assert_eq!((-128i8).wrapping_rem_euclid(-1), 0); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn wrapping_mod_euc(self, rhs: Self) -> Self { - self.overflowing_mod_euc(rhs).0 + pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { + self.overflowing_rem_euclid(rhs).0 } } @@ -1442,7 +1442,7 @@ $EndFeature, " } doc_comment! { - concat!("Calculates the quotient of Euclidean division `self.div_euc(rhs)`. + concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would occur. If an overflow would occur then `self` is returned. @@ -1459,17 +1459,17 @@ Basic usage: #![feature(euclidean_division)] use std::", stringify!($SelfT), "; -assert_eq!(5", stringify!($SelfT), ".overflowing_div_euc(2), (2, false)); -assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euc(-1), (", stringify!($SelfT), +assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); +assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringify!($SelfT), "::MIN, true)); ```"), #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn overflowing_div_euc(self, rhs: Self) -> (Self, bool) { + pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (self, true) } else { - (self.div_euc(rhs), false) + (self.div_euclid(rhs), false) } } } @@ -1508,7 +1508,7 @@ $EndFeature, " doc_comment! { - concat!("Calculates the remainder `self.mod_euc(rhs)` by Euclidean division. + concat!("Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`. Returns a tuple of the remainder after dividing along with a boolean indicating whether an arithmetic overflow would occur. If an overflow would occur then 0 is returned. @@ -1525,16 +1525,16 @@ Basic usage: #![feature(euclidean_division)] use std::", stringify!($SelfT), "; -assert_eq!(5", stringify!($SelfT), ".overflowing_mod_euc(2), (1, false)); -assert_eq!(", stringify!($SelfT), "::MIN.overflowing_mod_euc(-1), (0, true)); +assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); +assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn overflowing_mod_euc(self, rhs: Self) -> (Self, bool) { + pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (0, true) } else { - (self.mod_euc(rhs), false) + (self.rem_euclid(rhs), false) } } } @@ -1739,9 +1739,13 @@ $EndFeature, " doc_comment! { concat!("Calculates the quotient of Euclidean division of `self` by `rhs`. -This computes the integer `n` such that `self = n * rhs + self.mod_euc(rhs)`. +This computes the integer `n` such that `self = n * rhs + self.rem_euclid(rhs)`, +with the `0 <= self.rem_euclid(rhs) < rhs`. + In other words, the result is `self / rhs` rounded to the integer `n` such that `self >= n * rhs`. +If `self > 0`, this is equal to round towards zero (the default in Rust); +if `self < 0`, this is equal to round towards +/- infinity. # Panics @@ -1756,15 +1760,15 @@ Basic usage: let a: ", stringify!($SelfT), " = 7; // or any other integer type let b = 4; -assert_eq!(a.div_euc(b), 1); // 7 >= 4 * 1 -assert_eq!(a.div_euc(-b), -1); // 7 >= -4 * -1 -assert_eq!((-a).div_euc(b), -2); // -7 >= 4 * -2 -assert_eq!((-a).div_euc(-b), 2); // -7 >= -4 * 2 +assert_eq!(a.div_euclid(b), 1); // 7 >= 4 * 1 +assert_eq!(a.div_euclid(-b), -1); // 7 >= -4 * -1 +assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2 +assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] #[rustc_inherit_overflow_checks] - pub fn div_euc(self, rhs: Self) -> Self { + pub fn div_euclid(self, rhs: Self) -> Self { let q = self / rhs; if self % rhs < 0 { return if rhs > 0 { q - 1 } else { q + 1 } @@ -1775,9 +1779,9 @@ assert_eq!((-a).div_euc(-b), 2); // -7 >= -4 * 2 doc_comment! { - concat!("Calculates the remainder `self mod rhs` by Euclidean division. + concat!("Calculates the least nonnegative remainder of `self (mod rhs)`. -In particular, the result `n` satisfies `0 <= n < rhs.abs()`. +This is done as if by the euclidean division algorithm. # Panics @@ -1792,15 +1796,15 @@ Basic usage: let a: ", stringify!($SelfT), " = 7; // or any other integer type let b = 4; -assert_eq!(a.mod_euc(b), 3); -assert_eq!((-a).mod_euc(b), 1); -assert_eq!(a.mod_euc(-b), 3); -assert_eq!((-a).mod_euc(-b), 1); +assert_eq!(a.rem_euclid(b), 3); +assert_eq!((-a).rem_euclid(b), 1); +assert_eq!(a.rem_euclid(-b), 3); +assert_eq!((-a).rem_euclid(-b), 1); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] #[rustc_inherit_overflow_checks] - pub fn mod_euc(self, rhs: Self) -> Self { + pub fn rem_euclid(self, rhs: Self) -> Self { let r = self % rhs; if r < 0 { if rhs < 0 { @@ -2611,7 +2615,7 @@ assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, " } doc_comment! { - concat!("Checked Euclidean division. Computes `self.div_euc(rhs)`, returning `None` + concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if `rhs == 0`. # Examples @@ -2620,16 +2624,16 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(128", stringify!($SelfT), ".checked_div(2), Some(64)); -assert_eq!(1", stringify!($SelfT), ".checked_div_euc(0), None); +assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64)); +assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn checked_div_euc(self, rhs: Self) -> Option { + pub fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 { None } else { - Some(self.div_euc(rhs)) + Some(self.div_euclid(rhs)) } } } @@ -2659,7 +2663,7 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, " } doc_comment! { - concat!("Checked Euclidean modulo. Computes `self.mod_euc(rhs)`, returning `None` + concat!("Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning `None` if `rhs == 0`. # Examples @@ -2668,16 +2672,16 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(2), Some(1)); -assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(0), None); +assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1)); +assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn checked_mod_euc(self, rhs: Self) -> Option { + pub fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 { None } else { - Some(self.mod_euc(rhs)) + Some(self.rem_euclid(rhs)) } } } @@ -2965,11 +2969,14 @@ Basic usage: } doc_comment! { - concat!("Wrapping Euclidean division. Computes `self.div_euc(rhs)`. + concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`. Wrapped division on unsigned types is just normal division. There's no way wrapping could ever happen. This function exists, so that all operations are accounted for in the wrapping operations. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self.wrapping_div(rhs)`. # Examples @@ -2977,11 +2984,11 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(100", stringify!($SelfT), ".wrapping_div_euc(10), 10); +assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn wrapping_div_euc(self, rhs: Self) -> Self { + pub fn wrapping_div_euclid(self, rhs: Self) -> Self { self / rhs } } @@ -3009,12 +3016,15 @@ Basic usage: } doc_comment! { - concat!("Wrapping Euclidean modulo. Computes `self.mod_euc(rhs)`. + concat!("Wrapping Euclidean modulo. Computes `self.rem_euclid(rhs)`. Wrapped modulo calculation on unsigned types is just the regular remainder calculation. There's no way wrapping could ever happen. This function exists, so that all operations are accounted for in the wrapping operations. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self.wrapping_rem(rhs)`. # Examples @@ -3022,11 +3032,11 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(100", stringify!($SelfT), ".wrapping_mod_euc(10), 0); +assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn wrapping_mod_euc(self, rhs: Self) -> Self { + pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { self % rhs } } @@ -3270,12 +3280,15 @@ Basic usage } doc_comment! { - concat!("Calculates the quotient of Euclidean division `self.div_euc(rhs)`. + concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would occur. Note that for unsigned integers overflow never occurs, so the second value is always `false`. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self.overflowing_div(rhs)`. # Panics @@ -3287,11 +3300,11 @@ Basic usage ``` #![feature(euclidean_division)] -assert_eq!(5", stringify!($SelfT), ".overflowing_div_euc(2), (2, false)); +assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); ```"), #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn overflowing_div_euc(self, rhs: Self) -> (Self, bool) { + pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { (self / rhs, false) } } @@ -3323,12 +3336,15 @@ Basic usage } doc_comment! { - concat!("Calculates the remainder `self.mod_euc(rhs)` by Euclidean division. + concat!("Calculates the remainder `self.rem_euclid(rhs)` as if by Euclidean division. Returns a tuple of the modulo after dividing along with a boolean indicating whether an arithmetic overflow would occur. Note that for unsigned integers overflow never occurs, so the second value is always `false`. +Since, for the positive integers, all common +definitions of division are equal, this operation +is exactly equal to `self.overflowing_rem(rhs)`. # Panics @@ -3340,11 +3356,11 @@ Basic usage ``` #![feature(euclidean_division)] -assert_eq!(5", stringify!($SelfT), ".overflowing_mod_euc(2), (1, false)); +assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); ```"), #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn overflowing_mod_euc(self, rhs: Self) -> (Self, bool) { + pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { (self % rhs, false) } } @@ -3511,7 +3527,9 @@ Basic usage: doc_comment! { concat!("Performs Euclidean division. -For unsigned types, this is just the same as `self / rhs`. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self / rhs`. # Examples @@ -3519,21 +3537,23 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(7", stringify!($SelfT), ".div_euc(4), 1); // or any other integer type +assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] #[rustc_inherit_overflow_checks] - pub fn div_euc(self, rhs: Self) -> Self { + pub fn div_euclid(self, rhs: Self) -> Self { self / rhs } } doc_comment! { - concat!("Calculates the remainder `self mod rhs` by Euclidean division. + concat!("Calculates the least remainder of `self (mod rhs)`. -For unsigned types, this is just the same as `self % rhs`. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self % rhs`. # Examples @@ -3541,12 +3561,12 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(7", stringify!($SelfT), ".mod_euc(4), 3); // or any other integer type +assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] #[rustc_inherit_overflow_checks] - pub fn mod_euc(self, rhs: Self) -> Self { + pub fn rem_euclid(self, rhs: Self) -> Self { self % rhs } } diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs index 71d2e7945389b..577847b3c8282 100644 --- a/src/libcore/tests/num/int_macros.rs +++ b/src/libcore/tests/num/int_macros.rs @@ -31,8 +31,8 @@ mod tests { } #[test] - fn test_mod_euc() { - assert!((-1 as $T).mod_euc(MIN) == MAX); + fn test_mod_euclid() { + assert!((-1 as $T).mod_euclid(MIN) == MAX); } #[test] diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs index 0928f7560e175..e1648db5e8ed2 100644 --- a/src/libcore/tests/num/mod.rs +++ b/src/libcore/tests/num/mod.rs @@ -694,23 +694,23 @@ macro_rules! test_float { assert!(($nan as $fty).max($nan).is_nan()); } #[test] - fn mod_euc() { + fn rem_euclid() { let a: $fty = 42.0; - assert!($inf.mod_euc(a).is_nan()); - assert_eq!(a.mod_euc($inf), a); - assert!(a.mod_euc($nan).is_nan()); - assert!($inf.mod_euc($inf).is_nan()); - assert!($inf.mod_euc($nan).is_nan()); - assert!($nan.mod_euc($inf).is_nan()); + assert!($inf.rem_euclid(a).is_nan()); + assert_eq!(a.rem_euclid($inf), a); + assert!(a.rem_euclid($nan).is_nan()); + assert!($inf.rem_euclid($inf).is_nan()); + assert!($inf.rem_euclid($nan).is_nan()); + assert!($nan.rem_euclid($inf).is_nan()); } #[test] - fn div_euc() { + fn div_euclid() { let a: $fty = 42.0; - assert_eq!(a.div_euc($inf), 0.0); - assert!(a.div_euc($nan).is_nan()); - assert!($inf.div_euc($inf).is_nan()); - assert!($inf.div_euc($nan).is_nan()); - assert!($nan.div_euc($inf).is_nan()); + assert_eq!(a.div_euclid($inf), 0.0); + assert!(a.div_euclid($nan).is_nan()); + assert!($inf.div_euclid($inf).is_nan()); + assert!($inf.div_euclid($nan).is_nan()); + assert!($nan.div_euclid($inf).is_nan()); } } } } diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index d0dd4d4adcb98..209343444a0b5 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -253,10 +253,10 @@ impl f32 { unsafe { intrinsics::fmaf32(self, a, b) } } - /// Calculates Euclidean division, the matching method for `mod_euc`. + /// Calculates Euclidean division, the matching method for `rem_euclid`. /// /// This computes the integer `n` such that - /// `self = n * rhs + self.mod_euc(rhs)`. + /// `self = n * rhs + self.rem_euclid(rhs)`. /// In other words, the result is `self / rhs` rounded to the integer `n` /// such that `self >= n * rhs`. /// @@ -266,14 +266,14 @@ impl f32 { /// #![feature(euclidean_division)] /// let a: f32 = 7.0; /// let b = 4.0; - /// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0 - /// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0 - /// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0 - /// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0 + /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0 + /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0 + /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0 + /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// ``` #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn div_euc(self, rhs: f32) -> f32 { + pub fn div_euclid(self, rhs: f32) -> f32 { let q = (self / rhs).trunc(); if self % rhs < 0.0 { return if rhs > 0.0 { q - 1.0 } else { q + 1.0 } @@ -281,7 +281,7 @@ impl f32 { q } - /// Calculates the Euclidean modulo (self mod rhs), which is never negative. + /// Calculates the least nonnegative remainder of `self (mod rhs)`. /// /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in /// most cases. However, due to a floating point round-off error it can @@ -289,7 +289,7 @@ impl f32 { /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`. /// This result is not an element of the function's codomain, but it is the /// closest floating point number in the real numbers and thus fulfills the - /// property `self == self.div_euc(rhs) * rhs + self.mod_euc(rhs)` + /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)` /// approximatively. /// /// # Examples @@ -298,16 +298,16 @@ impl f32 { /// #![feature(euclidean_division)] /// let a: f32 = 7.0; /// let b = 4.0; - /// assert_eq!(a.mod_euc(b), 3.0); - /// assert_eq!((-a).mod_euc(b), 1.0); - /// assert_eq!(a.mod_euc(-b), 3.0); - /// assert_eq!((-a).mod_euc(-b), 1.0); + /// assert_eq!(a.rem_euclid(b), 3.0); + /// assert_eq!((-a).rem_euclid(b), 1.0); + /// assert_eq!(a.rem_euclid(-b), 3.0); + /// assert_eq!((-a).rem_euclid(-b), 1.0); /// // limitation due to round-off error - /// assert!((-std::f32::EPSILON).mod_euc(3.0) != 0.0); + /// assert!((-std::f32::EPSILON).rem_euclid(3.0) != 0.0); /// ``` #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn mod_euc(self, rhs: f32) -> f32 { + pub fn rem_euclid(self, rhs: f32) -> f32 { let r = self % rhs; if r < 0.0 { r + rhs.abs() diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 9e627ec204291..b73a67ed9d8a0 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -229,10 +229,10 @@ impl f64 { unsafe { intrinsics::fmaf64(self, a, b) } } - /// Calculates Euclidean division, the matching method for `mod_euc`. + /// Calculates Euclidean division, the matching method for `rem_euclid`. /// /// This computes the integer `n` such that - /// `self = n * rhs + self.mod_euc(rhs)`. + /// `self = n * rhs + self.rem_euclid(rhs)`. /// In other words, the result is `self / rhs` rounded to the integer `n` /// such that `self >= n * rhs`. /// @@ -242,14 +242,14 @@ impl f64 { /// #![feature(euclidean_division)] /// let a: f64 = 7.0; /// let b = 4.0; - /// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0 - /// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0 - /// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0 - /// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0 + /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0 + /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0 + /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0 + /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// ``` #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn div_euc(self, rhs: f64) -> f64 { + pub fn div_euclid(self, rhs: f64) -> f64 { let q = (self / rhs).trunc(); if self % rhs < 0.0 { return if rhs > 0.0 { q - 1.0 } else { q + 1.0 } @@ -257,7 +257,7 @@ impl f64 { q } - /// Calculates the Euclidean modulo (self mod rhs), which is never negative. + /// Calculates the least nonnegative remainder of `self (mod rhs)`. /// /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in /// most cases. However, due to a floating point round-off error it can @@ -265,7 +265,7 @@ impl f64 { /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`. /// This result is not an element of the function's codomain, but it is the /// closest floating point number in the real numbers and thus fulfills the - /// property `self == self.div_euc(rhs) * rhs + self.mod_euc(rhs)` + /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)` /// approximatively. /// /// # Examples @@ -274,16 +274,16 @@ impl f64 { /// #![feature(euclidean_division)] /// let a: f64 = 7.0; /// let b = 4.0; - /// assert_eq!(a.mod_euc(b), 3.0); - /// assert_eq!((-a).mod_euc(b), 1.0); - /// assert_eq!(a.mod_euc(-b), 3.0); - /// assert_eq!((-a).mod_euc(-b), 1.0); + /// assert_eq!(a.rem_euclid(b), 3.0); + /// assert_eq!((-a).rem_euclid(b), 1.0); + /// assert_eq!(a.rem_euclid(-b), 3.0); + /// assert_eq!((-a).rem_euclid(-b), 1.0); /// // limitation due to round-off error - /// assert!((-std::f64::EPSILON).mod_euc(3.0) != 0.0); + /// assert!((-std::f64::EPSILON).rem_euclid(3.0) != 0.0); /// ``` #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn mod_euc(self, rhs: f64) -> f64 { + pub fn rem_euclid(self, rhs: f64) -> f64 { let r = self % rhs; if r < 0.0 { r + rhs.abs() From 82e55c1bdcf0a20a2652152447160414a9cd57d7 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Mon, 17 Dec 2018 21:10:24 -0500 Subject: [PATCH 05/36] deny intra-doc link resolution failures in libstd --- src/liballoc/lib.rs | 2 ++ src/liballoc/rc.rs | 5 ++++- src/liballoc/sync.rs | 5 ++++- src/libcore/lib.rs | 1 + src/libcore/mem.rs | 3 +++ src/libcore/slice/mod.rs | 2 ++ src/libstd/io/buffered.rs | 5 ++++- src/libstd/io/error.rs | 3 +++ src/libstd/lib.rs | 1 + 9 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index abacc62c8562b..31a4aeeab4be8 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -72,6 +72,8 @@ test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![no_std] #![needs_allocator] + +#![deny(intra_doc_link_resolution_failure)] #![deny(missing_debug_implementations)] #![cfg_attr(not(test), feature(fn_traits))] diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 52ad30c411a10..37204bc20c272 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -840,6 +840,8 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc { /// drop(foo); // Doesn't print anything /// drop(foo2); // Prints "dropped!" /// ``` + /// + /// [`Weak`]: ../../std/rc/struct.Weak.html fn drop(&mut self) { unsafe { self.dec_strong(); @@ -1381,9 +1383,10 @@ impl fmt::Debug for Weak { #[stable(feature = "downgraded_weak", since = "1.10.0")] impl Default for Weak { /// Constructs a new `Weak`, allocating memory for `T` without initializing - /// it. Calling [`upgrade`][Weak::upgrade] on the return value always gives [`None`]. + /// it. Calling [`upgrade`] on the return value always gives [`None`]. /// /// [`None`]: ../../std/option/enum.Option.html + /// [`upgrade`]: ../../std/rc/struct.Weak.html#method.upgrade /// /// # Examples /// diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 111459d12a4df..5f72b232c64ce 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -952,6 +952,8 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { /// drop(foo); // Doesn't print anything /// drop(foo2); // Prints "dropped!" /// ``` + /// + /// [`Weak`]: ../../std/sync/struct.Weak.html #[inline] fn drop(&mut self) { // Because `fetch_sub` is already atomic, we do not need to synchronize @@ -1219,10 +1221,11 @@ impl Clone for Weak { #[stable(feature = "downgraded_weak", since = "1.10.0")] impl Default for Weak { /// Constructs a new `Weak`, without allocating memory. - /// Calling [`upgrade`][Weak::upgrade] on the return value always + /// Calling [`upgrade`] on the return value always /// gives [`None`]. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`upgrade`]: ../../std/sync/struct.Weak.html#method.upgrade /// /// # Examples /// diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a51674fbfc71a..258f499d44481 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -71,6 +71,7 @@ #![no_core] #![deny(missing_docs)] +#![deny(intra_doc_link_resolution_failure)] #![deny(missing_debug_implementations)] #![feature(allow_internal_unstable)] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index afd9fcb1fba84..0cde23cde40f1 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -984,6 +984,9 @@ impl ManuallyDrop { /// /// This function semantically moves out the contained value without preventing further usage. /// It is up to the user of this method to ensure that this container is not used again. + /// + /// [`ManuallyDrop::drop`]: #method.drop + /// [`ManuallyDrop::into_inner`]: #method.into_inner #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] #[unstable(feature = "manually_drop_take", issue = "55422")] #[inline] diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 59c11b273293f..193061457b5cd 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -877,6 +877,7 @@ impl [T] { /// assert_eq!(iter.remainder(), &['l']); /// ``` /// + /// [`chunks`]: #method.chunks /// [`rchunks`]: #method.rchunks /// [`chunks_exact`]: #method.chunks_exact #[stable(feature = "rchunks", since = "1.31.0")] @@ -921,6 +922,7 @@ impl [T] { /// assert_eq!(v, &[0, 2, 2, 1, 1]); /// ``` /// + /// [`chunks_mut`]: #method.chunks_mut /// [`rchunks_mut`]: #method.rchunks_mut /// [`chunks_exact_mut`]: #method.chunks_exact_mut #[stable(feature = "rchunks", since = "1.31.0")] diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 7ede050da6c45..7aaf89cd0ff71 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -294,7 +294,7 @@ impl Seek for BufReader { /// `.into_inner()` immediately after a seek yields the underlying reader /// at the same position. /// - /// To seek without discarding the internal buffer, use [`Seek::seek_relative`]. + /// To seek without discarding the internal buffer, use [`BufReader::seek_relative`]. /// /// See [`std::io::Seek`] for more details. /// @@ -303,6 +303,9 @@ impl Seek for BufReader { /// seeks will be performed instead of one. If the second seek returns /// `Err`, the underlying reader will be left at the same position it would /// have if you called `seek` with `SeekFrom::Current(0)`. + /// + /// [`BufReader::seek_relative`]: struct.BufReader.html#method.seek_relative + /// [`std::io::Seek`]: trait.Seek.html fn seek(&mut self, pos: SeekFrom) -> io::Result { let result: u64; if let SeekFrom::Current(n) = pos { diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index d3844ebe19e4b..324852355b0d6 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -225,6 +225,9 @@ impl From for Error { /// let error = Error::from(not_found); /// assert_eq!("entity not found", format!("{}", error)); /// ``` + /// + /// [`ErrorKind`]: ../../std/io/enum.ErrorKind.html + /// [`Error`]: ../../std/io/struct.Error.html #[inline] fn from(kind: ErrorKind) -> Error { Error { diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index ead38f2112687..13de55a6a542f 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -222,6 +222,7 @@ #![no_std] #![deny(missing_docs)] +#![deny(intra_doc_link_resolution_failure)] #![deny(missing_debug_implementations)] // Tell the compiler to link to either panic_abort or panic_unwind From de39aea91cdbaecb330ff666f63d27bbe7c109a2 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Mon, 17 Dec 2018 20:21:21 -0800 Subject: [PATCH 06/36] fix tests --- src/libcore/tests/num/int_macros.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs index 577847b3c8282..8b04f84007fa7 100644 --- a/src/libcore/tests/num/int_macros.rs +++ b/src/libcore/tests/num/int_macros.rs @@ -31,8 +31,8 @@ mod tests { } #[test] - fn test_mod_euclid() { - assert!((-1 as $T).mod_euclid(MIN) == MAX); + fn test_rem_euclid() { + assert!((-1 as $T).rem_euclid(MIN) == MAX); } #[test] From 5056669fc83b256cef39927d51b67f320ab1f325 Mon Sep 17 00:00:00 2001 From: John Heitmann Date: Mon, 17 Dec 2018 23:47:56 -0800 Subject: [PATCH 07/36] Fix rustdoc-js tests Fixes rustdoc-js tests by teaching tester.js how to handle single-line js comments. Also, added speculative support for template strings, and warnings for future debuggers. --- src/tools/rustdoc-js/tester.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index f7c30df9f3ebb..65ed86742e74b 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -26,7 +26,10 @@ function getNextStep(content, pos, stop) { return pos; } -// Stupid function extractor based on indent. +// Stupid function extractor based on indent. Doesn't support block +// comments. If someone puts a ' or an " in a block comment this +// will blow up. Template strings are not tested and might also be +// broken. function extractFunction(content, functionName) { var indent = 0; var splitter = "function " + functionName + "("; @@ -51,7 +54,14 @@ function extractFunction(content, functionName) { continue; } while (pos < content.length) { - if (content[pos] === '"' || content[pos] === "'") { + // Eat single-line comments + if (content[pos] === '/' && pos > 0 && content[pos-1] === '/') { + do { + pos += 1; + } while (pos < content.length && content[pos] !== '\n'); + + // Eat quoted strings + } else if (content[pos] === '"' || content[pos] === "'" || content[pos] === "`") { var stop = content[pos]; var is_escaped = false; do { @@ -62,6 +72,8 @@ function extractFunction(content, functionName) { } } while (pos < content.length && (content[pos] !== stop || content[pos - 1] === '\\')); + + // Otherwise, check for indent } else if (content[pos] === '{') { indent += 1; } else if (content[pos] === '}') { From 50eb5f6137719a7e8fdd270e90af0d734d002c5d Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 18 Dec 2018 10:08:37 +0100 Subject: [PATCH 08/36] Explain the math --- src/librustc_mir/interpret/memory.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 65347a02be0c7..77a5f5d7b3a84 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -707,10 +707,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { new_relocations.extend( relocations .iter() - .map(|&(offset, reloc)| ( - offset + dest.offset - src.offset + (i * size), - reloc, - )) + .map(|&(offset, reloc)| { + // compute offset for current repetition + let dest_offset = dest.offset + (i * size); + ( + // shift offsets from source allocation to destination allocation + offset + dest_offset - src.offset, + reloc, + ) + }) ); } From 3d8a066fa1558134a6f40d91def67bd4366ead31 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 19 Dec 2018 00:51:37 +0100 Subject: [PATCH 09/36] Replace current crate's searchIndex when regenerating --- src/librustdoc/html/render.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c9f3aa011a1d4..fb559305fb7d4 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -964,7 +964,7 @@ themePicker.onblur = handleThemeButtonsBlur; .collect::>() .join(","))); } - all_aliases.push(format!("ALIASES['{}'] = {{{}}};", krate.name, output)); + all_aliases.push(format!("ALIASES[\"{}\"] = {{{}}};", krate.name, output)); all_aliases.sort(); try_err!(writeln!(&mut w, "var ALIASES = {{}};"), &dst); for aliases in &all_aliases { @@ -1038,7 +1038,7 @@ themePicker.onblur = handleThemeButtonsBlur; let dst = cx.dst.join("source-files.js"); let (mut all_sources, _krates) = try_err!(collect(&dst, &krate.name, "sourcesIndex"), &dst); - all_sources.push(format!("sourcesIndex['{}'] = {};", + all_sources.push(format!("sourcesIndex[\"{}\"] = {};", &krate.name, hierarchy.to_json_string())); all_sources.sort(); From 00bd306e0d060fc737d670e9aacd2789d3103785 Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 19 Dec 2018 11:32:56 +1000 Subject: [PATCH 10/36] Extend documentation for mem uninit to discuss partial allocation of the values --- src/libcore/mem.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index afd9fcb1fba84..7e4e83999c1a3 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -530,6 +530,12 @@ pub unsafe fn zeroed() -> T { /// it goes out of scope (and therefore would be dropped). Note that this /// includes a `panic` occurring and unwinding the stack suddenly. /// +/// If you partially initialize an array, you may need to use +/// [`ptr::drop_in_place`][drop_in_place] to remove the set you have created +/// followed by [`mem::forget`][mem_forget] to prevent drop running on the +/// array. If a partially allocated array is dropped this may lead to +/// undefined behaviour. +/// /// # Examples /// /// Here's how to safely initialize an array of [`Vec`]s. @@ -583,11 +589,47 @@ pub unsafe fn zeroed() -> T { /// println!("{:?}", &data[0]); /// ``` /// +/// This example shows how to handle partially allocated arrays, which could +/// be found in low-level datastructures. +/// +/// ``` +/// use std::mem; +/// use std::ptr; +/// +/// // Count the number of elements we have assigned. +/// let mut data_len: usize = 0; +/// let mut data: [String; 1000]; +/// +/// unsafe { +/// data = mem::uninitialized(); +/// +/// for elem in &mut data[0..500] { +/// ptr::write(elem, String::from("hello")); +/// data_len += 1; +/// } +/// +/// // For each item in the array, drop if we allocated it. +/// for i in &mut data[0..data_len] { +/// ptr::drop_in_place(i); +/// } +/// } +/// // Forget the data. If this is allowed to drop, you may see a crash such as: +/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object 0x7ff3b8402920: pointer being freed was not allocated' +/// mem::forget(data); +/// ``` +/// +/// An alternate strategy is to use [`mem::zeroed`][mem_zeroed] with ptr +/// comparison. This is a very error prone strategy and may only be relevant +/// for FFI. +/// /// [`Vec`]: ../../std/vec/struct.Vec.html /// [`vec!`]: ../../std/macro.vec.html /// [`Clone`]: ../../std/clone/trait.Clone.html /// [ub]: ../../reference/behavior-considered-undefined.html /// [write]: ../ptr/fn.write.html +/// [drop_in_place]: ../ptr/fn.drop_in_place.html +/// [mem_zeroed]: fn.zeroed.html +/// [mem_forget]: fn.forget.html /// [copy]: ../intrinsics/fn.copy.html /// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html /// [`Drop`]: ../ops/trait.Drop.html From 0829d0c0e480a3729dcfe4f28f5969277dc8f646 Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 19 Dec 2018 12:40:57 +1000 Subject: [PATCH 11/36] Updates based on comment --- src/libcore/mem.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 7e4e83999c1a3..7492cf4c5ed32 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -531,9 +531,9 @@ pub unsafe fn zeroed() -> T { /// includes a `panic` occurring and unwinding the stack suddenly. /// /// If you partially initialize an array, you may need to use -/// [`ptr::drop_in_place`][drop_in_place] to remove the set you have created -/// followed by [`mem::forget`][mem_forget] to prevent drop running on the -/// array. If a partially allocated array is dropped this may lead to +/// [`ptr::drop_in_place`][drop_in_place] to remove the elements you have fully +/// initialized followed by [`mem::forget`][mem_forget] to prevent drop running +/// on the array. If a partially allocated array is dropped this will lead to /// undefined behaviour. /// /// # Examples @@ -589,7 +589,7 @@ pub unsafe fn zeroed() -> T { /// println!("{:?}", &data[0]); /// ``` /// -/// This example shows how to handle partially allocated arrays, which could +/// This example shows how to handle partially initialized arrays, which could /// be found in low-level datastructures. /// /// ``` @@ -618,10 +618,6 @@ pub unsafe fn zeroed() -> T { /// mem::forget(data); /// ``` /// -/// An alternate strategy is to use [`mem::zeroed`][mem_zeroed] with ptr -/// comparison. This is a very error prone strategy and may only be relevant -/// for FFI. -/// /// [`Vec`]: ../../std/vec/struct.Vec.html /// [`vec!`]: ../../std/macro.vec.html /// [`Clone`]: ../../std/clone/trait.Clone.html From b2d8040e6f89318c0ca7f5512ca31f8311b14a36 Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 19 Dec 2018 19:09:54 +1000 Subject: [PATCH 12/36] Fix tidy error --- src/libcore/mem.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 7492cf4c5ed32..9d1f5ce403570 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -614,7 +614,8 @@ pub unsafe fn zeroed() -> T { /// } /// } /// // Forget the data. If this is allowed to drop, you may see a crash such as: -/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object 0x7ff3b8402920: pointer being freed was not allocated' +/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object +/// // 0x7ff3b8402920: pointer being freed was not allocated' /// mem::forget(data); /// ``` /// From 202904b3f7a7d2563e6808b8d8d530768c949a99 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 19 Dec 2018 10:10:39 +0100 Subject: [PATCH 13/36] make basic CTFE tracing available on release builds --- src/librustc_mir/interpret/eval_context.rs | 8 ++++---- src/librustc_mir/interpret/step.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index d36d530fe78b2..8ae0345e07a34 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -422,7 +422,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc return_to_block: StackPopCleanup, ) -> EvalResult<'tcx> { if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... - debug!("PAUSING({}) {}", self.cur_frame(), self.frame().instance); + info!("PAUSING({}) {}", self.cur_frame(), self.frame().instance); } ::log_settings::settings().indentation += 1; @@ -491,7 +491,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE - debug!("ENTERING({}) {}", self.cur_frame(), self.frame().instance); + info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance); } if self.stack.len() > self.tcx.sess.const_eval_stack_frame_limit { @@ -503,7 +503,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> { if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE - debug!("LEAVING({}) {}", self.cur_frame(), self.frame().instance); + info!("LEAVING({}) {}", self.cur_frame(), self.frame().instance); } ::log_settings::settings().indentation -= 1; let frame = self.stack.pop().expect( @@ -557,7 +557,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... - debug!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); + info!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); } Ok(()) diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index a6835e4f16738..0b3f5b2678c7f 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -81,7 +81,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx> { - debug!("{:?}", stmt); + info!("{:?}", stmt); use rustc::mir::StatementKind::*; @@ -293,7 +293,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx> { - debug!("{:?}", terminator.kind); + info!("{:?}", terminator.kind); self.tcx.span = terminator.source_info.span; self.memory.tcx.span = terminator.source_info.span; @@ -303,7 +303,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> if !self.stack.is_empty() { // This should change *something* debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb); - debug!("// {:?}", self.frame().block); + info!("// {:?}", self.frame().block); } Ok(()) } From 885cf2a2afd6da270287cfc3bfa651ac737d0378 Mon Sep 17 00:00:00 2001 From: Vardhan Thigle Date: Fri, 14 Dec 2018 18:38:15 +0530 Subject: [PATCH 14/36] Adding unwinding support for x86_64_fortanix_unknown_sgx target. --- src/libpanic_unwind/lib.rs | 2 +- .../spec/x86_64_fortanix_unknown_sgx.rs | 46 +++--- src/libstd/sys/sgx/abi/entry.S | 8 + src/libstd/sys/sgx/rwlock.rs | 137 +++++++++++++++++- src/libunwind/lib.rs | 5 +- 5 files changed, 168 insertions(+), 30 deletions(-) diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 49f8a429126b7..cfe671c626bcf 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -62,7 +62,7 @@ cfg_if! { if #[cfg(target_os = "emscripten")] { #[path = "emcc.rs"] mod imp; - } else if #[cfg(any(target_arch = "wasm32", target_env = "sgx"))] { + } else if #[cfg(target_arch = "wasm32")] { #[path = "dummy.rs"] mod imp; } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] { diff --git a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs index 5b6d8abc5ef3e..6a6aab2bea366 100644 --- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs +++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs @@ -10,28 +10,29 @@ use std::iter; -use super::{LinkerFlavor, Target, TargetOptions, PanicStrategy}; +use super::{LinkerFlavor, PanicStrategy, Target, TargetOptions}; pub fn target() -> Result { const PRE_LINK_ARGS: &[&str] = &[ "-Wl,--as-needed", "-Wl,-z,noexecstack", "-m64", - "-fuse-ld=gold", - "-nostdlib", - "-shared", - "-Wl,-e,sgx_entry", - "-Wl,-Bstatic", - "-Wl,--gc-sections", - "-Wl,-z,text", - "-Wl,-z,norelro", - "-Wl,--rosegment", - "-Wl,--no-undefined", - "-Wl,--error-unresolved-symbols", - "-Wl,--no-undefined-version", - "-Wl,-Bsymbolic", - "-Wl,--export-dynamic", + "-fuse-ld=gold", + "-nostdlib", + "-shared", + "-Wl,-e,sgx_entry", + "-Wl,-Bstatic", + "-Wl,--gc-sections", + "-Wl,-z,text", + "-Wl,-z,norelro", + "-Wl,--rosegment", + "-Wl,--no-undefined", + "-Wl,--error-unresolved-symbols", + "-Wl,--no-undefined-version", + "-Wl,-Bsymbolic", + "-Wl,--export-dynamic", ]; + const EXPORT_SYMBOLS: &[&str] = &[ "sgx_entry", "HEAP_BASE", @@ -41,19 +42,26 @@ pub fn target() -> Result { "ENCLAVE_SIZE", "CFGDATA_BASE", "DEBUG", + "EH_FRM_HDR_BASE", + "EH_FRM_HDR_SIZE", + "TEXT_BASE", + "TEXT_SIZE", ]; let opts = TargetOptions { dynamic_linking: false, executables: true, linker_is_gnu: true, max_atomic_width: Some(64), - panic_strategy: PanicStrategy::Abort, + panic_strategy: PanicStrategy::Unwind, cpu: "x86-64".into(), features: "+rdrnd,+rdseed".into(), position_independent_executables: true, - pre_link_args: iter::once( - (LinkerFlavor::Gcc, PRE_LINK_ARGS.iter().cloned().map(String::from).collect()) - ).collect(), + pre_link_args: iter::once(( + LinkerFlavor::Gcc, + PRE_LINK_ARGS.iter().cloned().map(String::from).collect(), + )) + .collect(), + post_link_objects: vec!["libunwind.a".into()], override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()), ..Default::default() }; diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S index 4d5cc02e11e2c..49ede0674ce42 100644 --- a/src/libstd/sys/sgx/abi/entry.S +++ b/src/libstd/sys/sgx/abi/entry.S @@ -56,6 +56,14 @@ IMAGE_BASE: globvar CFGDATA_BASE 8 /* Non-zero if debugging is enabled, zero otherwise */ globvar DEBUG 1 + /* The base address (relative to enclave start) of the enclave text section */ + globvar TEXT_BASE 8 + /* The size in bytes of enclacve text section */ + globvar TEXT_SIZE 8 + /* The base address (relative to enclave start) of the enclave EH_FRM_HDR section */ + globvar EH_FRM_HDR_BASE 8 + /* The size in bytes of enclacve EH_FRM_HDR section */ + globvar EH_FRM_HDR_SIZE 8 .Lreentry_panic_msg: .asciz "Re-entered panicked enclave!" diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs index a1551dbb53b2d..d1af98bd4f525 100644 --- a/src/libstd/sys/sgx/rwlock.rs +++ b/src/libstd/sys/sgx/rwlock.rs @@ -9,14 +9,25 @@ // except according to those terms. use num::NonZeroUsize; +use slice; +use str; -use super::waitqueue::{WaitVariable, WaitQueue, SpinMutex, NotifiedTcs, try_lock_or_false}; +use super::waitqueue::{ + try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable, +}; +use mem; pub struct RWLock { readers: SpinMutex>>, writer: SpinMutex>, } +// Below is to check at compile time, that RWLock has size of 128 bytes. +#[allow(dead_code)] +unsafe fn rw_lock_size_assert(r: RWLock) { + mem::transmute::(r); +} + //unsafe impl Send for RWLock {} //unsafe impl Sync for RWLock {} // FIXME @@ -24,7 +35,7 @@ impl RWLock { pub const fn new() -> RWLock { RWLock { readers: SpinMutex::new(WaitVariable::new(None)), - writer: SpinMutex::new(WaitVariable::new(false)) + writer: SpinMutex::new(WaitVariable::new(false)), } } @@ -89,9 +100,11 @@ impl RWLock { } #[inline] - pub unsafe fn read_unlock(&self) { - let mut rguard = self.readers.lock(); - let wguard = self.writer.lock(); + unsafe fn __read_unlock( + &self, + mut rguard: SpinMutexGuard>>, + wguard: SpinMutexGuard>, + ) { *rguard.lock_var_mut() = NonZeroUsize::new(rguard.lock_var().unwrap().get() - 1); if rguard.lock_var().is_some() { // There are other active readers @@ -107,9 +120,18 @@ impl RWLock { } #[inline] - pub unsafe fn write_unlock(&self) { + pub unsafe fn read_unlock(&self) { let rguard = self.readers.lock(); let wguard = self.writer.lock(); + self.__read_unlock(rguard, wguard); + } + + #[inline] + unsafe fn __write_unlock( + &self, + rguard: SpinMutexGuard>>, + wguard: SpinMutexGuard>, + ) { if let Err(mut wguard) = WaitQueue::notify_one(wguard) { // No writers waiting, release the write lock *wguard.lock_var_mut() = false; @@ -128,6 +150,109 @@ impl RWLock { } } + #[inline] + pub unsafe fn write_unlock(&self) { + let rguard = self.readers.lock(); + let wguard = self.writer.lock(); + self.__write_unlock(rguard, wguard); + } + + #[inline] + unsafe fn unlock(&self) { + let rguard = self.readers.lock(); + let wguard = self.writer.lock(); + if *wguard.lock_var() == true { + self.__write_unlock(rguard, wguard); + } else { + self.__read_unlock(rguard, wguard); + } + } + #[inline] pub unsafe fn destroy(&self) {} } + +const EINVAL: i32 = 22; + +#[no_mangle] +pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 { + if p.is_null() { + return EINVAL; + } + (*p).read(); + return 0; +} + +#[no_mangle] +pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 { + if p.is_null() { + return EINVAL; + } + (*p).write(); + return 0; +} +#[no_mangle] +pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 { + if p.is_null() { + return EINVAL; + } + (*p).unlock(); + return 0; +} + +#[no_mangle] +pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) { + if s < 0 { + return; + } + let buf = slice::from_raw_parts(m as *const u8, s as _); + if let Ok(s) = str::from_utf8(&buf[..buf.iter().position(|&b| b == 0).unwrap_or(buf.len())]) { + eprint!("{}", s); + } +} + +#[no_mangle] +pub unsafe extern "C" fn __rust_abort() { + ::sys::abort_internal(); +} + +#[cfg(test)] +mod tests { + + use super::*; + use core::array::FixedSizeArray; + use mem::MaybeUninit; + use {mem, ptr}; + + // The below test verifies that the bytes of initialized RWLock are the ones + // we use in libunwind. + // If they change we need to update src/UnwindRustSgx.h in libunwind. + #[test] + fn test_c_rwlock_initializer() { + const RWLOCK_INIT: &[u8] = &[ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ]; + + let mut init = MaybeUninit::::zeroed(); + init.set(RWLock::new()); + assert_eq!( + mem::transmute::<_, [u8; 128]>(init.into_inner()).as_slice(), + RWLOCK_INIT + ); + } +} diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs index eb53332ab3302..954eb9d6d03ba 100644 --- a/src/libunwind/lib.rs +++ b/src/libunwind/lib.rs @@ -26,10 +26,7 @@ mod macros; cfg_if! { if #[cfg(target_env = "msvc")] { // no extra unwinder support needed - } else if #[cfg(any( - all(target_arch = "wasm32", not(target_os = "emscripten")), - target_env = "sgx" - ))] { + } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] { // no unwinder on the system! } else { extern crate libc; From 81a45e20385009db9b964be3ed18801477f0a3dc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 19 Dec 2018 14:11:01 +0100 Subject: [PATCH 15/36] miri: allocation is infallible --- src/librustc_mir/const_eval.rs | 6 +++--- src/librustc_mir/interpret/machine.rs | 2 +- src/librustc_mir/interpret/memory.rs | 10 +++++----- src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/interpret/place.rs | 12 ++++++------ src/librustc_mir/interpret/traits.rs | 2 +- src/librustc_mir/transform/const_prop.rs | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 248c5d2db4917..6e0f1c8b80c32 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -187,7 +187,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( } let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?; assert!(!layout.is_unsized()); - let ret = ecx.allocate(layout, MemoryKind::Stack)?; + let ret = ecx.allocate(layout, MemoryKind::Stack); let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id())); let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p)); @@ -490,8 +490,8 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, ptr: Pointer, _kind: MemoryKind, - ) -> EvalResult<'tcx, Pointer> { - Ok(ptr) + ) -> Pointer { + ptr } #[inline(always)] diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 4c7aa887045c7..74b633d67956e 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -185,7 +185,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, ptr: Pointer, kind: MemoryKind, - ) -> EvalResult<'tcx, Pointer>; + ) -> Pointer; /// Executed when evaluating the `*` operator: Following a reference. /// This has the chance to adjust the tag. It should not change anything else! diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 420fe26426321..ddecdd44347f6 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -131,10 +131,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &mut self, alloc: Allocation, kind: MemoryKind, - ) -> EvalResult<'tcx, AllocId> { + ) -> AllocId { let id = self.tcx.alloc_map.lock().reserve(); self.alloc_map.insert(id, (kind, alloc)); - Ok(id) + id } pub fn allocate( @@ -142,9 +142,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { size: Size, align: Align, kind: MemoryKind, - ) -> EvalResult<'tcx, Pointer> { + ) -> Pointer { let extra = AllocationExtra::memory_allocated(size, &self.extra); - Ok(Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind)?)) + Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind)) } pub fn reallocate( @@ -162,7 +162,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc". // This happens so rarely, the perf advantage is outweighed by the maintenance cost. - let new_ptr = self.allocate(new_size, new_align, kind)?; + let new_ptr = self.allocate(new_size, new_align, kind); self.copy( ptr.into(), old_align, diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 83ceadada65ce..7143d66ad9246 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -382,7 +382,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> _ => { trace!("Forcing allocation for local of type {:?}", layout.ty); Operand::Indirect( - *self.allocate(layout, MemoryKind::Stack)? + *self.allocate(layout, MemoryKind::Stack) ) } }) diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index bae670bf2b4b3..e316b54f8ca7d 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -911,7 +911,7 @@ where // that might e.g., be an inner field of a struct with `Scalar` layout, // that has different alignment than the outer field. let local_layout = self.layout_of_local(&self.stack[frame], local)?; - let ptr = self.allocate(local_layout, MemoryKind::Stack)?; + let ptr = self.allocate(local_layout, MemoryKind::Stack); // We don't have to validate as we can assume the local // was already valid for its type. self.write_immediate_to_mplace_no_validate(value, ptr)?; @@ -933,15 +933,15 @@ where &mut self, layout: TyLayout<'tcx>, kind: MemoryKind, - ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + ) -> MPlaceTy<'tcx, M::PointerTag> { if layout.is_unsized() { assert!(self.tcx.features().unsized_locals, "cannot alloc memory for unsized type"); // FIXME: What should we do here? We should definitely also tag! - Ok(MPlaceTy::dangling(layout, self)) + MPlaceTy::dangling(layout, self) } else { - let ptr = self.memory.allocate(layout.size, layout.align.abi, kind)?; - let ptr = M::tag_new_allocation(self, ptr, kind)?; - Ok(MPlaceTy::from_aligned_ptr(ptr, layout)) + let ptr = self.memory.allocate(layout.size, layout.align.abi, kind); + let ptr = M::tag_new_allocation(self, ptr, kind); + MPlaceTy::from_aligned_ptr(ptr, layout) } } diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index bda585b8eda34..22936a9b0a0cf 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -54,7 +54,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ptr_size * (3 + methods.len() as u64), ptr_align, MemoryKind::Vtable, - )?.with_default_tag(); + ).with_default_tag(); let tcx = &*self.tcx; let drop = ::monomorphize::resolve_drop_in_place(*tcx, ty); diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index acae03f7f94f5..cfa899eb5a62a 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -346,7 +346,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { Rvalue::Cast(kind, ref operand, _) => { let (op, span) = self.eval_operand(operand, source_info)?; self.use_ecx(source_info, |this| { - let dest = this.ecx.allocate(place_layout, MemoryKind::Stack)?; + let dest = this.ecx.allocate(place_layout, MemoryKind::Stack); this.ecx.cast(op, kind, dest.into())?; Ok((dest.into(), span)) }) From 818ed6935dc10f450f5c230b19465b1a323b07ea Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 19 Dec 2018 16:39:01 +0100 Subject: [PATCH 16/36] dropck: simplify common patterns --- src/librustc/traits/query/dropck_outlives.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index b8bf0fcc15307..b993dd6080bb6 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -55,8 +55,8 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { let c_ty = self.infcx.canonicalize_query(&self.param_env.and(ty), &mut orig_values); let span = self.cause.span; debug!("c_ty = {:?}", c_ty); - match &gcx.dropck_outlives(c_ty) { - Ok(result) if result.is_proven() => { + if let Ok(result) = &gcx.dropck_outlives(c_ty) { + if result.is_proven() { if let Ok(InferOk { value, obligations }) = self.infcx.instantiate_query_response_and_region_obligations( self.cause, @@ -72,8 +72,6 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { }; } } - - _ => { /* fallthrough to error-handling code below */ } } // Errors and ambiuity in dropck occur in two cases: @@ -82,10 +80,11 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { // Either of these should have created an error before. tcx.sess .delay_span_bug(span, "dtorck encountered internal error"); - return InferOk { + + InferOk { value: vec![], obligations: vec![], - }; + } } } @@ -102,7 +101,7 @@ impl<'tcx> DropckOutlivesResult<'tcx> { span: Span, ty: Ty<'tcx>, ) { - for overflow_ty in self.overflows.iter().take(1) { + if let Some(overflow_ty) = self.overflows.iter().next() { let mut err = struct_span_err!( tcx.sess, span, From ae3f6b015ec3f76e2d784fe7cb23b8bbb91faa43 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 19 Dec 2018 16:41:15 +0100 Subject: [PATCH 17/36] dropck: remove unnecessary call to cloned() --- src/librustc/traits/query/dropck_outlives.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index b993dd6080bb6..f506c47371c92 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -227,7 +227,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> // (T1..Tn) and closures have same properties as T1..Tn -- // check if *any* of those are trivial. - ty::Tuple(ref tys) => tys.iter().cloned().all(|t| trivial_dropck_outlives(tcx, t)), + ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)), ty::Closure(def_id, ref substs) => substs .upvar_tys(def_id, tcx) .all(|t| trivial_dropck_outlives(tcx, t)), From 7eb67c2503eb01079f41a5d176485d9a85a9bb2d Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Wed, 19 Dec 2018 17:52:27 +0100 Subject: [PATCH 18/36] test: Ignore ui/target-feature-gate on powerpc and powerpc64(le) --- src/test/ui/target-feature-gate.rs | 3 +++ src/test/ui/target-feature-gate.stderr | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs index 4207a3285c48c..9a82f2b05325f 100644 --- a/src/test/ui/target-feature-gate.rs +++ b/src/test/ui/target-feature-gate.rs @@ -14,6 +14,9 @@ // ignore-emscripten // ignore-mips // ignore-mips64 +// ignore-powerpc +// ignore-powerpc64 +// ignore-powerpc64le // gate-test-sse4a_target_feature // gate-test-powerpc_target_feature // gate-test-avx512_target_feature diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr index 54589536010ae..d7c2eb8c5f0a7 100644 --- a/src/test/ui/target-feature-gate.stderr +++ b/src/test/ui/target-feature-gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839) - --> $DIR/target-feature-gate.rs:31:18 + --> $DIR/target-feature-gate.rs:34:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ From a153d485fe9fbd0dd4f16c0dfa29bf5d75cd63df Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Wed, 19 Dec 2018 17:53:03 +0100 Subject: [PATCH 19/36] test: Ignore ui/target-feature-gate on sparc and sparc64 --- src/test/ui/target-feature-gate.rs | 2 ++ src/test/ui/target-feature-gate.stderr | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs index 9a82f2b05325f..cb0938b861c05 100644 --- a/src/test/ui/target-feature-gate.rs +++ b/src/test/ui/target-feature-gate.rs @@ -17,6 +17,8 @@ // ignore-powerpc // ignore-powerpc64 // ignore-powerpc64le +// ignore-sparc +// ignore-sparc64 // gate-test-sse4a_target_feature // gate-test-powerpc_target_feature // gate-test-avx512_target_feature diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr index d7c2eb8c5f0a7..d7154324d12fe 100644 --- a/src/test/ui/target-feature-gate.stderr +++ b/src/test/ui/target-feature-gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839) - --> $DIR/target-feature-gate.rs:34:18 + --> $DIR/target-feature-gate.rs:36:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ From 036ce5cdc4a2cd5c0bdfaa83ed3ce64644bbdcde Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 19 Dec 2018 19:41:22 +0100 Subject: [PATCH 20/36] Fix compiletest `trim` deprecation warnings --- src/tools/compiletest/src/header.rs | 10 +++++----- src/tools/compiletest/src/runtest.rs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 8b3023e63dfb4..4e25e3a77110a 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -205,7 +205,7 @@ impl EarlyProps { fn ignore_lldb(config: &Config, line: &str) -> bool { if let Some(ref actual_version) = config.lldb_version { if line.starts_with("min-lldb-version") { - let min_version = line.trim_right() + let min_version = line.trim_end() .rsplit(' ') .next() .expect("Malformed lldb version directive"); @@ -228,7 +228,7 @@ impl EarlyProps { } if let Some(ref actual_version) = config.llvm_version { if line.starts_with("min-llvm-version") { - let min_version = line.trim_right() + let min_version = line.trim_end() .rsplit(' ') .next() .expect("Malformed llvm version directive"); @@ -236,7 +236,7 @@ impl EarlyProps { // version &actual_version[..] < min_version } else if line.starts_with("min-system-llvm-version") { - let min_version = line.trim_right() + let min_version = line.trim_end() .rsplit(' ') .next() .expect("Malformed llvm version directive"); @@ -573,14 +573,14 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut dyn FnMut(&str)) { None => false, }; if matches { - it(ln[(close_brace + 1)..].trim_left()); + it(ln[(close_brace + 1)..].trim_start()); } } else { panic!("malformed condition directive: expected `{}foo]`, found `{}`", comment_with_brace, ln) } } else if ln.starts_with(comment) { - it(ln[comment.len() ..].trim_left()); + it(ln[comment.len() ..].trim_start()); } } return; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 45527a7cce535..cddaf93b67132 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1079,7 +1079,7 @@ impl<'test> TestCx<'test> { match line { Ok(line) => { let line = if line.starts_with("//") { - line[2..].trim_left() + line[2..].trim_start() } else { line.as_str() }; @@ -2143,8 +2143,8 @@ impl<'test> TestCx<'test> { .lines() .enumerate() .filter_map(|(line_nb, line)| { - if (line.trim_left().starts_with("pub mod ") - || line.trim_left().starts_with("mod ")) + if (line.trim_start().starts_with("pub mod ") + || line.trim_start().starts_with("mod ")) && line.ends_with(';') { if let Some(ref mut other_files) = other_files { @@ -2153,7 +2153,7 @@ impl<'test> TestCx<'test> { None } else { let sline = line.split("///").last().unwrap_or(""); - let line = sline.trim_left(); + let line = sline.trim_start(); if line.starts_with("```") { if ignore { ignore = false; @@ -3284,7 +3284,7 @@ fn normalize_mir_line(line: &str) -> String { fn nocomment_mir_line(line: &str) -> &str { if let Some(idx) = line.find("//") { let (l, _) = line.split_at(idx); - l.trim_right() + l.trim_end() } else { line } From 90726e1ac17a91d07ca5749ade718239f439d1bd Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Wed, 19 Dec 2018 13:51:52 -0500 Subject: [PATCH 21/36] suggest similar lint names for unknown lints --- src/librustc/lint/context.rs | 30 ++++++++++++++----- src/librustc/lint/levels.rs | 27 +++++++---------- src/test/ui/lint/lint-unknown-lint-cmdline.rs | 7 +++-- .../ui/lint/lint-unknown-lint-cmdline.stderr | 7 ++++- src/test/ui/lint/lint-unknown-lint.rs | 12 ++++++-- src/test/ui/lint/lint-unknown-lint.stderr | 29 ++++++++---------- src/test/ui/lint/not_found.stderr | 4 +-- 7 files changed, 69 insertions(+), 47 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 449f8e0a2db67..131dedb988832 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -42,11 +42,12 @@ use util::nodemap::FxHashMap; use std::default::Default as StdDefault; use syntax::ast; use syntax::edition; -use syntax_pos::{MultiSpan, Span, symbol::LocalInternedString}; +use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}}; use errors::DiagnosticBuilder; use hir; use hir::def_id::LOCAL_CRATE; use hir::intravisit as hir_visit; +use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit as ast_visit; /// Information about the registered lints. @@ -139,8 +140,8 @@ struct LintGroup { pub enum CheckLintNameResult<'a> { Ok(&'a [LintId]), - /// Lint doesn't exist - NoLint, + /// Lint doesn't exist. Potentially contains a suggestion for a correct lint name. + NoLint(Option), /// The lint is either renamed or removed. This is the warning /// message, and an optional new name (`None` if removed). Warning(String, Option), @@ -359,8 +360,14 @@ impl LintStore { CheckLintNameResult::Warning(ref msg, _) => { Some(sess.struct_warn(msg)) }, - CheckLintNameResult::NoLint => { - Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name)) + CheckLintNameResult::NoLint(suggestion) => { + let mut err = struct_err!(sess, E0602, "unknown lint: `{}`", lint_name); + + if let Some(suggestion) = suggestion { + err.help(&format!("did you mean: `{}`", suggestion)); + } + + Some(err) } CheckLintNameResult::Tool(result) => match result { Err((Some(_), new_name)) => Some(sess.struct_warn(&format!( @@ -464,7 +471,16 @@ impl LintStore { match self.by_name.get(&complete_name) { None => match self.lint_groups.get(&*complete_name) { // Now we are sure, that this lint exists nowhere - None => CheckLintNameResult::NoLint, + None => { + let symbols = self.by_name.keys() + .map(|name| Symbol::intern(&name)) + .collect::>(); + + let suggestion = + find_best_match_for_name(symbols.iter(), &lint_name.to_lowercase(), None); + + CheckLintNameResult::NoLint(suggestion) + } Some(LintGroup { lint_ids, depr, .. }) => { // Reaching this would be weird, but let's cover this case anyway if let Some(LintAlias { name, silent }) = depr { @@ -484,7 +500,7 @@ impl LintStore { Some(&Id(ref id)) => { CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name))) } - _ => CheckLintNameResult::NoLint, + _ => CheckLintNameResult::NoLint(None), } } } diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 06e3e0bab4f10..9ab8e89df72e6 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -385,7 +385,7 @@ impl<'a> LintLevelsBuilder<'a> { } err.emit(); } - CheckLintNameResult::NoLint => { + CheckLintNameResult::NoLint(suggestion) => { let lint = builtin::UNKNOWN_LINTS; let (level, src) = self.sets.get_lint_level(lint, self.cur, @@ -398,22 +398,17 @@ impl<'a> LintLevelsBuilder<'a> { src, Some(li.span.into()), &msg); - if name.as_str().chars().any(|c| c.is_uppercase()) { - let name_lower = name.as_str().to_lowercase().to_string(); - if let CheckLintNameResult::NoLint = - store.check_lint_name(&name_lower, tool_name) { - db.emit(); - } else { - db.span_suggestion_with_applicability( - li.span, - "lowercase the lint name", - name_lower, - Applicability::MachineApplicable - ).emit(); - } - } else { - db.emit(); + + if let Some(suggestion) = suggestion { + db.span_suggestion_with_applicability( + li.span, + "did you mean", + suggestion.to_string(), + Applicability::MachineApplicable, + ); } + + db.emit(); } } } diff --git a/src/test/ui/lint/lint-unknown-lint-cmdline.rs b/src/test/ui/lint/lint-unknown-lint-cmdline.rs index 0c41959f8a710..33fb46dce6e38 100644 --- a/src/test/ui/lint/lint-unknown-lint-cmdline.rs +++ b/src/test/ui/lint/lint-unknown-lint-cmdline.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-D bogus +// compile-flags:-D bogus -D dead_cod -// error-pattern:unknown lint +// error-pattern:unknown lint: `bogus` // error-pattern:requested on the command line with `-D bogus` +// error-pattern:unknown lint: `dead_cod` +// error-pattern:requested on the command line with `-D dead_cod` +// error-pattern:did you mean: `dead_code` fn main() { } diff --git a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr index 8636004102618..58fdae3333ca1 100644 --- a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr +++ b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr @@ -2,6 +2,11 @@ error[E0602]: unknown lint: `bogus` | = note: requested on the command line with `-D bogus` -error: aborting due to previous error +error[E0602]: unknown lint: `dead_cod` + | + = help: did you mean: `dead_code` + = note: requested on the command line with `-D dead_cod` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0602`. diff --git a/src/test/ui/lint/lint-unknown-lint.rs b/src/test/ui/lint/lint-unknown-lint.rs index 2de8d849d1915..5d3fd0f19721f 100644 --- a/src/test/ui/lint/lint-unknown-lint.rs +++ b/src/test/ui/lint/lint-unknown-lint.rs @@ -8,6 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(not_a_real_lint)] //~ WARN unknown lint -#![deny(unused)] -fn main() { let unused = (); } //~ ERROR unused variable +#![deny(unknown_lints)] + +#![allow(not_a_real_lint)] //~ ERROR unknown lint + +#![deny(dead_cod)] //~ ERROR unknown lint + //~| HELP did you mean + //~| SUGGESTION dead_code + +fn main() {} diff --git a/src/test/ui/lint/lint-unknown-lint.stderr b/src/test/ui/lint/lint-unknown-lint.stderr index b398a2f3690fb..6fc2da39a7c60 100644 --- a/src/test/ui/lint/lint-unknown-lint.stderr +++ b/src/test/ui/lint/lint-unknown-lint.stderr @@ -1,23 +1,20 @@ -warning: unknown lint: `not_a_real_lint` - --> $DIR/lint-unknown-lint.rs:11:10 +error: unknown lint: `not_a_real_lint` + --> $DIR/lint-unknown-lint.rs:13:10 | -LL | #![allow(not_a_real_lint)] //~ WARN unknown lint +LL | #![allow(not_a_real_lint)] //~ ERROR unknown lint | ^^^^^^^^^^^^^^^ | - = note: #[warn(unknown_lints)] on by default - -error: unused variable: `unused` - --> $DIR/lint-unknown-lint.rs:13:17 - | -LL | fn main() { let unused = (); } //~ ERROR unused variable - | ^^^^^^ help: consider using `_unused` instead - | note: lint level defined here - --> $DIR/lint-unknown-lint.rs:12:9 + --> $DIR/lint-unknown-lint.rs:11:9 + | +LL | #![deny(unknown_lints)] + | ^^^^^^^^^^^^^ + +error: unknown lint: `dead_cod` + --> $DIR/lint-unknown-lint.rs:15:9 | -LL | #![deny(unused)] - | ^^^^^^ - = note: #[deny(unused_variables)] implied by #[deny(unused)] +LL | #![deny(dead_cod)] //~ ERROR unknown lint + | ^^^^^^^^ help: did you mean: `dead_code` -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/not_found.stderr b/src/test/ui/lint/not_found.stderr index 603b5410444cd..dedbc829913a5 100644 --- a/src/test/ui/lint/not_found.stderr +++ b/src/test/ui/lint/not_found.stderr @@ -10,11 +10,11 @@ warning: unknown lint: `DEAD_CODE` --> $DIR/not_found.rs:18:8 | LL | #[warn(DEAD_CODE)] - | ^^^^^^^^^ help: lowercase the lint name: `dead_code` + | ^^^^^^^^^ help: did you mean: `dead_code` warning: unknown lint: `Warnings` --> $DIR/not_found.rs:20:8 | LL | #[deny(Warnings)] - | ^^^^^^^^ help: lowercase the lint name: `warnings` + | ^^^^^^^^ help: did you mean: `warnings` From 7b6cf6e87b5d0d54687dd56a803d3a86f1994182 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 19 Dec 2018 22:00:25 -0800 Subject: [PATCH 22/36] Stabilize Vec(Deque)::resize_with Closes #41758 --- src/liballoc/collections/vec_deque.rs | 4 +--- src/liballoc/vec.rs | 4 +--- src/librustc_data_structures/lib.rs | 1 - 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 0c5926fbaf1dc..99b1ad8d6e297 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1897,8 +1897,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(vec_resize_with)] - /// /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -1917,7 +1915,7 @@ impl VecDeque { /// buf.resize_with(5, || { state += 1; state }); /// assert_eq!(buf, [5, 10, 101, 102, 103]); /// ``` - #[unstable(feature = "vec_resize_with", issue = "41758")] + #[stable(feature = "vec_resize_with", since = "1.33.0")] pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut()->T) { let len = self.len(); diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 63af69dda1dce..b78e71331a97f 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1241,8 +1241,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(vec_resize_with)] - /// /// let mut vec = vec![1, 2, 3]; /// vec.resize_with(5, Default::default); /// assert_eq!(vec, [1, 2, 3, 0, 0]); @@ -1255,7 +1253,7 @@ impl Vec { /// /// [`resize`]: #method.resize /// [`Clone`]: ../../std/clone/trait.Clone.html - #[unstable(feature = "vec_resize_with", issue = "41758")] + #[stable(feature = "vec_resize_with", since = "1.33.0")] pub fn resize_with(&mut self, new_len: usize, f: F) where F: FnMut() -> T { diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index bc2b8f1d6523e..9e29b2798d860 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -28,7 +28,6 @@ #![feature(optin_builtin_traits)] #![feature(nll)] #![feature(allow_internal_unstable)] -#![feature(vec_resize_with)] #![feature(hash_raw_entry)] #![feature(stmt_expr_attributes)] #![feature(core_intrinsics)] From fb18ddaaaa8eeec29bf6fc8684cfceccaa09e064 Mon Sep 17 00:00:00 2001 From: Clar Fon Date: Thu, 13 Dec 2018 23:26:09 -0500 Subject: [PATCH 23/36] Add DoubleEndedIterator::nth_back --- src/libcore/iter/mod.rs | 6 +++ src/libcore/iter/traits.rs | 79 +++++++++++++++++++++++++++++++++++--- src/libcore/tests/iter.rs | 27 +++++++++++++ src/libcore/tests/lib.rs | 1 + 4 files changed, 107 insertions(+), 6 deletions(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index aa23d49672a0b..e493a3804376f 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -429,6 +429,9 @@ impl Iterator for Rev where I: DoubleEndedIterator { #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] + fn nth(&mut self, n: usize) -> Option<::Item> { self.iter.nth_back(n) } + fn try_fold(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { @@ -461,6 +464,9 @@ impl DoubleEndedIterator for Rev where I: DoubleEndedIterator { #[inline] fn next_back(&mut self) -> Option<::Item> { self.iter.next() } + #[inline] + fn nth_back(&mut self, n: usize) -> Option<::Item> { self.iter.nth(n) } + fn try_rfold(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 45e5b614db3e0..727a60e359694 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -427,6 +427,62 @@ pub trait DoubleEndedIterator: Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn next_back(&mut self) -> Option; + /// Returns the `n`th element from the end of the iterator. + /// + /// This is essentially the reversed version of [`nth`]. Although like most indexing + /// operations, the count starts from zero, so `nth_back(0)` returns the first value fro + /// the end, `nth_back(1)` the second, and so on. + /// + /// Note that all elements between the end and the returned element will be + /// consumed, including the returned element. This also means that calling + /// `nth_back(0)` multiple times on the same iterator will return different + /// elements. + /// + /// `nth_back()` will return [`None`] if `n` is greater than or equal to the length of the + /// iterator. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`nth`]: ../../std/iter/trait.Iterator.html#method.nth + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_nth_back)] + /// let a = [1, 2, 3]; + /// assert_eq!(a.iter().nth_back(2), Some(&1)); + /// ``` + /// + /// Calling `nth_back()` multiple times doesn't rewind the iterator: + /// + /// ``` + /// #![feature(iter_nth_back)] + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.nth_back(1), Some(&2)); + /// assert_eq!(iter.nth_back(1), None); + /// ``` + /// + /// Returning `None` if there are less than `n + 1` elements: + /// + /// ``` + /// #![feature(iter_nth_back)] + /// let a = [1, 2, 3]; + /// assert_eq!(a.iter().nth_back(10), None); + /// ``` + #[inline] + #[unstable(feature = "iter_nth_back", issue = "56995")] + fn nth_back(&mut self, mut n: usize) -> Option { + for x in self.rev() { + if n == 0 { return Some(x) } + n -= 1; + } + None + } + /// This is the reverse version of [`try_fold()`]: it takes elements /// starting from the back of the iterator. /// @@ -461,8 +517,11 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] - fn try_rfold(&mut self, init: B, mut f: F) -> R where - Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try + fn try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try { let mut accum = init; while let Some(x) = self.next_back() { @@ -524,8 +583,10 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_rfold", since = "1.27.0")] - fn rfold(mut self, accum: B, mut f: F) -> B where - Self: Sized, F: FnMut(B, Self::Item) -> B, + fn rfold(mut self, accum: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, { self.try_rfold(accum, move |acc, x| Ok::(f(acc, x))).unwrap() } @@ -574,7 +635,8 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_rfind", since = "1.27.0")] - fn rfind

(&mut self, mut predicate: P) -> Option where + fn rfind

(&mut self, mut predicate: P) -> Option + where Self: Sized, P: FnMut(&Self::Item) -> bool { @@ -587,7 +649,12 @@ pub trait DoubleEndedIterator: Iterator { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I { - fn next_back(&mut self) -> Option { (**self).next_back() } + fn next_back(&mut self) -> Option { + (**self).next_back() + } + fn nth_back(&mut self, n: usize) -> Option { + (**self).nth_back(n) + } } /// An iterator that knows its exact length. diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 00b4aa4fa2d7a..b5633333d0170 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1016,6 +1016,33 @@ fn test_iterator_nth() { assert_eq!(v.iter().nth(v.len()), None); } +#[test] +fn test_iterator_nth_back() { + let v: &[_] = &[0, 1, 2, 3, 4]; + for i in 0..v.len() { + assert_eq!(v.iter().nth_back(i).unwrap(), &v[v.len() - 1 - i]); + } + assert_eq!(v.iter().nth_back(v.len()), None); +} + +#[test] +fn test_iterator_rev_nth_back() { + let v: &[_] = &[0, 1, 2, 3, 4]; + for i in 0..v.len() { + assert_eq!(v.iter().rev().nth_back(i).unwrap(), &v[i]); + } + assert_eq!(v.iter().rev().nth_back(v.len()), None); +} + +#[test] +fn test_iterator_rev_nth() { + let v: &[_] = &[0, 1, 2, 3, 4]; + for i in 0..v.len() { + assert_eq!(v.iter().rev().nth(i).unwrap(), &v[v.len() - 1 - i]); + } + assert_eq!(v.iter().rev().nth(v.len()), None); +} + #[test] fn test_iterator_last() { let v: &[_] = &[0, 1, 2, 3, 4]; diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 7d62b4fa90f20..2377a4733678d 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -19,6 +19,7 @@ #![feature(flt2dec)] #![feature(fmt_internals)] #![feature(hashmap_internals)] +#![feature(iter_nth_back)] #![feature(iter_unfold)] #![feature(pattern)] #![feature(range_is_empty)] From 66bb34c3ab254d19623315d9d71695c3acb4e826 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 20 Dec 2018 01:34:31 -0800 Subject: [PATCH 24/36] Update src/libcore/num/mod.rs Co-Authored-By: ubsan --- src/libcore/num/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index cedee1c8e5f99..cd8adfdd1fd26 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1781,7 +1781,7 @@ assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 doc_comment! { concat!("Calculates the least nonnegative remainder of `self (mod rhs)`. -This is done as if by the euclidean division algorithm. +This is done as if by the Euclidean division algorithm. # Panics From 455bc95317ddb3f8d528d0220bfde7f7a7286463 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Thu, 20 Dec 2018 01:37:20 -0800 Subject: [PATCH 25/36] fix nits --- src/libcore/num/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index cd8adfdd1fd26..7ffb81901c619 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1740,7 +1740,7 @@ $EndFeature, " concat!("Calculates the quotient of Euclidean division of `self` by `rhs`. This computes the integer `n` such that `self = n * rhs + self.rem_euclid(rhs)`, -with the `0 <= self.rem_euclid(rhs) < rhs`. +with `0 <= self.rem_euclid(rhs) < rhs`. In other words, the result is `self / rhs` rounded to the integer `n` such that `self >= n * rhs`. @@ -1781,7 +1781,9 @@ assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 doc_comment! { concat!("Calculates the least nonnegative remainder of `self (mod rhs)`. -This is done as if by the Euclidean division algorithm. +This is done as if by the Euclidean division algorithm -- given +`r = self.rem_euclid(rhs)`, `self = rhs * self.div_euclid(rhs) + r`, and +`0 <= r < abs(rhs)`. # Panics From 0b0a00cc0551b7f525515e4e53bc0a11bd1b2ebd Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Thu, 20 Dec 2018 10:18:45 -0600 Subject: [PATCH 26/36] new --static-root-path flag for controlling static file locations --- src/doc/rustdoc/src/unstable-features.md | 15 +++++++++ src/librustdoc/config.rs | 5 +++ src/librustdoc/html/layout.rs | 39 +++++++++++++++--------- src/librustdoc/html/render.rs | 9 ++++++ src/librustdoc/lib.rs | 8 +++++ src/test/rustdoc/static-root-path.rs | 18 +++++++++++ 6 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 src/test/rustdoc/static-root-path.rs diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 43cdab27e9dae..905b06465340a 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -402,3 +402,18 @@ Using `index-page` option enables `enable-index-page` option as well. ### `--enable-index-page`: generate a default index page for docs This feature allows the generation of a default index-page which lists the generated crates. + +### `--static-root-path`: control how static files are loaded in HTML output + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --static-root-path '/cache/' +``` + +This flag controls how rustdoc links to its static files on HTML pages. If you're hosting a lot of +crates' docs generated by the same version of rustdoc, you can use this flag to cache rustdoc's CSS, +JavaScript, and font files in a single location, rather than duplicating it once per "doc root" +(grouping of crate docs generated into the same output directory, like with `cargo doc`). Per-crate +files like the search index will still load from the documentation root, but anything that gets +renamed with `--resource-suffix` will load from the given path. diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index b421f07ddafa2..f9a46fe362e3c 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -181,6 +181,9 @@ pub struct RenderOptions { /// A file to use as the index page at the root of the output directory. Overrides /// `enable_index_page` to be true if set. pub index_page: Option, + /// An optional path to use as the location of static files. If not set, uses combinations of + /// `../` to reach the documentation root. + pub static_root_path: Option, // Options specific to reading standalone Markdown files @@ -433,6 +436,7 @@ impl Options { let markdown_playground_url = matches.opt_str("markdown-playground-url"); let crate_version = matches.opt_str("crate-version"); let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some(); + let static_root_path = matches.opt_str("static-root-path"); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); @@ -471,6 +475,7 @@ impl Options { enable_minification, enable_index_page, index_page, + static_root_path, markdown_no_toc, markdown_css, markdown_playground_url, diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 37ff693bdf167..1ead428ff498c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -26,6 +26,7 @@ pub struct Page<'a> { pub title: &'a str, pub css_class: &'a str, pub root_path: &'a str, + pub static_root_path: Option<&'a str>, pub description: &'a str, pub keywords: &'a str, pub resource_suffix: &'a str, @@ -36,6 +37,7 @@ pub fn render( css_file_extension: bool, themes: &[PathBuf], extra_scripts: &[&str]) -> io::Result<()> { + let static_root_path = page.static_root_path.unwrap_or(page.root_path); write!(dst, "\ \ @@ -46,20 +48,20 @@ pub fn render( \ \ {title}\ - \ - \ + \ {themes}\ - \ - \ + \ - \ - \ + \ + \ {css_extension}\ {favicon}\ {in_header}\ \ \ \ @@ -77,11 +79,13 @@ pub fn render( \

\ \
\
\ - \ + \