From 9eb6f32d452bed518a2c3bd6d0e084fdb10cd26e Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 1 Apr 2019 19:38:00 +0100 Subject: [PATCH 01/53] Use normal newtype_index macro for MIR dataflow --- .../borrow_check/error_reporting.rs | 3 +- src/librustc_mir/borrow_check/flows.rs | 2 +- src/librustc_mir/borrow_check/nll/facts.rs | 12 ---- .../borrow_check/nll/invalidation.rs | 2 +- .../nll/type_check/liveness/trace.rs | 2 +- src/librustc_mir/dataflow/impls/borrows.rs | 7 +- src/librustc_mir/dataflow/mod.rs | 7 +- src/librustc_mir/dataflow/move_paths/mod.rs | 71 ++++--------------- 8 files changed, 30 insertions(+), 76 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 95701204cab6d..d7ad2dbfeaf9e 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -25,8 +25,7 @@ use super::borrow_set::BorrowData; use super::{Context, MirBorrowckCtxt}; use super::{InitializationRequiringAction, PrefixSet}; use crate::dataflow::drop_flag_effects; -use crate::dataflow::move_paths::indexes::MoveOutIndex; -use crate::dataflow::move_paths::MovePathIndex; +use crate::dataflow::indexes::{MovePathIndex, MoveOutIndex}; use crate::util::borrowck_errors::{BorrowckErrors, Origin}; #[derive(Debug)] diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index 8de39f0efc1a5..c0b199f1798d4 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -11,7 +11,7 @@ use crate::borrow_check::location::LocationIndex; use polonius_engine::Output; -use crate::dataflow::move_paths::indexes::BorrowIndex; +use crate::dataflow::indexes::BorrowIndex; use crate::dataflow::move_paths::HasMoveData; use crate::dataflow::Borrows; use crate::dataflow::EverInitializedPlaces; diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index 9714398d9d63a..926f52b7cfce8 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -72,18 +72,6 @@ impl Atom for BorrowIndex { } } -impl From for BorrowIndex { - fn from(i: usize) -> BorrowIndex { - BorrowIndex::new(i) - } -} - -impl From for usize { - fn from(vid: BorrowIndex) -> usize { - Idx::index(vid) - } -} - impl Atom for LocationIndex { fn index(self) -> usize { Idx::index(self) diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index aafbff3577647..7896feefd9aea 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -9,7 +9,7 @@ use crate::borrow_check::ArtificialField; use crate::borrow_check::{ReadKind, WriteKind}; use crate::borrow_check::nll::facts::AllFacts; use crate::borrow_check::path_utils::*; -use crate::dataflow::move_paths::indexes::BorrowIndex; +use crate::dataflow::indexes::BorrowIndex; use rustc::ty::TyCtxt; use rustc::mir::visit::Visitor; use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase, Rvalue}; diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index f0df7070e6b5a..4c4b4c0431927 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -3,7 +3,7 @@ use crate::borrow_check::nll::region_infer::values::{self, PointIndex, RegionVal use crate::borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap; use crate::borrow_check::nll::type_check::NormalizeLocation; use crate::borrow_check::nll::type_check::TypeChecker; -use crate::dataflow::move_paths::indexes::MovePathIndex; +use crate::dataflow::indexes::MovePathIndex; use crate::dataflow::move_paths::MoveData; use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces}; use rustc::infer::canonical::QueryRegionConstraint; diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index b47aff3a4f855..0e51a519da300 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -10,13 +10,18 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use crate::dataflow::{BitDenotation, BlockSets, InitialFlow}; -pub use crate::dataflow::indexes::BorrowIndex; use crate::borrow_check::nll::region_infer::RegionInferenceContext; use crate::borrow_check::nll::ToRegionVid; use crate::borrow_check::places_conflict; use std::rc::Rc; +newtype_index! { + pub struct BorrowIndex { + DEBUG_FORMAT = "bw{}" + } +} + /// `Borrows` stores the data used in the analyses that track the flow /// of borrows. /// diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index af0e3f5a27091..83221aca6c5b3 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -33,7 +33,12 @@ mod graphviz; mod impls; pub mod move_paths; -pub(crate) use self::move_paths::indexes; +pub(crate) mod indexes { + pub(crate) use super::{ + move_paths::{MovePathIndex, MoveOutIndex, InitIndex}, + impls::borrows::BorrowIndex, + }; +} pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 7eef68e5f8073..6b01ab2c4ffda 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -1,7 +1,7 @@ use rustc::ty::{self, TyCtxt}; use rustc::mir::*; use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::indexed_vec::{IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use smallvec::SmallVec; use syntax_pos::{Span}; @@ -12,66 +12,23 @@ use self::abs_domain::{AbstractElem, Lift}; mod abs_domain; -// This submodule holds some newtype'd Index wrappers that are using -// NonZero to ensure that Option occupies only a single word. -// They are in a submodule to impose privacy restrictions; namely, to -// ensure that other code does not accidentally access `index.0` -// (which is likely to yield a subtle off-by-one error). -pub(crate) mod indexes { - use std::fmt; - use std::num::NonZeroUsize; - use rustc_data_structures::indexed_vec::Idx; - - macro_rules! new_index { - ($(#[$attrs:meta])* $Index:ident, $debug_name:expr) => { - #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] - pub struct $Index(NonZeroUsize); - - impl Idx for $Index { - fn new(idx: usize) -> Self { - $Index(NonZeroUsize::new(idx + 1).unwrap()) - } - fn index(self) -> usize { - self.0.get() - 1 - } - } - - impl fmt::Debug for $Index { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "{}{}", $debug_name, self.index()) - } - } - } +newtype_index! { + pub struct MovePathIndex { + DEBUG_FORMAT = "mp{}" } +} - new_index!( - /// Index into MovePathData.move_paths - MovePathIndex, - "mp" - ); - - new_index!( - /// Index into MoveData.moves. - MoveOutIndex, - "mo" - ); - - new_index!( - /// Index into MoveData.inits. - InitIndex, - "in" - ); - - new_index!( - /// Index into Borrows.locations - BorrowIndex, - "bw" - ); +newtype_index! { + pub struct MoveOutIndex { + DEBUG_FORMAT = "mo{}" + } } -pub use self::indexes::MovePathIndex; -pub use self::indexes::MoveOutIndex; -pub use self::indexes::InitIndex; +newtype_index! { + pub struct InitIndex { + DEBUG_FORMAT = "in{}" + } +} impl MoveOutIndex { pub fn move_path_index(&self, move_data: &MoveData<'_>) -> MovePathIndex { From 968ea1ce32ac894a7d58702c409233638aa5592d Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 4 Apr 2019 21:25:08 +0100 Subject: [PATCH 02/53] Mark variables captured by reference as mutable correctly --- src/librustc_mir/borrow_check/mod.rs | 96 ++++++++++++++++++++++------ src/test/ui/nll/extra-unused-mut.rs | 19 +++--- 2 files changed, 87 insertions(+), 28 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index a8c151a22eebc..ab3239820e3a2 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -28,7 +28,7 @@ use std::collections::BTreeMap; use syntax_pos::Span; use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex}; -use crate::dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MoveError}; +use crate::dataflow::move_paths::{HasMoveData, InitLocation, LookupResult, MoveData, MoveError}; use crate::dataflow::Borrows; use crate::dataflow::DataflowResultsConsumer; use crate::dataflow::FlowAtLocation; @@ -1206,25 +1206,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } = self.infcx.tcx.mir_borrowck(def_id); debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars); for field in used_mut_upvars { - // This relies on the current way that by-value - // captures of a closure are copied/moved directly - // when generating MIR. - match operands[field.index()] { - Operand::Move(Place::Base(PlaceBase::Local(local))) - | Operand::Copy(Place::Base(PlaceBase::Local(local))) => { - self.used_mut.insert(local); - } - Operand::Move(ref place @ Place::Projection(_)) - | Operand::Copy(ref place @ Place::Projection(_)) => { - if let Some(field) = place.is_upvar_field_projection( - self.mir, &self.infcx.tcx) { - self.used_mut_upvars.push(field); - } - } - Operand::Move(Place::Base(PlaceBase::Static(..))) - | Operand::Copy(Place::Base(PlaceBase::Static(..))) - | Operand::Constant(..) => {} - } + self.propagate_closure_used_mut_upvar(&operands[field.index()]); } } AggregateKind::Adt(..) @@ -1239,6 +1221,80 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } + fn propagate_closure_used_mut_upvar(&mut self, operand: &Operand<'tcx>) { + let propagate_closure_used_mut_place = |this: &mut Self, place: &Place<'tcx>| { + match *place { + Place::Projection { .. } => { + if let Some(field) = place.is_upvar_field_projection( + this.mir, &this.infcx.tcx) { + this.used_mut_upvars.push(field); + } + } + Place::Base(PlaceBase::Local(local)) => { + this.used_mut.insert(local); + } + Place::Base(PlaceBase::Static(_)) => {} + } + }; + + // This relies on the current way that by-value + // captures of a closure are copied/moved directly + // when generating MIR. + match *operand { + Operand::Move(Place::Base(PlaceBase::Local(local))) + | Operand::Copy(Place::Base(PlaceBase::Local(local))) + if self.mir.local_decls[local].is_user_variable.is_none() => + { + if self.mir.local_decls[local].ty.is_mutable_pointer() { + // The variable will be marked as mutable by the borrow. + return; + } + // This is an edge case where we have a `move` closure + // inside a non-move closure, and the inner closure + // contains a mutation: + // + // let mut i = 0; + // || { move || { i += 1; }; }; + // + // In this case our usual strategy of assuming that the + // variable will be captured by mutable reference is + // wrong, since `i` can be copied into the inner + // closure from a shared reference. + // + // As such we have to search for the local that this + // capture comes from and mark it as being used as mut. + + let temp_mpi = self.move_data.rev_lookup.find_local(local); + let init = if let [init_index] = *self.move_data.init_path_map[temp_mpi] { + &self.move_data.inits[init_index] + } else { + bug!("temporary should be initialized exactly once") + }; + + let loc = match init.location { + InitLocation::Statement(stmt) => stmt, + _ => bug!("temporary initialized in arguments"), + }; + + let bbd = &self.mir[loc.block]; + let stmt = &bbd.statements[loc.statement_index]; + debug!("temporary assigned in: stmt={:?}", stmt); + + if let StatementKind::Assign(_, box Rvalue::Ref(_, _, ref source)) = stmt.kind { + propagate_closure_used_mut_place(self, source); + } else { + bug!("closures should only capture user variables \ + or references to user variables"); + } + } + Operand::Move(ref place) + | Operand::Copy(ref place) => { + propagate_closure_used_mut_place(self, place); + } + Operand::Constant(..) => {} + } + } + fn consume_operand( &mut self, context: Context, diff --git a/src/test/ui/nll/extra-unused-mut.rs b/src/test/ui/nll/extra-unused-mut.rs index d5f0b0ddf18bf..6d0d6e16a6775 100644 --- a/src/test/ui/nll/extra-unused-mut.rs +++ b/src/test/ui/nll/extra-unused-mut.rs @@ -1,6 +1,6 @@ // extra unused mut lint tests for #51918 -// run-pass +// compile-pass #![feature(generators, nll)] #![deny(unused_mut)] @@ -53,11 +53,14 @@ fn if_guard(x: Result) { } } -fn main() { - ref_argument(0); - mutable_upvar(); - generator_mutable_upvar(); - ref_closure_argument(); - parse_dot_or_call_expr_with(Vec::new()); - if_guard(Ok(0)); +// #59620 +fn nested_closures() { + let mut i = 0; + [].iter().for_each(|_: &i32| { + [].iter().for_each(move |_: &i32| { + i += 1; + }); + }); } + +fn main() {} From 63080b3c25046b29cbbaef8d587c7da91a302fce Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 5 Apr 2019 22:42:40 +0300 Subject: [PATCH 03/53] remove lookup_char_pos_adj It is now exactly equivalent to lookup_char_pos. --- src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/mir/interpret/error.rs | 4 ++-- src/libsyntax/diagnostics/metadata.rs | 4 ++-- src/libsyntax/source_map.rs | 16 +++------------- src/libsyntax_pos/lib.rs | 13 +------------ 5 files changed, 9 insertions(+), 30 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 19663161fe3fa..8cfcc466b4019 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -278,7 +278,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } fn explain_span(self, heading: &str, span: Span) -> (String, Option) { - let lo = self.sess.source_map().lookup_char_pos_adj(span.lo()); + let lo = self.sess.source_map().lookup_char_pos(span.lo()); ( format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span), diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 280e75476b72a..b9c4d312adb7b 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -65,8 +65,8 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> { write!(f, "inside call to `{}`", self.instance)?; } if !self.call_site.is_dummy() { - let lo = tcx.sess.source_map().lookup_char_pos_adj(self.call_site.lo()); - write!(f, " at {}:{}:{}", lo.filename, lo.line, lo.col.to_usize() + 1)?; + let lo = tcx.sess.source_map().lookup_char_pos(self.call_site.lo()); + write!(f, " at {}:{}:{}", lo.file.name, lo.line, lo.col.to_usize() + 1)?; } Ok(()) }) diff --git a/src/libsyntax/diagnostics/metadata.rs b/src/libsyntax/diagnostics/metadata.rs index 704135fe1d589..53f37bb10bdc0 100644 --- a/src/libsyntax/diagnostics/metadata.rs +++ b/src/libsyntax/diagnostics/metadata.rs @@ -36,9 +36,9 @@ pub struct ErrorLocation { impl ErrorLocation { /// Creates an error location from a span. pub fn from_span(ecx: &ExtCtxt<'_>, sp: Span) -> ErrorLocation { - let loc = ecx.source_map().lookup_char_pos_adj(sp.lo()); + let loc = ecx.source_map().lookup_char_pos(sp.lo()); ErrorLocation { - filename: loc.filename, + filename: loc.file.name.clone(), line: loc.line } } diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index 62a6972122abd..08abbf5e8a4dc 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -388,16 +388,6 @@ impl SourceMap { } } - pub fn lookup_char_pos_adj(&self, pos: BytePos) -> LocWithOpt { - let loc = self.lookup_char_pos(pos); - LocWithOpt { - filename: loc.file.name.clone(), - line: loc.line, - col: loc.col, - file: Some(loc.file) - } - } - /// Returns `Some(span)`, a union of the lhs and rhs span. The lhs must precede the rhs. If /// there are gaps between lhs and rhs, the resulting union will cross these gaps. /// For this to work, the spans have to be: @@ -438,10 +428,10 @@ impl SourceMap { return "no-location".to_string(); } - let lo = self.lookup_char_pos_adj(sp.lo()); - let hi = self.lookup_char_pos_adj(sp.hi()); + let lo = self.lookup_char_pos(sp.lo()); + let hi = self.lookup_char_pos(sp.hi()); format!("{}:{}:{}: {}:{}", - lo.filename, + lo.file.name, lo.line, lo.col.to_usize() + 1, hi.line, diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index db1543ff13f7e..81cf804cf0b73 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -1295,7 +1295,7 @@ impl Sub for CharPos { } // _____________________________________________________________________________ -// Loc, LocWithOpt, SourceFileAndLine, SourceFileAndBytePos +// Loc, SourceFileAndLine, SourceFileAndBytePos // /// A source code location used for error reporting. @@ -1311,17 +1311,6 @@ pub struct Loc { pub col_display: usize, } -/// A source code location used as the result of `lookup_char_pos_adj`. -// Actually, *none* of the clients use the filename *or* file field; -// perhaps they should just be removed. -#[derive(Debug)] -pub struct LocWithOpt { - pub filename: FileName, - pub line: usize, - pub col: CharPos, - pub file: Option>, -} - // Used to be structural records. #[derive(Debug)] pub struct SourceFileAndLine { pub sf: Lrc, pub line: usize } From 1c3979ca16df0c94be65c967ba6a82410e42db24 Mon Sep 17 00:00:00 2001 From: Bastian Gruber Date: Sat, 6 Apr 2019 11:57:02 +0200 Subject: [PATCH 04/53] Add book.toml to tools/unstable, add copy_book_toml to scipt --- .../unstable-book-gen/src}/book.toml | 1 + src/tools/unstable-book-gen/src/main.rs | 7 +++++++ 2 files changed, 8 insertions(+) rename src/{doc/unstable-book => tools/unstable-book-gen/src}/book.toml (57%) diff --git a/src/doc/unstable-book/book.toml b/src/tools/unstable-book-gen/src/book.toml similarity index 57% rename from src/doc/unstable-book/book.toml rename to src/tools/unstable-book-gen/src/book.toml index 5534340f0db16..5b2e19bd7aa78 100644 --- a/src/doc/unstable-book/book.toml +++ b/src/tools/unstable-book-gen/src/book.toml @@ -1,2 +1,3 @@ [book] title = "The Rust Unstable Book" +author = "The Rust Community" diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs index 427014ce7fe55..ec8654adb41d7 100644 --- a/src/tools/unstable-book-gen/src/main.rs +++ b/src/tools/unstable-book-gen/src/main.rs @@ -116,6 +116,11 @@ fn copy_recursive(path: &Path, to: &Path) { } } +fn copy_book_toml(path: &Path) { + let mut file = t!(File::create(&path.join("book.toml"))); + t!(file.write_fmt(format_args!(include_str!("book.toml")); +} + fn main() { let src_path_str = env::args_os().skip(1).next().expect("source path required"); let dest_path_str = env::args_os().skip(2).next().expect("destination path required"); @@ -141,4 +146,6 @@ fn main() { copy_recursive(&doc_src_path, &dest_path); generate_summary(&dest_path, &lang_features, &lib_features); + + copy_book_toml(&dest_path); } From 5ddb339c9d34e96ebceb9bb40436c736d0f9fddd Mon Sep 17 00:00:00 2001 From: Bastian Gruber Date: Sat, 6 Apr 2019 12:00:43 +0200 Subject: [PATCH 05/53] Remove copy_book_toml method in favor for copy_recursive --- src/tools/unstable-book-gen/src/main.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs index ec8654adb41d7..427014ce7fe55 100644 --- a/src/tools/unstable-book-gen/src/main.rs +++ b/src/tools/unstable-book-gen/src/main.rs @@ -116,11 +116,6 @@ fn copy_recursive(path: &Path, to: &Path) { } } -fn copy_book_toml(path: &Path) { - let mut file = t!(File::create(&path.join("book.toml"))); - t!(file.write_fmt(format_args!(include_str!("book.toml")); -} - fn main() { let src_path_str = env::args_os().skip(1).next().expect("source path required"); let dest_path_str = env::args_os().skip(2).next().expect("destination path required"); @@ -146,6 +141,4 @@ fn main() { copy_recursive(&doc_src_path, &dest_path); generate_summary(&dest_path, &lang_features, &lib_features); - - copy_book_toml(&dest_path); } From 280277a28b38d5f9a17f79fcb52b79486005bd64 Mon Sep 17 00:00:00 2001 From: Bastian Gruber Date: Sat, 6 Apr 2019 12:05:45 +0200 Subject: [PATCH 06/53] path -> from --- src/tools/unstable-book-gen/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs index 427014ce7fe55..d65c427523a26 100644 --- a/src/tools/unstable-book-gen/src/main.rs +++ b/src/tools/unstable-book-gen/src/main.rs @@ -102,8 +102,8 @@ fn generate_unstable_book_files(src :&Path, out: &Path, features :&Features) { } } -fn copy_recursive(path: &Path, to: &Path) { - for entry in t!(fs::read_dir(path)) { +fn copy_recursive(from: &Path, to: &Path) { + for entry in t!(fs::read_dir(from)) { let e = t!(entry); let t = t!(e.metadata()); let dest = &to.join(e.file_name()); From 442bef754eb9a521ecd7047b00ab796a54d8b10c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 7 Apr 2019 11:16:26 +0200 Subject: [PATCH 07/53] compiletest normalization: preserve non-JSON lines such as ICEs --- src/tools/compiletest/src/json.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 15d449260efa0..ba919f4c4118a 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -78,7 +78,8 @@ pub fn extract_rendered(output: &str, proc_res: &ProcRes) -> String { } } } else { - None + // preserve non-JSON lines, such as ICEs + Some(format!("{}\n", line)) } }) .collect() From 0c455463ba4140aaeb4179c2eee3644863d17322 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 7 Apr 2019 12:43:40 +0200 Subject: [PATCH 08/53] fix tests --- src/librustc_mir/interpret/validity.rs | 2 +- .../cfg-arg-invalid-1.stderr | 2 ++ .../cfg-arg-invalid-2.stderr | 2 ++ .../cfg-arg-invalid-3.stderr | 2 ++ .../cfg-arg-invalid-4.stderr | 2 ++ .../cfg-arg-invalid-5.stderr | 2 ++ .../cfg-empty-codemap.stderr | 2 ++ src/test/ui/pattern/const-pat-ice.stderr | 13 +++++++++++++ 8 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/conditional-compilation/cfg-arg-invalid-1.stderr create mode 100644 src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr create mode 100644 src/test/ui/conditional-compilation/cfg-arg-invalid-3.stderr create mode 100644 src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr create mode 100644 src/test/ui/conditional-compilation/cfg-arg-invalid-5.stderr create mode 100644 src/test/ui/conditional-compilation/cfg-empty-codemap.stderr create mode 100644 src/test/ui/pattern/const-pat-ice.stderr diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index d4cf906619d89..11e4ffe19da62 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -353,7 +353,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> match self.ecx.memory.check_align(ptr, align) { Ok(_) => {}, Err(err) => { - error!("{:?} is not aligned to {:?}", ptr, align); + info!("{:?} is not aligned to {:?}", ptr, align); match err.kind { InterpError::InvalidNullPointerUsage => return validation_failure!("NULL reference", self.path), diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-1.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-1.stderr new file mode 100644 index 0000000000000..1e7922a9ff155 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-1.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`) + diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr new file mode 100644 index 0000000000000..b92e1fd3d97cf --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`) + diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-3.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-3.stderr new file mode 100644 index 0000000000000..5412f7ffd5c9c --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-3.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `a::b` (argument key must be an identifier) + diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr new file mode 100644 index 0000000000000..6853a69b9eb22 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`) + diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-5.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-5.stderr new file mode 100644 index 0000000000000..aafc4e8980cb5 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-5.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `a=10` (argument value must be a string) + diff --git a/src/test/ui/conditional-compilation/cfg-empty-codemap.stderr b/src/test/ui/conditional-compilation/cfg-empty-codemap.stderr new file mode 100644 index 0000000000000..128e3cd730680 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-empty-codemap.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `""` (expected `key` or `key="value"`) + diff --git a/src/test/ui/pattern/const-pat-ice.stderr b/src/test/ui/pattern/const-pat-ice.stderr new file mode 100644 index 0000000000000..11cb507d8e6d7 --- /dev/null +++ b/src/test/ui/pattern/const-pat-ice.stderr @@ -0,0 +1,13 @@ +thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1069:5 +note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. + +error: internal compiler error: unexpected panic + +note: the compiler unexpectedly panicked. this is a bug. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports + +note: rustc 1.35.0-dev running on x86_64-unknown-linux-gnu + +note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath + From 83dcc968fb084bf9c4e1658ea3b864167793717c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 7 Apr 2019 16:40:27 +0200 Subject: [PATCH 09/53] fix output test for backtrace-debuginfo.rs --- src/test/run-pass/backtrace-debuginfo.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs index 37c889e9df4ad..7f038ddecc1fa 100644 --- a/src/test/run-pass/backtrace-debuginfo.rs +++ b/src/test/run-pass/backtrace-debuginfo.rs @@ -10,9 +10,11 @@ // ignore-pretty issue #37195 // ignore-cloudabi spawning processes is not supported // ignore-emscripten spawning processes is not supported +// normalize-stderr-test ".*\n" -> "" -// note that above `-opt-bisect-limit=0` is used to basically disable -// optimizations +// Note that above `-opt-bisect-limit=0` is used to basically disable +// optimizations. It creates tons of output on stderr, hence we normalize +// that away entirely. use std::env; From be83bd5c107e1efc5c16f72441bf08757e160049 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 7 Apr 2019 16:45:28 +0200 Subject: [PATCH 10/53] normalize flags and rustc version in ICE repro --- src/test/ui/pattern/const-pat-ice.rs | 2 ++ src/test/ui/pattern/const-pat-ice.stderr | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/ui/pattern/const-pat-ice.rs b/src/test/ui/pattern/const-pat-ice.rs index 865c54be1ad7b..b866c7fa6cc9e 100644 --- a/src/test/ui/pattern/const-pat-ice.rs +++ b/src/test/ui/pattern/const-pat-ice.rs @@ -1,5 +1,7 @@ // failure-status: 101 // rustc-env:RUST_BACKTRACE=0 +// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" +// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" // This is a repro test for an ICE in our pattern handling of constants. diff --git a/src/test/ui/pattern/const-pat-ice.stderr b/src/test/ui/pattern/const-pat-ice.stderr index 11cb507d8e6d7..03580dfecfb59 100644 --- a/src/test/ui/pattern/const-pat-ice.stderr +++ b/src/test/ui/pattern/const-pat-ice.stderr @@ -7,7 +7,7 @@ note: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports -note: rustc 1.35.0-dev running on x86_64-unknown-linux-gnu +note: rustc VERSION running on TARGET -note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath +note: compiler flags: FLAGS From 126ac9ef6c11ced54ba9191aba916dd7d5206159 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 7 Apr 2019 17:56:50 +0200 Subject: [PATCH 11/53] Add test with current behaviour. This commit adds a test demonstrating the current behaviour when a macro defined in a module with the `#[macro_export]` is imported from the module rather than the crate root. --- src/test/ui/auxiliary/issue-59764.rs | 8 ++++++++ src/test/ui/issue-59764.rs | 14 ++++++++++++++ src/test/ui/issue-59764.stderr | 24 ++++++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 src/test/ui/auxiliary/issue-59764.rs create mode 100644 src/test/ui/issue-59764.rs create mode 100644 src/test/ui/issue-59764.stderr diff --git a/src/test/ui/auxiliary/issue-59764.rs b/src/test/ui/auxiliary/issue-59764.rs new file mode 100644 index 0000000000000..0243ef5c6c74a --- /dev/null +++ b/src/test/ui/auxiliary/issue-59764.rs @@ -0,0 +1,8 @@ +pub mod foo { + #[macro_export] + macro_rules! makro { + ($foo:ident) => { + fn $foo() { } + } + } +} diff --git a/src/test/ui/issue-59764.rs b/src/test/ui/issue-59764.rs new file mode 100644 index 0000000000000..8ac9b9eaba181 --- /dev/null +++ b/src/test/ui/issue-59764.rs @@ -0,0 +1,14 @@ +// aux-build:issue-59764.rs +// compile-flags:--extern issue_59764 +// edition:2018 + +use issue_59764::foo::makro; +//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] + +makro!(bar); +//~^ ERROR cannot determine resolution for the macro `makro` + +fn main() { + bar(); + //~^ ERROR cannot find function `bar` in this scope [E0425] +} diff --git a/src/test/ui/issue-59764.stderr b/src/test/ui/issue-59764.stderr new file mode 100644 index 0000000000000..a428488b009ec --- /dev/null +++ b/src/test/ui/issue-59764.stderr @@ -0,0 +1,24 @@ +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:5:5 + | +LL | use issue_59764::foo::makro; + | ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` + +error: cannot determine resolution for the macro `makro` + --> $DIR/issue-59764.rs:8:1 + | +LL | makro!(bar); + | ^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/issue-59764.rs:12:5 + | +LL | bar(); + | ^^^ not found in this scope + +error: aborting due to 3 previous errors + +Some errors occurred: E0425, E0432. +For more information about an error, try `rustc --explain E0425`. From 34c1572a42e7e148dc9bf21126b26f49fcaf1a56 Mon Sep 17 00:00:00 2001 From: Bastian Gruber Date: Sun, 7 Apr 2019 19:29:20 +0200 Subject: [PATCH 12/53] Change root path for unstable-book --- .../src => doc/unstable-book}/book.toml | 0 src/tools/tidy/src/unstable_book.rs | 8 ++++---- src/tools/unstable-book-gen/src/main.rs | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) rename src/{tools/unstable-book-gen/src => doc/unstable-book}/book.toml (100%) diff --git a/src/tools/unstable-book-gen/src/book.toml b/src/doc/unstable-book/book.toml similarity index 100% rename from src/tools/unstable-book-gen/src/book.toml rename to src/doc/unstable-book/book.toml diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs index cd60f36b1d273..f7e40ce4bae36 100644 --- a/src/tools/tidy/src/unstable_book.rs +++ b/src/tools/tidy/src/unstable_book.rs @@ -3,13 +3,13 @@ use std::fs; use std::path; use crate::features::{collect_lang_features, collect_lib_features, Features, Status}; -pub const PATH_STR: &str = "doc/unstable-book/src"; +pub const PATH_STR: &str = "doc/unstable-book"; -pub const COMPILER_FLAGS_DIR: &str = "compiler-flags"; +pub const COMPILER_FLAGS_DIR: &str = "src/compiler-flags"; -pub const LANG_FEATURES_DIR: &str = "language-features"; +pub const LANG_FEATURES_DIR: &str = "src/language-features"; -pub const LIB_FEATURES_DIR: &str = "library-features"; +pub const LIB_FEATURES_DIR: &str = "src/library-features"; /// Builds the path to the Unstable Book source directory from the Rust 'src' directory. pub fn unstable_book_path(base_src_path: &path::Path) -> path::PathBuf { diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs index d65c427523a26..e92d174a4e1d4 100644 --- a/src/tools/unstable-book-gen/src/main.rs +++ b/src/tools/unstable-book-gen/src/main.rs @@ -52,7 +52,7 @@ fn set_to_summary_str(set: &BTreeSet, dir: &str fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Features) { let compiler_flags = collect_unstable_book_section_file_names( - &path.join("compiler-flags")); + &path.join("src/compiler-flags")); let compiler_flags_str = set_to_summary_str(&compiler_flags, "compiler-flags"); @@ -61,11 +61,11 @@ fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Featur let unstable_lib_features = collect_unstable_feature_names(&lib_features); let lang_features_str = set_to_summary_str(&unstable_lang_features, - LANG_FEATURES_DIR); + "language-features"); let lib_features_str = set_to_summary_str(&unstable_lib_features, - LIB_FEATURES_DIR); + "library-features"); - let mut file = t!(File::create(&path.join("SUMMARY.md"))); + let mut file = t!(File::create(&path.join("src/SUMMARY.md"))); t!(file.write_fmt(format_args!(include_str!("SUMMARY.md"), compiler_flags = compiler_flags_str, language_features = lang_features_str, @@ -120,7 +120,7 @@ fn main() { let src_path_str = env::args_os().skip(1).next().expect("source path required"); let dest_path_str = env::args_os().skip(2).next().expect("destination path required"); let src_path = Path::new(&src_path_str); - let dest_path = Path::new(&dest_path_str).join("src"); + let dest_path = Path::new(&dest_path_str); let lang_features = collect_lang_features(src_path, &mut false); let lib_features = collect_lib_features(src_path).into_iter().filter(|&(ref name, _)| { From b8e9da7c0885f624d186499f7521bae71381a97c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 8 Apr 2019 10:32:35 +0200 Subject: [PATCH 13/53] `asm!` output can neither be promotable nor const --- src/librustc_mir/transform/promote_consts.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 43723aaf568da..9c792a35bb429 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -101,7 +101,6 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { if *temp == TempState::Undefined { match context { PlaceContext::MutatingUse(MutatingUseContext::Store) | - PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | PlaceContext::MutatingUse(MutatingUseContext::Call) => { *temp = TempState::Defined { location, From 6b018444081a6a2940889bec495acea923e365cf Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 8 Apr 2019 15:28:00 +0200 Subject: [PATCH 14/53] Generalize initial "not const" assignments --- src/librustc_mir/transform/promote_consts.rs | 15 ++++++---- src/librustc_mir/transform/qualify_consts.rs | 31 ++++++++------------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 9c792a35bb429..ddf963c7fa9b5 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -44,8 +44,8 @@ pub enum TempState { impl TempState { pub fn is_promotable(&self) -> bool { debug!("is_promotable: self={:?}", self); - if let TempState::Defined { uses, .. } = *self { - uses > 0 + if let TempState::Defined { .. } = *self { + true } else { false } @@ -80,9 +80,14 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { context: PlaceContext<'tcx>, location: Location) { debug!("visit_local: index={:?} context={:?} location={:?}", index, context, location); - // We're only interested in temporaries - if self.mir.local_kind(index) != LocalKind::Temp { - return; + // We're only interested in temporaries and the return place + match self.mir.local_kind(index) { + | LocalKind::Temp + | LocalKind::ReturnPointer + => {}, + | LocalKind::Arg + | LocalKind::Var + => return, } // Ignore drops, if the temp gets promoted, diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 1faa9ad0d0da4..6272425012b98 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -631,26 +631,21 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { }; for (local, decl) in mir.local_decls.iter_enumerated() { - match mir.local_kind(local) { - LocalKind::Arg => { - let qualifs = cx.qualifs_in_any_value_of_ty(decl.ty); - for (per_local, qualif) in &mut cx.per_local.as_mut().zip(qualifs).0 { - if *qualif { - per_local.insert(local); - } + if let LocalKind::Arg = mir.local_kind(local) { + let qualifs = cx.qualifs_in_any_value_of_ty(decl.ty); + for (per_local, qualif) in &mut cx.per_local.as_mut().zip(qualifs).0 { + if *qualif { + per_local.insert(local); } - cx.per_local[IsNotConst].insert(local); - } - - LocalKind::Var if mode == Mode::Fn => { - cx.per_local[IsNotConst].insert(local); - } - - LocalKind::Temp if !temps[local].is_promotable() => { - cx.per_local[IsNotConst].insert(local); } - - _ => {} + } + if !temps[local].is_promotable() { + cx.per_local[IsNotConst].insert(local); + } + if let LocalKind::Var = mir.local_kind(local) { + // Sanity check to prevent implicit and explicit promotion of + // named locals + assert!(cx.per_local[IsNotConst].contains(local)); } } From ec5206588fe31e631d8f8b1d27400f18744b448e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 8 Apr 2019 15:32:31 +0200 Subject: [PATCH 15/53] Explicit promotion is indistinguishable from explicit promotion Implicit promotion on the other hand has very strict rules on what may be done --- src/librustc_mir/transform/qualify_consts.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 6272425012b98..9095b78dd726a 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -508,13 +508,11 @@ impl Qualif for IsNotConst { } } -// Refers to temporaries which cannot be promoted as -// promote_consts decided they weren't simple enough. -// FIXME(oli-obk,eddyb): Remove this flag entirely and -// solely process this information via `IsNotConst`. -struct IsNotPromotable; +/// Refers to temporaries which cannot be promoted *implicitly*. +/// Explicit promotion e.g. for constant arguments declared via `rustc_args_required_const`. +struct IsNotImplicitlyPromotable; -impl Qualif for IsNotPromotable { +impl Qualif for IsNotImplicitlyPromotable { const IDX: usize = 3; fn in_call( @@ -550,7 +548,7 @@ macro_rules! static_assert_seq_qualifs { static_assert!(SEQ_QUALIFS: QUALIF_COUNT == $i); }; } -static_assert_seq_qualifs!(0 => HasMutInterior, NeedsDrop, IsNotConst, IsNotPromotable); +static_assert_seq_qualifs!(0 => HasMutInterior, NeedsDrop, IsNotConst, IsNotImplicitlyPromotable); impl ConstCx<'_, 'tcx> { fn qualifs_in_any_value_of_ty(&self, ty: Ty<'tcx>) -> PerQualif { @@ -558,7 +556,7 @@ impl ConstCx<'_, 'tcx> { qualifs[HasMutInterior] = HasMutInterior::in_any_value_of_ty(self, ty).unwrap_or(false); qualifs[NeedsDrop] = NeedsDrop::in_any_value_of_ty(self, ty).unwrap_or(false); qualifs[IsNotConst] = IsNotConst::in_any_value_of_ty(self, ty).unwrap_or(false); - qualifs[IsNotPromotable] = IsNotPromotable::in_any_value_of_ty(self, ty).unwrap_or(false); + qualifs[IsNotImplicitlyPromotable] = IsNotImplicitlyPromotable::in_any_value_of_ty(self, ty).unwrap_or(false); qualifs } @@ -567,7 +565,7 @@ impl ConstCx<'_, 'tcx> { qualifs[HasMutInterior] = HasMutInterior::in_local(self, local); qualifs[NeedsDrop] = NeedsDrop::in_local(self, local); qualifs[IsNotConst] = IsNotConst::in_local(self, local); - qualifs[IsNotPromotable] = IsNotPromotable::in_local(self, local); + qualifs[IsNotImplicitlyPromotable] = IsNotImplicitlyPromotable::in_local(self, local); qualifs } @@ -576,7 +574,7 @@ impl ConstCx<'_, 'tcx> { qualifs[HasMutInterior] = HasMutInterior::in_value(self, source); qualifs[NeedsDrop] = NeedsDrop::in_value(self, source); qualifs[IsNotConst] = IsNotConst::in_value(self, source); - qualifs[IsNotPromotable] = IsNotPromotable::in_value(self, source); + qualifs[IsNotImplicitlyPromotable] = IsNotImplicitlyPromotable::in_value(self, source); qualifs } } From d3d56732a7278881900ce6709892636bdc546862 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 8 Apr 2019 15:36:00 +0200 Subject: [PATCH 16/53] Get rid of "is not const" naming --- src/librustc_mir/transform/qualify_consts.rs | 32 ++++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 9095b78dd726a..8dd060d7a150d 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -365,11 +365,11 @@ impl Qualif for NeedsDrop { } } -// Not constant at all - non-`const fn` calls, asm!, +// Not promotable at all - non-`const fn` calls, asm!, // pointer comparisons, ptr-to-int casts, etc. -struct IsNotConst; +struct IsNotPromotable; -impl Qualif for IsNotConst { +impl Qualif for IsNotPromotable { const IDX: usize = 2; fn in_static(cx: &ConstCx<'_, 'tcx>, static_: &Static<'tcx>) -> bool { @@ -548,14 +548,14 @@ macro_rules! static_assert_seq_qualifs { static_assert!(SEQ_QUALIFS: QUALIF_COUNT == $i); }; } -static_assert_seq_qualifs!(0 => HasMutInterior, NeedsDrop, IsNotConst, IsNotImplicitlyPromotable); +static_assert_seq_qualifs!(0 => HasMutInterior, NeedsDrop, IsNotPromotable, IsNotImplicitlyPromotable); impl ConstCx<'_, 'tcx> { fn qualifs_in_any_value_of_ty(&self, ty: Ty<'tcx>) -> PerQualif { let mut qualifs = PerQualif::default(); qualifs[HasMutInterior] = HasMutInterior::in_any_value_of_ty(self, ty).unwrap_or(false); qualifs[NeedsDrop] = NeedsDrop::in_any_value_of_ty(self, ty).unwrap_or(false); - qualifs[IsNotConst] = IsNotConst::in_any_value_of_ty(self, ty).unwrap_or(false); + qualifs[IsNotPromotable] = IsNotPromotable::in_any_value_of_ty(self, ty).unwrap_or(false); qualifs[IsNotImplicitlyPromotable] = IsNotImplicitlyPromotable::in_any_value_of_ty(self, ty).unwrap_or(false); qualifs } @@ -564,7 +564,7 @@ impl ConstCx<'_, 'tcx> { let mut qualifs = PerQualif::default(); qualifs[HasMutInterior] = HasMutInterior::in_local(self, local); qualifs[NeedsDrop] = NeedsDrop::in_local(self, local); - qualifs[IsNotConst] = IsNotConst::in_local(self, local); + qualifs[IsNotPromotable] = IsNotPromotable::in_local(self, local); qualifs[IsNotImplicitlyPromotable] = IsNotImplicitlyPromotable::in_local(self, local); qualifs } @@ -573,7 +573,7 @@ impl ConstCx<'_, 'tcx> { let mut qualifs = PerQualif::default(); qualifs[HasMutInterior] = HasMutInterior::in_value(self, source); qualifs[NeedsDrop] = NeedsDrop::in_value(self, source); - qualifs[IsNotConst] = IsNotConst::in_value(self, source); + qualifs[IsNotPromotable] = IsNotPromotable::in_value(self, source); qualifs[IsNotImplicitlyPromotable] = IsNotImplicitlyPromotable::in_value(self, source); qualifs } @@ -638,12 +638,12 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { } } if !temps[local].is_promotable() { - cx.per_local[IsNotConst].insert(local); + cx.per_local[IsNotPromotable].insert(local); } if let LocalKind::Var = mir.local_kind(local) { // Sanity check to prevent implicit and explicit promotion of // named locals - assert!(cx.per_local[IsNotConst].contains(local)); + assert!(cx.per_local[IsNotPromotable].contains(local)); } } @@ -691,11 +691,11 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { // the borrowed place is disallowed from being borrowed, // due to either a mutable borrow (with some exceptions), // or an shared borrow of a value with interior mutability. - // Then `HasMutInterior` is replaced with `IsNotConst`, + // Then `HasMutInterior` is replaced with `IsNotPromotable`, // to avoid duplicate errors (e.g. from reborrowing). if qualifs[HasMutInterior] { qualifs[HasMutInterior] = false; - qualifs[IsNotConst] = true; + qualifs[IsNotPromotable] = true; if self.mode != Mode::Fn { if let BorrowKind::Mut { .. } = kind { @@ -810,7 +810,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { } } - // Ensure the `IsNotConst` qualification is preserved. + // Ensure the `IsNotPromotable` qualification is preserved. // NOTE(eddyb) this is actually unnecessary right now, as // we never replace the local's qualif, but we might in // the future, and so it serves to catch changes that unset @@ -818,7 +818,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { // be replaced with calling `insert` to re-set the bit). if kind == LocalKind::Temp { if !self.temp_promotion_state[index].is_promotable() { - assert!(self.cx.per_local[IsNotConst].contains(index)); + assert!(self.cx.per_local[IsNotPromotable].contains(index)); } } } @@ -904,7 +904,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { // Account for errors in consts by using the // conservative type qualification instead. - if qualifs[IsNotConst] { + if qualifs[IsNotPromotable] { qualifs = self.qualifs_in_any_value_of_ty(mir.return_ty()); } @@ -1319,7 +1319,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // which happens even without the user requesting it. // We can error out with a hard error if the argument is not // constant here. - if !IsNotConst::in_operand(self, arg) { + if !IsNotPromotable::in_operand(self, arg) { debug!("visit_terminator_kind: candidate={:?}", candidate); self.promotion_candidates.push(candidate); } else { @@ -1437,7 +1437,7 @@ fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if mir.return_ty().references_error() { tcx.sess.delay_span_bug(mir.span, "mir_const_qualif: Mir had errors"); - return (1 << IsNotConst::IDX, Lrc::new(BitSet::new_empty(0))); + return (1 << IsNotPromotable::IDX, Lrc::new(BitSet::new_empty(0))); } Checker::new(tcx, def_id, mir, Mode::Const).check_const() From c63b9fff3f1e589d75db982e9839f9d52c5c57cc Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 8 Apr 2019 16:24:59 +0200 Subject: [PATCH 17/53] Pacify tidy --- src/librustc_mir/transform/qualify_consts.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 8dd060d7a150d..ae13e18ff03b0 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -548,7 +548,9 @@ macro_rules! static_assert_seq_qualifs { static_assert!(SEQ_QUALIFS: QUALIF_COUNT == $i); }; } -static_assert_seq_qualifs!(0 => HasMutInterior, NeedsDrop, IsNotPromotable, IsNotImplicitlyPromotable); +static_assert_seq_qualifs!( + 0 => HasMutInterior, NeedsDrop, IsNotPromotable, IsNotImplicitlyPromotable +); impl ConstCx<'_, 'tcx> { fn qualifs_in_any_value_of_ty(&self, ty: Ty<'tcx>) -> PerQualif { @@ -556,7 +558,8 @@ impl ConstCx<'_, 'tcx> { qualifs[HasMutInterior] = HasMutInterior::in_any_value_of_ty(self, ty).unwrap_or(false); qualifs[NeedsDrop] = NeedsDrop::in_any_value_of_ty(self, ty).unwrap_or(false); qualifs[IsNotPromotable] = IsNotPromotable::in_any_value_of_ty(self, ty).unwrap_or(false); - qualifs[IsNotImplicitlyPromotable] = IsNotImplicitlyPromotable::in_any_value_of_ty(self, ty).unwrap_or(false); + qualifs[IsNotImplicitlyPromotable] = + IsNotImplicitlyPromotable::in_any_value_of_ty(self, ty).unwrap_or(false); qualifs } From ae4717d95010f2d75ba02c200ecd0ace7de0a93b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 8 Apr 2019 18:34:45 +0200 Subject: [PATCH 18/53] Elaborate on implicit promotability --- src/librustc_mir/transform/qualify_consts.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index ae13e18ff03b0..5f8e7ad796ba3 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -509,7 +509,10 @@ impl Qualif for IsNotPromotable { } /// Refers to temporaries which cannot be promoted *implicitly*. -/// Explicit promotion e.g. for constant arguments declared via `rustc_args_required_const`. +/// Explicit promotion e.g. for constant arguments declared via `rustc_args_required_const` or by +/// happening inside a constant, static or const fn. Inside a const context all constness rules +/// apply, so implicit promotion simply has to follow the regular constant rules (modulo interior +/// mutability or `Drop` rules which are handled `HasMutInterior` and `NeedsDrop` respectively) struct IsNotImplicitlyPromotable; impl Qualif for IsNotImplicitlyPromotable { From 03727a4f257fc86b467457a1e87d06d56e62d5f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 8 Apr 2019 20:44:31 +0200 Subject: [PATCH 19/53] Clean up jobserver integration --- src/librustc_data_structures/Cargo.toml | 2 +- src/librustc_data_structures/jobserver.rs | 128 ++-------------------- 2 files changed, 8 insertions(+), 122 deletions(-) diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index 63e44d82a28c3..d586b376d45b6 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["dylib"] [dependencies] ena = "0.13" log = "0.4" -jobserver_crate = { version = "0.1", package = "jobserver" } +jobserver_crate = { version = "0.1.13", package = "jobserver" } lazy_static = "1" rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } serialize = { path = "../libserialize" } diff --git a/src/librustc_data_structures/jobserver.rs b/src/librustc_data_structures/jobserver.rs index 48ac8125a0d66..b42ccb932b9dc 100644 --- a/src/librustc_data_structures/jobserver.rs +++ b/src/librustc_data_structures/jobserver.rs @@ -1,89 +1,5 @@ -use jobserver_crate::{Client, HelperThread, Acquired}; +use jobserver_crate::Client; use lazy_static::lazy_static; -use std::sync::{Condvar, Arc, Mutex}; -use std::mem; - -#[derive(Default)] -struct LockedProxyData { - /// The number of free thread tokens, this may include the implicit token given to the process - free: usize, - - /// The number of threads waiting for a token - waiters: usize, - - /// The number of tokens we requested from the server - requested: usize, - - /// Stored tokens which will be dropped when we no longer need them - tokens: Vec, -} - -impl LockedProxyData { - fn request_token(&mut self, thread: &Mutex) { - self.requested += 1; - thread.lock().unwrap().request_token(); - } - - fn release_token(&mut self, cond_var: &Condvar) { - if self.waiters > 0 { - self.free += 1; - cond_var.notify_one(); - } else { - if self.tokens.is_empty() { - // We are returning the implicit token - self.free += 1; - } else { - // Return a real token to the server - self.tokens.pop().unwrap(); - } - } - } - - fn take_token(&mut self, thread: &Mutex) -> bool { - if self.free > 0 { - self.free -= 1; - self.waiters -= 1; - - // We stole some token reqested by someone else - // Request another one - if self.requested + self.free < self.waiters { - self.request_token(thread); - } - - true - } else { - false - } - } - - fn new_requested_token(&mut self, token: Acquired, cond_var: &Condvar) { - self.requested -= 1; - - // Does anything need this token? - if self.waiters > 0 { - self.free += 1; - self.tokens.push(token); - cond_var.notify_one(); - } else { - // Otherwise we'll just drop it - mem::drop(token); - } - } -} - -#[derive(Default)] -struct ProxyData { - lock: Mutex, - cond_var: Condvar, -} - -/// A helper type which makes managing jobserver tokens easier. -/// It also allows you to treat the implicit token given to the process -/// in the same manner as requested tokens. -struct Proxy { - thread: Mutex, - data: Arc, -} lazy_static! { // We can only call `from_env` once per process @@ -105,20 +21,12 @@ lazy_static! { // per-process. static ref GLOBAL_CLIENT: Client = unsafe { Client::from_env().unwrap_or_else(|| { - Client::new(32).expect("failed to create jobserver") + let client = Client::new(32).expect("failed to create jobserver"); + // Acquire a token for the main thread which we can release later + client.acquire_raw().ok(); + client }) }; - - static ref GLOBAL_PROXY: Proxy = { - let data = Arc::new(ProxyData::default()); - - Proxy { - data: data.clone(), - thread: Mutex::new(client().into_helper_thread(move |token| { - data.lock.lock().unwrap().new_requested_token(token.unwrap(), &data.cond_var); - }).unwrap()), - } - }; } pub fn client() -> Client { @@ -126,31 +34,9 @@ pub fn client() -> Client { } pub fn acquire_thread() { - GLOBAL_PROXY.acquire_token(); + GLOBAL_CLIENT.acquire_raw().ok(); } pub fn release_thread() { - GLOBAL_PROXY.release_token(); -} - -impl Proxy { - fn release_token(&self) { - self.data.lock.lock().unwrap().release_token(&self.data.cond_var); - } - - fn acquire_token(&self) { - let mut data = self.data.lock.lock().unwrap(); - data.waiters += 1; - if data.take_token(&self.thread) { - return; - } - // Request a token for us - data.request_token(&self.thread); - loop { - data = self.data.cond_var.wait(data).unwrap(); - if data.take_token(&self.thread) { - return; - } - } - } + GLOBAL_CLIENT.release_raw().ok(); } From 724ca0584e2be0714edf2f30b86230666d7a9d19 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 9 Apr 2019 14:47:00 +0200 Subject: [PATCH 20/53] Exclude profiler-generated symbols from MSVC __imp_-symbol workaround. --- src/librustc_codegen_llvm/back/write.rs | 18 +++++++++++++++++- .../pgo-gen-no-imp-symbols/Makefile | 11 +++++++++++ .../pgo-gen-no-imp-symbols/test.rs | 1 + 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile create mode 100644 src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/test.rs diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index f0ed201ad5c27..3628adeb3e9a7 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -795,6 +795,7 @@ fn create_msvc_imps( } else { "\x01__imp_" }; + unsafe { let i8p_ty = Type::i8p_llcx(llcx); let globals = base::iter_globals(llmod) @@ -802,14 +803,23 @@ fn create_msvc_imps( llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage && llvm::LLVMIsDeclaration(val) == 0 }) - .map(move |val| { + .filter_map(|val| { + // Exclude some symbols that we know are not Rust symbols. let name = CStr::from_ptr(llvm::LLVMGetValueName(val)); + if ignored(name.to_bytes()) { + None + } else { + Some((val, name)) + } + }) + .map(move |(val, name)| { let mut imp_name = prefix.as_bytes().to_vec(); imp_name.extend(name.to_bytes()); let imp_name = CString::new(imp_name).unwrap(); (imp_name, val) }) .collect::>(); + for (imp_name, val) in globals { let imp = llvm::LLVMAddGlobal(llmod, i8p_ty, @@ -818,4 +828,10 @@ fn create_msvc_imps( llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage); } } + + // Use this function to exclude certain symbols from `__imp` generation. + fn ignored(symbol_name: &[u8]) -> bool { + // These are symbols generated by LLVM's profiling instrumentation + symbol_name.starts_with(b"__llvm_profile_") + } } diff --git a/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile new file mode 100644 index 0000000000000..dc52e91317a5a --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +all: +ifeq ($(PROFILER_SUPPORT),1) + $(RUSTC) -O -Ccodegen-units=1 -Z pgo-gen="$(TMPDIR)/test.profraw" --emit=llvm-ir test.rs + # We expect symbols starting with "__llvm_profile_". + $(CGREP) "__llvm_profile_" < $(TMPDIR)/test.ll + # We do NOT expect the "__imp_" version of these symbols. + $(CGREP) -v "__imp___llvm_profile_" < $(TMPDIR)/test.ll # 64 bit + $(CGREP) -v "__imp____llvm_profile_" < $(TMPDIR)/test.ll # 32 bit +endif diff --git a/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/test.rs b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/test.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/test.rs @@ -0,0 +1 @@ +fn main() {} From 3a35b7e6c711a700efa591b0ef4a20ac864913e7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 9 Apr 2019 22:08:57 +0200 Subject: [PATCH 21/53] normalize away spurious error --- src/test/ui/duplicate/dupe-symbols-7.rs | 4 ++++ src/test/ui/duplicate/dupe-symbols-7.stderr | 2 +- src/test/ui/huge-array.rs | 4 ++++ src/test/ui/issues/issue-15919.rs | 4 ++++ src/test/ui/issues/issue-17913.rs | 4 ++++ src/test/ui/linkage2.rs | 4 ++++ src/test/ui/linkage2.stderr | 2 +- src/test/ui/linkage3.rs | 4 ++++ src/test/ui/linkage3.stderr | 2 +- 9 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/test/ui/duplicate/dupe-symbols-7.rs b/src/test/ui/duplicate/dupe-symbols-7.rs index b28f1a40fe93b..b838aaa102ebb 100644 --- a/src/test/ui/duplicate/dupe-symbols-7.rs +++ b/src/test/ui/duplicate/dupe-symbols-7.rs @@ -1,5 +1,9 @@ // // error-pattern: entry symbol `main` defined multiple times + +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" #![allow(warnings)] #[no_mangle] diff --git a/src/test/ui/duplicate/dupe-symbols-7.stderr b/src/test/ui/duplicate/dupe-symbols-7.stderr index a1dbbb0c685fb..7d033ec3d85fa 100644 --- a/src/test/ui/duplicate/dupe-symbols-7.stderr +++ b/src/test/ui/duplicate/dupe-symbols-7.stderr @@ -1,5 +1,5 @@ error: entry symbol `main` defined multiple times - --> $DIR/dupe-symbols-7.rs:6:1 + --> $DIR/dupe-symbols-7.rs:10:1 | LL | fn main(){} | ^^^^^^^^^^^ diff --git a/src/test/ui/huge-array.rs b/src/test/ui/huge-array.rs index 0608b23dac6b1..f58dcd5806761 100644 --- a/src/test/ui/huge-array.rs +++ b/src/test/ui/huge-array.rs @@ -1,5 +1,9 @@ // error-pattern:; 1518600000 +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + fn generic(t: T) { let s: [T; 1518600000] = [t; 1518600000]; } diff --git a/src/test/ui/issues/issue-15919.rs b/src/test/ui/issues/issue-15919.rs index 19ecf2f657e0a..a7ac4802a12d5 100644 --- a/src/test/ui/issues/issue-15919.rs +++ b/src/test/ui/issues/issue-15919.rs @@ -1,6 +1,10 @@ // error-pattern: too big for the current architecture // normalize-stderr-test "\[usize; \d+\]" -> "[usize; N]" +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + #[cfg(target_pointer_width = "32")] fn main() { let x = [0usize; 0xffff_ffff]; diff --git a/src/test/ui/issues/issue-17913.rs b/src/test/ui/issues/issue-17913.rs index b0c4ef54b165d..48d8f407aa1e4 100644 --- a/src/test/ui/issues/issue-17913.rs +++ b/src/test/ui/issues/issue-17913.rs @@ -1,6 +1,10 @@ // normalize-stderr-test "\[&usize; \d+\]" -> "[&usize; N]" // error-pattern: too big for the current architecture +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + #![feature(box_syntax)] #[cfg(target_pointer_width = "64")] diff --git a/src/test/ui/linkage2.rs b/src/test/ui/linkage2.rs index 6d1410a90bd21..fa4221fb3392e 100644 --- a/src/test/ui/linkage2.rs +++ b/src/test/ui/linkage2.rs @@ -1,3 +1,7 @@ +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + #![feature(linkage)] extern { diff --git a/src/test/ui/linkage2.stderr b/src/test/ui/linkage2.stderr index 64213f1270adb..c72978388ebfe 100644 --- a/src/test/ui/linkage2.stderr +++ b/src/test/ui/linkage2.stderr @@ -1,5 +1,5 @@ error: must have type `*const T` or `*mut T` - --> $DIR/linkage2.rs:4:32 + --> $DIR/linkage2.rs:8:32 | LL | #[linkage = "extern_weak"] static foo: i32; | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/linkage3.rs b/src/test/ui/linkage3.rs index f094a0d53e941..1462079acf7e7 100644 --- a/src/test/ui/linkage3.rs +++ b/src/test/ui/linkage3.rs @@ -1,3 +1,7 @@ +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + #![feature(linkage)] extern { diff --git a/src/test/ui/linkage3.stderr b/src/test/ui/linkage3.stderr index a03593ff2c68e..b74fdc91429e2 100644 --- a/src/test/ui/linkage3.stderr +++ b/src/test/ui/linkage3.stderr @@ -1,5 +1,5 @@ error: invalid linkage specified - --> $DIR/linkage3.rs:4:24 + --> $DIR/linkage3.rs:8:24 | LL | #[linkage = "foo"] static foo: *const i32; | ^^^^^^^^^^^^^^^^^^^^^^^ From 8861232b5a068da7d5ed6553fe65783f39987570 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 9 Apr 2019 22:36:56 +0200 Subject: [PATCH 22/53] some more tests need normalization --- src/test/ui/huge-array-simple.rs | 4 ++++ src/test/ui/huge-struct.rs | 4 ++++ src/test/ui/issues/issue-56762.rs | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/src/test/ui/huge-array-simple.rs b/src/test/ui/huge-array-simple.rs index 8b244a47232fa..0ff27168a7d86 100644 --- a/src/test/ui/huge-array-simple.rs +++ b/src/test/ui/huge-array-simple.rs @@ -1,6 +1,10 @@ // error-pattern: too big for the current architecture // normalize-stderr-test "; \d+]" -> "; N]" + +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" #![allow(exceeding_bitshifts)] #[cfg(target_pointer_width = "64")] diff --git a/src/test/ui/huge-struct.rs b/src/test/ui/huge-struct.rs index 74e43cc6472be..dc7d75a6f028e 100644 --- a/src/test/ui/huge-struct.rs +++ b/src/test/ui/huge-struct.rs @@ -2,6 +2,10 @@ // normalize-stderr-test "S1M" -> "SXX" // error-pattern: too big for the current +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + struct S32 { v0: T, v1: T, diff --git a/src/test/ui/issues/issue-56762.rs b/src/test/ui/issues/issue-56762.rs index 97b66b2c7c923..8bb81b907c9a4 100644 --- a/src/test/ui/issues/issue-56762.rs +++ b/src/test/ui/issues/issue-56762.rs @@ -1,4 +1,8 @@ // only-x86_64 + +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" const HUGE_SIZE: usize = !0usize / 8; From 1ad46cd1ede1c246802e5fc3d988d8c6aaa9ac46 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 9 Apr 2019 15:38:32 -0700 Subject: [PATCH 23/53] Fix links on keyword docs. - Make links relative. - Adjust links from old 2018-edition book. - Fix broken link in `let` docs. --- src/libstd/keyword_docs.rs | 55 +++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 7b0d1549e061a..ffe50f11e8a50 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -25,8 +25,7 @@ /// /// For more information on what `as` is capable of, see the [Reference] /// -/// [Reference]: -/// https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions +/// [Reference]: ../reference/expressions/operator-expr.html#type-cast-expressions /// [`crate`]: keyword.crate.html mod as_keyword { } @@ -80,8 +79,8 @@ mod as_keyword { } /// /// [pointer]: primitive.pointer.html /// [Rust Book]: -/// https://doc.rust-lang.org/stable/book/2018-edition/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants -/// [Reference]: https://doc.rust-lang.org/reference/items/constant-items.html +/// ../book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants +/// [Reference]: ../reference/items/constant-items.html mod const_keyword { } #[doc(keyword = "crate")] @@ -114,7 +113,7 @@ mod const_keyword { } /// } /// ``` /// -/// [Reference]: https://doc.rust-lang.org/reference/items/extern-crates.html +/// [Reference]: ../reference/items/extern-crates.html mod crate_keyword { } #[doc(keyword = "enum")] @@ -169,8 +168,8 @@ mod crate_keyword { } /// /// [Algebraic Data Types]: https://en.wikipedia.org/wiki/Algebraic_data_type /// [`Option`]: option/enum.Option.html -/// [Rust Book]: https://doc.rust-lang.org/book/ch06-01-defining-an-enum.html -/// [Reference]: https://doc.rust-lang.org/reference/items/enumerations.html +/// [Rust Book]: ../book/ch06-01-defining-an-enum.html +/// [Reference]: ../reference/items/enumerations.html mod enum_keyword { } #[doc(keyword = "extern")] @@ -211,8 +210,8 @@ mod enum_keyword { } /// For more information on FFI, check the [Rust book] or the [Reference]. /// /// [Rust book]: -/// https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code -/// [Reference]: https://doc.rust-lang.org/reference/items/external-blocks.html +/// ../book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code +/// [Reference]: ../reference/items/external-blocks.html mod extern_keyword { } #[doc(keyword = "fn")] @@ -278,8 +277,8 @@ mod extern_keyword { } /// /// [`impl`]: keyword.impl.html /// [`extern`]: keyword.extern.html -/// [Rust book]: https://doc.rust-lang.org/book/ch03-03-how-functions-work.html -/// [Reference]: https://doc.rust-lang.org/reference/items/functions.html +/// [Rust book]: ../book/ch03-03-how-functions-work.html +/// [Reference]: ../reference/items/functions.html mod fn_keyword { } #[doc(keyword = "for")] @@ -352,12 +351,11 @@ 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 +/// [higher-ranked trait bounds]: ../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 -/// [Reference]: https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops +/// ../book/ch03-05-control-flow.html#looping-through-a-collection-with-for +/// [Reference]: ../reference/expressions/loop-expr.html#iterator-loops mod for_keyword { } #[doc(keyword = "if")] @@ -430,9 +428,8 @@ mod for_keyword { } /// /// For more information on `if` expressions, see the [Rust book] or the [Reference]. /// -/// [Rust book]: -/// https://doc.rust-lang.org/stable/book/2018-edition/ch03-05-control-flow.html#if-expressions -/// [Reference]: https://doc.rust-lang.org/reference/expressions/if-expr.html +/// [Rust book]: ../book/ch03-05-control-flow.html#if-expressions +/// [Reference]: ../reference/expressions/if-expr.html mod if_keyword { } #[doc(keyword = "impl")] @@ -493,10 +490,9 @@ mod if_keyword { } /// /// For more information on `impl Trait` syntax, see the [Rust book][book2]. /// -/// [book1]: https://doc.rust-lang.org/stable/book/2018-edition/ch05-03-method-syntax.html -/// [Reference]: https://doc.rust-lang.org/reference/items/implementations.html -/// [book2]: -/// https://doc.rust-lang.org/stable/book/2018-edition/ch10-02-traits.html#returning-traits +/// [book1]: ../book/ch05-03-method-syntax.html +/// [Reference]: ../reference/items/implementations.html +/// [book2]: ../book/ch10-02-traits.html#returning-types-that-implement-traits mod impl_keyword { } #[doc(keyword = "let")] @@ -554,13 +550,12 @@ mod impl_keyword { } /// enumerations. `while let` also exists, which runs a loop with a pattern matched value until /// that pattern can't be matched. /// -/// For more information on the `let` keyword, see the [Rust book] or the [Reference] +/// For more information on the `let` keyword, see the [Rust book][book2] or the [Reference] /// -/// [book1]: https://doc.rust-lang.org/stable/book/2018-edition/ch06-02-match.html +/// [book1]: ../book/ch06-02-match.html /// [`if`]: keyword.if.html -/// [book2]: -/// https://doc.rust-lang.org/stable/book/2018-edition/ch18-01-all-the-places-for-patterns.html#let-statements -/// [Reference]: https://doc.rust-lang.org/reference/statements.html#let-statements +/// [book2]: ../book/ch18-01-all-the-places-for-patterns.html#let-statements +/// [Reference]: ../reference/statements.html#let-statements mod let_keyword { } #[doc(keyword = "loop")] @@ -605,7 +600,7 @@ mod let_keyword { } /// /// For more information on `loop` and loops in general, see the [Reference]. /// -/// [Reference]: https://doc.rust-lang.org/reference/expressions/loop-expr.html +/// [Reference]: ../reference/expressions/loop-expr.html mod loop_keyword { } #[doc(keyword = "struct")] @@ -712,6 +707,6 @@ mod loop_keyword { } /// [Reference][reference]. /// /// [`PhantomData`]: marker/struct.PhantomData.html -/// [book]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html -/// [reference]: https://doc.rust-lang.org/reference/items/structs.html +/// [book]: ../book/ch05-01-defining-structs.html +/// [reference]: ../reference/items/structs.html mod struct_keyword { } From 6635fbed4ca8c65822f99e994735bd1877fb063e Mon Sep 17 00:00:00 2001 From: CrLF0710 Date: Wed, 10 Apr 2019 00:46:28 +0800 Subject: [PATCH 24/53] Eliminate `FnBox` usages from libstd. --- src/libstd/sys/cloudabi/thread.rs | 3 +-- src/libstd/sys/redox/thread.rs | 3 +-- src/libstd/sys/sgx/thread.rs | 8 +++----- src/libstd/sys/unix/thread.rs | 3 +-- src/libstd/sys/wasi/thread.rs | 3 +-- src/libstd/sys/wasm/thread.rs | 3 +-- src/libstd/sys/windows/thread.rs | 3 +-- src/libstd/sys_common/at_exit_imp.rs | 5 ++--- src/libstd/sys_common/thread.rs | 3 +-- src/libstd/thread/mod.rs | 5 +++-- 10 files changed, 15 insertions(+), 24 deletions(-) diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index f853346e0e63c..7da16c4d247aa 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -1,4 +1,3 @@ -use crate::boxed::FnBox; use crate::cmp; use crate::ffi::CStr; use crate::io; @@ -22,7 +21,7 @@ unsafe impl Sync for Thread {} impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(stack: usize, p: Box) -> io::Result { + pub unsafe fn new(stack: usize, p: Box) -> io::Result { let p = box p; let mut native: libc::pthread_t = mem::zeroed(); let mut attr: libc::pthread_attr_t = mem::zeroed(); diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index ae0b91b4d6c7d..9d40a7e8bb8b3 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -1,4 +1,3 @@ -use crate::boxed::FnBox; use crate::ffi::CStr; use crate::io; use crate::mem; @@ -19,7 +18,7 @@ unsafe impl Sync for Thread {} impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(_stack: usize, p: Box) -> io::Result { + pub unsafe fn new(_stack: usize, p: Box) -> io::Result { let p = box p; let id = cvt(syscall::clone(syscall::CLONE_VM | syscall::CLONE_FS | syscall::CLONE_FILES))?; diff --git a/src/libstd/sys/sgx/thread.rs b/src/libstd/sys/sgx/thread.rs index 565a523ebe06f..b9f42d4ad1c59 100644 --- a/src/libstd/sys/sgx/thread.rs +++ b/src/libstd/sys/sgx/thread.rs @@ -1,5 +1,4 @@ #![cfg_attr(test, allow(dead_code))] // why is this necessary? -use crate::boxed::FnBox; use crate::ffi::CStr; use crate::io; use crate::time::Duration; @@ -13,17 +12,16 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; mod task_queue { use crate::sync::{Mutex, MutexGuard, Once}; use crate::sync::mpsc; - use crate::boxed::FnBox; pub type JoinHandle = mpsc::Receiver<()>; pub(super) struct Task { - p: Box, + p: Box, done: mpsc::Sender<()>, } impl Task { - pub(super) fn new(p: Box) -> (Task, JoinHandle) { + pub(super) fn new(p: Box) -> (Task, JoinHandle) { let (done, recv) = mpsc::channel(); (Task { p, done }, recv) } @@ -51,7 +49,7 @@ mod task_queue { impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(_stack: usize, p: Box) + pub unsafe fn new(_stack: usize, p: Box) -> io::Result { let mut queue_lock = task_queue::lock(); diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index feb15e8f585ab..f7d604ac4c8c1 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -1,4 +1,3 @@ -use crate::boxed::FnBox; use crate::cmp; use crate::ffi::CStr; use crate::io; @@ -39,7 +38,7 @@ unsafe fn pthread_attr_setstacksize(_attr: *mut libc::pthread_attr_t, impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(stack: usize, p: Box) + pub unsafe fn new(stack: usize, p: Box) -> io::Result { let p = box p; let mut native: libc::pthread_t = mem::zeroed(); diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index 9d3c6ac59d186..5e69e4d948fee 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -1,4 +1,3 @@ -use crate::boxed::FnBox; use crate::cmp; use crate::ffi::CStr; use crate::io; @@ -13,7 +12,7 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(_stack: usize, _p: Box) + pub unsafe fn new(_stack: usize, _p: Box) -> io::Result { unsupported() diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs index a65c413119f8c..1dc786cd5d7b6 100644 --- a/src/libstd/sys/wasm/thread.rs +++ b/src/libstd/sys/wasm/thread.rs @@ -1,4 +1,3 @@ -use crate::boxed::FnBox; use crate::ffi::CStr; use crate::io; use crate::sys::{unsupported, Void}; @@ -10,7 +9,7 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(_stack: usize, _p: Box) + pub unsafe fn new(_stack: usize, _p: Box) -> io::Result { unsupported() diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 1b0a811f13b72..ebdf3612e0602 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -1,4 +1,3 @@ -use crate::boxed::FnBox; use crate::io; use crate::ffi::CStr; use crate::mem; @@ -20,7 +19,7 @@ pub struct Thread { impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(stack: usize, p: Box) + pub unsafe fn new(stack: usize, p: Box) -> io::Result { let p = box p; diff --git a/src/libstd/sys_common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs index 1181b86161199..cdb72ee872e04 100644 --- a/src/libstd/sys_common/at_exit_imp.rs +++ b/src/libstd/sys_common/at_exit_imp.rs @@ -2,12 +2,11 @@ //! //! Documentation can be found on the `rt::at_exit` function. -use crate::boxed::FnBox; use crate::ptr; use crate::mem; use crate::sys_common::mutex::Mutex; -type Queue = Vec>; +type Queue = Vec>; // NB these are specifically not types from `std::sync` as they currently rely // on poisoning and this module needs to operate at a lower level than requiring @@ -61,7 +60,7 @@ pub fn cleanup() { } } -pub fn push(f: Box) -> bool { +pub fn push(f: Box) -> bool { unsafe { let _guard = LOCK.lock(); if init() { diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs index b2142e753085a..6ab0d5cbe9c96 100644 --- a/src/libstd/sys_common/thread.rs +++ b/src/libstd/sys_common/thread.rs @@ -1,4 +1,3 @@ -use crate::boxed::FnBox; use crate::env; use crate::sync::atomic::{self, Ordering}; use crate::sys::stack_overflow; @@ -11,7 +10,7 @@ pub unsafe fn start_thread(main: *mut u8) { let _handler = stack_overflow::Handler::new(); // Finally, let's run some code. - Box::from_raw(main as *mut Box)() + Box::from_raw(main as *mut Box)() } pub fn min_stack() -> usize { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index cb507971091a4..c59226e0c0b98 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -157,7 +157,6 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::any::Any; -use crate::boxed::FnBox; use crate::cell::UnsafeCell; use crate::ffi::{CStr, CString}; use crate::fmt; @@ -488,7 +487,9 @@ impl Builder { // returning. native: Some(imp::Thread::new( stack_size, - mem::transmute::, Box>(Box::new(main)) + mem::transmute::, Box>(Box::new( + main, + )), )?), thread: my_thread, packet: Packet(my_packet), From 2f975529a04766c0a7624672f0a02fc1b7b44118 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 10 Apr 2019 03:21:11 +0000 Subject: [PATCH 25/53] Re-export NonZero signed variant in std --- src/libstd/num.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libstd/num.rs b/src/libstd/num.rs index 828d5720eec1e..d67d0b55a799d 100644 --- a/src/libstd/num.rs +++ b/src/libstd/num.rs @@ -13,6 +13,8 @@ pub use core::num::Wrapping; #[stable(feature = "nonzero", since = "1.28.0")] pub use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize}; +#[stable(feature = "signed_nonzero", since = "1.34.0")] +pub use core::num::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize}; #[cfg(test)] use crate::fmt; #[cfg(test)] use crate::ops::{Add, Sub, Mul, Div, Rem}; From 404df312d304c4abeb583d55223ac6c2f1a768ae Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 10 Apr 2019 06:33:43 +0000 Subject: [PATCH 26/53] Update ui test --- src/test/ui/try-block/try-block-bad-type.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr index 6687bd9d9e1ff..07e7149793c14 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -6,9 +6,9 @@ LL | Err("")?; | = help: the following implementations were found: > - > > > + > and 2 others = note: required by `std::convert::From::from` From f10394ae0c5f2f73d1eba688c2cf5832eb38bc96 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 10 Apr 2019 11:21:19 +0200 Subject: [PATCH 27/53] Documentation should have proper grammar --- src/librustc_mir/transform/qualify_consts.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 5f8e7ad796ba3..3154f8e89e394 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -509,10 +509,13 @@ impl Qualif for IsNotPromotable { } /// Refers to temporaries which cannot be promoted *implicitly*. -/// Explicit promotion e.g. for constant arguments declared via `rustc_args_required_const` or by -/// happening inside a constant, static or const fn. Inside a const context all constness rules +/// Explicit promotion happens e.g. for constant arguments declared via `rustc_args_required_const`. +/// Inside a const context all constness rules /// apply, so implicit promotion simply has to follow the regular constant rules (modulo interior -/// mutability or `Drop` rules which are handled `HasMutInterior` and `NeedsDrop` respectively) +/// mutability or `Drop` rules which are handled `HasMutInterior` and `NeedsDrop` respectively). +/// Implicit promotion inside regular functions does not happen if `const fn` calls are involved, +/// as the call may be perfectly alright at runtime, but fail at compile time e.g. due to addresses +/// being compared inside the function. struct IsNotImplicitlyPromotable; impl Qualif for IsNotImplicitlyPromotable { From acf3ddb5ad163ea98f8935b045fc6d15faefa454 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 10 Apr 2019 12:51:25 -0700 Subject: [PATCH 28/53] std: Add `{read,write}_vectored` for more types This commit implements the `{read,write}_vectored` methods on more types in the standard library, namely: * `std::fs::File` * `std::process::ChildStd{in,out,err}` * `std::io::Std{in,out,err}` * `std::io::Std{in,out,err}Lock` * `std::io::Std{in,out,err}Raw` Where supported the OS implementations hook up to native support, otherwise it falls back to the already-defaulted implementation. --- src/libstd/fs.rs | 20 ++++++++++- src/libstd/io/stdio.rs | 51 ++++++++++++++++++++++++++- src/libstd/process.rs | 16 ++++++++- src/libstd/sys/cloudabi/shims/fs.rs | 10 +++++- src/libstd/sys/cloudabi/shims/pipe.rs | 10 +++++- src/libstd/sys/redox/fs.rs | 10 +++++- src/libstd/sys/redox/pipe.rs | 10 +++++- src/libstd/sys/sgx/fs.rs | 10 +++++- src/libstd/sys/sgx/pipe.rs | 15 +++++--- src/libstd/sys/unix/fs.rs | 10 +++++- src/libstd/sys/unix/pipe.rs | 10 +++++- src/libstd/sys/unix/stdio.rs | 30 +++++++++------- src/libstd/sys/wasi/pipe.rs | 10 +++++- src/libstd/sys/wasi/stdio.rs | 18 ++++++++-- src/libstd/sys/wasm/fs.rs | 10 +++++- src/libstd/sys/wasm/pipe.rs | 10 +++++- src/libstd/sys/windows/fs.rs | 10 +++++- src/libstd/sys/windows/handle.rs | 14 +++++++- src/libstd/sys/windows/pipe.rs | 10 +++++- 19 files changed, 247 insertions(+), 37 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 14ff4d72f8795..dea198d8c9178 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -9,7 +9,7 @@ use crate::fmt; use crate::ffi::OsString; -use crate::io::{self, SeekFrom, Seek, Read, Initializer, Write}; +use crate::io::{self, SeekFrom, Seek, Read, Initializer, Write, IoVec, IoVecMut}; use crate::path::{Path, PathBuf}; use crate::sys::fs as fs_imp; use crate::sys_common::{AsInnerMut, FromInner, AsInner, IntoInner}; @@ -615,6 +615,10 @@ impl Read for File { self.inner.read(buf) } + fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + self.inner.read_vectored(bufs) + } + #[inline] unsafe fn initializer(&self) -> Initializer { Initializer::nop() @@ -625,6 +629,11 @@ impl Write for File { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } + + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result { + self.inner.write_vectored(bufs) + } + fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } #[stable(feature = "rust1", since = "1.0.0")] @@ -639,6 +648,10 @@ impl Read for &File { self.inner.read(buf) } + fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + self.inner.read_vectored(bufs) + } + #[inline] unsafe fn initializer(&self) -> Initializer { Initializer::nop() @@ -649,6 +662,11 @@ impl Write for &File { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } + + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result { + self.inner.write_vectored(bufs) + } + fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 0bbff5769ab82..1848ddeab6556 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -5,7 +5,7 @@ use crate::io::prelude::*; use crate::cell::RefCell; use crate::fmt; use crate::io::lazy::Lazy; -use crate::io::{self, Initializer, BufReader, LineWriter}; +use crate::io::{self, Initializer, BufReader, LineWriter, IoVec, IoVecMut}; use crate::sync::{Arc, Mutex, MutexGuard}; use crate::sys::stdio; use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; @@ -75,6 +75,10 @@ fn stderr_raw() -> io::Result { stdio::Stderr::new().map(StderrRaw) } impl Read for StdinRaw { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } + fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + self.0.read_vectored(bufs) + } + #[inline] unsafe fn initializer(&self) -> Initializer { Initializer::nop() @@ -82,10 +86,20 @@ impl Read for StdinRaw { } impl Write for StdoutRaw { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } + + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result { + self.0.write_vectored(bufs) + } + fn flush(&mut self) -> io::Result<()> { self.0.flush() } } impl Write for StderrRaw { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } + + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result { + self.0.write_vectored(bufs) + } + fn flush(&mut self) -> io::Result<()> { self.0.flush() } } @@ -102,6 +116,14 @@ impl io::Write for Maybe { } } + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result { + let total = bufs.iter().map(|b| b.len()).sum(); + match self { + Maybe::Real(w) => handle_ebadf(w.write_vectored(bufs), total), + Maybe::Fake => Ok(total), + } + } + fn flush(&mut self) -> io::Result<()> { match *self { Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()), @@ -117,6 +139,13 @@ impl io::Read for Maybe { Maybe::Fake => Ok(0) } } + + fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + match self { + Maybe::Real(r) => handle_ebadf(r.read_vectored(bufs), 0), + Maybe::Fake => Ok(0) + } + } } fn handle_ebadf(r: io::Result, default: T) -> io::Result { @@ -305,6 +334,9 @@ impl Read for Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.lock().read(buf) } + fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + self.lock().read_vectored(bufs) + } #[inline] unsafe fn initializer(&self) -> Initializer { Initializer::nop() @@ -325,6 +357,11 @@ impl Read for StdinLock<'_> { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } + + fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + self.inner.read_vectored(bufs) + } + #[inline] unsafe fn initializer(&self) -> Initializer { Initializer::nop() @@ -483,6 +520,9 @@ impl Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { self.lock().write(buf) } + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result { + self.lock().write_vectored(bufs) + } fn flush(&mut self) -> io::Result<()> { self.lock().flush() } @@ -498,6 +538,9 @@ impl Write for StdoutLock<'_> { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.borrow_mut().write(buf) } + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result { + self.inner.borrow_mut().write_vectored(bufs) + } fn flush(&mut self) -> io::Result<()> { self.inner.borrow_mut().flush() } @@ -636,6 +679,9 @@ impl Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result { self.lock().write(buf) } + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result { + self.lock().write_vectored(bufs) + } fn flush(&mut self) -> io::Result<()> { self.lock().flush() } @@ -651,6 +697,9 @@ impl Write for StderrLock<'_> { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.borrow_mut().write(buf) } + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result { + self.inner.borrow_mut().write_vectored(bufs) + } fn flush(&mut self) -> io::Result<()> { self.inner.borrow_mut().flush() } diff --git a/src/libstd/process.rs b/src/libstd/process.rs index e0c9b7cad86ca..ef5626700e87a 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -111,7 +111,7 @@ use crate::io::prelude::*; use crate::ffi::OsStr; use crate::fmt; use crate::fs; -use crate::io::{self, Initializer}; +use crate::io::{self, Initializer, IoVec, IoVecMut}; use crate::path::Path; use crate::str; use crate::sys::pipe::{read2, AnonPipe}; @@ -225,6 +225,10 @@ impl Write for ChildStdin { self.inner.write(buf) } + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result { + self.inner.write_vectored(bufs) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } @@ -271,6 +275,11 @@ impl Read for ChildStdout { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } + + fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + self.inner.read_vectored(bufs) + } + #[inline] unsafe fn initializer(&self) -> Initializer { Initializer::nop() @@ -318,6 +327,11 @@ impl Read for ChildStderr { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } + + fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + self.inner.read_vectored(bufs) + } + #[inline] unsafe fn initializer(&self) -> Initializer { Initializer::nop() diff --git a/src/libstd/sys/cloudabi/shims/fs.rs b/src/libstd/sys/cloudabi/shims/fs.rs index ee045b8e51544..abd7f0fd3ee57 100644 --- a/src/libstd/sys/cloudabi/shims/fs.rs +++ b/src/libstd/sys/cloudabi/shims/fs.rs @@ -1,7 +1,7 @@ use crate::ffi::OsString; use crate::fmt; use crate::hash::{Hash, Hasher}; -use crate::io::{self, SeekFrom}; +use crate::io::{self, SeekFrom, IoVec, IoVecMut}; use crate::path::{Path, PathBuf}; use crate::sys::time::SystemTime; use crate::sys::{unsupported, Void}; @@ -198,10 +198,18 @@ impl File { match self.0 {} } + pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result { + match self.0 {} + } + pub fn write(&self, _buf: &[u8]) -> io::Result { match self.0 {} } + pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result { + match self.0 {} + } + pub fn flush(&self) -> io::Result<()> { match self.0 {} } diff --git a/src/libstd/sys/cloudabi/shims/pipe.rs b/src/libstd/sys/cloudabi/shims/pipe.rs index f3debb9504742..804d3e001ac15 100644 --- a/src/libstd/sys/cloudabi/shims/pipe.rs +++ b/src/libstd/sys/cloudabi/shims/pipe.rs @@ -1,4 +1,4 @@ -use crate::io; +use crate::io::{self, IoVec, IoVecMut}; use crate::sys::Void; pub struct AnonPipe(Void); @@ -8,10 +8,18 @@ impl AnonPipe { match self.0 {} } + pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result { + match self.0 {} + } + pub fn write(&self, _buf: &[u8]) -> io::Result { match self.0 {} } + pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result { + match self.0 {} + } + pub fn diverge(&self) -> ! { match self.0 {} } diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index ebefbc942103c..c86c6000eaead 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -2,7 +2,7 @@ use crate::os::unix::prelude::*; use crate::ffi::{OsString, OsStr}; use crate::fmt; -use crate::io::{self, Error, SeekFrom}; +use crate::io::{self, Error, SeekFrom, IoVec, IoVecMut}; use crate::path::{Path, PathBuf}; use crate::sync::Arc; use crate::sys::fd::FileDesc; @@ -278,10 +278,18 @@ impl File { self.0.read(buf) } + pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + crate::io::default_read_vectored(|buf| self.read(buf), bufs) + } + pub fn write(&self, buf: &[u8]) -> io::Result { self.0.write(buf) } + pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result { + crate::io::default_write_vectored(|buf| self.write(buf), bufs) + } + pub fn flush(&self) -> io::Result<()> { Ok(()) } pub fn seek(&self, pos: SeekFrom) -> io::Result { diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs index 911ba9c3f6524..b926968f7b325 100644 --- a/src/libstd/sys/redox/pipe.rs +++ b/src/libstd/sys/redox/pipe.rs @@ -1,4 +1,4 @@ -use crate::io; +use crate::io::{self, IoVec, IoVecMut}; use crate::sys::{cvt, syscall}; use crate::sys::fd::FileDesc; @@ -24,10 +24,18 @@ impl AnonPipe { self.0.read(buf) } + pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + crate::io::default_read_vectored(|buf| self.read(buf), bufs) + } + pub fn write(&self, buf: &[u8]) -> io::Result { self.0.write(buf) } + pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result { + crate::io::default_write_vectored(|buf| self.write(buf), bufs) + } + pub fn fd(&self) -> &FileDesc { &self.0 } pub fn into_fd(self) -> FileDesc { self.0 } } diff --git a/src/libstd/sys/sgx/fs.rs b/src/libstd/sys/sgx/fs.rs index 68c8e9356a89a..c3c898eb23e56 100644 --- a/src/libstd/sys/sgx/fs.rs +++ b/src/libstd/sys/sgx/fs.rs @@ -1,7 +1,7 @@ use crate::ffi::OsString; use crate::fmt; use crate::hash::{Hash, Hasher}; -use crate::io::{self, SeekFrom}; +use crate::io::{self, SeekFrom, IoVec, IoVecMut}; use crate::path::{Path, PathBuf}; use crate::sys::time::SystemTime; use crate::sys::{unsupported, Void}; @@ -200,10 +200,18 @@ impl File { match self.0 {} } + pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result { + match self.0 {} + } + pub fn write(&self, _buf: &[u8]) -> io::Result { match self.0 {} } + pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result { + match self.0 {} + } + pub fn flush(&self) -> io::Result<()> { match self.0 {} } diff --git a/src/libstd/sys/sgx/pipe.rs b/src/libstd/sys/sgx/pipe.rs index 2582b993b608e..804d3e001ac15 100644 --- a/src/libstd/sys/sgx/pipe.rs +++ b/src/libstd/sys/sgx/pipe.rs @@ -1,4 +1,4 @@ -use crate::io; +use crate::io::{self, IoVec, IoVecMut}; use crate::sys::Void; pub struct AnonPipe(Void); @@ -8,18 +8,23 @@ impl AnonPipe { match self.0 {} } + pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result { + match self.0 {} + } + pub fn write(&self, _buf: &[u8]) -> io::Result { match self.0 {} } + pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result { + match self.0 {} + } + pub fn diverge(&self) -> ! { match self.0 {} } } -pub fn read2(p1: AnonPipe, - _v1: &mut Vec, - _p2: AnonPipe, - _v2: &mut Vec) -> io::Result<()> { +pub fn read2(p1: AnonPipe, _v1: &mut Vec, _p2: AnonPipe, _v2: &mut Vec) -> io::Result<()> { match p1.0 {} } diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index dc3dcb5817c05..a14db108c3423 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -2,7 +2,7 @@ use crate::os::unix::prelude::*; use crate::ffi::{CString, CStr, OsString, OsStr}; use crate::fmt; -use crate::io::{self, Error, ErrorKind, SeekFrom}; +use crate::io::{self, Error, ErrorKind, SeekFrom, IoVec, IoVecMut}; use crate::mem; use crate::path::{Path, PathBuf}; use crate::ptr; @@ -560,6 +560,10 @@ impl File { self.0.read(buf) } + pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + self.0.read_vectored(bufs) + } + pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { self.0.read_at(buf, offset) } @@ -568,6 +572,10 @@ impl File { self.0.write(buf) } + pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result { + self.0.write_vectored(bufs) + } + pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { self.0.write_at(buf, offset) } diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index bc3c026adab8f..a7792d42af9ed 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -1,4 +1,4 @@ -use crate::io; +use crate::io::{self, IoVec, IoVecMut}; use crate::mem; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::fd::FileDesc; @@ -60,10 +60,18 @@ impl AnonPipe { self.0.read(buf) } + pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + self.0.read_vectored(bufs) + } + pub fn write(&self, buf: &[u8]) -> io::Result { self.0.write(buf) } + pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result { + self.0.write_vectored(bufs) + } + pub fn fd(&self) -> &FileDesc { &self.0 } pub fn into_fd(self) -> FileDesc { self.0 } } diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs index 35f163bbdb10f..bc2986f624e5c 100644 --- a/src/libstd/sys/unix/stdio.rs +++ b/src/libstd/sys/unix/stdio.rs @@ -1,5 +1,6 @@ -use crate::io; +use crate::io::{self, IoVec, IoVecMut}; use crate::sys::fd::FileDesc; +use crate::mem::ManuallyDrop; pub struct Stdin(()); pub struct Stdout(()); @@ -11,10 +12,11 @@ impl Stdin { impl io::Read for Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result { - let fd = FileDesc::new(libc::STDIN_FILENO); - let ret = fd.read(buf); - fd.into_raw(); // do not close this FD - ret + ManuallyDrop::new(FileDesc::new(libc::STDIN_FILENO)).read(buf) + } + + fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + ManuallyDrop::new(FileDesc::new(libc::STDIN_FILENO)).read_vectored(bufs) } } @@ -24,10 +26,11 @@ impl Stdout { impl io::Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { - let fd = FileDesc::new(libc::STDOUT_FILENO); - let ret = fd.write(buf); - fd.into_raw(); // do not close this FD - ret + ManuallyDrop::new(FileDesc::new(libc::STDOUT_FILENO)).write(buf) + } + + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result { + ManuallyDrop::new(FileDesc::new(libc::STDOUT_FILENO)).write_vectored(bufs) } fn flush(&mut self) -> io::Result<()> { @@ -41,10 +44,11 @@ impl Stderr { impl io::Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result { - let fd = FileDesc::new(libc::STDERR_FILENO); - let ret = fd.write(buf); - fd.into_raw(); // do not close this FD - ret + ManuallyDrop::new(FileDesc::new(libc::STDERR_FILENO)).write(buf) + } + + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result { + ManuallyDrop::new(FileDesc::new(libc::STDERR_FILENO)).write_vectored(bufs) } fn flush(&mut self) -> io::Result<()> { diff --git a/src/libstd/sys/wasi/pipe.rs b/src/libstd/sys/wasi/pipe.rs index 2582b993b608e..aa6bf8076f649 100644 --- a/src/libstd/sys/wasi/pipe.rs +++ b/src/libstd/sys/wasi/pipe.rs @@ -1,4 +1,4 @@ -use crate::io; +use crate::io::{self, IoVec, IoVecMut}; use crate::sys::Void; pub struct AnonPipe(Void); @@ -8,10 +8,18 @@ impl AnonPipe { match self.0 {} } + pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result { + match self.0 {} + } + pub fn write(&self, _buf: &[u8]) -> io::Result { match self.0 {} } + pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result { + match self.0 {} + } + pub fn diverge(&self) -> ! { match self.0 {} } diff --git a/src/libstd/sys/wasi/stdio.rs b/src/libstd/sys/wasi/stdio.rs index 192947886668f..bdad40848916e 100644 --- a/src/libstd/sys/wasi/stdio.rs +++ b/src/libstd/sys/wasi/stdio.rs @@ -13,8 +13,12 @@ impl Stdin { } pub fn read(&self, data: &mut [u8]) -> io::Result { + self.read_vectored(&mut [IoVecMut::new(data)]) + } + + pub fn read_vectored(&self, data: &mut [IoVecMut<'_>]) -> io::Result { ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDIN_FILENO as u32) }) - .read(&mut [IoVecMut::new(data)]) + .read(data) } } @@ -24,8 +28,12 @@ impl Stdout { } pub fn write(&self, data: &[u8]) -> io::Result { + self.write_vectored(&[IoVec::new(data)]) + } + + pub fn write_vectored(&self, data: &[IoVec<'_>]) -> io::Result { ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDOUT_FILENO as u32) }) - .write(&[IoVec::new(data)]) + .write(data) } pub fn flush(&self) -> io::Result<()> { @@ -39,8 +47,12 @@ impl Stderr { } pub fn write(&self, data: &[u8]) -> io::Result { + self.write_vectored(&[IoVec::new(data)]) + } + + pub fn write_vectored(&self, data: &[IoVec<'_>]) -> io::Result { ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDERR_FILENO as u32) }) - .write(&[IoVec::new(data)]) + .write(data) } pub fn flush(&self) -> io::Result<()> { diff --git a/src/libstd/sys/wasm/fs.rs b/src/libstd/sys/wasm/fs.rs index 68c8e9356a89a..c3c898eb23e56 100644 --- a/src/libstd/sys/wasm/fs.rs +++ b/src/libstd/sys/wasm/fs.rs @@ -1,7 +1,7 @@ use crate::ffi::OsString; use crate::fmt; use crate::hash::{Hash, Hasher}; -use crate::io::{self, SeekFrom}; +use crate::io::{self, SeekFrom, IoVec, IoVecMut}; use crate::path::{Path, PathBuf}; use crate::sys::time::SystemTime; use crate::sys::{unsupported, Void}; @@ -200,10 +200,18 @@ impl File { match self.0 {} } + pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result { + match self.0 {} + } + pub fn write(&self, _buf: &[u8]) -> io::Result { match self.0 {} } + pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result { + match self.0 {} + } + pub fn flush(&self) -> io::Result<()> { match self.0 {} } diff --git a/src/libstd/sys/wasm/pipe.rs b/src/libstd/sys/wasm/pipe.rs index 2582b993b608e..aa6bf8076f649 100644 --- a/src/libstd/sys/wasm/pipe.rs +++ b/src/libstd/sys/wasm/pipe.rs @@ -1,4 +1,4 @@ -use crate::io; +use crate::io::{self, IoVec, IoVecMut}; use crate::sys::Void; pub struct AnonPipe(Void); @@ -8,10 +8,18 @@ impl AnonPipe { match self.0 {} } + pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result { + match self.0 {} + } + pub fn write(&self, _buf: &[u8]) -> io::Result { match self.0 {} } + pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result { + match self.0 {} + } + pub fn diverge(&self) -> ! { match self.0 {} } diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 4ebbb0707f78a..1d8e47a4793ef 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -2,7 +2,7 @@ use crate::os::windows::prelude::*; use crate::ffi::OsString; use crate::fmt; -use crate::io::{self, Error, SeekFrom}; +use crate::io::{self, Error, SeekFrom, IoVec, IoVecMut}; use crate::mem; use crate::path::{Path, PathBuf}; use crate::ptr; @@ -314,6 +314,10 @@ impl File { self.handle.read(buf) } + pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + self.handle.read_vectored(bufs) + } + pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { self.handle.read_at(buf, offset) } @@ -322,6 +326,10 @@ impl File { self.handle.write(buf) } + pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result { + self.handle.write_vectored(bufs) + } + pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { self.handle.write_at(buf, offset) } diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index 02549088c8704..c3fa6c4e0bd51 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -1,7 +1,7 @@ #![unstable(issue = "0", feature = "windows_handle")] use crate::cmp; -use crate::io::{self, ErrorKind, Read}; +use crate::io::{self, ErrorKind, Read, IoVec, IoVecMut}; use crate::mem; use crate::ops::Deref; use crate::ptr; @@ -89,6 +89,10 @@ impl RawHandle { } } + pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + crate::io::default_read_vectored(|buf| self.read(buf), bufs) + } + pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { let mut read = 0; let len = cmp::min(buf.len(), ::max_value() as usize) as c::DWORD; @@ -169,6 +173,10 @@ impl RawHandle { Ok(amt as usize) } + pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result { + crate::io::default_write_vectored(|buf| self.write(buf), bufs) + } + pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { let mut written = 0; let len = cmp::min(buf.len(), ::max_value() as usize) as c::DWORD; @@ -199,4 +207,8 @@ impl<'a> Read for &'a RawHandle { fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } + + fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + (**self).read_vectored(bufs) + } } diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index b38727830f37f..6613d3a056775 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -1,7 +1,7 @@ use crate::os::windows::prelude::*; use crate::ffi::OsStr; -use crate::io; +use crate::io::{self, IoVec, IoVecMut}; use crate::mem; use crate::path::Path; use crate::ptr; @@ -166,9 +166,17 @@ impl AnonPipe { self.inner.read(buf) } + pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result { + self.inner.read_vectored(bufs) + } + pub fn write(&self, buf: &[u8]) -> io::Result { self.inner.write(buf) } + + pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result { + self.inner.write_vectored(bufs) + } } pub fn read2(p1: AnonPipe, From 825a11ea3bb8a4b1a07d4e03a009b2ca4205c6a9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 10 Apr 2019 22:31:42 +0200 Subject: [PATCH 29/53] Fix attributes position in type declaration --- src/librustdoc/html/render.rs | 9 +++------ src/librustdoc/html/static/rustdoc.css | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 866d8fe682a7b..bd134af55897e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3117,7 +3117,6 @@ fn item_trait( // FIXME: we should be using a derived_id for the Anchors here write!(w, "{{\n")?; for t in &types { - write!(w, " ")?; render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?; write!(w, ";\n")?; } @@ -3125,7 +3124,6 @@ fn item_trait( w.write_str("\n")?; } for t in &consts { - write!(w, " ")?; render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?; write!(w, ";\n")?; } @@ -3133,7 +3131,6 @@ fn item_trait( w.write_str("\n")?; } for (pos, m) in required.iter().enumerate() { - write!(w, " ")?; render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?; write!(w, ";\n")?; @@ -3145,7 +3142,6 @@ fn item_trait( w.write_str("\n")?; } for (pos, m) in provided.iter().enumerate() { - write!(w, " ")?; render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?; match m.inner { clean::MethodItem(ref inner) if !inner.generics.where_predicates.is_empty() => { @@ -3454,8 +3450,9 @@ fn render_assoc_item(w: &mut fmt::Formatter<'_>, (0, true) }; render_attributes(w, meth)?; - write!(w, "{}{}{}{}{}{}fn {name}\ + write!(w, "{}{}{}{}{}{}{}fn {name}\ {generics}{decl}{where_clause}", + if parent == ItemType::Trait { " " } else { "" }, VisSpace(&meth.visibility), ConstnessSpace(header.constness), UnsafetySpace(header.unsafety), @@ -3755,7 +3752,7 @@ const ATTRIBUTE_WHITELIST: &'static [&'static str] = &[ "non_exhaustive" ]; -fn render_attributes(w: &mut fmt::Formatter<'_>, it: &clean::Item) -> fmt::Result { +fn render_attributes(w: &mut dyn fmt::Write, it: &clean::Item) -> fmt::Result { let mut attrs = String::new(); for attr in &it.attrs.other_attrs { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 5314255ac322b..2228e58b0d232 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1577,3 +1577,17 @@ div.name.expand::before { left: -15px; top: 2px; } + +/* This part is to fix the "Expand attributes" part in the type declaration. */ +.type-decl > pre > :first-child { + margin-left: 0 !important; +} +.type-decl > pre > :nth-child(2) { + margin-left: 1.8em !important; +} +.type-decl > pre > .toggle-attributes { + margin-left: 2.2em; +} +.type-decl > pre > .docblock.attributes { + margin-left: 4em; +} From c440c0a0fd3c875defe5a832a212f305b355334c Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Tue, 2 Apr 2019 15:54:31 +0200 Subject: [PATCH 30/53] update polonius-engine --- Cargo.lock | 8 ++++---- src/librustc/Cargo.toml | 2 +- src/librustc_mir/Cargo.toml | 2 +- src/librustc_mir/borrow_check/nll/mod.rs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c071a2e11d269..2bf8d81f1aa97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1914,7 +1914,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "polonius-engine" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "datafrog 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2368,7 +2368,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "polonius-engine 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "polonius-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_apfloat 0.0.0", @@ -2868,7 +2868,7 @@ dependencies = [ "graphviz 0.0.0", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "polonius-engine 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "polonius-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_apfloat 0.0.0", "rustc_data_structures 0.0.0", @@ -4190,7 +4190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998" "checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum polonius-engine 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2490c396085801abf88df91758bad806b0890354f0875d624e62ecf0579a8145" +"checksum polonius-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b24942fee141ea45628484a453762bb7e515099c3ec05fbeb76b7bf57b1aeed" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 31e10c19c7a60..f07111ef647da 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -19,7 +19,7 @@ lazy_static = "1.0.0" num_cpus = "1.0" scoped-tls = "1.0" log = { version = "0.4", features = ["release_max_level_info", "std"] } -polonius-engine = "0.6.2" +polonius-engine = "0.7.0" rustc-rayon = "0.1.2" rustc-rayon-core = "0.1.2" rustc_apfloat = { path = "../librustc_apfloat" } diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index c32bafa99205f..5de5f5e757119 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -15,7 +15,7 @@ either = "1.5.0" dot = { path = "../libgraphviz", package = "graphviz" } log = "0.4" log_settings = "0.1.1" -polonius-engine = "0.6.2" +polonius-engine = "0.7.0" rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 2d3800dd1dda8..3e1b93fb4170a 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -173,7 +173,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( if infcx.tcx.sess.opts.debugging_opts.polonius { let algorithm = env::var("POLONIUS_ALGORITHM") - .unwrap_or_else(|_| String::from("DatafrogOpt")); + .unwrap_or_else(|_| String::from("Hybrid")); let algorithm = Algorithm::from_str(&algorithm).unwrap(); debug!("compute_regions: using polonius algorithm {:?}", algorithm); Some(Rc::new(Output::compute( From d7f5c50a335204e00565c978f5eb7fac40468f96 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 28 Mar 2019 12:36:13 -0500 Subject: [PATCH 31/53] make duplicate matcher bindings a hard error --- src/librustc/lint/builtin.rs | 6 -- src/librustc/lint/mod.rs | 3 +- src/librustc_lint/lib.rs | 7 +-- src/libsyntax/early_buffered_lints.rs | 2 - src/libsyntax/ext/tt/macro_rules.rs | 16 ++---- .../macros/macro-multiple-matcher-bindings.rs | 12 ++-- .../macro-multiple-matcher-bindings.stderr | 57 +++++++++++-------- 7 files changed, 44 insertions(+), 59 deletions(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index cbdeda7b90206..bfb0b3e4a6b2d 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -352,12 +352,6 @@ declare_lint! { "outlives requirements can be inferred" } -declare_lint! { - pub DUPLICATE_MATCHER_BINDING_NAME, - Deny, - "duplicate macro matcher binding name" -} - /// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`. pub mod parser { declare_lint! { diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 5ebb915d57f54..112c247d4d663 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -26,7 +26,7 @@ use rustc_data_structures::sync::{self, Lrc}; use crate::hir::def_id::{CrateNum, LOCAL_CRATE}; use crate::hir::intravisit; use crate::hir; -use crate::lint::builtin::{BuiltinLintDiagnostics, DUPLICATE_MATCHER_BINDING_NAME}; +use crate::lint::builtin::BuiltinLintDiagnostics; use crate::lint::builtin::parser::{QUESTION_MARK_MACRO_SEP, ILL_FORMED_ATTRIBUTE_INPUT}; use crate::session::{Session, DiagnosticMessageId}; use crate::ty::TyCtxt; @@ -82,7 +82,6 @@ impl Lint { match lint_id { BufferedEarlyLintId::QuestionMarkMacroSep => QUESTION_MARK_MACRO_SEP, BufferedEarlyLintId::IllFormedAttributeInput => ILL_FORMED_ATTRIBUTE_INPUT, - BufferedEarlyLintId::DuplicateMacroMatcherBindingName => DUPLICATE_MATCHER_BINDING_NAME, } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 07c505c6bde08..4a2d6dc68ae59 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -428,11 +428,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { reference: "issue #57644 ", edition: None, }, - FutureIncompatibleInfo { - id: LintId::of(DUPLICATE_MATCHER_BINDING_NAME), - reference: "issue #57593 ", - edition: None, - }, FutureIncompatibleInfo { id: LintId::of(NESTED_IMPL_TRAIT), reference: "issue #59014 ", @@ -494,6 +489,8 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { "no longer a warning, #[no_mangle] statics always exported"); store.register_removed("bad_repr", "replaced with a generic attribute input check"); + store.register_removed("duplicate_matcher_binding_name", + "converted into hard error, see https://github.com/rust-lang/rust/issues/57742"); } pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) { diff --git a/src/libsyntax/early_buffered_lints.rs b/src/libsyntax/early_buffered_lints.rs index 29cb9cd7f30b5..977e6d4587709 100644 --- a/src/libsyntax/early_buffered_lints.rs +++ b/src/libsyntax/early_buffered_lints.rs @@ -12,8 +12,6 @@ pub enum BufferedEarlyLintId { /// Usage of `?` as a macro separator is deprecated. QuestionMarkMacroSep, IllFormedAttributeInput, - /// Usage of a duplicate macro matcher binding name. - DuplicateMacroMatcherBindingName, } /// Stores buffered lint info which can later be passed to `librustc`. diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 12912044e4e3d..b1b9d25b3d56b 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -497,22 +497,14 @@ fn check_lhs_duplicate_matcher_bindings( node_id: ast::NodeId, ) -> bool { use self::quoted::TokenTree; - use crate::early_buffered_lints::BufferedEarlyLintId; for tt in tts { match *tt { TokenTree::MetaVarDecl(span, name, _kind) => { if let Some(&prev_span) = metavar_names.get(&name) { - // FIXME(mark-i-m): in a few cycles, make this a hard error. - // sess.span_diagnostic - // .struct_span_err(span, "duplicate matcher binding") - // .span_note(prev_span, "previous declaration was here") - // .emit(); - sess.buffer_lint( - BufferedEarlyLintId::DuplicateMacroMatcherBindingName, - crate::source_map::MultiSpan::from(vec![prev_span, span]), - node_id, - "duplicate matcher binding" - ); + sess.span_diagnostic + .struct_span_err(span, "duplicate matcher binding") + .span_note(prev_span, "previous declaration was here") + .emit(); return false; } else { metavar_names.insert(name, span); diff --git a/src/test/ui/macros/macro-multiple-matcher-bindings.rs b/src/test/ui/macros/macro-multiple-matcher-bindings.rs index 23d566780c855..f31af2365ff25 100644 --- a/src/test/ui/macros/macro-multiple-matcher-bindings.rs +++ b/src/test/ui/macros/macro-multiple-matcher-bindings.rs @@ -1,16 +1,12 @@ // Test that duplicate matcher binding names are caught at declaration time, rather than at macro // invocation time. -// -// FIXME(mark-i-m): Update this when it becomes a hard error. - -// compile-pass #![allow(unused_macros)] #![warn(duplicate_matcher_binding_name)] macro_rules! foo1 { - ($a:ident, $a:ident) => {}; //~WARNING duplicate matcher binding - ($a:ident, $a:path) => {}; //~WARNING duplicate matcher binding + ($a:ident, $a:ident) => {}; //~ERROR duplicate matcher binding + ($a:ident, $a:path) => {}; //~ERROR duplicate matcher binding } macro_rules! foo2 { @@ -19,8 +15,8 @@ macro_rules! foo2 { } macro_rules! foo3 { - ($a:ident, $($a:ident),*) => {}; //~WARNING duplicate matcher binding - ($($a:ident)+ # $($($a:path),+);*) => {}; //~WARNING duplicate matcher binding + ($a:ident, $($a:ident),*) => {}; //~ERROR duplicate matcher binding + ($($a:ident)+ # $($($a:path),+);*) => {}; //~ERROR duplicate matcher binding } fn main() {} diff --git a/src/test/ui/macros/macro-multiple-matcher-bindings.stderr b/src/test/ui/macros/macro-multiple-matcher-bindings.stderr index f7970dbd2eb22..65362388d7de1 100644 --- a/src/test/ui/macros/macro-multiple-matcher-bindings.stderr +++ b/src/test/ui/macros/macro-multiple-matcher-bindings.stderr @@ -1,41 +1,50 @@ -warning: duplicate matcher binding - --> $DIR/macro-multiple-matcher-bindings.rs:12:6 +error: duplicate matcher binding + --> $DIR/macro-multiple-matcher-bindings.rs:7:16 | LL | ($a:ident, $a:ident) => {}; - | ^^^^^^^^ ^^^^^^^^ + | ^^^^^^^^ | -note: lint level defined here - --> $DIR/macro-multiple-matcher-bindings.rs:9:9 +note: previous declaration was here + --> $DIR/macro-multiple-matcher-bindings.rs:7:6 | -LL | #![warn(duplicate_matcher_binding_name)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57593 +LL | ($a:ident, $a:ident) => {}; + | ^^^^^^^^ -warning: duplicate matcher binding - --> $DIR/macro-multiple-matcher-bindings.rs:13:6 +error: duplicate matcher binding + --> $DIR/macro-multiple-matcher-bindings.rs:8:16 | LL | ($a:ident, $a:path) => {}; - | ^^^^^^^^ ^^^^^^^ + | ^^^^^^^ + | +note: previous declaration was here + --> $DIR/macro-multiple-matcher-bindings.rs:8:6 | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57593 +LL | ($a:ident, $a:path) => {}; + | ^^^^^^^^ -warning: duplicate matcher binding - --> $DIR/macro-multiple-matcher-bindings.rs:22:6 +error: duplicate matcher binding + --> $DIR/macro-multiple-matcher-bindings.rs:17:18 | LL | ($a:ident, $($a:ident),*) => {}; - | ^^^^^^^^ ^^^^^^^^ + | ^^^^^^^^ + | +note: previous declaration was here + --> $DIR/macro-multiple-matcher-bindings.rs:17:6 | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57593 +LL | ($a:ident, $($a:ident),*) => {}; + | ^^^^^^^^ -warning: duplicate matcher binding - --> $DIR/macro-multiple-matcher-bindings.rs:23:8 +error: duplicate matcher binding + --> $DIR/macro-multiple-matcher-bindings.rs:18:25 | LL | ($($a:ident)+ # $($($a:path),+);*) => {}; - | ^^^^^^^^ ^^^^^^^ + | ^^^^^^^ + | +note: previous declaration was here + --> $DIR/macro-multiple-matcher-bindings.rs:18:8 | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57593 +LL | ($($a:ident)+ # $($($a:path),+);*) => {}; + | ^^^^^^^^ + +error: aborting due to 4 previous errors From 6fd3f5acaf2757ed3f3507a8a918e4071c5809a8 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 10 Apr 2019 21:32:46 -0500 Subject: [PATCH 32/53] forgot one --- src/librustc/lint/builtin.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index bfb0b3e4a6b2d..28a2a1eaf6b49 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -456,7 +456,6 @@ declare_lint_pass! { DEPRECATED_IN_FUTURE, AMBIGUOUS_ASSOCIATED_ITEMS, NESTED_IMPL_TRAIT, - DUPLICATE_MATCHER_BINDING_NAME, MUTABLE_BORROW_RESERVATION_CONFLICT, ] } From 7b1df42accbfdf54148072c7a3d1e80177c388b0 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 10 Apr 2019 13:46:37 +0200 Subject: [PATCH 33/53] Clean up handling of -Zpgo-gen commandline option. --- src/librustc/session/config.rs | 38 ++++++++++++++++--- src/librustc_codegen_llvm/attributes.rs | 2 +- src/librustc_codegen_llvm/back/link.rs | 2 +- src/librustc_codegen_llvm/back/write.rs | 22 ++++++++--- .../back/symbol_export.rs | 2 +- src/librustc_codegen_ssa/back/write.rs | 7 ++-- src/librustc_metadata/creader.rs | 2 +- .../run-make-fulldeps/pgo-gen-lto/Makefile | 6 +-- src/test/run-make-fulldeps/pgo-gen/Makefile | 6 +-- 9 files changed, 60 insertions(+), 27 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 988e4a9ff23a2..7c0eab26b09b6 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -113,6 +113,21 @@ impl LinkerPluginLto { } } +#[derive(Clone, PartialEq, Hash)] +pub enum PgoGenerate { + Enabled(Option), + Disabled, +} + +impl PgoGenerate { + pub fn enabled(&self) -> bool { + match *self { + PgoGenerate::Enabled(_) => true, + PgoGenerate::Disabled => false, + } + } +} + #[derive(Clone, Copy, PartialEq, Hash)] pub enum DebugInfo { None, @@ -826,13 +841,15 @@ macro_rules! options { pub const parse_linker_plugin_lto: Option<&str> = Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \ or the path to the linker plugin"); + pub const parse_pgo_generate: Option<&str> = + Some("an optional path to the profiling data output directory"); pub const parse_merge_functions: Option<&str> = Some("one of: `disabled`, `trampolines`, or `aliases`"); } #[allow(dead_code)] mod $mod_set { - use super::{$struct_name, Passes, Sanitizer, LtoCli, LinkerPluginLto}; + use super::{$struct_name, Passes, Sanitizer, LtoCli, LinkerPluginLto, PgoGenerate}; use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel}; use std::path::PathBuf; use std::str::FromStr; @@ -1087,6 +1104,14 @@ macro_rules! options { true } + fn parse_pgo_generate(slot: &mut PgoGenerate, v: Option<&str>) -> bool { + *slot = match v { + None => PgoGenerate::Enabled(None), + Some(path) => PgoGenerate::Enabled(Some(PathBuf::from(path))), + }; + true + } + fn parse_merge_functions(slot: &mut Option, v: Option<&str>) -> bool { match v.and_then(|s| MergeFunctions::from_str(s).ok()) { Some(mergefunc) => *slot = Some(mergefunc), @@ -1363,7 +1388,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "extra arguments to prepend to the linker invocation (space separated)"), profile: bool = (false, parse_bool, [TRACKED], "insert profiling code"), - pgo_gen: Option = (None, parse_opt_string, [TRACKED], + pgo_gen: PgoGenerate = (PgoGenerate::Disabled, parse_pgo_generate, [TRACKED], "Generate PGO profile data, to a given file, or to the default location if it's empty."), pgo_use: String = (String::new(), parse_string, [TRACKED], "Use PGO profile data from the given profile file."), @@ -1980,7 +2005,7 @@ pub fn build_session_options_and_crate_config( ); } - if debugging_opts.pgo_gen.is_some() && !debugging_opts.pgo_use.is_empty() { + if debugging_opts.pgo_gen.enabled() && !debugging_opts.pgo_use.is_empty() { early_error( error_format, "options `-Z pgo-gen` and `-Z pgo-use` are exclusive", @@ -2490,7 +2515,7 @@ mod dep_tracking { use std::path::PathBuf; use std::collections::hash_map::DefaultHasher; use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes, - Passes, Sanitizer, LtoCli, LinkerPluginLto}; + Passes, Sanitizer, LtoCli, LinkerPluginLto, PgoGenerate}; use syntax::feature_gate::UnstableFeatures; use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel, TargetTriple}; use syntax::edition::Edition; @@ -2558,6 +2583,7 @@ mod dep_tracking { impl_dep_tracking_hash_via_hash!(TargetTriple); impl_dep_tracking_hash_via_hash!(Edition); impl_dep_tracking_hash_via_hash!(LinkerPluginLto); + impl_dep_tracking_hash_via_hash!(PgoGenerate); impl_dep_tracking_hash_for_sortable_vec_of!(String); impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf); @@ -2625,7 +2651,7 @@ mod tests { build_session_options_and_crate_config, to_crate_config }; - use crate::session::config::{LtoCli, LinkerPluginLto}; + use crate::session::config::{LtoCli, LinkerPluginLto, PgoGenerate}; use crate::session::build_session; use crate::session::search_paths::SearchPath; use std::collections::{BTreeMap, BTreeSet}; @@ -3124,7 +3150,7 @@ mod tests { assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); - opts.debugging_opts.pgo_gen = Some(String::from("abc")); + opts.debugging_opts.pgo_gen = PgoGenerate::Enabled(None); assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts = reference.clone(); diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 77fa34e74dd70..b15a64c966b1b 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -104,7 +104,7 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { } // probestack doesn't play nice either with pgo-gen. - if cx.sess().opts.debugging_opts.pgo_gen.is_some() { + if cx.sess().opts.debugging_opts.pgo_gen.enabled() { return; } diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 19419a72b94dd..6a3c2adc85618 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -1014,7 +1014,7 @@ fn link_args(cmd: &mut dyn Linker, cmd.build_static_executable(); } - if sess.opts.debugging_opts.pgo_gen.is_some() { + if sess.opts.debugging_opts.pgo_gen.enabled() { cmd.pgo_gen(); } diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index f0ed201ad5c27..4de65325637ff 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -13,7 +13,7 @@ use crate::LlvmCodegenBackend; use rustc::hir::def_id::LOCAL_CRATE; use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, run_assembler}; use rustc_codegen_ssa::traits::*; -use rustc::session::config::{self, OutputType, Passes, Lto}; +use rustc::session::config::{self, OutputType, Passes, Lto, PgoGenerate}; use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_codegen_ssa::{ModuleCodegen, CompiledModule}; @@ -26,7 +26,7 @@ use errors::{Handler, FatalError}; use std::ffi::{CString, CStr}; use std::fs; use std::io::{self, Write}; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::str; use std::sync::Arc; use std::slice; @@ -708,10 +708,20 @@ pub unsafe fn with_llvm_pmb(llmod: &llvm::Module, .unwrap_or(llvm::CodeGenOptSizeNone); let inline_threshold = config.inline_threshold; - let pgo_gen_path = config.pgo_gen.as_ref().map(|s| { - let s = if s.is_empty() { "default_%m.profraw" } else { s }; - CString::new(s.as_bytes()).unwrap() - }); + let pgo_gen_path = match config.pgo_gen { + PgoGenerate::Enabled(ref opt_dir_path) => { + let path = if let Some(dir_path) = opt_dir_path { + dir_path.join("default_%m.profraw") + } else { + PathBuf::from("default_%m.profraw") + }; + + Some(CString::new(format!("{}", path.display())).unwrap()) + } + PgoGenerate::Disabled => { + None + } + }; let pgo_use_path = if config.pgo_use.is_empty() { None diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index 336f41b784a81..a55f783df43a3 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -209,7 +209,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - if tcx.sess.opts.debugging_opts.pgo_gen.is_some() { + if tcx.sess.opts.debugging_opts.pgo_gen.enabled() { // These are weak symbols that point to the profile version and the // profile name, which need to be treated as exported so LTO doesn't nix // them. diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index fa8c4177eafe2..7fc43f29701ad 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -12,7 +12,8 @@ use rustc_incremental::{copy_cgu_workproducts_to_incr_comp_cache_dir, use rustc::dep_graph::{WorkProduct, WorkProductId, WorkProductFileKind}; use rustc::dep_graph::cgu_reuse_tracker::CguReuseTracker; use rustc::middle::cstore::EncodedMetadata; -use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Sanitizer, Lto}; +use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Lto, + Sanitizer, PgoGenerate}; use rustc::session::Session; use rustc::util::nodemap::FxHashMap; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -56,7 +57,7 @@ pub struct ModuleConfig { /// Some(level) to optimize binary size, or None to not affect program size. pub opt_size: Option, - pub pgo_gen: Option, + pub pgo_gen: PgoGenerate, pub pgo_use: String, // Flags indicating which outputs to produce. @@ -94,7 +95,7 @@ impl ModuleConfig { opt_level: None, opt_size: None, - pgo_gen: None, + pgo_gen: PgoGenerate::Disabled, pgo_use: String::new(), emit_no_opt_bc: false, diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 36d9bf9f50dd5..66daa4518bef6 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -862,7 +862,7 @@ impl<'a> CrateLoader<'a> { fn inject_profiler_runtime(&mut self) { if self.sess.opts.debugging_opts.profile || - self.sess.opts.debugging_opts.pgo_gen.is_some() + self.sess.opts.debugging_opts.pgo_gen.enabled() { info!("loading profiler"); diff --git a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile index e358314c0d09e..7c19961b1e420 100644 --- a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile +++ b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile @@ -1,10 +1,8 @@ -include ../tools.mk -# ignore-windows - all: ifeq ($(PROFILER_SUPPORT),1) - $(RUSTC) -Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs + $(RUSTC) -Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)" test.rs $(call RUN,test) || exit 1 - [ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1) + [ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1) endif diff --git a/src/test/run-make-fulldeps/pgo-gen/Makefile b/src/test/run-make-fulldeps/pgo-gen/Makefile index 1961dff8d783e..0469c4443d85a 100644 --- a/src/test/run-make-fulldeps/pgo-gen/Makefile +++ b/src/test/run-make-fulldeps/pgo-gen/Makefile @@ -1,10 +1,8 @@ -include ../tools.mk -# ignore-windows - all: ifeq ($(PROFILER_SUPPORT),1) - $(RUSTC) -g -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs + $(RUSTC) -g -Z pgo-gen="$(TMPDIR)" test.rs $(call RUN,test) || exit 1 - [ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1) + [ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1) endif From 22f2afe21e5decae46ee76ee22aa10d51daaed4b Mon Sep 17 00:00:00 2001 From: Ed Barnard Date: Thu, 11 Apr 2019 13:47:27 +0100 Subject: [PATCH 34/53] Use SecRandomCopyBytes instead of /dev/urandom on MacOS --- src/libstd/build.rs | 2 +- src/libstd/sys/unix/rand.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 726c27321538d..bb85ac4240286 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -30,7 +30,7 @@ fn main() { println!("cargo:rustc-link-lib=resolv"); } else if target.contains("apple-darwin") { println!("cargo:rustc-link-lib=System"); - + println!("cargo:rustc-link-lib=framework=Security"); // res_init and friends require -lresolv on macOS/iOS. // See #41582 and http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html println!("cargo:rustc-link-lib=resolv"); diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index 122f22b37a26b..7934c7f0c820c 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -12,6 +12,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { } #[cfg(all(unix, + not(target_os = "macos"), not(target_os = "ios"), not(target_os = "openbsd"), not(target_os = "freebsd"), @@ -99,7 +100,7 @@ mod imp { } } -#[cfg(target_os = "ios")] +#[cfg(any(target_os = "macos", target_os = "ios"))] mod imp { use crate::io; use crate::ptr; From e149dc02a44f87d0dacba470db709b822b16db88 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 11 Apr 2019 15:09:43 -0500 Subject: [PATCH 35/53] remove warn --- src/test/ui/macros/macro-multiple-matcher-bindings.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/ui/macros/macro-multiple-matcher-bindings.rs b/src/test/ui/macros/macro-multiple-matcher-bindings.rs index f31af2365ff25..7d39dc0a52f2e 100644 --- a/src/test/ui/macros/macro-multiple-matcher-bindings.rs +++ b/src/test/ui/macros/macro-multiple-matcher-bindings.rs @@ -2,7 +2,6 @@ // invocation time. #![allow(unused_macros)] -#![warn(duplicate_matcher_binding_name)] macro_rules! foo1 { ($a:ident, $a:ident) => {}; //~ERROR duplicate matcher binding From d84907bbccf0430470ba7b8f121bb4f924cdffa4 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 7 Apr 2019 19:56:41 +0200 Subject: [PATCH 36/53] Suggest macro import from crate root. This commit suggests importing a macro from the root of a crate as the intent may have been to import a macro from the definition location that was annotated with `#[macro_export]`. --- src/librustc_resolve/error_reporting.rs | 82 +++++++++++++++++++++---- src/librustc_resolve/lib.rs | 10 +++ src/librustc_resolve/resolve_imports.rs | 55 +++++++++-------- src/test/ui/issue-59764.fixed | 15 +++++ src/test/ui/issue-59764.rs | 1 + src/test/ui/issue-59764.stderr | 12 +++- 6 files changed, 134 insertions(+), 41 deletions(-) create mode 100644 src/test/ui/issue-59764.fixed diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index 461d02e515d38..99aa6e39f7b71 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -5,15 +5,16 @@ use log::debug; use rustc::hir::def::{Def, CtorKind, Namespace::*}; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::session::config::nightly_options; -use syntax::ast::{Expr, ExprKind}; +use syntax::ast::{Expr, ExprKind, Ident}; +use syntax::ext::base::MacroKind; use syntax::symbol::keywords; use syntax_pos::Span; use crate::macros::ParentScope; -use crate::resolve_imports::ImportResolver; +use crate::resolve_imports::{ImportDirective, ImportResolver}; use crate::{import_candidate_to_enum_paths, is_self_type, is_self_value, path_names_to_string}; use crate::{AssocSuggestion, CrateLint, ImportSuggestion, ModuleOrUniformRoot, PathResult, - PathSource, Resolver, Segment}; + PathSource, Resolver, Segment, Suggestion}; impl<'a> Resolver<'a> { /// Handles error reporting for `smart_resolve_path_fragment` function. @@ -428,7 +429,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { span: Span, mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Vec)> { debug!("make_path_suggestion: span={:?} path={:?}", span, path); match (path.get(0), path.get(1)) { @@ -463,13 +464,13 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { span: Span, mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Vec)> { // Replace first ident with `self` and check if that is valid. path[0].ident.name = keywords::SelfLower.name(); let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { - Some((path, None)) + Some((path, Vec::new())) } else { None } @@ -487,7 +488,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { span: Span, mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Vec)> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = keywords::Crate.name(); let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); @@ -495,11 +496,11 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if let PathResult::Module(..) = result { Some(( path, - Some( + vec![ "`use` statements changed in Rust 2018; read more at \ ".to_string() - ), + ], )) } else { None @@ -518,13 +519,13 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { span: Span, mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Vec)> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = keywords::Super.name(); let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { - Some((path, None)) + Some((path, Vec::new())) } else { None } @@ -545,7 +546,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { span: Span, mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Vec)> { if path[1].ident.span.rust_2015() { return None; } @@ -564,10 +565,65 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}", name, path, result); if let PathResult::Module(..) = result { - return Some((path, None)); + return Some((path, Vec::new())); } } None } + + /// Suggests importing a macro from the root of the crate rather than a module within + /// the crate. + /// + /// ``` + /// help: a macro with this name exists at the root of the crate + /// | + /// LL | use issue_59764::makro; + /// | ^^^^^^^^^^^^^^^^^^ + /// | + /// = note: this could be because a macro annotated with `#[macro_export]` will be exported + /// at the root of the crate instead of the module where it is defined + /// ``` + pub(crate) fn check_for_module_export_macro( + &self, + directive: &'b ImportDirective<'b>, + module: ModuleOrUniformRoot<'b>, + ident: Ident, + ) -> Option<(Option, Vec)> { + let mut crate_module = if let ModuleOrUniformRoot::Module(module) = module { + module + } else { + return None; + }; + + while let Some(parent) = crate_module.parent { + crate_module = parent; + } + + if ModuleOrUniformRoot::same_def(ModuleOrUniformRoot::Module(crate_module), module) { + // Don't make a suggestion if the import was already from the root of the + // crate. + return None; + } + + let resolutions = crate_module.resolutions.borrow(); + let resolution = resolutions.get(&(ident, MacroNS))?; + let binding = resolution.borrow().binding()?; + if let Def::Macro(_, MacroKind::Bang) = binding.def() { + let name = crate_module.kind.name().unwrap(); + let suggestion = Some(( + directive.span, + String::from("a macro with this name exists at the root of the crate"), + format!("{}::{}", name, ident), + Applicability::MaybeIncorrect, + )); + let note = vec![ + "this could be because a macro annotated with `#[macro_export]` will be exported \ + at the root of the crate instead of the module where it is defined".to_string(), + ]; + Some((suggestion, note)) + } else { + None + } + } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 5216156c0cab8..0fb1ca4298358 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1091,6 +1091,16 @@ enum ModuleKind { Def(Def, Name), } +impl ModuleKind { + /// Get name of the module. + pub fn name(&self) -> Option { + match self { + ModuleKind::Block(..) => None, + ModuleKind::Def(_, name) => Some(*name), + } + } +} + /// One node in the tree of modules. pub struct ModuleData<'a> { parent: Option>, diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 97b630ba5f298..6a01af5d1153a 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -145,7 +145,7 @@ pub struct NameResolution<'a> { impl<'a> NameResolution<'a> { // Returns the binding for the name if it is known or None if it not known. - fn binding(&self) -> Option<&'a NameBinding<'a>> { + pub(crate) fn binding(&self) -> Option<&'a NameBinding<'a>> { self.binding.and_then(|binding| { if !binding.is_glob_import() || self.single_imports.is_empty() { Some(binding) } else { None } @@ -636,7 +636,7 @@ impl<'a> Resolver<'a> { struct UnresolvedImportError { span: Span, label: Option, - note: Option, + note: Vec, suggestion: Option, } @@ -756,8 +756,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { /// Upper limit on the number of `span_label` messages. const MAX_LABEL_COUNT: usize = 10; - let (span, msg, note) = if errors.is_empty() { - (span.unwrap(), "unresolved import".to_string(), None) + let (span, msg) = if errors.is_empty() { + (span.unwrap(), "unresolved import".to_string()) } else { let span = MultiSpan::from_spans( errors @@ -766,11 +766,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { .collect(), ); - let note = errors - .iter() - .filter_map(|(_, err)| err.note.as_ref()) - .last(); - let paths = errors .iter() .map(|(path, _)| format!("`{}`", path)) @@ -782,13 +777,15 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { paths.join(", "), ); - (span, msg, note) + (span, msg) }; let mut diag = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg); - if let Some(note) = ¬e { - diag.note(note); + if let Some((_, UnresolvedImportError { note, .. })) = errors.iter().last() { + for message in note { + diag.note(&message); + } } for (_, err) in errors.into_iter().take(MAX_LABEL_COUNT) { @@ -961,7 +958,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { UnresolvedImportError { span, label: Some(label), - note: None, + note: Vec::new(), suggestion, } } @@ -1006,7 +1003,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { return Some(UnresolvedImportError { span: directive.span, label: Some(String::from("cannot glob-import a module into itself")), - note: None, + note: Vec::new(), suggestion: None, }); } @@ -1114,15 +1111,22 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } }); - let lev_suggestion = - find_best_match_for_name(names, &ident.as_str(), None).map(|suggestion| { - ( - ident.span, - String::from("a similar name exists in the module"), - suggestion.to_string(), - Applicability::MaybeIncorrect, - ) - }); + let (suggestion, note) = if let Some((suggestion, note)) = + self.check_for_module_export_macro(directive, module, ident) + { + + ( + suggestion.or_else(|| + find_best_match_for_name(names, &ident.as_str(), None) + .map(|suggestion| + (ident.span, String::from("a similar name exists in the module"), + suggestion.to_string(), Applicability::MaybeIncorrect) + )), + note, + ) + } else { + (None, Vec::new()) + }; let label = match module { ModuleOrUniformRoot::Module(module) => { @@ -1143,11 +1147,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } } }; + Some(UnresolvedImportError { span: directive.span, label: Some(label), - note: None, - suggestion: lev_suggestion, + note, + suggestion, }) } else { // `resolve_ident_in_module` reported a privacy error. diff --git a/src/test/ui/issue-59764.fixed b/src/test/ui/issue-59764.fixed new file mode 100644 index 0000000000000..d7a01ce5f4d74 --- /dev/null +++ b/src/test/ui/issue-59764.fixed @@ -0,0 +1,15 @@ +// aux-build:issue-59764.rs +// compile-flags:--extern issue_59764 +// edition:2018 +// run-rustfix + +use issue_59764::makro; +//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] + +makro!(bar); +//~^ ERROR cannot determine resolution for the macro `makro` + +fn main() { + bar(); + //~^ ERROR cannot find function `bar` in this scope [E0425] +} diff --git a/src/test/ui/issue-59764.rs b/src/test/ui/issue-59764.rs index 8ac9b9eaba181..e6f7205bfca33 100644 --- a/src/test/ui/issue-59764.rs +++ b/src/test/ui/issue-59764.rs @@ -1,6 +1,7 @@ // aux-build:issue-59764.rs // compile-flags:--extern issue_59764 // edition:2018 +// run-rustfix use issue_59764::foo::makro; //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] diff --git a/src/test/ui/issue-59764.stderr b/src/test/ui/issue-59764.stderr index a428488b009ec..6b3237e9272c5 100644 --- a/src/test/ui/issue-59764.stderr +++ b/src/test/ui/issue-59764.stderr @@ -1,11 +1,17 @@ error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:5:5 + --> $DIR/issue-59764.rs:6:5 | LL | use issue_59764::foo::makro; | ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::makro; + | ^^^^^^^^^^^^^^^^^^ error: cannot determine resolution for the macro `makro` - --> $DIR/issue-59764.rs:8:1 + --> $DIR/issue-59764.rs:9:1 | LL | makro!(bar); | ^^^^^ @@ -13,7 +19,7 @@ LL | makro!(bar); = note: import resolution is stuck, try simplifying macro imports error[E0425]: cannot find function `bar` in this scope - --> $DIR/issue-59764.rs:12:5 + --> $DIR/issue-59764.rs:13:5 | LL | bar(); | ^^^ not found in this scope From d589cf911109149564c8898ad1cb1d906f91caea Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 7 Apr 2019 20:34:21 +0200 Subject: [PATCH 37/53] Handle renamed imports. This commit extends the suggestion to handle imports that are aliased to another name. --- src/librustc_resolve/error_reporting.rs | 11 ++++++++--- src/librustc_resolve/resolve_imports.rs | 26 +++++++++++-------------- src/test/ui/issue-59764.fixed | 15 ++++++++++++++ src/test/ui/issue-59764.rs | 15 ++++++++++++++ src/test/ui/issue-59764.stderr | 20 +++++++++++++++---- 5 files changed, 65 insertions(+), 22 deletions(-) diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index 99aa6e39f7b71..b7ccbbf607913 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -11,7 +11,7 @@ use syntax::symbol::keywords; use syntax_pos::Span; use crate::macros::ParentScope; -use crate::resolve_imports::{ImportDirective, ImportResolver}; +use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver}; use crate::{import_candidate_to_enum_paths, is_self_type, is_self_value, path_names_to_string}; use crate::{AssocSuggestion, CrateLint, ImportSuggestion, ModuleOrUniformRoot, PathResult, PathSource, Resolver, Segment, Suggestion}; @@ -610,11 +610,16 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let resolution = resolutions.get(&(ident, MacroNS))?; let binding = resolution.borrow().binding()?; if let Def::Macro(_, MacroKind::Bang) = binding.def() { - let name = crate_module.kind.name().unwrap(); + let module_name = crate_module.kind.name().unwrap(); + let import = match directive.subclass { + ImportDirectiveSubclass::SingleImport { source, target, .. } if source != target => + format!("{} as {}", source, target), + _ => format!("{}", ident), + }; let suggestion = Some(( directive.span, String::from("a macro with this name exists at the root of the crate"), - format!("{}::{}", name, ident), + format!("{}::{}", module_name, import), Applicability::MaybeIncorrect, )); let note = vec![ diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 6a01af5d1153a..ef5f0f54ee369 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1111,21 +1111,17 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } }); - let (suggestion, note) = if let Some((suggestion, note)) = - self.check_for_module_export_macro(directive, module, ident) - { - - ( - suggestion.or_else(|| - find_best_match_for_name(names, &ident.as_str(), None) - .map(|suggestion| - (ident.span, String::from("a similar name exists in the module"), - suggestion.to_string(), Applicability::MaybeIncorrect) - )), - note, - ) - } else { - (None, Vec::new()) + let lev_suggestion = find_best_match_for_name(names, &ident.as_str(), None) + .map(|suggestion| + (ident.span, String::from("a similar name exists in the module"), + suggestion.to_string(), Applicability::MaybeIncorrect) + ); + + let (suggestion, note) = match self.check_for_module_export_macro( + directive, module, ident, + ) { + Some((suggestion, note)) => (suggestion.or(lev_suggestion), note), + _ => (lev_suggestion, Vec::new()), }; let label = match module { diff --git a/src/test/ui/issue-59764.fixed b/src/test/ui/issue-59764.fixed index d7a01ce5f4d74..34b9fc4edd9b7 100644 --- a/src/test/ui/issue-59764.fixed +++ b/src/test/ui/issue-59764.fixed @@ -3,6 +3,21 @@ // edition:2018 // run-rustfix +#![allow(warnings)] + +// This tests the suggestion to import macros from the root of a crate. This aims to capture +// the case where a user attempts to import a macro from the definition location instead of the +// root of the crate and the macro is annotated with `#![macro_export]`. + +// Edge cases.. + +mod renamed_import { + use issue_59764::makro as baz; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +// Simple case.. + use issue_59764::makro; //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] diff --git a/src/test/ui/issue-59764.rs b/src/test/ui/issue-59764.rs index e6f7205bfca33..b33b8e0cf5c57 100644 --- a/src/test/ui/issue-59764.rs +++ b/src/test/ui/issue-59764.rs @@ -3,6 +3,21 @@ // edition:2018 // run-rustfix +#![allow(warnings)] + +// This tests the suggestion to import macros from the root of a crate. This aims to capture +// the case where a user attempts to import a macro from the definition location instead of the +// root of the crate and the macro is annotated with `#![macro_export]`. + +// Edge cases.. + +mod renamed_import { + use issue_59764::foo::makro as baz; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +// Simple case.. + use issue_59764::foo::makro; //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] diff --git a/src/test/ui/issue-59764.stderr b/src/test/ui/issue-59764.stderr index 6b3237e9272c5..8bb4d03fc5dd6 100644 --- a/src/test/ui/issue-59764.stderr +++ b/src/test/ui/issue-59764.stderr @@ -1,5 +1,17 @@ error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:6:5 + --> $DIR/issue-59764.rs:15:9 + | +LL | use issue_59764::foo::makro as baz; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::makro as baz; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:21:5 | LL | use issue_59764::foo::makro; | ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` @@ -11,7 +23,7 @@ LL | use issue_59764::makro; | ^^^^^^^^^^^^^^^^^^ error: cannot determine resolution for the macro `makro` - --> $DIR/issue-59764.rs:9:1 + --> $DIR/issue-59764.rs:24:1 | LL | makro!(bar); | ^^^^^ @@ -19,12 +31,12 @@ LL | makro!(bar); = note: import resolution is stuck, try simplifying macro imports error[E0425]: cannot find function `bar` in this scope - --> $DIR/issue-59764.rs:13:5 + --> $DIR/issue-59764.rs:28:5 | LL | bar(); | ^^^ not found in this scope -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors occurred: E0425, E0432. For more information about an error, try `rustc --explain E0425`. From 7c955409e3cb06b2a5c008e80c6856cb25a74b33 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 7 Apr 2019 23:18:13 +0200 Subject: [PATCH 38/53] Handle edge cases. This commit introduces more dirty span manipulation into the compiler in order to handle the various edge cases in moving/renaming the macro import so it is at the root of the import. --- src/librustc_resolve/error_reporting.rs | 230 +++++++++++++++++++++++- src/librustc_resolve/lib.rs | 77 ++------ src/test/ui/auxiliary/issue-59764.rs | 10 ++ src/test/ui/issue-59764.fixed | 93 ++++++++++ src/test/ui/issue-59764.rs | 93 ++++++++++ src/test/ui/issue-59764.stderr | 195 +++++++++++++++++++- 6 files changed, 625 insertions(+), 73 deletions(-) diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index b7ccbbf607913..eea8cb80f69ef 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -4,11 +4,11 @@ use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use log::debug; use rustc::hir::def::{Def, CtorKind, Namespace::*}; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; -use rustc::session::config::nightly_options; +use rustc::session::{Session, config::nightly_options}; use syntax::ast::{Expr, ExprKind, Ident}; use syntax::ext::base::MacroKind; -use syntax::symbol::keywords; -use syntax_pos::Span; +use syntax::symbol::{Symbol, keywords}; +use syntax_pos::{BytePos, Span}; use crate::macros::ParentScope; use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver}; @@ -616,10 +616,84 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { format!("{} as {}", source, target), _ => format!("{}", ident), }; + + // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove + // intermediate segments. + let (mut span, mut correction) = (directive.span, + format!("{}::{}", module_name, import)); + + if directive.is_nested() { + span = directive.use_span; + + // Find the binding span (and any trailing commas and spaces). + // ie. `use a::b::{c, d, e};` + // ^^^ + let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding( + self.resolver.session, directive.span, directive.use_span, + ); + debug!("check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}", + found_closing_brace, binding_span); + + let mut removal_span = binding_span; + if found_closing_brace { + // If the binding span ended with a closing brace, as in the below example: + // ie. `use a::b::{c, d};` + // ^ + // Then expand the span of characters to remove to include the previous + // binding's trailing comma. + // ie. `use a::b::{c, d};` + // ^^^ + if let Some(previous_span) = extend_span_to_previous_binding( + self.resolver.session, binding_span, + ) { + debug!("check_for_module_export_macro: previous_span={:?}", previous_span); + removal_span = removal_span.with_lo(previous_span.lo()); + } + } + debug!("check_for_module_export_macro: removal_span={:?}", removal_span); + + // Find the span after the crate name and if it has nested imports immediatately + // after the crate name already. + // ie. `use a::b::{c, d};` + // ^^^^^^^^^ + // or `use a::{b, c, d}};` + // ^^^^^^^^^^^ + let (has_nested, after_crate_name) = find_span_immediately_after_crate_name( + self.resolver.session, module_name, directive.use_span, + ); + debug!("check_for_module_export_macro: has_nested={:?} after_crate_name={:?}", + has_nested, after_crate_name); + + let source_map = self.resolver.session.source_map(); + + // Remove two bytes at the end to keep all but the `};` characters. + // ie. `{b::{c, d}, e::{f, g}};` + // ^^^^^^^^^^^^^^^^^^^^^ + let end_bytes = BytePos(if has_nested { 2 } else { 1 }); + let mut remaining_span = after_crate_name.with_hi( + after_crate_name.hi() - end_bytes); + if has_nested { + // Remove two bytes at the start to keep all but the initial `{` character. + // ie. `{b::{c, d}, e::{f, g}` + // ^^^^^^^^^^^^^^^^^^^^ + remaining_span = remaining_span.with_lo(after_crate_name.lo() + BytePos(1)); + } + + // Calculate the number of characters into a snippet to remove the removal + // span. + let lo = removal_span.lo() - remaining_span.lo(); + let hi = lo + (removal_span.hi() - removal_span.lo()); + if let Ok(mut remaining) = source_map.span_to_snippet(remaining_span) { + // Remove the original location of the binding. + remaining.replace_range((lo.0 as usize)..(hi.0 as usize), ""); + correction = format!("use {}::{{{}, {}}};", module_name, import, remaining); + } + } + let suggestion = Some(( - directive.span, + span, String::from("a macro with this name exists at the root of the crate"), - format!("{}::{}", module_name, import), + correction, Applicability::MaybeIncorrect, )); let note = vec![ @@ -632,3 +706,149 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } } } + +/// Given a `binding_span` of a binding within a use statement: +/// +/// ``` +/// use foo::{a, b, c}; +/// ^ +/// ``` +/// +/// then return the span until the next binding or the end of the statement: +/// +/// ``` +/// use foo::{a, b, c}; +/// ^^^ +/// ``` +pub(crate) fn find_span_of_binding_until_next_binding( + sess: &Session, + binding_span: Span, + use_span: Span, +) -> (bool, Span) { + let source_map = sess.source_map(); + + // Find the span of everything after the binding. + // ie. `a, e};` or `a};` + let binding_until_end = binding_span.with_hi(use_span.hi()); + + // Find everything after the binding but not including the binding. + // ie. `, e};` or `};` + let after_binding_until_end = binding_until_end.with_lo(binding_span.hi()); + + // Keep characters in the span until we encounter something that isn't a comma or + // whitespace. + // ie. `, ` or ``. + // + // Also note whether a closing brace character was encountered. If there + // was, then later go backwards to remove any trailing commas that are left. + let mut found_closing_brace = false; + let after_binding_until_next_binding = source_map.span_take_while( + after_binding_until_end, + |&ch| { + if ch == '}' { found_closing_brace = true; } + ch == ' ' || ch == ',' + } + ); + + // Combine the two spans. + // ie. `a, ` or `a`. + // + // Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };` + let span = binding_span.with_hi(after_binding_until_next_binding.hi()); + + (found_closing_brace, span) +} + +/// Given a `binding_span`, return the span through to the comma or opening brace of the previous +/// binding. +/// +/// ``` +/// use foo::a::{a, b, c}; +/// ^^--- binding span +/// | +/// returned span +/// +/// use foo::{a, b, c}; +/// --- binding span +/// ``` +pub(crate) fn extend_span_to_previous_binding( + sess: &Session, + binding_span: Span, +) -> Option { + let source_map = sess.source_map(); + + // `prev_source` will contain all of the source that came before the span. + // Then split based on a command and take the first (ie. closest to our span) + // snippet. In the example, this is a space. + let prev_source = source_map.span_to_prev_source(binding_span).ok()?; + + let prev_comma = prev_source.rsplit(',').collect::>(); + let prev_starting_brace = prev_source.rsplit('{').collect::>(); + if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 { + return None; + } + + let prev_comma = prev_comma.first().unwrap(); + let prev_starting_brace = prev_starting_brace.first().unwrap(); + + // If the amount of source code before the comma is greater than + // the amount of source code before the starting brace then we've only + // got one item in the nested item (eg. `issue_52891::{self}`). + if prev_comma.len() > prev_starting_brace.len() { + return None; + } + + Some(binding_span.with_lo(BytePos( + // Take away the number of bytes for the characters we've found and an + // extra for the comma. + binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1 + ))) +} + +/// Given a `use_span` of a binding within a use statement, returns the highlighted span and if +/// it is a nested use tree. +/// +/// ``` +/// use foo::a::{b, c}; +/// ^^^^^^^^^^ // false +/// +/// use foo::{a, b, c}; +/// ^^^^^^^^^^ // true +/// +/// use foo::{a, b::{c, d}}; +/// ^^^^^^^^^^^^^^^ // true +/// ``` +fn find_span_immediately_after_crate_name( + sess: &Session, + module_name: Symbol, + use_span: Span, +) -> (bool, Span) { + debug!("find_span_immediately_after_crate_name: module_name={:?} use_span={:?}", + module_name, use_span); + let source_map = sess.source_map(); + + // Get position of the first `{` character for the use statement. + // ie. `use foo::{a, b::{c, d}};` + // ^ + let pos_of_use_tree_left_bracket = source_map.span_until_char(use_span, '{').hi(); + debug!("find_span_immediately_after_crate_name: pos_of_use_tree_left_bracket={:?}", + pos_of_use_tree_left_bracket); + + // Calculate the expected difference between the first `{` character and the start of a + // use statement. + // ie. `use foo::{..};` + // ^^^^ + // | ^^^ + // 4 | ^^ + // 3 | + // 2 + let expected_difference = BytePos((module_name.as_str().len() + 4 + 2) as u32); + debug!("find_span_immediately_after_crate_name: expected_difference={:?}", + expected_difference); + let actual_difference = pos_of_use_tree_left_bracket - use_span.lo(); + debug!("find_span_immediately_after_crate_name: actual_difference={:?}", + actual_difference); + + (expected_difference == actual_difference, + use_span.with_lo(use_span.lo() + expected_difference)) +} diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0fb1ca4298358..b33356c2ba7ae 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -50,7 +50,7 @@ use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind}; use syntax::ptr::P; use syntax::{span_err, struct_span_err, unwrap_or, walk_list}; -use syntax_pos::{BytePos, Span, DUMMY_SP, MultiSpan}; +use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use log::debug; @@ -62,6 +62,7 @@ use std::mem::replace; use rustc_data_structures::ptr_key::PtrKey; use rustc_data_structures::sync::Lrc; +use error_reporting::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding}; use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver}; use macros::{InvocationData, LegacyBinding, ParentScope}; @@ -5144,7 +5145,6 @@ impl<'a> Resolver<'a> { ) { assert!(directive.is_nested()); let message = "remove unnecessary import"; - let source_map = self.session.source_map(); // Two examples will be used to illustrate the span manipulations we're doing: // @@ -5153,73 +5153,24 @@ impl<'a> Resolver<'a> { // - Given `use issue_52891::{d, e, a};` where `a` is a duplicate then `binding_span` is // `a` and `directive.use_span` is `issue_52891::{d, e, a};`. - // Find the span of everything after the binding. - // ie. `a, e};` or `a};` - let binding_until_end = binding_span.with_hi(directive.use_span.hi()); - - // Find everything after the binding but not including the binding. - // ie. `, e};` or `};` - let after_binding_until_end = binding_until_end.with_lo(binding_span.hi()); - - // Keep characters in the span until we encounter something that isn't a comma or - // whitespace. - // ie. `, ` or ``. - // - // Also note whether a closing brace character was encountered. If there - // was, then later go backwards to remove any trailing commas that are left. - let mut found_closing_brace = false; - let after_binding_until_next_binding = source_map.span_take_while( - after_binding_until_end, - |&ch| { - if ch == '}' { found_closing_brace = true; } - ch == ' ' || ch == ',' - } + let (found_closing_brace, span) = find_span_of_binding_until_next_binding( + self.session, binding_span, directive.use_span, ); - // Combine the two spans. - // ie. `a, ` or `a`. - // - // Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };` - let span = binding_span.with_hi(after_binding_until_next_binding.hi()); - // If there was a closing brace then identify the span to remove any trailing commas from // previous imports. if found_closing_brace { - if let Ok(prev_source) = source_map.span_to_prev_source(span) { - // `prev_source` will contain all of the source that came before the span. - // Then split based on a command and take the first (ie. closest to our span) - // snippet. In the example, this is a space. - let prev_comma = prev_source.rsplit(',').collect::>(); - let prev_starting_brace = prev_source.rsplit('{').collect::>(); - if prev_comma.len() > 1 && prev_starting_brace.len() > 1 { - let prev_comma = prev_comma.first().unwrap(); - let prev_starting_brace = prev_starting_brace.first().unwrap(); - - // If the amount of source code before the comma is greater than - // the amount of source code before the starting brace then we've only - // got one item in the nested item (eg. `issue_52891::{self}`). - if prev_comma.len() > prev_starting_brace.len() { - // So just remove the entire line... - err.span_suggestion( - directive.use_span_with_attributes, - message, - String::new(), - Applicability::MaybeIncorrect, - ); - return; - } - - let span = span.with_lo(BytePos( - // Take away the number of bytes for the characters we've found and an - // extra for the comma. - span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1 - )); - err.tool_only_span_suggestion( - span, message, String::new(), Applicability::MaybeIncorrect, - ); - return; - } + if let Some(span) = extend_span_to_previous_binding(self.session, span) { + err.tool_only_span_suggestion(span, message, String::new(), + Applicability::MaybeIncorrect); + } else { + // Remove the entire line if we cannot extend the span back, this indicates a + // `issue_52891::{self}` case. + err.span_suggestion(directive.use_span_with_attributes, message, String::new(), + Applicability::MaybeIncorrect); } + + return; } err.span_suggestion(span, message, String::new(), Applicability::MachineApplicable); diff --git a/src/test/ui/auxiliary/issue-59764.rs b/src/test/ui/auxiliary/issue-59764.rs index 0243ef5c6c74a..a92eed968d060 100644 --- a/src/test/ui/auxiliary/issue-59764.rs +++ b/src/test/ui/auxiliary/issue-59764.rs @@ -5,4 +5,14 @@ pub mod foo { fn $foo() { } } } + + pub fn baz() {} + + pub fn foobar() {} + + pub mod barbaz { + pub fn barfoo() {} + } } + +pub fn foobaz() {} diff --git a/src/test/ui/issue-59764.fixed b/src/test/ui/issue-59764.fixed index 34b9fc4edd9b7..ff193fce7eb1d 100644 --- a/src/test/ui/issue-59764.fixed +++ b/src/test/ui/issue-59764.fixed @@ -11,11 +11,104 @@ // Edge cases.. +mod multiple_imports_same_line_at_end { + use issue_59764::{makro, foo::{baz}}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod multiple_imports_multiline_at_end_trailing_comma { + use issue_59764::{makro, foo::{ + baz, + //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + }}; +} + +mod multiple_imports_multiline_at_end { + use issue_59764::{makro, foo::{ + baz, + //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + }}; +} + +mod multiple_imports_same_line_in_middle { + use issue_59764::{makro, foo::{baz, foobar}}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod multiple_imports_multiline_in_middle_trailing_comma { + use issue_59764::{makro, foo::{ + baz, + //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + foobar, + }}; +} + +mod multiple_imports_multiline_in_middle { + use issue_59764::{makro, foo::{ + baz, + //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + foobar + }}; +} + +mod nested_imports { + use issue_59764::{makro, foobaz}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod nested_multiple_imports { + use issue_59764::{makro, foobaz, foo::{baz}}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod nested_multiline_multiple_imports_trailing_comma { + use issue_59764::{makro, + foobaz, + foo::{ + baz, + //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + }, + }; +} + +mod nested_multiline_multiple_imports { + use issue_59764::{makro, + foobaz, + foo::{ + baz, + //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + } + }; +} + +mod doubly_nested_multiple_imports { + use issue_59764::{makro, foobaz, foo::{baz, barbaz::{barfoo}}}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod doubly_multiline_nested_multiple_imports { + use issue_59764::{makro, + foobaz, + foo::{ + baz, + //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + barbaz::{ + barfoo, + } + } + }; +} + mod renamed_import { use issue_59764::makro as baz; //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] } +mod renamed_multiple_imports { + use issue_59764::{makro as foobar, foo::{baz}}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + // Simple case.. use issue_59764::makro; diff --git a/src/test/ui/issue-59764.rs b/src/test/ui/issue-59764.rs index b33b8e0cf5c57..c68471adaad56 100644 --- a/src/test/ui/issue-59764.rs +++ b/src/test/ui/issue-59764.rs @@ -11,11 +11,104 @@ // Edge cases.. +mod multiple_imports_same_line_at_end { + use issue_59764::foo::{baz, makro}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod multiple_imports_multiline_at_end_trailing_comma { + use issue_59764::foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + }; +} + +mod multiple_imports_multiline_at_end { + use issue_59764::foo::{ + baz, + makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + }; +} + +mod multiple_imports_same_line_in_middle { + use issue_59764::foo::{baz, makro, foobar}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod multiple_imports_multiline_in_middle_trailing_comma { + use issue_59764::foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + foobar, + }; +} + +mod multiple_imports_multiline_in_middle { + use issue_59764::foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + foobar + }; +} + +mod nested_imports { + use issue_59764::{foobaz, foo::makro}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod nested_multiple_imports { + use issue_59764::{foobaz, foo::{baz, makro}}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod nested_multiline_multiple_imports_trailing_comma { + use issue_59764::{ + foobaz, + foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + }, + }; +} + +mod nested_multiline_multiple_imports { + use issue_59764::{ + foobaz, + foo::{ + baz, + makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + } + }; +} + +mod doubly_nested_multiple_imports { + use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod doubly_multiline_nested_multiple_imports { + use issue_59764::{ + foobaz, + foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + barbaz::{ + barfoo, + } + } + }; +} + mod renamed_import { use issue_59764::foo::makro as baz; //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] } +mod renamed_multiple_imports { + use issue_59764::foo::{baz, makro as foobar}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + // Simple case.. use issue_59764::foo::makro; diff --git a/src/test/ui/issue-59764.stderr b/src/test/ui/issue-59764.stderr index 8bb4d03fc5dd6..fe93547318468 100644 --- a/src/test/ui/issue-59764.stderr +++ b/src/test/ui/issue-59764.stderr @@ -1,5 +1,178 @@ error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:15:9 + --> $DIR/issue-59764.rs:15:33 + | +LL | use issue_59764::foo::{baz, makro}; + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foo::{baz}}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:22:9 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foo::{ +LL | baz, +LL | +LL | }}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:29:9 + | +LL | makro + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foo::{ +LL | baz, +LL | +LL | }}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:34:33 + | +LL | use issue_59764::foo::{baz, makro, foobar}; + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foo::{baz, foobar}}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:41:9 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foo::{ +LL | baz, +LL | +LL | foobar, +LL | }}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:49:9 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foo::{ +LL | baz, +LL | +LL | foobar +LL | }}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:55:31 + | +LL | use issue_59764::{foobaz, foo::makro}; + | ^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foobaz}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:60:42 + | +LL | use issue_59764::{foobaz, foo::{baz, makro}}; + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foobaz, foo::{baz}}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:69:13 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, +LL | foobaz, +LL | foo::{ +LL | baz, +LL | +LL | }, + ... + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:79:13 + | +LL | makro + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, +LL | foobaz, +LL | foo::{ +LL | baz, +LL | +LL | } + ... + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:85:42 + | +LL | use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}}; + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foobaz, foo::{baz, barbaz::{barfoo}}}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:94:13 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, +LL | foobaz, +LL | foo::{ +LL | baz, +LL | +LL | barbaz::{ + ... + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:103:9 | LL | use issue_59764::foo::makro as baz; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` @@ -11,7 +184,19 @@ LL | use issue_59764::makro as baz; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:21:5 + --> $DIR/issue-59764.rs:108:33 + | +LL | use issue_59764::foo::{baz, makro as foobar}; + | ^^^^^^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro as foobar, foo::{baz}}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:114:5 | LL | use issue_59764::foo::makro; | ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` @@ -23,7 +208,7 @@ LL | use issue_59764::makro; | ^^^^^^^^^^^^^^^^^^ error: cannot determine resolution for the macro `makro` - --> $DIR/issue-59764.rs:24:1 + --> $DIR/issue-59764.rs:117:1 | LL | makro!(bar); | ^^^^^ @@ -31,12 +216,12 @@ LL | makro!(bar); = note: import resolution is stuck, try simplifying macro imports error[E0425]: cannot find function `bar` in this scope - --> $DIR/issue-59764.rs:28:5 + --> $DIR/issue-59764.rs:121:5 | LL | bar(); | ^^^ not found in this scope -error: aborting due to 4 previous errors +error: aborting due to 17 previous errors Some errors occurred: E0425, E0432. For more information about an error, try `rustc --explain E0425`. From 137ffa10229bfec497a446d24045388ee3c418d6 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 12 Apr 2019 01:19:02 +0200 Subject: [PATCH 39/53] Improve robustness of nested check. This commit removes the assumption that the start of a use statement will always be on one line with a single space - which was silly in the first place. --- src/librustc_resolve/error_reporting.rs | 49 +++++++++++++------------ src/test/ui/issue-59764.fixed | 11 ++++++ src/test/ui/issue-59764.rs | 14 +++++++ src/test/ui/issue-59764.stderr | 25 +++++++++++-- 4 files changed, 71 insertions(+), 28 deletions(-) diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index eea8cb80f69ef..5372c4ee44bdc 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -827,28 +827,29 @@ fn find_span_immediately_after_crate_name( module_name, use_span); let source_map = sess.source_map(); - // Get position of the first `{` character for the use statement. - // ie. `use foo::{a, b::{c, d}};` - // ^ - let pos_of_use_tree_left_bracket = source_map.span_until_char(use_span, '{').hi(); - debug!("find_span_immediately_after_crate_name: pos_of_use_tree_left_bracket={:?}", - pos_of_use_tree_left_bracket); - - // Calculate the expected difference between the first `{` character and the start of a - // use statement. - // ie. `use foo::{..};` - // ^^^^ - // | ^^^ - // 4 | ^^ - // 3 | - // 2 - let expected_difference = BytePos((module_name.as_str().len() + 4 + 2) as u32); - debug!("find_span_immediately_after_crate_name: expected_difference={:?}", - expected_difference); - let actual_difference = pos_of_use_tree_left_bracket - use_span.lo(); - debug!("find_span_immediately_after_crate_name: actual_difference={:?}", - actual_difference); - - (expected_difference == actual_difference, - use_span.with_lo(use_span.lo() + expected_difference)) + // Using `use issue_59764::foo::{baz, makro};` as an example throughout.. + let mut num_colons = 0; + // Find second colon.. `use issue_59764:` + let until_second_colon = source_map.span_take_while(use_span, |c| { + if *c == ':' { num_colons += 1; } + match c { + ':' if num_colons == 2 => false, + _ => true, + } + }); + // Find everything after the second colon.. `foo::{baz, makro};` + let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1)); + + let mut found_a_non_whitespace_character = false; + // Find the first non-whitespace character in `from_second_colon`.. `f` + let after_second_colon = source_map.span_take_while(from_second_colon, |c| { + if found_a_non_whitespace_character { return false; } + if !c.is_whitespace() { found_a_non_whitespace_character = true; } + true + }); + + // Find the first `{` in from_second_colon.. `foo::{` + let next_left_bracket = source_map.span_through_char(from_second_colon, '{'); + + (next_left_bracket == after_second_colon, from_second_colon) } diff --git a/src/test/ui/issue-59764.fixed b/src/test/ui/issue-59764.fixed index ff193fce7eb1d..ad3bab50cfca3 100644 --- a/src/test/ui/issue-59764.fixed +++ b/src/test/ui/issue-59764.fixed @@ -109,6 +109,17 @@ mod renamed_multiple_imports { //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] } +mod lots_of_whitespace { + use issue_59764::{makro as foobar, + + foobaz, + + + foo::{baz} //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + + }; +} + // Simple case.. use issue_59764::makro; diff --git a/src/test/ui/issue-59764.rs b/src/test/ui/issue-59764.rs index c68471adaad56..0c6787691de0a 100644 --- a/src/test/ui/issue-59764.rs +++ b/src/test/ui/issue-59764.rs @@ -109,6 +109,20 @@ mod renamed_multiple_imports { //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] } +mod lots_of_whitespace { + use + issue_59764::{ + + foobaz, + + + foo::{baz, + + makro as foobar} //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + + }; +} + // Simple case.. use issue_59764::foo::makro; diff --git a/src/test/ui/issue-59764.stderr b/src/test/ui/issue-59764.stderr index fe93547318468..89b1f84605dc7 100644 --- a/src/test/ui/issue-59764.stderr +++ b/src/test/ui/issue-59764.stderr @@ -196,7 +196,24 @@ LL | use issue_59764::{makro as foobar, foo::{baz}}; | error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:114:5 + --> $DIR/issue-59764.rs:121:17 + | +LL | makro as foobar} + | ^^^^^^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro as foobar, +LL | +LL | foobaz, +LL | +LL | +LL | foo::{baz} + ... + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:128:5 | LL | use issue_59764::foo::makro; | ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` @@ -208,7 +225,7 @@ LL | use issue_59764::makro; | ^^^^^^^^^^^^^^^^^^ error: cannot determine resolution for the macro `makro` - --> $DIR/issue-59764.rs:117:1 + --> $DIR/issue-59764.rs:131:1 | LL | makro!(bar); | ^^^^^ @@ -216,12 +233,12 @@ LL | makro!(bar); = note: import resolution is stuck, try simplifying macro imports error[E0425]: cannot find function `bar` in this scope - --> $DIR/issue-59764.rs:121:5 + --> $DIR/issue-59764.rs:135:5 | LL | bar(); | ^^^ not found in this scope -error: aborting due to 17 previous errors +error: aborting due to 18 previous errors Some errors occurred: E0425, E0432. For more information about an error, try `rustc --explain E0425`. From 5158063c3ec1e1dc8d9b0a0806e29d6c6e54d765 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 12 Apr 2019 01:53:32 +0200 Subject: [PATCH 40/53] Switch to multipart suggestions. This commit changes the suggestion so that it is split into multiple parts in an effort to reduce the impact the applied suggestion could have on formatting. --- src/librustc_resolve/error_reporting.rs | 57 +++++----- src/librustc_resolve/lib.rs | 11 +- src/librustc_resolve/resolve_imports.rs | 12 +-- src/test/ui/issue-59764.fixed | 134 ------------------------ src/test/ui/issue-59764.rs | 1 - src/test/ui/issue-59764.stderr | 61 +++++------ 6 files changed, 68 insertions(+), 208 deletions(-) delete mode 100644 src/test/ui/issue-59764.fixed diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index 5372c4ee44bdc..931bce91d7d43 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -617,14 +617,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { _ => format!("{}", ident), }; - // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove - // intermediate segments. - let (mut span, mut correction) = (directive.span, - format!("{}::{}", module_name, import)); - - if directive.is_nested() { - span = directive.use_span; - + let mut corrections: Vec<(Span, String)> = Vec::new(); + if !directive.is_nested() { + // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove + // intermediate segments. + corrections.push((directive.span, format!("{}::{}", module_name, import))); + } else { // Find the binding span (and any trailing commas and spaces). // ie. `use a::b::{c, d, e};` // ^^^ @@ -652,6 +650,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } debug!("check_for_module_export_macro: removal_span={:?}", removal_span); + // Remove the `removal_span`. + corrections.push((removal_span, "".to_string())); + // Find the span after the crate name and if it has nested imports immediatately // after the crate name already. // ie. `use a::b::{c, d};` @@ -666,34 +667,32 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let source_map = self.resolver.session.source_map(); - // Remove two bytes at the end to keep all but the `};` characters. - // ie. `{b::{c, d}, e::{f, g}};` - // ^^^^^^^^^^^^^^^^^^^^^ - let end_bytes = BytePos(if has_nested { 2 } else { 1 }); - let mut remaining_span = after_crate_name.with_hi( - after_crate_name.hi() - end_bytes); - if has_nested { - // Remove two bytes at the start to keep all but the initial `{` character. - // ie. `{b::{c, d}, e::{f, g}` - // ^^^^^^^^^^^^^^^^^^^^ - remaining_span = remaining_span.with_lo(after_crate_name.lo() + BytePos(1)); + // Add the import to the start, with a `{` if required. + let start_point = source_map.start_point(after_crate_name); + if let Ok(start_snippet) = source_map.span_to_snippet(start_point) { + corrections.push(( + start_point, + if has_nested { + // In this case, `start_snippet` must equal '{'. + format!("{}{}, ", start_snippet, import) + } else { + // In this case, add a `{`, then the moved import, then whatever + // was there before. + format!("{{{}, {}", import, start_snippet) + } + )); } - // Calculate the number of characters into a snippet to remove the removal - // span. - let lo = removal_span.lo() - remaining_span.lo(); - let hi = lo + (removal_span.hi() - removal_span.lo()); - if let Ok(mut remaining) = source_map.span_to_snippet(remaining_span) { - // Remove the original location of the binding. - remaining.replace_range((lo.0 as usize)..(hi.0 as usize), ""); - correction = format!("use {}::{{{}, {}}};", module_name, import, remaining); + // Add a `};` to the end if nested, matching the `{` added at the start. + if !has_nested { + corrections.push((source_map.end_point(after_crate_name), + "};".to_string())); } } let suggestion = Some(( - span, + corrections, String::from("a macro with this name exists at the root of the crate"), - correction, Applicability::MaybeIncorrect, )); let note = vec![ diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b33356c2ba7ae..c1353d771c26f 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -139,8 +139,8 @@ impl Ord for BindingError { } } -/// A span, message, replacement text, and applicability. -type Suggestion = (Span, String, String, Applicability); +/// A vector of spans and replacements, a message and applicability. +type Suggestion = (Vec<(Span, String)>, String, Applicability); enum ResolutionError<'a> { /// Error E0401: can't use type or const parameters from outer function. @@ -390,8 +390,8 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>, "failed to resolve: {}", &label); err.span_label(span, label); - if let Some((span, msg, suggestion, applicability)) = suggestion { - err.span_suggestion(span, &msg, suggestion, applicability); + if let Some((suggestions, msg, applicability)) = suggestion { + err.multipart_suggestion(&msg, suggestions, applicability); } err @@ -3774,9 +3774,8 @@ impl<'a> Resolver<'a> { ( String::from("unresolved import"), Some(( - ident.span, + vec![(ident.span, candidate.path.to_string())], String::from("a similar path exists"), - candidate.path.to_string(), Applicability::MaybeIncorrect, )), ) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index ef5f0f54ee369..62af6e19603c4 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -793,8 +793,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { diag.span_label(err.span, label); } - if let Some((span, msg, suggestion, applicability)) = err.suggestion { - diag.span_suggestion(span, &msg, suggestion, applicability); + if let Some((suggestions, msg, applicability)) = err.suggestion { + diag.multipart_suggestion(&msg, suggestions, applicability); } } @@ -947,9 +947,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { label: None, note, suggestion: Some(( - span, + vec![(span, Segment::names_to_string(&suggestion))], String::from("a similar path exists"), - Segment::names_to_string(&suggestion), Applicability::MaybeIncorrect, )), } @@ -1113,8 +1112,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let lev_suggestion = find_best_match_for_name(names, &ident.as_str(), None) .map(|suggestion| - (ident.span, String::from("a similar name exists in the module"), - suggestion.to_string(), Applicability::MaybeIncorrect) + (vec![(ident.span, suggestion.to_string())], + String::from("a similar name exists in the module"), + Applicability::MaybeIncorrect) ); let (suggestion, note) = match self.check_for_module_export_macro( diff --git a/src/test/ui/issue-59764.fixed b/src/test/ui/issue-59764.fixed deleted file mode 100644 index ad3bab50cfca3..0000000000000 --- a/src/test/ui/issue-59764.fixed +++ /dev/null @@ -1,134 +0,0 @@ -// aux-build:issue-59764.rs -// compile-flags:--extern issue_59764 -// edition:2018 -// run-rustfix - -#![allow(warnings)] - -// This tests the suggestion to import macros from the root of a crate. This aims to capture -// the case where a user attempts to import a macro from the definition location instead of the -// root of the crate and the macro is annotated with `#![macro_export]`. - -// Edge cases.. - -mod multiple_imports_same_line_at_end { - use issue_59764::{makro, foo::{baz}}; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod multiple_imports_multiline_at_end_trailing_comma { - use issue_59764::{makro, foo::{ - baz, - //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - }}; -} - -mod multiple_imports_multiline_at_end { - use issue_59764::{makro, foo::{ - baz, - //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - }}; -} - -mod multiple_imports_same_line_in_middle { - use issue_59764::{makro, foo::{baz, foobar}}; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod multiple_imports_multiline_in_middle_trailing_comma { - use issue_59764::{makro, foo::{ - baz, - //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - foobar, - }}; -} - -mod multiple_imports_multiline_in_middle { - use issue_59764::{makro, foo::{ - baz, - //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - foobar - }}; -} - -mod nested_imports { - use issue_59764::{makro, foobaz}; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod nested_multiple_imports { - use issue_59764::{makro, foobaz, foo::{baz}}; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod nested_multiline_multiple_imports_trailing_comma { - use issue_59764::{makro, - foobaz, - foo::{ - baz, - //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - }, - }; -} - -mod nested_multiline_multiple_imports { - use issue_59764::{makro, - foobaz, - foo::{ - baz, - //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - } - }; -} - -mod doubly_nested_multiple_imports { - use issue_59764::{makro, foobaz, foo::{baz, barbaz::{barfoo}}}; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod doubly_multiline_nested_multiple_imports { - use issue_59764::{makro, - foobaz, - foo::{ - baz, - //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - barbaz::{ - barfoo, - } - } - }; -} - -mod renamed_import { - use issue_59764::makro as baz; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod renamed_multiple_imports { - use issue_59764::{makro as foobar, foo::{baz}}; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod lots_of_whitespace { - use issue_59764::{makro as foobar, - - foobaz, - - - foo::{baz} //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - - }; -} - -// Simple case.. - -use issue_59764::makro; -//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] - -makro!(bar); -//~^ ERROR cannot determine resolution for the macro `makro` - -fn main() { - bar(); - //~^ ERROR cannot find function `bar` in this scope [E0425] -} diff --git a/src/test/ui/issue-59764.rs b/src/test/ui/issue-59764.rs index 0c6787691de0a..09dee8c273268 100644 --- a/src/test/ui/issue-59764.rs +++ b/src/test/ui/issue-59764.rs @@ -1,7 +1,6 @@ // aux-build:issue-59764.rs // compile-flags:--extern issue_59764 // edition:2018 -// run-rustfix #![allow(warnings)] diff --git a/src/test/ui/issue-59764.stderr b/src/test/ui/issue-59764.stderr index 89b1f84605dc7..924e69f5f9703 100644 --- a/src/test/ui/issue-59764.stderr +++ b/src/test/ui/issue-59764.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:15:33 + --> $DIR/issue-59764.rs:14:33 | LL | use issue_59764::foo::{baz, makro}; | ^^^^^ no `makro` in `foo` @@ -8,10 +8,10 @@ LL | use issue_59764::foo::{baz, makro}; help: a macro with this name exists at the root of the crate | LL | use issue_59764::{makro, foo::{baz}}; - | + | ^^^^^^^^^ --^^ error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:22:9 + --> $DIR/issue-59764.rs:21:9 | LL | makro, | ^^^^^ no `makro` in `foo` @@ -26,7 +26,7 @@ LL | }}; | error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:29:9 + --> $DIR/issue-59764.rs:28:9 | LL | makro | ^^^^^ no `makro` in `foo` @@ -41,7 +41,7 @@ LL | }}; | error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:34:33 + --> $DIR/issue-59764.rs:33:33 | LL | use issue_59764::foo::{baz, makro, foobar}; | ^^^^^ no `makro` in `foo` @@ -50,10 +50,10 @@ LL | use issue_59764::foo::{baz, makro, foobar}; help: a macro with this name exists at the root of the crate | LL | use issue_59764::{makro, foo::{baz, foobar}}; - | + | ^^^^^^^^^ -- ^^ error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:41:9 + --> $DIR/issue-59764.rs:40:9 | LL | makro, | ^^^^^ no `makro` in `foo` @@ -69,7 +69,7 @@ LL | }}; | error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:49:9 + --> $DIR/issue-59764.rs:48:9 | LL | makro, | ^^^^^ no `makro` in `foo` @@ -85,7 +85,7 @@ LL | }}; | error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:55:31 + --> $DIR/issue-59764.rs:54:31 | LL | use issue_59764::{foobaz, foo::makro}; | ^^^^^^^^^^ no `makro` in `foo` @@ -94,10 +94,10 @@ LL | use issue_59764::{foobaz, foo::makro}; help: a macro with this name exists at the root of the crate | LL | use issue_59764::{makro, foobaz}; - | + | ^^^^^^^ -- error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:60:42 + --> $DIR/issue-59764.rs:59:42 | LL | use issue_59764::{foobaz, foo::{baz, makro}}; | ^^^^^ no `makro` in `foo` @@ -106,10 +106,10 @@ LL | use issue_59764::{foobaz, foo::{baz, makro}}; help: a macro with this name exists at the root of the crate | LL | use issue_59764::{makro, foobaz, foo::{baz}}; - | + | ^^^^^^^ -- error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:69:13 + --> $DIR/issue-59764.rs:68:13 | LL | makro, | ^^^^^ no `makro` in `foo` @@ -122,11 +122,10 @@ LL | foobaz, LL | foo::{ LL | baz, LL | -LL | }, - ... + | error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:79:13 + --> $DIR/issue-59764.rs:78:13 | LL | makro | ^^^^^ no `makro` in `foo` @@ -139,11 +138,10 @@ LL | foobaz, LL | foo::{ LL | baz, LL | -LL | } - ... + | error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:85:42 + --> $DIR/issue-59764.rs:84:42 | LL | use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}}; | ^^^^^ no `makro` in `foo` @@ -152,10 +150,10 @@ LL | use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}}; help: a macro with this name exists at the root of the crate | LL | use issue_59764::{makro, foobaz, foo::{baz, barbaz::{barfoo}}}; - | + | ^^^^^^^ -- error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:94:13 + --> $DIR/issue-59764.rs:93:13 | LL | makro, | ^^^^^ no `makro` in `foo` @@ -168,11 +166,10 @@ LL | foobaz, LL | foo::{ LL | baz, LL | -LL | barbaz::{ - ... + | error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:103:9 + --> $DIR/issue-59764.rs:102:9 | LL | use issue_59764::foo::makro as baz; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` @@ -184,7 +181,7 @@ LL | use issue_59764::makro as baz; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:108:33 + --> $DIR/issue-59764.rs:107:33 | LL | use issue_59764::foo::{baz, makro as foobar}; | ^^^^^^^^^^^^^^^ no `makro` in `foo` @@ -193,10 +190,10 @@ LL | use issue_59764::foo::{baz, makro as foobar}; help: a macro with this name exists at the root of the crate | LL | use issue_59764::{makro as foobar, foo::{baz}}; - | + | ^^^^^^^^^^^^^^^^^^^ --^^ error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:121:17 + --> $DIR/issue-59764.rs:120:17 | LL | makro as foobar} | ^^^^^^^^^^^^^^^ no `makro` in `foo` @@ -204,16 +201,16 @@ LL | makro as foobar} = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined help: a macro with this name exists at the root of the crate | -LL | use issue_59764::{makro as foobar, +LL | issue_59764::{makro as foobar, LL | LL | foobaz, LL | LL | LL | foo::{baz} - ... + | error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:128:5 + --> $DIR/issue-59764.rs:127:5 | LL | use issue_59764::foo::makro; | ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` @@ -225,7 +222,7 @@ LL | use issue_59764::makro; | ^^^^^^^^^^^^^^^^^^ error: cannot determine resolution for the macro `makro` - --> $DIR/issue-59764.rs:131:1 + --> $DIR/issue-59764.rs:130:1 | LL | makro!(bar); | ^^^^^ @@ -233,7 +230,7 @@ LL | makro!(bar); = note: import resolution is stuck, try simplifying macro imports error[E0425]: cannot find function `bar` in this scope - --> $DIR/issue-59764.rs:135:5 + --> $DIR/issue-59764.rs:134:5 | LL | bar(); | ^^^ not found in this scope From ca1ab3ed30fc41308b0f14135b293f3d9d89e53f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 12 Apr 2019 12:18:23 +1000 Subject: [PATCH 41/53] In `-Zprint-type-size` output, sort enum variants by size. It's useful to see the biggest variants first. --- src/librustc/session/code_stats.rs | 8 +++++- .../ui/print_type_sizes/multiple_types.stdout | 4 +-- .../ui/print_type_sizes/niche-filling.stdout | 28 +++++++++---------- src/test/ui/print_type_sizes/padding.stdout | 10 +++---- .../ui/print_type_sizes/repr-align.stdout | 4 +-- src/test/ui/print_type_sizes/variants.stdout | 4 +-- 6 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs index 730abacf6f691..0f535249b5e2a 100644 --- a/src/librustc/session/code_stats.rs +++ b/src/librustc/session/code_stats.rs @@ -57,7 +57,13 @@ impl CodeStats { overall_size: Size, packed: bool, opt_discr_size: Option, - variants: Vec) { + mut variants: Vec) { + // Sort variants so the largest ones are shown first. A stable sort is + // used here so that source code order is preserved for all variants + // that have the same size. + variants.sort_by(|info1, info2| { + info2.size.cmp(&info1.size) + }); let info = TypeSizeInfo { kind, type_description: type_desc.to_string(), diff --git a/src/test/ui/print_type_sizes/multiple_types.stdout b/src/test/ui/print_type_sizes/multiple_types.stdout index eed9af26987b4..6411881545843 100644 --- a/src/test/ui/print_type_sizes/multiple_types.stdout +++ b/src/test/ui/print_type_sizes/multiple_types.stdout @@ -1,9 +1,9 @@ print-type-size type: `Enum`: 51 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes -print-type-size variant `Small`: 7 bytes -print-type-size field `.0`: 7 bytes print-type-size variant `Large`: 50 bytes print-type-size field `.0`: 50 bytes +print-type-size variant `Small`: 7 bytes +print-type-size field `.0`: 7 bytes print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes print-type-size field `.0`: 50 bytes print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes diff --git a/src/test/ui/print_type_sizes/niche-filling.stdout b/src/test/ui/print_type_sizes/niche-filling.stdout index 0789c6d7f3486..9cdb2ae4f57e0 100644 --- a/src/test/ui/print_type_sizes/niche-filling.stdout +++ b/src/test/ui/print_type_sizes/niche-filling.stdout @@ -4,15 +4,15 @@ print-type-size field `.post`: 2 bytes print-type-size field `.pre`: 1 bytes print-type-size end padding: 1 bytes print-type-size type: `MyOption`: 12 bytes, alignment: 4 bytes -print-type-size variant `None`: 0 bytes print-type-size variant `Some`: 12 bytes print-type-size field `.0`: 12 bytes -print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes print-type-size variant `None`: 0 bytes +print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes print-type-size variant `Record`: 7 bytes print-type-size field `.val`: 4 bytes print-type-size field `.post`: 2 bytes print-type-size field `.pre`: 1 bytes +print-type-size variant `None`: 0 bytes print-type-size end padding: 1 bytes print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes print-type-size field `.val`: 4 bytes @@ -20,59 +20,59 @@ print-type-size field `.post`: 2 bytes print-type-size field `.pre`: 1 bytes print-type-size end padding: 1 bytes print-type-size type: `Enum4<(), char, (), ()>`: 4 bytes, alignment: 4 bytes -print-type-size variant `One`: 0 bytes -print-type-size field `.0`: 0 bytes print-type-size variant `Two`: 4 bytes print-type-size field `.0`: 4 bytes +print-type-size variant `One`: 0 bytes +print-type-size field `.0`: 0 bytes print-type-size variant `Three`: 0 bytes print-type-size field `.0`: 0 bytes print-type-size variant `Four`: 0 bytes print-type-size field `.0`: 0 bytes print-type-size type: `MyOption`: 4 bytes, alignment: 4 bytes -print-type-size variant `None`: 0 bytes print-type-size variant `Some`: 4 bytes print-type-size field `.0`: 4 bytes -print-type-size type: `MyOption`: 4 bytes, alignment: 4 bytes print-type-size variant `None`: 0 bytes +print-type-size type: `MyOption`: 4 bytes, alignment: 4 bytes print-type-size variant `Some`: 4 bytes print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes print-type-size field `.0`: 4 bytes print-type-size type: `Enum4<(), (), (), MyOption>`: 2 bytes, alignment: 1 bytes +print-type-size variant `Four`: 2 bytes +print-type-size field `.0`: 2 bytes print-type-size variant `One`: 0 bytes print-type-size field `.0`: 0 bytes print-type-size variant `Two`: 0 bytes print-type-size field `.0`: 0 bytes print-type-size variant `Three`: 0 bytes print-type-size field `.0`: 0 bytes -print-type-size variant `Four`: 2 bytes -print-type-size field `.0`: 2 bytes print-type-size type: `MyOption>`: 2 bytes, alignment: 1 bytes -print-type-size variant `None`: 0 bytes print-type-size variant `Some`: 2 bytes print-type-size field `.0`: 2 bytes +print-type-size variant `None`: 0 bytes print-type-size type: `MyOption`: 2 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes -print-type-size variant `None`: 0 bytes print-type-size variant `Some`: 1 bytes print-type-size field `.0`: 1 bytes +print-type-size variant `None`: 0 bytes print-type-size type: `Enum4<(), (), bool, ()>`: 1 bytes, alignment: 1 bytes +print-type-size variant `Three`: 1 bytes +print-type-size field `.0`: 1 bytes print-type-size variant `One`: 0 bytes print-type-size field `.0`: 0 bytes print-type-size variant `Two`: 0 bytes print-type-size field `.0`: 0 bytes -print-type-size variant `Three`: 1 bytes -print-type-size field `.0`: 1 bytes print-type-size variant `Four`: 0 bytes print-type-size field `.0`: 0 bytes print-type-size type: `MyOption`: 1 bytes, alignment: 1 bytes -print-type-size variant `None`: 0 bytes print-type-size variant `Some`: 1 bytes print-type-size field `.0`: 1 bytes -print-type-size type: `MyOption`: 1 bytes, alignment: 1 bytes print-type-size variant `None`: 0 bytes +print-type-size type: `MyOption`: 1 bytes, alignment: 1 bytes print-type-size variant `Some`: 1 bytes print-type-size field `.0`: 1 bytes +print-type-size variant `None`: 0 bytes print-type-size type: `std::cmp::Ordering`: 1 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Less`: 0 bytes diff --git a/src/test/ui/print_type_sizes/padding.stdout b/src/test/ui/print_type_sizes/padding.stdout index 0eaff7118b35c..9afdf76245df7 100644 --- a/src/test/ui/print_type_sizes/padding.stdout +++ b/src/test/ui/print_type_sizes/padding.stdout @@ -1,21 +1,21 @@ print-type-size type: `E1`: 12 bytes, alignment: 4 bytes print-type-size discriminant: 1 bytes +print-type-size variant `B`: 11 bytes +print-type-size padding: 3 bytes +print-type-size field `.0`: 8 bytes, alignment: 4 bytes print-type-size variant `A`: 7 bytes print-type-size field `.1`: 1 bytes print-type-size padding: 2 bytes print-type-size field `.0`: 4 bytes, alignment: 4 bytes +print-type-size type: `E2`: 12 bytes, alignment: 4 bytes +print-type-size discriminant: 1 bytes print-type-size variant `B`: 11 bytes print-type-size padding: 3 bytes print-type-size field `.0`: 8 bytes, alignment: 4 bytes -print-type-size type: `E2`: 12 bytes, alignment: 4 bytes -print-type-size discriminant: 1 bytes print-type-size variant `A`: 7 bytes print-type-size field `.0`: 1 bytes print-type-size padding: 2 bytes print-type-size field `.1`: 4 bytes, alignment: 4 bytes -print-type-size variant `B`: 11 bytes -print-type-size padding: 3 bytes -print-type-size field `.0`: 8 bytes, alignment: 4 bytes print-type-size type: `S`: 8 bytes, alignment: 4 bytes print-type-size field `.g`: 4 bytes print-type-size field `.a`: 1 bytes diff --git a/src/test/ui/print_type_sizes/repr-align.stdout b/src/test/ui/print_type_sizes/repr-align.stdout index 7df12f040b15d..33671bd8e14bc 100644 --- a/src/test/ui/print_type_sizes/repr-align.stdout +++ b/src/test/ui/print_type_sizes/repr-align.stdout @@ -1,10 +1,10 @@ print-type-size type: `E`: 32 bytes, alignment: 16 bytes print-type-size discriminant: 4 bytes -print-type-size variant `A`: 4 bytes -print-type-size field `.0`: 4 bytes print-type-size variant `B`: 28 bytes print-type-size padding: 12 bytes print-type-size field `.0`: 16 bytes, alignment: 16 bytes +print-type-size variant `A`: 4 bytes +print-type-size field `.0`: 4 bytes print-type-size type: `S`: 32 bytes, alignment: 16 bytes print-type-size field `.c`: 16 bytes print-type-size field `.a`: 4 bytes diff --git a/src/test/ui/print_type_sizes/variants.stdout b/src/test/ui/print_type_sizes/variants.stdout index eed9af26987b4..6411881545843 100644 --- a/src/test/ui/print_type_sizes/variants.stdout +++ b/src/test/ui/print_type_sizes/variants.stdout @@ -1,9 +1,9 @@ print-type-size type: `Enum`: 51 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes -print-type-size variant `Small`: 7 bytes -print-type-size field `.0`: 7 bytes print-type-size variant `Large`: 50 bytes print-type-size field `.0`: 50 bytes +print-type-size variant `Small`: 7 bytes +print-type-size field `.0`: 7 bytes print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes print-type-size field `.0`: 50 bytes print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes From 633fc9eef0d26a1c9b59fad8e807632f234a8aae Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 12 Apr 2019 12:30:21 +0200 Subject: [PATCH 42/53] Revert PR #59401 to fix issue #59652 (a stable-to-beta regression). This is result of squashing two revert commits: Revert "compile all crates under test w/ -Zemit-stack-sizes" This reverts commit 7d365cf27f4249fc9b61ba8abfc813abe43f1cb7. Revert "bootstrap: build compiler-builtins with -Z emit-stack-sizes" This reverts commit 8b8488ce8fc047282e7159343f30609417f9fa39. --- src/bootstrap/bin/rustc.rs | 27 --------------------------- src/bootstrap/compile.rs | 4 ---- 2 files changed, 31 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 86ce5fd01a812..a76584093fc76 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -187,33 +187,6 @@ fn main() { cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions)); } - // Build all crates in the `std` facade with `-Z emit-stack-sizes` to add stack usage - // information. - // - // When you use this `-Z` flag with Cargo you get stack usage information on all crates - // compiled from source, and when you are using LTO you also get information on pre-compiled - // crates like `core` and `std`, even if they were not compiled with `-Z emit-stack-sizes`. - // However, there's an exception: `compiler_builtins`. This crate is special and doesn't - // participate in LTO because it's always linked as a separate object file. For this reason - // it's impossible to get stack usage information about `compiler-builtins` using - // `RUSTFLAGS` + Cargo, or `cargo rustc`. - // - // To make the stack usage information of all crates under the `std` facade available to - // Cargo based stack usage analysis tools, in both LTO and non-LTO mode, we compile them - // with the `-Z emit-stack-sizes` flag. The `RUSTC_EMIT_STACK_SIZES` var helps us apply this - // flag only to the crates in the `std` facade. The `-Z` flag is known to currently work - // with targets that produce ELF files so we limit its use flag to those targets. - // - // NOTE(japaric) if this ever causes problem with an LLVM upgrade or any PR feel free to - // remove it or comment it out - if env::var_os("RUSTC_EMIT_STACK_SIZES").is_some() - && (target.contains("-linux-") - || target.contains("-none-eabi") - || target.ends_with("-none-elf")) - { - cmd.arg("-Zemit-stack-sizes"); - } - if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") { cmd.arg("-C").arg(format!("codegen-units={}", s)); } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 08316b71ea85b..66443d472d334 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -97,8 +97,6 @@ impl Step for Std { let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage)); builder.info(&format!("Building stage{} std artifacts ({} -> {})", compiler.stage, &compiler.host, target)); - // compile with `-Z emit-stack-sizes`; see bootstrap/src/rustc.rs for more details - cargo.env("RUSTC_EMIT_STACK_SIZES", "1"); run_cargo(builder, &mut cargo, &libstd_stamp(builder, compiler, target), @@ -397,8 +395,6 @@ impl Step for Test { let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage)); builder.info(&format!("Building stage{} test artifacts ({} -> {})", compiler.stage, &compiler.host, target)); - // compile with `-Z emit-stack-sizes`; see bootstrap/src/rustc.rs for more details - cargo.env("RUSTC_EMIT_STACK_SIZES", "1"); run_cargo(builder, &mut cargo, &libtest_stamp(builder, compiler, target), From 1ce6645d1f6e80325f2c13ae72b879c66d09c644 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 12 Apr 2019 12:41:17 +0200 Subject: [PATCH 43/53] MaybeUninit: remove deprecated functions --- src/libcore/mem.rs | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 66bcf1f7d0101..e887426554701 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -1152,15 +1152,6 @@ impl MaybeUninit { MaybeUninit { uninit: () } } - /// Deprecated before stabilization. - #[unstable(feature = "maybe_uninit", issue = "53491")] - #[inline(always)] - // FIXME: still used by stdsimd - // #[rustc_deprecated(since = "1.35.0", reason = "use `uninit` instead")] - pub const fn uninitialized() -> MaybeUninit { - Self::uninit() - } - /// Creates a new `MaybeUninit` in an uninitialized state, with the memory being /// filled with `0` bytes. It depends on `T` whether that already makes for /// proper initialization. For example, `MaybeUninit::zeroed()` is initialized, @@ -1221,14 +1212,6 @@ impl MaybeUninit { } } - /// Deprecated before stabilization. - #[unstable(feature = "maybe_uninit", issue = "53491")] - #[inline(always)] - #[rustc_deprecated(since = "1.35.0", reason = "use `write` instead")] - pub fn set(&mut self, val: T) -> &mut T { - self.write(val) - } - /// Gets a pointer to the contained value. Reading from this pointer or turning it /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. /// @@ -1346,15 +1329,6 @@ impl MaybeUninit { ManuallyDrop::into_inner(self.value) } - /// Deprecated before stabilization. - #[unstable(feature = "maybe_uninit", issue = "53491")] - #[inline(always)] - // FIXME: still used by stdsimd - // #[rustc_deprecated(since = "1.35.0", reason = "use `assume_init` instead")] - pub unsafe fn into_initialized(self) -> T { - self.assume_init() - } - /// Reads the value from the `MaybeUninit` container. The resulting `T` is subject /// to the usual drop handling. /// @@ -1417,14 +1391,6 @@ impl MaybeUninit { self.as_ptr().read() } - /// Deprecated before stabilization. - #[unstable(feature = "maybe_uninit", issue = "53491")] - #[inline(always)] - #[rustc_deprecated(since = "1.35.0", reason = "use `read` instead")] - pub unsafe fn read_initialized(&self) -> T { - self.read() - } - /// Gets a reference to the contained value. /// /// # Safety From 796e6e37d6fa76b719dbf9b38872daffdc9caa70 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 11 Apr 2019 22:48:53 +0200 Subject: [PATCH 44/53] Don't generate empty json variables --- src/librustdoc/html/render.rs | 19 +++++++++--- src/librustdoc/html/static/source-script.js | 34 ++++++++++++--------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 866d8fe682a7b..3f2eaf8ec5527 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1060,11 +1060,22 @@ themePicker.onblur = handleThemeButtonsBlur; .expect("invalid osstring conversion"))) .collect::>(); files.sort_unstable_by(|a, b| a.cmp(b)); - // FIXME(imperio): we could avoid to generate "dirs" and "files" if they're empty. - format!("{{\"name\":\"{name}\",\"dirs\":[{subs}],\"files\":[{files}]}}", + let subs = subs.iter().map(|s| s.to_json_string()).collect::>().join(","); + let dirs = if subs.is_empty() { + String::new() + } else { + format!(",\"dirs\":[{}]", subs) + }; + let files = files.join(","); + let files = if files.is_empty() { + String::new() + } else { + format!(",\"files\":[{}]", files) + }; + format!("{{\"name\":\"{name}\"{dirs}{files}}}", name=self.elem.to_str().expect("invalid osstring conversion"), - subs=subs.iter().map(|s| s.to_json_string()).collect::>().join(","), - files=files.join(",")) + dirs=dirs, + files=files) } } diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js index 509c628ce5a46..567022b4139ad 100644 --- a/src/librustdoc/html/static/source-script.js +++ b/src/librustdoc/html/static/source-script.js @@ -39,28 +39,32 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) { children.className = "children"; var folders = document.createElement("div"); folders.className = "folders"; - for (var i = 0; i < elem.dirs.length; ++i) { - if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile, - hasFoundFile) === true) { - addClass(name, "expand"); - hasFoundFile = true; + if (elem.dirs) { + for (var i = 0; i < elem.dirs.length; ++i) { + if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile, + hasFoundFile) === true) { + addClass(name, "expand"); + hasFoundFile = true; + } } } children.appendChild(folders); var files = document.createElement("div"); files.className = "files"; - for (i = 0; i < elem.files.length; ++i) { - var file = document.createElement("a"); - file.innerText = elem.files[i]; - file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html"; - if (hasFoundFile === false && - currentFile === fullPath + elem.files[i]) { - file.className = "selected"; - addClass(name, "expand"); - hasFoundFile = true; + if (elem.files) { + for (i = 0; i < elem.files.length; ++i) { + var file = document.createElement("a"); + file.innerText = elem.files[i]; + file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html"; + if (hasFoundFile === false && + currentFile === fullPath + elem.files[i]) { + file.className = "selected"; + addClass(name, "expand"); + hasFoundFile = true; + } + files.appendChild(file); } - files.appendChild(file); } search.fullPath = fullPath; children.appendChild(files); From 4f28431e39fa2abc16703e067bcf9a7e3a0502d4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 7 Apr 2019 18:09:28 +0200 Subject: [PATCH 45/53] Apply resource-suffix to search-index and source-files scripts as well --- src/librustdoc/html/layout.rs | 4 ++-- src/librustdoc/html/render.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 6ff3917a265ed..acf019fd2254d 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -157,11 +157,11 @@ pub fn render( window.rootPath = \"{root_path}\";\ window.currentCrate = \"{krate}\";\ \ - \ + \ \ {static_extra_scripts}\ {extra_scripts}\ - \ + \ \ ", css_extension = if css_file_extension { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 866d8fe682a7b..65922dfb24b2c 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1009,7 +1009,7 @@ themePicker.onblur = handleThemeButtonsBlur; }) } - let dst = cx.dst.join("aliases.js"); + let dst = cx.dst.join(&format!("aliases{}.js", cx.shared.resource_suffix)); { let (mut all_aliases, _, _) = try_err!(collect(&dst, &krate.name, "ALIASES", false), &dst); let mut w = try_err!(File::create(&dst), &dst); @@ -1097,7 +1097,7 @@ themePicker.onblur = handleThemeButtonsBlur; } } - let dst = cx.dst.join("source-files.js"); + let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix)); let (mut all_sources, _krates, _) = try_err!(collect(&dst, &krate.name, "sourcesIndex", false), &dst); @@ -1113,7 +1113,7 @@ themePicker.onblur = handleThemeButtonsBlur; } // Update the search index - let dst = cx.dst.join("search-index.js"); + let dst = cx.dst.join(&format!("search-index{}.js", cx.shared.resource_suffix)); let (mut all_indexes, mut krates, variables) = try_err!(collect(&dst, &krate.name, "searchIndex", @@ -1476,7 +1476,7 @@ impl<'a> SourceCollector<'a> { description: &desc, keywords: BASIC_KEYWORDS, resource_suffix: &self.scx.resource_suffix, - extra_scripts: &["source-files"], + extra_scripts: &[&format!("source-files{}", self.scx.resource_suffix)], static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)], }; layout::render(&mut w, &self.scx.layout, From 7e620529e3f3be464e18173b495222ea90b31ccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 3 Apr 2019 02:43:49 +0200 Subject: [PATCH 46/53] Use a proc macro to declare preallocated symbols --- Cargo.lock | 1 + src/librustc_macros/src/lib.rs | 6 + src/librustc_macros/src/symbols.rs | 173 +++++++++++++++++++++++ src/libsyntax/ast.rs | 6 + src/libsyntax/attr/mod.rs | 21 +++ src/libsyntax/feature_gate.rs | 28 ++-- src/libsyntax_pos/Cargo.toml | 1 + src/libsyntax_pos/lib.rs | 2 + src/libsyntax_pos/symbol.rs | 213 ++++++++++++----------------- 9 files changed, 312 insertions(+), 139 deletions(-) create mode 100644 src/librustc_macros/src/symbols.rs diff --git a/Cargo.lock b/Cargo.lock index 8fd365b8462b7..c57a72d67bfcb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3374,6 +3374,7 @@ dependencies = [ "arena 0.0.0", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", + "rustc_macros 0.1.0", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/librustc_macros/src/lib.rs b/src/librustc_macros/src/lib.rs index e99ceb1b0c79b..98fba55218f9b 100644 --- a/src/librustc_macros/src/lib.rs +++ b/src/librustc_macros/src/lib.rs @@ -9,10 +9,16 @@ use proc_macro::TokenStream; mod hash_stable; mod query; +mod symbols; #[proc_macro] pub fn rustc_queries(input: TokenStream) -> TokenStream { query::rustc_queries(input) } +#[proc_macro] +pub fn symbols(input: TokenStream) -> TokenStream { + symbols::symbols(input) +} + decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive); diff --git a/src/librustc_macros/src/symbols.rs b/src/librustc_macros/src/symbols.rs new file mode 100644 index 0000000000000..e72ab7f84e92a --- /dev/null +++ b/src/librustc_macros/src/symbols.rs @@ -0,0 +1,173 @@ +use proc_macro::TokenStream; +use syn::{ + Token, Ident, LitStr, + braced, parse_macro_input, +}; +use syn::parse::{Result, Parse, ParseStream}; +use syn; +use std::collections::HashSet; +use quote::quote; + +#[allow(non_camel_case_types)] +mod kw { + syn::custom_keyword!(Keywords); + syn::custom_keyword!(Other); +} + +struct Keyword { + name: Ident, + value: LitStr, +} + +impl Parse for Keyword { + fn parse(input: ParseStream<'_>) -> Result { + let name = input.parse()?; + input.parse::()?; + let value = input.parse()?; + input.parse::()?; + + Ok(Keyword { + name, + value, + }) + } +} + +struct Symbol(Ident); + +impl Parse for Symbol { + fn parse(input: ParseStream<'_>) -> Result { + let ident: Ident = input.parse()?; + input.parse::()?; + + Ok(Symbol(ident)) + } +} + +/// A type used to greedily parse another type until the input is empty. +struct List(Vec); + +impl Parse for List { + fn parse(input: ParseStream<'_>) -> Result { + let mut list = Vec::new(); + while !input.is_empty() { + list.push(input.parse()?); + } + Ok(List(list)) + } +} + +struct Input { + keywords: List, + symbols: List, +} + +impl Parse for Input { + fn parse(input: ParseStream<'_>) -> Result { + input.parse::()?; + let content; + braced!(content in input); + let keywords = content.parse()?; + + input.parse::()?; + let content; + braced!(content in input); + let symbols = content.parse()?; + + Ok(Input { + keywords, + symbols, + }) + } +} + +pub fn symbols(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as Input); + + let mut keyword_stream = quote! {}; + let mut symbols_stream = quote! {}; + let mut prefill_stream = quote! {}; + let mut from_str_stream = quote! {}; + let mut counter = 0u32; + let mut keys = HashSet::::new(); + + let mut check_dup = |str: &str| { + if !keys.insert(str.to_string()) { + panic!("Symbol `{}` is duplicated", str); + } + }; + + for keyword in &input.keywords.0 { + let name = &keyword.name; + let value = &keyword.value; + check_dup(&value.value()); + prefill_stream.extend(quote! { + #value, + }); + keyword_stream.extend(quote! { + pub const #name: Keyword = Keyword { + ident: Ident::with_empty_ctxt(super::Symbol::new(#counter)) + }; + }); + from_str_stream.extend(quote! { + #value => Ok(#name), + }); + counter += 1; + } + + for symbol in &input.symbols.0 { + let value = &symbol.0; + let value_str = value.to_string(); + check_dup(&value_str); + prefill_stream.extend(quote! { + #value_str, + }); + symbols_stream.extend(quote! { + pub const #value: Symbol = Symbol::new(#counter); + }); + counter += 1; + } + + TokenStream::from(quote! { + #[allow(non_upper_case_globals)] + pub mod keywords { + use super::{Symbol, Ident}; + #[derive(Clone, Copy, PartialEq, Eq)] + pub struct Keyword { + ident: Ident, + } + impl Keyword { + #[inline] pub fn ident(self) -> Ident { self.ident } + #[inline] pub fn name(self) -> Symbol { self.ident.name } + } + + #keyword_stream + + impl std::str::FromStr for Keyword { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + #from_str_stream + _ => Err(()), + } + } + } + } + + #[allow(non_upper_case_globals)] + pub mod symbols { + use super::Symbol; + + #symbols_stream + } + + impl Interner { + pub fn fresh() -> Self { + Interner::prefill(&[ + #prefill_stream + ]) + } + } + }) +} diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index bcc8fdf8cd4e7..735b4ef4a3e52 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -68,6 +68,12 @@ pub struct Path { pub segments: Vec, } +impl PartialEq for Path { + fn eq(&self, symbol: &Symbol) -> bool { + self.segments.len() == 1 && self.segments[0].ident.name.interned() == *symbol + } +} + impl<'a> PartialEq<&'a str> for Path { fn eq(&self, string: &&'a str) -> bool { self.segments.len() == 1 && self.segments[0].ident.name == *string diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index c0bd5c79b1dd1..f34bbc9f35dad 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -85,6 +85,11 @@ impl NestedMetaItem { self.meta_item().map_or(false, |meta_item| meta_item.check_name(name)) } + /// Returns `true` if this list item is a MetaItem with a name of `name`. + pub fn check_name_symbol(&self, name: Symbol) -> bool { + self.meta_item().map_or(false, |meta_item| meta_item.check_name_symbol(name)) + } + /// For a single-segment meta-item returns its name, otherwise returns `None`. pub fn ident(&self) -> Option { self.meta_item().and_then(|meta_item| meta_item.ident()) @@ -159,6 +164,18 @@ impl Attribute { matches } + /// Returns `true` if the attribute's path matches the argument. If it matches, then the + /// attribute is marked as used. + /// + /// To check the attribute name without marking it used, use the `path` field directly. + pub fn check_name_symbol(&self, name: Symbol) -> bool { + let matches = self.path == name; + if matches { + mark_used(self); + } + matches + } + /// For a single-segment attribute returns its name, otherwise returns `None`. pub fn ident(&self) -> Option { if self.path.segments.len() == 1 { @@ -248,6 +265,10 @@ impl MetaItem { self.path == name } + pub fn check_name_symbol(&self, name: Symbol) -> bool { + self.path == name + } + pub fn is_value_str(&self) -> bool { self.value_str().is_some() } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index dcb55fb572f33..9f655c4158008 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -28,7 +28,7 @@ use crate::tokenstream::TokenTree; use errors::{DiagnosticBuilder, Handler}; use rustc_data_structures::fx::FxHashMap; use rustc_target::spec::abi::Abi; -use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::{Span, DUMMY_SP, symbols}; use log::debug; use std::env; @@ -1366,7 +1366,7 @@ impl<'a> Context<'a> { } } else if n == "doc" { if let Some(content) = attr.meta_item_list() { - if content.iter().any(|c| c.check_name("include")) { + if content.iter().any(|c| c.check_name_symbol(symbols::include)) { gate_feature!(self, external_doc, attr.span, "#[doc(include = \"...\")] is experimental" ); @@ -1648,25 +1648,25 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { // check for gated attributes self.context.check_attribute(attr, false); - if attr.check_name("doc") { + if attr.check_name_symbol(symbols::doc) { if let Some(content) = attr.meta_item_list() { - if content.len() == 1 && content[0].check_name("cfg") { + if content.len() == 1 && content[0].check_name_symbol(symbols::cfg) { gate_feature_post!(&self, doc_cfg, attr.span, "#[doc(cfg(...))] is experimental" ); - } else if content.iter().any(|c| c.check_name("masked")) { + } else if content.iter().any(|c| c.check_name_symbol(symbols::masked)) { gate_feature_post!(&self, doc_masked, attr.span, "#[doc(masked)] is experimental" ); - } else if content.iter().any(|c| c.check_name("spotlight")) { + } else if content.iter().any(|c| c.check_name_symbol(symbols::spotlight)) { gate_feature_post!(&self, doc_spotlight, attr.span, "#[doc(spotlight)] is experimental" ); - } else if content.iter().any(|c| c.check_name("alias")) { + } else if content.iter().any(|c| c.check_name_symbol(symbols::alias)) { gate_feature_post!(&self, doc_alias, attr.span, "#[doc(alias = \"...\")] is experimental" ); - } else if content.iter().any(|c| c.check_name("keyword")) { + } else if content.iter().any(|c| c.check_name_symbol(symbols::keyword)) { gate_feature_post!(&self, doc_keyword, attr.span, "#[doc(keyword = \"...\")] is experimental" ); @@ -1674,7 +1674,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - match BUILTIN_ATTRIBUTES.iter().find(|(name, ..)| attr.path == name) { + match BUILTIN_ATTRIBUTES.iter().find(|(name, ..)| attr.path == *name) { Some(&(name, _, template, _)) => self.check_builtin_attribute(attr, name, template), None => if let Some(TokenTree::Token(_, token::Eq)) = attr.tokens.trees().next() { // All key-value attributes are restricted to meta-item syntax. @@ -1727,7 +1727,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::Struct(..) => { for attr in attr::filter_by_name(&i.attrs[..], "repr") { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { - if item.check_name("simd") { + if item.check_name_symbol(symbols::simd) { gate_feature_post!(&self, repr_simd, attr.span, "SIMD types are experimental and possibly buggy"); } @@ -1738,7 +1738,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::Enum(..) => { for attr in attr::filter_by_name(&i.attrs[..], "repr") { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { - if item.check_name("align") { + if item.check_name_symbol(symbols::align) { gate_feature_post!(&self, repr_align_enum, attr.span, "`#[repr(align(x))]` on enums is experimental"); } @@ -2062,7 +2062,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], // Process the edition umbrella feature-gates first, to ensure // `edition_enabled_features` is completed before it's queried. for attr in krate_attrs { - if !attr.check_name("feature") { + if !attr.check_name_symbol(symbols::feature) { continue } @@ -2107,7 +2107,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } for attr in krate_attrs { - if !attr.check_name("feature") { + if !attr.check_name_symbol(symbols::feature) { continue } @@ -2237,7 +2237,7 @@ fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, }; if !allow_features { for attr in &krate.attrs { - if attr.check_name("feature") { + if attr.check_name_symbol(symbols::feature) { let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"); span_err!(span_handler, attr.span, E0554, "#![feature] may not be used on the {} release channel", diff --git a/src/libsyntax_pos/Cargo.toml b/src/libsyntax_pos/Cargo.toml index 691abffbbc1af..af7edc0a6bd3e 100644 --- a/src/libsyntax_pos/Cargo.toml +++ b/src/libsyntax_pos/Cargo.toml @@ -11,6 +11,7 @@ crate-type = ["dylib"] [dependencies] serialize = { path = "../libserialize" } +rustc_macros = { path = "../librustc_macros" } rustc_data_structures = { path = "../librustc_data_structures" } arena = { path = "../libarena" } scoped-tls = "1.0" diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index db1543ff13f7e..da857abe66e23 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -16,6 +16,7 @@ #![feature(non_exhaustive)] #![feature(optin_builtin_traits)] #![feature(rustc_attrs)] +#![feature(proc_macro_hygiene)] #![feature(specialization)] #![feature(step_trait)] @@ -32,6 +33,7 @@ mod span_encoding; pub use span_encoding::{Span, DUMMY_SP}; pub mod symbol; +pub use symbol::symbols; mod analyze_source_file; diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 393f52e7de517..0b00d4f9a54b1 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -6,6 +6,7 @@ use arena::DroplessArena; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::newtype_index; +use rustc_macros::symbols; use serialize::{Decodable, Decoder, Encodable, Encoder}; use std::fmt; @@ -16,6 +17,93 @@ use std::hash::{Hash, Hasher}; use crate::hygiene::SyntaxContext; use crate::{Span, DUMMY_SP, GLOBALS}; +symbols! { + // After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`, + // this should be rarely necessary though if the keywords are kept in alphabetic order. + Keywords { + // Special reserved identifiers used internally for elided lifetimes, + // unnamed method parameters, crate root module, error recovery etc. + Invalid, "", + PathRoot, "{{root}}", + DollarCrate, "$crate", + Underscore, "_", + + // Keywords that are used in stable Rust. + As, "as", + Box, "box", + Break, "break", + Const, "const", + Continue, "continue", + Crate, "crate", + Else, "else", + Enum, "enum", + Extern, "extern", + False, "false", + Fn, "fn", + For, "for", + If, "if", + Impl, "impl", + In, "in", + Let, "let", + Loop, "loop", + Match, "match", + Mod, "mod", + Move, "move", + Mut, "mut", + Pub, "pub", + Ref, "ref", + Return, "return", + SelfLower, "self", + SelfUpper, "Self", + Static, "static", + Struct, "struct", + Super, "super", + Trait, "trait", + True, "true", + Type, "type", + Unsafe, "unsafe", + Use, "use", + Where, "where", + While, "while", + + // Keywords that are used in unstable Rust or reserved for future use. + Abstract, "abstract", + Become, "become", + Do, "do", + Final, "final", + Macro, "macro", + Override, "override", + Priv, "priv", + Typeof, "typeof", + Unsized, "unsized", + Virtual, "virtual", + Yield, "yield", + + // Edition-specific keywords that are used in stable Rust. + Dyn, "dyn", // >= 2018 Edition only + + // Edition-specific keywords that are used in unstable Rust or reserved for future use. + Async, "async", // >= 2018 Edition only + Try, "try", // >= 2018 Edition only + + // Special lifetime names + UnderscoreLifetime, "'_", + StaticLifetime, "'static", + + // Weak keywords, have special meaning only in specific contexts. + Auto, "auto", + Catch, "catch", + Default, "default", + Existential, "existential", + Union, "union", + } + + // Other symbols that can be referred to with syntax_pos::symbols::* + Other { + doc, cfg, masked, spotlight, alias, keyword, feature, include, simd, align, + } +} + #[derive(Copy, Clone, Eq)] pub struct Ident { pub name: Symbol, @@ -317,131 +405,6 @@ impl Interner { } } -// In this macro, there is the requirement that the name (the number) must be monotonically -// increasing by one in the special identifiers, starting at 0; the same holds for the keywords, -// except starting from the next number instead of zero. -macro_rules! declare_keywords {( - $( ($index: expr, $konst: ident, $string: expr) )* -) => { - pub mod keywords { - use super::{Symbol, Ident}; - #[derive(Clone, Copy, PartialEq, Eq)] - pub struct Keyword { - ident: Ident, - } - impl Keyword { - #[inline] pub fn ident(self) -> Ident { self.ident } - #[inline] pub fn name(self) -> Symbol { self.ident.name } - } - $( - #[allow(non_upper_case_globals)] - pub const $konst: Keyword = Keyword { - ident: Ident::with_empty_ctxt(super::Symbol::new($index)) - }; - )* - - impl std::str::FromStr for Keyword { - type Err = (); - - fn from_str(s: &str) -> Result { - match s { - $($string => Ok($konst),)* - _ => Err(()), - } - } - } - } - - impl Interner { - pub fn fresh() -> Self { - Interner::prefill(&[$($string,)*]) - } - } -}} - -// N.B., leaving holes in the ident table is bad! a different ident will get -// interned with the id from the hole, but it will be between the min and max -// of the reserved words, and thus tagged as "reserved". -// After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`, -// this should be rarely necessary though if the keywords are kept in alphabetic order. -declare_keywords! { - // Special reserved identifiers used internally for elided lifetimes, - // unnamed method parameters, crate root module, error recovery etc. - (0, Invalid, "") - (1, PathRoot, "{{root}}") - (2, DollarCrate, "$crate") - (3, Underscore, "_") - - // Keywords that are used in stable Rust. - (4, As, "as") - (5, Box, "box") - (6, Break, "break") - (7, Const, "const") - (8, Continue, "continue") - (9, Crate, "crate") - (10, Else, "else") - (11, Enum, "enum") - (12, Extern, "extern") - (13, False, "false") - (14, Fn, "fn") - (15, For, "for") - (16, If, "if") - (17, Impl, "impl") - (18, In, "in") - (19, Let, "let") - (20, Loop, "loop") - (21, Match, "match") - (22, Mod, "mod") - (23, Move, "move") - (24, Mut, "mut") - (25, Pub, "pub") - (26, Ref, "ref") - (27, Return, "return") - (28, SelfLower, "self") - (29, SelfUpper, "Self") - (30, Static, "static") - (31, Struct, "struct") - (32, Super, "super") - (33, Trait, "trait") - (34, True, "true") - (35, Type, "type") - (36, Unsafe, "unsafe") - (37, Use, "use") - (38, Where, "where") - (39, While, "while") - - // Keywords that are used in unstable Rust or reserved for future use. - (40, Abstract, "abstract") - (41, Become, "become") - (42, Do, "do") - (43, Final, "final") - (44, Macro, "macro") - (45, Override, "override") - (46, Priv, "priv") - (47, Typeof, "typeof") - (48, Unsized, "unsized") - (49, Virtual, "virtual") - (50, Yield, "yield") - - // Edition-specific keywords that are used in stable Rust. - (51, Dyn, "dyn") // >= 2018 Edition only - - // Edition-specific keywords that are used in unstable Rust or reserved for future use. - (52, Async, "async") // >= 2018 Edition only - (53, Try, "try") // >= 2018 Edition only - - // Special lifetime names - (54, UnderscoreLifetime, "'_") - (55, StaticLifetime, "'static") - - // Weak keywords, have special meaning only in specific contexts. - (56, Auto, "auto") - (57, Catch, "catch") - (58, Default, "default") - (59, Existential, "existential") - (60, Union, "union") -} - impl Symbol { fn is_used_keyword_2018(self) -> bool { self == keywords::Dyn.name() From 0e26063b5b06056f4dc985e501a18da84db6bfbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 5 Apr 2019 03:05:30 +0200 Subject: [PATCH 47/53] Make check_name generic --- src/librustc/middle/lib_features.rs | 6 ++-- .../persist/dirty_clean.rs | 2 +- src/librustc_lint/unused.rs | 2 +- src/libsyntax/attr/mod.rs | 36 +++++++------------ src/libsyntax/feature_gate.rs | 24 ++++++------- src/libsyntax_ext/proc_macro_decls.rs | 2 +- src/libsyntax_pos/symbol.rs | 3 +- 7 files changed, 32 insertions(+), 43 deletions(-) diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs index ee8dd9e58b5ff..e79ef8bfc6fb4 100644 --- a/src/librustc/middle/lib_features.rs +++ b/src/librustc/middle/lib_features.rs @@ -8,7 +8,7 @@ use crate::ty::TyCtxt; use crate::hir::intravisit::{self, NestedVisitorMap, Visitor}; use syntax::symbol::Symbol; use syntax::ast::{Attribute, MetaItem, MetaItemKind}; -use syntax_pos::Span; +use syntax_pos::{Span, symbols}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_macros::HashStable; use errors::DiagnosticId; @@ -51,12 +51,12 @@ impl<'a, 'tcx> LibFeatureCollector<'a, 'tcx> { } fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option, Span)> { - let stab_attrs = vec!["stable", "unstable", "rustc_const_unstable"]; + let stab_attrs = [symbols::stable, symbols::unstable, symbols::rustc_const_unstable]; // Find a stability attribute (i.e., `#[stable (..)]`, `#[unstable (..)]`, // `#[rustc_const_unstable (..)]`). if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| { - attr.check_name(stab_attr) + attr.check_name(**stab_attr) }) { let meta_item = attr.meta(); if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta_item { diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 5c4fd9dba7af4..6f5b411946c2d 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -599,7 +599,7 @@ impl<'a, 'tcx> FindAllAttrs<'a, 'tcx> { fn is_active_attr(&mut self, attr: &Attribute) -> bool { for attr_name in &self.attr_names { - if attr.check_name(attr_name) && check_config(self.tcx, attr) { + if attr.check_name(*attr_name) && check_config(self.tcx, attr) { return true; } } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index d41d97f58bcbe..2aee21abb58e5 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -228,7 +228,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { let plugin_attributes = cx.sess().plugin_attributes.borrow_mut(); for &(ref name, ty) in plugin_attributes.iter() { - if ty == AttributeType::Whitelisted && attr.check_name(&name) { + if ty == AttributeType::Whitelisted && attr.check_name(&**name) { debug!("{:?} (plugin attr) is whitelisted with ty {:?}", name, ty); break; } diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index f34bbc9f35dad..e00f91e395280 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -81,15 +81,13 @@ impl NestedMetaItem { } /// Returns `true` if this list item is a MetaItem with a name of `name`. - pub fn check_name(&self, name: &str) -> bool { + pub fn check_name(&self, name: T) -> bool + where + Path: PartialEq, + { self.meta_item().map_or(false, |meta_item| meta_item.check_name(name)) } - /// Returns `true` if this list item is a MetaItem with a name of `name`. - pub fn check_name_symbol(&self, name: Symbol) -> bool { - self.meta_item().map_or(false, |meta_item| meta_item.check_name_symbol(name)) - } - /// For a single-segment meta-item returns its name, otherwise returns `None`. pub fn ident(&self) -> Option { self.meta_item().and_then(|meta_item| meta_item.ident()) @@ -156,19 +154,10 @@ impl Attribute { /// attribute is marked as used. /// /// To check the attribute name without marking it used, use the `path` field directly. - pub fn check_name(&self, name: &str) -> bool { - let matches = self.path == name; - if matches { - mark_used(self); - } - matches - } - - /// Returns `true` if the attribute's path matches the argument. If it matches, then the - /// attribute is marked as used. - /// - /// To check the attribute name without marking it used, use the `path` field directly. - pub fn check_name_symbol(&self, name: Symbol) -> bool { + pub fn check_name(&self, name: T) -> bool + where + Path: PartialEq, + { let matches = self.path == name; if matches { mark_used(self); @@ -261,11 +250,10 @@ impl MetaItem { } } - pub fn check_name(&self, name: &str) -> bool { - self.path == name - } - - pub fn check_name_symbol(&self, name: Symbol) -> bool { + pub fn check_name(&self, name: T) -> bool + where + Path: PartialEq, + { self.path == name } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9f655c4158008..80aeb31337d50 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1366,7 +1366,7 @@ impl<'a> Context<'a> { } } else if n == "doc" { if let Some(content) = attr.meta_item_list() { - if content.iter().any(|c| c.check_name_symbol(symbols::include)) { + if content.iter().any(|c| c.check_name(symbols::include)) { gate_feature!(self, external_doc, attr.span, "#[doc(include = \"...\")] is experimental" ); @@ -1648,25 +1648,25 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { // check for gated attributes self.context.check_attribute(attr, false); - if attr.check_name_symbol(symbols::doc) { + if attr.check_name(symbols::doc) { if let Some(content) = attr.meta_item_list() { - if content.len() == 1 && content[0].check_name_symbol(symbols::cfg) { + if content.len() == 1 && content[0].check_name(symbols::cfg) { gate_feature_post!(&self, doc_cfg, attr.span, "#[doc(cfg(...))] is experimental" ); - } else if content.iter().any(|c| c.check_name_symbol(symbols::masked)) { + } else if content.iter().any(|c| c.check_name(symbols::masked)) { gate_feature_post!(&self, doc_masked, attr.span, "#[doc(masked)] is experimental" ); - } else if content.iter().any(|c| c.check_name_symbol(symbols::spotlight)) { + } else if content.iter().any(|c| c.check_name(symbols::spotlight)) { gate_feature_post!(&self, doc_spotlight, attr.span, "#[doc(spotlight)] is experimental" ); - } else if content.iter().any(|c| c.check_name_symbol(symbols::alias)) { + } else if content.iter().any(|c| c.check_name(symbols::alias)) { gate_feature_post!(&self, doc_alias, attr.span, "#[doc(alias = \"...\")] is experimental" ); - } else if content.iter().any(|c| c.check_name_symbol(symbols::keyword)) { + } else if content.iter().any(|c| c.check_name(symbols::keyword)) { gate_feature_post!(&self, doc_keyword, attr.span, "#[doc(keyword = \"...\")] is experimental" ); @@ -1727,7 +1727,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::Struct(..) => { for attr in attr::filter_by_name(&i.attrs[..], "repr") { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { - if item.check_name_symbol(symbols::simd) { + if item.check_name(symbols::simd) { gate_feature_post!(&self, repr_simd, attr.span, "SIMD types are experimental and possibly buggy"); } @@ -1738,7 +1738,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::Enum(..) => { for attr in attr::filter_by_name(&i.attrs[..], "repr") { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { - if item.check_name_symbol(symbols::align) { + if item.check_name(symbols::align) { gate_feature_post!(&self, repr_align_enum, attr.span, "`#[repr(align(x))]` on enums is experimental"); } @@ -2062,7 +2062,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], // Process the edition umbrella feature-gates first, to ensure // `edition_enabled_features` is completed before it's queried. for attr in krate_attrs { - if !attr.check_name_symbol(symbols::feature) { + if !attr.check_name(symbols::feature) { continue } @@ -2107,7 +2107,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } for attr in krate_attrs { - if !attr.check_name_symbol(symbols::feature) { + if !attr.check_name(symbols::feature) { continue } @@ -2237,7 +2237,7 @@ fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, }; if !allow_features { for attr in &krate.attrs { - if attr.check_name_symbol(symbols::feature) { + if attr.check_name(symbols::feature) { let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"); span_err!(span_handler, attr.span, E0554, "#![feature] may not be used on the {} release channel", diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index 22fee902aea26..f0390ba3d40cb 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -87,7 +87,7 @@ pub fn modify(sess: &ParseSess, } pub fn is_proc_macro_attr(attr: &ast::Attribute) -> bool { - PROC_MACRO_KINDS.iter().any(|kind| attr.check_name(kind)) + PROC_MACRO_KINDS.iter().any(|kind| attr.check_name(*kind)) } impl<'a> CollectProcMacros<'a> { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 0b00d4f9a54b1..f1f4c4d3598bc 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -100,7 +100,8 @@ symbols! { // Other symbols that can be referred to with syntax_pos::symbols::* Other { - doc, cfg, masked, spotlight, alias, keyword, feature, include, simd, align, + doc, cfg, masked, spotlight, alias, keyword, feature, include, simd, align, stable, + unstable, rustc_const_unstable, } } From 9c63475f22de85af443285c124af8244089589b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 9 Apr 2019 09:18:49 +0200 Subject: [PATCH 48/53] Ensure the symbols are pure strings --- src/libsyntax/ast.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 735b4ef4a3e52..ed207a1692a43 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -70,7 +70,13 @@ pub struct Path { impl PartialEq for Path { fn eq(&self, symbol: &Symbol) -> bool { - self.segments.len() == 1 && self.segments[0].ident.name.interned() == *symbol + self.segments.len() == 1 && { + let name = self.segments[0].ident.name; + // Make sure these symbols are pure strings + debug_assert!(!symbol.is_gensymed()); + debug_assert!(!name.is_gensymed()); + name == *symbol + } } } From 856c8a094607fc8fd6d0c95a428f08f8a43cbb27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 9 Apr 2019 09:36:17 +0200 Subject: [PATCH 49/53] Move modules outside the proc macro --- src/librustc_macros/src/symbols.rs | 42 ++++++++++++------------------ src/libsyntax_pos/symbol.rs | 28 ++++++++++++++++++++ 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/src/librustc_macros/src/symbols.rs b/src/librustc_macros/src/symbols.rs index e72ab7f84e92a..15f4d988a1f65 100644 --- a/src/librustc_macros/src/symbols.rs +++ b/src/librustc_macros/src/symbols.rs @@ -129,37 +129,27 @@ pub fn symbols(input: TokenStream) -> TokenStream { } TokenStream::from(quote! { - #[allow(non_upper_case_globals)] - pub mod keywords { - use super::{Symbol, Ident}; - #[derive(Clone, Copy, PartialEq, Eq)] - pub struct Keyword { - ident: Ident, - } - impl Keyword { - #[inline] pub fn ident(self) -> Ident { self.ident } - #[inline] pub fn name(self) -> Symbol { self.ident.name } - } - - #keyword_stream - - impl std::str::FromStr for Keyword { - type Err = (); - - fn from_str(s: &str) -> Result { - match s { - #from_str_stream - _ => Err(()), + macro_rules! keywords { + () => { + #keyword_stream + + impl std::str::FromStr for Keyword { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + #from_str_stream + _ => Err(()), + } } } } } - #[allow(non_upper_case_globals)] - pub mod symbols { - use super::Symbol; - - #symbols_stream + macro_rules! symbols { + () => { + #symbols_stream + } } impl Interner { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index f1f4c4d3598bc..5b366d0a1e65c 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -406,6 +406,34 @@ impl Interner { } } +pub mod keywords { + use super::{Symbol, Ident}; + + #[derive(Clone, Copy, PartialEq, Eq)] + pub struct Keyword { + ident: Ident, + } + + impl Keyword { + #[inline] + pub fn ident(self) -> Ident { + self.ident + } + + #[inline] + pub fn name(self) -> Symbol { + self.ident.name + } + } + + keywords!(); +} + +pub mod symbols { + use super::Symbol; + symbols!(); +} + impl Symbol { fn is_used_keyword_2018(self) -> bool { self == keywords::Dyn.name() From b5f246aa70eb029a95b977fc51c5b74d66748a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 9 Apr 2019 09:39:48 +0200 Subject: [PATCH 50/53] Use colon for keyword defs --- src/librustc_macros/src/symbols.rs | 2 +- src/libsyntax_pos/symbol.rs | 122 ++++++++++++++--------------- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/src/librustc_macros/src/symbols.rs b/src/librustc_macros/src/symbols.rs index 15f4d988a1f65..169c5e1371833 100644 --- a/src/librustc_macros/src/symbols.rs +++ b/src/librustc_macros/src/symbols.rs @@ -22,7 +22,7 @@ struct Keyword { impl Parse for Keyword { fn parse(input: ParseStream<'_>) -> Result { let name = input.parse()?; - input.parse::()?; + input.parse::()?; let value = input.parse()?; input.parse::()?; diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 5b366d0a1e65c..64dbb500d2e32 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -23,79 +23,79 @@ symbols! { Keywords { // Special reserved identifiers used internally for elided lifetimes, // unnamed method parameters, crate root module, error recovery etc. - Invalid, "", - PathRoot, "{{root}}", - DollarCrate, "$crate", - Underscore, "_", + Invalid: "", + PathRoot: "{{root}}", + DollarCrate: "$crate", + Underscore: "_", // Keywords that are used in stable Rust. - As, "as", - Box, "box", - Break, "break", - Const, "const", - Continue, "continue", - Crate, "crate", - Else, "else", - Enum, "enum", - Extern, "extern", - False, "false", - Fn, "fn", - For, "for", - If, "if", - Impl, "impl", - In, "in", - Let, "let", - Loop, "loop", - Match, "match", - Mod, "mod", - Move, "move", - Mut, "mut", - Pub, "pub", - Ref, "ref", - Return, "return", - SelfLower, "self", - SelfUpper, "Self", - Static, "static", - Struct, "struct", - Super, "super", - Trait, "trait", - True, "true", - Type, "type", - Unsafe, "unsafe", - Use, "use", - Where, "where", - While, "while", + As: "as", + Box: "box", + Break: "break", + Const: "const", + Continue: "continue", + Crate: "crate", + Else: "else", + Enum: "enum", + Extern: "extern", + False: "false", + Fn: "fn", + For: "for", + If: "if", + Impl: "impl", + In: "in", + Let: "let", + Loop: "loop", + Match: "match", + Mod: "mod", + Move: "move", + Mut: "mut", + Pub: "pub", + Ref: "ref", + Return: "return", + SelfLower: "self", + SelfUpper: "Self", + Static: "static", + Struct: "struct", + Super: "super", + Trait: "trait", + True: "true", + Type: "type", + Unsafe: "unsafe", + Use: "use", + Where: "where", + While: "while", // Keywords that are used in unstable Rust or reserved for future use. - Abstract, "abstract", - Become, "become", - Do, "do", - Final, "final", - Macro, "macro", - Override, "override", - Priv, "priv", - Typeof, "typeof", - Unsized, "unsized", - Virtual, "virtual", - Yield, "yield", + Abstract: "abstract", + Become: "become", + Do: "do", + Final: "final", + Macro: "macro", + Override: "override", + Priv: "priv", + Typeof: "typeof", + Unsized: "unsized", + Virtual: "virtual", + Yield: "yield", // Edition-specific keywords that are used in stable Rust. - Dyn, "dyn", // >= 2018 Edition only + Dyn: "dyn", // >= 2018 Edition only // Edition-specific keywords that are used in unstable Rust or reserved for future use. - Async, "async", // >= 2018 Edition only - Try, "try", // >= 2018 Edition only + Async: "async", // >= 2018 Edition only + Try: "try", // >= 2018 Edition only // Special lifetime names - UnderscoreLifetime, "'_", - StaticLifetime, "'static", + UnderscoreLifetime: "'_", + StaticLifetime: "'static", // Weak keywords, have special meaning only in specific contexts. - Auto, "auto", - Catch, "catch", - Default, "default", - Existential, "existential", - Union, "union", + Auto: "auto", + Catch: "catch", + Default: "default", + Existential: "existential", + Union: "union", } // Other symbols that can be referred to with syntax_pos::symbols::* From fc928a18bad0b6aa275a6908351b164f6f4abcd6 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 3 Apr 2019 19:50:28 +0200 Subject: [PATCH 51/53] Stabilize the `alloc` crate. This implements RFC 2480: * https://github.com/rust-lang/rfcs/pull/2480 * https://github.com/rust-lang/rfcs/blob/master/text/2480-liballoc.md Closes https://github.com/rust-lang/rust/issues/27783 --- src/liballoc/lib.rs | 5 +---- src/liballoc/prelude/mod.rs | 1 - src/liballoc/raw_vec.rs | 4 ++-- src/libarena/lib.rs | 1 - src/libpanic_unwind/lib.rs | 2 -- src/libstd/lib.rs | 1 - .../run-make-fulldeps/sysroot-crates-are-unstable/test.py | 4 ++-- src/test/run-pass/array-slice-vec/vec-macro-no-std.rs | 2 +- src/test/run-pass/extern/extern-prelude-core.rs | 2 +- src/test/run-pass/extern/extern-prelude-core.stderr | 2 +- src/test/run-pass/for-loop-while/for-loop-no-std.rs | 2 +- src/test/run-pass/format-no-std.rs | 2 +- .../run-pass/structs-enums/unit-like-struct-drop-run.rs | 3 --- src/test/ui/allocator-submodule.rs | 2 -- src/test/ui/allocator-submodule.stderr | 2 +- src/test/ui/error-codes/E0254.rs | 1 - src/test/ui/error-codes/E0254.stderr | 2 +- src/test/ui/error-codes/E0259.rs | 2 +- src/test/ui/error-codes/E0260.rs | 1 - src/test/ui/error-codes/E0260.stderr | 2 +- src/test/ui/missing/missing-alloc_error_handler.rs | 2 +- src/test/ui/missing/missing-allocator.rs | 2 +- src/test/ui/resolve_self_super_hint.rs | 1 - src/test/ui/resolve_self_super_hint.stderr | 8 ++++---- src/test/ui/rust-2018/remove-extern-crate.fixed | 1 - src/test/ui/rust-2018/remove-extern-crate.rs | 1 - src/test/ui/rust-2018/remove-extern-crate.stderr | 8 ++++---- src/test/ui/unnecessary-extern-crate.rs | 2 +- 28 files changed, 25 insertions(+), 43 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 90ff56814fbb1..9129ce61d8c82 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -51,10 +51,7 @@ //! default global allocator. It is not compatible with the libc allocator API. #![allow(unused_attributes)] -#![unstable(feature = "alloc", - reason = "this library is unlikely to be stabilized in its current \ - form or name", - issue = "27783")] +#![stable(feature = "alloc", since = "1.36.0")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] diff --git a/src/liballoc/prelude/mod.rs b/src/liballoc/prelude/mod.rs index 33cc51d173203..0534ad3edc79d 100644 --- a/src/liballoc/prelude/mod.rs +++ b/src/liballoc/prelude/mod.rs @@ -5,7 +5,6 @@ //! //! ``` //! # #![allow(unused_imports)] -//! # #![feature(alloc)] //! #![feature(alloc_prelude)] //! extern crate alloc; //! use alloc::prelude::v1::*; diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index fe28fe5095cce..d1fc5ac3b30d4 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -256,7 +256,7 @@ impl RawVec { /// # Examples /// /// ``` - /// # #![feature(alloc, raw_vec_internals)] + /// # #![feature(raw_vec_internals)] /// # extern crate alloc; /// # use std::ptr; /// # use alloc::raw_vec::RawVec; @@ -460,7 +460,7 @@ impl RawVec { /// # Examples /// /// ``` - /// # #![feature(alloc, raw_vec_internals)] + /// # #![feature(raw_vec_internals)] /// # extern crate alloc; /// # use std::ptr; /// # use alloc::raw_vec::RawVec; diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 0a5b79c36aad8..f2913295bdce3 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -13,7 +13,6 @@ #![deny(rust_2018_idioms)] -#![feature(alloc)] #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] #![feature(raw_vec_internals)] diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 9d3d8f6185bb3..72ddafb420ce7 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -19,8 +19,6 @@ #![deny(rust_2018_idioms)] -#![feature(allocator_api)] -#![feature(alloc)] #![feature(core_intrinsics)] #![feature(lang_items)] #![feature(libc)] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index d11dee8fc9707..ee6ba3f438f15 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -229,7 +229,6 @@ #![feature(align_offset)] #![feature(alloc_error_handler)] #![feature(alloc_layout_extra)] -#![feature(alloc)] #![feature(allocator_api)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] diff --git a/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py b/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py index e0fa4e8f5debe..855b6421cf822 100644 --- a/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py +++ b/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py @@ -7,8 +7,8 @@ # This is a whitelist of files which are stable crates or simply are not crates, # we don't check for the instability of these crates as they're all stable! -STABLE_CRATES = ['std', 'core', 'proc_macro', 'rsbegin.o', 'rsend.o', 'dllcrt2.o', 'crt2.o', - 'clang_rt'] +STABLE_CRATES = ['std', 'alloc', 'core', 'proc_macro', + 'rsbegin.o', 'rsend.o', 'dllcrt2.o', 'crt2.o', 'clang_rt'] def convert_to_string(s): diff --git a/src/test/run-pass/array-slice-vec/vec-macro-no-std.rs b/src/test/run-pass/array-slice-vec/vec-macro-no-std.rs index 7f7f1e4331507..443895f7c4824 100644 --- a/src/test/run-pass/array-slice-vec/vec-macro-no-std.rs +++ b/src/test/run-pass/array-slice-vec/vec-macro-no-std.rs @@ -2,7 +2,7 @@ // ignore-emscripten no no_std executables -#![feature(lang_items, start, rustc_private, alloc)] +#![feature(lang_items, start, rustc_private)] #![no_std] extern crate std as other; diff --git a/src/test/run-pass/extern/extern-prelude-core.rs b/src/test/run-pass/extern/extern-prelude-core.rs index a5d31009f9cee..f0d43404b0046 100644 --- a/src/test/run-pass/extern/extern-prelude-core.rs +++ b/src/test/run-pass/extern/extern-prelude-core.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(extern_prelude, lang_items, start, alloc)] +#![feature(extern_prelude, lang_items, start)] #![no_std] extern crate std as other; diff --git a/src/test/run-pass/extern/extern-prelude-core.stderr b/src/test/run-pass/extern/extern-prelude-core.stderr index 417483af707ca..8d2a0b7425f2a 100644 --- a/src/test/run-pass/extern/extern-prelude-core.stderr +++ b/src/test/run-pass/extern/extern-prelude-core.stderr @@ -1,7 +1,7 @@ warning: the feature `extern_prelude` has been stable since 1.30.0 and no longer requires an attribute to enable --> $DIR/extern-prelude-core.rs:2:12 | -LL | #![feature(extern_prelude, lang_items, start, alloc)] +LL | #![feature(extern_prelude, lang_items, start)] | ^^^^^^^^^^^^^^ | = note: #[warn(stable_features)] on by default diff --git a/src/test/run-pass/for-loop-while/for-loop-no-std.rs b/src/test/run-pass/for-loop-while/for-loop-no-std.rs index 877429f5d3900..65a33c5f16f1d 100644 --- a/src/test/run-pass/for-loop-while/for-loop-no-std.rs +++ b/src/test/run-pass/for-loop-while/for-loop-no-std.rs @@ -1,6 +1,6 @@ // run-pass #![allow(unused_imports)] -#![feature(lang_items, start, alloc)] +#![feature(lang_items, start)] #![no_std] extern crate std as other; diff --git a/src/test/run-pass/format-no-std.rs b/src/test/run-pass/format-no-std.rs index 0f3a5c277b4c5..32f7a4a07c499 100644 --- a/src/test/run-pass/format-no-std.rs +++ b/src/test/run-pass/format-no-std.rs @@ -1,6 +1,6 @@ // ignore-emscripten no no_std executables -#![feature(lang_items, start, alloc)] +#![feature(lang_items, start)] #![no_std] extern crate std as other; diff --git a/src/test/run-pass/structs-enums/unit-like-struct-drop-run.rs b/src/test/run-pass/structs-enums/unit-like-struct-drop-run.rs index dfe73875215c5..980fd97e2c678 100644 --- a/src/test/run-pass/structs-enums/unit-like-struct-drop-run.rs +++ b/src/test/run-pass/structs-enums/unit-like-struct-drop-run.rs @@ -3,9 +3,6 @@ // Make sure the destructor is run for unit-like structs. - -#![feature(alloc)] - use std::thread; struct Foo; diff --git a/src/test/ui/allocator-submodule.rs b/src/test/ui/allocator-submodule.rs index a1cca50ba9817..7a8d86b8da18c 100644 --- a/src/test/ui/allocator-submodule.rs +++ b/src/test/ui/allocator-submodule.rs @@ -1,8 +1,6 @@ // Tests that it is possible to create a global allocator in a submodule, rather than in the crate // root. -#![feature(alloc, allocator_api, global_allocator)] - extern crate alloc; use std::{ diff --git a/src/test/ui/allocator-submodule.stderr b/src/test/ui/allocator-submodule.stderr index 26d7aa80eee16..91c7c0f6b8e24 100644 --- a/src/test/ui/allocator-submodule.stderr +++ b/src/test/ui/allocator-submodule.stderr @@ -1,5 +1,5 @@ error: `global_allocator` cannot be used in submodules - --> $DIR/allocator-submodule.rs:27:5 + --> $DIR/allocator-submodule.rs:25:5 | LL | static MY_HEAP: MyAlloc = MyAlloc; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/error-codes/E0254.rs b/src/test/ui/error-codes/E0254.rs index 706cd347e134a..d166aff565792 100644 --- a/src/test/ui/error-codes/E0254.rs +++ b/src/test/ui/error-codes/E0254.rs @@ -1,4 +1,3 @@ -#![feature(alloc)] #![allow(unused_extern_crates, non_camel_case_types)] extern crate alloc; diff --git a/src/test/ui/error-codes/E0254.stderr b/src/test/ui/error-codes/E0254.stderr index c2d013da41747..10456fd5a5dc1 100644 --- a/src/test/ui/error-codes/E0254.stderr +++ b/src/test/ui/error-codes/E0254.stderr @@ -1,5 +1,5 @@ error[E0254]: the name `alloc` is defined multiple times - --> $DIR/E0254.rs:12:5 + --> $DIR/E0254.rs:11:5 | LL | extern crate alloc; | ------------------- previous import of the extern crate `alloc` here diff --git a/src/test/ui/error-codes/E0259.rs b/src/test/ui/error-codes/E0259.rs index cda3db34dfc41..c83561be9c6a5 100644 --- a/src/test/ui/error-codes/E0259.rs +++ b/src/test/ui/error-codes/E0259.rs @@ -1,4 +1,4 @@ -#![feature(alloc, rustc_private)] +#![feature(rustc_private)] #![allow(unused_extern_crates)] extern crate alloc; diff --git a/src/test/ui/error-codes/E0260.rs b/src/test/ui/error-codes/E0260.rs index 80382c0d2fcb5..73b8934159fcf 100644 --- a/src/test/ui/error-codes/E0260.rs +++ b/src/test/ui/error-codes/E0260.rs @@ -1,4 +1,3 @@ -#![feature(alloc)] #![allow(unused_extern_crates)] extern crate alloc; diff --git a/src/test/ui/error-codes/E0260.stderr b/src/test/ui/error-codes/E0260.stderr index bfe2ed0cfc778..7d0b3022914d8 100644 --- a/src/test/ui/error-codes/E0260.stderr +++ b/src/test/ui/error-codes/E0260.stderr @@ -1,5 +1,5 @@ error[E0260]: the name `alloc` is defined multiple times - --> $DIR/E0260.rs:6:1 + --> $DIR/E0260.rs:5:1 | LL | extern crate alloc; | ------------------- previous import of the extern crate `alloc` here diff --git a/src/test/ui/missing/missing-alloc_error_handler.rs b/src/test/ui/missing/missing-alloc_error_handler.rs index 1a9e8688e8a42..ae0c067bb5f3e 100644 --- a/src/test/ui/missing/missing-alloc_error_handler.rs +++ b/src/test/ui/missing/missing-alloc_error_handler.rs @@ -3,7 +3,7 @@ #![no_std] #![crate_type = "staticlib"] -#![feature(panic_handler, alloc_error_handler, alloc)] +#![feature(panic_handler, alloc_error_handler)] #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { diff --git a/src/test/ui/missing/missing-allocator.rs b/src/test/ui/missing/missing-allocator.rs index dbb10d1e7b97e..6d867e2e8b48e 100644 --- a/src/test/ui/missing/missing-allocator.rs +++ b/src/test/ui/missing/missing-allocator.rs @@ -3,7 +3,7 @@ #![no_std] #![crate_type = "staticlib"] -#![feature(panic_handler, alloc_error_handler, alloc)] +#![feature(panic_handler, alloc_error_handler)] #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { diff --git a/src/test/ui/resolve_self_super_hint.rs b/src/test/ui/resolve_self_super_hint.rs index 91a01cc0fa231..a9423830d9040 100644 --- a/src/test/ui/resolve_self_super_hint.rs +++ b/src/test/ui/resolve_self_super_hint.rs @@ -1,4 +1,3 @@ -#![feature(alloc)] #![allow(unused_extern_crates)] mod a { diff --git a/src/test/ui/resolve_self_super_hint.stderr b/src/test/ui/resolve_self_super_hint.stderr index 03214cad8e41a..14cdae97d14f3 100644 --- a/src/test/ui/resolve_self_super_hint.stderr +++ b/src/test/ui/resolve_self_super_hint.stderr @@ -1,17 +1,17 @@ error[E0432]: unresolved import `alloc` - --> $DIR/resolve_self_super_hint.rs:6:9 + --> $DIR/resolve_self_super_hint.rs:5:9 | LL | use alloc::HashMap; | ^^^^^ help: a similar path exists: `self::alloc` error[E0432]: unresolved import `alloc` - --> $DIR/resolve_self_super_hint.rs:11:13 + --> $DIR/resolve_self_super_hint.rs:10:13 | LL | use alloc::HashMap; | ^^^^^ help: a similar path exists: `super::alloc` error[E0432]: unresolved import `alloc` - --> $DIR/resolve_self_super_hint.rs:16:17 + --> $DIR/resolve_self_super_hint.rs:15:17 | LL | use alloc::HashMap; | ^^^^^ @@ -20,7 +20,7 @@ LL | use alloc::HashMap; | help: a similar path exists: `a::alloc` error[E0432]: unresolved import `alloc` - --> $DIR/resolve_self_super_hint.rs:21:21 + --> $DIR/resolve_self_super_hint.rs:20:21 | LL | use alloc::HashMap; | ^^^^^ diff --git a/src/test/ui/rust-2018/remove-extern-crate.fixed b/src/test/ui/rust-2018/remove-extern-crate.fixed index a977e00c0131b..17449caf84fb4 100644 --- a/src/test/ui/rust-2018/remove-extern-crate.fixed +++ b/src/test/ui/rust-2018/remove-extern-crate.fixed @@ -4,7 +4,6 @@ // aux-build:remove-extern-crate.rs // compile-flags:--extern remove_extern_crate -#![feature(alloc)] #![warn(rust_2018_idioms)] diff --git a/src/test/ui/rust-2018/remove-extern-crate.rs b/src/test/ui/rust-2018/remove-extern-crate.rs index cafe82d846ed8..fb2217df0005d 100644 --- a/src/test/ui/rust-2018/remove-extern-crate.rs +++ b/src/test/ui/rust-2018/remove-extern-crate.rs @@ -4,7 +4,6 @@ // aux-build:remove-extern-crate.rs // compile-flags:--extern remove_extern_crate -#![feature(alloc)] #![warn(rust_2018_idioms)] extern crate core; diff --git a/src/test/ui/rust-2018/remove-extern-crate.stderr b/src/test/ui/rust-2018/remove-extern-crate.stderr index 4e08b7aa6a03d..549693201b703 100644 --- a/src/test/ui/rust-2018/remove-extern-crate.stderr +++ b/src/test/ui/rust-2018/remove-extern-crate.stderr @@ -1,24 +1,24 @@ warning: unused extern crate - --> $DIR/remove-extern-crate.rs:10:1 + --> $DIR/remove-extern-crate.rs:9:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ help: remove it | note: lint level defined here - --> $DIR/remove-extern-crate.rs:8:9 + --> $DIR/remove-extern-crate.rs:7:9 | LL | #![warn(rust_2018_idioms)] | ^^^^^^^^^^^^^^^^ = note: #[warn(unused_extern_crates)] implied by #[warn(rust_2018_idioms)] warning: `extern crate` is not idiomatic in the new edition - --> $DIR/remove-extern-crate.rs:11:1 + --> $DIR/remove-extern-crate.rs:10:1 | LL | extern crate core as another_name; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use` warning: `extern crate` is not idiomatic in the new edition - --> $DIR/remove-extern-crate.rs:29:5 + --> $DIR/remove-extern-crate.rs:28:5 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ help: convert it to a `use` diff --git a/src/test/ui/unnecessary-extern-crate.rs b/src/test/ui/unnecessary-extern-crate.rs index e25b99bcb61dd..67eaaf4b6c21b 100644 --- a/src/test/ui/unnecessary-extern-crate.rs +++ b/src/test/ui/unnecessary-extern-crate.rs @@ -1,7 +1,7 @@ // edition:2018 #![deny(unused_extern_crates)] -#![feature(alloc, test, rustc_private, crate_visibility_modifier)] +#![feature(test, rustc_private, crate_visibility_modifier)] extern crate libc; //~^ ERROR unused extern crate From b27bcc0a17230179d010d914e06bb90ccadca1f7 Mon Sep 17 00:00:00 2001 From: Scott Olson Date: Fri, 12 Apr 2019 13:57:42 -0600 Subject: [PATCH 52/53] Fix paste error in split_ascii_whitespace docs. --- src/libcore/str/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index f54d7badc3ae0..8d28be621d647 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2712,7 +2712,7 @@ impl str { /// All kinds of ASCII whitespace are considered: /// /// ``` - /// let mut iter = " Mary had\ta little \n\t lamb".split_whitespace(); + /// let mut iter = " Mary had\ta little \n\t lamb".split_ascii_whitespace(); /// assert_eq!(Some("Mary"), iter.next()); /// assert_eq!(Some("had"), iter.next()); /// assert_eq!(Some("a"), iter.next()); From 0a9b214b503265e42e86ca7846577664efb1819e Mon Sep 17 00:00:00 2001 From: Kornel Date: Sat, 13 Apr 2019 00:38:46 +0100 Subject: [PATCH 53/53] Exclude some copies of old book editions from search engines --- src/doc/robots.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/doc/robots.txt b/src/doc/robots.txt index a54ec508c1bef..61ee12739fb37 100644 --- a/src/doc/robots.txt +++ b/src/doc/robots.txt @@ -17,3 +17,11 @@ Disallow: /1.0.0-beta.2/ Disallow: /1.0.0-beta.3/ Disallow: /1.0.0-beta.4/ Disallow: /1.0.0-beta.5/ +Disallow: /book/first-edition/ +Disallow: /book/second-edition/ +Disallow: /stable/book/first-edition/ +Disallow: /stable/book/second-edition/ +Disallow: /beta/book/first-edition/ +Disallow: /beta/book/second-edition/ +Disallow: /nightly/book/first-edition/ +Disallow: /nightly/book/second-edition/