diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index 085f243785c..1c9f6e1ab28 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -69,6 +69,17 @@ fn main() { .arg("unstable-options"); } cmd.arg("--generate-redirect-pages"); + has_unstable = true; + } + + // Needed to be able to run all rustdoc tests. + if let Some(ref x) = env::var_os("RUSTDOC_RESOURCE_SUFFIX") { + // This "unstable-options" can be removed when `--resource-suffix` is stabilized + if !has_unstable { + cmd.arg("-Z") + .arg("unstable-options"); + } + cmd.arg("--resource-suffix").arg(x); } if verbose > 1 { diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 2ea6be55210..d831d2f1af2 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -343,12 +343,9 @@ fn invoke_rustdoc( .arg("--html-before-content").arg(&version_info) .arg("--html-in-header").arg(&header) .arg("--markdown-no-toc") - .arg("--markdown-playground-url") - .arg("https://play.rust-lang.org/") - .arg("-o").arg(&out) - .arg(&path) - .arg("--markdown-css") - .arg("../rust.css"); + .arg("--markdown-playground-url").arg("https://play.rust-lang.org/") + .arg("-o").arg(&out).arg(&path) + .arg("--markdown-css").arg("../rust.css"); builder.run(&mut cmd); } @@ -431,8 +428,7 @@ impl Step for Standalone { .arg("--html-in-header").arg(&favicon) .arg("--markdown-no-toc") .arg("--index-page").arg(&builder.src.join("src/doc/index.md")) - .arg("--markdown-playground-url") - .arg("https://play.rust-lang.org/") + .arg("--markdown-playground-url").arg("https://play.rust-lang.org/") .arg("-o").arg(&out) .arg(&path); @@ -523,6 +519,7 @@ impl Step for Std { .arg("--markdown-css").arg("rust.css") .arg("--markdown-no-toc") .arg("--generate-redirect-pages") + .arg("--resource-suffix").arg(crate::channel::CFG_RELEASE_NUM) .arg("--index-page").arg(&builder.src.join("src/doc/index.md")); builder.run(&mut cargo); @@ -589,6 +586,7 @@ impl Step for Test { cargo.arg("--no-deps") .arg("-p").arg("test") + .env("RUSTDOC_RESOURCE_SUFFIX", crate::channel::CFG_RELEASE_NUM) .env("RUSTDOC_GENERATE_REDIRECT_PAGES", "1"); builder.run(&mut cargo); @@ -660,6 +658,7 @@ impl Step for WhitelistedRustc { // for which docs must be built. for krate in &["proc_macro"] { cargo.arg("-p").arg(krate) + .env("RUSTDOC_RESOURCE_SUFFIX", crate::channel::CFG_RELEASE_NUM) .env("RUSTDOC_GENERATE_REDIRECT_PAGES", "1"); } @@ -890,6 +889,7 @@ impl Step for ErrorIndex { ); index.arg("html"); index.arg(out.join("error-index.html")); + index.arg(crate::channel::CFG_RELEASE_NUM); // FIXME: shouldn't have to pass this env var index.env("CFG_BUILD", &builder.config.build) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 0c3daea7a3c..d245b3e98d3 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -190,6 +190,7 @@ const LLVM_TOOLS: &[&str] = &[ "llvm-readobj", // used to get information from ELFs/objects that the other tools don't provide "llvm-size", // used to prints the size of the linker sections of a program "llvm-strip", // used to discard symbols from binary files to reduce their size + "llvm-ar" // used for creating and modifying archive files ]; /// A structure representing a Rust compiler. diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index 5cc9c25c21e..231a1f199bd 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -47,7 +47,7 @@ impl fmt::Debug for c_void { /// Basic implementation of a `va_list`. #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), - all(target_arch = "aarch4", target_os = "ios"), + all(target_arch = "aarch64", target_os = "ios"), windows))] #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ @@ -59,6 +59,7 @@ extern { #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), + all(target_arch = "aarch64", target_os = "ios"), windows))] impl fmt::Debug for VaListImpl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -67,11 +68,11 @@ impl fmt::Debug for VaListImpl { } /// AArch64 ABI implementation of a `va_list`. See the -/// [Aarch64 Procedure Call Standard] for more details. +/// [AArch64 Procedure Call Standard] for more details. /// /// [AArch64 Procedure Call Standard]: /// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf -#[cfg(all(target_arch = "aarch64", not(windows)))] +#[cfg(all(target_arch = "aarch64", not(target_os = "ios"), not(windows)))] #[repr(C)] #[derive(Debug)] #[unstable(feature = "c_variadic", @@ -193,14 +194,14 @@ impl<'a> VaList<'a> { where F: for<'copy> FnOnce(VaList<'copy>) -> R { #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), - all(target_arch = "aarch4", target_os = "ios"), + all(target_arch = "aarch64", target_os = "ios"), windows))] let mut ap = va_copy(self); #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), - not(windows)))] + not(windows), not(all(target_arch = "aarch64", target_os = "ios"))))] let mut ap_inner = va_copy(self); #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), - not(windows)))] + not(windows), not(all(target_arch = "aarch64", target_os = "ios"))))] let mut ap = VaList(&mut ap_inner); let ret = f(VaList(ap.0)); va_end(&mut ap); @@ -216,10 +217,11 @@ extern "rust-intrinsic" { /// Copies the current location of arglist `src` to the arglist `dst`. #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), + all(target_arch = "aarch64", target_os = "ios"), windows))] fn va_copy<'a>(src: &VaList<'a>) -> VaList<'a>; #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), - not(windows)))] + not(windows), not(all(target_arch = "aarch64", target_os = "ios"))))] fn va_copy(src: &VaList) -> VaListImpl; /// Loads an argument of type `T` from the `va_list` `ap` and increment the diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index ad8ce1af1f6..d2ee9b11b36 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -1,4 +1,6 @@ -/// Entry point of thread panic. For details, see `std::macros`. +/// Panics the current thread. +/// +/// For details, see `std::macros`. #[macro_export] #[allow_internal_unstable(core_panic, __rust_unstable_column)] #[stable(feature = "core", since = "1.6.0")] @@ -132,7 +134,7 @@ macro_rules! assert_ne { }); } -/// Ensure that a boolean expression is `true` at runtime. +/// Asserts that a boolean expression is `true` at runtime. /// /// This will invoke the [`panic!`] macro if the provided expression cannot be /// evaluated to `true` at runtime. @@ -236,8 +238,7 @@ macro_rules! debug_assert_ne { ($($arg:tt)*) => (if cfg!(debug_assertions) { assert_ne!($($arg)*); }) } -/// Helper macro for reducing boilerplate code for matching `Result` together -/// with converting downstream errors. +/// Unwraps a result or propagates its error. /// /// The `?` operator was added to replace `try!` and should be used instead. /// Furthermore, `try` is a reserved word in Rust 2018, so if you must use @@ -312,7 +313,7 @@ macro_rules! r#try { ($expr:expr,) => (r#try!($expr)); } -/// Write formatted data into a buffer. +/// Writes formatted data into a buffer. /// /// This macro accepts a format string, a list of arguments, and a 'writer'. Arguments will be /// formatted according to the specified format string and the result will be passed to the writer. @@ -434,7 +435,7 @@ macro_rules! writeln { ); } -/// A utility macro for indicating unreachable code. +/// Indicates unreachable code. /// /// This is useful any time that the compiler can't determine that some code is unreachable. For /// example: @@ -502,7 +503,7 @@ macro_rules! unreachable { }); } -/// A standardized placeholder for marking unfinished code. +/// Indicates unfinished code. /// /// This can be useful if you are prototyping and are just looking to have your /// code type-check, or if you're implementing a trait that requires multiple @@ -559,10 +560,10 @@ macro_rules! unimplemented { ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)*))); } -/// A standardized placeholder for marking unfinished code. +/// Indicates unfinished code. /// /// This can be useful if you are prototyping and are just looking to have your -/// code typecheck. `todo!` works exactly like `unimplemented!`, there only +/// code typecheck. `todo!` works exactly like `unimplemented!`. The only /// difference between the two macros is the name. /// /// # Panics @@ -618,7 +619,7 @@ macro_rules! todo { ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)*))); } -/// A macro to create an array of [`MaybeUninit`] +/// Creates an array of [`MaybeUninit`]. /// /// This macro constructs an uninitialized array of the type `[MaybeUninit; N]`. /// @@ -645,7 +646,7 @@ macro_rules! uninitialized_array { #[cfg(rustdoc)] mod builtin { - /// Unconditionally causes compilation to fail with the given error message when encountered. + /// Causes compilation to fail with the given error message when encountered. /// /// For more information, see the documentation for [`std::compile_error!`]. /// @@ -657,7 +658,7 @@ mod builtin { ($msg:expr,) => ({ /* compiler built-in */ }); } - /// The core macro for formatted string creation & output. + /// Constructs parameters for the other string-formatting macros. /// /// For more information, see the documentation for [`std::format_args!`]. /// @@ -669,7 +670,7 @@ mod builtin { ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }); } - /// Inspect an environment variable at compile time. + /// Inspects an environment variable at compile time. /// /// For more information, see the documentation for [`std::env!`]. /// @@ -681,7 +682,7 @@ mod builtin { ($name:expr,) => ({ /* compiler built-in */ }); } - /// Optionally inspect an environment variable at compile time. + /// Optionally inspects an environment variable at compile time. /// /// For more information, see the documentation for [`std::option_env!`]. /// @@ -693,7 +694,7 @@ mod builtin { ($name:expr,) => ({ /* compiler built-in */ }); } - /// Concatenate identifiers into one identifier. + /// Concatenates identifiers into one identifier. /// /// For more information, see the documentation for [`std::concat_idents!`]. /// @@ -717,7 +718,7 @@ mod builtin { ($($e:expr,)*) => ({ /* compiler built-in */ }); } - /// A macro which expands to the line number on which it was invoked. + /// Expands to the line number on which it was invoked. /// /// For more information, see the documentation for [`std::line!`]. /// @@ -726,7 +727,7 @@ mod builtin { #[rustc_doc_only_macro] macro_rules! line { () => ({ /* compiler built-in */ }) } - /// A macro which expands to the column number on which it was invoked. + /// Expands to the column number on which it was invoked. /// /// For more information, see the documentation for [`std::column!`]. /// @@ -735,7 +736,7 @@ mod builtin { #[rustc_doc_only_macro] macro_rules! column { () => ({ /* compiler built-in */ }) } - /// A macro which expands to the file name from which it was invoked. + /// Expands to the file name from which it was invoked. /// /// For more information, see the documentation for [`std::file!`]. /// @@ -744,7 +745,7 @@ mod builtin { #[rustc_doc_only_macro] macro_rules! file { () => ({ /* compiler built-in */ }) } - /// A macro which stringifies its arguments. + /// Stringifies its arguments. /// /// For more information, see the documentation for [`std::stringify!`]. /// @@ -786,7 +787,7 @@ mod builtin { #[rustc_doc_only_macro] macro_rules! module_path { () => ({ /* compiler built-in */ }) } - /// Boolean evaluation of configuration flags, at compile-time. + /// Evaluates boolean combinations of configuration flags, at compile-time. /// /// For more information, see the documentation for [`std::cfg!`]. /// @@ -795,7 +796,7 @@ mod builtin { #[rustc_doc_only_macro] macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) } - /// Parse a file as an expression or an item according to the context. + /// Parses a file as an expression or an item according to the context. /// /// For more information, see the documentation for [`std::include!`]. /// @@ -807,7 +808,7 @@ mod builtin { ($file:expr,) => ({ /* compiler built-in */ }); } - /// Ensure that a boolean expression is `true` at runtime. + /// Asserts that a boolean expression is `true` at runtime. /// /// For more information, see the documentation for [`std::assert!`]. /// diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index bce528189ad..39069b66f29 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -163,7 +163,7 @@ pub trait Visitor<'v> : Sized { /// but cannot supply a `Map`; see `nested_visit_map` for advice. #[allow(unused_variables)] fn visit_nested_item(&mut self, id: ItemId) { - let opt_item = self.nested_visit_map().inter().map(|map| map.expect_item(id.id)); + let opt_item = self.nested_visit_map().inter().map(|map| map.expect_item_by_hir_id(id.id)); if let Some(item) = opt_item { self.visit_item(item); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 891210511ca..7dfb16602a3 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -51,7 +51,6 @@ use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::sync::Lrc; use std::collections::{BTreeSet, BTreeMap}; -use std::fmt::Debug; use std::mem; use smallvec::SmallVec; use syntax::attr; @@ -82,7 +81,7 @@ pub struct LoweringContext<'a> { resolver: &'a mut dyn Resolver, /// The items being lowered are collected here. - items: BTreeMap, + items: BTreeMap, trait_items: BTreeMap, impl_items: BTreeMap, @@ -321,7 +320,7 @@ enum AnonymousLifetimeMode { PassThrough, } -struct ImplTraitTypeIdVisitor<'a> { ids: &'a mut SmallVec<[hir::ItemId; 1]> } +struct ImplTraitTypeIdVisitor<'a> { ids: &'a mut SmallVec<[NodeId; 1]> } impl<'a, 'b> Visitor<'a> for ImplTraitTypeIdVisitor<'b> { fn visit_ty(&mut self, ty: &'a Ty) { @@ -330,7 +329,7 @@ impl<'a, 'b> Visitor<'a> for ImplTraitTypeIdVisitor<'b> { | TyKind::BareFn(_) => return, - TyKind::ImplTrait(id, _) => self.ids.push(hir::ItemId { id }), + TyKind::ImplTrait(id, _) => self.ids.push(id), _ => {}, } visit::walk_ty(self, ty); @@ -361,9 +360,40 @@ impl<'a> LoweringContext<'a> { lctx: &'lcx mut LoweringContext<'interner>, } + impl MiscCollector<'_, '_> { + fn allocate_use_tree_hir_id_counters( + &mut self, + tree: &UseTree, + owner: DefIndex, + ) { + match tree.kind { + UseTreeKind::Simple(_, id1, id2) => { + for &id in &[id1, id2] { + self.lctx.resolver.definitions().create_def_with_parent( + owner, + id, + DefPathData::Misc, + DefIndexAddressSpace::High, + Mark::root(), + tree.prefix.span, + ); + self.lctx.allocate_hir_id_counter(id); + } + } + UseTreeKind::Glob => (), + UseTreeKind::Nested(ref trees) => { + for &(ref use_tree, id) in trees { + let hir_id = self.lctx.allocate_hir_id_counter(id).hir_id; + self.allocate_use_tree_hir_id_counters(use_tree, hir_id.owner); + } + } + } + } + } + impl<'lcx, 'interner> Visitor<'lcx> for MiscCollector<'lcx, 'interner> { fn visit_item(&mut self, item: &'lcx Item) { - self.lctx.allocate_hir_id_counter(item.id, item); + let hir_id = self.lctx.allocate_hir_id_counter(item.id).hir_id; match item.node { ItemKind::Struct(_, ref generics) @@ -383,18 +413,21 @@ impl<'a> LoweringContext<'a> { .count(); self.lctx.type_def_lifetime_params.insert(def_id, count); } + ItemKind::Use(ref use_tree) => { + self.allocate_use_tree_hir_id_counters(use_tree, hir_id.owner); + } _ => {} } visit::walk_item(self, item); } fn visit_trait_item(&mut self, item: &'lcx TraitItem) { - self.lctx.allocate_hir_id_counter(item.id, item); + self.lctx.allocate_hir_id_counter(item.id); visit::walk_trait_item(self, item); } fn visit_impl_item(&mut self, item: &'lcx ImplItem) { - self.lctx.allocate_hir_id_counter(item.id, item); + self.lctx.allocate_hir_id_counter(item.id); visit::walk_impl_item(self, item); } } @@ -434,17 +467,16 @@ impl<'a> LoweringContext<'a> { } fn visit_item(&mut self, item: &'lcx Item) { - let mut item_lowered = true; + let mut item_hir_id = None; self.lctx.with_hir_id_owner(item.id, |lctx| { if let Some(hir_item) = lctx.lower_item(item) { - lctx.insert_item(item.id, hir_item); - } else { - item_lowered = false; + item_hir_id = Some(hir_item.hir_id); + lctx.insert_item(hir_item); } }); - if item_lowered { - let item_generics = match self.lctx.items.get(&item.id).unwrap().node { + if let Some(hir_id) = item_hir_id { + let item_generics = match self.lctx.items.get(&hir_id).unwrap().node { hir::ItemKind::Impl(_, _, _, ref generics, ..) | hir::ItemKind::Trait(_, _, ref generics, ..) => { generics.params.clone() @@ -516,20 +548,21 @@ impl<'a> LoweringContext<'a> { } } - fn insert_item(&mut self, id: NodeId, item: hir::Item) { + fn insert_item(&mut self, item: hir::Item) { + let id = item.hir_id; + // FIXME: Use debug_asset-rt + assert_eq!(id.local_id, hir::ItemLocalId::from_u32(0)); self.items.insert(id, item); self.modules.get_mut(&self.current_module).unwrap().items.insert(id); } - fn allocate_hir_id_counter(&mut self, owner: NodeId, debug: &T) -> LoweredNodeId { - if self.item_local_id_counters.insert(owner, 0).is_some() { - bug!( - "Tried to allocate item_local_id_counter for {:?} twice", - debug - ); - } + fn allocate_hir_id_counter(&mut self, owner: NodeId) -> LoweredNodeId { + // Setup the counter if needed + self.item_local_id_counters.entry(owner).or_insert(0); // Always allocate the first `HirId` for the owner itself. - self.lower_node_id_with_owner(owner, owner) + let lowered = self.lower_node_id_with_owner(owner, owner); + debug_assert_eq!(lowered.hir_id.local_id.as_u32(), 0); + lowered } fn lower_node_id_generic(&mut self, ast_node_id: NodeId, alloc_hir_id: F) -> LoweredNodeId @@ -1381,7 +1414,7 @@ impl<'a> LoweringContext<'a> { .opt_def_index(exist_ty_node_id) .unwrap(); - self.allocate_hir_id_counter(exist_ty_node_id, &"existential impl trait"); + self.allocate_hir_id_counter(exist_ty_node_id); let hir_bounds = self.with_hir_id_owner(exist_ty_node_id, lower_bounds); @@ -1422,10 +1455,10 @@ impl<'a> LoweringContext<'a> { // Insert the item into the global list. This usually happens // automatically for all AST items. But this existential type item // does not actually exist in the AST. - lctx.insert_item(exist_ty_id.node_id, exist_ty_item); + lctx.insert_item(exist_ty_item); // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. - hir::TyKind::Def(hir::ItemId { id: exist_ty_id.node_id }, lifetimes) + hir::TyKind::Def(hir::ItemId { id: exist_ty_id.hir_id }, lifetimes) }) } @@ -2002,9 +2035,9 @@ impl<'a> LoweringContext<'a> { ) } - fn lower_local(&mut self, l: &Local) -> (hir::Local, SmallVec<[hir::ItemId; 1]>) { + fn lower_local(&mut self, l: &Local) -> (hir::Local, SmallVec<[NodeId; 1]>) { let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(l.id); - let mut ids = SmallVec::<[hir::ItemId; 1]>::new(); + let mut ids = SmallVec::<[NodeId; 1]>::new(); if self.sess.features_untracked().impl_trait_in_bindings { if let Some(ref ty) = l.ty { let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids }; @@ -3065,7 +3098,6 @@ impl<'a> LoweringContext<'a> { } } - let parent_def_index = self.current_hir_id_owner.last().unwrap().0; let mut defs = self.expect_full_def_from_use(id); // We want to return *something* from this function, so hold onto the first item // for later. @@ -3084,14 +3116,6 @@ impl<'a> LoweringContext<'a> { seg.id = self.sess.next_node_id(); } let span = path.span; - self.resolver.definitions().create_def_with_parent( - parent_def_index, - new_node_id, - DefPathData::Misc, - DefIndexAddressSpace::High, - Mark::root(), - span); - self.allocate_hir_id_counter(new_node_id, &path); self.with_hir_id_owner(new_node_id, |this| { let new_id = this.lower_node_id(new_node_id); @@ -3114,7 +3138,6 @@ impl<'a> LoweringContext<'a> { let vis = respan(vis.span, vis_kind); this.insert_item( - new_id.node_id, hir::Item { hir_id: new_id.hir_id, ident, @@ -3174,8 +3197,6 @@ impl<'a> LoweringContext<'a> { // Add all the nested `PathListItem`s to the HIR. for &(ref use_tree, id) in trees { - self.allocate_hir_id_counter(id, &use_tree); - let LoweredNodeId { node_id: new_id, hir_id: new_hir_id, @@ -3219,7 +3240,6 @@ impl<'a> LoweringContext<'a> { let vis = respan(vis.span, vis_kind); this.insert_item( - new_id, hir::Item { hir_id: new_hir_id, ident, @@ -3443,17 +3463,17 @@ impl<'a> LoweringContext<'a> { } fn lower_item_id(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { - match i.node { + let node_ids = match i.node { ItemKind::Use(ref use_tree) => { - let mut vec = smallvec![hir::ItemId { id: i.id }]; + let mut vec = smallvec![i.id]; self.lower_item_id_use_tree(use_tree, i.id, &mut vec); vec } ItemKind::MacroDef(..) => SmallVec::new(), ItemKind::Fn(..) | - ItemKind::Impl(.., None, _, _) => smallvec![hir::ItemId { id: i.id }], + ItemKind::Impl(.., None, _, _) => smallvec![i.id], ItemKind::Static(ref ty, ..) => { - let mut ids = smallvec![hir::ItemId { id: i.id }]; + let mut ids = smallvec![i.id]; if self.sess.features_untracked().impl_trait_in_bindings { let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids }; visitor.visit_ty(ty); @@ -3461,25 +3481,29 @@ impl<'a> LoweringContext<'a> { ids }, ItemKind::Const(ref ty, ..) => { - let mut ids = smallvec![hir::ItemId { id: i.id }]; + let mut ids = smallvec![i.id]; if self.sess.features_untracked().impl_trait_in_bindings { let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids }; visitor.visit_ty(ty); } ids }, - _ => smallvec![hir::ItemId { id: i.id }], - } + _ => smallvec![i.id], + }; + + node_ids.into_iter().map(|node_id| hir::ItemId { + id: self.allocate_hir_id_counter(node_id).hir_id + }).collect() } fn lower_item_id_use_tree(&mut self, tree: &UseTree, base_id: NodeId, - vec: &mut SmallVec<[hir::ItemId; 1]>) + vec: &mut SmallVec<[NodeId; 1]>) { match tree.kind { UseTreeKind::Nested(ref nested_vec) => for &(ref nested, id) in nested_vec { - vec.push(hir::ItemId { id }); + vec.push(id); self.lower_item_id_use_tree(nested, id, vec); }, UseTreeKind::Glob => {} @@ -3488,7 +3512,7 @@ impl<'a> LoweringContext<'a> { .skip(1) .zip([id1, id2].iter()) { - vec.push(hir::ItemId { id }); + vec.push(id); } }, } @@ -4604,6 +4628,7 @@ impl<'a> LoweringContext<'a> { let mut ids: SmallVec<[hir::Stmt; 1]> = item_ids .into_iter() .map(|item_id| { + let item_id = hir::ItemId { id: self.lower_node_id(item_id).hir_id }; let LoweredNodeId { node_id: _, hir_id } = self.next_id(); hir::Stmt { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 2ffb4959951..f906ff9963d 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -609,7 +609,7 @@ impl<'hir> Map<'hir> { let module = &self.forest.krate.modules[&node_id]; for id in &module.items { - visitor.visit_item(self.expect_item(*id)); + visitor.visit_item(self.expect_item_by_hir_id(*id)); } for id in &module.trait_items { @@ -1293,7 +1293,7 @@ pub fn map_crate<'hir>(sess: &crate::session::Session, impl<'hir> print::PpAnn for Map<'hir> { fn nested(&self, state: &mut print::State<'_>, nested: print::Nested) -> io::Result<()> { match nested { - Nested::Item(id) => state.print_item(self.expect_item(id.id)), + Nested::Item(id) => state.print_item(self.expect_item_by_hir_id(id.id)), Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)), Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), Nested::Body(id) => state.print_expr(&self.body(id).value), diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 1bf7eed71bf..8509ddaccf7 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -698,7 +698,7 @@ pub struct WhereEqPredicate { pub struct ModuleItems { // Use BTreeSets here so items are in the same order as in the // list of all items in Crate - pub items: BTreeSet, + pub items: BTreeSet, pub trait_items: BTreeSet, pub impl_items: BTreeSet, } @@ -722,7 +722,7 @@ pub struct Crate { // does, because it can affect the order in which errors are // detected, which in turn can make compile-fail tests yield // slightly different results. - pub items: BTreeMap, + pub items: BTreeMap, pub trait_items: BTreeMap, pub impl_items: BTreeMap, @@ -741,7 +741,7 @@ pub struct Crate { } impl Crate { - pub fn item(&self, id: NodeId) -> &Item { + pub fn item(&self, id: HirId) -> &Item { &self.items[&id] } @@ -2215,7 +2215,7 @@ impl VariantData { // so it can fetched later. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ItemId { - pub id: NodeId, + pub id: HirId, } /// An item diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index cdd4043f4bc..0a65473de8f 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -48,7 +48,7 @@ pub trait PpAnn { fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) -> io::Result<()> { Ok(()) } - fn try_fetch_item(&self, _: ast::NodeId) -> Option<&hir::Item> { + fn try_fetch_item(&self, _: hir::HirId) -> Option<&hir::Item> { None } } @@ -58,7 +58,7 @@ impl PpAnn for NoAnn {} pub const NO_ANN: &dyn PpAnn = &NoAnn; impl PpAnn for hir::Crate { - fn try_fetch_item(&self, item: ast::NodeId) -> Option<&hir::Item> { + fn try_fetch_item(&self, item: hir::HirId) -> Option<&hir::Item> { Some(self.item(item)) } fn nested(&self, state: &mut State<'_>, nested: Nested) -> io::Result<()> { diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index f12367a89bb..0a0a1dee7f0 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -292,7 +292,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty) { match ty.node { TyKind::Def(item_id, _) => { - let item = self.tcx.hir().expect_item(item_id.id); + let item = self.tcx.hir().expect_item_by_hir_id(item_id.id); intravisit::walk_item(self, item); } _ => () diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index ab105360388..73e232a6a4f 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -638,7 +638,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // `abstract type MyAnonTy<'b>: MyTrait<'b>;` // ^ ^ this gets resolved in the scope of // the exist_ty generics - let (generics, bounds) = match self.tcx.hir().expect_item(item_id.id).node { + let (generics, bounds) = match self.tcx.hir().expect_item_by_hir_id(item_id.id).node + { // named existential types are reached via TyKind::Path // this arm is for `impl Trait` in the types of statics, constants and locals hir::ItemKind::Existential(hir::ExistTy { @@ -678,8 +679,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let parent_impl_id = hir::ImplItemId { hir_id: parent_id }; let parent_trait_id = hir::TraitItemId { hir_id: parent_id }; let krate = self.tcx.hir().forest.krate(); - let parent_node_id = self.tcx.hir().hir_to_node_id(parent_id); - if !(krate.items.contains_key(&parent_node_id) + + if !(krate.items.contains_key(&parent_id) || krate.impl_items.contains_key(&parent_impl_id) || krate.trait_items.contains_key(&parent_trait_id)) { diff --git a/src/librustc_codegen_llvm/va_arg.rs b/src/librustc_codegen_llvm/va_arg.rs index 7aceaea4510..7fc17d17f99 100644 --- a/src/librustc_codegen_llvm/va_arg.rs +++ b/src/librustc_codegen_llvm/va_arg.rs @@ -108,12 +108,12 @@ pub(super) fn emit_va_arg( emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true) } - // Windows Aarch64 + // Windows AArch64 ("aarch64", true) => { emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false) } - // iOS Aarch64 + // iOS AArch64 ("aarch64", _) if target.target_os == "ios" => { emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true) diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index e6470dbb61c..244505976b6 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -596,18 +596,6 @@ impl<'a> Linker for MsvcLinker<'a> { // This will cause the Microsoft linker to embed .natvis info into the PDB file let natvis_dir_path = self.sess.sysroot.join("lib\\rustlib\\etc"); if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) { - // LLVM 5.0.0's lld-link frontend doesn't yet recognize, and chokes - // on, the /NATVIS:... flags. LLVM 6 (or earlier) should at worst ignore - // them, eventually mooting this workaround, per this landed patch: - // https://github.com/llvm-mirror/lld/commit/27b9c4285364d8d76bb43839daa100 - if let Some(ref linker_path) = self.sess.opts.cg.linker { - if let Some(linker_name) = Path::new(&linker_path).file_stem() { - if linker_name.to_str().unwrap().to_lowercase() == "lld-link" { - self.sess.warn("not embedding natvis: lld-link may not support the flag"); - return; - } - } - } for entry in natvis_dir { match entry { Ok(entry) => { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index fb519407398..f456a5c1619 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -413,6 +413,8 @@ impl<'tcx> EntryKind<'tcx> { EntryKind::ForeignFn(_) => Def::Fn(did), EntryKind::Method(_) => Def::Method(did), EntryKind::Type => Def::TyAlias(did), + EntryKind::TypeParam => Def::TyParam(did), + EntryKind::ConstParam => Def::ConstParam(did), EntryKind::Existential => Def::Existential(did), EntryKind::AssociatedType(_) => Def::AssociatedTy(did), EntryKind::AssociatedExistential(_) => Def::AssociatedExistential(did), diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 78a186fbb71..9c908176a6d 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -7,6 +7,7 @@ use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; use rustc::hir::def::CtorKind; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LocalDefId, LOCAL_CRATE}; +use rustc::hir::GenericParamKind; use rustc::hir::map::definitions::DefPathTable; use rustc_data_structures::fingerprint::Fingerprint; use rustc::middle::dependency_format::Linkage; @@ -692,7 +693,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { span: self.lazy(&tcx.def_span(def_id)), attributes: self.encode_attributes(attrs), children: self.lazy_seq(md.item_ids.iter().map(|item_id| { - tcx.hir().local_def_id(item_id.id).index + tcx.hir().local_def_id_from_hir_id(item_id.id).index })), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), @@ -1352,25 +1353,22 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } } - fn encode_info_for_ty_param(&mut self, - (def_id, Untracked(has_default)): (DefId, Untracked)) - -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_ty_param({:?})", def_id); + fn encode_info_for_generic_param( + &mut self, + def_id: DefId, + entry_kind: EntryKind<'tcx>, + encode_type: bool, + ) -> Entry<'tcx> { let tcx = self.tcx; Entry { - kind: EntryKind::Type, + kind: entry_kind, visibility: self.lazy(&ty::Visibility::Public), span: self.lazy(&tcx.def_span(def_id)), attributes: LazySeq::empty(), children: LazySeq::empty(), stability: None, deprecation: None, - - ty: if has_default { - Some(self.encode_item_type(def_id)) - } else { - None - }, + ty: if encode_type { Some(self.encode_item_type(def_id)) } else { None }, inherent_impls: LazySeq::empty(), variances: LazySeq::empty(), generics: None, @@ -1381,27 +1379,20 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } } - fn encode_info_for_const_param(&mut self, def_id: DefId) -> Entry<'tcx> { + fn encode_info_for_ty_param( + &mut self, + (def_id, Untracked(encode_type)): (DefId, Untracked), + ) -> Entry<'tcx> { + debug!("IsolatedEncoder::encode_info_for_ty_param({:?})", def_id); + self.encode_info_for_generic_param(def_id, EntryKind::TypeParam, encode_type) + } + + fn encode_info_for_const_param( + &mut self, + def_id: DefId, + ) -> Entry<'tcx> { debug!("IsolatedEncoder::encode_info_for_const_param({:?})", def_id); - let tcx = self.tcx; - Entry { - kind: EntryKind::Type, - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), - stability: None, - deprecation: None, - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - - mir: None, - } + self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true) } fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> { @@ -1748,18 +1739,18 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { fn encode_info_for_generics(&mut self, generics: &hir::Generics) { for param in &generics.params { + let def_id = self.tcx.hir().local_def_id_from_hir_id(param.hir_id); match param.kind { - hir::GenericParamKind::Lifetime { .. } => {} - hir::GenericParamKind::Type { ref default, .. } => { - let def_id = self.tcx.hir().local_def_id_from_hir_id(param.hir_id); - let has_default = Untracked(default.is_some()); - let encode_info = IsolatedEncoder::encode_info_for_ty_param; - self.record(def_id, encode_info, (def_id, has_default)); + GenericParamKind::Lifetime { .. } => continue, + GenericParamKind::Type { ref default, .. } => { + self.record( + def_id, + IsolatedEncoder::encode_info_for_ty_param, + (def_id, Untracked(default.is_some())), + ); } - hir::GenericParamKind::Const { .. } => { - let def_id = self.tcx.hir().local_def_id_from_hir_id(param.hir_id); - let encode_info = IsolatedEncoder::encode_info_for_const_param; - self.record(def_id, encode_info, def_id); + GenericParamKind::Const { .. } => { + self.record(def_id, IsolatedEncoder::encode_info_for_const_param, def_id); } } } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 5b6166ebeaf..fe2ea26c327 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -299,6 +299,8 @@ pub enum EntryKind<'tcx> { ForeignType, GlobalAsm, Type, + TypeParam, + ConstParam, Existential, Enum(ReprOptions), Field, @@ -335,7 +337,9 @@ impl<'a, 'gcx> HashStable> for EntryKind<'gcx> { EntryKind::ForeignType | EntryKind::Field | EntryKind::Existential | - EntryKind::Type => { + EntryKind::Type | + EntryKind::TypeParam | + EntryKind::ConstParam => { // Nothing else to hash here. } EntryKind::Const(qualif, ref const_data) => { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index b532e5c94d5..f155beaaff2 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -472,8 +472,8 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { { if let hir::ItemKind::Mod(m) = &item.node { for item_id in m.item_ids.as_ref() { - let item = self.tcx.hir().expect_item(item_id.id); - let def_id = self.tcx.hir().local_def_id(item_id.id); + let item = self.tcx.hir().expect_item_by_hir_id(item_id.id); + let def_id = self.tcx.hir().local_def_id_from_hir_id(item_id.id); if !self.tcx.hygienic_eq(segment.ident, item.ident, def_id) { continue; } if let hir::ItemKind::Use(..) = item.node { self.update(item.hir_id, Some(AccessLevel::Exported)); @@ -737,8 +737,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { unreachable!() }; for id in &module.item_ids { - let hir_id = self.tcx.hir().node_to_hir_id(id.id); - self.update(hir_id, level); + self.update(id.id, level); } let def_id = self.tcx.hir().local_def_id_from_hir_id(module_id); if let Some(exports) = self.tcx.module_exports(def_id) { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 3e61b175b76..fba4414c127 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1817,7 +1817,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { self.def_to_ty(opt_self_ty, path, false) } hir::TyKind::Def(item_id, ref lifetimes) => { - let did = tcx.hir().local_def_id(item_id.id); + let did = tcx.hir().local_def_id_from_hir_id(item_id.id); self.impl_trait_ty_to_ty(did, lifetimes) }, hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 7b530c69a88..fde0e47650d 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -853,7 +853,7 @@ impl<'a, 'tcx, 'gcx> hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'a, ' } // Find a `use` statement. for item_id in &module.item_ids { - let item = self.tcx.hir().expect_item(item_id.id); + let item = self.tcx.hir().expect_item_by_hir_id(item_id.id); match item.node { hir::ItemKind::Use(..) => { // Don't suggest placing a `use` before the prelude diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 31f757c87b2..396488c981d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -278,16 +278,16 @@ impl Clean for CrateNum { }; let primitives = if root.is_local() { cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| { - let item = cx.tcx.hir().expect_item(id.id); + let item = cx.tcx.hir().expect_item_by_hir_id(id.id); match item.node { hir::ItemKind::Mod(_) => { - as_primitive(Def::Mod(cx.tcx.hir().local_def_id(id.id))) + as_primitive(Def::Mod(cx.tcx.hir().local_def_id_from_hir_id(id.id))) } hir::ItemKind::Use(ref path, hir::UseKind::Single) if item.vis.node.is_pub() => { as_primitive(path.def).map(|(_, prim, attrs)| { // Pretend the primitive is local. - (cx.tcx.hir().local_def_id(id.id), prim, attrs) + (cx.tcx.hir().local_def_id_from_hir_id(id.id), prim, attrs) }) } _ => None @@ -320,15 +320,15 @@ impl Clean for CrateNum { }; let keywords = if root.is_local() { cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| { - let item = cx.tcx.hir().expect_item(id.id); + let item = cx.tcx.hir().expect_item_by_hir_id(id.id); match item.node { hir::ItemKind::Mod(_) => { - as_keyword(Def::Mod(cx.tcx.hir().local_def_id(id.id))) + as_keyword(Def::Mod(cx.tcx.hir().local_def_id_from_hir_id(id.id))) } hir::ItemKind::Use(ref path, hir::UseKind::Single) if item.vis.node.is_pub() => { as_keyword(path.def).map(|(_, prim, attrs)| { - (cx.tcx.hir().local_def_id(id.id), prim, attrs) + (cx.tcx.hir().local_def_id_from_hir_id(id.id), prim, attrs) }) } _ => None @@ -2762,7 +2762,7 @@ impl Clean for hir::Ty { }, TyKind::Tup(ref tys) => Tuple(tys.clean(cx)), TyKind::Def(item_id, _) => { - let item = cx.tcx.hir().expect_item(item_id.id); + let item = cx.tcx.hir().expect_item_by_hir_id(item_id.id); if let hir::ItemKind::Existential(ref ty) = item.node { ImplTrait(ty.bounds.clean(cx)) } else { @@ -4393,10 +4393,10 @@ pub fn path_to_def_local(tcx: &TyCtxt<'_, '_, '_>, path: &[&str]) -> Option RustdocVisitor<'a, 'tcx> { let orig_inside_public_path = self.inside_public_path; self.inside_public_path &= vis.node.is_pub(); for i in &m.item_ids { - let item = self.cx.tcx.hir().expect_item(i.id); + let item = self.cx.tcx.hir().expect_item_by_hir_id(i.id); self.visit_item(item, None, &mut om); } self.inside_public_path = orig_inside_public_path; @@ -344,7 +344,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Node::Item(&hir::Item { node: hir::ItemKind::Mod(ref m), .. }) if glob => { let prev = mem::replace(&mut self.inlining, true); for i in &m.item_ids { - let i = self.cx.tcx.hir().expect_item(i.id); + let i = self.cx.tcx.hir().expect_item_by_hir_id(i.id); self.visit_item(i, None, om); } self.inlining = prev; diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 4668e3ec7ea..441f6b95d0b 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -21,6 +21,10 @@ use crate::memchr; /// times. It also provides no advantage when reading from a source that is /// already in memory, like a `Vec`. /// +/// When the `BufReader` is dropped, the contents of its buffer will be +/// discarded. Creating multiple instances of a `BufReader` on the same +/// stream can cause data loss. +/// /// [`Read`]: ../../std/io/trait.Read.html /// [`TcpStream::read`]: ../../std/net/struct.TcpStream.html#method.read /// [`TcpStream`]: ../../std/net/struct.TcpStream.html @@ -350,7 +354,7 @@ impl Seek for BufReader { /// /// It can be excessively inefficient to work directly with something that /// implements [`Write`]. For example, every call to -/// [`write`][`Tcpstream::write`] on [`TcpStream`] results in a system call. A +/// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A /// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying /// writer in large, infrequent batches. /// @@ -401,7 +405,7 @@ impl Seek for BufReader { /// the `stream` is dropped. /// /// [`Write`]: ../../std/io/trait.Write.html -/// [`Tcpstream::write`]: ../../std/net/struct.TcpStream.html#method.write +/// [`TcpStream::write`]: ../../std/net/struct.TcpStream.html#method.write /// [`TcpStream`]: ../../std/net/struct.TcpStream.html /// [`flush`]: #method.flush #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index bef6bc92661..7b0d1549e06 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -286,11 +286,16 @@ mod fn_keyword { } // /// The `for` keyword. /// -/// `for` is primarily used in for-in-loops, but it has a few other pieces of syntactic uses such as -/// `impl Trait for Type` (see [`impl`] for more info on that). for-in-loops, or to be more -/// precise, iterator loops, are a simple syntactic sugar over an exceedingly common practice -/// within Rust, which is to loop over an iterator until that iterator returns `None` (or `break` -/// is called). +/// The `for` keyword is used in many syntactic locations: +/// +/// * `for` is used in for-in-loops (see below). +/// * `for` is used when implementing traits as in `impl Trait for Type` (see [`impl`] for more info +/// on that). +/// * `for` is also used for [higher-ranked trait bounds] as in `for<'a> &'a T: PartialEq`. +/// +/// for-in-loops, or to be more precise, iterator loops, are a simple syntactic sugar over a common +/// practice within Rust, which is to loop over an iterator until that iterator returns `None` (or +/// `break` is called). /// /// ```rust /// for i in 0..5 { @@ -347,6 +352,8 @@ mod fn_keyword { } /// For more information on for-loops, see the [Rust book] or the [Reference]. /// /// [`impl`]: keyword.impl.html +/// [higher-ranked trait bounds]: +/// https://doc.rust-lang.org/nightly/reference/trait-bounds.html#higher-ranked-trait-bounds /// [`IntoIterator`]: iter/trait.IntoIterator.html /// [Rust book]: /// https://doc.rust-lang.org/book/2018-edition/ch03-05-control-flow.html#looping-through-a-collection-with-for diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index d5dc5f7c4f0..d5afd069d7f 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -4,7 +4,7 @@ //! library. Each macro is available for use when linking against the standard //! library. -/// The entry point for panic of Rust threads. +/// Panics the current thread. /// /// This allows a program to terminate immediately and provide feedback /// to the caller of the program. `panic!` should be used when a program reaches @@ -70,7 +70,7 @@ macro_rules! panic { }); } -/// Macro for printing to the standard output. +/// Prints to the standard output. /// /// Equivalent to the [`println!`] macro except that a newline is not printed at /// the end of the message. @@ -116,7 +116,7 @@ macro_rules! print { ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*))); } -/// Macro for printing to the standard output, with a newline. +/// Prints to the standard output, with a newline. /// /// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone /// (no additional CARRIAGE RETURN (`\r`/`U+000D`). @@ -151,7 +151,7 @@ macro_rules! println { }) } -/// Macro for printing to the standard error. +/// Prints to the standard error. /// /// Equivalent to the [`print!`] macro, except that output goes to /// [`io::stderr`] instead of `io::stdout`. See [`print!`] for @@ -179,7 +179,7 @@ macro_rules! eprint { ($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*))); } -/// Macro for printing to the standard error, with a newline. +/// Prints to the standard error, with a newline. /// /// Equivalent to the [`println!`] macro, except that output goes to /// [`io::stderr`] instead of `io::stdout`. See [`println!`] for @@ -210,8 +210,10 @@ macro_rules! eprintln { }) } -/// A macro for quick and dirty debugging with which you can inspect -/// the value of a given expression. An example: +/// Prints and returns the value of a given expression for quick and dirty +/// debugging. +/// +/// An example: /// /// ```rust /// let a = 2; @@ -328,7 +330,7 @@ macro_rules! dbg { } } -/// A macro to await on an async call. +/// Awaits the completion of an async call. #[macro_export] #[unstable(feature = "await_macro", issue = "50547")] #[allow_internal_unstable(gen_future, generators)] @@ -351,7 +353,7 @@ macro_rules! r#await { } } } -/// A macro to select an event from a number of receivers. +/// Selects the first successful receive event from a number of receivers. /// /// This macro is used to wait for the first event to occur on a number of /// receivers. It places no restrictions on the types of receivers given to @@ -423,7 +425,7 @@ macro_rules! assert_approx_eq { #[cfg(rustdoc)] mod builtin { - /// Unconditionally causes compilation to fail with the given error message when encountered. + /// Causes compilation to fail with the given error message when encountered. /// /// This macro should be used when a crate uses a conditional compilation strategy to provide /// better error messages for erroneous conditions. It's the compiler-level form of [`panic!`], @@ -465,7 +467,7 @@ mod builtin { ($msg:expr,) => ({ /* compiler built-in */ }); } - /// The core macro for formatted string creation & output. + /// Constructs parameters for the other string-formatting macros. /// /// This macro functions by taking a formatting string literal containing /// `{}` for each additional argument passed. `format_args!` prepares the @@ -517,7 +519,7 @@ mod builtin { ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }); } - /// Inspect an environment variable at compile time. + /// Inspects an environment variable at compile time. /// /// This macro will expand to the value of the named environment variable at /// compile time, yielding an expression of type `&'static str`. @@ -555,7 +557,7 @@ mod builtin { ($name:expr,) => ({ /* compiler built-in */ }); } - /// Optionally inspect an environment variable at compile time. + /// Optionally inspects an environment variable at compile time. /// /// If the named environment variable is present at compile time, this will /// expand into an expression of type `Option<&'static str>` whose value is @@ -581,7 +583,7 @@ mod builtin { ($name:expr,) => ({ /* compiler built-in */ }); } - /// Concatenate identifiers into one identifier. + /// Concatenates identifiers into one identifier. /// /// This macro takes any number of comma-separated identifiers, and /// concatenates them all into one, yielding an expression which is a new @@ -634,7 +636,7 @@ mod builtin { ($($e:expr,)*) => ({ /* compiler built-in */ }); } - /// A macro which expands to the line number on which it was invoked. + /// Expands to the line number on which it was invoked. /// /// With [`column!`] and [`file!`], these macros provide debugging information for /// developers about the location within the source. @@ -659,7 +661,7 @@ mod builtin { #[rustc_doc_only_macro] macro_rules! line { () => ({ /* compiler built-in */ }) } - /// A macro which expands to the column number on which it was invoked. + /// Expands to the column number at which it was invoked. /// /// With [`line!`] and [`file!`], these macros provide debugging information for /// developers about the location within the source. @@ -684,7 +686,7 @@ mod builtin { #[rustc_doc_only_macro] macro_rules! column { () => ({ /* compiler built-in */ }) } - /// A macro which expands to the file name from which it was invoked. + /// Expands to the file name in which it was invoked. /// /// With [`line!`] and [`column!`], these macros provide debugging information for /// developers about the location within the source. @@ -708,7 +710,7 @@ mod builtin { #[rustc_doc_only_macro] macro_rules! file { () => ({ /* compiler built-in */ }) } - /// A macro which stringifies its arguments. + /// Stringifies its arguments. /// /// This macro will yield an expression of type `&'static str` which is the /// stringification of all the tokens passed to the macro. No restrictions @@ -822,7 +824,7 @@ mod builtin { #[rustc_doc_only_macro] macro_rules! module_path { () => ({ /* compiler built-in */ }) } - /// Boolean evaluation of configuration flags, at compile-time. + /// Evaluates boolean combinations of configuration flags at compile-time. /// /// In addition to the `#[cfg]` attribute, this macro is provided to allow /// boolean expression evaluation of configuration flags. This frequently @@ -844,7 +846,7 @@ mod builtin { #[rustc_doc_only_macro] macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) } - /// Parse a file as an expression or an item according to the context. + /// Parses a file as an expression or an item according to the context. /// /// The file is located relative to the current file (similarly to how /// modules are found). @@ -890,7 +892,7 @@ mod builtin { ($file:expr,) => ({ /* compiler built-in */ }); } - /// Ensure that a boolean expression is `true` at runtime. + /// Asserts that a boolean expression is `true` at runtime. /// /// This will invoke the [`panic!`] macro if the provided expression cannot be /// evaluated to `true` at runtime. @@ -944,7 +946,7 @@ mod builtin { } } -/// A macro for defining `#[cfg]` if-else statements. +/// Defines `#[cfg]` if-else statements. /// /// This is similar to the `if/elif` C preprocessor macro by allowing definition /// of a cascade of `#[cfg]` cases, emitting the implementation which matches diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 7ff098bc9e1..c73f7983146 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -827,30 +827,54 @@ pub fn canonicalize(p: &Path) -> io::Result { Ok(PathBuf::from(OsString::from_vec(buf))) } +fn open_and_set_permissions( + from: &Path, + to: &Path, +) -> io::Result<(crate::fs::File, crate::fs::File, u64, crate::fs::Metadata)> { + use crate::fs::{File, OpenOptions}; + use crate::os::unix::fs::{OpenOptionsExt, PermissionsExt}; + + let reader = File::open(from)?; + let (perm, len) = { + let metadata = reader.metadata()?; + if !metadata.is_file() { + return Err(Error::new( + ErrorKind::InvalidInput, + "the source path is not an existing regular file", + )); + } + (metadata.permissions(), metadata.len()) + }; + let writer = OpenOptions::new() + // create the file with the correct mode right away + .mode(perm.mode()) + .write(true) + .create(true) + .truncate(true) + .open(to)?; + let writer_metadata = writer.metadata()?; + if writer_metadata.is_file() { + // Set the correct file permissions, in case the file already existed. + // Don't set the permissions on already existing non-files like + // pipes/FIFOs or device nodes. + writer.set_permissions(perm)?; + } + Ok((reader, writer, len, writer_metadata)) +} + #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios")))] pub fn copy(from: &Path, to: &Path) -> io::Result { - use crate::fs::File; - if !from.is_file() { - return Err(Error::new(ErrorKind::InvalidInput, - "the source path is not an existing regular file")) - } + let (mut reader, mut writer, _, _) = open_and_set_permissions(from, to)?; - let mut reader = File::open(from)?; - let mut writer = File::create(to)?; - let perm = reader.metadata()?.permissions(); - - let ret = io::copy(&mut reader, &mut writer)?; - writer.set_permissions(perm)?; - Ok(ret) + io::copy(&mut reader, &mut writer) } #[cfg(any(target_os = "linux", target_os = "android"))] pub fn copy(from: &Path, to: &Path) -> io::Result { use crate::cmp; - use crate::fs::File; use crate::sync::atomic::{AtomicBool, Ordering}; // Kernel prior to 4.5 don't have copy_file_range @@ -876,17 +900,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { ) } - if !from.is_file() { - return Err(Error::new(ErrorKind::InvalidInput, - "the source path is not an existing regular file")) - } - - let mut reader = File::open(from)?; - let mut writer = File::create(to)?; - let (perm, len) = { - let metadata = reader.metadata()?; - (metadata.permissions(), metadata.size()) - }; + let (mut reader, mut writer, len, _) = open_and_set_permissions(from, to)?; let has_copy_file_range = HAS_COPY_FILE_RANGE.load(Ordering::Relaxed); let mut written = 0u64; @@ -896,13 +910,14 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { let copy_result = unsafe { // We actually don't have to adjust the offsets, // because copy_file_range adjusts the file offset automatically - cvt(copy_file_range(reader.as_raw_fd(), - ptr::null_mut(), - writer.as_raw_fd(), - ptr::null_mut(), - bytes_to_copy, - 0) - ) + cvt(copy_file_range( + reader.as_raw_fd(), + ptr::null_mut(), + writer.as_raw_fd(), + ptr::null_mut(), + bytes_to_copy, + 0, + )) }; if let Err(ref copy_err) = copy_result { match copy_err.raw_os_error() { @@ -920,24 +935,25 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { Ok(ret) => written += ret as u64, Err(err) => { match err.raw_os_error() { - Some(os_err) if os_err == libc::ENOSYS - || os_err == libc::EXDEV - || os_err == libc::EPERM => { - // Try fallback io::copy if either: - // - Kernel version is < 4.5 (ENOSYS) - // - Files are mounted on different fs (EXDEV) - // - copy_file_range is disallowed, for example by seccomp (EPERM) - assert_eq!(written, 0); - let ret = io::copy(&mut reader, &mut writer)?; - writer.set_permissions(perm)?; - return Ok(ret) - }, + Some(os_err) + if os_err == libc::ENOSYS + || os_err == libc::EXDEV + || os_err == libc::EINVAL + || os_err == libc::EPERM => + { + // Try fallback io::copy if either: + // - Kernel version is < 4.5 (ENOSYS) + // - Files are mounted on different fs (EXDEV) + // - copy_file_range is disallowed, for example by seccomp (EPERM) + // - copy_file_range cannot be used with pipes or device nodes (EINVAL) + assert_eq!(written, 0); + return io::copy(&mut reader, &mut writer); + } _ => return Err(err), } } } } - writer.set_permissions(perm)?; Ok(written) } @@ -960,9 +976,9 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { type copyfile_flags_t = u32; extern "C" { - fn copyfile( - from: *const libc::c_char, - to: *const libc::c_char, + fn fcopyfile( + from: libc::c_int, + to: libc::c_int, state: copyfile_state_t, flags: copyfile_flags_t, ) -> libc::c_int; @@ -988,10 +1004,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { } } - if !from.is_file() { - return Err(Error::new(ErrorKind::InvalidInput, - "the source path is not an existing regular file")) - } + let (reader, writer, _, writer_metadata) = open_and_set_permissions(from, to)?; // We ensure that `FreeOnDrop` never contains a null pointer so it is // always safe to call `copyfile_state_free` @@ -1003,12 +1016,18 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { FreeOnDrop(state) }; + let flags = if writer_metadata.is_file() { + COPYFILE_ALL + } else { + COPYFILE_DATA + }; + cvt(unsafe { - copyfile( - cstr(from)?.as_ptr(), - cstr(to)?.as_ptr(), + fcopyfile( + reader.as_raw_fd(), + writer.as_raw_fd(), state.0, - COPYFILE_ALL, + flags, ) })?; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d3eadfeceb2..79c1f0cb4cc 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4734,7 +4734,7 @@ impl<'a> Parser<'a> { let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| { e.emit(); self.recover_stmt(); - (vec![], false) + (vec![], true) }); self.bump(); pat = PatKind::Struct(path, fields, etc); diff --git a/src/test/run-pass/paths-containing-nul.rs b/src/test/run-pass/paths-containing-nul.rs index 8c800089d1c..dfcef59aa57 100644 --- a/src/test/run-pass/paths-containing-nul.rs +++ b/src/test/run-pass/paths-containing-nul.rs @@ -1,6 +1,7 @@ #![allow(deprecated)] // ignore-cloudabi no files or I/O // ignore-wasm32-bare no files or I/O +// ignore-emscripten no files use std::fs; use std::io; @@ -22,14 +23,18 @@ fn main() { assert_invalid_input("remove_file", fs::remove_file("\0")); assert_invalid_input("metadata", fs::metadata("\0")); assert_invalid_input("symlink_metadata", fs::symlink_metadata("\0")); + + // If `dummy_file` does not exist, then we might get another unrelated error + let dummy_file = std::env::current_exe().unwrap(); + assert_invalid_input("rename1", fs::rename("\0", "a")); - assert_invalid_input("rename2", fs::rename("a", "\0")); + assert_invalid_input("rename2", fs::rename(&dummy_file, "\0")); assert_invalid_input("copy1", fs::copy("\0", "a")); - assert_invalid_input("copy2", fs::copy("a", "\0")); + assert_invalid_input("copy2", fs::copy(&dummy_file, "\0")); assert_invalid_input("hard_link1", fs::hard_link("\0", "a")); - assert_invalid_input("hard_link2", fs::hard_link("a", "\0")); + assert_invalid_input("hard_link2", fs::hard_link(&dummy_file, "\0")); assert_invalid_input("soft_link1", fs::soft_link("\0", "a")); - assert_invalid_input("soft_link2", fs::soft_link("a", "\0")); + assert_invalid_input("soft_link2", fs::soft_link(&dummy_file, "\0")); assert_invalid_input("read_link", fs::read_link("\0")); assert_invalid_input("canonicalize", fs::canonicalize("\0")); assert_invalid_input("create_dir", fs::create_dir("\0")); diff --git a/src/test/ui/parser/bind-struct-early-modifiers.rs b/src/test/ui/parser/bind-struct-early-modifiers.rs index c1de0df54e2..c4b1937de10 100644 --- a/src/test/ui/parser/bind-struct-early-modifiers.rs +++ b/src/test/ui/parser/bind-struct-early-modifiers.rs @@ -2,7 +2,6 @@ fn main() { struct Foo { x: isize } match (Foo { x: 10 }) { Foo { ref x: ref x } => {}, //~ ERROR expected `,` - //~| ERROR pattern does not mention field `x` _ => {} } } diff --git a/src/test/ui/parser/bind-struct-early-modifiers.stderr b/src/test/ui/parser/bind-struct-early-modifiers.stderr index 50c95b8cf40..03482a41f54 100644 --- a/src/test/ui/parser/bind-struct-early-modifiers.stderr +++ b/src/test/ui/parser/bind-struct-early-modifiers.stderr @@ -4,12 +4,5 @@ error: expected `,` LL | Foo { ref x: ref x } => {}, | ^ -error[E0027]: pattern does not mention field `x` - --> $DIR/bind-struct-early-modifiers.rs:4:9 - | -LL | Foo { ref x: ref x } => {}, - | ^^^^^^^^^^^^^^^^^^^^ missing field `x` +error: aborting due to previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0027`. diff --git a/src/test/ui/parser/issue-10392.rs b/src/test/ui/parser/issue-10392.rs index dd84af39300..5b0c2fc2be4 100644 --- a/src/test/ui/parser/issue-10392.rs +++ b/src/test/ui/parser/issue-10392.rs @@ -4,5 +4,4 @@ fn a() -> A { panic!() } fn main() { let A { , } = a(); //~ ERROR expected ident - //~| ERROR pattern does not mention field `foo` } diff --git a/src/test/ui/parser/issue-10392.stderr b/src/test/ui/parser/issue-10392.stderr index 7bf5aa93f0a..34991151c1e 100644 --- a/src/test/ui/parser/issue-10392.stderr +++ b/src/test/ui/parser/issue-10392.stderr @@ -4,12 +4,5 @@ error: expected identifier, found `,` LL | let A { , } = a(); | ^ expected identifier -error[E0027]: pattern does not mention field `foo` - --> $DIR/issue-10392.rs:6:9 - | -LL | let A { , } = a(); - | ^^^^^^^ missing field `foo` +error: aborting due to previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0027`. diff --git a/src/test/ui/resolve/issue-54379.rs b/src/test/ui/resolve/issue-54379.rs index a48f66bf0fd..807c54393f2 100644 --- a/src/test/ui/resolve/issue-54379.rs +++ b/src/test/ui/resolve/issue-54379.rs @@ -6,7 +6,7 @@ fn main() { let thing = MyStruct { s1: None }; match thing { - MyStruct { .., Some(_) } => {}, //~ ERROR pattern does not mention field `s1` + MyStruct { .., Some(_) } => {}, //~^ ERROR expected `,` //~| ERROR expected `}`, found `,` _ => {} diff --git a/src/test/ui/resolve/issue-54379.stderr b/src/test/ui/resolve/issue-54379.stderr index 60a6f904610..2a6b54572de 100644 --- a/src/test/ui/resolve/issue-54379.stderr +++ b/src/test/ui/resolve/issue-54379.stderr @@ -13,12 +13,5 @@ error: expected `,` LL | MyStruct { .., Some(_) } => {}, | ^^^^ -error[E0027]: pattern does not mention field `s1` - --> $DIR/issue-54379.rs:9:9 - | -LL | MyStruct { .., Some(_) } => {}, - | ^^^^^^^^^^^^^^^^^^^^^^^^ missing field `s1` +error: aborting due to 2 previous errors -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0027`. diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index faeeea605a2..04986b59ea0 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -27,9 +27,10 @@ enum OutputFormat { } impl OutputFormat { - fn from(format: &str) -> OutputFormat { + fn from(format: &str, resource_suffix: &str) -> OutputFormat { match &*format.to_lowercase() { - "html" => OutputFormat::HTML(HTMLFormatter(RefCell::new(IdMap::new()))), + "html" => OutputFormat::HTML(HTMLFormatter(RefCell::new(IdMap::new()), + resource_suffix.to_owned())), "markdown" => OutputFormat::Markdown(MarkdownFormatter), s => OutputFormat::Unknown(s.to_owned()), } @@ -44,7 +45,7 @@ trait Formatter { fn footer(&self, output: &mut dyn Write) -> Result<(), Box>; } -struct HTMLFormatter(RefCell); +struct HTMLFormatter(RefCell, String); struct MarkdownFormatter; impl Formatter for HTMLFormatter { @@ -55,7 +56,7 @@ impl Formatter for HTMLFormatter { Rust Compiler Error Index - + -"##)?; +"##, suffix=self.1)?; Ok(()) } @@ -242,9 +243,12 @@ fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box (OutputFormat, PathBuf) { let mut args = env::args().skip(1); - let format = args.next().map(|a| OutputFormat::from(&a)) - .unwrap_or(OutputFormat::from("html")); - let dst = args.next().map(PathBuf::from).unwrap_or_else(|| { + let format = args.next(); + let dst = args.next(); + let resource_suffix = args.next().unwrap_or_else(String::new); + let format = format.map(|a| OutputFormat::from(&a, &resource_suffix)) + .unwrap_or(OutputFormat::from("html", &resource_suffix)); + let dst = dst.map(PathBuf::from).unwrap_or_else(|| { match format { OutputFormat::HTML(..) => PathBuf::from("doc/error-index.html"), OutputFormat::Markdown(..) => PathBuf::from("doc/error-index.md"),