From 6674db48872c1b84fe3ac3feb94b8d3e0ee82b24 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 20 Nov 2018 20:16:57 +1100 Subject: [PATCH 01/22] Reuse the `P` in `InvocationCollector::fold_{,opt_}expr`. This requires adding a new method, `P::filter_map`. This commit reduces instruction counts for various benchmarks by up to 0.7%. --- src/libsyntax/ext/expand.rs | 84 +++++++++++++++++++++---------------- src/libsyntax/ptr.rs | 28 +++++++++++-- 2 files changed, 73 insertions(+), 39 deletions(-) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index cc8af70a050c9..68a96293891a0 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1201,50 +1201,62 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { fn fold_expr(&mut self, expr: P) -> P { - let mut expr = self.cfg.configure_expr(expr).into_inner(); - expr.node = self.cfg.configure_expr_kind(expr.node); - - // ignore derives so they remain unused - let (attr, expr, after_derive) = self.classify_nonitem(expr); - - if attr.is_some() { - // collect the invoc regardless of whether or not attributes are permitted here - // expansion will eat the attribute so it won't error later - attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); - - // AstFragmentKind::Expr requires the macro to emit an expression - return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), - AstFragmentKind::Expr, after_derive).make_expr(); - } + let expr = self.cfg.configure_expr(expr); + expr.map(|mut expr| { + expr.node = self.cfg.configure_expr_kind(expr.node); + + // ignore derives so they remain unused + let (attr, expr, after_derive) = self.classify_nonitem(expr); + + if attr.is_some() { + // Collect the invoc regardless of whether or not attributes are permitted here + // expansion will eat the attribute so it won't error later. + attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); + + // AstFragmentKind::Expr requires the macro to emit an expression. + return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), + AstFragmentKind::Expr, after_derive) + .make_expr() + .into_inner() + } - if let ast::ExprKind::Mac(mac) = expr.node { - self.check_attributes(&expr.attrs); - self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr() - } else { - P(noop_fold_expr(expr, self)) - } + if let ast::ExprKind::Mac(mac) = expr.node { + self.check_attributes(&expr.attrs); + self.collect_bang(mac, expr.span, AstFragmentKind::Expr) + .make_expr() + .into_inner() + } else { + noop_fold_expr(expr, self) + } + }) } fn fold_opt_expr(&mut self, expr: P) -> Option> { - let mut expr = configure!(self, expr).into_inner(); - expr.node = self.cfg.configure_expr_kind(expr.node); + let expr = configure!(self, expr); + expr.filter_map(|mut expr| { + expr.node = self.cfg.configure_expr_kind(expr.node); - // ignore derives so they remain unused - let (attr, expr, after_derive) = self.classify_nonitem(expr); + // Ignore derives so they remain unused. + let (attr, expr, after_derive) = self.classify_nonitem(expr); - if attr.is_some() { - attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); + if attr.is_some() { + attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); - return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), - AstFragmentKind::OptExpr, after_derive).make_opt_expr(); - } + return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), + AstFragmentKind::OptExpr, after_derive) + .make_opt_expr() + .map(|expr| expr.into_inner()) + } - if let ast::ExprKind::Mac(mac) = expr.node { - self.check_attributes(&expr.attrs); - self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr).make_opt_expr() - } else { - Some(P(noop_fold_expr(expr, self))) - } + if let ast::ExprKind::Mac(mac) = expr.node { + self.check_attributes(&expr.attrs); + self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr) + .make_opt_expr() + .map(|expr| expr.into_inner()) + } else { + Some(noop_fold_expr(expr, self)) + } + }) } fn fold_pat(&mut self, pat: P) -> P { diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index bb47d9b535bef..9fbc64758da4d 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -72,7 +72,7 @@ impl P { *self.ptr } - /// Transform the inner value, consuming `self` and producing a new `P`. + /// Produce a new `P` from `self` without reallocating. pub fn map(mut self, f: F) -> P where F: FnOnce(T) -> T, { @@ -88,8 +88,30 @@ impl P { ptr::write(p, f(ptr::read(p))); // Recreate self from the raw pointer. - P { - ptr: Box::from_raw(p) + P { ptr: Box::from_raw(p) } + } + } + + /// Optionally produce a new `P` from `self` without reallocating. + pub fn filter_map(mut self, f: F) -> Option> where + F: FnOnce(T) -> Option, + { + let p: *mut T = &mut *self.ptr; + + // Leak self in case of panic. + // FIXME(eddyb) Use some sort of "free guard" that + // only deallocates, without dropping the pointee, + // in case the call the `f` below ends in a panic. + mem::forget(self); + + unsafe { + if let Some(v) = f(ptr::read(p)) { + ptr::write(p, v); + + // Recreate self from the raw pointer. + Some(P { ptr: Box::from_raw(p) }) + } else { + None } } } From 464c9da9c229111298d413882735ea707a30e077 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 21 Nov 2018 10:07:33 +0100 Subject: [PATCH 02/22] serialize: preallocate VecDeque in Decodable::decode --- src/libserialize/collection_impls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index 3e028d755c6d4..cbd642dd6ad91 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -86,7 +86,7 @@ impl Encodable for VecDeque { impl Decodable for VecDeque { fn decode(d: &mut D) -> Result, D::Error> { d.read_seq(|d, len| { - let mut deque: VecDeque = VecDeque::new(); + let mut deque: VecDeque = VecDeque::with_capacity(len); for i in 0..len { deque.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))?); } From 591607d237665857880e16899788517b9b82d414 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 21 Nov 2018 10:17:54 +0100 Subject: [PATCH 03/22] String: add a FIXME to from_utf16 --- src/liballoc/string.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 8d009101ce7da..0b25d911a299c 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -618,6 +618,8 @@ impl String { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf16(v: &[u16]) -> Result { + // This isn't done via collect::>() for performance reasons. + // FIXME: the function can be simplified again when #48994 is closed. let mut ret = String::with_capacity(v.len()); for c in decode_utf16(v.iter().cloned()) { if let Ok(c) = c { From 057e6d3a35a54e8b88c2cef1e6a1b9e590066276 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sun, 25 Nov 2018 17:33:16 +0100 Subject: [PATCH 04/22] Add TryFrom<&[T]> for [T; $N] where T: Copy `TryFrom<&[T]> for &[T; $N]` (note *reference* to an array) already exists, but not needing to dereference makes type inference easier for example when using `u32::from_be_bytes`. Also add doc examples doing just that. --- src/libcore/array.rs | 9 +++++ src/libcore/num/mod.rs | 78 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 3d24f8902bd83..26e7a79d35df6 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -148,6 +148,15 @@ macro_rules! array_impls { } } + #[unstable(feature = "try_from", issue = "33417")] + impl<'a, T> TryFrom<&'a [T]> for [T; $N] where T: Copy { + type Error = TryFromSliceError; + + fn try_from(slice: &[T]) -> Result<[T; $N], TryFromSliceError> { + <&Self>::try_from(slice).map(|r| *r) + } + } + #[unstable(feature = "try_from", issue = "33417")] impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] { type Error = TryFromSliceError; diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 9deae12482976..f6f649bc06d01 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1989,6 +1989,19 @@ big endian. ``` let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, "); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -2008,6 +2021,19 @@ little endian. ``` let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, "); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -2037,6 +2063,19 @@ let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"bi ", $le_bytes, " }); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -3719,6 +3758,19 @@ big endian. ``` let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, "); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -3738,6 +3790,19 @@ little endian. ``` let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, "); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -3767,6 +3832,19 @@ let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"bi ", $le_bytes, " }); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] From ae0d0339e801bc10c46adbeb021b537b8313b760 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 25 Nov 2018 15:36:17 -0800 Subject: [PATCH 05/22] Update cargo --- Cargo.lock | 17 +++++++++++++++++ src/tools/cargo | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index a7b83f87b191b..604839d3a8a0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -201,6 +201,7 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ignore 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "im-rc 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -978,6 +979,15 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "im-rc" +version = "12.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "installer" version = "0.0.0" @@ -3038,6 +3048,11 @@ dependencies = [ "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ucd-util" version = "0.1.1" @@ -3331,6 +3346,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec" "checksum ignore 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9faa7c84064f07b40da27044af629f578bc7994b650d3e458d0c29183c1d91" +"checksum im-rc 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4591152fd573cf453a890b5f9fdc5c328a751a0785539316739d5f85e5c468c" "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053" "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" @@ -3482,6 +3498,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" "checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" "checksum toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6854664bfc6df0360c695480836ee90e2d0c965f06db291d10be9344792d43e8" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" diff --git a/src/tools/cargo b/src/tools/cargo index b3d0b2e545b61..1ff5975b96b3d 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit b3d0b2e545b61d4cd08096911724b7d49d213f73 +Subproject commit 1ff5975b96b3d395bb962394596998dfb485f793 From 769d7115fed078c93f66d8db24de2046a6ab6334 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Wed, 14 Nov 2018 14:51:28 -0500 Subject: [PATCH 06/22] add test for issue #21335 Fixes #21335. --- src/test/run-make/llvm-outputs/Makefile | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/test/run-make/llvm-outputs/Makefile diff --git a/src/test/run-make/llvm-outputs/Makefile b/src/test/run-make/llvm-outputs/Makefile new file mode 100644 index 0000000000000..d7f67577b04ce --- /dev/null +++ b/src/test/run-make/llvm-outputs/Makefile @@ -0,0 +1,5 @@ +-include ../../run-make-fulldeps/tools.mk + +all: + echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_ir/ --emit=llvm-ir + echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_bc/ --emit=llvm-bc From d4a6e739f3322c56e66fa8fef31569b7f16bc325 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Fri, 9 Nov 2018 15:12:09 +0100 Subject: [PATCH 07/22] Use sort_by_cached_key when key the function is not trivial/free --- src/librustc/middle/resolve_lifetime.rs | 2 +- src/librustc/traits/object_safety.rs | 2 +- src/librustc_mir/monomorphize/partitioning.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 6ff450508d136..07054ee99af76 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -1573,7 +1573,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .collect(); // ensure that we issue lints in a repeatable order - def_ids.sort_by_key(|&def_id| self.tcx.def_path_hash(def_id)); + def_ids.sort_by_cached_key(|&def_id| self.tcx.def_path_hash(def_id)); for def_id in def_ids { debug!( diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index c79fa3861234f..2909daf22b3ba 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -409,7 +409,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { .collect::>(); // existential predicates need to be in a specific order - associated_types.sort_by_key(|item| self.def_path_hash(item.def_id)); + associated_types.sort_by_cached_key(|item| self.def_path_hash(item.def_id)); let projection_predicates = associated_types.into_iter().map(|item| { ty::ExistentialPredicate::Projection(ty::ExistentialProjection { diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 6dba020120f84..3a6ee6da42215 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -985,7 +985,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>( output.push_str(" @@"); let mut empty = Vec::new(); let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); - cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone()); + cgus.as_mut_slice().sort_by_cached_key(|&(ref name, _)| name.clone()); cgus.dedup(); for &(ref cgu_name, (linkage, _)) in cgus.iter() { output.push_str(" "); From c4e0b89454ae8eb8d888830fa2563f8d5c52fe07 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Sat, 24 Nov 2018 10:13:27 +0100 Subject: [PATCH 08/22] move stage0.txt to toplevel directory This way all files needed by packagers now reside in toplevel Signed-off-by: Marc-Antoine Perennou --- config.toml.example | 4 ++-- src/bootstrap/bootstrap.py | 2 +- src/bootstrap/bootstrap_test.py | 3 +-- src/bootstrap/lib.rs | 2 +- src/bootstrap/sanity.rs | 2 +- src/stage0.txt => stage0.txt | 0 6 files changed, 6 insertions(+), 7 deletions(-) rename src/stage0.txt => stage0.txt (100%) diff --git a/config.toml.example b/config.toml.example index 8b11014edae79..fefbb227f00b9 100644 --- a/config.toml.example +++ b/config.toml.example @@ -112,11 +112,11 @@ # for each target triple. #target = ["x86_64-unknown-linux-gnu"] # defaults to just the build triple -# Instead of downloading the src/stage0.txt version of Cargo specified, use +# Instead of downloading the stage0.txt version of Cargo specified, use # this Cargo binary instead to build all Rust code #cargo = "/path/to/bin/cargo" -# Instead of downloading the src/stage0.txt version of the compiler +# Instead of downloading the stage0.txt version of the compiler # specified, use this rustc binary instead as the stage0 snapshot compiler. #rustc = "/path/to/bin/rustc" diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d143dffb24be5..b36c1bd7bb13b 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -154,7 +154,7 @@ def run(args, verbose=False, exception=False, **kwargs): def stage0_data(rust_root): """Build a dictionary from stage0.txt""" - nightlies = os.path.join(rust_root, "src/stage0.txt") + nightlies = os.path.join(rust_root, "stage0.txt") with open(nightlies, 'r') as nightlies: lines = [line.rstrip() for line in nightlies if not line.startswith("#")] diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index 4db7e2ec016f0..43cbe9967e312 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -28,8 +28,7 @@ class Stage0DataTestCase(unittest.TestCase): def setUp(self): self.rust_root = tempfile.mkdtemp() os.mkdir(os.path.join(self.rust_root, "src")) - with open(os.path.join(self.rust_root, "src", - "stage0.txt"), "w") as stage0: + with open(os.path.join(self.rust_root, "stage0.txt"), "w") as stage0: stage0.write("#ignore\n\ndate: 2017-06-15\nrustc: beta\ncargo: beta") def tearDown(self): diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 76697e482d3a8..548d5312dc7ce 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -41,7 +41,7 @@ //! When you execute `x.py build`, the steps which are executed are: //! //! * First, the python script is run. This will automatically download the -//! stage0 rustc and cargo according to `src/stage0.txt`, or use the cached +//! stage0 rustc and cargo according to `stage0.txt`, or use the cached //! versions if they're available. These are then used to compile rustbuild //! itself (using Cargo). Finally, control is then transferred to rustbuild. //! diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 15d3bccba09cc..c62ce5a5b93a2 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -236,7 +236,7 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake if build.config.channel == "stable" { let mut stage0 = String::new(); - t!(t!(File::open(build.src.join("src/stage0.txt"))) + t!(t!(File::open(build.src.join("stage0.txt"))) .read_to_string(&mut stage0)); if stage0.contains("\ndev:") { panic!("bootstrapping from a dev compiler in a stable release, but \ diff --git a/src/stage0.txt b/stage0.txt similarity index 100% rename from src/stage0.txt rename to stage0.txt From c343bbd055515b5b22afaf7b73e967d0b3ac55cc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Nov 2018 21:22:45 +0100 Subject: [PATCH 09/22] update miri --- Cargo.lock | 11 +++++++++++ src/tools/miri | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index a7b83f87b191b..c5c07acb1ecc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -624,6 +624,15 @@ name = "difference" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "directories" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "dlmalloc" version = "0.0.0" @@ -1316,6 +1325,7 @@ dependencies = [ "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "compiletest_rs 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "vergen 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3293,6 +3303,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +"checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum elasticlunr-rs 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4837d77a1e157489a3933b743fd774ae75074e0e390b2b7f071530048a0d87ee" "checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" diff --git a/src/tools/miri b/src/tools/miri index 32e93ed7762e5..fb72348e5f4bd 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 32e93ed7762e5aa1a721636096848fc3c7bc7218 +Subproject commit fb72348e5f4bd396d91c808b1e404f233908fb05 From 6c80f7c4fcb83be65c0b3595eb30690c626a30e3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Nov 2018 16:45:58 +1100 Subject: [PATCH 10/22] Fix whitespace in `pp.rs`. This commit converts some 2-space indents to 4-space indents. --- src/libsyntax/print/pp.rs | 252 +++++++++++++++++++------------------- 1 file changed, 126 insertions(+), 126 deletions(-) diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 086de35d531c7..00f22597a3fa3 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -316,75 +316,75 @@ impl<'a> Printer<'a> { pub fn pretty_print(&mut self, token: Token) -> io::Result<()> { debug!("pp Vec<{},{}>", self.left, self.right); match token { - Token::Eof => { - if !self.scan_stack.is_empty() { - self.check_stack(0); - self.advance_left()?; - } - self.indent(0); - Ok(()) - } - Token::Begin(b) => { - if self.scan_stack.is_empty() { - self.left_total = 1; - self.right_total = 1; - self.left = 0; - self.right = 0; - } else { - self.advance_right(); + Token::Eof => { + if !self.scan_stack.is_empty() { + self.check_stack(0); + self.advance_left()?; + } + self.indent(0); + Ok(()) } - debug!("pp Begin({})/buffer Vec<{},{}>", - b.offset, self.left, self.right); - self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; - let right = self.right; - self.scan_push(right); - Ok(()) - } - Token::End => { - if self.scan_stack.is_empty() { - debug!("pp End/print Vec<{},{}>", self.left, self.right); - self.print(token, 0) - } else { - debug!("pp End/buffer Vec<{},{}>", self.left, self.right); - self.advance_right(); - self.buf[self.right] = BufEntry { token: token, size: -1 }; + Token::Begin(b) => { + if self.scan_stack.is_empty() { + self.left_total = 1; + self.right_total = 1; + self.left = 0; + self.right = 0; + } else { + self.advance_right(); + } + debug!("pp Begin({})/buffer Vec<{},{}>", + b.offset, self.left, self.right); + self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; let right = self.right; self.scan_push(right); Ok(()) } - } - Token::Break(b) => { - if self.scan_stack.is_empty() { - self.left_total = 1; - self.right_total = 1; - self.left = 0; - self.right = 0; - } else { - self.advance_right(); + Token::End => { + if self.scan_stack.is_empty() { + debug!("pp End/print Vec<{},{}>", self.left, self.right); + self.print(token, 0) + } else { + debug!("pp End/buffer Vec<{},{}>", self.left, self.right); + self.advance_right(); + self.buf[self.right] = BufEntry { token: token, size: -1 }; + let right = self.right; + self.scan_push(right); + Ok(()) + } } - debug!("pp Break({})/buffer Vec<{},{}>", - b.offset, self.left, self.right); - self.check_stack(0); - let right = self.right; - self.scan_push(right); - self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; - self.right_total += b.blank_space; - Ok(()) - } - Token::String(s, len) => { - if self.scan_stack.is_empty() { - debug!("pp String('{}')/print Vec<{},{}>", - s, self.left, self.right); - self.print(Token::String(s, len), len) - } else { - debug!("pp String('{}')/buffer Vec<{},{}>", - s, self.left, self.right); - self.advance_right(); - self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len }; - self.right_total += len; - self.check_stream() + Token::Break(b) => { + if self.scan_stack.is_empty() { + self.left_total = 1; + self.right_total = 1; + self.left = 0; + self.right = 0; + } else { + self.advance_right(); + } + debug!("pp Break({})/buffer Vec<{},{}>", + b.offset, self.left, self.right); + self.check_stack(0); + let right = self.right; + self.scan_push(right); + self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; + self.right_total += b.blank_space; + Ok(()) + } + Token::String(s, len) => { + if self.scan_stack.is_empty() { + debug!("pp String('{}')/print Vec<{},{}>", + s, self.left, self.right); + self.print(Token::String(s, len), len) + } else { + debug!("pp String('{}')/buffer Vec<{},{}>", + s, self.left, self.right); + self.advance_right(); + self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len }; + self.right_total += len; + self.check_stream() + } } - } } } pub fn check_stream(&mut self) -> io::Result<()> { @@ -523,74 +523,74 @@ impl<'a> Printer<'a> { self.right, 6)); match token { - Token::Begin(b) => { - if l > self.space { - let col = self.margin - self.space + b.offset; - debug!("print Begin -> push broken block at col {}", col); - self.print_stack.push(PrintStackElem { - offset: col, - pbreak: PrintStackBreak::Broken(b.breaks) - }); - } else { - debug!("print Begin -> push fitting block"); - self.print_stack.push(PrintStackElem { - offset: 0, - pbreak: PrintStackBreak::Fits - }); - } - Ok(()) - } - Token::End => { - debug!("print End -> pop End"); - let print_stack = &mut self.print_stack; - assert!(!print_stack.is_empty()); - print_stack.pop().unwrap(); - Ok(()) - } - Token::Break(b) => { - let top = self.get_top(); - match top.pbreak { - PrintStackBreak::Fits => { - debug!("print Break({}) in fitting block", b.blank_space); - self.space -= b.blank_space; - self.indent(b.blank_space); - Ok(()) - } - PrintStackBreak::Broken(Breaks::Consistent) => { - debug!("print Break({}+{}) in consistent block", - top.offset, b.offset); - let ret = self.print_newline(top.offset + b.offset); - self.space = self.margin - (top.offset + b.offset); - ret - } - PrintStackBreak::Broken(Breaks::Inconsistent) => { + Token::Begin(b) => { if l > self.space { - debug!("print Break({}+{}) w/ newline in inconsistent", - top.offset, b.offset); - let ret = self.print_newline(top.offset + b.offset); - self.space = self.margin - (top.offset + b.offset); - ret + let col = self.margin - self.space + b.offset; + debug!("print Begin -> push broken block at col {}", col); + self.print_stack.push(PrintStackElem { + offset: col, + pbreak: PrintStackBreak::Broken(b.breaks) + }); } else { - debug!("print Break({}) w/o newline in inconsistent", - b.blank_space); - self.indent(b.blank_space); - self.space -= b.blank_space; - Ok(()) + debug!("print Begin -> push fitting block"); + self.print_stack.push(PrintStackElem { + offset: 0, + pbreak: PrintStackBreak::Fits + }); } - } + Ok(()) + } + Token::End => { + debug!("print End -> pop End"); + let print_stack = &mut self.print_stack; + assert!(!print_stack.is_empty()); + print_stack.pop().unwrap(); + Ok(()) + } + Token::Break(b) => { + let top = self.get_top(); + match top.pbreak { + PrintStackBreak::Fits => { + debug!("print Break({}) in fitting block", b.blank_space); + self.space -= b.blank_space; + self.indent(b.blank_space); + Ok(()) + } + PrintStackBreak::Broken(Breaks::Consistent) => { + debug!("print Break({}+{}) in consistent block", + top.offset, b.offset); + let ret = self.print_newline(top.offset + b.offset); + self.space = self.margin - (top.offset + b.offset); + ret + } + PrintStackBreak::Broken(Breaks::Inconsistent) => { + if l > self.space { + debug!("print Break({}+{}) w/ newline in inconsistent", + top.offset, b.offset); + let ret = self.print_newline(top.offset + b.offset); + self.space = self.margin - (top.offset + b.offset); + ret + } else { + debug!("print Break({}) w/o newline in inconsistent", + b.blank_space); + self.indent(b.blank_space); + self.space -= b.blank_space; + Ok(()) + } + } + } + } + Token::String(ref s, len) => { + debug!("print String({})", s); + assert_eq!(l, len); + // assert!(l <= space); + self.space -= len; + self.print_str(s) + } + Token::Eof => { + // Eof should never get here. + panic!(); } - } - Token::String(ref s, len) => { - debug!("print String({})", s); - assert_eq!(l, len); - // assert!(l <= space); - self.space -= len; - self.print_str(s) - } - Token::Eof => { - // Eof should never get here. - panic!(); - } } } From deb9195e5749c4f15e9a5ae0e7ee8e1802c716e4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Nov 2018 16:46:43 +1100 Subject: [PATCH 11/22] Remove `huge_word` and `zero_word`. They are unused. The commit also adds some blank lines between some methods. --- src/libsyntax/print/pp.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 00f22597a3fa3..e01c4b01aaa66 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -309,10 +309,12 @@ impl<'a> Printer<'a> { pub fn last_token(&mut self) -> Token { self.buf[self.right].token.clone() } - /// be very careful with this! + + /// Be very careful with this! pub fn replace_last_token(&mut self, t: Token) { self.buf[self.right].token = t; } + pub fn pretty_print(&mut self, token: Token) -> io::Result<()> { debug!("pp Vec<{},{}>", self.left, self.right); match token { @@ -387,6 +389,7 @@ impl<'a> Printer<'a> { } } } + pub fn check_stream(&mut self) -> io::Result<()> { debug!("check_stream Vec<{}, {}> with left_total={}, right_total={}", self.left, self.right, self.left_total, self.right_total); @@ -405,19 +408,24 @@ impl<'a> Printer<'a> { } Ok(()) } + pub fn scan_push(&mut self, x: usize) { debug!("scan_push {}", x); self.scan_stack.push_front(x); } + pub fn scan_pop(&mut self) -> usize { self.scan_stack.pop_front().unwrap() } + pub fn scan_top(&mut self) -> usize { *self.scan_stack.front().unwrap() } + pub fn scan_pop_bottom(&mut self) -> usize { self.scan_stack.pop_back().unwrap() } + pub fn advance_right(&mut self) { self.right += 1; self.right %= self.buf_max_len; @@ -427,6 +435,7 @@ impl<'a> Printer<'a> { } assert_ne!(self.right, self.left); } + pub fn advance_left(&mut self) -> io::Result<()> { debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right, self.left, self.buf[self.left].size); @@ -461,6 +470,7 @@ impl<'a> Printer<'a> { Ok(()) } + pub fn check_stack(&mut self, k: isize) { if !self.scan_stack.is_empty() { let x = self.scan_top(); @@ -488,6 +498,7 @@ impl<'a> Printer<'a> { } } } + pub fn print_newline(&mut self, amount: isize) -> io::Result<()> { debug!("NEWLINE {}", amount); let ret = write!(self.out, "\n"); @@ -495,10 +506,12 @@ impl<'a> Printer<'a> { self.indent(amount); ret } + pub fn indent(&mut self, amount: isize) { debug!("INDENT {}", amount); self.pending_indentation += amount; } + pub fn get_top(&mut self) -> PrintStackElem { match self.print_stack.last() { Some(el) => *el, @@ -508,6 +521,7 @@ impl<'a> Printer<'a> { } } } + pub fn print_str(&mut self, s: &str) -> io::Result<()> { while self.pending_indentation > 0 { write!(self.out, " ")?; @@ -515,6 +529,7 @@ impl<'a> Printer<'a> { } write!(self.out, "{}", s) } + pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> { debug!("print {} {} (remaining line space={})", token, l, self.space); @@ -633,14 +648,6 @@ impl<'a> Printer<'a> { self.pretty_print(Token::String(wrd.to_string(), wrd.len() as isize)) } - pub fn huge_word(&mut self, wrd: &str) -> io::Result<()> { - self.pretty_print(Token::String(wrd.to_string(), SIZE_INFINITY)) - } - - pub fn zero_word(&mut self, wrd: &str) -> io::Result<()> { - self.pretty_print(Token::String(wrd.to_string(), 0)) - } - fn spaces(&mut self, n: usize) -> io::Result<()> { self.break_offset(n, 0) } From 787959c20d062d396b97a5566e0a766d963af022 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 29 Nov 2018 11:36:58 +1100 Subject: [PATCH 12/22] Use `Cow` in `Token::String`. `Printer::word` takes a `&str` and converts it into a `String`, which causes an allocation. But that allocation is rarely necessary, because `&str` is almost always a `&'static str` or a `String` that won't be used again. This commit changes `Token::String` so it holds a `Cow<'static, str>` instead of a `String`, which avoids a lot of allocations. --- src/librustc/hir/print.rs | 61 ++++++++-------- src/librustc_driver/pretty.rs | 2 +- src/librustc_typeck/check_unused.rs | 2 +- src/libsyntax/parse/parser.rs | 2 +- src/libsyntax/print/pp.rs | 12 +++- src/libsyntax/print/pprust.rs | 106 ++++++++++++++-------------- src/libsyntax_pos/symbol.rs | 4 ++ 7 files changed, 101 insertions(+), 88 deletions(-) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index e69d32ad1deaf..9a0ceddcf1b4a 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -25,6 +25,7 @@ use hir; use hir::{PatKind, GenericBound, TraitBoundModifier, RangeEnd}; use hir::{GenericParam, GenericParamKind, GenericArg}; +use std::borrow::Cow; use std::cell::Cell; use std::io::{self, Write, Read}; use std::iter::Peekable; @@ -209,7 +210,7 @@ pub fn to_string(ann: &dyn PpAnn, f: F) -> String String::from_utf8(wr).unwrap() } -pub fn visibility_qualified(vis: &hir::Visibility, w: &str) -> String { +pub fn visibility_qualified>>(vis: &hir::Visibility, w: S) -> String { to_string(NO_ANN, |s| { s.print_visibility(vis)?; s.s.word(w) @@ -226,12 +227,13 @@ impl<'a> State<'a> { self.s.word(" ") } - pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> { + pub fn word_nbsp>>(&mut self, w: S) -> io::Result<()> { self.s.word(w)?; self.nbsp() } - pub fn head(&mut self, w: &str) -> io::Result<()> { + pub fn head>>(&mut self, w: S) -> io::Result<()> { + let w = w.into(); // outer-box is consistent self.cbox(indent_unit)?; // head-box is inconsistent @@ -303,7 +305,7 @@ impl<'a> State<'a> { pub fn synth_comment(&mut self, text: String) -> io::Result<()> { self.s.word("/*")?; self.s.space()?; - self.s.word(&text[..])?; + self.s.word(text)?; self.s.space()?; self.s.word("*/") } @@ -468,7 +470,7 @@ impl<'a> State<'a> { self.end() // end the outer fn box } hir::ForeignItemKind::Static(ref t, m) => { - self.head(&visibility_qualified(&item.vis, "static"))?; + self.head(visibility_qualified(&item.vis, "static"))?; if m { self.word_space("mut")?; } @@ -480,7 +482,7 @@ impl<'a> State<'a> { self.end() // end the outer cbox } hir::ForeignItemKind::Type => { - self.head(&visibility_qualified(&item.vis, "type"))?; + self.head(visibility_qualified(&item.vis, "type"))?; self.print_name(item.name)?; self.s.word(";")?; self.end()?; // end the head-ibox @@ -495,7 +497,7 @@ impl<'a> State<'a> { default: Option, vis: &hir::Visibility) -> io::Result<()> { - self.s.word(&visibility_qualified(vis, ""))?; + self.s.word(visibility_qualified(vis, ""))?; self.word_space("const")?; self.print_ident(ident)?; self.word_space(":")?; @@ -534,7 +536,7 @@ impl<'a> State<'a> { self.ann.pre(self, AnnNode::Item(item))?; match item.node { hir::ItemKind::ExternCrate(orig_name) => { - self.head(&visibility_qualified(&item.vis, "extern crate"))?; + self.head(visibility_qualified(&item.vis, "extern crate"))?; if let Some(orig_name) = orig_name { self.print_name(orig_name)?; self.s.space()?; @@ -547,7 +549,7 @@ impl<'a> State<'a> { self.end()?; // end outer head-block } hir::ItemKind::Use(ref path, kind) => { - self.head(&visibility_qualified(&item.vis, "use"))?; + self.head(visibility_qualified(&item.vis, "use"))?; self.print_path(path, false)?; match kind { @@ -566,7 +568,7 @@ impl<'a> State<'a> { self.end()?; // end outer head-block } hir::ItemKind::Static(ref ty, m, expr) => { - self.head(&visibility_qualified(&item.vis, "static"))?; + self.head(visibility_qualified(&item.vis, "static"))?; if m == hir::MutMutable { self.word_space("mut")?; } @@ -582,7 +584,7 @@ impl<'a> State<'a> { self.end()?; // end the outer cbox } hir::ItemKind::Const(ref ty, expr) => { - self.head(&visibility_qualified(&item.vis, "const"))?; + self.head(visibility_qualified(&item.vis, "const"))?; self.print_name(item.name)?; self.word_space(":")?; self.print_type(&ty)?; @@ -609,7 +611,7 @@ impl<'a> State<'a> { self.ann.nested(self, Nested::Body(body))?; } hir::ItemKind::Mod(ref _mod) => { - self.head(&visibility_qualified(&item.vis, "mod"))?; + self.head(visibility_qualified(&item.vis, "mod"))?; self.print_name(item.name)?; self.nbsp()?; self.bopen()?; @@ -618,18 +620,18 @@ impl<'a> State<'a> { } hir::ItemKind::ForeignMod(ref nmod) => { self.head("extern")?; - self.word_nbsp(&nmod.abi.to_string())?; + self.word_nbsp(nmod.abi.to_string())?; self.bopen()?; self.print_foreign_mod(nmod, &item.attrs)?; self.bclose(item.span)?; } hir::ItemKind::GlobalAsm(ref ga) => { - self.head(&visibility_qualified(&item.vis, "global asm"))?; - self.s.word(&ga.asm.as_str())?; + self.head(visibility_qualified(&item.vis, "global asm"))?; + self.s.word(ga.asm.as_str().get())?; self.end()? } hir::ItemKind::Ty(ref ty, ref generics) => { - self.head(&visibility_qualified(&item.vis, "type"))?; + self.head(visibility_qualified(&item.vis, "type"))?; self.print_name(item.name)?; self.print_generic_params(&generics.params)?; self.end()?; // end the inner ibox @@ -642,7 +644,7 @@ impl<'a> State<'a> { self.end()?; // end the outer ibox } hir::ItemKind::Existential(ref exist) => { - self.head(&visibility_qualified(&item.vis, "existential type"))?; + self.head(visibility_qualified(&item.vis, "existential type"))?; self.print_name(item.name)?; self.print_generic_params(&exist.generics.params)?; self.end()?; // end the inner ibox @@ -668,11 +670,11 @@ impl<'a> State<'a> { self.print_enum_def(enum_definition, params, item.name, item.span, &item.vis)?; } hir::ItemKind::Struct(ref struct_def, ref generics) => { - self.head(&visibility_qualified(&item.vis, "struct"))?; + self.head(visibility_qualified(&item.vis, "struct"))?; self.print_struct(struct_def, generics, item.name, item.span, true)?; } hir::ItemKind::Union(ref struct_def, ref generics) => { - self.head(&visibility_qualified(&item.vis, "union"))?; + self.head(visibility_qualified(&item.vis, "union"))?; self.print_struct(struct_def, generics, item.name, item.span, true)?; } hir::ItemKind::Impl(unsafety, @@ -795,7 +797,7 @@ impl<'a> State<'a> { span: syntax_pos::Span, visibility: &hir::Visibility) -> io::Result<()> { - self.head(&visibility_qualified(visibility, "enum"))?; + self.head(visibility_qualified(visibility, "enum"))?; self.print_name(name)?; self.print_generic_params(&generics.params)?; self.print_where_clause(&generics.where_clause)?; @@ -1587,14 +1589,14 @@ impl<'a> State<'a> { } pub fn print_usize(&mut self, i: usize) -> io::Result<()> { - self.s.word(&i.to_string()) + self.s.word(i.to_string()) } pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> { if ident.is_raw_guess() { - self.s.word(&format!("r#{}", ident.name))?; + self.s.word(format!("r#{}", ident.name))?; } else { - self.s.word(&ident.as_str())?; + self.s.word(ident.as_str().get())?; } self.ann.post(self, AnnNode::Name(&ident.name)) } @@ -2010,7 +2012,7 @@ impl<'a> State<'a> { self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(indent_unit)?; if let Some(arg_name) = arg_names.get(i) { - s.s.word(&arg_name.as_str())?; + s.s.word(arg_name.as_str().get())?; s.s.word(":")?; s.s.space()?; } else if let Some(body_id) = body_id { @@ -2073,7 +2075,8 @@ impl<'a> State<'a> { } } - pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::GenericBound]) -> io::Result<()> { + pub fn print_bounds(&mut self, prefix: &'static str, bounds: &[hir::GenericBound]) + -> io::Result<()> { if !bounds.is_empty() { self.s.word(prefix)?; let mut first = true; @@ -2322,7 +2325,7 @@ impl<'a> State<'a> { Some(Abi::Rust) => Ok(()), Some(abi) => { self.word_nbsp("extern")?; - self.word_nbsp(&abi.to_string()) + self.word_nbsp(abi.to_string()) } None => Ok(()), } @@ -2332,7 +2335,7 @@ impl<'a> State<'a> { match opt_abi { Some(abi) => { self.word_nbsp("extern")?; - self.word_nbsp(&abi.to_string()) + self.word_nbsp(abi.to_string()) } None => Ok(()), } @@ -2342,7 +2345,7 @@ impl<'a> State<'a> { header: hir::FnHeader, vis: &hir::Visibility) -> io::Result<()> { - self.s.word(&visibility_qualified(vis, ""))?; + self.s.word(visibility_qualified(vis, ""))?; match header.constness { hir::Constness::NotConst => {} @@ -2358,7 +2361,7 @@ impl<'a> State<'a> { if header.abi != Abi::Rust { self.word_nbsp("extern")?; - self.word_nbsp(&header.abi.to_string())?; + self.word_nbsp(header.abi.to_string())?; } self.s.word("fn") diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index c7ba31e339570..fb8093d1d77a7 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -530,7 +530,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { s.s.space()?; s.s.word("as")?; s.s.space()?; - s.s.word(&self.tables.get().expr_ty(expr).to_string())?; + s.s.word(self.tables.get().expr_ty(expr).to_string())?; s.pclose() } _ => Ok(()), diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 22a96d4e908ca..103331894ff1e 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -185,7 +185,7 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) { Some(orig_name) => format!("use {} as {};", orig_name, item.name), None => format!("use {};", item.name), }; - let replacement = visibility_qualified(&item.vis, &base_replacement); + let replacement = visibility_qualified(&item.vis, base_replacement); tcx.struct_span_lint_node(lint, id, extern_crate.span, msg) .span_suggestion_short_with_applicability( extern_crate.span, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e2f09affd4fea..99a59fa8a75ca 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2795,7 +2795,7 @@ impl<'a> Parser<'a> { s.print_usize(float.trunc() as usize)?; s.pclose()?; s.s.word(".")?; - s.s.word(fstr.splitn(2, ".").last().unwrap()) + s.s.word(fstr.splitn(2, ".").last().unwrap().to_string()) }); err.span_suggestion_with_applicability( lo.to(self.prev_span), diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index e01c4b01aaa66..b9addcaeb8edf 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -147,6 +147,7 @@ use std::collections::VecDeque; use std::fmt; use std::io; +use std::borrow::Cow; /// How to break. Described in more detail in the module docs. #[derive(Clone, Copy, PartialEq)] @@ -169,7 +170,10 @@ pub struct BeginToken { #[derive(Clone)] pub enum Token { - String(String, isize), + // In practice a string token contains either a `&'static str` or a + // `String`. `Cow` is overkill for this because we never modify the data, + // but it's more convenient than rolling our own more specialized type. + String(Cow<'static, str>, isize), Break(BreakToken), Begin(BeginToken), End, @@ -644,8 +648,10 @@ impl<'a> Printer<'a> { self.pretty_print(Token::Eof) } - pub fn word(&mut self, wrd: &str) -> io::Result<()> { - self.pretty_print(Token::String(wrd.to_string(), wrd.len() as isize)) + pub fn word>>(&mut self, wrd: S) -> io::Result<()> { + let s = wrd.into(); + let len = s.len() as isize; + self.pretty_print(Token::String(s, len)) } fn spaces(&mut self, n: usize) -> io::Result<()> { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index ce7708cc42e56..14ad4b5c6f815 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -29,6 +29,7 @@ use syntax_pos::{DUMMY_SP, FileName}; use tokenstream::{self, TokenStream, TokenTree}; use std::ascii; +use std::borrow::Cow; use std::io::{self, Write, Read}; use std::iter::Peekable; use std::vec; @@ -444,7 +445,7 @@ pub trait PrintState<'a> { fn cur_lit(&mut self) -> Option<&comments::Literal>; fn bump_lit(&mut self) -> Option; - fn word_space(&mut self, w: &str) -> io::Result<()> { + fn word_space>>(&mut self, w: S) -> io::Result<()> { self.writer().word(w)?; self.writer().space() } @@ -539,7 +540,7 @@ pub trait PrintState<'a> { comments::Mixed => { assert_eq!(cmnt.lines.len(), 1); self.writer().zerobreak()?; - self.writer().word(&cmnt.lines[0])?; + self.writer().word(cmnt.lines[0].clone())?; self.writer().zerobreak() } comments::Isolated => { @@ -548,7 +549,7 @@ pub trait PrintState<'a> { // Don't print empty lines because they will end up as trailing // whitespace if !line.is_empty() { - self.writer().word(&line[..])?; + self.writer().word(line.clone())?; } self.writer().hardbreak()?; } @@ -559,13 +560,13 @@ pub trait PrintState<'a> { self.writer().word(" ")?; } if cmnt.lines.len() == 1 { - self.writer().word(&cmnt.lines[0])?; + self.writer().word(cmnt.lines[0].clone())?; self.writer().hardbreak() } else { self.ibox(0)?; for line in &cmnt.lines { if !line.is_empty() { - self.writer().word(&line[..])?; + self.writer().word(line.clone())?; } self.writer().hardbreak()?; } @@ -610,7 +611,7 @@ pub trait PrintState<'a> { fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> { self.maybe_print_comment(lit.span.lo())?; if let Some(ltrl) = self.next_lit(lit.span.lo()) { - return self.writer().word(<rl.lit); + return self.writer().word(ltrl.lit.clone()); } match lit.node { ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style), @@ -618,31 +619,31 @@ pub trait PrintState<'a> { let mut res = String::from("b'"); res.extend(ascii::escape_default(byte).map(|c| c as char)); res.push('\''); - self.writer().word(&res[..]) + self.writer().word(res) } ast::LitKind::Char(ch) => { let mut res = String::from("'"); res.extend(ch.escape_default()); res.push('\''); - self.writer().word(&res[..]) + self.writer().word(res) } ast::LitKind::Int(i, t) => { match t { ast::LitIntType::Signed(st) => { - self.writer().word(&st.val_to_string(i as i128)) + self.writer().word(st.val_to_string(i as i128)) } ast::LitIntType::Unsigned(ut) => { - self.writer().word(&ut.val_to_string(i)) + self.writer().word(ut.val_to_string(i)) } ast::LitIntType::Unsuffixed => { - self.writer().word(&i.to_string()) + self.writer().word(i.to_string()) } } } ast::LitKind::Float(ref f, t) => { - self.writer().word(&format!("{}{}", &f, t.ty_to_string())) + self.writer().word(format!("{}{}", &f, t.ty_to_string())) } - ast::LitKind::FloatUnsuffixed(ref f) => self.writer().word(&f.as_str()), + ast::LitKind::FloatUnsuffixed(ref f) => self.writer().word(f.as_str().get()), ast::LitKind::Bool(val) => { if val { self.writer().word("true") } else { self.writer().word("false") } } @@ -652,7 +653,7 @@ pub trait PrintState<'a> { escaped.extend(ascii::escape_default(ch) .map(|c| c as char)); } - self.writer().word(&format!("b\"{}\"", escaped)) + self.writer().word(format!("b\"{}\"", escaped)) } } } @@ -669,7 +670,7 @@ pub trait PrintState<'a> { string=st)) } }; - self.writer().word(&st[..]) + self.writer().word(st) } fn print_inner_attributes(&mut self, @@ -727,7 +728,7 @@ pub trait PrintState<'a> { if segment.ident.name != keywords::CrateRoot.name() && segment.ident.name != keywords::DollarCrate.name() { - self.writer().word(&segment.ident.as_str())?; + self.writer().word(segment.ident.as_str().get())?; } else if segment.ident.name == keywords::DollarCrate.name() { self.print_dollar_crate(segment.ident.span.ctxt())?; } @@ -746,7 +747,7 @@ pub trait PrintState<'a> { } self.maybe_print_comment(attr.span.lo())?; if attr.is_sugared_doc { - self.writer().word(&attr.value_str().unwrap().as_str())?; + self.writer().word(attr.value_str().unwrap().as_str().get())?; self.writer().hardbreak() } else { match attr.style { @@ -807,7 +808,7 @@ pub trait PrintState<'a> { fn print_tt(&mut self, tt: tokenstream::TokenTree) -> io::Result<()> { match tt { TokenTree::Token(_, ref tk) => { - self.writer().word(&token_to_string(tk))?; + self.writer().word(token_to_string(tk))?; match *tk { parse::token::DocComment(..) => { self.writer().hardbreak() @@ -816,11 +817,11 @@ pub trait PrintState<'a> { } } TokenTree::Delimited(_, ref delimed) => { - self.writer().word(&token_to_string(&delimed.open_token()))?; + self.writer().word(token_to_string(&delimed.open_token()))?; self.writer().space()?; self.print_tts(delimed.stream())?; self.writer().space()?; - self.writer().word(&token_to_string(&delimed.close_token())) + self.writer().word(token_to_string(&delimed.close_token())) }, } } @@ -889,12 +890,13 @@ impl<'a> State<'a> { self.s.cbox(u) } - pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> { + pub fn word_nbsp>>(&mut self, w: S) -> io::Result<()> { self.s.word(w)?; self.nbsp() } - pub fn head(&mut self, w: &str) -> io::Result<()> { + pub fn head>>(&mut self, w: S) -> io::Result<()> { + let w = w.into(); // outer-box is consistent self.cbox(INDENT_UNIT)?; // head-box is inconsistent @@ -956,7 +958,7 @@ impl<'a> State<'a> { pub fn synth_comment(&mut self, text: String) -> io::Result<()> { self.s.word("/*")?; self.s.space()?; - self.s.word(&text[..])?; + self.s.word(text)?; self.s.space()?; self.s.word("*/") } @@ -1129,7 +1131,7 @@ impl<'a> State<'a> { self.end() // end the outer fn box } ast::ForeignItemKind::Static(ref t, m) => { - self.head(&visibility_qualified(&item.vis, "static"))?; + self.head(visibility_qualified(&item.vis, "static"))?; if m { self.word_space("mut")?; } @@ -1141,7 +1143,7 @@ impl<'a> State<'a> { self.end() // end the outer cbox } ast::ForeignItemKind::Ty => { - self.head(&visibility_qualified(&item.vis, "type"))?; + self.head(visibility_qualified(&item.vis, "type"))?; self.print_ident(item.ident)?; self.s.word(";")?; self.end()?; // end the head-ibox @@ -1164,7 +1166,7 @@ impl<'a> State<'a> { vis: &ast::Visibility) -> io::Result<()> { - self.s.word(&visibility_qualified(vis, ""))?; + self.s.word(visibility_qualified(vis, ""))?; self.word_space("const")?; self.print_ident(ident)?; self.word_space(":")?; @@ -1203,7 +1205,7 @@ impl<'a> State<'a> { self.ann.pre(self, AnnNode::Item(item))?; match item.node { ast::ItemKind::ExternCrate(orig_name) => { - self.head(&visibility_qualified(&item.vis, "extern crate"))?; + self.head(visibility_qualified(&item.vis, "extern crate"))?; if let Some(orig_name) = orig_name { self.print_name(orig_name)?; self.s.space()?; @@ -1216,14 +1218,14 @@ impl<'a> State<'a> { self.end()?; // end outer head-block } ast::ItemKind::Use(ref tree) => { - self.head(&visibility_qualified(&item.vis, "use"))?; + self.head(visibility_qualified(&item.vis, "use"))?; self.print_use_tree(tree)?; self.s.word(";")?; self.end()?; // end inner head-block self.end()?; // end outer head-block } ast::ItemKind::Static(ref ty, m, ref expr) => { - self.head(&visibility_qualified(&item.vis, "static"))?; + self.head(visibility_qualified(&item.vis, "static"))?; if m == ast::Mutability::Mutable { self.word_space("mut")?; } @@ -1239,7 +1241,7 @@ impl<'a> State<'a> { self.end()?; // end the outer cbox } ast::ItemKind::Const(ref ty, ref expr) => { - self.head(&visibility_qualified(&item.vis, "const"))?; + self.head(visibility_qualified(&item.vis, "const"))?; self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(ty)?; @@ -1264,7 +1266,7 @@ impl<'a> State<'a> { self.print_block_with_attrs(body, &item.attrs)?; } ast::ItemKind::Mod(ref _mod) => { - self.head(&visibility_qualified(&item.vis, "mod"))?; + self.head(visibility_qualified(&item.vis, "mod"))?; self.print_ident(item.ident)?; if _mod.inline || self.is_expanded { @@ -1281,18 +1283,18 @@ impl<'a> State<'a> { } ast::ItemKind::ForeignMod(ref nmod) => { self.head("extern")?; - self.word_nbsp(&nmod.abi.to_string())?; + self.word_nbsp(nmod.abi.to_string())?; self.bopen()?; self.print_foreign_mod(nmod, &item.attrs)?; self.bclose(item.span)?; } ast::ItemKind::GlobalAsm(ref ga) => { - self.head(&visibility_qualified(&item.vis, "global_asm!"))?; - self.s.word(&ga.asm.as_str())?; + self.head(visibility_qualified(&item.vis, "global_asm!"))?; + self.s.word(ga.asm.as_str().get())?; self.end()?; } ast::ItemKind::Ty(ref ty, ref generics) => { - self.head(&visibility_qualified(&item.vis, "type"))?; + self.head(visibility_qualified(&item.vis, "type"))?; self.print_ident(item.ident)?; self.print_generic_params(&generics.params)?; self.end()?; // end the inner ibox @@ -1305,7 +1307,7 @@ impl<'a> State<'a> { self.end()?; // end the outer ibox } ast::ItemKind::Existential(ref bounds, ref generics) => { - self.head(&visibility_qualified(&item.vis, "existential type"))?; + self.head(visibility_qualified(&item.vis, "existential type"))?; self.print_ident(item.ident)?; self.print_generic_params(&generics.params)?; self.end()?; // end the inner ibox @@ -1326,11 +1328,11 @@ impl<'a> State<'a> { )?; } ast::ItemKind::Struct(ref struct_def, ref generics) => { - self.head(&visibility_qualified(&item.vis, "struct"))?; + self.head(visibility_qualified(&item.vis, "struct"))?; self.print_struct(struct_def, generics, item.ident, item.span, true)?; } ast::ItemKind::Union(ref struct_def, ref generics) => { - self.head(&visibility_qualified(&item.vis, "union"))?; + self.head(visibility_qualified(&item.vis, "union"))?; self.print_struct(struct_def, generics, item.ident, item.span, true)?; } ast::ItemKind::Impl(unsafety, @@ -1479,7 +1481,7 @@ impl<'a> State<'a> { generics: &ast::Generics, ident: ast::Ident, span: syntax_pos::Span, visibility: &ast::Visibility) -> io::Result<()> { - self.head(&visibility_qualified(visibility, "enum"))?; + self.head(visibility_qualified(visibility, "enum"))?; self.print_ident(ident)?; self.print_generic_params(&generics.params)?; self.print_where_clause(&generics.where_clause)?; @@ -1514,9 +1516,9 @@ impl<'a> State<'a> { ast::VisibilityKind::Restricted { ref path, .. } => { let path = to_string(|s| s.print_path(path, false, 0)); if path == "self" || path == "super" { - self.word_nbsp(&format!("pub({})", path)) + self.word_nbsp(format!("pub({})", path)) } else { - self.word_nbsp(&format!("pub(in {})", path)) + self.word_nbsp(format!("pub(in {})", path)) } } ast::VisibilityKind::Inherited => Ok(()) @@ -2415,19 +2417,19 @@ impl<'a> State<'a> { pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> { if ident.is_raw_guess() { - self.s.word(&format!("r#{}", ident))?; + self.s.word(format!("r#{}", ident))?; } else { - self.s.word(&ident.as_str())?; + self.s.word(ident.as_str().get())?; } self.ann.post(self, AnnNode::Ident(&ident)) } pub fn print_usize(&mut self, i: usize) -> io::Result<()> { - self.s.word(&i.to_string()) + self.s.word(i.to_string()) } pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { - self.s.word(&name.as_str())?; + self.s.word(name.as_str().get())?; self.ann.post(self, AnnNode::Name(&name)) } @@ -2851,10 +2853,8 @@ impl<'a> State<'a> { } } - pub fn print_type_bounds(&mut self, - prefix: &str, - bounds: &[ast::GenericBound]) - -> io::Result<()> { + pub fn print_type_bounds(&mut self, prefix: &'static str, bounds: &[ast::GenericBound]) + -> io::Result<()> { if !bounds.is_empty() { self.s.word(prefix)?; let mut first = true; @@ -3146,7 +3146,7 @@ impl<'a> State<'a> { Some(Abi::Rust) => Ok(()), Some(abi) => { self.word_nbsp("extern")?; - self.word_nbsp(&abi.to_string()) + self.word_nbsp(abi.to_string()) } None => Ok(()) } @@ -3157,7 +3157,7 @@ impl<'a> State<'a> { match opt_abi { Some(abi) => { self.word_nbsp("extern")?; - self.word_nbsp(&abi.to_string()) + self.word_nbsp(abi.to_string()) } None => Ok(()) } @@ -3166,7 +3166,7 @@ impl<'a> State<'a> { pub fn print_fn_header_info(&mut self, header: ast::FnHeader, vis: &ast::Visibility) -> io::Result<()> { - self.s.word(&visibility_qualified(vis, ""))?; + self.s.word(visibility_qualified(vis, ""))?; match header.constness.node { ast::Constness::NotConst => {} @@ -3178,7 +3178,7 @@ impl<'a> State<'a> { if header.abi != Abi::Rust { self.word_nbsp("extern")?; - self.word_nbsp(&header.abi.to_string())?; + self.word_nbsp(header.abi.to_string())?; } self.s.word("fn") diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 361353c82e25c..b891cdefc2a41 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -493,6 +493,10 @@ impl LocalInternedString { symbol: Symbol::intern(self.string) } } + + pub fn get(&self) -> &'static str { + self.string + } } impl ::std::convert::AsRef for LocalInternedString From 64cd645d14407d312c7ed3a10efd9b3a99271884 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 29 Nov 2018 13:58:58 +1100 Subject: [PATCH 13/22] Split up `pretty_print` and `print`. `pretty_print` takes a `Token` and `match`es on it. But the particular `Token` kind is known at each call site, so this commit splits it into five functions: `pretty_print_eof`, `pretty_print_begin`, etc. This commit also does likewise with `print`, though there is one callsite for `print` where the `Token` kind isn't known, so a generic `print` has to stay (but it now just calls out to the various `print_*` functions). --- src/libsyntax/print/pp.rs | 302 +++++++++++++++++++------------------- 1 file changed, 152 insertions(+), 150 deletions(-) diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index b9addcaeb8edf..aaed56da29d5f 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -140,9 +140,9 @@ //! calculation, SCAN will write "infinity" to the size and let PRINT consume //! it. //! -//! In this implementation (following the paper, again) the SCAN process is -//! the method called `Printer::pretty_print`, and the 'PRINT' process is the method -//! called `Printer::print`. +//! In this implementation (following the paper, again) the SCAN process is the +//! methods called `Printer::pretty_print_*`, and the 'PRINT' process is the +//! method called `Printer::print`. use std::collections::VecDeque; use std::fmt; @@ -319,78 +319,77 @@ impl<'a> Printer<'a> { self.buf[self.right].token = t; } - pub fn pretty_print(&mut self, token: Token) -> io::Result<()> { - debug!("pp Vec<{},{}>", self.left, self.right); - match token { - Token::Eof => { - if !self.scan_stack.is_empty() { - self.check_stack(0); - self.advance_left()?; - } - self.indent(0); - Ok(()) - } - Token::Begin(b) => { - if self.scan_stack.is_empty() { - self.left_total = 1; - self.right_total = 1; - self.left = 0; - self.right = 0; - } else { - self.advance_right(); - } - debug!("pp Begin({})/buffer Vec<{},{}>", - b.offset, self.left, self.right); - self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; - let right = self.right; - self.scan_push(right); - Ok(()) - } - Token::End => { - if self.scan_stack.is_empty() { - debug!("pp End/print Vec<{},{}>", self.left, self.right); - self.print(token, 0) - } else { - debug!("pp End/buffer Vec<{},{}>", self.left, self.right); - self.advance_right(); - self.buf[self.right] = BufEntry { token: token, size: -1 }; - let right = self.right; - self.scan_push(right); - Ok(()) - } - } - Token::Break(b) => { - if self.scan_stack.is_empty() { - self.left_total = 1; - self.right_total = 1; - self.left = 0; - self.right = 0; - } else { - self.advance_right(); - } - debug!("pp Break({})/buffer Vec<{},{}>", - b.offset, self.left, self.right); - self.check_stack(0); - let right = self.right; - self.scan_push(right); - self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; - self.right_total += b.blank_space; - Ok(()) - } - Token::String(s, len) => { - if self.scan_stack.is_empty() { - debug!("pp String('{}')/print Vec<{},{}>", - s, self.left, self.right); - self.print(Token::String(s, len), len) - } else { - debug!("pp String('{}')/buffer Vec<{},{}>", - s, self.left, self.right); - self.advance_right(); - self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len }; - self.right_total += len; - self.check_stream() - } - } + fn pretty_print_eof(&mut self) -> io::Result<()> { + if !self.scan_stack.is_empty() { + self.check_stack(0); + self.advance_left()?; + } + self.indent(0); + Ok(()) + } + + fn pretty_print_begin(&mut self, b: BeginToken) -> io::Result<()> { + if self.scan_stack.is_empty() { + self.left_total = 1; + self.right_total = 1; + self.left = 0; + self.right = 0; + } else { + self.advance_right(); + } + debug!("pp Begin({})/buffer Vec<{},{}>", + b.offset, self.left, self.right); + self.buf[self.right] = BufEntry { token: Token::Begin(b), size: -self.right_total }; + let right = self.right; + self.scan_push(right); + Ok(()) + } + + fn pretty_print_end(&mut self) -> io::Result<()> { + if self.scan_stack.is_empty() { + debug!("pp End/print Vec<{},{}>", self.left, self.right); + self.print_end() + } else { + debug!("pp End/buffer Vec<{},{}>", self.left, self.right); + self.advance_right(); + self.buf[self.right] = BufEntry { token: Token::End, size: -1 }; + let right = self.right; + self.scan_push(right); + Ok(()) + } + } + + fn pretty_print_break(&mut self, b: BreakToken) -> io::Result<()> { + if self.scan_stack.is_empty() { + self.left_total = 1; + self.right_total = 1; + self.left = 0; + self.right = 0; + } else { + self.advance_right(); + } + debug!("pp Break({})/buffer Vec<{},{}>", + b.offset, self.left, self.right); + self.check_stack(0); + let right = self.right; + self.scan_push(right); + self.buf[self.right] = BufEntry { token: Token::Break(b), size: -self.right_total }; + self.right_total += b.blank_space; + Ok(()) + } + + fn pretty_print_string(&mut self, s: Cow<'static, str>, len: isize) -> io::Result<()> { + if self.scan_stack.is_empty() { + debug!("pp String('{}')/print Vec<{},{}>", + s, self.left, self.right); + self.print_string(s, len) + } else { + debug!("pp String('{}')/buffer Vec<{},{}>", + s, self.left, self.right); + self.advance_right(); + self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len }; + self.right_total += len; + self.check_stream() } } @@ -526,7 +525,70 @@ impl<'a> Printer<'a> { } } - pub fn print_str(&mut self, s: &str) -> io::Result<()> { + pub fn print_begin(&mut self, b: BeginToken, l: isize) -> io::Result<()> { + if l > self.space { + let col = self.margin - self.space + b.offset; + debug!("print Begin -> push broken block at col {}", col); + self.print_stack.push(PrintStackElem { + offset: col, + pbreak: PrintStackBreak::Broken(b.breaks) + }); + } else { + debug!("print Begin -> push fitting block"); + self.print_stack.push(PrintStackElem { + offset: 0, + pbreak: PrintStackBreak::Fits + }); + } + Ok(()) + } + + pub fn print_end(&mut self) -> io::Result<()> { + debug!("print End -> pop End"); + let print_stack = &mut self.print_stack; + assert!(!print_stack.is_empty()); + print_stack.pop().unwrap(); + Ok(()) + } + + pub fn print_break(&mut self, b: BreakToken, l: isize) -> io::Result<()> { + let top = self.get_top(); + match top.pbreak { + PrintStackBreak::Fits => { + debug!("print Break({}) in fitting block", b.blank_space); + self.space -= b.blank_space; + self.indent(b.blank_space); + Ok(()) + } + PrintStackBreak::Broken(Breaks::Consistent) => { + debug!("print Break({}+{}) in consistent block", + top.offset, b.offset); + let ret = self.print_newline(top.offset + b.offset); + self.space = self.margin - (top.offset + b.offset); + ret + } + PrintStackBreak::Broken(Breaks::Inconsistent) => { + if l > self.space { + debug!("print Break({}+{}) w/ newline in inconsistent", + top.offset, b.offset); + let ret = self.print_newline(top.offset + b.offset); + self.space = self.margin - (top.offset + b.offset); + ret + } else { + debug!("print Break({}) w/o newline in inconsistent", + b.blank_space); + self.indent(b.blank_space); + self.space -= b.blank_space; + Ok(()) + } + } + } + } + + pub fn print_string(&mut self, s: Cow<'static, str>, len: isize) -> io::Result<()> { + debug!("print String({})", s); + // assert!(len <= space); + self.space -= len; while self.pending_indentation > 0 { write!(self.out, " ")?; self.pending_indentation -= 1; @@ -542,74 +604,14 @@ impl<'a> Printer<'a> { self.right, 6)); match token { - Token::Begin(b) => { - if l > self.space { - let col = self.margin - self.space + b.offset; - debug!("print Begin -> push broken block at col {}", col); - self.print_stack.push(PrintStackElem { - offset: col, - pbreak: PrintStackBreak::Broken(b.breaks) - }); - } else { - debug!("print Begin -> push fitting block"); - self.print_stack.push(PrintStackElem { - offset: 0, - pbreak: PrintStackBreak::Fits - }); - } - Ok(()) - } - Token::End => { - debug!("print End -> pop End"); - let print_stack = &mut self.print_stack; - assert!(!print_stack.is_empty()); - print_stack.pop().unwrap(); - Ok(()) - } - Token::Break(b) => { - let top = self.get_top(); - match top.pbreak { - PrintStackBreak::Fits => { - debug!("print Break({}) in fitting block", b.blank_space); - self.space -= b.blank_space; - self.indent(b.blank_space); - Ok(()) - } - PrintStackBreak::Broken(Breaks::Consistent) => { - debug!("print Break({}+{}) in consistent block", - top.offset, b.offset); - let ret = self.print_newline(top.offset + b.offset); - self.space = self.margin - (top.offset + b.offset); - ret - } - PrintStackBreak::Broken(Breaks::Inconsistent) => { - if l > self.space { - debug!("print Break({}+{}) w/ newline in inconsistent", - top.offset, b.offset); - let ret = self.print_newline(top.offset + b.offset); - self.space = self.margin - (top.offset + b.offset); - ret - } else { - debug!("print Break({}) w/o newline in inconsistent", - b.blank_space); - self.indent(b.blank_space); - self.space -= b.blank_space; - Ok(()) - } - } - } - } - Token::String(ref s, len) => { - debug!("print String({})", s); - assert_eq!(l, len); - // assert!(l <= space); - self.space -= len; - self.print_str(s) - } - Token::Eof => { - // Eof should never get here. - panic!(); + Token::Begin(b) => self.print_begin(b, l), + Token::End => self.print_end(), + Token::Break(b) => self.print_break(b, l), + Token::String(s, len) => { + assert_eq!(len, l); + self.print_string(s, len) } + Token::Eof => panic!(), // Eof should never get here. } } @@ -617,10 +619,10 @@ impl<'a> Printer<'a> { /// "raw box" pub fn rbox(&mut self, indent: usize, b: Breaks) -> io::Result<()> { - self.pretty_print(Token::Begin(BeginToken { + self.pretty_print_begin(BeginToken { offset: indent as isize, breaks: b - })) + }) } /// Inconsistent breaking box @@ -634,24 +636,24 @@ impl<'a> Printer<'a> { } pub fn break_offset(&mut self, n: usize, off: isize) -> io::Result<()> { - self.pretty_print(Token::Break(BreakToken { + self.pretty_print_break(BreakToken { offset: off, blank_space: n as isize - })) + }) } pub fn end(&mut self) -> io::Result<()> { - self.pretty_print(Token::End) + self.pretty_print_end() } pub fn eof(&mut self) -> io::Result<()> { - self.pretty_print(Token::Eof) + self.pretty_print_eof() } pub fn word>>(&mut self, wrd: S) -> io::Result<()> { let s = wrd.into(); let len = s.len() as isize; - self.pretty_print(Token::String(s, len)) + self.pretty_print_string(s, len) } fn spaces(&mut self, n: usize) -> io::Result<()> { From 71f643e5bf98427dc91886365ded0936b1f68b60 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Thu, 29 Nov 2018 08:44:44 +0900 Subject: [PATCH 14/22] Remove not used option `mir_stats` has not been used since 2b32cb90c72d90c722d56324ca0ea9f748ebf4e1. --- src/librustc/session/config.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 3fd22793a08a0..480d4a8e48f0e 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1286,8 +1286,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "print some performance-related statistics"), hir_stats: bool = (false, parse_bool, [UNTRACKED], "print some statistics about AST and HIR"), - mir_stats: bool = (false, parse_bool, [UNTRACKED], - "print some statistics about MIR"), always_encode_mir: bool = (false, parse_bool, [TRACKED], "encode MIR of all functions into the crate metadata"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], From 2a91bbac5d04273b217170f4ad5eebe02ffcb1af Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Thu, 29 Nov 2018 08:09:28 -0500 Subject: [PATCH 15/22] Rename conversion util; remove duplicate util in librustc_codegen_llvm. --- src/librustc_codegen_llvm/back/write.rs | 10 +++++----- src/librustc_codegen_llvm/debuginfo/metadata.rs | 4 ++-- src/librustc_codegen_llvm/llvm/archive_ro.rs | 16 ++-------------- src/librustc_codegen_llvm/metadata.rs | 4 ++-- src/librustc_fs_util/lib.rs | 6 +++--- 5 files changed, 14 insertions(+), 26 deletions(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 7945d381760a1..4eb920324bd00 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -23,7 +23,7 @@ use llvm_util; use ModuleLlvm; use rustc_codegen_ssa::{ModuleCodegen, CompiledModule}; use rustc::util::common::time_ext; -use rustc_fs_util::{path2cstr, link_or_copy}; +use rustc_fs_util::{path_to_c_string, link_or_copy}; use rustc_data_structures::small_c_str::SmallCStr; use errors::{self, Handler, FatalError}; use type_::Type; @@ -80,7 +80,7 @@ pub fn write_output_file( output: &Path, file_type: llvm::FileType) -> Result<(), FatalError> { unsafe { - let output_c = path2cstr(output); + let output_c = path_to_c_string(output); let result = llvm::LLVMRustWriteOutputFile(target, pm, m, output_c.as_ptr(), file_type); if result.into_result().is_err() { let msg = format!("could not write output to {}", output.display()); @@ -211,7 +211,7 @@ pub(crate) fn save_temp_bitcode( let ext = format!("{}.bc", name); let cgu = Some(&module.name[..]); let path = cgcx.output_filenames.temp_path_ext(&ext, cgu); - let cstr = path2cstr(&path); + let cstr = path_to_c_string(&path); let llmod = module.module_llvm.llmod(); llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr()); } @@ -324,7 +324,7 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext, if config.emit_no_opt_bc { let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name); - let out = path2cstr(&out); + let out = path_to_c_string(&out); llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); } @@ -530,7 +530,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, || -> Result<(), FatalError> { if config.emit_ir { let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); - let out = path2cstr(&out); + let out = path_to_c_string(&out); extern "C" fn demangle_callback(input_ptr: *const c_char, input_len: size_t, diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 81f2769800d2f..47e92fbe87d31 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -39,7 +39,7 @@ use rustc::ty::layout::{self, Align, HasDataLayout, Integer, IntegerExt, LayoutO PrimitiveExt, Size, TyLayout}; use rustc::session::config; use rustc::util::nodemap::FxHashMap; -use rustc_fs_util::path2cstr; +use rustc_fs_util::path_to_c_string; use rustc_data_structures::small_c_str::SmallCStr; use libc::{c_uint, c_longlong}; @@ -892,7 +892,7 @@ pub fn compile_unit_metadata(tcx: TyCtxt, }; fn path_to_mdstring(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value { - let path_str = path2cstr(path); + let path_str = path_to_c_string(path); unsafe { llvm::LLVMMDStringInContext(llcx, path_str.as_ptr(), diff --git a/src/librustc_codegen_llvm/llvm/archive_ro.rs b/src/librustc_codegen_llvm/llvm/archive_ro.rs index 2a77f256e3a0c..d5c73fecf814a 100644 --- a/src/librustc_codegen_llvm/llvm/archive_ro.rs +++ b/src/librustc_codegen_llvm/llvm/archive_ro.rs @@ -10,10 +10,10 @@ //! A wrapper around LLVM's archive (.a) code -use std::ffi::CString; use std::path::Path; use std::slice; use std::str; +use rustc_fs_util::path_to_c_string; pub struct ArchiveRO { pub raw: &'static mut super::Archive, @@ -38,24 +38,12 @@ impl ArchiveRO { /// raised. pub fn open(dst: &Path) -> Result { return unsafe { - let s = path2cstr(dst); + let s = path_to_c_string(dst); let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| { super::last_error().unwrap_or_else(|| "failed to open archive".to_owned()) })?; Ok(ArchiveRO { raw: ar }) }; - - #[cfg(unix)] - fn path2cstr(p: &Path) -> CString { - use std::os::unix::prelude::*; - use std::ffi::OsStr; - let p: &OsStr = p.as_ref(); - CString::new(p.as_bytes()).unwrap() - } - #[cfg(windows)] - fn path2cstr(p: &Path) -> CString { - CString::new(p.to_str().unwrap()).unwrap() - } } pub fn iter(&self) -> Iter { diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs index 7752465d885bb..5605f64c2e72c 100644 --- a/src/librustc_codegen_llvm/metadata.rs +++ b/src/librustc_codegen_llvm/metadata.rs @@ -18,7 +18,7 @@ use rustc_data_structures::owning_ref::OwningRef; use std::path::Path; use std::ptr; use std::slice; -use rustc_fs_util::path2cstr; +use rustc_fs_util::path_to_c_string; pub use rustc_data_structures::sync::MetadataRef; @@ -57,7 +57,7 @@ impl MetadataLoader for LlvmMetadataLoader { filename: &Path) -> Result { unsafe { - let buf = path2cstr(filename); + let buf = path_to_c_string(filename); let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr()) .ok_or_else(|| format!("error reading library: '{}'", filename.display()))?; let of = ObjectFile::new(mb) diff --git a/src/librustc_fs_util/lib.rs b/src/librustc_fs_util/lib.rs index ffe420b109d3e..1b0ff4f861c7b 100644 --- a/src/librustc_fs_util/lib.rs +++ b/src/librustc_fs_util/lib.rs @@ -116,13 +116,13 @@ pub fn rename_or_copy_remove, Q: AsRef>(p: P, } #[cfg(unix)] -pub fn path2cstr(p: &Path) -> CString { - use std::os::unix::prelude::*; +pub fn path_to_c_string(p: &Path) -> CString { + use std::os::unix::ffi::OsStrExt; use std::ffi::OsStr; let p: &OsStr = p.as_ref(); CString::new(p.as_bytes()).unwrap() } #[cfg(windows)] -pub fn path2cstr(p: &Path) -> CString { +pub fn path_to_c_string(p: &Path) -> CString { CString::new(p.to_str().unwrap()).unwrap() } From 0124341935787d1d6aa5eace209c9bb7968f35db Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 29 Nov 2018 20:40:43 +0100 Subject: [PATCH 16/22] Only consider stem when extension is exe. This commit modifies linker flavor inference to only remove the extension to the linker when performing inference if that extension is a 'exe'. --- src/librustc_codegen_ssa/back/link.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index b0575b841d5d5..24a70dc797771 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -161,7 +161,11 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { LinkerFlavor::Lld(_) => "lld", }), flavor)), (Some(linker), None) => { - let stem = linker.file_stem().and_then(|stem| stem.to_str()).unwrap_or_else(|| { + let stem = if linker.extension().and_then(|ext| ext.to_str()) == Some("exe") { + linker.file_stem().and_then(|stem| stem.to_str()) + } else { + linker.to_str() + }.unwrap_or_else(|| { sess.fatal("couldn't extract file stem from specified linker"); }).to_owned(); From 4cce4ffdefd23b4113ca2f54128b88b70fd31dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 29 Nov 2018 21:13:04 +0100 Subject: [PATCH 17/22] Add inline attributes and add unit to CommonTypes --- src/libcore/num/mod.rs | 1 + src/librustc/infer/at.rs | 1 + src/librustc/infer/resolve.rs | 1 + src/librustc/traits/mod.rs | 1 + src/librustc/ty/context.rs | 39 ++++++++++++++++++++++++++++++++++- src/librustc/ty/fold.rs | 1 + src/librustc/ty/mod.rs | 5 +++++ src/librustc/ty/sty.rs | 8 +++++++ src/libsyntax_pos/lib.rs | 1 + 9 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 57b5903c9d39f..c87dcbe500cba 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -3614,6 +3614,7 @@ assert_eq!(3", stringify!($SelfT), ".checked_next_power_of_two(), Some(4)); assert_eq!(", stringify!($SelfT), "::max_value().checked_next_power_of_two(), None);", $EndFeature, " ```"), + #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn checked_next_power_of_two(self) -> Option { self.one_less_than_next_power_of_two().checked_add(1) diff --git a/src/librustc/infer/at.rs b/src/librustc/infer/at.rs index 0e4c94aaaf394..70e922c6676e1 100644 --- a/src/librustc/infer/at.rs +++ b/src/librustc/infer/at.rs @@ -52,6 +52,7 @@ pub struct Trace<'a, 'gcx: 'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { + #[inline] pub fn at(&'a self, cause: &'a ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>) diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs index a0c310ac2761e..7a1ee85acd42c 100644 --- a/src/librustc/infer/resolve.rs +++ b/src/librustc/infer/resolve.rs @@ -25,6 +25,7 @@ pub struct OpportunisticTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> OpportunisticTypeResolver<'a, 'gcx, 'tcx> { + #[inline] pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self { OpportunisticTypeResolver { infcx } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index e582a9020464d..ab2fa68ab5f89 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -1052,6 +1052,7 @@ impl<'tcx,O> Obligation<'tcx,O> { } impl<'tcx> ObligationCause<'tcx> { + #[inline] pub fn new(span: Span, body_id: ast::NodeId, code: ObligationCauseCode<'tcx>) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 79a4638d6f7d9..ebcf83cb8ecad 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -155,6 +155,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { } /// Intern a type + #[inline(never)] fn intern_ty( local: &CtxtInterners<'tcx>, global: &CtxtInterners<'gcx>, @@ -216,6 +217,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { } pub struct CommonTypes<'tcx> { + pub unit: Ty<'tcx>, pub bool: Ty<'tcx>, pub char: Ty<'tcx>, pub isize: Ty<'tcx>, @@ -832,7 +834,9 @@ impl<'tcx> CommonTypes<'tcx> { interners.region.borrow_mut().insert(Interned(r)); &*r }; + CommonTypes { + unit: mk(Tuple(List::empty())), bool: mk(Bool), char: mk(Char), never: mk(Never), @@ -885,6 +889,7 @@ pub struct TyCtxt<'a, 'gcx: 'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> Deref for TyCtxt<'a, 'gcx, 'tcx> { type Target = &'a GlobalCtxt<'gcx>; + #[inline(always)] fn deref(&self) -> &Self::Target { &self.gcx } @@ -2515,6 +2520,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_fn_ptr(converted_sig) } + #[inline] pub fn mk_ty(&self, st: TyKind<'tcx>) -> Ty<'tcx> { CtxtInterners::intern_ty(&self.interners, &self.global_interners, st) } @@ -2548,19 +2554,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + #[inline] pub fn mk_str(self) -> Ty<'tcx> { self.mk_ty(Str) } + #[inline] pub fn mk_static_str(self) -> Ty<'tcx> { self.mk_imm_ref(self.types.re_static, self.mk_str()) } + #[inline] pub fn mk_adt(self, def: &'tcx AdtDef, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { // take a copy of substs so that we own the vectors inside self.mk_ty(Adt(def, substs)) } + #[inline] pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> { self.mk_ty(Foreign(def_id)) } @@ -2584,42 +2594,52 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_ty(Adt(adt_def, substs)) } + #[inline] pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { self.mk_ty(RawPtr(tm)) } + #[inline] pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { self.mk_ty(Ref(r, tm.ty, tm.mutbl)) } + #[inline] pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutMutable}) } + #[inline] pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutImmutable}) } + #[inline] pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutMutable}) } + #[inline] pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutImmutable}) } + #[inline] pub fn mk_nil_ptr(self) -> Ty<'tcx> { self.mk_imm_ptr(self.mk_unit()) } + #[inline] pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { self.mk_ty(Array(ty, ty::Const::from_usize(self, n))) } + #[inline] pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> { self.mk_ty(Slice(ty)) } + #[inline] pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> { self.mk_ty(Tuple(self.intern_type_list(ts))) } @@ -2628,10 +2648,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(ts)))) } + #[inline] pub fn mk_unit(self) -> Ty<'tcx> { - self.intern_tup(&[]) + self.types.unit } + #[inline] pub fn mk_diverging_default(self) -> Ty<'tcx> { if self.features().never_type { self.types.never @@ -2640,19 +2662,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + #[inline] pub fn mk_bool(self) -> Ty<'tcx> { self.mk_ty(Bool) } + #[inline] pub fn mk_fn_def(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { self.mk_ty(FnDef(def_id, substs)) } + #[inline] pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { self.mk_ty(FnPtr(fty)) } + #[inline] pub fn mk_dynamic( self, obj: ty::Binder<&'tcx List>>, @@ -2661,6 +2687,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_ty(Dynamic(obj, reg)) } + #[inline] pub fn mk_projection(self, item_def_id: DefId, substs: &'tcx Substs<'tcx>) @@ -2671,11 +2698,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { })) } + #[inline] pub fn mk_closure(self, closure_id: DefId, closure_substs: ClosureSubsts<'tcx>) -> Ty<'tcx> { self.mk_ty(Closure(closure_id, closure_substs)) } + #[inline] pub fn mk_generator(self, id: DefId, generator_substs: GeneratorSubsts<'tcx>, @@ -2684,32 +2713,39 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_ty(Generator(id, generator_substs, movability)) } + #[inline] pub fn mk_generator_witness(self, types: ty::Binder<&'tcx List>>) -> Ty<'tcx> { self.mk_ty(GeneratorWitness(types)) } + #[inline] pub fn mk_var(self, v: TyVid) -> Ty<'tcx> { self.mk_infer(TyVar(v)) } + #[inline] pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> { self.mk_infer(IntVar(v)) } + #[inline] pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> { self.mk_infer(FloatVar(v)) } + #[inline] pub fn mk_infer(self, it: InferTy) -> Ty<'tcx> { self.mk_ty(Infer(it)) } + #[inline] pub fn mk_ty_param(self, index: u32, name: InternedString) -> Ty<'tcx> { self.mk_ty(Param(ParamTy { idx: index, name: name })) } + #[inline] pub fn mk_self_type(self) -> Ty<'tcx> { self.mk_ty_param(0, keywords::SelfType.name().as_interned_str()) } @@ -2723,6 +2759,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + #[inline] pub fn mk_opaque(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { self.mk_ty(Opaque(def_id, substs)) } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 6f0e8d4f02680..1bc7d64879267 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -374,6 +374,7 @@ pub struct RegionFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> RegionFolder<'a, 'gcx, 'tcx> { + #[inline] pub fn new( tcx: TyCtxt<'a, 'gcx, 'tcx>, skipped_regions: &'a mut bool, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index b371f4532e5fa..4633ab1166347 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1275,6 +1275,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { self.skip_binder().projection_ty.item_def_id } + #[inline] pub fn to_poly_trait_ref(&self, tcx: TyCtxt<'_, '_, '_>) -> PolyTraitRef<'tcx> { // Note: unlike with `TraitRef::to_poly_trait_ref()`, // `self.0.trait_ref` is permitted to have escaping regions. @@ -1633,6 +1634,7 @@ impl<'tcx> ParamEnv<'tcx> { /// there are no where clauses in scope. Hidden types (like `impl /// Trait`) are left hidden, so this is suitable for ordinary /// type-checking. + #[inline] pub fn empty() -> Self { Self::new(List::empty(), Reveal::UserFacing) } @@ -1644,11 +1646,13 @@ impl<'tcx> ParamEnv<'tcx> { /// /// N.B. If you want to have predicates in scope, use `ParamEnv::new`, /// or invoke `param_env.with_reveal_all()`. + #[inline] pub fn reveal_all() -> Self { Self::new(List::empty(), Reveal::All) } /// Construct a trait environment with the given set of predicates. + #[inline] pub fn new(caller_bounds: &'tcx List>, reveal: Reveal) -> Self { @@ -2148,6 +2152,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } + #[inline] pub fn variant_descr(&self) -> &'static str { match self.adt_kind() { AdtKind::Struct => "struct", diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index a18e3a275467d..1416cb17feaed 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -667,6 +667,7 @@ impl<'tcx> TraitRef<'tcx> { } } + #[inline] pub fn self_ty(&self) -> Ty<'tcx> { self.substs.type_at(0) } @@ -978,15 +979,18 @@ impl<'tcx> FnSig<'tcx> { pub type PolyFnSig<'tcx> = Binder>; impl<'tcx> PolyFnSig<'tcx> { + #[inline] pub fn inputs(&self) -> Binder<&'tcx [Ty<'tcx>]> { self.map_bound_ref(|fn_sig| fn_sig.inputs()) } + #[inline] pub fn input(&self, index: usize) -> ty::Binder> { self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) } pub fn inputs_and_output(&self) -> ty::Binder<&'tcx List>> { self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output) } + #[inline] pub fn output(&self) -> ty::Binder> { self.map_bound_ref(|fn_sig| fn_sig.output()) } @@ -1548,6 +1552,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } + #[inline] pub fn is_ty_var(&self) -> bool { match self.sty { Infer(TyVar(_)) => true, @@ -1732,6 +1737,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } + #[inline] pub fn is_integral(&self) -> bool { match self.sty { Infer(IntVar(_)) | Int(_) | Uint(_) => true, @@ -1762,6 +1768,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } + #[inline] pub fn is_fp(&self) -> bool { match self.sty { Infer(FloatVar(_)) | Float(_) => true, @@ -1845,6 +1852,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } + #[inline] pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> { match self.sty { Adt(adt, _) => Some(adt), diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 65f6d27239b83..34fb71e4ddf68 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -587,6 +587,7 @@ impl fmt::Debug for SpanData { } impl MultiSpan { + #[inline] pub fn new() -> MultiSpan { MultiSpan { primary_spans: vec![], From 225140ed216d7395530b2e4597fb224305e6375b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 29 Nov 2018 15:02:06 -0800 Subject: [PATCH 18/22] Optimize local linkchecker program I noticed on a [recent build][1] that the linkchecker stage of CI took a whopping 15 minutes of CI time for something that should be near instantaneous. Some local profiling showed some very hot functions and clones which were pretty easy to remove, and now instead of running in minutes locally it runs in seconds. [1]: https://ci.appveyor.com/project/rust-lang/rust/build/job/kptifw1kb1nm4xuu --- src/tools/linkchecker/main.rs | 38 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index ca7e0224dc328..11c83819eaa93 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -24,12 +24,12 @@ //! A few whitelisted exceptions are allowed as there's known bugs in rustdoc, //! but this should catch the majority of "broken link" cases. +use std::collections::hash_map::Entry; +use std::collections::{HashMap, HashSet}; use std::env; -use std::fs::File; -use std::io::prelude::*; +use std::fs; use std::path::{Path, PathBuf, Component}; -use std::collections::{HashMap, HashSet}; -use std::collections::hash_map::Entry; +use std::rc::Rc; use Redirect::*; @@ -63,7 +63,7 @@ enum Redirect { } struct FileEntry { - source: String, + source: Rc, ids: HashSet, } @@ -113,7 +113,7 @@ fn walk(cache: &mut Cache, root: &Path, dir: &Path, errors: &mut bool) { let entry = cache.get_mut(&pretty_path).unwrap(); // we don't need the source anymore, // so drop to reduce memory-usage - entry.source = String::new(); + entry.source = Rc::new(String::new()); } } } @@ -287,24 +287,24 @@ fn load_file(cache: &mut Cache, root: &Path, file: &Path, redirect: Redirect) - -> Result<(PathBuf, String), LoadError> { - let mut contents = String::new(); + -> Result<(PathBuf, Rc), LoadError> { let pretty_file = PathBuf::from(file.strip_prefix(root).unwrap_or(&file)); - let maybe_redirect = match cache.entry(pretty_file.clone()) { + let (maybe_redirect, contents) = match cache.entry(pretty_file.clone()) { Entry::Occupied(entry) => { - contents = entry.get().source.clone(); - None + (None, entry.get().source.clone()) } Entry::Vacant(entry) => { - let mut fp = File::open(file).map_err(|err| { - if let FromRedirect(true) = redirect { - LoadError::BrokenRedirect(file.to_path_buf(), err) - } else { - LoadError::IOError(err) + let contents = match fs::read_to_string(file) { + Ok(s) => Rc::new(s), + Err(err) => { + return Err(if let FromRedirect(true) = redirect { + LoadError::BrokenRedirect(file.to_path_buf(), err) + } else { + LoadError::IOError(err) + }) } - })?; - fp.read_to_string(&mut contents).map_err(|err| LoadError::IOError(err))?; + }; let maybe = maybe_redirect(&contents); if maybe.is_some() { @@ -317,7 +317,7 @@ fn load_file(cache: &mut Cache, ids: HashSet::new(), }); } - maybe + (maybe, contents) } }; match maybe_redirect.map(|url| file.parent().unwrap().join(url)) { From a0fec9488ed6f1d7b751f7e45b9919f908b560a1 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Fri, 30 Nov 2018 02:04:10 +0000 Subject: [PATCH 19/22] Fix panic with outlives in existential type Don't panic in determining the privacy of a type if a lifetime outlives generic exists in an existential type. --- src/librustc_privacy/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index fbd6f6edd31c5..6d9abbf5af2ac 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -969,7 +969,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { Some(poly_projection_predicate.skip_binder() .projection_ty.trait_ref(self.tcx)) } - ty::Predicate::TypeOutlives(..) => None, + ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => None, _ => bug!("unexpected predicate: {:?}", predicate), }; if let Some(trait_ref) = trait_ref { From 113ae0fa8db1dff4830edf7c1eb72a48a9f77859 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 30 Nov 2018 08:08:31 +0100 Subject: [PATCH 20/22] update miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index fb72348e5f4bd..8d2bc97d7c392 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit fb72348e5f4bd396d91c808b1e404f233908fb05 +Subproject commit 8d2bc97d7c3927cc8cb53afeaf97bd832be2b7c2 From 4c34404940e616e1ccd5520e0bf758853c2511c3 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Fri, 30 Nov 2018 09:29:36 -0500 Subject: [PATCH 21/22] update nomicon --- src/doc/nomicon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/nomicon b/src/doc/nomicon index f8a4e96feb2e5..b7eb4a087207a 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit f8a4e96feb2e5a6ed1ef170ad40e3509a7755cb4 +Subproject commit b7eb4a087207af2405c0669fa577f8545b894c66 From 934871aa794e87000b1255257a33b5d8b176aa40 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Fri, 30 Nov 2018 09:36:49 -0500 Subject: [PATCH 22/22] Add the edition guide to doc.rust-lang.org --- .gitmodules | 3 +++ src/bootstrap/doc.rs | 1 + src/doc/edition-guide | 1 + 3 files changed, 5 insertions(+) create mode 160000 src/doc/edition-guide diff --git a/.gitmodules b/.gitmodules index 6b2714edd4d12..4a136cff1cdf2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -65,3 +65,6 @@ [submodule "src/doc/rustc-guide"] path = src/doc/rustc-guide url = https://github.com/rust-lang/rustc-guide.git +[submodule "src/doc/edition-guide"] + path = src/doc/edition-guide + url = https://github.com/rust-lang-nursery/edition-guide diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index f9b19ffb10d69..18a2b950e5966 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -70,6 +70,7 @@ macro_rules! book { book!( Nomicon, "src/doc/nomicon", "nomicon"; Reference, "src/doc/reference", "reference"; + EditionGuide, "src/doc/edition-guide", "edition-guide"; RustdocBook, "src/doc/rustdoc", "rustdoc"; RustcBook, "src/doc/rustc", "rustc"; RustByExample, "src/doc/rust-by-example", "rust-by-example"; diff --git a/src/doc/edition-guide b/src/doc/edition-guide new file mode 160000 index 0000000000000..ad895867b6751 --- /dev/null +++ b/src/doc/edition-guide @@ -0,0 +1 @@ +Subproject commit ad895867b675199a7f597ce7045a56875a7e516a