diff --git a/src/Cargo.lock b/src/Cargo.lock index 0c08e35c18df3..64e18899c9d05 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2278,12 +2278,14 @@ version = "0.0.0" dependencies = [ "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", "serialize 0.0.0", + "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_ext 0.0.0", "syntax_pos 0.0.0", diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index deca9591fbd5c..f9b455fe796d1 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -69,7 +69,7 @@ struct LeafNode { /// This node's index into the parent node's `edges` array. /// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`. - /// This is only guaranteed to be initialized when `parent` is nonnull. + /// This is only guaranteed to be initialized when `parent` is non-null. parent_idx: MaybeUninit, /// The number of keys and values this node stores. diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 837770feecef5..e87bf78561c61 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -44,7 +44,7 @@ use boxed::Box; /// This enables you to use capacity growing logic catch the overflows in your length /// that might occur with zero-sized types. /// -/// However this means that you need to be careful when roundtripping this type +/// However this means that you need to be careful when round-tripping this type /// with a `Box<[T]>`: `cap()` won't yield the len. However `with_capacity`, /// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity /// field. This allows zero-sized types to not be special-cased by consumers of diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 2beb3240aaca0..8d009101ce7da 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -618,7 +618,15 @@ impl String { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf16(v: &[u16]) -> Result { - decode_utf16(v.iter().cloned()).collect::>().map_err(|_| FromUtf16Error(())) + let mut ret = String::with_capacity(v.len()); + for c in decode_utf16(v.iter().cloned()) { + if let Ok(c) = c { + ret.push(c); + } else { + return Err(FromUtf16Error(())); + } + } + Ok(ret) } /// Decode a UTF-16 encoded slice `v` into a `String`, replacing diff --git a/src/libcore/benches/char/methods.rs b/src/libcore/benches/char/methods.rs new file mode 100644 index 0000000000000..faf820d871cfa --- /dev/null +++ b/src/libcore/benches/char/methods.rs @@ -0,0 +1,42 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use test::Bencher; + +const CHARS: [char; 9] = ['0', 'x', '2', '5', 'A', 'f', '7', '8', '9']; +const RADIX: [u32; 5] = [2, 8, 10, 16, 32]; + +#[bench] +fn bench_to_digit_radix_2(b: &mut Bencher) { + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(2)).min()) +} + +#[bench] +fn bench_to_digit_radix_10(b: &mut Bencher) { + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(10)).min()) +} + +#[bench] +fn bench_to_digit_radix_16(b: &mut Bencher) { + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(16)).min()) +} + +#[bench] +fn bench_to_digit_radix_36(b: &mut Bencher) { + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(36)).min()) +} + +#[bench] +fn bench_to_digit_radix_var(b: &mut Bencher) { + b.iter(|| CHARS.iter().cycle() + .zip(RADIX.iter().cycle()) + .take(10_000) + .map(|(c, radix)| c.to_digit(*radix)).min()) +} diff --git a/src/libcore/benches/char/mod.rs b/src/libcore/benches/char/mod.rs new file mode 100644 index 0000000000000..a656e82cb61e6 --- /dev/null +++ b/src/libcore/benches/char/mod.rs @@ -0,0 +1,11 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod methods; diff --git a/src/libcore/benches/lib.rs b/src/libcore/benches/lib.rs index ced77d779182a..d44f1577d56b0 100644 --- a/src/libcore/benches/lib.rs +++ b/src/libcore/benches/lib.rs @@ -15,6 +15,7 @@ extern crate core; extern crate test; mod any; +mod char; mod hash; mod iter; mod num; diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index 35181afea3da6..d6fcff644acf6 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -121,15 +121,24 @@ impl char { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn to_digit(self, radix: u32) -> Option { - if radix > 36 { - panic!("to_digit: radix is too high (maximum 36)"); - } - let val = match self { - '0' ..= '9' => self as u32 - '0' as u32, - 'a' ..= 'z' => self as u32 - 'a' as u32 + 10, - 'A' ..= 'Z' => self as u32 - 'A' as u32 + 10, - _ => return None, + assert!(radix <= 36, "to_digit: radix is too high (maximum 36)"); + + // the code is split up here to improve execution speed for cases where + // the `radix` is constant and 10 or smaller + let val = if radix <= 10 { + match self { + '0' ..= '9' => self as u32 - '0' as u32, + _ => return None, + } + } else { + match self { + '0'..='9' => self as u32 - '0' as u32, + 'a'..='z' => self as u32 - 'a' as u32 + 10, + 'A'..='Z' => self as u32 - 'A' as u32 + 10, + _ => return None, + } }; + if val < radix { Some(val) } else { None } } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 7ed6e4a8f51eb..16f0299c18b9a 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -672,6 +672,9 @@ extern "rust-intrinsic" { /// /// More specifically, this is the offset in bytes between successive /// items of the same type, including alignment padding. + /// + /// The stabilized version of this intrinsic is + /// [`std::mem::size_of`](../../std/mem/fn.size_of.html). pub fn size_of() -> usize; /// Moves a value to an uninitialized memory location. @@ -714,6 +717,10 @@ extern "rust-intrinsic" { /// initialize memory previous set to the result of `uninit`. pub fn uninit() -> T; + /// Moves a value out of scope without running drop glue. + #[cfg(not(stage0))] + pub fn forget(_: T); + /// Reinterprets the bits of a value of one type as another type. /// /// Both types must have the same size. Neither the original, nor the result, diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 5872ac815c259..a02b5bc87c5e9 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -106,6 +106,7 @@ #![feature(staged_api)] #![feature(stmt_expr_attributes)] #![feature(unboxed_closures)] +#![feature(unsized_locals)] #![feature(untagged_unions)] #![feature(unwind_attributes)] #![feature(doc_alias)] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 56146a9a5fd39..d8eec2bd9a6a2 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -143,6 +143,19 @@ pub fn forget(t: T) { ManuallyDrop::new(t); } +/// Like [`forget`], but also accepts unsized values. +/// +/// This function is just a shim intended to be removed when the `unsized_locals` feature gets +/// stabilized. +/// +/// [`forget`]: fn.forget.html +#[inline] +#[cfg(not(stage0))] +#[unstable(feature = "forget_unsized", issue = "0")] +pub fn forget_unsized(t: T) { + unsafe { intrinsics::forget(t) } +} + /// Returns the size of a type in bytes. /// /// More specifically, this is the offset in bytes between successive elements diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 577c823f9a060..d6c3996971a58 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -445,7 +445,7 @@ impl f32 { /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa. /// /// Rather than trying to preserve signaling-ness cross-platform, this - /// implementation favours preserving the exact bits. This means that + /// implementation favors preserving the exact bits. This means that /// any payloads encoded in NaNs will be preserved even if the result of /// this method is sent over the network from an x86 machine to a MIPS one. /// diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index c9fb22e0080dd..c0ce7255d6287 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -108,7 +108,7 @@ impl Drop for Waker { /// is ready to be run. /// /// This is similar to the `Waker` type, but cannot be sent across threads. -/// Task executors can use this type to implement more optimized singlethreaded wakeup +/// Task executors can use this type to implement more optimized single-threaded wakeup /// behavior. #[repr(transparent)] #[derive(Clone)] diff --git a/src/liblibc b/src/liblibc index 1844a772b6077..c75ca6465a139 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 1844a772b60771d0124a157019f627d60fea4e73 +Subproject commit c75ca6465a139704e00295be355b1f067af2f535 diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 1a2b16a4fed06..60b6a8bac41d3 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -535,7 +535,7 @@ impl TokenTree { } } -/// Prints token treee in a form convenient for debugging. +/// Prints token tree in a form convenient for debugging. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] impl fmt::Debug for TokenTree { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -730,7 +730,7 @@ impl fmt::Debug for Group { /// An `Punct` is an single punctuation character like `+`, `-` or `#`. /// -/// Multicharacter operators like `+=` are represented as two instances of `Punct` with different +/// Multi-character operators like `+=` are represented as two instances of `Punct` with different /// forms of `Spacing` returned. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] #[derive(Clone)] @@ -788,7 +788,7 @@ impl Punct { /// Returns the spacing of this punctuation character, indicating whether it's immediately /// followed by another `Punct` in the token stream, so they can potentially be combined into - /// a multicharacter operator (`Joint`), or it's followed by some other token or whitespace + /// a multi-character operator (`Joint`), or it's followed by some other token or whitespace /// (`Alone`) so the operator has certainly ended. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub fn spacing(&self) -> Spacing { @@ -947,7 +947,7 @@ macro_rules! suffixed_int_literals { /// This function will create an integer like `1u32` where the integer /// value specified is the first part of the token and the integral is /// also suffixed at the end. - /// Literals created from negative numbers may not survive rountrips through + /// Literals created from negative numbers may not survive round-trips through /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). /// /// Literals created through this method have the `Span::call_site()` @@ -1047,7 +1047,7 @@ impl Literal { /// Creates a new suffixed floating-point literal. /// - /// This consturctor will create a literal like `1.0f32` where the value + /// This constructor will create a literal like `1.0f32` where the value /// specified is the preceding part of the token and `f32` is the suffix of /// the token. This token will always be inferred to be an `f32` in the /// compiler. @@ -1096,7 +1096,7 @@ impl Literal { /// Creates a new suffixed floating-point literal. /// - /// This consturctor will create a literal like `1.0f64` where the value + /// This constructor will create a literal like `1.0f64` where the value /// specified is the preceding part of the token and `f64` is the suffix of /// the token. This token will always be inferred to be an `f64` in the /// compiler. diff --git a/src/librustc/dep_graph/cgu_reuse_tracker.rs b/src/librustc/dep_graph/cgu_reuse_tracker.rs index 99fc020bbe44f..0392d32989697 100644 --- a/src/librustc/dep_graph/cgu_reuse_tracker.rs +++ b/src/librustc/dep_graph/cgu_reuse_tracker.rs @@ -9,7 +9,7 @@ // except according to those terms. //! Some facilities for tracking how codegen-units are reused during incremental -//! compilition. This is used for incremental compiliation tests and debug +//! compilation. This is used for incremental compilation tests and debug //! output. use session::Session; diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 61996b5a8a75c..3ff2545f78dfa 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -63,7 +63,7 @@ use mir::interpret::GlobalId; use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; use hir::map::DefPathHash; -use hir::{HirId, ItemLocalId}; +use hir::HirId; use ich::{Fingerprint, StableHashingContext}; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; @@ -790,11 +790,11 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for HirId { fn to_fingerprint(&self, tcx: TyCtxt<'_, '_, '_>) -> Fingerprint { let HirId { owner, - local_id: ItemLocalId(local_id), + local_id, } = *self; let def_path_hash = tcx.def_path_hash(DefId::local(owner)); - let local_id = Fingerprint::from_smaller_hash(local_id as u64); + let local_id = Fingerprint::from_smaller_hash(local_id.as_u32().into()); def_path_hash.0.combine(local_id) } diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 5d9d4deb0abc9..e4c434b562ddc 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -36,7 +36,7 @@ pub enum NonMacroAttrKind { Tool, /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`). DeriveHelper, - /// Single-segment custom attriubte registered by a legacy plugin (`register_attribute`). + /// Single-segment custom attribute registered by a legacy plugin (`register_attribute`). LegacyPluginHelper, /// Single-segment custom attribute not registered in any way (`#[my_attr]`). Custom, diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index dcc0f8545e5d7..d9963f23a1593 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -49,7 +49,6 @@ use hir::map::{self, Map}; use super::itemlikevisit::DeepVisitor; use std::cmp; -use std::u32; #[derive(Copy, Clone)] pub enum FnKind<'a> { @@ -1152,8 +1151,8 @@ pub struct IdRange { impl IdRange { pub fn max() -> IdRange { IdRange { - min: NodeId::from_u32(u32::MAX), - max: NodeId::from_u32(u32::MIN), + min: NodeId::MAX, + max: NodeId::from_u32(0), } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index dd5d4b8f6afff..e532b50a28b6b 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -588,7 +588,7 @@ impl<'a> LoweringContext<'a> { *local_id_counter += 1; hir::HirId { owner: def_index, - local_id: hir::ItemLocalId(local_id), + local_id: hir::ItemLocalId::from_u32(local_id), } }) } @@ -616,7 +616,7 @@ impl<'a> LoweringContext<'a> { hir::HirId { owner: def_index, - local_id: hir::ItemLocalId(local_id), + local_id: hir::ItemLocalId::from_u32(local_id), } }) } diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index 896a6163eba64..ac4119dc372d3 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -101,7 +101,7 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> { if max != self.hir_ids_seen.len() - 1 { // Collect the missing ItemLocalIds let missing: Vec<_> = (0 .. max as u32 + 1) - .filter(|&i| !self.hir_ids_seen.contains_key(&ItemLocalId(i))) + .filter(|&i| !self.hir_ids_seen.contains_key(&ItemLocalId::from_u32(i))) .collect(); // Try to map those to something more useful @@ -110,7 +110,7 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> { for local_id in missing { let hir_id = HirId { owner: owner_def_index, - local_id: ItemLocalId(local_id as u32), + local_id: ItemLocalId::from_u32(local_id), }; trace!("missing hir id {:#?}", hir_id); @@ -124,7 +124,7 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> { .enumerate() .find(|&(_, &entry)| hir_id == entry) .expect("no node_to_hir_id entry"); - let node_id = NodeId::new(node_id); + let node_id = NodeId::from_usize(node_id); missing_items.push(format!("[local_id: {}, node:{}]", local_id, self.hir_map.node_to_string(node_id))); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index f57e3ff913b38..e28193be34a44 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -27,7 +27,7 @@ use syntax_pos::{Span, DUMMY_SP, symbol::InternedString}; use syntax::source_map::{self, Spanned}; use rustc_target::spec::abi::Abi; use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect}; -use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem}; +use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy}; use syntax::attr::InlineAttr; use syntax::ext::hygiene::SyntaxContext; use syntax::ptr::P; @@ -37,7 +37,6 @@ use syntax::util::parser::ExprPrecedence; use ty::AdtKind; use ty::query::Providers; -use rustc_data_structures::indexed_vec; use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync, scope}; use rustc_data_structures::thin_vec::ThinVec; @@ -58,7 +57,6 @@ macro_rules! hir_vec { ($($x:expr),*) => ( $crate::hir::HirVec::from(vec![$($x),*]) ); - ($($x:expr,)*) => (hir_vec![$($x),*]) } pub mod check_attr; @@ -121,40 +119,28 @@ impl serialize::UseSpecializedDecodable for HirId { } } - -/// An `ItemLocalId` uniquely identifies something within a given "item-like", -/// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no -/// guarantee that the numerical value of a given `ItemLocalId` corresponds to -/// the node's position within the owning item in any way, but there is a -/// guarantee that the `LocalItemId`s within an owner occupy a dense range of -/// integers starting at zero, so a mapping that maps all or most nodes within -/// an "item-like" to something else can be implement by a `Vec` instead of a -/// tree or hash map. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, - RustcEncodable, RustcDecodable)] -pub struct ItemLocalId(pub u32); - -impl ItemLocalId { - pub fn as_usize(&self) -> usize { - self.0 as usize +// hack to ensure that we don't try to access the private parts of `ItemLocalId` in this module +mod item_local_id_inner { + use rustc_data_structures::indexed_vec::Idx; + /// An `ItemLocalId` uniquely identifies something within a given "item-like", + /// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no + /// guarantee that the numerical value of a given `ItemLocalId` corresponds to + /// the node's position within the owning item in any way, but there is a + /// guarantee that the `LocalItemId`s within an owner occupy a dense range of + /// integers starting at zero, so a mapping that maps all or most nodes within + /// an "item-like" to something else can be implement by a `Vec` instead of a + /// tree or hash map. + newtype_index! { + pub struct ItemLocalId { .. } } } -impl indexed_vec::Idx for ItemLocalId { - fn new(idx: usize) -> Self { - debug_assert!((idx as u32) as usize == idx); - ItemLocalId(idx as u32) - } - - fn index(self) -> usize { - self.0 as usize - } -} +pub use self::item_local_id_inner::ItemLocalId; /// The `HirId` corresponding to CRATE_NODE_ID and CRATE_DEF_INDEX pub const CRATE_HIR_ID: HirId = HirId { owner: CRATE_DEF_INDEX, - local_id: ItemLocalId(0) + local_id: ItemLocalId::from_u32_const(0) }; pub const DUMMY_HIR_ID: HirId = HirId { @@ -162,7 +148,7 @@ pub const DUMMY_HIR_ID: HirId = HirId { local_id: DUMMY_ITEM_LOCAL_ID, }; -pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId(!0); +pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX; #[derive(Clone, RustcEncodable, RustcDecodable, Copy)] pub struct Label { @@ -331,7 +317,7 @@ impl Path { impl fmt::Debug for Path { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "path({})", print::to_string(print::NO_ANN, |s| s.print_path(self, false))) + write!(f, "path({})", self) } } @@ -698,8 +684,6 @@ pub struct WhereEqPredicate { pub rhs_ty: P, } -pub type CrateConfig = HirVec>; - /// The top-level data structure that stores the entire contents of /// the crate currently being compiled. /// @@ -1196,8 +1180,8 @@ impl StmtKind { pub fn id(&self) -> NodeId { match *self { - StmtKind::Decl(_, id) => id, - StmtKind::Expr(_, id) => id, + StmtKind::Decl(_, id) | + StmtKind::Expr(_, id) | StmtKind::Semi(_, id) => id, } } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index b220634d0d903..ae0d78d2958ad 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -79,7 +79,14 @@ impl<'a> ToStableHashKey> for CrateNum { } } -impl_stable_hash_for!(tuple_struct hir::ItemLocalId { index }); +impl<'a> HashStable> for hir::ItemLocalId { + #[inline] + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { + self.as_u32().hash_stable(hcx, hasher); + } +} impl<'a> ToStableHashKey> for hir::ItemLocalId { @@ -800,7 +807,7 @@ impl<'a> HashStable> for hir::Mod { .iter() .map(|id| { let (def_path_hash, local_id) = id.id.to_stable_hash_key(hcx); - debug_assert_eq!(local_id, hir::ItemLocalId(0)); + debug_assert_eq!(local_id, hir::ItemLocalId::from_u32(0)); def_path_hash.0 }).fold(Fingerprint::ZERO, |a, b| { a.combine_commutative(b) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 61a861a8a1cd8..a787eeae663fd 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -10,7 +10,7 @@ //! This module contains the "canonicalizer" itself. //! -//! For an overview of what canonicaliation is and how it fits into +//! For an overview of what canonicalization is and how it fits into //! rustc, check out the [chapter in the rustc guide][c]. //! //! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index f4607f7a9092f..6f3d10268351a 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -556,7 +556,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { } /// Given two sets of values for the same set of canonical variables, unify them. - /// The second set is produced lazilly by supplying indices from the first set. + /// The second set is produced lazily by supplying indices from the first set. fn unify_canonical_vars( &self, cause: &ObligationCause<'tcx>, diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs index 70ce5d0d8dc0c..e2110e148de52 100644 --- a/src/librustc/infer/canonical/substitute.rs +++ b/src/librustc/infer/canonical/substitute.rs @@ -11,7 +11,7 @@ //! This module contains code to substitute new values into a //! `Canonical<'tcx, T>`. //! -//! For an overview of what canonicaliation is and how it fits into +//! For an overview of what canonicalization is and how it fits into //! rustc, check out the [chapter in the rustc guide][c]. //! //! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html diff --git a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs index 009a823568131..7a92b3084ba9f 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs @@ -20,7 +20,7 @@ use util::common::ErrorReported; use infer::lexical_region_resolve::RegionResolutionError::SubSupConflict; impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { - /// Print the error message for lifetime errors when binding excapes a closure. + /// Print the error message for lifetime errors when binding escapes a closure. /// /// Consider a case where we have /// diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index 642382bcf0fa3..8172f620c3646 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -428,7 +428,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// /// This routine is only intended to be used when the leak-check has /// passed; currently, it's used in the trait matching code to create - /// a set of nested obligations frmo an impl that matches against + /// a set of nested obligations from an impl that matches against /// something higher-ranked. More details can be found in /// `librustc/middle/traits/README.md`. /// diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 4ddf47c88ddba..87e32be1a1759 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1160,10 +1160,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } /// Takes ownership of the list of variable regions. This implies - /// that all the region constriants have already been taken, and + /// that all the region constraints have already been taken, and /// hence that `resolve_regions_and_report_errors` can never be /// called. This is used only during NLL processing to "hand off" ownership - /// of the set of region vairables into the NLL region context. + /// of the set of region variables into the NLL region context. pub fn take_region_var_origins(&self) -> VarInfos { let (var_infos, data) = self.region_constraints .borrow_mut() @@ -1478,7 +1478,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } /// Clears the selection, evaluation, and projection caches. This is useful when - /// repeatedly attemping to select an Obligation while changing only + /// repeatedly attempting to select an Obligation while changing only /// its ParamEnv, since FulfillmentContext doesn't use 'probe' pub fn clear_caches(&self) { self.selection_cache.clear(); diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs index a7a79dd2e6560..5fee04341b676 100644 --- a/src/librustc/infer/outlives/verify.rs +++ b/src/librustc/infer/outlives/verify.rs @@ -299,8 +299,8 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> { let assoc_item = tcx.associated_item(assoc_item_def_id); let trait_def_id = assoc_item.container.assert_trait(); let trait_predicates = tcx.predicates_of(trait_def_id).predicates - .into_iter() - .map(|(p, _)| p) + .iter() + .map(|(p, _)| *p) .collect(); let identity_substs = Substs::identity_for_item(tcx, assoc_item_def_id); let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs); diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index 39bf59a7a4ec5..bec19ba9099dc 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -320,7 +320,7 @@ impl<'tcx> TypeVariableTable<'tcx> { /// but which have only been unified since `s` started, and /// return the types with which they were unified. So if we had /// a type variable `V0`, then we started the snapshot, then we - /// created a type variable `V1`, unifed `V0` with `T0`, and + /// created a type variable `V1`, unified `V0` with `T0`, and /// unified `V1` with `T1`, this function would return `{T0}`. pub fn types_escaping_snapshot(&mut self, s: &Snapshot<'tcx>) -> Vec> { let mut new_elem_threshold = u32::MAX; diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 5470aff77f8a4..8acbaaa844d74 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1020,9 +1020,12 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { } fn visit_pat(&mut self, p: &'a ast::Pat) { - run_lints!(self, check_pat, p); + let mut visit_subpats = true; + run_lints!(self, check_pat, p, &mut visit_subpats); self.check_id(p.id); - ast_visit::walk_pat(self, p); + if visit_subpats { + ast_visit::walk_pat(self, p); + } } fn visit_expr(&mut self, e: &'a ast::Expr) { diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 732b32cc35d68..cfb9f04c4c6d1 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -189,7 +189,7 @@ impl<'a> LintLevelsBuilder<'a> { /// This function will perform a number of tasks: /// /// * It'll validate all lint-related attributes in `attrs` - /// * It'll mark all lint-related attriutes as used + /// * It'll mark all lint-related attributes as used /// * Lint levels will be updated based on the attributes provided /// * Lint attributes are validated, e.g. a #[forbid] can't be switched to /// #[allow] diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index afd7800810982..18922ec5d1739 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -341,7 +341,7 @@ pub trait EarlyLintPass: LintPass { fn check_block_post(&mut self, _: &EarlyContext<'_>, _: &ast::Block) { } fn check_stmt(&mut self, _: &EarlyContext<'_>, _: &ast::Stmt) { } fn check_arm(&mut self, _: &EarlyContext<'_>, _: &ast::Arm) { } - fn check_pat(&mut self, _: &EarlyContext<'_>, _: &ast::Pat) { } + fn check_pat(&mut self, _: &EarlyContext<'_>, _: &ast::Pat, _: &mut bool) { } fn check_expr(&mut self, _: &EarlyContext<'_>, _: &ast::Expr) { } fn check_expr_post(&mut self, _: &EarlyContext<'_>, _: &ast::Expr) { } fn check_ty(&mut self, _: &EarlyContext<'_>, _: &ast::Ty) { } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 78aabf86e300d..ee6d970750adf 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -224,7 +224,7 @@ impl Default for ErrorOutputType { // Use tree-based collections to cheaply get a deterministic Hash implementation. // DO NOT switch BTreeMap out for an unsorted container type! That would break -// dependency tracking for commandline arguments. +// dependency tracking for command-line arguments. #[derive(Clone, Hash)] pub struct OutputTypes(BTreeMap>); @@ -273,7 +273,7 @@ impl OutputTypes { // Use tree-based collections to cheaply get a deterministic Hash implementation. // DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That -// would break dependency tracking for commandline arguments. +// would break dependency tracking for command-line arguments. #[derive(Clone, Hash)] pub struct Externs(BTreeMap>>); @@ -339,7 +339,7 @@ macro_rules! top_level_options { ); } -// The top-level commandline options struct +// The top-level command-line options struct // // For each option, one has to specify how it behaves with regard to the // dependency tracking system of incremental compilation. This is done via the @@ -2377,11 +2377,11 @@ impl fmt::Display for CrateType { } } -/// Commandline arguments passed to the compiler have to be incorporated with +/// Command-line arguments passed to the compiler have to be incorporated with /// the dependency tracking system for incremental compilation. This module /// provides some utilities to make this more convenient. /// -/// The values of all commandline arguments that are relevant for dependency +/// The values of all command-line arguments that are relevant for dependency /// tracking are hashed into a single value that determines whether the /// incremental compilation cache can be re-used or not. This hashing is done /// via the DepTrackingHash trait defined below, since the standard Hash @@ -2394,7 +2394,7 @@ impl fmt::Display for CrateType { /// impl_dep_tracking_hash_via_hash!() macro that allows to simply reuse the /// Hash implementation for DepTrackingHash. It's important though that /// we have an opt-in scheme here, so one is hopefully forced to think about -/// how the hash should be calculated when adding a new commandline argument. +/// how the hash should be calculated when adding a new command-line argument. mod dep_tracking { use lint; use middle::cstore; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 8cfbd27fc6163..8582900b72c83 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -393,7 +393,7 @@ impl Session { match id.as_usize().checked_add(count) { Some(next) => { - self.next_node_id.set(ast::NodeId::new(next)); + self.next_node_id.set(ast::NodeId::from_usize(next)); } None => bug!("Input too large, ran out of node ids!"), } @@ -1160,7 +1160,7 @@ pub fn build_session_( recursion_limit: Once::new(), type_length_limit: Once::new(), const_eval_stack_frame_limit: 100, - next_node_id: OneThread::new(Cell::new(NodeId::new(1))), + next_node_id: OneThread::new(Cell::new(NodeId::from_u32(1))), allocator_kind: Once::new(), injected_panic_runtime: Once::new(), imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())), diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 1d76ccdca3161..715ce0d7e805b 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -182,7 +182,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { }; predicates .predicates - .into_iter() + .iter() .map(|(predicate, _)| predicate.subst_supertrait(self, &trait_ref)) .any(|predicate| { match predicate { @@ -302,9 +302,10 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return Some(MethodViolationCode::Generic); } - if self.predicates_of(method.def_id).predicates.into_iter() + if self.predicates_of(method.def_id).predicates.iter() // A trait object can't claim to live more than the concrete type, // so outlives predicates will always hold. + .cloned() .filter(|(p, _)| p.to_opt_type_outlives().is_none()) .collect::>() // Do a shallow visit so that `contains_illegal_self_type_reference` diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index 62317f074764f..99dc099d57738 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -200,7 +200,7 @@ impl_stable_hash_for!(struct DtorckConstraint<'tcx> { /// trivial for dropck-outlives. /// /// Note also that `needs_drop` requires a "global" type (i.e., one -/// with erased regions), but this funtcion does not. +/// with erased regions), but this function does not. pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool { match ty.sty { // None of these types have a destructor and hence they do not diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index d7b5dd049e350..d3dc1655b0df2 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -407,7 +407,7 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_, '_, '_>, impl_def_id: DefId) -> Option< // The predicates will contain default bounds like `T: Sized`. We need to // remove these bounds, and add `T: ?Sized` to any untouched type parameters. - let predicates = tcx.predicates_of(impl_def_id).predicates; + let predicates = &tcx.predicates_of(impl_def_id).predicates; let mut pretty_predicates = Vec::with_capacity( predicates.len() + types_without_default_bounds.len()); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index a897afa0ca663..2c7814831450c 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -781,7 +781,7 @@ pub fn shift_vars<'a, 'gcx, 'tcx, T>( /// /// Note that what I'm calling an "escaping var" is often just called a "free var". However, /// we already use the term "free var". It refers to the regions or types that we use to represent -/// bound regions or type params on a fn definition while we are typechecking its body. +/// bound regions or type params on a fn definition while we are type checking its body. /// /// To clarify, conceptually there is no particular difference between /// an "escaping" var and a "free" var. However, there is a big @@ -857,7 +857,7 @@ struct LateBoundRegionsCollector { /// If true, we only want regions that are known to be /// "constrained" when you equate this type with another type. In - /// partcular, if you have e.g. `&'a u32` and `&'b u32`, equating + /// particular, if you have e.g. `&'a u32` and `&'b u32`, equating /// them constraints `'a == 'b`. But if you have `<&'a u32 as /// Trait>::Foo` and `<&'b u32 as Trait>::Foo`, normalizing those /// types may mean that `'a` and `'b` don't appear in the results, diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 877bd5a82e6a0..79324bd97a3db 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1287,7 +1287,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { /// Type size "skeleton", i.e. the only information determining a type's size. /// While this is conservative, (aside from constant sizes, only pointers, /// newtypes thereof and null pointer optimized enums are allowed), it is -/// enough to statically check common usecases of transmute. +/// enough to statically check common use cases of transmute. #[derive(Copy, Clone, Debug)] pub enum SizeSkeleton<'tcx> { /// Any statically computable Layout. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8197136d189ae..96f4b1ef8e32a 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2130,7 +2130,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } #[inline] - pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> GenericPredicates<'gcx> { + pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Lrc> { tcx.predicates_of(self.did) } @@ -2373,8 +2373,8 @@ impl<'a, 'gcx, 'tcx> AdtDef { def_id: sized_trait, substs: tcx.mk_substs_trait(ty, &[]) }).to_predicate(); - let predicates = tcx.predicates_of(self.did).predicates; - if predicates.into_iter().any(|(p, _)| p == sized_predicate) { + let predicates = &tcx.predicates_of(self.did).predicates; + if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] @@ -2400,7 +2400,7 @@ impl<'a, 'gcx, 'tcx> FieldDef { /// Represents the various closure traits in the Rust language. This /// will determine the type of the environment (`self`, in the -/// desuaring) argument that the closure expects. +/// desugaring) argument that the closure expects. /// /// You can get the environment type of a closure using /// `tcx.closure_env_ty()`. diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index c82a44011db6c..89e7f4db502bb 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -127,17 +127,18 @@ define_queries! { <'tcx> /// predicate gets in the way of some checks, which are intended /// to operate over only the actual where-clauses written by the /// user.) - [] fn predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>, + [] fn predicates_of: PredicatesOfItem(DefId) -> Lrc>, /// Maps from the def-id of an item (trait/struct/enum/fn) to the /// predicates (where clauses) directly defined on it. This is /// equal to the `explicit_predicates_of` predicates plus the /// `inferred_outlives_of` predicates. - [] fn predicates_defined_on: PredicatesDefinedOnItem(DefId) -> ty::GenericPredicates<'tcx>, + [] fn predicates_defined_on: PredicatesDefinedOnItem(DefId) + -> Lrc>, /// Returns the predicates written explicit by the user. [] fn explicit_predicates_of: ExplicitPredicatesOfItem(DefId) - -> ty::GenericPredicates<'tcx>, + -> Lrc>, /// Returns the inferred outlives predicates (e.g., for `struct /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`). @@ -149,12 +150,12 @@ define_queries! { <'tcx> /// evaluate them even during type conversion, often before the /// full predicates are available (note that supertraits have /// additional acyclicity requirements). - [] fn super_predicates_of: SuperPredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>, + [] fn super_predicates_of: SuperPredicatesOfItem(DefId) -> Lrc>, /// To avoid cycles within the predicates of a single item we compute /// per-type-parameter predicates for resolving `T::AssocTy`. [] fn type_param_predicates: type_param_predicates((DefId, DefId)) - -> ty::GenericPredicates<'tcx>, + -> Lrc>, [] fn trait_def: TraitDefOfItem(DefId) -> &'tcx ty::TraitDef, [] fn adt_def: AdtDefOfItem(DefId) -> &'tcx ty::AdtDef, diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 821b074cd68c6..9971a41560335 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -942,7 +942,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// /// In the process of working on rust-lang/rust#55238 a mysterious segfault was /// stumbled upon. The segfault was never reproduced locally, but it was -/// suspected to be releated to the fact that codegen worker threads were +/// suspected to be related to the fact that codegen worker threads were /// sticking around by the time the main thread was exiting, causing issues. /// /// This structure is an attempt to fix that issue where the `codegen_aborted` diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index a5f90149f4ac4..8f79d49b3e2b4 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -194,7 +194,7 @@ pub fn codegen_intrinsic_call( return; } // Effectively no-ops - "uninit" => { + "uninit" | "forget" => { return; } "needs_drop" => { diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 0d95b0c7bbc0c..f8593363bb16a 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -79,7 +79,7 @@ //! - In order to be able to also use symbols from two versions of the same //! crate (which naturally also have the same name), a stronger measure is //! required: The compiler accepts an arbitrary "disambiguator" value via the -//! `-C metadata` commandline argument. This disambiguator is then fed into +//! `-C metadata` command-line argument. This disambiguator is then fed into //! the symbol hash of every exported item. Consequently, the symbols in two //! identical crates but with different disambiguators are not in conflict //! with each other. This facility is mainly intended to be used by build diff --git a/src/librustc_data_structures/graph/scc/mod.rs b/src/librustc_data_structures/graph/scc/mod.rs index a989a54010222..64de0c2f565a1 100644 --- a/src/librustc_data_structures/graph/scc/mod.rs +++ b/src/librustc_data_structures/graph/scc/mod.rs @@ -38,7 +38,7 @@ struct SccData { /// successors can be found. ranges: IndexVec>, - /// Contains the succcessors for all the Sccs, concatenated. The + /// Contains the successors for all the Sccs, concatenated. The /// range of indices corresponding to a given SCC is found in its /// SccData. all_successors: Vec, diff --git a/src/librustc_data_structures/owning_ref/mod.rs b/src/librustc_data_structures/owning_ref/mod.rs index 02640a71010e2..27c2f8b718ab8 100644 --- a/src/librustc_data_structures/owning_ref/mod.rs +++ b/src/librustc_data_structures/owning_ref/mod.rs @@ -452,7 +452,7 @@ impl OwningRef { /// use owning_ref::{OwningRef, Erased}; /// /// fn main() { - /// // NB: Using the concrete types here for explicitnes. + /// // NB: Using the concrete types here for explicitness. /// // For less verbose code type aliases like `BoxRef` are provided. /// /// let owning_ref_a: OwningRef, [i32; 4]> @@ -722,7 +722,7 @@ impl OwningRefMut { /// use owning_ref::{OwningRefMut, Erased}; /// /// fn main() { - /// // NB: Using the concrete types here for explicitnes. + /// // NB: Using the concrete types here for explicitness. /// // For less verbose code type aliases like `BoxRef` are provided. /// /// let owning_ref_mut_a: OwningRefMut, [i32; 4]> diff --git a/src/librustc_data_structures/sorted_map.rs b/src/librustc_data_structures/sorted_map.rs index 730b13a0584fc..29d99a6aef3f2 100644 --- a/src/librustc_data_structures/sorted_map.rs +++ b/src/librustc_data_structures/sorted_map.rs @@ -15,7 +15,7 @@ use std::mem; use std::ops::{RangeBounds, Bound, Index, IndexMut}; /// `SortedMap` is a data structure with similar characteristics as BTreeMap but -/// slightly different trade-offs: lookup, inseration, and removal are O(log(N)) +/// slightly different trade-offs: lookup, insertion, and removal are O(log(N)) /// and elements can be iterated in order cheaply. /// /// `SortedMap` can be faster than a `BTreeMap` for small sizes (<50) since it diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 6c7982242bfad..ec3cb95db88f8 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -643,8 +643,8 @@ impl Compilation { } } -/// A trait for customising the compilation process. Offers a number of hooks for -/// executing custom code or customising input. +/// A trait for customizing the compilation process. Offers a number of hooks for +/// executing custom code or customizing input. pub trait CompilerCalls<'a> { /// Hook for a callback early in the process of handling arguments. This will /// be called straight after options have been parsed but before anything diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index b4f6d10b1f829..c7ba31e339570 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -425,7 +425,7 @@ impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> { pprust_hir::AnnNode::Item(item) => { s.s.space()?; s.synth_comment(format!("node_id: {} hir local_id: {}", - item.id, item.hir_id.local_id.0)) + item.id, item.hir_id.local_id.as_u32())) } pprust_hir::AnnNode::SubItem(id) => { s.s.space()?; @@ -434,18 +434,18 @@ impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> { pprust_hir::AnnNode::Block(blk) => { s.s.space()?; s.synth_comment(format!("block node_id: {} hir local_id: {}", - blk.id, blk.hir_id.local_id.0)) + blk.id, blk.hir_id.local_id.as_u32())) } pprust_hir::AnnNode::Expr(expr) => { s.s.space()?; s.synth_comment(format!("node_id: {} hir local_id: {}", - expr.id, expr.hir_id.local_id.0))?; + expr.id, expr.hir_id.local_id.as_u32()))?; s.pclose() } pprust_hir::AnnNode::Pat(pat) => { s.s.space()?; s.synth_comment(format!("pat node_id: {} hir local_id: {}", - pat.id, pat.hir_id.local_id.0)) + pat.id, pat.hir_id.local_id.as_u32())) } } } @@ -566,7 +566,7 @@ impl FromStr for UserIdentifiedItem { type Err = (); fn from_str(s: &str) -> Result { Ok(s.parse() - .map(ast::NodeId::new) + .map(ast::NodeId::from_u32) .map(ItemViaNode) .unwrap_or_else(|_| ItemViaPath(s.split("::").map(|s| s.to_string()).collect()))) } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 28b7c610a91c0..8865c7e438e5e 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -232,20 +232,20 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { // children of 1, etc let dscope = region::Scope { - id: hir::ItemLocalId(1), + id: hir::ItemLocalId::from_u32(1), data: region::ScopeData::Destruction, }; self.region_scope_tree.record_scope_parent(dscope, None); self.create_region_hierarchy( &RH { - id: hir::ItemLocalId(1), + id: hir::ItemLocalId::from_u32(1), sub: &[ RH { - id: hir::ItemLocalId(10), + id: hir::ItemLocalId::from_u32(10), sub: &[], }, RH { - id: hir::ItemLocalId(11), + id: hir::ItemLocalId::from_u32(11), sub: &[], }, ], @@ -400,7 +400,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { pub fn t_rptr_scope(&self, id: u32) -> Ty<'tcx> { let r = ty::ReScope(region::Scope { - id: hir::ItemLocalId(id), + id: hir::ItemLocalId::from_u32(id), data: region::ScopeData::Node, }); self.infcx diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 58a799bb45f2d..f76086139ed7e 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -160,7 +160,7 @@ const LABELS_FN_IN_TRAIT: &[&[&str]] = &[ EXTRA_TRAIT, ]; -/// For generic cases like inline-assemply/mod/etc +/// For generic cases like inline-assembly/mod/etc const LABELS_HIR_ONLY: &[&[&str]] = &[ BASE_HIR, ]; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 2a9b58200e5d6..bef7b364d8447 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -40,6 +40,8 @@ use rustc::util::nodemap::FxHashSet; use syntax::tokenstream::{TokenTree, TokenStream}; use syntax::ast; +use syntax::ptr::P; +use syntax::ast::Expr; use syntax::attr; use syntax::source_map::Spanned; use syntax::edition::Edition; @@ -47,6 +49,7 @@ use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_a use syntax_pos::{BytePos, Span, SyntaxContext}; use syntax::symbol::keywords; use syntax::errors::{Applicability, DiagnosticBuilder}; +use syntax::print::pprust::expr_to_string; use rustc::hir::{self, GenericParamKind, PatKind}; use rustc::hir::intravisit::FnKind; @@ -1407,21 +1410,48 @@ impl LintPass for EllipsisInclusiveRangePatterns { } impl EarlyLintPass for EllipsisInclusiveRangePatterns { - fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) { - use self::ast::{PatKind, RangeEnd, RangeSyntax}; + fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat, visit_subpats: &mut bool) { + use self::ast::{PatKind, RangeEnd, RangeSyntax::DotDotDot}; + + /// If `pat` is a `...` pattern, return the start and end of the range, as well as the span + /// corresponding to the ellipsis. + fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(&P, &P, Span)> { + match &pat.node { + PatKind::Range(a, b, Spanned { span, node: RangeEnd::Included(DotDotDot), .. }) => { + Some((a, b, *span)) + } + _ => None, + } + } - if let PatKind::Range( - _, _, Spanned { span, node: RangeEnd::Included(RangeSyntax::DotDotDot) } - ) = pat.node { + let (parenthesise, endpoints) = match &pat.node { + PatKind::Ref(subpat, _) => (true, matches_ellipsis_pat(&subpat)), + _ => (false, matches_ellipsis_pat(pat)), + }; + + if let Some((start, end, join)) = endpoints { let msg = "`...` range patterns are deprecated"; - let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, span, msg); - err.span_suggestion_short_with_applicability( - span, "use `..=` for an inclusive range", "..=".to_owned(), - // FIXME: outstanding problem with precedence in ref patterns: - // https://github.com/rust-lang/rust/issues/51043#issuecomment-392252285 - Applicability::MaybeIncorrect - ); - err.emit() + let suggestion = "use `..=` for an inclusive range"; + if parenthesise { + *visit_subpats = false; + let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg); + err.span_suggestion_with_applicability( + pat.span, + suggestion, + format!("&({}..={})", expr_to_string(&start), expr_to_string(&end)), + Applicability::MachineApplicable, + ); + err.emit(); + } else { + let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, msg); + err.span_suggestion_short_with_applicability( + join, + suggestion, + "..=".to_owned(), + Applicability::MachineApplicable, + ); + err.emit(); + }; } } } @@ -1486,7 +1516,7 @@ declare_lint! { "detects edition keywords being used as an identifier" } -/// Checks for uses of edtion keywords used as an identifier +/// Checks for uses of edition keywords used as an identifier #[derive(Clone)] pub struct KeywordIdents; diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 6d365e6d1ecbf..7eab7d2100290 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -396,12 +396,12 @@ impl EarlyLintPass for UnusedParens { self.check_unused_parens_expr(cx, &value, msg, followed_by_block); } - fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat) { + fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat, _: &mut bool) { use ast::PatKind::{Paren, Range}; // The lint visitor will visit each subpattern of `p`. We do not want to lint any range // pattern no matter where it occurs in the pattern. For something like `&(a..=b)`, there // is a recursive `check_pat` on `a` and `b`, but we will assume that if there are - // unnecessry parens they serve a purpose of readability. + // unnecessary parens they serve a purpose of readability. if let Paren(ref pat) = p.node { match pat.node { Range(..) => {} diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index 338824d5efe4c..276e2a911e697 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -11,12 +11,14 @@ crate-type = ["dylib"] [dependencies] flate2 = "1.0" log = "0.4" +memmap = "0.6" proc_macro = { path = "../libproc_macro" } rustc = { path = "../librustc" } -rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } +rustc_target = { path = "../librustc_target" } serialize = { path = "../libserialize" } +stable_deref_trait = "1.0.0" syntax = { path = "../libsyntax" } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index e6e1367b592df..e1d9ca5339e6a 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -103,9 +103,9 @@ provide! { <'tcx> tcx, def_id, other, cdata, generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess)) } - predicates_of => { cdata.get_predicates(def_id.index, tcx) } - predicates_defined_on => { cdata.get_predicates_defined_on(def_id.index, tcx) } - super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) } + predicates_of => { Lrc::new(cdata.get_predicates(def_id.index, tcx)) } + predicates_defined_on => { Lrc::new(cdata.get_predicates_defined_on(def_id.index, tcx)) } + super_predicates_of => { Lrc::new(cdata.get_super_predicates(def_id.index, tcx)) } trait_def => { tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess)) } diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 0cc0707a3a51f..0322c888ad5c9 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -30,6 +30,8 @@ extern crate libc; #[macro_use] extern crate log; +extern crate memmap; +extern crate stable_deref_trait; #[macro_use] extern crate syntax; extern crate syntax_pos; diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index a732446d50481..528c96f240dba 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -243,12 +243,14 @@ use std::cmp; use std::fmt; use std::fs; use std::io::{self, Read}; +use std::ops::Deref; use std::path::{Path, PathBuf}; use std::time::Instant; use flate2::read::DeflateDecoder; use rustc_data_structures::owning_ref::OwningRef; + pub struct CrateMismatch { path: PathBuf, got: String, @@ -856,6 +858,19 @@ fn get_metadata_section(target: &Target, return ret; } +/// A trivial wrapper for `Mmap` that implements `StableDeref`. +struct StableDerefMmap(memmap::Mmap); + +impl Deref for StableDerefMmap { + type Target = [u8]; + + fn deref(&self) -> &[u8] { + self.0.deref() + } +} + +unsafe impl stable_deref_trait::StableDeref for StableDerefMmap {} + fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Path, @@ -892,9 +907,14 @@ fn get_metadata_section_imp(target: &Target, } } CrateFlavor::Rmeta => { - let buf = fs::read(filename).map_err(|_| - format!("failed to read rmeta metadata: '{}'", filename.display()))?; - rustc_erase_owner!(OwningRef::new(buf).map_owner_box()) + // mmap the file, because only a small fraction of it is read. + let file = std::fs::File::open(filename).map_err(|_| + format!("failed to open rmeta metadata: '{}'", filename.display()))?; + let mmap = unsafe { memmap::Mmap::map(&file) }; + let mmap = mmap.map_err(|_| + format!("failed to mmap rmeta metadata: '{}'", filename.display()))?; + + rustc_erase_owner!(OwningRef::new(StableDerefMmap(mmap)).map_owner_box()) } }; let blob = MetadataBlob(raw_bytes); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index cd814de10c365..06dfd4bc2cc1f 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -112,7 +112,7 @@ mod relate_tys; /// - `liveness` -- results of a liveness computation on the MIR; used to create liveness /// constraints for the regions in the types of variables /// - `flow_inits` -- results of a maybe-init dataflow analysis -/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysiss +/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis pub(crate) fn type_check<'gcx, 'tcx>( infcx: &InferCtxt<'_, 'gcx, 'tcx>, param_env: ty::ParamEnv<'gcx>, diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index c0f059619a497..715d6e0c0d1b3 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -262,7 +262,7 @@ struct PlaceComponents<'p, 'tcx: 'p> { impl<'p, 'tcx> PlaceComponents<'p, 'tcx> { /// Converts a list of `Place` components into an iterator; this /// iterator yields up a never-ending stream of `Option<&Place>`. - /// These begin with the "innermst" place and then with each + /// These begin with the "innermost" place and then with each /// projection therefrom. So given a place like `a.b.c` it would /// yield up: /// diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index aa383a123b69a..2ef71617b7cb6 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -90,7 +90,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source_info = this.source_info(span); for stmt in stmts { - let Stmt { kind, opt_destruction_scope } = this.hir.mirror(stmt); + let Stmt { kind, opt_destruction_scope, span: stmt_span } = this.hir.mirror(stmt); match kind { StmtKind::Expr { scope, expr } => { this.block_context.push(BlockFrame::Statement { ignores_expr_result: true }); @@ -99,7 +99,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let si = (scope, source_info); this.in_scope(si, LintLevel::Inherited, block, |this| { let expr = this.hir.mirror(expr); - this.stmt_expr(block, expr) + this.stmt_expr(block, expr, Some(stmt_span)) }) })); } @@ -177,17 +177,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let destination_ty = destination.ty(&this.local_decls, tcx).to_ty(tcx); if let Some(expr) = expr { let tail_result_is_ignored = destination_ty.is_unit() || - match this.block_context.last() { - // no context: conservatively assume result is read - None => false, - - // sub-expression: block result feeds into some computation - Some(BlockFrame::SubExpr) => false, - - // otherwise: use accumualated is_ignored state. - Some(BlockFrame::TailExpr { tail_result_is_ignored: ignored }) | - Some(BlockFrame::Statement { ignores_expr_result: ignored }) => *ignored, - }; + this.block_context.currently_ignores_tail_results(); this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored }); unpack!(block = this.into(destination, block, expr)); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 8fee74390cc6b..18ce7ae490708 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -351,7 +351,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block.and(Rvalue::Aggregate(adt, fields)) } ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => { - block = unpack!(this.stmt_expr(block, expr)); + block = unpack!(this.stmt_expr(block, expr, None)); block.and(this.unit_rvalue()) } ExprKind::Yield { value } => { diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index e0bf02c6739e3..8f50a1e9a21b9 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -10,7 +10,7 @@ //! See docs in build/expr/mod.rs -use build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; +use build::{BlockAnd, BlockAndExtension, Builder}; use hair::*; use rustc::middle::region; use rustc::mir::*; @@ -68,19 +68,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { debug!("creating temp {:?} with block_context: {:?}", local_decl, this.block_context); // Find out whether this temp is being created within the // tail expression of a block whose result is ignored. - for bf in this.block_context.iter().rev() { - match bf { - BlockFrame::SubExpr => continue, - BlockFrame::Statement { .. } => break, - &BlockFrame::TailExpr { tail_result_is_ignored } => { - local_decl = local_decl.block_tail(BlockTailInfo { - tail_result_is_ignored - }); - break; - } - } + if let Some(tail_info) = this.block_context.currently_in_block_tail() { + local_decl = local_decl.block_tail(tail_info); } - this.local_decls.push(local_decl) }; if !expr_ty.is_never() { diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index d2913872fca45..8eb46a0483917 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -351,7 +351,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { | ExprKind::Break { .. } | ExprKind::InlineAsm { .. } | ExprKind::Return { .. } => { - unpack!(block = this.stmt_expr(block, expr)); + unpack!(block = this.stmt_expr(block, expr, None)); this.cfg.push_assign_unit(block, source_info, destination); block.unit() } diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index 8f52499124ab7..45235b3153934 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -14,7 +14,18 @@ use hair::*; use rustc::mir::*; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { - pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd<()> { + /// Builds a block of MIR statements to evaluate the HAIR `expr`. + /// If the original expression was an AST statement, + /// (e.g. `some().code(&here());`) then `opt_stmt_span` is the + /// span of that statement (including its semicolon, if any). + /// Diagnostics use this span (which may be larger than that of + /// `expr`) to identify when statement temporaries are dropped. + pub fn stmt_expr(&mut self, + mut block: BasicBlock, + expr: Expr<'tcx>, + opt_stmt_span: Option) + -> BlockAnd<()> + { let this = self; let expr_span = expr.span; let source_info = this.source_info(expr.span); @@ -29,7 +40,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } => { let value = this.hir.mirror(value); this.in_scope((region_scope, source_info), lint_level, block, |this| { - this.stmt_expr(block, value) + this.stmt_expr(block, value, opt_stmt_span) }) } ExprKind::Assign { lhs, rhs } => { @@ -190,9 +201,56 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } _ => { let expr_ty = expr.ty; - let temp = this.temp(expr.ty.clone(), expr_span); + + // Issue #54382: When creating temp for the value of + // expression like: + // + // `{ side_effects(); { let l = stuff(); the_value } }` + // + // it is usually better to focus on `the_value` rather + // than the entirety of block(s) surrounding it. + let mut temp_span = expr_span; + let mut temp_in_tail_of_block = false; + if let ExprKind::Block { body } = expr.kind { + if let Some(tail_expr) = &body.expr { + let mut expr = tail_expr; + while let rustc::hir::ExprKind::Block(subblock, _label) = &expr.node { + if let Some(subtail_expr) = &subblock.expr { + expr = subtail_expr + } else { + break; + } + } + temp_span = expr.span; + temp_in_tail_of_block = true; + } + } + + let temp = { + let mut local_decl = LocalDecl::new_temp(expr.ty.clone(), temp_span); + if temp_in_tail_of_block { + if this.block_context.currently_ignores_tail_results() { + local_decl = local_decl.block_tail(BlockTailInfo { + tail_result_is_ignored: true + }); + } + } + let temp = this.local_decls.push(local_decl); + let place = Place::Local(temp); + debug!("created temp {:?} for expr {:?} in block_context: {:?}", + temp, expr, this.block_context); + place + }; unpack!(block = this.into(&temp, block, expr)); - unpack!(block = this.build_drop(block, expr_span, temp, expr_ty)); + + // Attribute drops of the statement's temps to the + // semicolon at the statement's end. + let drop_point = this.hir.tcx().sess.source_map().end_point(match opt_stmt_span { + None => expr_span, + Some(StatementSpan(span)) => span, + }); + + unpack!(block = this.build_drop(block, drop_point, temp, expr_ty)); block.unit() } } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 177c71b80d1f5..5d9cb014f5821 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -31,7 +31,7 @@ use std::cmp::Ordering; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Identifies what test is needed to decide if `match_pair` is applicable. /// - /// It is a bug to call this with a simplifyable pattern. + /// It is a bug to call this with a simplifiable pattern. pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> { match *match_pair.pattern.kind { PatternKind::Variant { ref adt_def, substs: _, variant_index: _, subpatterns: _ } => { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 5b4001f0652ad..a01f8940a948a 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -336,6 +336,9 @@ impl BlockFrame { } } +#[derive(Debug)] +struct BlockContext(Vec); + struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { hir: Cx<'a, 'gcx, 'tcx>, cfg: CFG<'tcx>, @@ -359,7 +362,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// start just throwing new entries onto that vector in order to /// distinguish the context of EXPR1 from the context of EXPR2 in /// `{ STMTS; EXPR1 } + EXPR2` - block_context: Vec, + block_context: BlockContext, /// The current unsafe block in scope, even if it is hidden by /// a PushUnsafeBlock @@ -409,6 +412,55 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } +impl BlockContext { + fn new() -> Self { BlockContext(vec![]) } + fn push(&mut self, bf: BlockFrame) { self.0.push(bf); } + fn pop(&mut self) -> Option { self.0.pop() } + + /// Traverses the frames on the BlockContext, searching for either + /// the first block-tail expression frame with no intervening + /// statement frame. + /// + /// Notably, this skips over `SubExpr` frames; this method is + /// meant to be used in the context of understanding the + /// relationship of a temp (created within some complicated + /// expression) with its containing expression, and whether the + /// value of that *containing expression* (not the temp!) is + /// ignored. + fn currently_in_block_tail(&self) -> Option { + for bf in self.0.iter().rev() { + match bf { + BlockFrame::SubExpr => continue, + BlockFrame::Statement { .. } => break, + &BlockFrame::TailExpr { tail_result_is_ignored } => + return Some(BlockTailInfo { tail_result_is_ignored }) + } + } + + return None; + } + + /// Looks at the topmost frame on the BlockContext and reports + /// whether its one that would discard a block tail result. + /// + /// Unlike `currently_within_ignored_tail_expression`, this does + /// *not* skip over `SubExpr` frames: here, we want to know + /// whether the block result itself is discarded. + fn currently_ignores_tail_results(&self) -> bool { + match self.0.last() { + // no context: conservatively assume result is read + None => false, + + // sub-expression: block result feeds into some computation + Some(BlockFrame::SubExpr) => false, + + // otherwise: use accumulated is_ignored state. + Some(BlockFrame::TailExpr { tail_result_is_ignored: ignored }) | + Some(BlockFrame::Statement { ignores_expr_result: ignored }) => *ignored, + } + } +} + #[derive(Debug)] enum LocalsForNode { /// In the usual case, a node-id for an identifier maps to at most @@ -764,7 +816,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn_span: span, arg_count, scopes: vec![], - block_context: vec![], + block_context: BlockContext::new(), source_scopes: IndexVec::new(), source_scope: OUTERMOST_SOURCE_SCOPE, source_scope_local_data: IndexVec::new(), diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 586d6d87fa0dc..d56ddcb494406 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -57,6 +57,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, for (index, stmt) in stmts.iter().enumerate() { let hir_id = cx.tcx.hir.node_to_hir_id(stmt.node.id()); let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id); + let stmt_span = StatementSpan(cx.tcx.hir.span(stmt.node.id())); match stmt.node { hir::StmtKind::Expr(ref expr, _) | hir::StmtKind::Semi(ref expr, _) => { @@ -69,6 +70,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: expr.to_ref(), }, opt_destruction_scope: opt_dxn_ext, + span: stmt_span, }))) } hir::StmtKind::Decl(ref decl, _) => { @@ -111,6 +113,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, lint_level: cx.lint_level_of(local.id), }, opt_destruction_scope: opt_dxn_ext, + span: stmt_span, }))); } } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 460afba38d674..3078f10598c0d 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -72,10 +72,14 @@ pub enum StmtRef<'tcx> { Mirror(Box>), } +#[derive(Clone, Debug)] +pub struct StatementSpan(pub Span); + #[derive(Clone, Debug)] pub struct Stmt<'tcx> { pub kind: StmtKind<'tcx>, pub opt_destruction_scope: Option, + pub span: StatementSpan, } #[derive(Clone, Debug)] @@ -116,7 +120,7 @@ pub enum StmtKind<'tcx> { /// reference to an expression in this enum is an `ExprRef<'tcx>`, which /// may in turn be another instance of this enum (boxed), or else an /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very -/// shortlived. They are created by `Hair::to_expr`, analyzed and +/// short-lived. They are created by `Hair::to_expr`, analyzed and /// converted into MIR, and then discarded. /// /// If you compare `Expr` to the full compiler AST, you will see it is diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 08736330acbe7..fd869d6c334ab 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -55,11 +55,11 @@ /// all the values it covers are already covered by row 2. /// /// To compute `U`, we must have two other concepts. -/// 1. `S(c, P)` is a "specialised matrix", where `c` is a constructor (like `Some` or +/// 1. `S(c, P)` is a "specialized matrix", where `c` is a constructor (like `Some` or /// `None`). You can think of it as filtering `P` to just the rows whose *first* pattern /// can cover `c` (and expanding OR-patterns into distinct patterns), and then expanding /// the constructor into all of its components. -/// The specialisation of a row vector is computed by `specialize`. +/// The specialization of a row vector is computed by `specialize`. /// /// It is computed as follows. For each row `p_i` of P, we have four cases: /// 1.1. `p_(i,1) = c(r_1, .., r_a)`. Then `S(c, P)` has a corresponding row: @@ -1453,7 +1453,7 @@ fn should_treat_range_exhaustively(tcx: TyCtxt<'_, 'tcx, 'tcx>, ctor: &Construct /// mean creating a separate constructor for every single value in the range, which is clearly /// impractical. However, observe that for some ranges of integers, the specialisation will be /// identical across all values in that range (i.e. there are equivalence classes of ranges of -/// constructors based on their `is_useful_specialised` outcome). These classes are grouped by +/// constructors based on their `is_useful_specialized` outcome). These classes are grouped by /// the patterns that apply to them (in the matrix `P`). We can split the range whenever the /// patterns that apply to that range (specifically: the patterns that *intersect* with that range) /// change. diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index c3554512806b3..988ff7e75163d 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -67,7 +67,7 @@ macro_rules! try_validation { }} } -/// We want to show a nice path to the invalid field for diagnotsics, +/// We want to show a nice path to the invalid field for diagnostics, /// but avoid string operations in the happy case where no error happens. /// So we track a `Vec` where `PathElem` contains all the data we /// need to later print something for the user. diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index ca58239df8eac..a90cccfa7a774 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -172,7 +172,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { /// While the `ExprUseVisitor` walks, we will identify which /// expressions are borrowed, and insert their ids into this /// table. Actually, we insert the "borrow-id", which is normally - /// the id of the expession being borrowed: but in the case of + /// the id of the expression being borrowed: but in the case of /// `ref mut` borrows, the `id` of the pattern is /// inserted. Therefore later we remove that entry from the table /// and transfer it over to the value being matched. This will diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index a3694cd73ad53..5a91b50f6bcc9 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -663,7 +663,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { let mut errors = false; let mut seen_spans = FxHashSet::default(); let mut error_vec = Vec::new(); - let mut prev_root_id: NodeId = NodeId::new(0); + let mut prev_root_id: NodeId = NodeId::from_u32(0); for i in 0 .. self.determined_imports.len() { let import = self.determined_imports[i]; let error = self.finalize_import(import); diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index 83b90cf1bf204..cf1bc04dd4e01 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -217,8 +217,9 @@ fn program_clauses_for_trait<'a, 'tcx>( let implemented_from_env = Clause::ForAll(ty::Binder::bind(implemented_from_env)); - let where_clauses = &tcx.predicates_defined_on(def_id).predicates - .into_iter() + let predicates = &tcx.predicates_defined_on(def_id).predicates; + let where_clauses = &predicates + .iter() .map(|(wc, _)| wc.lower()) .map(|wc| wc.subst(tcx, bound_vars)) .collect::>(); @@ -314,8 +315,9 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId let trait_pred = ty::TraitPredicate { trait_ref }.lower(); // `WC` - let where_clauses = tcx.predicates_of(def_id).predicates - .into_iter() + let predicates = &tcx.predicates_of(def_id).predicates; + let where_clauses = predicates + .iter() .map(|(wc, _)| wc.lower()) .map(|wc| wc.subst(tcx, bound_vars)); @@ -352,7 +354,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>( // `WC` let where_clauses = tcx.predicates_of(def_id).predicates - .into_iter() + .iter() .map(|(wc, _)| wc.lower()) .map(|wc| wc.subst(tcx, bound_vars)) .collect::>(); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 572e79407a10b..d388d75643888 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -24,6 +24,7 @@ use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc::ty::wf::object_region_bounds; +use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi; use std::collections::BTreeSet; use std::slice; @@ -45,7 +46,7 @@ pub trait AstConv<'gcx, 'tcx> { /// Returns the set of bounds in scope for the type parameter with /// the given id. fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) - -> ty::GenericPredicates<'tcx>; + -> Lrc>; /// What lifetime should we use when a lifetime is omitted (and not elided)? fn re_infer(&self, span: Span, _def: Option<&ty::GenericParamDef>) @@ -1119,8 +1120,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { { let tcx = self.tcx(); - let bounds = self.get_type_parameter_bounds(span, ty_param_def_id) - .predicates.into_iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()); + let predicates = &self.get_type_parameter_bounds(span, ty_param_def_id).predicates; + let bounds = predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()); // Check that there is exactly one way to find an associated type with the // correct name. diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 84967aaf72f57..9aad17626f9a1 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -134,6 +134,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "rustc_peek" => (1, vec![param(0)], param(0)), "init" => (1, Vec::new(), param(0)), "uninit" => (1, Vec::new(), param(0)), + "forget" => (1, vec![param(0)], tcx.mk_unit()), "transmute" => (2, vec![ param(0) ], param(1)), "move_val_init" => { (1, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 4c06cae1d0752..0373bf4e7522d 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1440,7 +1440,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { /// /// 1. Because the numbers of the region variables would otherwise be fairly unique to this /// particular method call, it winds up creating fewer types overall, which helps for memory - /// usage. (Admittedly, this is a rather small effect, though measureable.) + /// usage. (Admittedly, this is a rather small effect, though measurable.) /// /// 2. It makes it easier to deal with higher-ranked trait bounds, because we can replace any /// late-bound regions with 'static. Otherwise, if we were going to replace late-bound diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e3a6f92d79e5b..eed5d909063bd 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1869,7 +1869,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) - -> ty::GenericPredicates<'tcx> + -> Lrc> { let tcx = self.tcx; let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); @@ -1877,7 +1877,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { let item_def_id = tcx.hir.local_def_id(item_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; - ty::GenericPredicates { + Lrc::new(ty::GenericPredicates { parent: None, predicates: self.param_env.caller_bounds.iter().filter_map(|&predicate| { match predicate { @@ -1890,7 +1890,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { _ => None } }).collect() - } + }) } fn re_infer(&self, span: Span, def: Option<&ty::GenericParamDef>) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 8574443190d7c..b5addbd18d2a4 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -910,8 +910,8 @@ fn check_false_global_bounds<'a, 'gcx, 'tcx>( let def_id = fcx.tcx.hir.local_def_id(id); let predicates = fcx.tcx.predicates_of(def_id).predicates - .into_iter() - .map(|(p, _)| p) + .iter() + .map(|(p, _)| *p) .collect(); // Check elaborated bounds let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d2dc226aca250..6ef09d96fd153 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -39,6 +39,7 @@ use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::{ReprOptions, ToPredicate}; use rustc::util::captures::Captures; use rustc::util::nodemap::FxHashMap; +use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi; use syntax::ast; @@ -178,7 +179,8 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { self.tcx } - fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> { + fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) + -> Lrc> { self.tcx .at(span) .type_param_predicates((self.item_def_id, def_id)) @@ -243,7 +245,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { fn type_param_predicates<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, (item_def_id, def_id): (DefId, DefId), -) -> ty::GenericPredicates<'tcx> { +) -> Lrc> { use rustc::hir::*; // In the AST, bounds can derive from two places. Either @@ -264,11 +266,11 @@ fn type_param_predicates<'a, 'tcx>( tcx.generics_of(item_def_id).parent }; - let mut result = parent.map_or( - ty::GenericPredicates { + let mut result = parent.map_or_else( + || Lrc::new(ty::GenericPredicates { parent: None, predicates: vec![], - }, + }), |parent| { let icx = ItemCtxt::new(tcx, parent); icx.get_type_parameter_bounds(DUMMY_SP, def_id) @@ -298,7 +300,7 @@ fn type_param_predicates<'a, 'tcx>( // Implied `Self: Trait` and supertrait bounds. if param_id == item_node_id { let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); - result + Lrc::make_mut(&mut result) .predicates .push((identity_trait_ref.to_predicate(), item.span)); } @@ -317,7 +319,7 @@ fn type_param_predicates<'a, 'tcx>( }; let icx = ItemCtxt::new(tcx, item_def_id); - result + Lrc::make_mut(&mut result) .predicates .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true))); @@ -685,7 +687,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad fn super_predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId, -) -> ty::GenericPredicates<'tcx> { +) -> Lrc> { debug!("super_predicates(trait_def_id={:?})", trait_def_id); let trait_node_id = tcx.hir.as_local_node_id(trait_def_id).unwrap(); @@ -729,10 +731,10 @@ fn super_predicates_of<'a, 'tcx>( } } - ty::GenericPredicates { + Lrc::new(ty::GenericPredicates { parent: None, predicates: superbounds, - } + }) } fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::TraitDef { @@ -1605,27 +1607,23 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>( fn predicates_defined_on<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> ty::GenericPredicates<'tcx> { - let explicit = tcx.explicit_predicates_of(def_id); - let span = tcx.def_span(def_id); - let predicates = explicit.predicates.into_iter().chain( - tcx.inferred_outlives_of(def_id).iter().map(|&p| (p, span)) - ).collect(); - - ty::GenericPredicates { - parent: explicit.parent, - predicates: predicates, +) -> Lrc> { + let mut result = tcx.explicit_predicates_of(def_id); + let inferred_outlives = tcx.inferred_outlives_of(def_id); + if !inferred_outlives.is_empty() { + let span = tcx.def_span(def_id); + Lrc::make_mut(&mut result) + .predicates + .extend(inferred_outlives.iter().map(|&p| (p, span))); } + result } fn predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> ty::GenericPredicates<'tcx> { - let ty::GenericPredicates { - parent, - mut predicates, - } = tcx.predicates_defined_on(def_id); +) -> Lrc> { + let mut result = tcx.predicates_defined_on(def_id); if tcx.is_trait(def_id) { // For traits, add `Self: Trait` predicate. This is @@ -1641,16 +1639,17 @@ fn predicates_of<'a, 'tcx>( // used, and adding the predicate into this list ensures // that this is done. let span = tcx.def_span(def_id); - predicates.push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span)); + Lrc::make_mut(&mut result) + .predicates + .push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span)); } - - ty::GenericPredicates { parent, predicates } + result } fn explicit_predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> ty::GenericPredicates<'tcx> { +) -> Lrc> { use rustc::hir::*; use rustc_data_structures::fx::FxHashSet; @@ -1761,10 +1760,10 @@ fn explicit_predicates_of<'a, 'tcx>( if impl_trait_fn.is_some() { // impl Trait - return ty::GenericPredicates { + return Lrc::new(ty::GenericPredicates { parent: None, predicates: bounds.predicates(tcx, opaque_ty), - }; + }); } else { // named existential types predicates.extend(bounds.predicates(tcx, opaque_ty)); @@ -1794,7 +1793,7 @@ fn explicit_predicates_of<'a, 'tcx>( // on a trait we need to add in the supertrait bounds and bounds found on // associated types. if let Some((_trait_ref, _)) = is_trait { - predicates.extend(tcx.super_predicates_of(def_id).predicates); + predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned()); } // In default impls, we can assume that the self type implements @@ -1971,10 +1970,10 @@ fn explicit_predicates_of<'a, 'tcx>( ); } - ty::GenericPredicates { + Lrc::new(ty::GenericPredicates { parent: generics.parent, predicates, - } + }) } pub enum SizedByDefault { diff --git a/src/librustc_typeck/outlives/explicit.rs b/src/librustc_typeck/outlives/explicit.rs index 75f8b78b9ecf3..9b374cf932fa9 100644 --- a/src/librustc_typeck/outlives/explicit.rs +++ b/src/librustc_typeck/outlives/explicit.rs @@ -33,14 +33,14 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { ) -> &RequiredPredicates<'tcx> { self.map.entry(def_id).or_insert_with(|| { let predicates = if def_id.is_local() { - tcx.explicit_predicates_of(def_id).predicates + tcx.explicit_predicates_of(def_id) } else { - tcx.predicates_of(def_id).predicates + tcx.predicates_of(def_id) }; let mut required_predicates = RequiredPredicates::default(); // process predicates and convert to `RequiredPredicates` entry, see below - for (pred, _) in predicates.into_iter() { + for (pred, _) in predicates.predicates.iter() { match pred { ty::Predicate::TypeOutlives(predicate) => { let OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder(); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 931ba21f6e4bd..0518d73e1e30f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1563,7 +1563,7 @@ impl Clean for hir::Generics { } impl<'a, 'tcx> Clean for (&'a ty::Generics, - &'a ty::GenericPredicates<'tcx>) { + &'a Lrc>) { fn clean(&self, cx: &DocContext) -> Generics { use self::WherePredicate as WP; diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index eda522af92245..635608d140db4 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -156,8 +156,8 @@ fn trait_is_same_or_supertrait(cx: &DocContext, child: DefId, if child == trait_ { return true } - let predicates = cx.tcx.super_predicates_of(child).predicates; - predicates.iter().filter_map(|(pred, _)| { + let predicates = cx.tcx.super_predicates_of(child); + predicates.predicates.iter().filter_map(|(pred, _)| { if let ty::Predicate::Trait(ref pred) = *pred { if pred.skip_binder().trait_ref.self_ty().is_self() { Some(pred.def_id()) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 7dafe67485a6e..f4d05c6dbd65c 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -187,7 +187,7 @@ pub struct RenderOptions { /// Whether to generate a table of contents on the output file when reading a standalone /// Markdown file. pub markdown_no_toc: bool, - /// Additional CSS files to link in pages generated from standlone Markdown files. + /// Additional CSS files to link in pages generated from standalone Markdown files. pub markdown_css: Vec, /// If present, playground URL to use in the "Run" button added to code samples generated from /// standalone Markdown files. If not present, `playground_url` is used. diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 0f9104f91b4c0..b2473dd9b236d 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -961,7 +961,7 @@ span.since { padding-top: 0px; } - body > .sidebar { + .rustdoc > .sidebar { height: 45px; min-height: 40px; margin: 0; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index a780322e85e86..471ba6345e248 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -243,7 +243,7 @@ fn look_for_tests<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx>( if tests.found_tests == 0 { let mut diag = cx.tcx.struct_span_lint_node( lint::builtin::MISSING_DOC_CODE_EXAMPLES, - NodeId::new(0), + NodeId::from_u32(0), span_of_attrs(&item.attrs), "Missing code example in this documentation"); diag.emit(); @@ -281,14 +281,14 @@ impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for LinkCollector<'a, 'tcx, 'rcx, 'cstor let current_item = match item.inner { ModuleItem(..) => { if item.attrs.inner_docs { - if item_node_id.unwrap() != NodeId::new(0) { + if item_node_id.unwrap() != NodeId::from_u32(0) { item.name.clone() } else { None } } else { match parent_node.or(self.mod_ids.last().cloned()) { - Some(parent) if parent != NodeId::new(0) => { + Some(parent) if parent != NodeId::from_u32(0) => { //FIXME: can we pull the parent module's name from elsewhere? Some(self.cx.tcx.hir.name(parent).to_string()) } @@ -538,13 +538,13 @@ fn resolution_failure( ); diag = cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, - NodeId::new(0), + NodeId::from_u32(0), sp, &msg); diag.span_label(sp, "cannot be resolved, ignoring"); } else { diag = cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, - NodeId::new(0), + NodeId::from_u32(0), sp, &msg); @@ -564,7 +564,7 @@ fn resolution_failure( diag } else { cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, - NodeId::new(0), + NodeId::from_u32(0), sp, &msg) }; diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 9c0573964702e..b024574427e71 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -85,7 +85,7 @@ pub use alloc_crate::alloc::*; /// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows, /// plus related functions. /// -/// This type implements the `GlobalAlloc` trait and Rust programs by deafult +/// This type implements the `GlobalAlloc` trait and Rust programs by default /// work as if they had this definition: /// /// ```rust diff --git a/src/libstd/build.rs b/src/libstd/build.rs index b3851d22841e8..9d6e8c4cafdcb 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -41,8 +41,11 @@ fn main() { } else if target.contains("freebsd") { println!("cargo:rustc-link-lib=execinfo"); println!("cargo:rustc-link-lib=pthread"); + } else if target.contains("netbsd") { + println!("cargo:rustc-link-lib=pthread"); + println!("cargo:rustc-link-lib=rt"); } else if target.contains("dragonfly") || target.contains("bitrig") || - target.contains("netbsd") || target.contains("openbsd") { + target.contains("openbsd") { println!("cargo:rustc-link-lib=pthread"); } else if target.contains("solaris") { println!("cargo:rustc-link-lib=socket"); diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 8de415e8aed5c..bb2f152edc63d 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1569,7 +1569,7 @@ impl HashMap /// where the key should go, meaning the keys may become "lost" if their /// location does not reflect their state. For instance, if you change a key /// so that the map now contains keys which compare equal, search may start - /// acting eratically, with two keys randomly masking eachother. Implementations + /// acting erratically, with two keys randomly masking each other. Implementations /// are free to assume this doesn't happen (within the limits of memory-safety). #[unstable(feature = "hash_raw_entry", issue = "54043")] pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut { diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index e26e6d391f84d..476ee3f71caf0 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -525,6 +525,25 @@ impl BufWriter { #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() } + /// Returns a reference to the internally buffered data. + /// + /// # Examples + /// + /// ```no_run + /// # #![feature(bufreader_buffer)] + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // See how many bytes are currently buffered + /// let bytes_buffered = buf_writer.buffer().len(); + /// ``` + #[unstable(feature = "bufreader_buffer", issue = "45323")] + pub fn buffer(&self) -> &[u8] { + &self.buf + } + /// Unwraps this `BufWriter`, returning the underlying writer. /// /// The buffer is written out before returning the writer. @@ -965,31 +984,31 @@ mod tests { let mut buf = [0, 0, 0]; let nread = reader.read(&mut buf); assert_eq!(nread.unwrap(), 3); - let b: &[_] = &[5, 6, 7]; - assert_eq!(buf, b); + assert_eq!(buf, [5, 6, 7]); + assert_eq!(reader.buffer(), []); let mut buf = [0, 0]; let nread = reader.read(&mut buf); assert_eq!(nread.unwrap(), 2); - let b: &[_] = &[0, 1]; - assert_eq!(buf, b); + assert_eq!(buf, [0, 1]); + assert_eq!(reader.buffer(), []); let mut buf = [0]; let nread = reader.read(&mut buf); assert_eq!(nread.unwrap(), 1); - let b: &[_] = &[2]; - assert_eq!(buf, b); + assert_eq!(buf, [2]); + assert_eq!(reader.buffer(), [3]); let mut buf = [0, 0, 0]; let nread = reader.read(&mut buf); assert_eq!(nread.unwrap(), 1); - let b: &[_] = &[3, 0, 0]; - assert_eq!(buf, b); + assert_eq!(buf, [3, 0, 0]); + assert_eq!(reader.buffer(), []); let nread = reader.read(&mut buf); assert_eq!(nread.unwrap(), 1); - let b: &[_] = &[4, 0, 0]; - assert_eq!(buf, b); + assert_eq!(buf, [4, 0, 0]); + assert_eq!(reader.buffer(), []); assert_eq!(reader.read(&mut buf).unwrap(), 0); } @@ -1078,31 +1097,40 @@ mod tests { let mut writer = BufWriter::with_capacity(2, inner); writer.write(&[0, 1]).unwrap(); + assert_eq!(writer.buffer(), []); assert_eq!(*writer.get_ref(), [0, 1]); writer.write(&[2]).unwrap(); + assert_eq!(writer.buffer(), [2]); assert_eq!(*writer.get_ref(), [0, 1]); writer.write(&[3]).unwrap(); + assert_eq!(writer.buffer(), [2, 3]); assert_eq!(*writer.get_ref(), [0, 1]); writer.flush().unwrap(); + assert_eq!(writer.buffer(), []); assert_eq!(*writer.get_ref(), [0, 1, 2, 3]); writer.write(&[4]).unwrap(); writer.write(&[5]).unwrap(); + assert_eq!(writer.buffer(), [4, 5]); assert_eq!(*writer.get_ref(), [0, 1, 2, 3]); writer.write(&[6]).unwrap(); + assert_eq!(writer.buffer(), [6]); assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5]); writer.write(&[7, 8]).unwrap(); + assert_eq!(writer.buffer(), []); assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8]); writer.write(&[9, 10, 11]).unwrap(); + assert_eq!(writer.buffer(), []); assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); writer.flush().unwrap(); + assert_eq!(writer.buffer(), []); assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); } diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 6c95854c66cbf..13cf3133dcd12 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -615,7 +615,7 @@ mod loop_keyword { } // /// The keyword used to define structs. /// -/// Structs in Rust come in three flavours: Structs with named fields, tuple structs, and unit +/// Structs in Rust come in three flavors: Structs with named fields, tuple structs, and unit /// structs. /// /// ```rust diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 2517c45696a2d..8685cb7388705 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -852,7 +852,7 @@ impl From<[u8; 4]> for IpAddr { impl Ipv6Addr { /// Creates a new IPv6 address from eight 16-bit segments. /// - /// The result will represent the IP address a:b:c:d:e:f:g:h. + /// The result will represent the IP address `a:b:c:d:e:f:g:h`. /// /// # Examples /// diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 327ad7f64c23f..51481e129df8d 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1122,7 +1122,7 @@ impl From for Stdio { /// let file = File::open("foo.txt").unwrap(); /// /// let reverse = Command::new("rev") - /// .stdin(file) // Implicit File convertion into a Stdio + /// .stdin(file) // Implicit File conversion into a Stdio /// .output() /// .expect("failed reverse command"); /// @@ -1340,7 +1340,7 @@ impl Child { /// Attempts to collect the exit status of the child if it has already /// exited. /// - /// This function will not block the calling thread and will only advisorily + /// This function will not block the calling thread and will only /// check to see if the child process has exited or not. If the child has /// exited then on Unix the process id is reaped. This function is /// guaranteed to repeatedly return a successful exit status so long as the diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs index d61103a872f9e..d62b09134bbf1 100644 --- a/src/libstd/sys/redox/fd.rs +++ b/src/libstd/sys/redox/fd.rs @@ -26,7 +26,7 @@ impl FileDesc { pub fn raw(&self) -> usize { self.fd } - /// Extracts the actual filedescriptor without closing it. + /// Extracts the actual file descriptor without closing it. pub fn into_raw(self) -> usize { let fd = self.fd; mem::forget(self); diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index edb407ecd23ce..3543d8f8fa331 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -77,6 +77,29 @@ pub fn cvt(result: Result) -> io::Result { result.map_err(|err| io::Error::from_raw_os_error(err.errno)) } +#[doc(hidden)] +pub trait IsMinusOne { + fn is_minus_one(&self) -> bool; +} + +macro_rules! impl_is_minus_one { + ($($t:ident)*) => ($(impl IsMinusOne for $t { + fn is_minus_one(&self) -> bool { + *self == -1 + } + })*) +} + +impl_is_minus_one! { i8 i16 i32 i64 isize } + +pub fn cvt_libc(t: T) -> io::Result { + if t.is_minus_one() { + Err(io::Error::last_os_error()) + } else { + Ok(t) + } +} + /// On Redox, use an illegal instruction to abort pub unsafe fn abort_internal() -> ! { ::core::intrinsics::abort(); diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs index 5822216779b6e..84eb56615b60d 100644 --- a/src/libstd/sys/redox/os.rs +++ b/src/libstd/sys/redox/os.rs @@ -12,10 +12,12 @@ #![allow(unused_imports)] // lots of cfg code here +use libc::{self, c_char}; + use os::unix::prelude::*; use error::Error as StdError; -use ffi::{OsString, OsStr}; +use ffi::{CStr, CString, OsStr, OsString}; use fmt; use io::{self, Read, Write}; use iter; @@ -27,7 +29,7 @@ use ptr; use slice; use str; use sys_common::mutex::Mutex; -use sys::{cvt, fd, syscall}; +use sys::{cvt, cvt_libc, fd, syscall}; use vec; extern { @@ -129,6 +131,8 @@ pub fn current_exe() -> io::Result { Ok(PathBuf::from(path)) } +pub static ENV_LOCK: Mutex = Mutex::new(); + pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, _dont_send_or_sync_me: PhantomData<*mut ()>, @@ -140,52 +144,83 @@ impl Iterator for Env { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } +pub unsafe fn environ() -> *mut *const *const c_char { + extern { static mut environ: *const *const c_char; } + &mut environ +} + /// Returns a vector of (variable, value) byte-vector pairs for all the /// environment variables of the current process. pub fn env() -> Env { - let mut variables: Vec<(OsString, OsString)> = Vec::new(); - if let Ok(mut file) = ::fs::File::open("env:") { - let mut string = String::new(); - if file.read_to_string(&mut string).is_ok() { - for line in string.lines() { - let mut parts = line.splitn(2, '='); - if let Some(name) = parts.next() { - let value = parts.next().unwrap_or(""); - variables.push((OsString::from(name.to_string()), - OsString::from(value.to_string()))); - } + unsafe { + let _guard = ENV_LOCK.lock(); + let mut environ = *environ(); + if environ == ptr::null() { + panic!("os::env() failure getting env string from OS: {}", + io::Error::last_os_error()); + } + let mut result = Vec::new(); + while *environ != ptr::null() { + if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { + result.push(key_value); } + environ = environ.offset(1); + } + return Env { + iter: result.into_iter(), + _dont_send_or_sync_me: PhantomData, + } + } + + fn parse(input: &[u8]) -> Option<(OsString, OsString)> { + // Strategy (copied from glibc): Variable name and value are separated + // by an ASCII equals sign '='. Since a variable name must not be + // empty, allow variable names starting with an equals sign. Skip all + // malformed lines. + if input.is_empty() { + return None; } + let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); + pos.map(|p| ( + OsStringExt::from_vec(input[..p].to_vec()), + OsStringExt::from_vec(input[p+1..].to_vec()), + )) } - Env { iter: variables.into_iter(), _dont_send_or_sync_me: PhantomData } } -pub fn getenv(key: &OsStr) -> io::Result> { - if ! key.is_empty() { - if let Ok(mut file) = ::fs::File::open(&("env:".to_owned() + key.to_str().unwrap())) { - let mut string = String::new(); - file.read_to_string(&mut string)?; - Ok(Some(OsString::from(string))) +pub fn getenv(k: &OsStr) -> io::Result> { + // environment variables with a nul byte can't be set, so their value is + // always None as well + let k = CString::new(k.as_bytes())?; + unsafe { + let _guard = ENV_LOCK.lock(); + let s = libc::getenv(k.as_ptr()) as *const libc::c_char; + let ret = if s.is_null() { + None } else { - Ok(None) - } - } else { - Ok(None) + Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec())) + }; + Ok(ret) } } -pub fn setenv(key: &OsStr, value: &OsStr) -> io::Result<()> { - if ! key.is_empty() { - let mut file = ::fs::File::create(&("env:".to_owned() + key.to_str().unwrap()))?; - file.write_all(value.as_bytes())?; - file.set_len(value.len() as u64)?; +pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + let k = CString::new(k.as_bytes())?; + let v = CString::new(v.as_bytes())?; + + unsafe { + let _guard = ENV_LOCK.lock(); + cvt_libc(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ()) } - Ok(()) } -pub fn unsetenv(key: &OsStr) -> io::Result<()> { - ::fs::remove_file(&("env:".to_owned() + key.to_str().unwrap()))?; - Ok(()) +pub fn unsetenv(n: &OsStr) -> io::Result<()> { + let nbuf = CString::new(n.as_bytes())?; + + unsafe { + let _guard = ENV_LOCK.lock(); + cvt_libc(libc::unsetenv(nbuf.as_ptr())).map(|_| ()) + } } pub fn page_size() -> usize { diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 2037616e6ac7c..4370c1e05027b 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -9,15 +9,19 @@ // except according to those terms. use env::{split_paths}; -use ffi::OsStr; -use os::unix::ffi::OsStrExt; +use ffi::{CStr, OsStr}; use fmt; -use io::{self, Error, ErrorKind}; -use iter; +use fs::File; +use io::{self, prelude::*, BufReader, Error, ErrorKind, SeekFrom}; use libc::{EXIT_SUCCESS, EXIT_FAILURE}; +use os::unix::ffi::OsStrExt; use path::{Path, PathBuf}; +use ptr; +use sys::ext::fs::MetadataExt; +use sys::ext::io::AsRawFd; use sys::fd::FileDesc; -use sys::fs::{File, OpenOptions}; +use sys::fs::{File as SysFile, OpenOptions}; +use sys::os::{ENV_LOCK, environ}; use sys::pipe::{self, AnonPipe}; use sys::{cvt, syscall}; use sys_common::process::{CommandEnv, DefaultEnvKey}; @@ -297,12 +301,6 @@ impl Command { t!(callback()); } - let args: Vec<[usize; 2]> = iter::once( - [self.program.as_ptr() as usize, self.program.len()] - ).chain( - self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()]) - ).collect(); - self.env.apply(); let program = if self.program.contains(':') || self.program.contains('/') { @@ -321,14 +319,93 @@ impl Command { None }; - if let Some(program) = program { - if let Err(err) = syscall::execve(program.as_os_str().as_bytes(), &args) { - io::Error::from_raw_os_error(err.errno as i32) + let mut file = if let Some(program) = program { + t!(File::open(program.as_os_str())) + } else { + return io::Error::from_raw_os_error(syscall::ENOENT); + }; + + // Push all the arguments + let mut args: Vec<[usize; 2]> = Vec::with_capacity(1 + self.args.len()); + + let interpreter = { + let mut reader = BufReader::new(&file); + + let mut shebang = [0; 2]; + let mut read = 0; + loop { + match t!(reader.read(&mut shebang[read..])) { + 0 => break, + n => read += n, + } + } + + if &shebang == b"#!" { + // This is an interpreted script. + // First of all, since we'll be passing another file to + // fexec(), we need to manually check that we have permission + // to execute this file: + let uid = t!(cvt(syscall::getuid())); + let gid = t!(cvt(syscall::getgid())); + let meta = t!(file.metadata()); + + let mode = if uid == meta.uid() as usize { + meta.mode() >> 3*2 & 0o7 + } else if gid == meta.gid() as usize { + meta.mode() >> 3*1 & 0o7 + } else { + meta.mode() & 0o7 + }; + if mode & 1 == 0 { + return io::Error::from_raw_os_error(syscall::EPERM); + } + + // Second of all, we need to actually read which interpreter it wants + let mut interpreter = Vec::new(); + t!(reader.read_until(b'\n', &mut interpreter)); + // Pop one trailing newline, if any + if interpreter.ends_with(&[b'\n']) { + interpreter.pop().unwrap(); + } + + // FIXME: Here we could just reassign `file` directly, if it + // wasn't for lexical lifetimes. Remove the whole `let + // interpreter = { ... };` hack once NLL lands. + // NOTE: Although DO REMEMBER to make sure the interpreter path + // still lives long enough to reach fexec. + Some(interpreter) } else { - panic!("return from exec without err"); + None + } + }; + if let Some(ref interpreter) = interpreter { + let path: &OsStr = OsStr::from_bytes(&interpreter); + file = t!(File::open(path)); + + args.push([interpreter.as_ptr() as usize, interpreter.len()]); + } else { + t!(file.seek(SeekFrom::Start(0))); + } + + args.push([self.program.as_ptr() as usize, self.program.len()]); + args.extend(self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()])); + + // Push all the variables + let mut vars: Vec<[usize; 2]> = Vec::new(); + { + let _guard = ENV_LOCK.lock(); + let mut environ = *environ(); + while *environ != ptr::null() { + let var = CStr::from_ptr(*environ).to_bytes(); + vars.push([var.as_ptr() as usize, var.len()]); + environ = environ.offset(1); } + } + + if let Err(err) = syscall::fexec(file.as_raw_fd(), &args, &vars) { + io::Error::from_raw_os_error(err.errno as i32) } else { - io::Error::from_raw_os_error(syscall::ENOENT) + panic!("return from exec without err"); } } @@ -392,7 +469,7 @@ impl Stdio { let mut opts = OpenOptions::new(); opts.read(readable); opts.write(!readable); - let fd = File::open(Path::new("null:"), &opts)?; + let fd = SysFile::open(Path::new("null:"), &opts)?; Ok((ChildStdio::Owned(fd.into_fd()), None)) } } @@ -405,8 +482,8 @@ impl From for Stdio { } } -impl From for Stdio { - fn from(file: File) -> Stdio { +impl From for Stdio { + fn from(file: SysFile) -> Stdio { Stdio::Fd(file.into_fd()) } } diff --git a/src/libstd/sys/redox/syscall/call.rs b/src/libstd/sys/redox/syscall/call.rs index f9a8bd61ac800..577dde4b4beef 100644 --- a/src/libstd/sys/redox/syscall/call.rs +++ b/src/libstd/sys/redox/syscall/call.rs @@ -45,7 +45,7 @@ pub unsafe fn brk(addr: usize) -> Result { /// # Errors /// /// * `EACCES` - permission is denied for one of the components of `path`, or `path` -/// * `EFAULT` - `path` does not point to the process's addressible memory +/// * `EFAULT` - `path` does not point to the process's addressable memory /// * `EIO` - an I/O error occurred /// * `ENOENT` - `path` does not exit /// * `ENOTDIR` - `path` is not a directory @@ -82,12 +82,6 @@ pub fn dup2(fd: usize, newfd: usize, buf: &[u8]) -> Result { unsafe { syscall4(SYS_DUP2, fd, newfd, buf.as_ptr() as usize, buf.len()) } } -/// Replace the current process with a new executable -pub fn execve>(path: T, args: &[[usize; 2]]) -> Result { - unsafe { syscall4(SYS_EXECVE, path.as_ref().as_ptr() as usize, - path.as_ref().len(), args.as_ptr() as usize, args.len()) } -} - /// Exit the current process pub fn exit(status: usize) -> Result { unsafe { syscall1(SYS_EXIT, status) } @@ -110,9 +104,10 @@ pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result { unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) } } -/// Register a file for event-based I/O -pub fn fevent(fd: usize, flags: usize) -> Result { - unsafe { syscall2(SYS_FEVENT, fd, flags) } +/// Replace the current process with a new executable +pub fn fexec(fd: usize, args: &[[usize; 2]], vars: &[[usize; 2]]) -> Result { + unsafe { syscall5(SYS_FEXEC, fd, args.as_ptr() as usize, args.len(), + vars.as_ptr() as usize, vars.len()) } } /// Map a file into memory @@ -347,7 +342,7 @@ pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result /// /// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block /// * `EBADF` - the file descriptor is not valid or is not open for writing -/// * `EFAULT` - `buf` does not point to the process's addressible memory +/// * `EFAULT` - `buf` does not point to the process's addressable memory /// * `EIO` - an I/O error occurred /// * `ENOSPC` - the device containing the file descriptor has no room for data /// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed diff --git a/src/libstd/sys/redox/syscall/flag.rs b/src/libstd/sys/redox/syscall/flag.rs index 0f61b9fa77b52..0f1a2c2315973 100644 --- a/src/libstd/sys/redox/syscall/flag.rs +++ b/src/libstd/sys/redox/syscall/flag.rs @@ -113,4 +113,46 @@ pub const SA_RESTART: usize = 0x10000000; pub const SA_NODEFER: usize = 0x40000000; pub const SA_RESETHAND: usize = 0x80000000; -pub const WNOHANG: usize = 1; +pub const WNOHANG: usize = 0x01; +pub const WUNTRACED: usize = 0x02; +pub const WCONTINUED: usize = 0x08; + +/// True if status indicates the child is stopped. +pub fn wifstopped(status: usize) -> bool { + (status & 0xff) == 0x7f +} + +/// If wifstopped(status), the signal that stopped the child. +pub fn wstopsig(status: usize) -> usize { + (status >> 8) & 0xff +} + +/// True if status indicates the child continued after a stop. +pub fn wifcontinued(status: usize) -> bool { + status == 0xffff +} + +/// True if STATUS indicates termination by a signal. +pub fn wifsignaled(status: usize) -> bool { + ((status & 0x7f) + 1) as i8 >= 2 +} + +/// If wifsignaled(status), the terminating signal. +pub fn wtermsig(status: usize) -> usize { + status & 0x7f +} + +/// True if status indicates normal termination. +pub fn wifexited(status: usize) -> bool { + wtermsig(status) == 0 +} + +/// If wifexited(status), the exit status. +pub fn wexitstatus(status: usize) -> usize { + (status >> 8) & 0xff +} + +/// True if status indicates a core dump was created. +pub fn wcoredump(status: usize) -> bool { + (status & 0x80) != 0 +} diff --git a/src/libstd/sys/redox/syscall/number.rs b/src/libstd/sys/redox/syscall/number.rs index 45cb40e390840..1e187565a675c 100644 --- a/src/libstd/sys/redox/syscall/number.rs +++ b/src/libstd/sys/redox/syscall/number.rs @@ -36,6 +36,7 @@ pub const SYS_FCHMOD: usize = SYS_CLASS_FILE | 94; pub const SYS_FCHOWN: usize = SYS_CLASS_FILE | 207; pub const SYS_FCNTL: usize = SYS_CLASS_FILE | 55; pub const SYS_FEVENT: usize = SYS_CLASS_FILE | 927; +pub const SYS_FEXEC: usize = SYS_CLASS_FILE | 11; pub const SYS_FMAP: usize = SYS_CLASS_FILE | 90; pub const SYS_FUNMAP: usize = SYS_CLASS_FILE | 91; pub const SYS_FPATH: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 928; @@ -50,7 +51,6 @@ pub const SYS_BRK: usize = 45; pub const SYS_CHDIR: usize = 12; pub const SYS_CLOCK_GETTIME: usize = 265; pub const SYS_CLONE: usize = 120; -pub const SYS_EXECVE: usize = 11; pub const SYS_EXIT: usize = 1; pub const SYS_FUTEX: usize = 240; pub const SYS_GETCWD: usize = 183; diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index af33d2636fb1f..5a81d6dfb672e 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -46,7 +46,7 @@ impl FileDesc { pub fn raw(&self) -> c_int { self.fd } - /// Extracts the actual filedescriptor without closing it. + /// Extracts the actual file descriptor without closing it. pub fn into_raw(self) -> c_int { let fd = self.fd; mem::forget(self); diff --git a/src/libstd/sys/unix/rwlock.rs b/src/libstd/sys/unix/rwlock.rs index c754d5b8359a9..fcd6f7a27b6e3 100644 --- a/src/libstd/sys/unix/rwlock.rs +++ b/src/libstd/sys/unix/rwlock.rs @@ -14,7 +14,7 @@ use sync::atomic::{AtomicUsize, Ordering}; pub struct RWLock { inner: UnsafeCell, - write_locked: UnsafeCell, + write_locked: UnsafeCell, // guarded by the `inner` RwLock num_readers: AtomicUsize, } @@ -52,13 +52,13 @@ impl RWLock { // allow that because it could lead to aliasing issues. if r == libc::EAGAIN { panic!("rwlock maximum reader count exceeded"); - } else if r == libc::EDEADLK || *self.write_locked.get() { + } else if r == libc::EDEADLK || (r == 0 && *self.write_locked.get()) { if r == 0 { self.raw_unlock(); } panic!("rwlock read lock would result in deadlock"); } else { - debug_assert_eq!(r, 0); + assert_eq!(r, 0); self.num_readers.fetch_add(1, Ordering::Relaxed); } } diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index a57b8dc723767..8a845efd41362 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -233,7 +233,7 @@ pub use self::local::{LocalKey, AccessError}; /// /// You may want to use [`spawn`] instead of [`thread::spawn`], when you want /// to recover from a failure to launch a thread, indeed the free function will -/// panick where the `Builder` method will return a [`io::Result`]. +/// panic where the `Builder` method will return a [`io::Result`]. /// /// # Examples /// diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 808e19d6f120f..227017a9073fe 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -18,7 +18,6 @@ pub use util::parser::ExprPrecedence; use ext::hygiene::{Mark, SyntaxContext}; use print::pprust; use ptr::P; -use rustc_data_structures::indexed_vec; use rustc_data_structures::indexed_vec::Idx; #[cfg(target_arch = "x86_64")] use rustc_data_structures::static_assert; @@ -33,7 +32,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use serialize::{self, Decoder, Encoder}; use std::fmt; -use std::u32; pub use rustc_target::abi::FloatTy; @@ -215,71 +213,54 @@ pub struct ParenthesisedArgs { pub output: Option>, } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub struct NodeId(u32); - -impl NodeId { - pub fn new(x: usize) -> NodeId { - assert!(x < (u32::MAX as usize)); - NodeId(x as u32) - } - - pub fn from_u32(x: u32) -> NodeId { - NodeId(x) - } - - pub fn as_usize(&self) -> usize { - self.0 as usize +// hack to ensure that we don't try to access the private parts of `NodeId` in this module +mod node_id_inner { + use rustc_data_structures::indexed_vec::Idx; + newtype_index! { + pub struct NodeId { + ENCODABLE = custom + DEBUG_FORMAT = "NodeId({})" + } } +} - pub fn as_u32(&self) -> u32 { - self.0 - } +pub use self::node_id_inner::NodeId; +impl NodeId { pub fn placeholder_from_mark(mark: Mark) -> Self { - NodeId(mark.as_u32()) + NodeId::from_u32(mark.as_u32()) } pub fn placeholder_to_mark(self) -> Mark { - Mark::from_u32(self.0) + Mark::from_u32(self.as_u32()) } } impl fmt::Display for NodeId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.0, f) + fmt::Display::fmt(&self.as_u32(), f) } } impl serialize::UseSpecializedEncodable for NodeId { fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_u32(self.0) + s.emit_u32(self.as_u32()) } } impl serialize::UseSpecializedDecodable for NodeId { fn default_decode(d: &mut D) -> Result { - d.read_u32().map(NodeId) - } -} - -impl indexed_vec::Idx for NodeId { - fn new(idx: usize) -> Self { - NodeId::new(idx) - } - - fn index(self) -> usize { - self.as_usize() + d.read_u32().map(NodeId::from_u32) } } /// Node id used to represent the root of the crate. -pub const CRATE_NODE_ID: NodeId = NodeId(0); +pub const CRATE_NODE_ID: NodeId = NodeId::from_u32_const(0); /// When parsing and doing expansions, we initially give all AST nodes this AST /// node value. Then later, in the renumber pass, we renumber them to have /// small, positive ids. -pub const DUMMY_NODE_ID: NodeId = NodeId(!0); +pub const DUMMY_NODE_ID: NodeId = NodeId::MAX; /// A modifier on a bound, currently this is only used for `?Sized`, where the /// modifier is `Maybe`. Negative bounds should also be handled here. diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index e9a6535cba1d2..9bbd59e09be15 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -26,6 +26,7 @@ #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] #![feature(str_escape)] +#![feature(step_trait)] #![feature(try_trait)] #![feature(unicode_internals)] @@ -37,7 +38,7 @@ extern crate serialize; #[macro_use] extern crate log; pub extern crate rustc_errors as errors; extern crate syntax_pos; -extern crate rustc_data_structures; +#[macro_use] extern crate rustc_data_structures; extern crate rustc_target; #[macro_use] extern crate scoped_tls; #[macro_use] diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 29bd63d28c5ec..cfdd4340a19fe 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -150,7 +150,7 @@ impl TokenTree { } } - /// Modify the `TokenTree`'s span inplace. + /// Modify the `TokenTree`'s span in-place. pub fn set_span(&mut self, span: Span) { match *self { TokenTree::Token(ref mut sp, _) => *sp = span, diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index dd90ef06c3929..2f6b306e8f8ba 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -68,7 +68,7 @@ //! The `i32`s in `B` and `C0` don't have an identifier, so the //! `Option`s would be `None` for them. //! -//! In the static cases, the structure is summarised, either into the just +//! In the static cases, the structure is summarized, either into the just //! spans of the fields or a list of spans and the field idents (for tuple //! structs and record structs, respectively), or a list of these, for //! enums (one for each variant). For empty struct and empty enum diff --git a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs index f2f14f84923c0..2c5de33232754 100644 --- a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs +++ b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs @@ -43,7 +43,7 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree]) &[], Edition::Edition2015, // not used... - NodeId::new(0)); + NodeId::from_u32(0)); let map = match TokenTree::parse(cx, &mbe_matcher, args.iter().cloned().collect()) { Success(map) => map, Failure(_, tok) => { diff --git a/src/test/ui/issues/issue-54348.rs b/src/test/ui/issues/issue-54348.rs new file mode 100644 index 0000000000000..b980290391d3a --- /dev/null +++ b/src/test/ui/issues/issue-54348.rs @@ -0,0 +1,5 @@ +fn main() { + [1][0u64 as usize]; + [1][1.5 as usize]; // ERROR index out of bounds + [1][1u64 as usize]; // ERROR index out of bounds +} diff --git a/src/test/ui/issues/issue-54348.stderr b/src/test/ui/issues/issue-54348.stderr new file mode 100644 index 0000000000000..a9f1b4942584d --- /dev/null +++ b/src/test/ui/issues/issue-54348.stderr @@ -0,0 +1,16 @@ +error: index out of bounds: the len is 1 but the index is 1 + --> $DIR/issue-54348.rs:3:5 + | +LL | [1][1.5 as usize]; // ERROR index out of bounds + | ^^^^^^^^^^^^^^^^^ + | + = note: #[deny(const_err)] on by default + +error: index out of bounds: the len is 1 but the index is 1 + --> $DIR/issue-54348.rs:4:5 + | +LL | [1][1u64 as usize]; // ERROR index out of bounds + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/issues/issue-55587.rs b/src/test/ui/issues/issue-55587.rs new file mode 100644 index 0000000000000..8b78749f6529a --- /dev/null +++ b/src/test/ui/issues/issue-55587.rs @@ -0,0 +1,5 @@ +use std::path::Path; + +fn main() { + let Path::new(); //~ ERROR expected tuple struct/variant +} diff --git a/src/test/ui/issues/issue-55587.stderr b/src/test/ui/issues/issue-55587.stderr new file mode 100644 index 0000000000000..876fb4391b1bc --- /dev/null +++ b/src/test/ui/issues/issue-55587.stderr @@ -0,0 +1,9 @@ +error[E0164]: expected tuple struct/variant, found method `::new` + --> $DIR/issue-55587.rs:4:9 + | +LL | let Path::new(); //~ ERROR expected tuple struct/variant + | ^^^^^^^^^^^ not a tuple variant or struct + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0164`. diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed index d16859df79e25..f0aee8a51f18b 100644 --- a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed +++ b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed @@ -20,4 +20,10 @@ fn main() { //~^ WARN `...` range patterns are deprecated _ => {} } + + match &despondency { + &(1..=2) => {} + //~^ WARN `...` range patterns are deprecated + _ => {} + } } diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.rs b/src/test/ui/lint/inclusive-range-pattern-syntax.rs index 9d418aec0858f..97bc04faa774b 100644 --- a/src/test/ui/lint/inclusive-range-pattern-syntax.rs +++ b/src/test/ui/lint/inclusive-range-pattern-syntax.rs @@ -20,4 +20,10 @@ fn main() { //~^ WARN `...` range patterns are deprecated _ => {} } + + match &despondency { + &1...2 => {} + //~^ WARN `...` range patterns are deprecated + _ => {} + } } diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr index de04fed589b23..b13afdbc023d4 100644 --- a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr +++ b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr @@ -10,3 +10,9 @@ note: lint level defined here LL | #![warn(ellipsis_inclusive_range_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: `...` range patterns are deprecated + --> $DIR/inclusive-range-pattern-syntax.rs:25:9 + | +LL | &1...2 => {} + | ^^^^^^ help: use `..=` for an inclusive range: `&(1..=2)` + diff --git a/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.nll.stderr b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.nll.stderr new file mode 100644 index 0000000000000..c308562c0cc76 --- /dev/null +++ b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.nll.stderr @@ -0,0 +1,20 @@ +error[E0597]: `_thing1` does not live long enough + --> $DIR/issue-54382-use-span-of-tail-of-block.rs:7:29 + | +LL | D("other").next(&_thing1) + | ----------------^^^^^^^^- + | | | + | | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +LL | } +LL | } + | - `_thing1` dropped here while still borrowed +LL | +LL | ; + | - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + | + = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.rs b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.rs new file mode 100644 index 0000000000000..99eafe0e9d18f --- /dev/null +++ b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.rs @@ -0,0 +1,28 @@ +fn main() { + { + let mut _thing1 = D(Box::new("thing1")); + { + let _thing2 = D("thing2"); + side_effects(); + D("other").next(&_thing1) + } + } + + ; +} + +#[derive(Debug)] +struct D(T); + +impl Drop for D { + fn drop(&mut self) { + println!("dropping {:?})", self); + } +} + +impl D { + fn next(&self, _other: U) -> D { D(_other) } + fn end(&self) { } +} + +fn side_effects() { } diff --git a/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.stderr b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.stderr new file mode 100644 index 0000000000000..eeba7d6bb445f --- /dev/null +++ b/src/test/ui/nll/issue-54382-use-span-of-tail-of-block.stderr @@ -0,0 +1,15 @@ +error[E0597]: `_thing1` does not live long enough + --> $DIR/issue-54382-use-span-of-tail-of-block.rs:7:30 + | +LL | D("other").next(&_thing1) + | ^^^^^^^ borrowed value does not live long enough +LL | } +LL | } + | - `_thing1` dropped here while still borrowed +LL | +LL | ; + | - borrowed value needs to live until here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/range/range-inclusive-pattern-precedence.stderr b/src/test/ui/range/range-inclusive-pattern-precedence.stderr index cd5ce3035c683..6fa67a5d4fa30 100644 --- a/src/test/ui/range/range-inclusive-pattern-precedence.stderr +++ b/src/test/ui/range/range-inclusive-pattern-precedence.stderr @@ -11,10 +11,10 @@ LL | box 10..=15 => {} | ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)` warning: `...` range patterns are deprecated - --> $DIR/range-inclusive-pattern-precedence.rs:24:11 + --> $DIR/range-inclusive-pattern-precedence.rs:24:9 | LL | &0...9 => {} - | ^^^ help: use `..=` for an inclusive range + | ^^^^^^ help: use `..=` for an inclusive range: `&(0..=9)` | note: lint level defined here --> $DIR/range-inclusive-pattern-precedence.rs:19:9