Skip to content
Closed
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7aca34b
add readme for librustdoc
QuietMisdreavus Feb 16, 2018
8d893c1
review nits
QuietMisdreavus Feb 20, 2018
8e4ad29
Disable NEON on musl ARMv7
sanxiyn Feb 23, 2018
ffb6291
Improve --help performance for x.py
Phlosioneer Feb 27, 2018
89e55d1
Make TransitiveRelation thread safe. Avoid locking by using get_mut i…
Zoxc Dec 3, 2017
993e594
Run Rustfix on librustc
Manishearth Feb 23, 2018
753f61e
Perform manual fixups
Manishearth Feb 23, 2018
bde583a
Remove allow(bare_trait_object) from librustc
Manishearth Feb 23, 2018
28381bd
Run Rustfix on librustc_mir
Manishearth Feb 23, 2018
12e03ee
Perform manual fixups
Manishearth Feb 23, 2018
38676c6
Remove allow(bare_trait_object) from librustc_mir
Manishearth Feb 23, 2018
5ac4f62
impl Clone for ::std_unicode::char::{ToLowercase, ToUppercase}
strake Mar 1, 2018
70d5a46
Specialize Zip::nth for TrustedRandomAccess
scottmcm Mar 1, 2018
11fefeb
Add a Zip::nth test for side effects
scottmcm Mar 1, 2018
5105fc1
Fix braces
scottmcm Mar 1, 2018
2269ff5
Remove print_what_bootstrap_means
Phlosioneer Mar 2, 2018
900d511
Don't produce TOCs for doc markdown files
steveklabnik Mar 2, 2018
22fa7c0
Rollup merge of #48283 - QuietMisdreavus:rustdoc-readme, r=@Guillaume…
Manishearth Mar 3, 2018
414dddf
Rollup merge of #48466 - sanxiyn:no-neon, r=alexcrichton
Manishearth Mar 3, 2018
d54cf1b
Rollup merge of #48477 - Manishearth:dyn-trait-fixes, r=nmatsakis
Manishearth Mar 3, 2018
9f9ae29
Rollup merge of #48569 - Phlosioneer:x-py-help-optimization, r=petroc…
Manishearth Mar 3, 2018
5c56296
Rollup merge of #48587 - Zoxc:transitive-relation, r=nikomatsakis
Manishearth Mar 3, 2018
75ccd63
Rollup merge of #48629 - strake:char, r=alexcrichton
Manishearth Mar 3, 2018
d07dcd8
Rollup merge of #48635 - scottmcm:faster-zip-nth, r=kennytm
Manishearth Mar 3, 2018
f5fc69a
Rollup merge of #48680 - steveklabnik:no-toc, r=nikomatsakis
Manishearth Mar 3, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 15 additions & 25 deletions src/bootstrap/bootstrap.py
Original file line number Diff line number Diff line change
@@ -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)))
1 change: 1 addition & 0 deletions src/bootstrap/doc.rs
Original file line number Diff line number Diff line change
@@ -312,6 +312,7 @@ fn invoke_rustdoc(builder: &Builder, compiler: Compiler, target: Interned<String
cmd.arg("--html-after-content").arg(&footer)
.arg("--html-before-content").arg(&version_info)
.arg("--html-in-header").arg(&favicon)
.arg("--markdown-no-toc")
.arg("--markdown-playground-url")
.arg("https://play.rust-lang.org/")
.arg("-o").arg(&out)
29 changes: 29 additions & 0 deletions src/libcore/benches/iter.rs
Original file line number Diff line number Diff line change
@@ -281,3 +281,32 @@ bench_sums! {
bench_take_while_chain_ref_sum,
(0i64..1000000).chain(1000000..).take_while(|&x| x < 1111111)
}

// Checks whether Skip<Zip<A,B>> is as fast as Zip<Skip<A>, Skip<B>>, 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::<u64>();
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::<u64>();
assert_eq!(s, 2009900);
});
}
36 changes: 36 additions & 0 deletions src/libcore/iter/mod.rs
Original file line number Diff line number Diff line change
@@ -1045,6 +1045,11 @@ impl<A, B> Iterator for Zip<A, B> where A: Iterator, B: Iterator
fn size_hint(&self) -> (usize, Option<usize>) {
ZipImpl::size_hint(self)
}

