From 69b2179afe695d1a93b792cfd7c4197ca63ce658 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 3 May 2020 20:47:51 +0300 Subject: [PATCH 1/8] Print accessed env vars as special comments into depinfo files --- src/librustc_builtin_macros/env.rs | 18 ++++++++----- src/librustc_builtin_macros/lib.rs | 1 + src/librustc_interface/passes.rs | 35 +++++++++++++++++++++++++ src/librustc_session/parse.rs | 3 +++ src/test/run-make/env-dep-info/Makefile | 8 ++++++ src/test/run-make/env-dep-info/main.rs | 6 +++++ 6 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 src/test/run-make/env-dep-info/Makefile create mode 100644 src/test/run-make/env-dep-info/main.rs diff --git a/src/librustc_builtin_macros/env.rs b/src/librustc_builtin_macros/env.rs index d769ebb1f5520..6c3a1ce0958ec 100644 --- a/src/librustc_builtin_macros/env.rs +++ b/src/librustc_builtin_macros/env.rs @@ -22,8 +22,10 @@ pub fn expand_option_env<'cx>( }; let sp = cx.with_def_site_ctxt(sp); - let e = match env::var(&var.as_str()) { - Err(..) => { + let value = env::var(&var.as_str()).ok().as_deref().map(Symbol::intern); + cx.parse_sess.env_depinfo.borrow_mut().insert((Symbol::intern(&var), value)); + let e = match value { + None => { let lt = cx.lifetime(sp, Ident::new(kw::StaticLifetime, sp)); cx.expr_path(cx.path_all( sp, @@ -37,10 +39,10 @@ pub fn expand_option_env<'cx>( ))], )) } - Ok(s) => cx.expr_call_global( + Some(value) => cx.expr_call_global( sp, cx.std_path(&[sym::option, sym::Option, sym::Some]), - vec![cx.expr_str(sp, Symbol::intern(&s))], + vec![cx.expr_str(sp, value)], ), }; MacEager::expr(e) @@ -78,12 +80,14 @@ pub fn expand_env<'cx>( } let sp = cx.with_def_site_ctxt(sp); - let e = match env::var(&*var.as_str()) { - Err(_) => { + let value = env::var(&*var.as_str()).ok().as_deref().map(Symbol::intern); + cx.parse_sess.env_depinfo.borrow_mut().insert((var, value)); + let e = match value { + None => { cx.span_err(sp, &msg.as_str()); return DummyResult::any(sp); } - Ok(s) => cx.expr_str(sp, Symbol::intern(&s)), + Some(value) => cx.expr_str(sp, value), }; MacEager::expr(e) } diff --git a/src/librustc_builtin_macros/lib.rs b/src/librustc_builtin_macros/lib.rs index a0f82d65618f4..f56d8a372a73e 100644 --- a/src/librustc_builtin_macros/lib.rs +++ b/src/librustc_builtin_macros/lib.rs @@ -5,6 +5,7 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] +#![feature(inner_deref)] #![feature(nll)] #![feature(or_patterns)] #![feature(proc_macro_internals)] diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index c06fd91133b5c..5af0ba2afb977 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -540,6 +540,22 @@ fn escape_dep_filename(filename: &FileName) -> String { filename.to_string().replace(" ", "\\ ") } +// Makefile comments only need escaping newlines and `\`. +// The result can be unescaped by anything that can unescape `escape_default` and friends. +fn escape_dep_env(symbol: Symbol) -> String { + let s = symbol.as_str(); + let mut escaped = String::with_capacity(s.len()); + for c in s.chars() { + match c { + '\n' => escaped.push_str(r"\n"), + '\r' => escaped.push_str(r"\r"), + '\\' => escaped.push_str(r"\\"), + _ => escaped.push(c), + } + } + escaped +} + fn write_out_deps( sess: &Session, boxed_resolver: &Steal>>, @@ -592,6 +608,25 @@ fn write_out_deps( for path in files { writeln!(file, "{}:", path)?; } + + // Emit special comments with information about accessed environment variables. + let env_depinfo = sess.parse_sess.env_depinfo.borrow(); + if !env_depinfo.is_empty() { + let mut envs: Vec<_> = env_depinfo + .iter() + .map(|(k, v)| (escape_dep_env(*k), v.map(escape_dep_env))) + .collect(); + envs.sort_unstable(); + writeln!(file)?; + for (k, v) in envs { + write!(file, "# env-dep:{}", k)?; + if let Some(v) = v { + write!(file, "={}", v)?; + } + writeln!(file)?; + } + } + Ok(()) })(); diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs index 233761dbed7de..aaae5889117ed 100644 --- a/src/librustc_session/parse.rs +++ b/src/librustc_session/parse.rs @@ -135,6 +135,8 @@ pub struct ParseSess { pub symbol_gallery: SymbolGallery, /// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors. pub reached_eof: Lock, + /// Environment variables accessed during the build and their values when they exist. + pub env_depinfo: Lock)>>, } impl ParseSess { @@ -160,6 +162,7 @@ impl ParseSess { gated_spans: GatedSpans::default(), symbol_gallery: SymbolGallery::default(), reached_eof: Lock::new(false), + env_depinfo: Default::default(), } } diff --git a/src/test/run-make/env-dep-info/Makefile b/src/test/run-make/env-dep-info/Makefile new file mode 100644 index 0000000000000..2be0b4b324b08 --- /dev/null +++ b/src/test/run-make/env-dep-info/Makefile @@ -0,0 +1,8 @@ +-include ../../run-make-fulldeps/tools.mk + +all: + EXISTING_ENV=1 EXISTING_OPT_ENV=1 $(RUSTC) --emit dep-info main.rs + $(CGREP) "# env-dep:EXISTING_ENV=1" < $(TMPDIR)/main.d + $(CGREP) "# env-dep:EXISTING_OPT_ENV=1" < $(TMPDIR)/main.d + $(CGREP) "# env-dep:NONEXISTENT_OPT_ENV" < $(TMPDIR)/main.d + $(CGREP) "# env-dep:ESCAPE\nESCAPE\\" < $(TMPDIR)/main.d diff --git a/src/test/run-make/env-dep-info/main.rs b/src/test/run-make/env-dep-info/main.rs new file mode 100644 index 0000000000000..a25246bac792c --- /dev/null +++ b/src/test/run-make/env-dep-info/main.rs @@ -0,0 +1,6 @@ +fn main() { + env!("EXISTING_ENV"); + option_env!("EXISTING_OPT_ENV"); + option_env!("NONEXISTENT_OPT_ENV"); + option_env!("ESCAPE\nESCAPE\\"); +} From 560a99603d36416969778c1d7402bbecf3e326e2 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Tue, 16 Jun 2020 16:07:49 +0000 Subject: [PATCH 2/8] Implement slice_strip feature --- src/libcore/slice/mod.rs | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 21ba2b5abcfb6..40be2bcc8eefa 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1459,6 +1459,86 @@ impl [T] { m >= n && needle == &self[m - n..] } + /// Returns a subslice with the prefix removed. + /// + /// Returns [`None`] if slice does not start with `prefix`. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_strip)] + /// let v = [10, 40, 30]; + /// assert_eq!(v.strip_prefix(&[10]), Some(&[40, 30])); + /// assert_eq!(v.strip_prefix(&[10, 40]), Some(&[30])); + /// assert_eq!(v.strip_prefix(&[50]), None); + /// assert_eq!(v.strip_prefix(&[10, 50]), None); + /// ``` + /// + /// This method returns the original slice if `prefix` is an empty slice: + /// + /// ``` + /// #![feature(slice_strip)] + /// let v = &[10, 40, 30]; + /// assert_eq!(v.strip_prefix(&[]), Some(v)); + /// let v: &[u8] = &[]; + /// assert_eq!(v.strip_prefix(&[]), Some(v)); + /// ``` + #[must_use = "returns the subslice without modifying the original"] + #[unstable(feature = "slice_strip", issue = "73413")] + pub fn strip_prefix(&self, prefix: &[T]) -> Option<&[T]> + where + T: PartialEq, + { + let n = prefix.len(); + if n <= self.len() { + let (head, tail) = self.split_at(n); + if head == prefix { + return Some(tail); + } + } + None + } + + /// Returns a subslice with the suffix removed. + /// + /// Returns [`None`] if slice does not end with `suffix`. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_strip)] + /// let v = [10, 40, 30]; + /// assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40])); + /// assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10])); + /// assert_eq!(v.strip_suffix(&[50]), None); + /// assert_eq!(v.strip_suffix(&[50, 30]), None); + /// ``` + /// + /// This method returns the original slice if `suffix` is an empty slice: + /// + /// ``` + /// #![feature(slice_strip)] + /// let v = &[10, 40, 30]; + /// assert_eq!(v.strip_suffix(&[]), Some(v)); + /// let v: &[u8] = &[]; + /// assert_eq!(v.strip_suffix(&[]), Some(v)); + /// ``` + #[must_use = "returns the subslice without modifying the original"] + #[unstable(feature = "slice_strip", issue = "73413")] + pub fn strip_suffix(&self, suffix: &[T]) -> Option<&[T]> + where + T: PartialEq, + { + let (len, n) = (self.len(), suffix.len()); + if n <= len { + let (head, tail) = self.split_at(len - n); + if tail == suffix { + return Some(head); + } + } + None + } + /// Binary searches this sorted slice for a given element. /// /// If the value is found then [`Result::Ok`] is returned, containing the From 3c46e36d39cc0f833075e59936cf96a60f6348e4 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Mon, 22 Jun 2020 16:27:23 +0200 Subject: [PATCH 3/8] Document the mut keyword --- src/libstd/keyword_docs.rs | 45 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index a4996d9eee810..7d54f9ed2d20f 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -967,9 +967,50 @@ mod move_keyword {} // /// A mutable binding, reference, or pointer. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// `mut` can be used in several situations. The first is mutable bindings, +/// which can be used anywhere you can bind a value to a variable name. Some +/// examples: /// -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 +/// ``` +/// // A mutable binding in the parameter list of a function. +/// fn foo(mut x: u8, y: u8) -> u8 { +/// x += y; +/// x +/// } +/// +/// // A mutable binding for a variable. +/// let mut a = 5; +/// a = 6; +/// +/// assert_eq!(foo(3, 4), 7); +/// assert_eq!(a, 6); +/// ``` +/// +/// The second is references. They can be created from `mut` bindings and must +/// be unique: no other binding can have a mutable reference, nor a simple +/// reference. +/// +/// ``` +/// // Taking a mutable reference. +/// fn push_two(v: &mut Vec) { +/// v.push(2); +/// } +/// +/// // You cannot take a mutable reference to a non-mutable variable. +/// let mut v = vec![0, 1]; +/// // Passing a mutable reference. +/// push_two(&mut v); +/// +/// assert_eq!(v, vec![0, 1, 2]); +/// ``` +/// +/// Mutable pointers work much like mutable references, with the added +/// possibility of being nul. The syntax is `*mut Type`. +/// +/// You can find more information on mutable references and pointers in the +/// [Reference]. +/// +/// [Reference]: ../reference/types/pointer.html#mutable-references-mut mod mut_keyword {} #[doc(keyword = "pub")] From 9bb414faffbb5e31ecc41edb78e0047b0b8b1221 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 23 Jun 2020 16:25:01 -0700 Subject: [PATCH 4/8] Fix ptr doc warnings. --- src/libcore/ptr/const_ptr.rs | 2 -- src/libcore/ptr/mut_ptr.rs | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index 395b3879cfd0c..64a506a6377f2 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -316,7 +316,6 @@ impl *const T { /// differently have not been explored. This method should not be used to introduce such /// differences, and it should also not be stabilized before we have a better understanding /// of this issue. - /// ``` #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[inline] @@ -349,7 +348,6 @@ impl *const T { /// differently have not been explored. This method should not be used to introduce such /// differences, and it should also not be stabilized before we have a better understanding /// of this issue. - /// ``` #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[inline] diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index b86ef5b13b353..6b5cd9fdb854d 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -294,7 +294,6 @@ impl *mut T { /// differently have not been explored. This method should not be used to introduce such /// differences, and it should also not be stabilized before we have a better understanding /// of this issue. - /// ``` #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[inline] @@ -327,7 +326,6 @@ impl *mut T { /// differently have not been explored. This method should not be used to introduce such /// differences, and it should also not be stabilized before we have a better understanding /// of this issue. - /// ``` #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[inline] From 65becefd4ac378c9c6aa0e7becb7eaa1fc12b84f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 24 Jun 2020 13:19:06 +0200 Subject: [PATCH 5/8] Clean up E0701 explanation --- src/librustc_error_codes/error_codes/E0701.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0701.md b/src/librustc_error_codes/error_codes/E0701.md index 87f416ada1803..4965e64310591 100644 --- a/src/librustc_error_codes/error_codes/E0701.md +++ b/src/librustc_error_codes/error_codes/E0701.md @@ -1,7 +1,7 @@ This error indicates that a `#[non_exhaustive]` attribute was incorrectly placed on something other than a struct or enum. -Examples of erroneous code: +Erroneous code example: ```compile_fail,E0701 #[non_exhaustive] From 2735f43cef6b00ac4ca2d59f07830a25513031a9 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Wed, 24 Jun 2020 23:34:19 +0200 Subject: [PATCH 6/8] Fix links in `SliceIndex` documentation --- src/libcore/slice/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index c69aafe687cf8..57bacdd99eff4 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -2817,6 +2817,7 @@ pub trait SliceIndex: private_slice_index::Sealed { /// performing any bounds checking. /// Calling this method with an out-of-bounds index is *[undefined behavior]* /// even if the resulting reference is not used. + /// /// [undefined behavior]: ../../reference/behavior-considered-undefined.html #[unstable(feature = "slice_index_methods", issue = "none")] unsafe fn get_unchecked(self, slice: &T) -> &Self::Output; @@ -2825,6 +2826,7 @@ pub trait SliceIndex: private_slice_index::Sealed { /// performing any bounds checking. /// Calling this method with an out-of-bounds index is *[undefined behavior]* /// even if the resulting reference is not used. + /// /// [undefined behavior]: ../../reference/behavior-considered-undefined.html #[unstable(feature = "slice_index_methods", issue = "none")] unsafe fn get_unchecked_mut(self, slice: &mut T) -> &mut Self::Output; From 3d09017477e562d44cb90fca1a4a38c75f664f2d Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Thu, 25 Jun 2020 10:05:30 +0200 Subject: [PATCH 7/8] Add a compile fail example, binding -> variable, apply suggestions --- src/libstd/keyword_docs.rs | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 7d54f9ed2d20f..32fa0da3e2925 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -965,20 +965,21 @@ mod move_keyword {} #[doc(keyword = "mut")] // -/// A mutable binding, reference, or pointer. +/// A mutable variable, reference, or pointer. /// -/// `mut` can be used in several situations. The first is mutable bindings, +/// `mut` can be used in several situations. The first is mutable variables, /// which can be used anywhere you can bind a value to a variable name. Some /// examples: /// -/// ``` -/// // A mutable binding in the parameter list of a function. +/// ```rust +/// // A mutable variable in the parameter list of a function. /// fn foo(mut x: u8, y: u8) -> u8 { /// x += y; /// x /// } /// -/// // A mutable binding for a variable. +/// // Modifying a mutable variable. +/// # #[allow(unused_assignments)] /// let mut a = 5; /// a = 6; /// @@ -986,17 +987,17 @@ mod move_keyword {} /// assert_eq!(a, 6); /// ``` /// -/// The second is references. They can be created from `mut` bindings and must -/// be unique: no other binding can have a mutable reference, nor a simple -/// reference. +/// The second is mutable references. They can be created from `mut` variables +/// and must be unique: no other variables can have a mutable reference, nor a +/// shared reference. /// -/// ``` +/// ```rust /// // Taking a mutable reference. /// fn push_two(v: &mut Vec) { /// v.push(2); /// } /// -/// // You cannot take a mutable reference to a non-mutable variable. +/// // A mutable reference cannot be taken to a non-mutable variable. /// let mut v = vec![0, 1]; /// // Passing a mutable reference. /// push_two(&mut v); @@ -1004,10 +1005,18 @@ mod move_keyword {} /// assert_eq!(v, vec![0, 1, 2]); /// ``` /// -/// Mutable pointers work much like mutable references, with the added -/// possibility of being nul. The syntax is `*mut Type`. +/// ```rust,compile_fail,E0502 +/// let mut v = vec![0, 1]; +/// let mut_ref_v = &mut v; +/// ##[allow(unused)] +/// let ref_v = &v; +/// mut_ref_v.push(2); +/// ``` +/// +/// Mutable raw pointers work much like mutable references, with the added +/// possibility of not pointing to a valid object. The syntax is `*mut Type`. /// -/// You can find more information on mutable references and pointers in the +/// More information on mutable references and pointers can be found in``` /// [Reference]. /// /// [Reference]: ../reference/types/pointer.html#mutable-references-mut From 11a3584de4084deabe23354cb387984d6664a4a8 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 25 Jun 2020 11:56:15 +0100 Subject: [PATCH 8/8] emitter: column width defaults to 140 This commit modifies the column width computation in the emitter when `termize::dimensions` returns `None` so that it uses the default value of 140 (which is used in UI testing currently) instead of `usize::MAX` which just ends up causing overflows in later computations. This is hard to test but appears to produce the same output as using saturating functions instead. Signed-off-by: David Wood --- src/librustc_errors/emitter.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index b22da86c09187..1362a1155bcdd 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -31,6 +31,9 @@ use std::path::Path; use termcolor::{Ansi, BufferWriter, ColorChoice, ColorSpec, StandardStream}; use termcolor::{Buffer, Color, WriteColor}; +/// Default column width, used in tests and when terminal dimensions cannot be determined. +const DEFAULT_COLUMN_WIDTH: usize = 140; + /// Describes the way the content of the `rendered` field of the json output is generated #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum HumanReadableErrorType { @@ -74,7 +77,8 @@ struct Margin { pub computed_left: usize, /// The end of the line to be displayed. pub computed_right: usize, - /// The current width of the terminal. 140 by default and in tests. + /// The current width of the terminal. Uses value of `DEFAULT_COLUMN_WIDTH` constant by default + /// and in tests. pub column_width: usize, /// The end column of a span label, including the span. Doesn't account for labels not in the /// same line as the span. @@ -1414,11 +1418,11 @@ impl EmitterWriter { let column_width = if let Some(width) = self.terminal_width { width.saturating_sub(code_offset) } else if self.ui_testing { - 140 + DEFAULT_COLUMN_WIDTH } else { termize::dimensions() .map(|(w, _)| w.saturating_sub(code_offset)) - .unwrap_or(usize::MAX) + .unwrap_or(DEFAULT_COLUMN_WIDTH) }; let margin = Margin::new(