diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 5966bb65df9c8..cc5ee53affc66 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -314,7 +314,6 @@ def __init__(self): self.build_dir = os.path.join(os.getcwd(), "build") self.clean = False self.config_toml = '' - self.printed = False self.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) self.use_locked_deps = '' self.use_vendored_sources = '' @@ -336,7 +335,6 @@ def download_stage0(self): if self.rustc().startswith(self.bin_root()) and \ (not os.path.exists(self.rustc()) or self.program_out_of_date(self.rustc_stamp())): - self.print_what_bootstrap_means() if os.path.exists(self.bin_root()): shutil.rmtree(self.bin_root()) filename = "rust-std-{}-{}.tar.gz".format( @@ -354,7 +352,6 @@ def download_stage0(self): if self.cargo().startswith(self.bin_root()) and \ (not os.path.exists(self.cargo()) or self.program_out_of_date(self.cargo_stamp())): - self.print_what_bootstrap_means() filename = "cargo-{}-{}.tar.gz".format(cargo_channel, self.build) self._download_stage0_helper(filename, "cargo") self.fix_executable("{}/bin/cargo".format(self.bin_root())) @@ -555,23 +552,6 @@ def exe_suffix(): return '.exe' return '' - def print_what_bootstrap_means(self): - """Prints more information about the build system""" - if hasattr(self, 'printed'): - return - self.printed = True - if os.path.exists(self.bootstrap_binary()): - return - if '--help' not in sys.argv or len(sys.argv) == 1: - return - - print('info: the build system for Rust is written in Rust, so this') - print(' script is now going to download a stage0 rust compiler') - print(' and then compile the build system itself') - print('') - print('info: in the meantime you can read more about rustbuild at') - print(' src/bootstrap/README.md before the download finishes') - def bootstrap_binary(self): """Return the path of the boostrap binary @@ -585,7 +565,6 @@ def bootstrap_binary(self): def build_bootstrap(self): """Build bootstrap""" - self.print_what_bootstrap_means() build_dir = os.path.join(self.build_dir, "bootstrap") if self.clean and os.path.exists(build_dir): shutil.rmtree(build_dir) @@ -670,8 +649,16 @@ def set_dev_environment(self): self._download_url = 'https://dev-static.rust-lang.org' -def bootstrap(): +def bootstrap(help_triggered): """Configure, fetch, build and run the initial bootstrap""" + + # If the user is asking for help, let them know that the whole download-and-build + # process has to happen before anything is printed out. + if help_triggered: + print("info: Downloading and building bootstrap before processing --help") + print(" command. See src/bootstrap/README.md for help with common") + print(" commands.") + parser = argparse.ArgumentParser(description='Build rust') parser.add_argument('--config') parser.add_argument('--build') @@ -708,7 +695,7 @@ def bootstrap(): print(' and so in order to preserve your $HOME this will now') print(' use vendored sources by default. Note that if this') print(' does not work you should run a normal build first') - print(' before running a command like `sudo make install`') + print(' before running a command like `sudo ./x.py install`') if build.use_vendored_sources: if not os.path.exists('.cargo'): @@ -734,7 +721,10 @@ def bootstrap(): if 'dev' in data: build.set_dev_environment() - build.update_submodules() + # No help text depends on submodules. This check saves ~1 minute of git commands, even if + # all the submodules are present and downloaded! + if not help_triggered: + build.update_submodules() # Fetch/build the bootstrap build.build = args.build or build.build_triple() @@ -760,7 +750,7 @@ def main(): help_triggered = ( '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1) try: - bootstrap() + bootstrap(help_triggered) if not help_triggered: print("Build completed successfully in {}".format( format_build_time(time() - start_time))) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 55d9723527e6d..a791dd13f0f4b 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -312,6 +312,7 @@ fn invoke_rustdoc(builder: &Builder, compiler: Compiler, target: Interned> is as fast as Zip, Skip>, from +// https://users.rust-lang.org/t/performance-difference-between-iterator-zip-and-skip-order/15743 +#[bench] +fn bench_zip_then_skip(b: &mut Bencher) { + let v: Vec<_> = (0..100_000).collect(); + let t: Vec<_> = (0..100_000).collect(); + + b.iter(|| { + let s = v.iter().zip(t.iter()).skip(10000) + .take_while(|t| *t.0 < 10100) + .map(|(a, b)| *a + *b) + .sum::(); + assert_eq!(s, 2009900); + }); +} +#[bench] +fn bench_skip_then_zip(b: &mut Bencher) { + let v: Vec<_> = (0..100_000).collect(); + let t: Vec<_> = (0..100_000).collect(); + + b.iter(|| { + let s = v.iter().skip(10000).zip(t.iter().skip(10000)) + .take_while(|t| *t.0 < 10100) + .map(|(a, b)| *a + *b) + .sum::(); + assert_eq!(s, 2009900); + }); +} diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 623cad754dd72..257d7d6caaaf8 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1045,6 +1045,11 @@ impl Iterator for Zip where A: Iterator, B: Iterator fn size_hint(&self) -> (usize, Option) { ZipImpl::size_hint(self) } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + ZipImpl::nth(self, n) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1065,6 +1070,14 @@ trait ZipImpl { fn new(a: A, b: B) -> Self; fn next(&mut self) -> Option; fn size_hint(&self) -> (usize, Option); + fn nth(&mut self, n: usize) -> Option; + fn super_nth(&mut self, mut n: usize) -> Option { + while let Some(x) = self.next() { + if n == 0 { return Some(x) } + n -= 1; + } + None + } fn next_back(&mut self) -> Option where A: DoubleEndedIterator + ExactSizeIterator, B: DoubleEndedIterator + ExactSizeIterator; @@ -1094,6 +1107,11 @@ impl ZipImpl for Zip }) } + #[inline] + default fn nth(&mut self, n: usize) -> Option { + self.super_nth(n) + } + #[inline] default fn next_back(&mut self) -> Option<(A::Item, B::Item)> where A: DoubleEndedIterator + ExactSizeIterator, @@ -1174,6 +1192,24 @@ impl ZipImpl for Zip (len, Some(len)) } + #[inline] + fn nth(&mut self, n: usize) -> Option { + let delta = cmp::min(n, self.len - self.index); + let end = self.index + delta; + while self.index < end { + let i = self.index; + self.index += 1; + if A::may_have_side_effect() { + unsafe { self.a.get_unchecked(i); } + } + if B::may_have_side_effect() { + unsafe { self.b.get_unchecked(i); } + } + } + + self.super_nth(n - delta) + } + #[inline] fn next_back(&mut self) -> Option<(A::Item, B::Item)> where A: DoubleEndedIterator + ExactSizeIterator, diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index edd75f7795ed7..a962efadd64e9 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -144,6 +144,43 @@ fn test_iterator_chain_find() { assert_eq!(iter.next(), None); } +#[test] +fn test_zip_nth() { + let xs = [0, 1, 2, 4, 5]; + let ys = [10, 11, 12]; + + let mut it = xs.iter().zip(&ys); + assert_eq!(it.nth(0), Some((&0, &10))); + assert_eq!(it.nth(1), Some((&2, &12))); + assert_eq!(it.nth(0), None); + + let mut it = xs.iter().zip(&ys); + assert_eq!(it.nth(3), None); + + let mut it = ys.iter().zip(&xs); + assert_eq!(it.nth(3), None); +} + +#[test] +fn test_zip_nth_side_effects() { + let mut a = Vec::new(); + let mut b = Vec::new(); + let value = [1, 2, 3, 4, 5, 6].iter().cloned() + .map(|n| { + a.push(n); + n * 10 + }) + .zip([2, 3, 4, 5, 6, 7, 8].iter().cloned().map(|n| { + b.push(n * 100); + n * 1000 + })) + .skip(1) + .nth(3); + assert_eq!(value, Some((50, 6000))); + assert_eq!(a, vec![1, 2, 3, 4, 5]); + assert_eq!(b, vec![200, 300, 400, 500, 600]); +} + #[test] fn test_iterator_step_by() { // Identity diff --git a/src/librustc/dep_graph/debug.rs b/src/librustc/dep_graph/debug.rs index e22552008d5a8..e56333aba9be5 100644 --- a/src/librustc/dep_graph/debug.rs +++ b/src/librustc/dep_graph/debug.rs @@ -54,7 +54,7 @@ pub struct EdgeFilter { } impl EdgeFilter { - pub fn new(test: &str) -> Result> { + pub fn new(test: &str) -> Result> { let parts: Vec<_> = test.split("->").collect(); if parts.len() != 2 { Err(format!("expected a filter like `a&b -> c&d`, not `{}`", test).into()) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index a41ac5bceed27..fa745bf165577 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -80,13 +80,13 @@ pub struct LoweringContext<'a> { // Use to assign ids to hir nodes that do not directly correspond to an ast node sess: &'a Session, - cstore: &'a CrateStore, + cstore: &'a dyn CrateStore, // As we walk the AST we must keep track of the current 'parent' def id (in // the form of a DefIndex) so that if we create a new node which introduces // a definition, then we can properly create the def id. parent_def: Option, - resolver: &'a mut Resolver, + resolver: &'a mut dyn Resolver, name_map: FxHashMap, /// The items being lowered are collected here. @@ -177,10 +177,10 @@ enum ImplTraitContext { } pub fn lower_crate(sess: &Session, - cstore: &CrateStore, + cstore: &dyn CrateStore, dep_graph: &DepGraph, krate: &Crate, - resolver: &mut Resolver) + resolver: &mut dyn Resolver) -> hir::Crate { // We're constructing the HIR here; we don't care what we will // read, since we haven't even constructed the *input* to diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 99b1e5783e01e..9bbda9d74479b 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -123,7 +123,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { pub(super) fn finalize_and_compute_crate_hash(self, crate_disambiguator: CrateDisambiguator, - cstore: &CrateStore, + cstore: &dyn CrateStore, codemap: &CodeMap, commandline_args_hash: u64) -> (Vec>, Svh) { diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index d68b18dd2f17d..cdd6395747865 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -26,7 +26,7 @@ pub struct DefCollector<'a> { definitions: &'a mut Definitions, parent_def: Option, expansion: Mark, - pub visit_macro_invoc: Option<&'a mut FnMut(MacroInvocationData)>, + pub visit_macro_invoc: Option<&'a mut dyn FnMut(MacroInvocationData)>, } pub struct MacroInvocationData { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 3799bdada888e..61fae4609d54f 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -19,6 +19,8 @@ use dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex}; use hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId, DefIndexAddressSpace}; +use middle::cstore::CrateStore; + use syntax::abi::Abi; use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID}; use syntax::codemap::Spanned; @@ -1136,8 +1138,9 @@ impl Named for StructField { fn name(&self) -> Name { self.name } } impl Named for TraitItem { fn name(&self) -> Name { self.name } } impl Named for ImplItem { fn name(&self) -> Name { self.name } } + pub fn map_crate<'hir>(sess: &::session::Session, - cstore: &::middle::cstore::CrateStore, + cstore: &dyn CrateStore, forest: &'hir mut Forest, definitions: &'hir Definitions) -> Map<'hir> { diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 30c1ad01d1401..ed8cea3eb6563 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -62,7 +62,7 @@ pub trait PpAnn { pub struct NoAnn; impl PpAnn for NoAnn {} -pub const NO_ANN: &'static PpAnn = &NoAnn; +pub const NO_ANN: &'static dyn PpAnn = &NoAnn; impl PpAnn for hir::Crate { fn nested(&self, state: &mut State, nested: Nested) -> io::Result<()> { @@ -83,7 +83,7 @@ pub struct State<'a> { literals: Peekable>, cur_cmnt: usize, boxes: Vec, - ann: &'a (PpAnn + 'a), + ann: &'a (dyn PpAnn + 'a), } impl<'a> PrintState<'a> for State<'a> { @@ -126,9 +126,9 @@ pub fn print_crate<'a>(cm: &'a CodeMap, sess: &ParseSess, krate: &hir::Crate, filename: FileName, - input: &mut Read, - out: Box, - ann: &'a PpAnn, + input: &mut dyn Read, + out: Box, + ann: &'a dyn PpAnn, is_expanded: bool) -> io::Result<()> { let mut s = State::new_from_input(cm, sess, filename, input, out, ann, is_expanded); @@ -145,9 +145,9 @@ impl<'a> State<'a> { pub fn new_from_input(cm: &'a CodeMap, sess: &ParseSess, filename: FileName, - input: &mut Read, - out: Box, - ann: &'a PpAnn, + input: &mut dyn Read, + out: Box, + ann: &'a dyn PpAnn, is_expanded: bool) -> State<'a> { let (cmnts, lits) = comments::gather_comments_and_literals(sess, filename, input); @@ -167,8 +167,8 @@ impl<'a> State<'a> { } pub fn new(cm: &'a CodeMap, - out: Box, - ann: &'a PpAnn, + out: Box, + ann: &'a dyn PpAnn, comments: Option>, literals: Option>) -> State<'a> { @@ -184,7 +184,7 @@ impl<'a> State<'a> { } } -pub fn to_string(ann: &PpAnn, f: F) -> String +pub fn to_string(ann: &dyn PpAnn, f: F) -> String where F: FnOnce(&mut State) -> io::Result<()> { let mut wr = Vec::new(); diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 67f6c0c2e49e8..4dcab6a04ee20 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -49,7 +49,7 @@ pub fn compute_ignored_attr_names() -> FxHashSet { pub struct StableHashingContext<'gcx> { sess: &'gcx Session, definitions: &'gcx Definitions, - cstore: &'gcx CrateStore, + cstore: &'gcx dyn CrateStore, body_resolver: BodyResolver<'gcx>, hash_spans: bool, hash_bodies: bool, @@ -88,7 +88,7 @@ impl<'gcx> StableHashingContext<'gcx> { pub fn new(sess: &'gcx Session, krate: &'gcx hir::Crate, definitions: &'gcx Definitions, - cstore: &'gcx CrateStore) + cstore: &'gcx dyn CrateStore) -> Self { let hash_spans_initial = !sess.opts.debugging_opts.incremental_ignore_spans; diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 4a75037aa5035..ed89d1d2f57a5 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -896,7 +896,7 @@ impl<'a, 'gcx, 'tcx> GenericKind<'tcx> { } impl<'a, 'gcx, 'tcx> VerifyBound<'tcx> { - fn for_each_region(&self, f: &mut FnMut(ty::Region<'tcx>)) { + fn for_each_region(&self, f: &mut dyn FnMut(ty::Region<'tcx>)) { match self { &VerifyBound::AnyRegion(ref rs) | &VerifyBound::AllRegions(ref rs) => for &r in rs { f(r); diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index f05ed0a460d87..d08a41010ab16 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -41,8 +41,6 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![deny(warnings)] -#![cfg_attr(not(stage0), allow(bare_trait_object))] - #![feature(box_patterns)] #![feature(box_syntax)] #![feature(conservative_impl_trait)] diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index a51d06c06edd3..5cc7cd5440f8c 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -280,8 +280,8 @@ pub trait EarlyLintPass: LintPass { } /// A lint pass boxed up as a trait object. -pub type EarlyLintPassObject = Box; -pub type LateLintPassObject = Box LateLintPass<'a, 'tcx> + 'static>; +pub type EarlyLintPassObject = Box; +pub type LateLintPassObject = Box LateLintPass<'a, 'tcx> + 'static>; /// Identifies a lint known to the compiler. #[derive(Clone, Copy, Debug)] diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 9708afd204593..b0aaa76c75ed7 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -225,10 +225,10 @@ pub struct ExternBodyNestedBodies { /// (it'd break incremental compilation) and should only be called pre-HIR (e.g. /// during resolve) pub trait CrateStore { - fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc; + fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc; // access to the metadata loader - fn metadata_loader(&self) -> &MetadataLoader; + fn metadata_loader(&self) -> &dyn MetadataLoader; // resolve fn def_key(&self, def: DefId) -> DefKey; @@ -297,7 +297,7 @@ pub struct DummyCrateStore; #[allow(unused_variables)] impl CrateStore for DummyCrateStore { - fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc + fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc { bug!("crate_data_as_rc_any") } // item info fn visibility_untracked(&self, def: DefId) -> ty::Visibility { bug!("visibility") } @@ -351,7 +351,7 @@ impl CrateStore for DummyCrateStore { fn postorder_cnums_untracked(&self) -> Vec { bug!("postorder_cnums_untracked") } // access to the metadata loader - fn metadata_loader(&self) -> &MetadataLoader { bug!("metadata_loader") } + fn metadata_loader(&self) -> &dyn MetadataLoader { bug!("metadata_loader") } } pub trait CrateLoader { diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index db0ecb6aa5eb1..e7055827c491f 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -319,7 +319,7 @@ fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option, list: &mut DependencyList, - replaces_injected: &Fn(CrateNum) -> bool) { + replaces_injected: &dyn Fn(CrateNum) -> bool) { for (i, slot) in list.iter().enumerate() { let cnum = CrateNum::new(i + 1); if !replaces_injected(cnum) { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 7db75a5166898..0ee25ae8116fd 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -239,7 +239,7 @@ impl OverloadedCallType { // This is the code that actually walks the tree. pub struct ExprUseVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { mc: mc::MemCategorizationContext<'a, 'gcx, 'tcx>, - delegate: &'a mut Delegate<'tcx>, + delegate: &'a mut dyn Delegate<'tcx>, param_env: ty::ParamEnv<'tcx>, } @@ -274,7 +274,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> { /// `None` means that rvalues will be given more conservative lifetimes. /// /// See also `with_infer`, which is used *during* typeck. - pub fn new(delegate: &'a mut (Delegate<'tcx>+'a), + pub fn new(delegate: &'a mut (dyn Delegate<'tcx>+'a), tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, region_scope_tree: &'a region::ScopeTree, @@ -294,7 +294,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> { } impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { - pub fn with_infer(delegate: &'a mut (Delegate<'tcx>+'a), + pub fn with_infer(delegate: &'a mut (dyn Delegate<'tcx>+'a), infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, region_scope_tree: &'a region::ScopeTree, diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 10497c95e27d0..d13b16dce8986 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -673,7 +673,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn write_vars(&self, - wr: &mut Write, + wr: &mut dyn Write, ln: LiveNode, mut test: F) -> io::Result<()> where @@ -694,7 +694,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn ln_str(&self, ln: LiveNode) -> String { let mut wr = Vec::new(); { - let wr = &mut wr as &mut Write; + let wr = &mut wr as &mut dyn Write; write!(wr, "[ln({:?}) of kind {:?} reads", ln.get(), self.ir.lnk(ln)); self.write_vars(wr, ln, |idx| self.users[idx].reader); write!(wr, " writes"); diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 9ebfe25c107a9..f9ea544156ce3 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -35,7 +35,7 @@ impl<'tcx> From> for EvalError<'tcx> { pub enum EvalErrorKind<'tcx> { /// This variant is used by machines to signal their own errors that do not /// match an existing variant - MachineError(Box), + MachineError(Box), FunctionPointerTyMismatch(FnSig<'tcx>, FnSig<'tcx>), NoMirFor(String), UnterminatedCString(MemoryPointer), @@ -248,7 +248,7 @@ impl<'tcx> Error for EvalError<'tcx> { } } - fn cause(&self) -> Option<&Error> { + fn cause(&self) -> Option<&dyn Error> { use self::EvalErrorKind::*; match self.kind { MachineError(ref inner) => Some(&**inner), diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index b69f5d6c8bdd7..ca17e18beccba 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -341,7 +341,7 @@ macro_rules! hash_option { ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [UNTRACKED]) => ({}); ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => ({ if $sub_hashes.insert(stringify!($opt_name), - $opt_expr as &dep_tracking::DepTrackingHash).is_some() { + $opt_expr as &dyn dep_tracking::DepTrackingHash).is_some() { bug!("Duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name)) } }); @@ -1456,7 +1456,7 @@ pub enum OptionStability { } pub struct RustcOptGroup { - pub apply: Box &mut getopts::Options>, + pub apply: Box &mut getopts::Options>, pub name: &'static str, pub stability: OptionStability, } @@ -2256,7 +2256,7 @@ mod dep_tracking { } // This is a stable hash because BTreeMap is a sorted container - pub fn stable_hash(sub_hashes: BTreeMap<&'static str, &DepTrackingHash>, + pub fn stable_hash(sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>, hasher: &mut DefaultHasher, error_format: ErrorOutputType) { for (key, sub_hash) in sub_hashes { diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 2437eaadc6d48..c0085a803dc40 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -904,7 +904,7 @@ pub fn build_session_with_codemap(sopts: config::Options, local_crate_source_file: Option, registry: errors::registry::Registry, codemap: Rc, - emitter_dest: Option>) + emitter_dest: Option>) -> Session { // FIXME: This is not general enough to make the warning lint completely override // normal diagnostic warnings, since the warning lint can also be denied and changed @@ -923,7 +923,7 @@ pub fn build_session_with_codemap(sopts: config::Options, let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace; - let emitter: Box = match (sopts.error_format, emitter_dest) { + let emitter: Box = match (sopts.error_format, emitter_dest) { (config::ErrorOutputType::HumanReadable(color_config), None) => { Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()), false, sopts.debugging_opts.teach) @@ -1122,7 +1122,7 @@ pub enum IncrCompSession { } pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { - let emitter: Box = match output { + let emitter: Box = match output { config::ErrorOutputType::HumanReadable(color_config) => { Box::new(EmitterWriter::stderr(color_config, None, false, false)) } @@ -1137,7 +1137,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { } pub fn early_warn(output: config::ErrorOutputType, msg: &str) { - let emitter: Box = match output { + let emitter: Box = match output { config::ErrorOutputType::HumanReadable(color_config) => { Box::new(EmitterWriter::stderr(color_config, None, false, false)) } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index dba23c22647f8..b1d2142060699 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -499,7 +499,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { item_name: ast::Name, _impl_item_def_id: DefId, trait_item_def_id: DefId, - requirement: &fmt::Display) + requirement: &dyn fmt::Display) -> DiagnosticBuilder<'tcx> { let msg = "impl has stricter requirements than trait"; diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index a10169e13e60a..efc4089367486 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -190,13 +190,13 @@ impl<'a, 'gcx, 'tcx> Children { Ok(Inserted::BecameNewSibling(last_lint)) } - fn iter_mut(&'a mut self) -> Box + 'a> { + fn iter_mut(&'a mut self) -> Box + 'a> { let nonblanket = self.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter_mut()); Box::new(self.blanket_impls.iter_mut().chain(nonblanket)) } fn filtered_mut(&'a mut self, sty: SimplifiedType) - -> Box + 'a> { + -> Box + 'a> { let nonblanket = self.nonblanket_impls.entry(sty).or_insert(vec![]).iter_mut(); Box::new(self.blanket_impls.iter_mut().chain(nonblanket)) } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a39d63d05eeaf..a02115c4afb85 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -799,7 +799,7 @@ pub struct GlobalCtxt<'tcx> { global_arenas: &'tcx GlobalArenas<'tcx>, global_interners: CtxtInterners<'tcx>, - cstore: &'tcx CrateStore, + cstore: &'tcx dyn CrateStore, pub sess: &'tcx Session, @@ -883,7 +883,7 @@ pub struct GlobalCtxt<'tcx> { /// This is intended to only get used during the trans phase of the compiler /// when satisfying the query for a particular codegen unit. Internally in /// the query it'll send data along this channel to get processed later. - pub tx_to_llvm_workers: mpsc::Sender>, + pub tx_to_llvm_workers: mpsc::Sender>, output_filenames: Arc, } @@ -1131,7 +1131,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// value (types, substs, etc.) can only be used while `ty::tls` has a valid /// reference to the context, to allow formatting values that need it. pub fn create_and_enter(s: &'tcx Session, - cstore: &'tcx CrateStore, + cstore: &'tcx dyn CrateStore, local_providers: ty::maps::Providers<'tcx>, extern_providers: ty::maps::Providers<'tcx>, arenas: &'tcx AllArenas<'tcx>, @@ -1139,7 +1139,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { hir: hir_map::Map<'tcx>, on_disk_query_result_cache: maps::OnDiskCache<'tcx>, crate_name: &str, - tx: mpsc::Sender>, + tx: mpsc::Sender>, output_filenames: &OutputFilenames, f: F) -> R where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R @@ -1312,7 +1312,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Note that this is *untracked* and should only be used within the query // system if the result is otherwise tracked through queries - pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Rc { + pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Rc { self.cstore.crate_data_as_rc_any(cnum) } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index c5b82730e488c..4cc7406af721e 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -277,7 +277,7 @@ pub struct RegionFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, skipped_regions: &'a mut bool, current_depth: u32, - fld_r: &'a mut (FnMut(ty::Region<'tcx>, u32) -> ty::Region<'tcx> + 'a), + fld_r: &'a mut (dyn FnMut(ty::Region<'tcx>, u32) -> ty::Region<'tcx> + 'a), } impl<'a, 'gcx, 'tcx> RegionFolder<'a, 'gcx, 'tcx> { @@ -330,7 +330,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFolder<'a, 'gcx, 'tcx> { struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, current_depth: u32, - fld_r: &'a mut (FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), + fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), map: BTreeMap> } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 44771444c8aa8..47ad7cbcb56f7 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -419,7 +419,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn calculate_dtor( self, adt_did: DefId, - validate: &mut FnMut(Self, DefId) -> Result<(), ErrorReported> + validate: &mut dyn FnMut(Self, DefId) -> Result<(), ErrorReported> ) -> Option { let drop_trait = if let Some(def_id) = self.lang_items().drop_trait() { def_id diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 55e9a98e7ef13..bdb120ea59c8a 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -38,7 +38,7 @@ pub struct ErrorReported; thread_local!(static TIME_DEPTH: Cell = Cell::new(0)); lazy_static! { - static ref DEFAULT_HOOK: Box = { + static ref DEFAULT_HOOK: Box = { let hook = panic::take_hook(); panic::set_hook(Box::new(panic_hook)); hook diff --git a/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs index a36e26c0b7d5f..88f2b59675186 100644 --- a/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs +++ b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs @@ -12,13 +12,7 @@ use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let mut base = super::linux_musl_base::opts(); - - // Most of these settings are copied from the armv7_unknown_linux_gnueabihf - // target. - base.features = "+v7,+vfp3,+neon".to_string(); - base.cpu = "cortex-a8".to_string(); - base.max_atomic_width = Some(64); + let base = super::linux_musl_base::opts(); Ok(Target { // It's important we use "gnueabihf" and not "musleabihf" here. LLVM // uses it to determine the calling convention and float ABI, and LLVM @@ -33,9 +27,15 @@ pub fn target() -> TargetResult { target_env: "musl".to_string(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, + + // Most of these settings are copied from the armv7_unknown_linux_gnueabihf + // target. options: TargetOptions { + features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(), + cpu: "generic".to_string(), + max_atomic_width: Some(64), abi_blacklist: super::arm_base::abi_blacklist(), .. base - }, + } }) } diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs index ba7ab0c07c66a..6d63bc4436fe8 100644 --- a/src/librustc_data_structures/transitive_relation.rs +++ b/src/librustc_data_structures/transitive_relation.rs @@ -10,16 +10,16 @@ use bitvec::BitMatrix; use fx::FxHashMap; +use sync::Lock; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; use stable_hasher::{HashStable, StableHasher, StableHasherResult}; -use std::cell::RefCell; use std::fmt::Debug; use std::hash::Hash; use std::mem; #[derive(Clone, Debug)] -pub struct TransitiveRelation { +pub struct TransitiveRelation { // List of elements. This is used to map from a T to a usize. elements: Vec, @@ -32,14 +32,14 @@ pub struct TransitiveRelation { // This is a cached transitive closure derived from the edges. // Currently, we build it lazilly and just throw out any existing - // copy whenever a new edge is added. (The RefCell is to permit + // copy whenever a new edge is added. (The Lock is to permit // the lazy computation.) This is kind of silly, except for the // fact its size is tied to `self.elements.len()`, so I wanted to // wait before building it up to avoid reallocating as new edges // are added with new elements. Perhaps better would be to ask the // user for a batch of edges to minimize this effect, but I // already wrote the code this way. :P -nmatsakis - closure: RefCell>, + closure: Lock>, } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)] @@ -51,13 +51,13 @@ struct Edge { target: Index, } -impl TransitiveRelation { +impl TransitiveRelation { pub fn new() -> TransitiveRelation { TransitiveRelation { elements: vec![], map: FxHashMap(), edges: vec![], - closure: RefCell::new(None), + closure: Lock::new(None), } } @@ -72,7 +72,7 @@ impl TransitiveRelation { fn add_index(&mut self, a: T) -> Index { let &mut TransitiveRelation { ref mut elements, - ref closure, + ref mut closure, ref mut map, .. } = self; @@ -82,7 +82,7 @@ impl TransitiveRelation { elements.push(a); // if we changed the dimensions, clear the cache - *closure.borrow_mut() = None; + *closure.get_mut() = None; Index(elements.len() - 1) }) @@ -122,7 +122,7 @@ impl TransitiveRelation { self.edges.push(edge); // added an edge, clear the cache - *self.closure.borrow_mut() = None; + *self.closure.get_mut() = None; } } @@ -443,7 +443,7 @@ impl Decodable for TransitiveRelation .enumerate() .map(|(index, elem)| (elem.clone(), Index(index))) .collect(); - Ok(TransitiveRelation { elements, edges, map, closure: RefCell::new(None) }) + Ok(TransitiveRelation { elements, edges, map, closure: Lock::new(None) }) }) } } diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index 948c1ac0b1362..b6d8e14b74757 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -176,7 +176,7 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> { None } - fn def_use(&self, location: Location, thing: &MirVisitable<'tcx>) -> (bool, bool) { + fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> (bool, bool) { let mut visitor = DefUseVisitor { defined: false, used: false, diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 07e5091da9c1e..dbfb8a6d06e63 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -260,10 +260,10 @@ fn dump_annotation<'a, 'gcx, 'tcx>( fn for_each_region_constraint( closure_region_requirements: &ClosureRegionRequirements, - with_msg: &mut FnMut(&str) -> io::Result<()>, + with_msg: &mut dyn FnMut(&str) -> io::Result<()>, ) -> io::Result<()> { for req in &closure_region_requirements.outlives_requirements { - let subject: &Debug = match &req.subject { + let subject: &dyn Debug = match &req.subject { ClosureOutlivesSubject::Region(subject) => subject, ClosureOutlivesSubject::Ty(ty) => ty, }; diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs index 69ecafa66aee7..631b1d0f8941d 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs @@ -23,7 +23,7 @@ const REGION_WIDTH: usize = 8; impl<'tcx> RegionInferenceContext<'tcx> { /// Write out our state into the `.mir` files. - pub(crate) fn dump_mir(&self, out: &mut Write) -> io::Result<()> { + pub(crate) fn dump_mir(&self, out: &mut dyn Write) -> io::Result<()> { writeln!(out, "| Free Region Mapping")?; for region in self.regions() { @@ -67,7 +67,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// inference resulted in the values that it did when debugging. fn for_each_constraint( &self, - with_msg: &mut FnMut(&str) -> io::Result<()>, + with_msg: &mut dyn FnMut(&str) -> io::Result<()>, ) -> io::Result<()> { for region in self.definitions.indices() { let value = self.liveness_constraints.region_value_str(region); diff --git a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs index 7923b159d80dc..db773240809c5 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs @@ -20,7 +20,7 @@ use super::*; impl<'tcx> RegionInferenceContext<'tcx> { /// Write out the region constraint graph. - pub(crate) fn dump_graphviz(&self, mut w: &mut Write) -> io::Result<()> { + pub(crate) fn dump_graphviz(&self, mut w: &mut dyn Write) -> io::Result<()> { dot::render(self, &mut w) } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index d57b8e78f18a9..a06d39d225c45 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -127,7 +127,7 @@ fn type_check_internal<'gcx, 'tcx>( mir: &Mir<'tcx>, region_bound_pairs: &[(ty::Region<'tcx>, GenericKind<'tcx>)], implicit_region_bound: Option>, - extra: &mut FnMut(&mut TypeChecker<'_, 'gcx, 'tcx>), + extra: &mut dyn FnMut(&mut TypeChecker<'_, 'gcx, 'tcx>), ) -> MirTypeckRegionConstraints<'tcx> { let mut checker = TypeChecker::new( infcx, @@ -231,7 +231,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { self.cx.infcx.tcx } - fn sanitize_type(&mut self, parent: &fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> { + fn sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> { if ty.has_escaping_regions() || ty.references_error() { span_mirbug_and_err!(self, parent, "bad type {:?}", ty) } else { @@ -516,7 +516,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { fn field_ty( &mut self, - parent: &fmt::Debug, + parent: &dyn fmt::Debug, base_ty: PlaceTy<'tcx>, field: Field, location: Location, @@ -1171,7 +1171,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { fn assert_iscleanup( &mut self, mir: &Mir<'tcx>, - ctxt: &fmt::Debug, + ctxt: &dyn fmt::Debug, bb: BasicBlock, iscleanuppad: bool, ) { diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 9c7d9b398cc56..aa7bb6f97786c 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -61,7 +61,7 @@ pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation pub(crate) struct DebugFormatted(String); impl DebugFormatted { - pub fn new(input: &fmt::Debug) -> DebugFormatted { + pub fn new(input: &dyn fmt::Debug) -> DebugFormatted { DebugFormatted(format!("{:?}", input)) } } diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index d3b084fde6ab8..bc555368f0f5f 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -168,7 +168,7 @@ impl Error for ConstEvalError { } } - fn cause(&self) -> Option<&Error> { + fn cause(&self) -> Option<&dyn Error> { None } } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 9887ac82a2ea6..8c15d1cf8b03a 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -15,7 +15,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! */ #![deny(warnings)] -#![cfg_attr(not(stage0), allow(bare_trait_object))] #![feature(box_patterns)] #![feature(box_syntax)] diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index 98753eaa5a354..a16ef2adea9be 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -49,7 +49,7 @@ impl fmt::Display for Disambiguator { pub fn on_mir_pass<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - pass_num: &fmt::Display, + pass_num: &dyn fmt::Display, pass_name: &str, source: MirSource, mir: &Mir<'tcx>, diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 54a7a0eafe0af..24a2790b1e79a 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -161,7 +161,7 @@ pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $ promoted }; let mut index = 0; - let mut run_pass = |pass: &MirPass| { + let mut run_pass = |pass: &dyn MirPass| { let run_hooks = |mir: &_, index, is_after| { dump_mir::on_mir_pass($tcx, &format_args!("{:03}-{:03}", suite_index, index), &pass.name(), source, mir, is_after); diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 6251b64bb279d..42ddabddd2dcd 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -425,12 +425,12 @@ pub fn write_mir_fn<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &Mir<'tcx>, - w: &mut Write, + w: &mut dyn Write, result: &LivenessResult, ) -> io::Result<()> { write_mir_intro(tcx, src, mir, w)?; for block in mir.basic_blocks().indices() { - let print = |w: &mut Write, prefix, result: &IndexVec| { + let print = |w: &mut dyn Write, prefix, result: &IndexVec| { let live: Vec = mir.local_decls .indices() .filter(|i| result[block].contains(i)) diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index f326b6e9274fc..4509cace794d4 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -72,14 +72,14 @@ pub enum PassWhere { /// or `typeck` and `bar` both appear in the name. pub fn dump_mir<'a, 'gcx, 'tcx, F>( tcx: TyCtxt<'a, 'gcx, 'tcx>, - pass_num: Option<&Display>, + pass_num: Option<&dyn Display>, pass_name: &str, - disambiguator: &Display, + disambiguator: &dyn Display, source: MirSource, mir: &Mir<'tcx>, extra_data: F, ) where - F: FnMut(PassWhere, &mut Write) -> io::Result<()>, + F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>, { if !dump_enabled(tcx, pass_name, source) { return; @@ -127,15 +127,15 @@ pub fn dump_enabled<'a, 'gcx, 'tcx>( fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>( tcx: TyCtxt<'a, 'gcx, 'tcx>, - pass_num: Option<&Display>, + pass_num: Option<&dyn Display>, pass_name: &str, node_path: &str, - disambiguator: &Display, + disambiguator: &dyn Display, source: MirSource, mir: &Mir<'tcx>, mut extra_data: F, ) where - F: FnMut(PassWhere, &mut Write) -> io::Result<()>, + F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>, { let _: io::Result<()> = do catch { let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?; @@ -169,9 +169,9 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>( fn dump_path( tcx: TyCtxt<'_, '_, '_>, extension: &str, - pass_num: Option<&Display>, + pass_num: Option<&dyn Display>, pass_name: &str, - disambiguator: &Display, + disambiguator: &dyn Display, source: MirSource, ) -> PathBuf { let promotion_id = match source.promoted { @@ -217,9 +217,9 @@ fn dump_path( pub(crate) fn create_dump_file( tcx: TyCtxt<'_, '_, '_>, extension: &str, - pass_num: Option<&Display>, + pass_num: Option<&dyn Display>, pass_name: &str, - disambiguator: &Display, + disambiguator: &dyn Display, source: MirSource, ) -> io::Result { let file_path = dump_path(tcx, extension, pass_num, pass_name, disambiguator, source); @@ -233,7 +233,7 @@ pub(crate) fn create_dump_file( pub fn write_mir_pretty<'a, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'tcx>, single: Option, - w: &mut Write, + w: &mut dyn Write, ) -> io::Result<()> { writeln!( w, @@ -274,10 +274,10 @@ pub fn write_mir_fn<'a, 'gcx, 'tcx, F>( src: MirSource, mir: &Mir<'tcx>, extra_data: &mut F, - w: &mut Write, + w: &mut dyn Write, ) -> io::Result<()> where - F: FnMut(PassWhere, &mut Write) -> io::Result<()>, + F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>, { write_mir_intro(tcx, src, mir, w)?; for block in mir.basic_blocks().indices() { @@ -298,10 +298,10 @@ pub fn write_basic_block<'cx, 'gcx, 'tcx, F>( block: BasicBlock, mir: &Mir<'tcx>, extra_data: &mut F, - w: &mut Write, + w: &mut dyn Write, ) -> io::Result<()> where - F: FnMut(PassWhere, &mut Write) -> io::Result<()>, + F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>, { let data = &mir[block]; @@ -362,7 +362,7 @@ where /// a statement. fn write_extra<'cx, 'gcx, 'tcx, F>( tcx: TyCtxt<'cx, 'gcx, 'tcx>, - write: &mut Write, + write: &mut dyn Write, mut visit_op: F, ) -> io::Result<()> where @@ -450,7 +450,7 @@ fn write_scope_tree( tcx: TyCtxt, mir: &Mir, scope_tree: &FxHashMap>, - w: &mut Write, + w: &mut dyn Write, parent: VisibilityScope, depth: usize, ) -> io::Result<()> { @@ -515,7 +515,7 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'tcx>, src: MirSource, mir: &Mir, - w: &mut Write, + w: &mut dyn Write, ) -> io::Result<()> { write_mir_sig(tcx, src, mir, w)?; writeln!(w, "{{")?; @@ -553,7 +553,7 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>( Ok(()) } -fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write) -> io::Result<()> { +fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut dyn Write) -> io::Result<()> { let id = tcx.hir.as_local_node_id(src.def_id).unwrap(); let body_owner_kind = tcx.hir.body_owner_kind(id); match (body_owner_kind, src.promoted) { @@ -597,7 +597,7 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write) -> io::R Ok(()) } -fn write_temp_decls(mir: &Mir, w: &mut Write) -> io::Result<()> { +fn write_temp_decls(mir: &Mir, w: &mut dyn Write) -> io::Result<()> { // Compiler-introduced temporary types. for temp in mir.temps_iter() { writeln!( diff --git a/src/librustdoc/README.md b/src/librustdoc/README.md new file mode 100644 index 0000000000000..b0a5ae3718df3 --- /dev/null +++ b/src/librustdoc/README.md @@ -0,0 +1,172 @@ +# The walking tour of rustdoc + +Rustdoc is implemented entirely within the crate `librustdoc`. After partially compiling a crate to +get its AST (technically the HIR map) from rustc, librustdoc performs two major steps past that to +render a set of documentation: + +* "Clean" the AST into a form that's more suited to creating documentation (and slightly more + resistant to churn in the compiler). +* Use this cleaned AST to render a crate's documentation, one page at a time. + +Naturally, there's more than just this, and those descriptions simplify out lots of details, but +that's the high-level overview. + +(Side note: this is a library crate! The `rustdoc` binary is crated using the project in +`src/tools/rustdoc`. Note that literally all that does is call the `main()` that's in this crate's +`lib.rs`, though.) + +## Cheat sheet + +* Use `x.py build --stage 1 src/libstd src/tools/rustdoc` to make a useable rustdoc you can run on + other projects. + * Add `src/libtest` to be able to use `rustdoc --test`. + * If you've used `rustup toolchain link local /path/to/build/$TARGET/stage1` previously, then + after the previous build command, `cargo +local doc` will Just Work. +* Use `x.py doc --stage 1 src/libstd` to use this rustdoc to generate the standard library docs. + * The completed docs will be available in `build/$TARGET/doc/std`, though the bundle is meant to + be used as though you would copy out the `doc` folder to a web server, since that's where the + CSS/JS and landing page are. +* Most of the HTML printing code is in `html/format.rs` and `html/render.rs`. It's in a bunch of + `fmt::Display` implementations and supplementary functions. +* The types that got `Display` impls above are defined in `clean/mod.rs`, right next to the custom + `Clean` trait used to process them out of the rustc HIR. +* The bits specific to using rustdoc as a test harness are in `test.rs`. +* The Markdown renderer is loaded up in `html/markdown.rs`, including functions for extracting + doctests from a given block of Markdown. +* The tests on rustdoc *output* are located in `src/test/rustdoc`, where they're handled by the test + runner of rustbuild and the supplementary script `src/etc/htmldocck.py`. +* Tests on search index generation are located in `src/test/rustdoc-js`, as a series of JavaScript + files that encode queries on the standard library search index and expected results. + +## From crate to clean + +In `core.rs` are two central items: the `DocContext` struct, and the `run_core` function. The latter +is where rustdoc calls out to rustc to compile a crate to the point where rustdoc can take over. The +former is a state container used when crawling through a crate to gather its documentation. + +The main process of crate crawling is done in `clean/mod.rs` through several implementations of the +`Clean` trait defined within. This is a conversion trait, which defines one method: + +```rust +pub trait Clean { + fn clean(&self, cx: &DocContext) -> T; +} +``` + +`clean/mod.rs` also defines the types for the "cleaned" AST used later on to render documentation +pages. Each usually accompanies an implementation of `Clean` that takes some AST or HIR type from +rustc and converts it into the appropriate "cleaned" type. "Big" items like modules or associated +items may have some extra processing in its `Clean` implementation, but for the most part these +impls are straightforward conversions. The "entry point" to this module is the `impl Clean +for visit_ast::RustdocVisitor`, which is called by `run_core` above. + +You see, I actually lied a little earlier: There's another AST transformation that happens before +the events in `clean/mod.rs`. In `visit_ast.rs` is the type `RustdocVisitor`, which *actually* +crawls a `hir::Crate` to get the first intermediate representation, defined in `doctree.rs`. This +pass is mainly to get a few intermediate wrappers around the HIR types and to process visibility +and inlining. This is where `#[doc(inline)]`, `#[doc(no_inline)]`, and `#[doc(hidden)]` are +processed, as well as the logic for whether a `pub use` should get the full page or a "Reexport" +line in the module page. + +The other major thing that happens in `clean/mod.rs` is the collection of doc comments and +`#[doc=""]` attributes into a separate field of the Attributes struct, present on anything that gets +hand-written documentation. This makes it easier to collect this documentation later in the process. + +The primary output of this process is a clean::Crate with a tree of Items which describe the +publicly-documentable items in the target crate. + +### Hot potato + +Before moving on to the next major step, a few important "passes" occur over the documentation. +These do things like combine the separate "attributes" into a single string and strip leading +whitespace to make the document easier on the markdown parser, or drop items that are not public or +deliberately hidden with `#[doc(hidden)]`. These are all implemented in the `passes/` directory, one +file per pass. By default, all of these passes are run on a crate, but the ones regarding dropping +private/hidden items can be bypassed by passing `--document-private-items` to rustdoc. + +(Strictly speaking, you can fine-tune the passes run and even add your own, but [we're trying to +deprecate that][44136]. If you need finer-grain control over these passes, please let us know!) + +[44136]: https://github.com/rust-lang/rust/issues/44136 + +## From clean to crate + +This is where the "second phase" in rustdoc begins. This phase primarily lives in the `html/` +folder, and it all starts with `run()` in `html/render.rs`. This code is responsible for setting up +the `Context`, `SharedContext`, and `Cache` which are used during rendering, copying out the static +files which live in every rendered set of documentation (things like the fonts, CSS, and JavaScript +that live in `html/static/`), creating the search index, and printing out the source code rendering, +before beginning the process of rendering all the documentation for the crate. + +Several functions implemented directly on `Context` take the `clean::Crate` and set up some state +between rendering items or recursing on a module's child items. From here the "page rendering" +begins, via an enormous `write!()` call in `html/layout.rs`. The parts that actually generate HTML +from the items and documentation occurs within a series of `std::fmt::Display` implementations and +functions that pass around a `&mut std::fmt::Formatter`. The top-level implementation that writes +out the page body is the `impl<'a> fmt::Display for Item<'a>` in `html/render.rs`, which switches +out to one of several `item_*` functions based on the kind of `Item` being rendered. + +Depending on what kind of rendering code you're looking for, you'll probably find it either in +`html/render.rs` for major items like "what sections should I print for a struct page" or +`html/format.rs` for smaller component pieces like "how should I print a where clause as part of +some other item". + +Whenever rustdoc comes across an item that should print hand-written documentation alongside, it +calls out to `html/markdown.rs` which interfaces with the Markdown parser. This is exposed as a +series of types that wrap a string of Markdown, and implement `fmt::Display` to emit HTML text. It +takes special care to enable certain features like footnotes and tables and add syntax highlighting +to Rust code blocks (via `html/highlight.rs`) before running the Markdown parser. There's also a +function in here (`find_testable_code`) that specifically scans for Rust code blocks so the +test-runner code can find all the doctests in the crate. + +### From soup to nuts + +(alternate title: ["An unbroken thread that stretches from those first `Cell`s to us"][video]) + +[video]: https://www.youtube.com/watch?v=hOLAGYmUQV0 + +It's important to note that the AST cleaning can ask the compiler for information (crucially, +`DocContext` contains a `TyCtxt`), but page rendering cannot. The `clean::Crate` created within +`run_core` is passed outside the compiler context before being handed to `html::render::run`. This +means that a lot of the "supplementary data" that isn't immediately available inside an item's +definition, like which trait is the `Deref` trait used by the language, needs to be collected during +cleaning, stored in the `DocContext`, and passed along to the `SharedContext` during HTML rendering. +This manifests as a bunch of shared state, context variables, and `RefCell`s. + +Also of note is that some items that come from "asking the compiler" don't go directly into the +`DocContext` - for example, when loading items from a foreign crate, rustdoc will ask about trait +implementations and generate new `Item`s for the impls based on that information. This goes directly +into the returned `Crate` rather than roundabout through the `DocContext`. This way, these +implementations can be collected alongside the others, right before rendering the HTML. + +## Other tricks up its sleeve + +All this describes the process for generating HTML documentation from a Rust crate, but there are +couple other major modes that rustdoc runs in. It can also be run on a standalone Markdown file, or +it can run doctests on Rust code or standalone Markdown files. For the former, it shortcuts straight +to `html/markdown.rs`, optionally including a mode which inserts a Table of Contents to the output +HTML. + +For the latter, rustdoc runs a similar partial-compilation to get relevant documentation in +`test.rs`, but instead of going through the full clean and render process, it runs a much simpler +crate walk to grab *just* the hand-written documentation. Combined with the aforementioned +"`find_testable_code`" in `html/markdown.rs`, it builds up a collection of tests to run before +handing them off to the libtest test runner. One notable location in `test.rs` is the function +`make_test`, which is where hand-written doctests get transformed into something that can be +executed. + +## Dotting i's and crossing t's + +So that's rustdoc's code in a nutshell, but there's more things in the repo that deal with it. Since +we have the full `compiletest` suite at hand, there's a set of tests in `src/test/rustdoc` that make +sure the final HTML is what we expect in various situations. These tests also use a supplementary +script, `src/etc/htmldocck.py`, that allows it to look through the final HTML using XPath notation +to get a precise look at the output. The full description of all the commands available to rustdoc +tests is in `htmldocck.py`. + +In addition, there are separate tests for the search index and rustdoc's ability to query it. The +files in `src/test/rustdoc-js` each contain a different search query and the expected results, +broken out by search tab. These files are processed by a script in `src/tools/rustdoc-js` and the +Node.js runtime. These tests don't have as thorough of a writeup, but a broad example that features +results in all tabs can be found in `basic.js`. The basic idea is that you match a given `QUERY` +with a set of `EXPECTED` results, complete with the full item path of each item. diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index 844ff7a3c1252..5dd9c62775097 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -59,7 +59,7 @@ pub use version::UnicodeVersion; /// [`to_lowercase`]: ../../std/primitive.char.html#method.to_lowercase /// [`char`]: ../../std/primitive.char.html #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ToLowercase(CaseMappingIter); #[stable(feature = "rust1", since = "1.0.0")] @@ -81,7 +81,7 @@ impl FusedIterator for ToLowercase {} /// [`to_uppercase`]: ../../std/primitive.char.html#method.to_uppercase /// [`char`]: ../../std/primitive.char.html #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ToUppercase(CaseMappingIter); #[stable(feature = "rust1", since = "1.0.0")] @@ -95,7 +95,7 @@ impl Iterator for ToUppercase { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for ToUppercase {} -#[derive(Debug)] +#[derive(Debug, Clone)] enum CaseMappingIter { Three(char, char, char), Two(char, char),