#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
ZipImpl::nth(self, n)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
@@ -1065,6 +1070,14 @@ trait ZipImpl<A, B> {
fn new(a: A, b: B) -> Self;
fn next(&mut self) -> Option<Self::Item>;
fn size_hint(&self) -> (usize, Option<usize>);
fn nth(&mut self, n: usize) -> Option<Self::Item>;
fn super_nth(&mut self, mut n: usize) -> Option<Self::Item> {
while let Some(x) = self.next() {
if n == 0 { return Some(x) }
n -= 1;
}
None
}
fn next_back(&mut self) -> Option<Self::Item>
where A: DoubleEndedIterator + ExactSizeIterator,
B: DoubleEndedIterator + ExactSizeIterator;
@@ -1094,6 +1107,11 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
})
}

#[inline]
default fn nth(&mut self, n: usize) -> Option<Self::Item> {
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<A, B> ZipImpl<A, B> for Zip<A, B>
(len, Some(len))
}

#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
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,
37 changes: 37 additions & 0 deletions src/libcore/tests/iter.rs
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion src/librustc/dep_graph/debug.rs
Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@ pub struct EdgeFilter {
}

impl EdgeFilter {
pub fn new(test: &str) -> Result<EdgeFilter, Box<Error>> {
pub fn new(test: &str) -> Result<EdgeFilter, Box<dyn Error>> {
let parts: Vec<_> = test.split("->").collect();
if parts.len() != 2 {
Err(format!("expected a filter like `a&b -> c&d`, not `{}`", test).into())
8 changes: 4 additions & 4 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
@@ -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<DefIndex>,
resolver: &'a mut Resolver,
resolver: &'a mut dyn Resolver,
name_map: FxHashMap<Ident, Name>,

/// 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
2 changes: 1 addition & 1 deletion src/librustc/hir/map/collector.rs
Original file line number Diff line number Diff line change
@@ -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<MapEntry<'hir>>, Svh) {
2 changes: 1 addition & 1 deletion src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ pub struct DefCollector<'a> {
definitions: &'a mut Definitions,
parent_def: Option<DefIndex>,
expansion: Mark,
pub visit_macro_invoc: Option<&'a mut FnMut(MacroInvocationData)>,
pub visit_macro_invoc: Option<&'a mut dyn FnMut(MacroInvocationData)>,
}

pub struct MacroInvocationData {
5 changes: 4 additions & 1 deletion src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
@@ -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> {
22 changes: 11 additions & 11 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
@@ -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<vec::IntoIter<comments::Literal>>,
cur_cmnt: usize,
boxes: Vec<pp::Breaks>,
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<Write + 'a>,
ann: &'a PpAnn,
input: &mut dyn Read,
out: Box<dyn Write + 'a>,
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<Write + 'a>,
ann: &'a PpAnn,
input: &mut dyn Read,
out: Box<dyn Write + 'a>,
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<Write + 'a>,
ann: &'a PpAnn,
out: Box<dyn Write + 'a>,
ann: &'a dyn PpAnn,
comments: Option<Vec<comments::Comment>>,
literals: Option<Vec<comments::Literal>>)
-> State<'a> {
@@ -184,7 +184,7 @@ impl<'a> State<'a> {
}
}

pub fn to_string<F>(ann: &PpAnn, f: F) -> String
pub fn to_string<F>(ann: &dyn PpAnn, f: F) -> String
where F: FnOnce(&mut State) -> io::Result<()>
{
let mut wr = Vec::new();
4 changes: 2 additions & 2 deletions src/librustc/ich/hcx.rs
Original file line number Diff line number Diff line change
@@ -49,7 +49,7 @@ pub fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
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;

2 changes: 1 addition & 1 deletion src/librustc/infer/region_constraints/mod.rs
Original file line number Diff line number Diff line change
@@ -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);
2 changes: 0 additions & 2 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
@@ -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)]
4 changes: 2 additions & 2 deletions src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
@@ -280,8 +280,8 @@ pub trait EarlyLintPass: LintPass {
}

/// A lint pass boxed up as a trait object.
pub type EarlyLintPassObject = Box<EarlyLintPass + 'static>;
pub type LateLintPassObject = Box<for<'a, 'tcx> LateLintPass<'a, 'tcx> + 'static>;
pub type EarlyLintPassObject = Box<dyn EarlyLintPass + 'static>;
pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + 'static>;

/// Identifies a lint known to the compiler.
#[derive(Clone, Copy, Debug)]
8 changes: 4 additions & 4 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
@@ -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<Any>;
fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<dyn Any>;

// 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<Any>
fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<dyn Any>
{ 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<CrateNum> { 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 {
2 changes: 1 addition & 1 deletion src/librustc/middle/dependency_format.rs
Original file line number Diff line number Diff line change
@@ -319,7 +319,7 @@ fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<DependencyLis
// also skip this step entirely.
fn activate_injected_dep(injected: Option<CrateNum>,
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) {
6 changes: 3 additions & 3 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
@@ -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,
4 changes: 2 additions & 2 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
@@ -673,7 +673,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}

fn write_vars<F>(&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");
4 changes: 2 additions & 2 deletions src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ impl<'tcx> From<EvalErrorKind<'tcx>> 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<Error>),
MachineError(Box<dyn Error>),
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),
6 changes: 3 additions & 3 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
@@ -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<Fn(&mut getopts::Options) -> &mut getopts::Options>,
pub apply: Box<dyn Fn(&mut getopts::Options) -> &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 {
8 changes: 4 additions & 4 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
@@ -904,7 +904,7 @@ pub fn build_session_with_codemap(sopts: config::Options,
local_crate_source_file: Option<PathBuf>,
registry: errors::registry::Registry,
codemap: Rc<codemap::CodeMap>,
emitter_dest: Option<Box<Write + Send>>)
emitter_dest: Option<Box<dyn Write + Send>>)
-> 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<Emitter> = match (sopts.error_format, emitter_dest) {
let emitter: Box<dyn Emitter> = 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<Emitter> = match output {
let emitter: Box<dyn Emitter> = 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<Emitter> = match output {
let emitter: Box<dyn Emitter> = match output {
config::ErrorOutputType::HumanReadable(color_config) => {
Box::new(EmitterWriter::stderr(color_config, None, false, false))
}
2 changes: 1 addition & 1 deletion src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
@@ -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";
4 changes: 2 additions & 2 deletions src/librustc/traits/specialize/specialization_graph.rs
Original file line number Diff line number Diff line change
@@ -190,13 +190,13 @@ impl<'a, 'gcx, 'tcx> Children {
Ok(Inserted::BecameNewSibling(last_lint))
}

fn iter_mut(&'a mut self) -> Box<Iterator<Item = &'a mut DefId> + 'a> {
fn iter_mut(&'a mut self) -> Box<dyn Iterator<Item = &'a mut DefId> + '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<Iterator<Item = &'a mut DefId> + 'a> {
-> Box<dyn Iterator<Item = &'a mut DefId> + 'a> {
let nonblanket = self.nonblanket_impls.entry(sty).or_insert(vec![]).iter_mut();
Box::new(self.blanket_impls.iter_mut().chain(nonblanket))
}
10 changes: 5 additions & 5 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
@@ -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<Box<Any + Send>>,
pub tx_to_llvm_workers: mpsc::Sender<Box<dyn Any + Send>>,

output_filenames: Arc<OutputFilenames>,
}
@@ -1131,15 +1131,15 @@ 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<F, R>(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>,
resolutions: ty::Resolutions,
hir: hir_map::Map<'tcx>,
on_disk_query_result_cache: maps::OnDiskCache<'tcx>,
crate_name: &str,
tx: mpsc::Sender<Box<Any + Send>>,
tx: mpsc::Sender<Box<dyn Any + Send>>,
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<Any> {
pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Rc<dyn Any> {
self.cstore.crate_data_as_rc_any(cnum)
}

4 changes: 2 additions & 2 deletions src/librustc/ty/fold.rs
Original file line number Diff line number Diff line change
@@ -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<ty::BoundRegion, ty::Region<'tcx>>
}

2 changes: 1 addition & 1 deletion src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
@@ -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<ty::Destructor> {
let drop_trait = if let Some(def_id) = self.lang_items().drop_trait() {
def_id
2 changes: 1 addition & 1 deletion src/librustc/util/common.rs
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ pub struct ErrorReported;
thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));

lazy_static! {
static ref DEFAULT_HOOK: Box<Fn(&panic::PanicInfo) + Sync + Send + 'static> = {
static ref DEFAULT_HOOK: Box<dyn Fn(&panic::PanicInfo) + Sync + Send + 'static> = {
let hook = panic::take_hook();
panic::set_hook(Box::new(panic_hook));
hook
16 changes: 8 additions & 8 deletions src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
Original file line number Diff line number Diff line change
@@ -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
},
}
})
}
20 changes: 10 additions & 10 deletions src/librustc_data_structures/transitive_relation.rs
Original file line number Diff line number Diff line change
@@ -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<T: Clone + Debug + Eq + Hash + Clone> {
pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash> {
// List of elements. This is used to map from a T to a usize.
elements: Vec<T>,

@@ -32,14 +32,14 @@ pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash + Clone> {

// 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<Option<BitMatrix>>,
closure: Lock<Option<BitMatrix>>,
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
@@ -51,13 +51,13 @@ struct Edge {
target: Index,
}

impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
pub fn new() -> TransitiveRelation<T> {
TransitiveRelation {
elements: vec![],
map: FxHashMap(),
edges: vec![],
closure: RefCell::new(None),
closure: Lock::new(None),
}
}

@@ -72,7 +72,7 @@ impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
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<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
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<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
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<T> Decodable for TransitiveRelation<T>
.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) })
})
}
}
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
Original file line number Diff line number Diff line change
@@ -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,
4 changes: 2 additions & 2 deletions src/librustc_mir/borrow_check/nll/mod.rs
Original file line number Diff line number Diff line change
@@ -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,
};
4 changes: 2 additions & 2 deletions src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
Original file line number Diff line number Diff line change
@@ -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);
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
Original file line number Diff line number Diff line change
@@ -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)
}
}
8 changes: 4 additions & 4 deletions src/librustc_mir/borrow_check/nll/type_check/mod.rs
Original file line number Diff line number Diff line change
@@ -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<ty::Region<'tcx>>,
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,
) {
2 changes: 1 addition & 1 deletion src/librustc_mir/dataflow/mod.rs
Original file line number Diff line number Diff line change
@@ -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))
}
}
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/const_eval.rs
Original file line number Diff line number Diff line change
@@ -168,7 +168,7 @@ impl Error for ConstEvalError {
}
}

fn cause(&self) -> Option<&Error> {
fn cause(&self) -> Option<&dyn Error> {
None
}
}
1 change: 0 additions & 1 deletion src/librustc_mir/lib.rs
Original file line number Diff line number Diff line change
@@ -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)]
2 changes: 1 addition & 1 deletion src/librustc_mir/transform/dump_mir.rs
Original file line number Diff line number Diff line change
@@ -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>,
2 changes: 1 addition & 1 deletion src/librustc_mir/transform/mod.rs
Original file line number Diff line number Diff line change
@@ -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);
4 changes: 2 additions & 2 deletions src/librustc_mir/util/liveness.rs
Original file line number Diff line number Diff line change
@@ -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<BasicBlock, LocalSet>| {
let print = |w: &mut dyn Write, prefix, result: &IndexVec<BasicBlock, LocalSet>| {
let live: Vec<String> = mir.local_decls
.indices()
.filter(|i| result[block].contains(i))
40 changes: 20 additions & 20 deletions src/librustc_mir/util/pretty.rs
Original file line number Diff line number Diff line change
@@ -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<fs::File> {
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<DefId>,
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<VisibilityScope, Vec<VisibilityScope>>,
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!(
172 changes: 172 additions & 0 deletions src/librustdoc/README.md
Original file line number Diff line number Diff line change
@@ -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<T> {
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<Crate>
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.
6 changes: 3 additions & 3 deletions src/libstd_unicode/char.rs
Original file line number Diff line number Diff line change
@@ -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),