From 3008f53c95aeb4d5d6e4d9258a427e1372be63c7 Mon Sep 17 00:00:00 2001 From: Charlie Sheridan Date: Mon, 1 May 2017 13:49:15 -0400 Subject: Increase macro recursion limit to 1024 Fixes #22552 --- src/libsyntax/ext/expand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 2db295d0136..e811afffb2a 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1038,7 +1038,7 @@ impl<'feat> ExpansionConfig<'feat> { ExpansionConfig { crate_name: crate_name, features: None, - recursion_limit: 64, + recursion_limit: 1024, trace_mac: false, should_test: false, single_step: false, -- cgit 1.4.1-3-g733a5 From 05329e578014ee1e9a0a45658e5fba60f6b06e83 Mon Sep 17 00:00:00 2001 From: Tommy Ip Date: Thu, 4 May 2017 13:14:39 +0100 Subject: Remove use of `Self: Sized` from libsyntax The bound is not required for compiling but it prevents using `next_token()` from a trait object. Fixes #33506. --- src/libsyntax/parse/lexer/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index c2e5763237d..7d2a1b3c4a4 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -73,7 +73,7 @@ fn mk_sp(lo: BytePos, hi: BytePos) -> Span { } impl<'a> StringReader<'a> { - fn next_token(&mut self) -> TokenAndSpan where Self: Sized { + fn next_token(&mut self) -> TokenAndSpan { let res = self.try_next_token(); self.unwrap_or_abort(res) } -- cgit 1.4.1-3-g733a5 From d5863e99853c22c649a1787f40c47b60795ea93d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 4 May 2017 23:53:48 +0200 Subject: Add Options type in libtest and remove argument --- src/librustdoc/markdown.rs | 6 ++---- src/librustdoc/test.rs | 6 ++---- src/libsyntax/test.rs | 4 ++-- src/libtest/lib.rs | 45 ++++++++++++++++++++++++++++----------- src/tools/compiletest/src/main.rs | 2 +- 5 files changed, 39 insertions(+), 24 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index efeb8ea72ba..057ce69d9de 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -166,9 +166,7 @@ pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, old_find_testable_code(&input_str, &mut collector, DUMMY_SP); find_testable_code(&input_str, &mut collector, DUMMY_SP); test_args.insert(0, "rustdoctest".to_string()); - if display_warnings { - test_args.insert(1, "--display-stdout".to_string()); - } - testing::test_main(&test_args, collector.tests); + testing::test_main(&test_args, collector.tests, + testing::Options::new().display_output(display_warnings)); 0 } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 23462443eff..d5237d629cf 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -126,12 +126,10 @@ pub fn run(input: &str, } test_args.insert(0, "rustdoctest".to_string()); - if display_warnings { - test_args.insert(1, "--display-stdout".to_string()); - } testing::test_main(&test_args, - collector.tests.into_iter().collect()); + collector.tests.into_iter().collect(), + testing::Options::new().display_output(display_warnings)); 0 } diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 50380626d7f..91746a2edd9 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -442,7 +442,7 @@ We're going to be building a module that looks more or less like: mod __test { extern crate test (name = "test", vers = "..."); fn main() { - test::test_main_static(&::os::args()[], tests) + test::test_main_static(&::os::args()[], tests, test::Options::new()) } static tests : &'static [test::TestDescAndFn] = &[ @@ -478,7 +478,7 @@ fn mk_main(cx: &mut TestCtxt) -> P { // pub fn main() { // #![main] // use std::slice::AsSlice; - // test::test_main_static(::std::os::args().as_slice(), TESTS); + // test::test_main_static(::std::os::args().as_slice(), TESTS, test::Options::new()); // } let sp = ignored_span(cx, DUMMY_SP); diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 23c0c6065a8..35f2fbca69f 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -76,7 +76,7 @@ pub mod test { pub use {Bencher, TestName, TestResult, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg, TrIgnored, TrOk, Metric, MetricMap, StaticTestFn, StaticTestName, DynTestName, DynTestFn, run_test, test_main, test_main_static, filter_tests, - parse_opts, StaticBenchFn, ShouldPanic}; + parse_opts, StaticBenchFn, ShouldPanic, Options}; } pub mod stats; @@ -252,14 +252,34 @@ impl Clone for MetricMap { } } +/// In case we want to add other options as well, just add them in this struct. +#[derive(Copy, Clone, Debug)] +pub struct Options { + display_output: bool, +} + +impl Options { + pub fn new() -> Options { + Options { + display_output: false, + } + } + + pub fn display_output(mut self, display_output: bool) -> Options { + self.display_output = display_output; + self + } +} + // The default console test runner. It accepts the command line // arguments and a vector of test_descs. -pub fn test_main(args: &[String], tests: Vec) { - let opts = match parse_opts(args) { +pub fn test_main(args: &[String], tests: Vec, options: Options) { + let mut opts = match parse_opts(args) { Some(Ok(o)) => o, Some(Err(msg)) => panic!("{:?}", msg), None => return, }; + opts.options = options; if opts.list { if let Err(e) = list_tests_console(&opts, tests) { panic!("io error when listing tests: {:?}", e); @@ -301,7 +321,7 @@ pub fn test_main_static(tests: &[TestDescAndFn]) { } }) .collect(); - test_main(&args, owned_tests) + test_main(&args, owned_tests, Options::new()) } #[derive(Copy, Clone, Debug)] @@ -325,7 +345,7 @@ pub struct TestOpts { pub quiet: bool, pub test_threads: Option, pub skip: Vec, - pub display_stdout: bool, + pub options: Options, } impl TestOpts { @@ -344,7 +364,7 @@ impl TestOpts { quiet: false, test_threads: None, skip: vec![], - display_stdout: false, + options: Options::new(), } } } @@ -372,8 +392,7 @@ fn optgroups() -> Vec { getopts::optopt("", "color", "Configure coloring of output: auto = colorize if stdout is a tty and tests are run on serially (default); always = always colorize output; - never = never colorize output;", "auto|always|never"), - getopts::optflag("", "display-stdout", "to print stdout even if the test succeeds")] + never = never colorize output;", "auto|always|never")] } fn usage(binary: &str) { @@ -485,7 +504,7 @@ pub fn parse_opts(args: &[String]) -> Option { quiet: quiet, test_threads: test_threads, skip: matches.opt_strs("skip"), - display_stdout: matches.opt_present("display-stdout"), + options: Options::new(), }; Some(Ok(test_opts)) @@ -528,7 +547,7 @@ struct ConsoleTestState { failures: Vec<(TestDesc, Vec)>, not_failures: Vec<(TestDesc, Vec)>, max_name_len: usize, // number of columns to fill when aligning names - display_stdout: bool, + options: Options, } impl ConsoleTestState { @@ -556,7 +575,7 @@ impl ConsoleTestState { failures: Vec::new(), not_failures: Vec::new(), max_name_len: 0, - display_stdout: opts.display_stdout, + options: opts.options, }) } @@ -741,7 +760,7 @@ impl ConsoleTestState { pub fn write_run_finish(&mut self) -> io::Result { assert!(self.passed + self.failed + self.ignored + self.measured == self.total); - if self.display_stdout { + if self.options.display_output { self.write_outputs()?; } let success = self.failed == 0; @@ -942,7 +961,7 @@ fn should_sort_failures_before_printing_them() { max_name_len: 10, metrics: MetricMap::new(), failures: vec![(test_b, Vec::new()), (test_a, Vec::new())], - display_stdout: false, + options: Options::new(), not_failures: Vec::new(), }; diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 0d1795a182c..6fc7f9f07ac 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -336,7 +336,7 @@ pub fn test_opts(config: &Config) -> test::TestOpts { test_threads: None, skip: vec![], list: false, - display_stdout: false, + options: test::Options::new(), } } -- cgit 1.4.1-3-g733a5 From a9d3b3498e20a926d5b1662eb576d7db230ca110 Mon Sep 17 00:00:00 2001 From: F001 Date: Tue, 2 May 2017 23:31:47 -0700 Subject: Suggest `!` for bitwise negation when encountering a `~` --- src/libsyntax/parse/parser.rs | 13 +++++++++++++ src/test/ui/did_you_mean/issue-41679.rs | 13 +++++++++++++ src/test/ui/did_you_mean/issue-41679.stderr | 10 ++++++++++ 3 files changed, 36 insertions(+) create mode 100644 src/test/ui/did_you_mean/issue-41679.rs create mode 100644 src/test/ui/did_you_mean/issue-41679.stderr (limited to 'src/libsyntax') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d252963274e..f99f39dae6b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2700,6 +2700,19 @@ impl<'a> Parser<'a> { let (span, e) = self.interpolated_or_expr_span(e)?; (span, self.mk_unary(UnOp::Not, e)) } + // Suggest `!` for bitwise negation when encountering a `~` + token::Tilde => { + self.bump(); + let e = self.parse_prefix_expr(None); + let (span, e) = self.interpolated_or_expr_span(e)?; + let span_of_tilde = lo; + let mut err = self.diagnostic().struct_span_err(span_of_tilde, + "`~` can not be used as an unary operator"); + err.span_label(span_of_tilde, &"did you mean `!`?"); + err.help("use `!` instead of `~` if you meant to perform bitwise negation"); + err.emit(); + (span, self.mk_unary(UnOp::Not, e)) + } token::BinOp(token::Minus) => { self.bump(); let e = self.parse_prefix_expr(None); diff --git a/src/test/ui/did_you_mean/issue-41679.rs b/src/test/ui/did_you_mean/issue-41679.rs new file mode 100644 index 00000000000..5091b9efc34 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-41679.rs @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let x = ~1; +} diff --git a/src/test/ui/did_you_mean/issue-41679.stderr b/src/test/ui/did_you_mean/issue-41679.stderr new file mode 100644 index 00000000000..5a89ec96e24 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-41679.stderr @@ -0,0 +1,10 @@ +error: `~` can not be used as an unary operator + --> $DIR/issue-41679.rs:12:13 + | +12 | let x = ~1; + | ^ did you mean `!`? + | + = help: use `!` instead of `~` if you meant to perform bitwise negation + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 56411443f2421e6726413c212a697a45d45ddfa1 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Mon, 24 Apr 2017 16:27:07 -0700 Subject: Use diagnostics for trace_macro instead of println --- src/librustc_errors/lib.rs | 6 ++++++ src/libsyntax/ext/base.rs | 3 +++ src/libsyntax/ext/tt/macro_rules.rs | 4 +++- src/test/run-make/trace-macros-flag/Makefile | 9 --------- src/test/run-make/trace-macros-flag/hello.rs | 13 ------------- src/test/run-make/trace-macros-flag/hello.trace | 2 -- src/test/ui/macros/trace-macro.rs | 13 +++++++++++++ src/test/ui/macros/trace-macro.stderr | 14 ++++++++++++++ 8 files changed, 39 insertions(+), 25 deletions(-) delete mode 100644 src/test/run-make/trace-macros-flag/Makefile delete mode 100644 src/test/run-make/trace-macros-flag/hello.rs delete mode 100644 src/test/run-make/trace-macros-flag/hello.trace create mode 100644 src/test/ui/macros/trace-macro.rs create mode 100644 src/test/ui/macros/trace-macro.stderr (limited to 'src/libsyntax') diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 02d8297dd46..06aafa05052 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -388,6 +388,12 @@ impl Handler { pub fn span_note_without_error>(&self, sp: S, msg: &str) { self.emit(&sp.into(), msg, Note); } + pub fn span_label_without_error(&self, sp: Span, msg: &str, lbl: &str) { + let mut db = DiagnosticBuilder::new(self, Note, msg); + db.set_span(sp); + db.span_label(sp, &lbl); + db.emit(); + } pub fn span_unimpl>(&self, sp: S, msg: &str) -> ! { self.span_bug(sp, &format!("unimplemented {}", msg)); } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index fda026fec64..3bfa63a022d 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -765,6 +765,9 @@ impl<'a> ExtCtxt<'a> { pub fn span_bug(&self, sp: Span, msg: &str) -> ! { self.parse_sess.span_diagnostic.span_bug(sp, msg); } + pub fn span_label_without_error(&self, sp: Span, msg: &str, label: &str) { + self.parse_sess.span_diagnostic.span_label_without_error(sp, msg, label); + } pub fn bug(&self, msg: &str) -> ! { self.parse_sess.span_diagnostic.bug(msg); } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index be979960725..46c49ffb24c 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -93,7 +93,9 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, rhses: &[quoted::TokenTree]) -> Box { if cx.trace_macros() { - println!("{}! {{ {} }}", name, arg); + cx.span_label_without_error(sp, + &"trace_macro", + &format!("expands to `{}! {{ {} }}`", name, arg)); } // Which arm's failure should we report? (the one furthest along) diff --git a/src/test/run-make/trace-macros-flag/Makefile b/src/test/run-make/trace-macros-flag/Makefile deleted file mode 100644 index 3338e394e0e..00000000000 --- a/src/test/run-make/trace-macros-flag/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# This test verifies that "-Z trace-macros" works as it should. The traditional -# "hello world" program provides a small example of this as not only println! is -# listed, but also print! (since println! expands to this) - --include ../tools.mk - -all: - $(RUSTC) -Z trace-macros hello.rs > $(TMPDIR)/hello.out - diff -u $(TMPDIR)/hello.out hello.trace diff --git a/src/test/run-make/trace-macros-flag/hello.rs b/src/test/run-make/trace-macros-flag/hello.rs deleted file mode 100644 index 42d3d4c799d..00000000000 --- a/src/test/run-make/trace-macros-flag/hello.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - println!("Hello, World!"); -} diff --git a/src/test/run-make/trace-macros-flag/hello.trace b/src/test/run-make/trace-macros-flag/hello.trace deleted file mode 100644 index cf733339ead..00000000000 --- a/src/test/run-make/trace-macros-flag/hello.trace +++ /dev/null @@ -1,2 +0,0 @@ -println! { "Hello, World!" } -print! { concat ! ( "Hello, World!" , "\n" ) } diff --git a/src/test/ui/macros/trace-macro.rs b/src/test/ui/macros/trace-macro.rs new file mode 100644 index 00000000000..42d3d4c799d --- /dev/null +++ b/src/test/ui/macros/trace-macro.rs @@ -0,0 +1,13 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + println!("Hello, World!"); +} diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr new file mode 100644 index 00000000000..8f091ef9455 --- /dev/null +++ b/src/test/ui/macros/trace-macro.stderr @@ -0,0 +1,14 @@ +note: trace_macro + --> $DIR/trace-macro.rs:12:5 + | +12 | println!("Hello, World!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expands to `println! { "Hello, World!" }` + +note: trace_macro + --> $DIR/trace-macro.rs:12:5 + | +12 | println!("Hello, World!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expands to `print! { concat ! ( "Hello, World!" , "\n" ) }` + | + = note: this error originates in a macro outside of the current crate + -- cgit 1.4.1-3-g733a5 From 8c9ad8d72c5a3ad73af33e3ad9a409327645ac28 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Fri, 5 May 2017 21:49:59 -0700 Subject: Group "macro expansion" notes per call span --- src/librustc_errors/lib.rs | 8 +++++--- src/libsyntax/ext/base.rs | 13 +++++++++++-- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/ext/tt/macro_rules.rs | 12 ++++++------ src/test/ui/macros/trace-macro.rs | 2 ++ src/test/ui/macros/trace-macro.stderr | 15 +++++---------- 6 files changed, 30 insertions(+), 22 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 06aafa05052..db8c9ac306b 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -388,11 +388,13 @@ impl Handler { pub fn span_note_without_error>(&self, sp: S, msg: &str) { self.emit(&sp.into(), msg, Note); } - pub fn span_label_without_error(&self, sp: Span, msg: &str, lbl: &str) { + pub fn span_note_diag<'a>(&'a self, + sp: Span, + msg: &str) + -> DiagnosticBuilder<'a> { let mut db = DiagnosticBuilder::new(self, Note, msg); db.set_span(sp); - db.span_label(sp, &lbl); - db.emit(); + db } pub fn span_unimpl>(&self, sp: S, msg: &str) -> ! { self.span_bug(sp, &format!("unimplemented {}", msg)); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 3bfa63a022d..f731c5abdd6 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -24,6 +24,7 @@ use ptr::P; use symbol::Symbol; use util::small_vector::SmallVector; +use std::collections::HashMap; use std::path::PathBuf; use std::rc::Rc; use std::default::Default; @@ -643,6 +644,7 @@ pub struct ExtCtxt<'a> { pub resolver: &'a mut Resolver, pub resolve_err_count: usize, pub current_expansion: ExpansionData, + pub expansions: HashMap>, } impl<'a> ExtCtxt<'a> { @@ -662,6 +664,7 @@ impl<'a> ExtCtxt<'a> { module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }), directory_ownership: DirectoryOwnership::Owned, }, + expansions: HashMap::new(), } } @@ -765,8 +768,14 @@ impl<'a> ExtCtxt<'a> { pub fn span_bug(&self, sp: Span, msg: &str) -> ! { self.parse_sess.span_diagnostic.span_bug(sp, msg); } - pub fn span_label_without_error(&self, sp: Span, msg: &str, label: &str) { - self.parse_sess.span_diagnostic.span_label_without_error(sp, msg, label); + pub fn trace_macros_diag(&self) { + for (sp, notes) in self.expansions.iter() { + let mut db = self.parse_sess.span_diagnostic.span_note_diag(*sp, &"trace_macro"); + for note in notes { + db.note(¬e); + } + db.emit(); + } } pub fn bug(&self, msg: &str) -> ! { self.parse_sess.span_diagnostic.bug(msg); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 2db295d0136..31d4cc779c2 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -231,7 +231,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }, _ => unreachable!(), }; - + self.cx.trace_macros_diag(); krate } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 46c49ffb24c..f959ccc989e 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -27,8 +27,8 @@ use symbol::Symbol; use tokenstream::{TokenStream, TokenTree}; use std::cell::RefCell; -use std::collections::{HashMap}; -use std::collections::hash_map::{Entry}; +use std::collections::HashMap; +use std::collections::hash_map::Entry; use std::rc::Rc; pub struct ParserAnyMacro<'a> { @@ -85,7 +85,7 @@ impl TTMacroExpander for MacroRulesMacroExpander { } /// Given `lhses` and `rhses`, this is the new macro we create -fn generic_extension<'cx>(cx: &'cx ExtCtxt, +fn generic_extension<'cx>(cx: &'cx mut ExtCtxt, sp: Span, name: ast::Ident, arg: TokenStream, @@ -93,9 +93,9 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, rhses: &[quoted::TokenTree]) -> Box { if cx.trace_macros() { - cx.span_label_without_error(sp, - &"trace_macro", - &format!("expands to `{}! {{ {} }}`", name, arg)); + let sp = sp.macro_backtrace().last().map(|trace| trace.call_site).unwrap_or(sp); + let mut values: &mut Vec = cx.expansions.entry(sp).or_insert(vec![]); + values.push(format!("expands to `{}! {{ {} }}`", name, arg)); } // Which arm's failure should we report? (the one furthest along) diff --git a/src/test/ui/macros/trace-macro.rs b/src/test/ui/macros/trace-macro.rs index 42d3d4c799d..34f674ae016 100644 --- a/src/test/ui/macros/trace-macro.rs +++ b/src/test/ui/macros/trace-macro.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z trace-macros + fn main() { println!("Hello, World!"); } diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr index 8f091ef9455..09117a4ca74 100644 --- a/src/test/ui/macros/trace-macro.stderr +++ b/src/test/ui/macros/trace-macro.stderr @@ -1,14 +1,9 @@ note: trace_macro - --> $DIR/trace-macro.rs:12:5 + --> $DIR/trace-macro.rs:14:5 | -12 | println!("Hello, World!"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expands to `println! { "Hello, World!" }` - -note: trace_macro - --> $DIR/trace-macro.rs:12:5 - | -12 | println!("Hello, World!"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expands to `print! { concat ! ( "Hello, World!" , "\n" ) }` +14 | println!("Hello, World!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in a macro outside of the current crate + = note: expands to `println! { "Hello, World!" }` + = note: expands to `print! { concat ! ( "Hello, World!" , "/n" ) }` -- cgit 1.4.1-3-g733a5 From a257d5afb037b45581657fe343d5df5a100f8d70 Mon Sep 17 00:00:00 2001 From: acdenisSK Date: Sat, 6 May 2017 16:06:38 +0200 Subject: Fix "an" usage --- .travis.yml | 2 +- src/libsyntax/parse/parser.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libsyntax') diff --git a/.travis.yml b/.travis.yml index beb7b435cba..4fcf6f02def 100644 --- a/.travis.yml +++ b/.travis.yml @@ -194,7 +194,7 @@ after_failure: # Save tagged docker images we created and load them if they're available # Travis saves caches whether the build failed or not, nuke rustsrc if -# the failure was while updating it (as it may be in an bad state) +# the failure was while updating it (as it may be in a bad state) # https://github.com/travis-ci/travis-ci/issues/4472 before_cache: - docker history -q rust-ci | diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f99f39dae6b..268b3d08a80 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2707,7 +2707,7 @@ impl<'a> Parser<'a> { let (span, e) = self.interpolated_or_expr_span(e)?; let span_of_tilde = lo; let mut err = self.diagnostic().struct_span_err(span_of_tilde, - "`~` can not be used as an unary operator"); + "`~` can not be used as a unary operator"); err.span_label(span_of_tilde, &"did you mean `!`?"); err.help("use `!` instead of `~` if you meant to perform bitwise negation"); err.emit(); -- cgit 1.4.1-3-g733a5 From 0be875827fe64412f6c0eedc8f775f57137e7c55 Mon Sep 17 00:00:00 2001 From: ubsan Date: Wed, 3 May 2017 10:54:03 -0700 Subject: fix the easy features in libsyntax --- src/Cargo.lock | 2 +- src/libsyntax/Cargo.toml | 2 +- src/libsyntax/lib.rs | 7 +------ src/libsyntax/parse/mod.rs | 8 ++++++-- src/libsyntax/parse/parser.rs | 40 ++++++++++++++++++++-------------------- src/libsyntax/print/pprust.rs | 2 +- 6 files changed, 30 insertions(+), 31 deletions(-) (limited to 'src/libsyntax') diff --git a/src/Cargo.lock b/src/Cargo.lock index 21b167f6d42..3e0e6339692 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -858,8 +858,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "syntax" version = "0.0.0" dependencies = [ + "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_bitflags 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "serialize 0.0.0", diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml index 97d37266130..82e7cfa0032 100644 --- a/src/libsyntax/Cargo.toml +++ b/src/libsyntax/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["dylib"] [dependencies] serialize = { path = "../libserialize" } log = "0.3" -rustc_bitflags = { path = "../librustc_bitflags" } +bitflags = "0.8" syntax_pos = { path = "../libsyntax_pos" } rustc_errors = { path = "../librustc_errors" } rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 86ee1c5336d..89c67b88cbd 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -24,20 +24,15 @@ test(attr(deny(warnings))))] #![deny(warnings)] -#![feature(associated_consts)] -#![feature(const_fn)] -#![feature(optin_builtin_traits)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(str_escape)] #![feature(unicode)] #![feature(rustc_diagnostic_macros)] -#![feature(specialization)] #![feature(i128_type)] extern crate serialize; #[macro_use] extern crate log; -#[macro_use] #[no_link] extern crate rustc_bitflags; +#[macro_use] extern crate bitflags; extern crate std_unicode; pub extern crate rustc_errors as errors; extern crate syntax_pos; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 9d8f3b3d039..fe3ca1cf230 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -261,10 +261,14 @@ pub fn char_lit(lit: &str) -> (char, isize) { } } +pub fn escape_default(s: &str) -> String { + s.chars().map(char::escape_default).flat_map(|x| x).collect() +} + /// Parse a string representing a string literal into its final form. Does /// unescaping. pub fn str_lit(lit: &str) -> String { - debug!("parse_str_lit: given {}", lit.escape_default()); + debug!("parse_str_lit: given {}", escape_default(lit)); let mut res = String::with_capacity(lit.len()); // FIXME #8372: This could be a for-loop if it didn't borrow the iterator @@ -339,7 +343,7 @@ pub fn str_lit(lit: &str) -> String { /// Parse a string representing a raw string literal into its final form. The /// only operation this does is convert embedded CRLF into a single LF. pub fn raw_str_lit(lit: &str) -> String { - debug!("raw_str_lit: given {}", lit.escape_default()); + debug!("raw_str_lit: given {}", escape_default(lit)); let mut res = String::with_capacity(lit.len()); // FIXME #8372: This could be a for-loop if it didn't borrow the iterator diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d252963274e..0a59d2a089d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -64,7 +64,7 @@ use std::path::{self, Path, PathBuf}; use std::slice; bitflags! { - flags Restrictions: u8 { + pub flags Restrictions: u8 { const RESTRICTION_STMT_EXPR = 1 << 0, const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1, } @@ -2291,7 +2291,7 @@ impl<'a> Parser<'a> { let e = if self.token.can_begin_expr() && !(self.token == token::OpenDelim(token::Brace) && self.restrictions.contains( - Restrictions::RESTRICTION_NO_STRUCT_LITERAL)) { + RESTRICTION_NO_STRUCT_LITERAL)) { Some(self.parse_expr()?) } else { None @@ -2318,7 +2318,7 @@ impl<'a> Parser<'a> { // This is a struct literal, unless we're prohibited // from parsing struct literals here. let prohibited = self.restrictions.contains( - Restrictions::RESTRICTION_NO_STRUCT_LITERAL + RESTRICTION_NO_STRUCT_LITERAL ); if !prohibited { return self.parse_struct_expr(lo, pth, attrs); @@ -2722,7 +2722,7 @@ impl<'a> Parser<'a> { token::Ident(..) if self.token.is_keyword(keywords::In) => { self.bump(); let place = self.parse_expr_res( - Restrictions::RESTRICTION_NO_STRUCT_LITERAL, + RESTRICTION_NO_STRUCT_LITERAL, None, )?; let blk = self.parse_block()?; @@ -2785,7 +2785,7 @@ impl<'a> Parser<'a> { let cur_op_span = self.span; let restrictions = if op.is_assign_like() { - self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL + self.restrictions & RESTRICTION_NO_STRUCT_LITERAL } else { self.restrictions }; @@ -2835,13 +2835,13 @@ impl<'a> Parser<'a> { let rhs = match op.fixity() { Fixity::Right => self.with_res( - restrictions - Restrictions::RESTRICTION_STMT_EXPR, + restrictions - RESTRICTION_STMT_EXPR, |this| { this.parse_assoc_expr_with(op.precedence(), LhsExpr::NotYetParsed) }), Fixity::Left => self.with_res( - restrictions - Restrictions::RESTRICTION_STMT_EXPR, + restrictions - RESTRICTION_STMT_EXPR, |this| { this.parse_assoc_expr_with(op.precedence() + 1, LhsExpr::NotYetParsed) @@ -2849,7 +2849,7 @@ impl<'a> Parser<'a> { // We currently have no non-associative operators that are not handled above by // the special cases. The code is here only for future convenience. Fixity::None => self.with_res( - restrictions - Restrictions::RESTRICTION_STMT_EXPR, + restrictions - RESTRICTION_STMT_EXPR, |this| { this.parse_assoc_expr_with(op.precedence() + 1, LhsExpr::NotYetParsed) @@ -2959,7 +2959,7 @@ impl<'a> Parser<'a> { if self.token.can_begin_expr() { // parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`. if self.token == token::OpenDelim(token::Brace) { - return !self.restrictions.contains(Restrictions::RESTRICTION_NO_STRUCT_LITERAL); + return !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL); } true } else { @@ -2973,7 +2973,7 @@ impl<'a> Parser<'a> { return self.parse_if_let_expr(attrs); } let lo = self.prev_span; - let cond = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; + let cond = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?; let thn = self.parse_block()?; let mut els: Option> = None; let mut hi = thn.span; @@ -2992,7 +2992,7 @@ impl<'a> Parser<'a> { self.expect_keyword(keywords::Let)?; let pat = self.parse_pat()?; self.expect(&token::Eq)?; - let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; + let expr = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?; let thn = self.parse_block()?; let (hi, els) = if self.eat_keyword(keywords::Else) { let expr = self.parse_else_expr()?; @@ -3046,7 +3046,7 @@ impl<'a> Parser<'a> { let pat = self.parse_pat()?; self.expect_keyword(keywords::In)?; - let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; + let expr = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?; let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); @@ -3061,7 +3061,7 @@ impl<'a> Parser<'a> { if self.token.is_keyword(keywords::Let) { return self.parse_while_let_expr(opt_ident, span_lo, attrs); } - let cond = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; + let cond = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?; let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); let span = span_lo.to(body.span); @@ -3075,7 +3075,7 @@ impl<'a> Parser<'a> { self.expect_keyword(keywords::Let)?; let pat = self.parse_pat()?; self.expect(&token::Eq)?; - let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; + let expr = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?; let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); let span = span_lo.to(body.span); @@ -3105,7 +3105,7 @@ impl<'a> Parser<'a> { fn parse_match_expr(&mut self, mut attrs: ThinVec) -> PResult<'a, P> { let match_span = self.prev_span; let lo = self.prev_span; - let discriminant = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, + let discriminant = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?; if let Err(mut e) = self.expect(&token::OpenDelim(token::Brace)) { if self.token == token::Token::Semi { @@ -3146,7 +3146,7 @@ impl<'a> Parser<'a> { guard = Some(self.parse_expr()?); } self.expect(&token::FatArrow)?; - let expr = self.parse_expr_res(Restrictions::RESTRICTION_STMT_EXPR, None)?; + let expr = self.parse_expr_res(RESTRICTION_STMT_EXPR, None)?; let require_comma = !classify::expr_is_simple_block(&expr) @@ -3727,7 +3727,7 @@ impl<'a> Parser<'a> { self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) && // prevent `while catch {} {}`, `if catch {} {} else {}`, etc. - !self.restrictions.contains(Restrictions::RESTRICTION_NO_STRUCT_LITERAL) + !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL) } fn is_union_item(&self) -> bool { @@ -3799,7 +3799,7 @@ impl<'a> Parser<'a> { self.mk_expr(lo.to(hi), ExprKind::Path(None, pth), ThinVec::new()) }; - let expr = self.with_res(Restrictions::RESTRICTION_STMT_EXPR, |this| { + let expr = self.with_res(RESTRICTION_STMT_EXPR, |this| { let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?; this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr)) })?; @@ -3939,7 +3939,7 @@ impl<'a> Parser<'a> { // Remainder are line-expr stmts. let e = self.parse_expr_res( - Restrictions::RESTRICTION_STMT_EXPR, Some(attrs.into()))?; + RESTRICTION_STMT_EXPR, Some(attrs.into()))?; Stmt { id: ast::DUMMY_NODE_ID, span: lo.to(e.span), @@ -3952,7 +3952,7 @@ impl<'a> Parser<'a> { /// Is this expression a successfully-parsed statement? fn expr_is_complete(&mut self, e: &Expr) -> bool { - self.restrictions.contains(Restrictions::RESTRICTION_STMT_EXPR) && + self.restrictions.contains(RESTRICTION_STMT_EXPR) && !classify::expr_requires_semi_to_be_stmt(e) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a911c21ed98..0c7e8fda837 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -677,7 +677,7 @@ pub trait PrintState<'a> { style: ast::StrStyle) -> io::Result<()> { let st = match style { ast::StrStyle::Cooked => { - (format!("\"{}\"", st.escape_default())) + (format!("\"{}\"", parse::escape_default(st))) } ast::StrStyle::Raw(n) => { (format!("r{delim}\"{string}\"{delim}", -- cgit 1.4.1-3-g733a5 From 6a5e2a5a9eee3a504d89c014d80fd8f301226c27 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 27 Apr 2017 16:12:57 +0200 Subject: incr.comp.: Hash more pieces of crate metadata to detect changes there. --- src/librustc/dep_graph/dep_node.rs | 21 +- src/librustc/dep_graph/mod.rs | 1 + src/librustc/hir/svh.rs | 4 + src/librustc/ich/caching_codemap_view.rs | 35 +- src/librustc/ich/impls_cstore.rs | 40 + src/librustc/ich/impls_hir.rs | 8 + src/librustc/ich/impls_syntax.rs | 80 +- src/librustc/ich/mod.rs | 1 + src/librustc/middle/cstore.rs | 30 +- src/librustc/session/mod.rs | 23 +- src/librustc_data_structures/stable_hasher.rs | 10 + src/librustc_driver/driver.rs | 3 +- src/librustc_incremental/calculate_svh/mod.rs | 61 +- src/librustc_incremental/persist/data.rs | 6 +- src/librustc_incremental/persist/hash.rs | 82 +- src/librustc_incremental/persist/load.rs | 57 +- src/librustc_incremental/persist/save.rs | 11 +- src/librustc_metadata/astencode.rs | 4 +- src/librustc_metadata/creader.rs | 76 +- src/librustc_metadata/cstore.rs | 53 +- src/librustc_metadata/cstore_impl.rs | 58 +- src/librustc_metadata/decoder.rs | 236 +++-- src/librustc_metadata/encoder.rs | 973 +++++++++++---------- src/librustc_metadata/index_builder.rs | 122 +-- src/librustc_metadata/isolated_encoder.rs | 160 ++++ src/librustc_metadata/lib.rs | 1 + src/librustc_metadata/schema.rs | 77 +- src/librustc_trans/base.rs | 5 +- src/libsyntax/codemap.rs | 43 +- src/libsyntax_pos/lib.rs | 4 + .../remapped_paths_cc/auxiliary/extern_crate.rs | 24 + src/test/incremental/remapped_paths_cc/main.rs | 42 + 32 files changed, 1500 insertions(+), 851 deletions(-) create mode 100644 src/librustc/ich/impls_cstore.rs create mode 100644 src/librustc_metadata/isolated_encoder.rs create mode 100644 src/test/incremental/remapped_paths_cc/auxiliary/extern_crate.rs create mode 100644 src/test/incremental/remapped_paths_cc/main.rs (limited to 'src/libsyntax') diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 12e0d4d3ea2..af425a95fb1 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -51,6 +51,9 @@ pub enum DepNode { // in an extern crate. MetaData(D), + // Represents some piece of metadata global to its crate. + GlobalMetaData(D, GlobalMetaDataKind), + // Represents some artifact that we save to disk. Note that these // do not have a def-id as part of their identifier. WorkProduct(Arc), @@ -79,7 +82,6 @@ pub enum DepNode { MirKeys, LateLintCheck, TransCrateItem(D), - TransInlinedItem(D), TransWriteMetadata, CrateVariances, @@ -157,6 +159,7 @@ pub enum DepNode { DefSpan(D), Stability(D), Deprecation(D), + FileMap(D, Arc), } impl DepNode { @@ -234,7 +237,6 @@ impl DepNode { RegionMaps(ref d) => op(d).map(RegionMaps), RvalueCheck(ref d) => op(d).map(RvalueCheck), TransCrateItem(ref d) => op(d).map(TransCrateItem), - TransInlinedItem(ref d) => op(d).map(TransInlinedItem), AssociatedItems(ref d) => op(d).map(AssociatedItems), ItemSignature(ref d) => op(d).map(ItemSignature), ItemVariances(ref d) => op(d).map(ItemVariances), @@ -271,6 +273,8 @@ impl DepNode { DefSpan(ref d) => op(d).map(DefSpan), Stability(ref d) => op(d).map(Stability), Deprecation(ref d) => op(d).map(Deprecation), + GlobalMetaData(ref d, kind) => op(d).map(|d| GlobalMetaData(d, kind)), + FileMap(ref d, ref file_name) => op(d).map(|d| FileMap(d, file_name.clone())), } } } @@ -282,3 +286,16 @@ impl DepNode { /// them even in the absence of a tcx.) #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct WorkProductId(pub String); + +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +pub enum GlobalMetaDataKind { + Krate, + CrateDeps, + DylibDependencyFormats, + LangItems, + LangItemsMissing, + NativeLibraries, + CodeMap, + Impls, + ExportedSymbols, +} diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index 809bed939f5..822b61df7a4 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -22,6 +22,7 @@ mod thread; pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig}; pub use self::dep_node::DepNode; pub use self::dep_node::WorkProductId; +pub use self::dep_node::GlobalMetaDataKind; pub use self::graph::DepGraph; pub use self::graph::WorkProduct; pub use self::query::DepGraphQuery; diff --git a/src/librustc/hir/svh.rs b/src/librustc/hir/svh.rs index ae1f9d3028c..a6cfcb710ed 100644 --- a/src/librustc/hir/svh.rs +++ b/src/librustc/hir/svh.rs @@ -66,3 +66,7 @@ impl Decodable for Svh { .map(Svh::new) } } + +impl_stable_hash_for!(struct Svh { + hash +}); diff --git a/src/librustc/ich/caching_codemap_view.rs b/src/librustc/ich/caching_codemap_view.rs index 1278d9f5171..b21c3a2b216 100644 --- a/src/librustc/ich/caching_codemap_view.rs +++ b/src/librustc/ich/caching_codemap_view.rs @@ -8,10 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ty::TyCtxt; +use dep_graph::{DepGraph, DepNode}; +use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX}; +use rustc_data_structures::bitvec::BitVector; use std::rc::Rc; +use std::sync::Arc; use syntax::codemap::CodeMap; use syntax_pos::{BytePos, FileMap}; +use ty::TyCtxt; #[derive(Clone)] struct CacheEntry { @@ -20,30 +24,37 @@ struct CacheEntry { line_start: BytePos, line_end: BytePos, file: Rc, + file_index: usize, } pub struct CachingCodemapView<'tcx> { codemap: &'tcx CodeMap, line_cache: [CacheEntry; 3], time_stamp: usize, + dep_graph: DepGraph, + dep_tracking_reads: BitVector, } impl<'tcx> CachingCodemapView<'tcx> { pub fn new<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CachingCodemapView<'tcx> { let codemap = tcx.sess.codemap(); - let first_file = codemap.files.borrow()[0].clone(); + let files = codemap.files_untracked(); + let first_file = files[0].clone(); let entry = CacheEntry { time_stamp: 0, line_number: 0, line_start: BytePos(0), line_end: BytePos(0), file: first_file, + file_index: 0, }; CachingCodemapView { + dep_graph: tcx.dep_graph.clone(), codemap: codemap, line_cache: [entry.clone(), entry.clone(), entry.clone()], time_stamp: 0, + dep_tracking_reads: BitVector::new(files.len()), } } @@ -56,6 +67,10 @@ impl<'tcx> CachingCodemapView<'tcx> { for cache_entry in self.line_cache.iter_mut() { if pos >= cache_entry.line_start && pos < cache_entry.line_end { cache_entry.time_stamp = self.time_stamp; + if self.dep_tracking_reads.insert(cache_entry.file_index) { + self.dep_graph.read(dep_node(cache_entry)); + } + return Some((cache_entry.file.clone(), cache_entry.line_number, pos - cache_entry.line_start)); @@ -75,7 +90,7 @@ impl<'tcx> CachingCodemapView<'tcx> { // If the entry doesn't point to the correct file, fix it up if pos < cache_entry.file.start_pos || pos >= cache_entry.file.end_pos { let file_valid; - let files = self.codemap.files.borrow(); + let files = self.codemap.files_untracked(); if files.len() > 0 { let file_index = self.codemap.lookup_filemap_idx(pos); @@ -83,6 +98,7 @@ impl<'tcx> CachingCodemapView<'tcx> { if pos >= file.start_pos && pos < file.end_pos { cache_entry.file = file; + cache_entry.file_index = file_index; file_valid = true; } else { file_valid = false; @@ -104,8 +120,21 @@ impl<'tcx> CachingCodemapView<'tcx> { cache_entry.line_end = line_bounds.1; cache_entry.time_stamp = self.time_stamp; + if self.dep_tracking_reads.insert(cache_entry.file_index) { + self.dep_graph.read(dep_node(cache_entry)); + } + return Some((cache_entry.file.clone(), cache_entry.line_number, pos - cache_entry.line_start)); } } + +fn dep_node(cache_entry: &CacheEntry) -> DepNode { + let def_id = DefId { + krate: CrateNum::from_u32(cache_entry.file.crate_of_origin), + index: CRATE_DEF_INDEX, + }; + let name = Arc::new(cache_entry.file.name.clone()); + DepNode::FileMap(def_id, name) +} diff --git a/src/librustc/ich/impls_cstore.rs b/src/librustc/ich/impls_cstore.rs new file mode 100644 index 00000000000..e95dbdd15c5 --- /dev/null +++ b/src/librustc/ich/impls_cstore.rs @@ -0,0 +1,40 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! This module contains `HashStable` implementations for various data types +//! from rustc::middle::cstore in no particular order. + +use middle; + +impl_stable_hash_for!(enum middle::cstore::DepKind { + UnexportedMacrosOnly, + MacrosOnly, + Implicit, + Explicit +}); + +impl_stable_hash_for!(enum middle::cstore::NativeLibraryKind { + NativeStatic, + NativeStaticNobundle, + NativeFramework, + NativeUnknown +}); + +impl_stable_hash_for!(struct middle::cstore::NativeLibrary { + kind, + name, + cfg, + foreign_items +}); + +impl_stable_hash_for!(enum middle::cstore::LinkagePreference { + RequireDynamic, + RequireStatic +}); diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 3aeee1c1b98..abc51601b6e 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -1120,3 +1120,11 @@ impl_stable_hash_for!(struct hir::def::Export { def, span }); + +impl<'a, 'tcx> HashStable> for ::middle::lang_items::LangItem { + fn hash_stable(&self, + _: &mut StableHashingContext<'a, 'tcx>, + hasher: &mut StableHasher) { + ::std::hash::Hash::hash(self, hasher); + } +} diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 26734500001..7138db01339 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -19,7 +19,9 @@ use std::mem; use syntax::ast; use syntax::parse::token; use syntax::tokenstream; -use syntax_pos::Span; +use syntax_pos::{Span, FileMap}; + +use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; @@ -299,3 +301,79 @@ fn hash_token<'a, 'tcx, W: StableHasherResult>(token: &token::Token, token::Token::Shebang(val) => val.hash_stable(hcx, hasher), } } + +impl_stable_hash_for_spanned!(::syntax::ast::NestedMetaItemKind); + +impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind { + MetaItem(meta_item), + Literal(lit) +}); + +impl_stable_hash_for!(struct ::syntax::ast::MetaItem { + name, + node, + span +}); + +impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind { + Word, + List(nested_items), + NameValue(lit) +}); + +impl<'a, 'tcx> HashStable> for FileMap { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'tcx>, + hasher: &mut StableHasher) { + let FileMap { + ref name, + name_was_remapped, + crate_of_origin, + // Do not hash the source as it is not encoded + src: _, + start_pos, + end_pos: _, + ref lines, + ref multibyte_chars, + } = *self; + + name.hash_stable(hcx, hasher); + name_was_remapped.hash_stable(hcx, hasher); + + DefId { + krate: CrateNum::from_u32(crate_of_origin), + index: CRATE_DEF_INDEX, + }.hash_stable(hcx, hasher); + + // We only hash the relative position within this filemap + let lines = lines.borrow(); + lines.len().hash_stable(hcx, hasher); + for &line in lines.iter() { + stable_byte_pos(line, start_pos).hash_stable(hcx, hasher); + } + + // We only hash the relative position within this filemap + let multibyte_chars = multibyte_chars.borrow(); + multibyte_chars.len().hash_stable(hcx, hasher); + for &char_pos in multibyte_chars.iter() { + stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher); + } + } +} + +fn stable_byte_pos(pos: ::syntax_pos::BytePos, + filemap_start: ::syntax_pos::BytePos) + -> u32 { + pos.0 - filemap_start.0 +} + +fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar, + filemap_start: ::syntax_pos::BytePos) + -> (u32, u32) { + let ::syntax_pos::MultiByteChar { + pos, + bytes, + } = mbc; + + (pos.0 - filemap_start.0, bytes as u32) +} diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs index d70ed051ac4..d881a1cc45a 100644 --- a/src/librustc/ich/mod.rs +++ b/src/librustc/ich/mod.rs @@ -19,6 +19,7 @@ mod caching_codemap_view; mod hcx; mod impls_const_math; +mod impls_cstore; mod impls_hir; mod impls_mir; mod impls_ty; diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 303c5059e7c..16b3fcd2f8c 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -23,6 +23,7 @@ // probably get a better home if someone can find one. use hir::def; +use dep_graph::DepNode; use hir::def_id::{CrateNum, DefId, DefIndex}; use hir::map as hir_map; use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData}; @@ -161,7 +162,16 @@ pub struct ExternCrate { pub struct EncodedMetadata { pub raw_data: Vec, - pub hashes: Vec, + pub hashes: EncodedMetadataHashes, +} + +impl EncodedMetadata { + pub fn new() -> EncodedMetadata { + EncodedMetadata { + raw_data: Vec::new(), + hashes: EncodedMetadataHashes::new(), + } + } } /// The hash for some metadata that (when saving) will be exported @@ -173,6 +183,24 @@ pub struct EncodedMetadataHash { pub hash: ich::Fingerprint, } +/// The hash for some metadata that (when saving) will be exported +/// from this crate, or which (when importing) was exported by an +/// upstream crate. +#[derive(Debug, RustcEncodable, RustcDecodable, Clone)] +pub struct EncodedMetadataHashes { + pub entry_hashes: Vec, + pub global_hashes: Vec<(DepNode<()>, ich::Fingerprint)>, +} + +impl EncodedMetadataHashes { + pub fn new() -> EncodedMetadataHashes { + EncodedMetadataHashes { + entry_hashes: Vec::new(), + global_hashes: Vec::new(), + } + } +} + /// A store of Rust crates, through with their metadata /// can be accessed. pub trait CrateStore { diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index ec3eaa124c3..2e2d5a6bd4d 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -11,8 +11,8 @@ pub use self::code_stats::{CodeStats, DataTypeKind, FieldInfo}; pub use self::code_stats::{SizeKind, TypeSizeInfo, VariantInfo}; -use dep_graph::DepGraph; -use hir::def_id::{CrateNum, DefIndex}; +use dep_graph::{DepGraph, DepNode}; +use hir::def_id::{DefId, CrateNum, DefIndex, CRATE_DEF_INDEX}; use lint; use middle::cstore::CrateStore; use middle::dependency_format; @@ -32,7 +32,7 @@ use syntax::parse::ParseSess; use syntax::symbol::Symbol; use syntax::{ast, codemap}; use syntax::feature_gate::AttributeType; -use syntax_pos::{Span, MultiSpan}; +use syntax_pos::{Span, MultiSpan, FileMap}; use rustc_back::{LinkerFlavor, PanicStrategy}; use rustc_back::target::Target; @@ -48,6 +48,7 @@ use std::io::Write; use std::rc::Rc; use std::fmt; use std::time::Duration; +use std::sync::Arc; use libc::c_int; mod code_stats; @@ -627,6 +628,22 @@ pub fn build_session_(sopts: config::Options, } }; let target_cfg = config::build_target_config(&sopts, &span_diagnostic); + + // Hook up the codemap with a callback that allows it to register FileMap + // accesses with the dependency graph. + let cm_depgraph = dep_graph.clone(); + let codemap_dep_tracking_callback = Box::new(move |filemap: &FileMap| { + let def_id = DefId { + krate: CrateNum::from_u32(filemap.crate_of_origin), + index: CRATE_DEF_INDEX, + }; + let name = Arc::new(filemap.name.clone()); + let dep_node = DepNode::FileMap(def_id, name); + + cm_depgraph.read(dep_node); + }); + codemap.set_dep_tracking_callback(codemap_dep_tracking_callback); + let p_s = parse::ParseSess::with_span_handler(span_diagnostic, codemap); let default_sysroot = match sopts.maybe_sysroot { Some(_) => None, diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 95f063976d4..635b95d861d 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -283,6 +283,16 @@ impl HashStable for str { } } + +impl HashStable for String { + #[inline] + fn hash_stable(&self, + hcx: &mut CTX, + hasher: &mut StableHasher) { + (&self[..]).hash_stable(hcx, hasher); + } +} + impl HashStable for bool { #[inline] fn hash_stable(&self, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 9f0f567b6ce..5f14890665c 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1155,8 +1155,7 @@ fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) { // Build a list of files used to compile the output and // write Makefile-compatible dependency rules let files: Vec = sess.codemap() - .files - .borrow() + .files() .iter() .filter(|fmap| fmap.is_real_file()) .filter(|fmap| !fmap.is_imported()) diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs index c67866971e1..6f5cc1f3f45 100644 --- a/src/librustc_incremental/calculate_svh/mod.rs +++ b/src/librustc_incremental/calculate_svh/mod.rs @@ -29,9 +29,10 @@ use std::cell::RefCell; use std::hash::Hash; +use std::sync::Arc; use rustc::dep_graph::DepNode; use rustc::hir; -use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; +use rustc::hir::def_id::{LOCAL_CRATE, CRATE_DEF_INDEX, DefId}; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ich::{Fingerprint, StableHashingContext}; use rustc::ty::TyCtxt; @@ -60,6 +61,10 @@ impl IncrementalHashesMap { } } + pub fn get(&self, k: &DepNode) -> Option<&Fingerprint> { + self.hashes.get(k) + } + pub fn insert(&mut self, k: DepNode, v: Fingerprint) -> Option { self.hashes.insert(k, v) } @@ -140,14 +145,34 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> { let hcx = &mut self.hcx; let mut item_hashes: Vec<_> = self.hashes.iter() - .map(|(item_dep_node, &item_hash)| { - // convert from a DepNode tp a - // DepNode where the u64 is the - // hash of the def-id's def-path: - let item_dep_node = - item_dep_node.map_def(|&did| Some(hcx.def_path_hash(did))) - .unwrap(); - (item_dep_node, item_hash) + .filter_map(|(item_dep_node, &item_hash)| { + // This `match` determines what kinds of nodes + // go into the SVH: + match *item_dep_node { + DepNode::Hir(_) | + DepNode::HirBody(_) => { + // We want to incoporate these into the + // SVH. + } + DepNode::FileMap(..) => { + // These don't make a semantic + // difference, filter them out. + return None + } + ref other => { + bug!("Found unexpected DepNode during \ + SVH computation: {:?}", + other) + } + } + + // Convert from a DepNode to a + // DepNode where the u64 is the hash of + // the def-id's def-path: + let item_dep_node = + item_dep_node.map_def(|&did| Some(hcx.def_path_hash(did))) + .unwrap(); + Some((item_dep_node, item_hash)) }) .collect(); item_hashes.sort_unstable(); // avoid artificial dependencies on item ordering @@ -229,6 +254,24 @@ pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) visitor.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, macro_def); visitor.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, macro_def); } + + for filemap in tcx.sess + .codemap() + .files_untracked() + .iter() + .filter(|fm| !fm.is_imported()) { + assert_eq!(LOCAL_CRATE.as_u32(), filemap.crate_of_origin); + let def_id = DefId { + krate: LOCAL_CRATE, + index: CRATE_DEF_INDEX, + }; + let name = Arc::new(filemap.name.clone()); + let dep_node = DepNode::FileMap(def_id, name); + let mut hasher = IchHasher::new(); + filemap.hash_stable(&mut visitor.hcx, &mut hasher); + let fingerprint = hasher.finish(); + visitor.hashes.insert(dep_node, fingerprint); + } }); tcx.sess.perf_stats.incr_comp_hashes_count.set(visitor.hashes.len() as u64); diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs index 8a1af5dd08d..b016ff34bc5 100644 --- a/src/librustc_incremental/persist/data.rs +++ b/src/librustc_incremental/persist/data.rs @@ -99,7 +99,11 @@ pub struct SerializedMetadataHashes { /// where `X` refers to some item in this crate. That `X` will be /// a `DefPathIndex` that gets retracted to the current `DefId` /// (matching the one found in this structure). - pub hashes: Vec, + pub entry_hashes: Vec, + + /// This map contains fingerprints that are not specific to some DefId but + /// describe something global to the whole crate. + pub global_hashes: Vec<(DepNode<()>, Fingerprint)>, /// For each DefIndex (as it occurs in SerializedMetadataHash), this /// map stores the DefPathIndex (as it occurs in DefIdDirectory), so diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs index 9d8ff57e03b..5bc442deafa 100644 --- a/src/librustc_incremental/persist/hash.rs +++ b/src/librustc_incremental/persist/hash.rs @@ -9,7 +9,7 @@ // except according to those terms. use rustc::dep_graph::DepNode; -use rustc::hir::def_id::{CrateNum, DefId}; +use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; use rustc::hir::svh::Svh; use rustc::ich::Fingerprint; use rustc::ty::TyCtxt; @@ -23,11 +23,15 @@ use super::data::*; use super::fs::*; use super::file_format; +use std::hash::Hash; +use std::fmt::Debug; + pub struct HashContext<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, incremental_hashes_map: &'a IncrementalHashesMap, item_metadata_hashes: FxHashMap, crate_hashes: FxHashMap, + global_metadata_hashes: FxHashMap, Fingerprint>, } impl<'a, 'tcx> HashContext<'a, 'tcx> { @@ -39,6 +43,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { incremental_hashes_map: incremental_hashes_map, item_metadata_hashes: FxHashMap(), crate_hashes: FxHashMap(), + global_metadata_hashes: FxHashMap(), } } @@ -46,9 +51,11 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { match *dep_node { DepNode::Krate | DepNode::Hir(_) | - DepNode::HirBody(_) => + DepNode::HirBody(_) | + DepNode::FileMap(..) => true, - DepNode::MetaData(def_id) => !def_id.is_local(), + DepNode::MetaData(def_id) | + DepNode::GlobalMetaData(def_id, _) => !def_id.is_local(), _ => false, } } @@ -60,7 +67,8 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { } // HIR nodes (which always come from our crate) are an input: - DepNode::Hir(def_id) | DepNode::HirBody(def_id) => { + DepNode::Hir(def_id) | + DepNode::HirBody(def_id) => { assert!(def_id.is_local(), "cannot hash HIR for non-local def-id {:?} => {:?}", def_id, @@ -69,12 +77,30 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { Some(self.incremental_hashes_map[dep_node]) } + DepNode::FileMap(def_id, ref name) => { + if def_id.is_local() { + Some(self.incremental_hashes_map[dep_node]) + } else { + Some(self.metadata_hash(DepNode::FileMap(def_id, name.clone()), + def_id.krate, + |this| &mut this.global_metadata_hashes)) + } + } + // MetaData from other crates is an *input* to us. // MetaData nodes from *our* crates are an *output*; we // don't hash them, but we do compute a hash for them and // save it for others to use. DepNode::MetaData(def_id) if !def_id.is_local() => { - Some(self.metadata_hash(def_id)) + Some(self.metadata_hash(def_id, + def_id.krate, + |this| &mut this.item_metadata_hashes)) + } + + DepNode::GlobalMetaData(def_id, kind) => { + Some(self.metadata_hash(DepNode::GlobalMetaData(def_id, kind), + def_id.krate, + |this| &mut this.global_metadata_hashes)) } _ => { @@ -87,33 +113,37 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { } } - fn metadata_hash(&mut self, def_id: DefId) -> Fingerprint { - debug!("metadata_hash(def_id={:?})", def_id); + fn metadata_hash(&mut self, + key: K, + cnum: CrateNum, + cache: C) + -> Fingerprint + where K: Hash + Eq + Debug, + C: Fn(&mut Self) -> &mut FxHashMap, + { + debug!("metadata_hash(key={:?})", key); - assert!(!def_id.is_local()); + debug_assert!(cnum != LOCAL_CRATE); loop { // check whether we have a result cached for this def-id - if let Some(&hash) = self.item_metadata_hashes.get(&def_id) { - debug!("metadata_hash: def_id={:?} hash={:?}", def_id, hash); + if let Some(&hash) = cache(self).get(&key) { return hash; } // check whether we did not find detailed metadata for this // krate; in that case, we just use the krate's overall hash - if let Some(&svh) = self.crate_hashes.get(&def_id.krate) { - debug!("metadata_hash: def_id={:?} crate_hash={:?}", def_id, svh); - + if let Some(&svh) = self.crate_hashes.get(&cnum) { // micro-"optimization": avoid a cache miss if we ask // for metadata from this particular def-id again. let fingerprint = svh_to_fingerprint(svh); - self.item_metadata_hashes.insert(def_id, fingerprint); + cache(self).insert(key, fingerprint); return fingerprint; } // otherwise, load the data and repeat. - self.load_data(def_id.krate); - assert!(self.crate_hashes.contains_key(&def_id.krate)); + self.load_data(cnum); + assert!(self.crate_hashes.contains_key(&cnum)); } } @@ -191,7 +221,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { } let serialized_hashes = SerializedMetadataHashes::decode(&mut decoder)?; - for serialized_hash in serialized_hashes.hashes { + for serialized_hash in serialized_hashes.entry_hashes { // the hashes are stored with just a def-index, which is // always relative to the old crate; convert that to use // our internal crate number @@ -202,6 +232,24 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { debug!("load_from_data: def_id={:?} hash={}", def_id, serialized_hash.hash); assert!(old.is_none(), "already have hash for {:?}", def_id); } + + for (dep_node, fingerprint) in serialized_hashes.global_hashes { + // Here we need to remap the CrateNum in the DepNode. + let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; + let dep_node = match dep_node { + DepNode::GlobalMetaData(_, kind) => DepNode::GlobalMetaData(def_id, kind), + DepNode::FileMap(_, name) => DepNode::FileMap(def_id, name), + other => { + bug!("unexpected DepNode variant: {:?}", other) + } + }; + + // record the hash for this dep-node + debug!("load_from_data: def_node={:?} hash={}", dep_node, fingerprint); + let old = self.global_metadata_hashes.insert(dep_node.clone(), fingerprint); + assert!(old.is_none(), "already have hash for {:?}", dep_node); + } + Ok(()) } } diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index ed2e2e72ee7..7fad600d105 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -240,35 +240,40 @@ fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut hcx = HashContext::new(tcx, incremental_hashes_map); let mut dirty_nodes = FxHashMap(); + let print_removed_message = |dep_node: &DepNode<_>| { + if tcx.sess.opts.debugging_opts.incremental_dump_hash { + println!("node {:?} is dirty as it was removed", dep_node); + } + + debug!("initial_dirty_nodes: {:?} is dirty as it was removed", dep_node); + }; + for hash in serialized_hashes { if let Some(dep_node) = retraced.map(&hash.dep_node) { - let current_hash = hcx.hash(&dep_node).unwrap(); - if current_hash == hash.hash { - debug!("initial_dirty_nodes: {:?} is clean (hash={:?})", - dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), - current_hash); - continue; - } + if let Some(current_hash) = hcx.hash(&dep_node) { + if current_hash == hash.hash { + debug!("initial_dirty_nodes: {:?} is clean (hash={:?})", + dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), + current_hash); + continue; + } - if tcx.sess.opts.debugging_opts.incremental_dump_hash { - println!("node {:?} is dirty as hash is {:?} was {:?}", - dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), - current_hash, - hash.hash); - } + if tcx.sess.opts.debugging_opts.incremental_dump_hash { + println!("node {:?} is dirty as hash is {:?} was {:?}", + dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), + current_hash, + hash.hash); + } - debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}", - dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), - current_hash, - hash.hash); - } else { - if tcx.sess.opts.debugging_opts.incremental_dump_hash { - println!("node {:?} is dirty as it was removed", - hash.dep_node); + debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}", + dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), + current_hash, + hash.hash); + } else { + print_removed_message(&hash.dep_node); } - - debug!("initial_dirty_nodes: {:?} is dirty as it was removed", - hash.dep_node); + } else { + print_removed_message(&hash.dep_node); } dirty_nodes.insert(hash.dep_node.clone(), hash.dep_node.clone()); @@ -382,8 +387,8 @@ fn load_prev_metadata_hashes(tcx: TyCtxt, debug!("load_prev_metadata_hashes() - Mapping DefIds"); - assert_eq!(serialized_hashes.index_map.len(), serialized_hashes.hashes.len()); - for serialized_hash in serialized_hashes.hashes { + assert_eq!(serialized_hashes.index_map.len(), serialized_hashes.entry_hashes.len()); + for serialized_hash in serialized_hashes.entry_hashes { let def_path_index = serialized_hashes.index_map[&serialized_hash.def_index]; if let Some(def_id) = retraced.def_id(def_path_index) { let old = output.insert(def_id, serialized_hash.hash); diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 1864009fbdf..06e49e9d37c 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -12,7 +12,7 @@ use rustc::dep_graph::DepNode; use rustc::hir::def_id::DefId; use rustc::hir::svh::Svh; use rustc::ich::Fingerprint; -use rustc::middle::cstore::EncodedMetadataHash; +use rustc::middle::cstore::EncodedMetadataHashes; use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; @@ -34,7 +34,7 @@ use super::work_product; pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, incremental_hashes_map: &IncrementalHashesMap, - metadata_hashes: &[EncodedMetadataHash], + metadata_hashes: &EncodedMetadataHashes, svh: Svh) { debug!("save_dep_graph()"); let _ignore = tcx.dep_graph.in_ignore(); @@ -240,18 +240,19 @@ pub fn encode_dep_graph(preds: &Predecessors, pub fn encode_metadata_hashes(tcx: TyCtxt, svh: Svh, - metadata_hashes: &[EncodedMetadataHash], + metadata_hashes: &EncodedMetadataHashes, builder: &mut DefIdDirectoryBuilder, current_metadata_hashes: &mut FxHashMap, encoder: &mut Encoder) -> io::Result<()> { let mut serialized_hashes = SerializedMetadataHashes { - hashes: metadata_hashes.to_vec(), + entry_hashes: metadata_hashes.entry_hashes.to_vec(), + global_hashes: metadata_hashes.global_hashes.to_vec(), index_map: FxHashMap() }; if tcx.sess.opts.debugging_opts.query_dep_graph { - for serialized_hash in &serialized_hashes.hashes { + for serialized_hash in &serialized_hashes.entry_hashes { let def_id = DefId::local(serialized_hash.def_index); // Store entry in the index_map diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index d9008ce555c..6c02ac7eafe 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -10,7 +10,7 @@ use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; -use index_builder::EntryBuilder; +use isolated_encoder::IsolatedEncoder; use schema::*; use rustc::hir; @@ -31,7 +31,7 @@ impl_stable_hash_for!(struct Ast<'tcx> { rvalue_promotable_to_static }); -impl<'a, 'b, 'tcx> EntryBuilder<'a, 'b, 'tcx> { +impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> { pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy> { let body = self.tcx.hir.body(body_id); let lazy_body = self.lazy(body); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 966e814e337..58c2d3b2c12 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -12,9 +12,10 @@ use cstore::{self, CStore, CrateSource, MetadataBlob}; use locator::{self, CratePaths}; -use schema::CrateRoot; +use schema::{CrateRoot, Tracked}; -use rustc::hir::def_id::{CrateNum, DefIndex}; +use rustc::dep_graph::{DepNode, GlobalMetaDataKind}; +use rustc::hir::def_id::{DefId, CrateNum, DefIndex, CRATE_DEF_INDEX}; use rustc::hir::svh::Svh; use rustc::middle::cstore::DepKind; use rustc::session::Session; @@ -311,7 +312,8 @@ impl<'a> CrateLoader<'a> { crate_root.def_path_table.decode(&metadata) }); - let exported_symbols = crate_root.exported_symbols.decode(&metadata).collect(); + let exported_symbols = crate_root.exported_symbols + .map(|x| x.decode(&metadata).collect()); let mut cmeta = cstore::CrateMetadata { name: name, @@ -333,16 +335,27 @@ impl<'a> CrateLoader<'a> { rlib: rlib, rmeta: rmeta, }, - dllimport_foreign_items: FxHashSet(), + // Initialize this with an empty set. The field is populated below + // after we were able to deserialize its contents. + dllimport_foreign_items: Tracked::new(FxHashSet()), }; - let dllimports: Vec<_> = cmeta.get_native_libraries().iter() - .filter(|lib| relevant_lib(self.sess, lib) && - lib.kind == cstore::NativeLibraryKind::NativeUnknown) - .flat_map(|lib| &lib.foreign_items) - .map(|id| *id) - .collect(); - cmeta.dllimport_foreign_items.extend(dllimports); + let dllimports: Tracked> = cmeta + .root + .native_libraries + .map(|native_libraries| { + let native_libraries: Vec<_> = native_libraries.decode(&cmeta) + .collect(); + native_libraries + .iter() + .filter(|lib| relevant_lib(self.sess, lib) && + lib.kind == cstore::NativeLibraryKind::NativeUnknown) + .flat_map(|lib| lib.foreign_items.iter()) + .map(|id| *id) + .collect() + }); + + cmeta.dllimport_foreign_items = dllimports; let cmeta = Rc::new(cmeta); self.cstore.set_crate_data(cnum, cmeta.clone()); @@ -493,10 +506,16 @@ impl<'a> CrateLoader<'a> { return cstore::CrateNumMap::new(); } + let dep_node = DepNode::GlobalMetaData(DefId { krate, index: CRATE_DEF_INDEX }, + GlobalMetaDataKind::CrateDeps); + // The map from crate numbers in the crate we're resolving to local crate numbers. // We map 0 and all other holes in the map to our parent crate. The "additional" // self-dependencies should be harmless. - ::std::iter::once(krate).chain(crate_root.crate_deps.decode(metadata).map(|dep| { + ::std::iter::once(krate).chain(crate_root.crate_deps + .get(&self.sess.dep_graph, dep_node) + .decode(metadata) + .map(|dep| { debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); if dep.kind == DepKind::UnexportedMacrosOnly { return krate; @@ -654,7 +673,9 @@ impl<'a> CrateLoader<'a> { /// Look for a plugin registrar. Returns library path, crate /// SVH and DefIndex of the registrar function. - pub fn find_plugin_registrar(&mut self, span: Span, name: &str) + pub fn find_plugin_registrar(&mut self, + span: Span, + name: &str) -> Option<(PathBuf, Symbol, DefIndex)> { let ekrate = self.read_extension_crate(span, &ExternCrateInfo { name: Symbol::intern(name), @@ -740,13 +761,17 @@ impl<'a> CrateLoader<'a> { let mut runtime_found = false; let mut needs_panic_runtime = attr::contains_name(&krate.attrs, "needs_panic_runtime"); + + let dep_graph = &self.sess.dep_graph; + self.cstore.iter_crate_data(|cnum, data| { - needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime(); - if data.is_panic_runtime() { + needs_panic_runtime = needs_panic_runtime || + data.needs_panic_runtime(dep_graph); + if data.is_panic_runtime(dep_graph) { // Inject a dependency from all #![needs_panic_runtime] to this // #![panic_runtime] crate. self.inject_dependency_if(cnum, "a panic runtime", - &|data| data.needs_panic_runtime()); + &|data| data.needs_panic_runtime(dep_graph)); runtime_found = runtime_found || data.dep_kind.get() == DepKind::Explicit; } }); @@ -782,11 +807,11 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. - if !data.is_panic_runtime() { + if !data.is_panic_runtime(dep_graph) { self.sess.err(&format!("the crate `{}` is not a panic runtime", name)); } - if data.panic_strategy() != desired_strategy { + if data.panic_strategy(dep_graph) != desired_strategy { self.sess.err(&format!("the crate `{}` does not have the panic \ strategy `{}`", name, desired_strategy.desc())); @@ -794,7 +819,7 @@ impl<'a> CrateLoader<'a> { self.sess.injected_panic_runtime.set(Some(cnum)); self.inject_dependency_if(cnum, "a panic runtime", - &|data| data.needs_panic_runtime()); + &|data| data.needs_panic_runtime(dep_graph)); } fn inject_sanitizer_runtime(&mut self) { @@ -862,7 +887,7 @@ impl<'a> CrateLoader<'a> { PathKind::Crate, dep_kind); // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime - if !data.is_sanitizer_runtime() { + if !data.is_sanitizer_runtime(&self.sess.dep_graph) { self.sess.err(&format!("the crate `{}` is not a sanitizer runtime", name)); } @@ -878,12 +903,13 @@ impl<'a> CrateLoader<'a> { // also bail out as we don't need to implicitly inject one. let mut needs_allocator = false; let mut found_required_allocator = false; + let dep_graph = &self.sess.dep_graph; self.cstore.iter_crate_data(|cnum, data| { - needs_allocator = needs_allocator || data.needs_allocator(); - if data.is_allocator() { + needs_allocator = needs_allocator || data.needs_allocator(dep_graph); + if data.is_allocator(dep_graph) { info!("{} required by rlib and is an allocator", data.name()); self.inject_dependency_if(cnum, "an allocator", - &|data| data.needs_allocator()); + &|data| data.needs_allocator(dep_graph)); found_required_allocator = found_required_allocator || data.dep_kind.get() == DepKind::Explicit; } @@ -937,14 +963,14 @@ impl<'a> CrateLoader<'a> { // Sanity check the crate we loaded to ensure that it is indeed an // allocator. - if !data.is_allocator() { + if !data.is_allocator(dep_graph) { self.sess.err(&format!("the allocator crate `{}` is not tagged \ with #![allocator]", data.name())); } self.sess.injected_allocator.set(Some(cnum)); self.inject_dependency_if(cnum, "an allocator", - &|data| data.needs_allocator()); + &|data| data.needs_allocator(dep_graph)); } fn inject_dependency_if(&self, diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 72ad1d75a56..8d53e7d49ee 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -12,9 +12,9 @@ // crates and libraries use locator; -use schema; +use schema::{self, Tracked}; -use rustc::dep_graph::DepGraph; +use rustc::dep_graph::{DepGraph, DepNode, GlobalMetaDataKind}; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefIndex, DefId}; use rustc::hir::map::definitions::DefPathTable; use rustc::hir::svh::Svh; @@ -83,14 +83,14 @@ pub struct CrateMetadata { /// compilation support. pub def_path_table: DefPathTable, - pub exported_symbols: FxHashSet, + pub exported_symbols: Tracked>, pub dep_kind: Cell, pub source: CrateSource, pub proc_macros: Option)>>, // Foreign items imported from a dylib (Windows only) - pub dllimport_foreign_items: FxHashSet, + pub dllimport_foreign_items: Tracked>, } pub struct CStore { @@ -269,8 +269,8 @@ impl CrateMetadata { self.root.disambiguator } - pub fn is_staged_api(&self) -> bool { - for attr in self.get_item_attrs(CRATE_DEF_INDEX).iter() { + pub fn is_staged_api(&self, dep_graph: &DepGraph) -> bool { + for attr in self.get_item_attrs(CRATE_DEF_INDEX, dep_graph).iter() { if attr.path == "stable" || attr.path == "unstable" { return true; } @@ -278,42 +278,51 @@ impl CrateMetadata { false } - pub fn is_allocator(&self) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX); + pub fn is_allocator(&self, dep_graph: &DepGraph) -> bool { + let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph); attr::contains_name(&attrs, "allocator") } - pub fn needs_allocator(&self) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX); + pub fn needs_allocator(&self, dep_graph: &DepGraph) -> bool { + let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph); attr::contains_name(&attrs, "needs_allocator") } - pub fn is_panic_runtime(&self) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX); + pub fn is_panic_runtime(&self, dep_graph: &DepGraph) -> bool { + let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph); attr::contains_name(&attrs, "panic_runtime") } - pub fn needs_panic_runtime(&self) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX); + pub fn needs_panic_runtime(&self, dep_graph: &DepGraph) -> bool { + let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph); attr::contains_name(&attrs, "needs_panic_runtime") } - pub fn is_compiler_builtins(&self) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX); + pub fn is_compiler_builtins(&self, dep_graph: &DepGraph) -> bool { + let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph); attr::contains_name(&attrs, "compiler_builtins") } - pub fn is_sanitizer_runtime(&self) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX); + pub fn is_sanitizer_runtime(&self, dep_graph: &DepGraph) -> bool { + let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph); attr::contains_name(&attrs, "sanitizer_runtime") } - pub fn is_no_builtins(&self) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX); + pub fn is_no_builtins(&self, dep_graph: &DepGraph) -> bool { + let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph); attr::contains_name(&attrs, "no_builtins") } - pub fn panic_strategy(&self) -> PanicStrategy { - self.root.panic_strategy.clone() + pub fn panic_strategy(&self, dep_graph: &DepGraph) -> PanicStrategy { + let def_id = DefId { + krate: self.cnum, + index: CRATE_DEF_INDEX, + }; + let dep_node = DepNode::GlobalMetaData(def_id, GlobalMetaDataKind::Krate); + + self.root + .panic_strategy + .get(dep_graph, dep_node) + .clone() } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index a1794ec2d82..6fa6a868605 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -24,7 +24,7 @@ use rustc::ty::{self, TyCtxt}; use rustc::ty::maps::Providers; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc::dep_graph::DepNode; +use rustc::dep_graph::{DepNode, GlobalMetaDataKind}; use rustc::hir::map::{DefKey, DefPath, DisambiguatedDefPathData}; use rustc::util::nodemap::{NodeSet, DefIdMap}; use rustc_back::PanicStrategy; @@ -147,8 +147,8 @@ impl CrateStore for cstore::CStore { fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]> { - self.dep_graph.read(DepNode::MetaData(def_id)); - self.get_crate_data(def_id.krate).get_item_attrs(def_id.index) + self.get_crate_data(def_id.krate) + .get_item_attrs(def_id.index, &self.dep_graph) } fn fn_arg_names(&self, did: DefId) -> Vec @@ -168,7 +168,7 @@ impl CrateStore for cstore::CStore { } let mut result = vec![]; self.iter_crate_data(|_, cdata| { - cdata.get_implementations_for_trait(filter, &mut result) + cdata.get_implementations_for_trait(filter, &self.dep_graph, &mut result) }); result } @@ -216,70 +216,82 @@ impl CrateStore for cstore::CStore { } fn is_exported_symbol(&self, def_id: DefId) -> bool { - self.get_crate_data(def_id.krate).exported_symbols.contains(&def_id.index) + let data = self.get_crate_data(def_id.krate); + let dep_node = data.metadata_dep_node(GlobalMetaDataKind::ExportedSymbols); + data.exported_symbols + .get(&self.dep_graph, dep_node) + .contains(&def_id.index) } fn is_dllimport_foreign_item(&self, def_id: DefId) -> bool { if def_id.krate == LOCAL_CRATE { self.dllimport_foreign_items.borrow().contains(&def_id.index) } else { - self.get_crate_data(def_id.krate).is_dllimport_foreign_item(def_id.index) + self.get_crate_data(def_id.krate) + .is_dllimport_foreign_item(def_id.index, &self.dep_graph) } } fn dylib_dependency_formats(&self, cnum: CrateNum) -> Vec<(CrateNum, LinkagePreference)> { - self.get_crate_data(cnum).get_dylib_dependency_formats() + self.get_crate_data(cnum).get_dylib_dependency_formats(&self.dep_graph) } fn dep_kind(&self, cnum: CrateNum) -> DepKind { - self.get_crate_data(cnum).dep_kind.get() + let data = self.get_crate_data(cnum); + let dep_node = data.metadata_dep_node(GlobalMetaDataKind::CrateDeps); + self.dep_graph.read(dep_node); + data.dep_kind.get() } fn export_macros(&self, cnum: CrateNum) { - if self.get_crate_data(cnum).dep_kind.get() == DepKind::UnexportedMacrosOnly { - self.get_crate_data(cnum).dep_kind.set(DepKind::MacrosOnly) + let data = self.get_crate_data(cnum); + let dep_node = data.metadata_dep_node(GlobalMetaDataKind::CrateDeps); + + self.dep_graph.read(dep_node); + if data.dep_kind.get() == DepKind::UnexportedMacrosOnly { + data.dep_kind.set(DepKind::MacrosOnly) } } fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)> { - self.get_crate_data(cnum).get_lang_items() + self.get_crate_data(cnum).get_lang_items(&self.dep_graph) } fn missing_lang_items(&self, cnum: CrateNum) -> Vec { - self.get_crate_data(cnum).get_missing_lang_items() + self.get_crate_data(cnum).get_missing_lang_items(&self.dep_graph) } fn is_staged_api(&self, cnum: CrateNum) -> bool { - self.get_crate_data(cnum).is_staged_api() + self.get_crate_data(cnum).is_staged_api(&self.dep_graph) } fn is_allocator(&self, cnum: CrateNum) -> bool { - self.get_crate_data(cnum).is_allocator() + self.get_crate_data(cnum).is_allocator(&self.dep_graph) } fn is_panic_runtime(&self, cnum: CrateNum) -> bool { - self.get_crate_data(cnum).is_panic_runtime() + self.get_crate_data(cnum).is_panic_runtime(&self.dep_graph) } fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { - self.get_crate_data(cnum).is_compiler_builtins() + self.get_crate_data(cnum).is_compiler_builtins(&self.dep_graph) } fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { - self.get_crate_data(cnum).is_sanitizer_runtime() + self.get_crate_data(cnum).is_sanitizer_runtime(&self.dep_graph) } fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy { - self.get_crate_data(cnum).panic_strategy() + self.get_crate_data(cnum).panic_strategy(&self.dep_graph) } fn crate_name(&self, cnum: CrateNum) -> Symbol @@ -325,16 +337,16 @@ impl CrateStore for cstore::CStore { fn native_libraries(&self, cnum: CrateNum) -> Vec { - self.get_crate_data(cnum).get_native_libraries() + self.get_crate_data(cnum).get_native_libraries(&self.dep_graph) } fn exported_symbols(&self, cnum: CrateNum) -> Vec { - self.get_crate_data(cnum).get_exported_symbols() + self.get_crate_data(cnum).get_exported_symbols(&self.dep_graph) } fn is_no_builtins(&self, cnum: CrateNum) -> bool { - self.get_crate_data(cnum).is_no_builtins() + self.get_crate_data(cnum).is_no_builtins(&self.dep_graph) } fn retrace_path(&self, @@ -401,7 +413,7 @@ impl CrateStore for cstore::CStore { let body = filemap_to_stream(&sess.parse_sess, filemap); // Mark the attrs as used - let attrs = data.get_item_attrs(id.index); + let attrs = data.get_item_attrs(id.index, &self.dep_graph); for attr in attrs.iter() { attr::mark_used(attr); } @@ -483,7 +495,7 @@ impl CrateStore for cstore::CStore { reachable: &NodeSet) -> EncodedMetadata { - encoder::encode_metadata(tcx, self, link_meta, reachable) + encoder::encode_metadata(tcx, link_meta, reachable) } fn metadata_encoding_version(&self) -> &[u8] diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ae755adcf5f..820b5a68bcc 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -13,6 +13,7 @@ use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary}; use schema::*; +use rustc::dep_graph::{DepGraph, DepNode, GlobalMetaDataKind}; use rustc::hir::map::{DefKey, DefPath, DefPathData}; use rustc::hir; @@ -404,10 +405,14 @@ impl<'a, 'tcx> MetadataBlob { Lazy::with_position(pos).decode(self) } - pub fn list_crate_metadata(&self, out: &mut io::Write) -> io::Result<()> { + pub fn list_crate_metadata(&self, + out: &mut io::Write) -> io::Result<()> { write!(out, "=External Dependencies=\n")?; let root = self.get_root(); - for (i, dep) in root.crate_deps.decode(self).enumerate() { + for (i, dep) in root.crate_deps + .get_untracked() + .decode(self) + .enumerate() { write!(out, "{} {}-{}\n", i + 1, dep.name, dep.hash)?; } write!(out, "\n")?; @@ -653,8 +658,13 @@ impl<'a, 'tcx> CrateMetadata { } /// Iterates over the language items in the given crate. - pub fn get_lang_items(&self) -> Vec<(DefIndex, usize)> { - self.root.lang_items.decode(self).collect() + pub fn get_lang_items(&self, dep_graph: &DepGraph) -> Vec<(DefIndex, usize)> { + let dep_node = self.metadata_dep_node(GlobalMetaDataKind::LangItems); + self.root + .lang_items + .get(dep_graph, dep_node) + .decode(self) + .collect() } /// Iterates over each child of the given item. @@ -853,13 +863,17 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_item_attrs(&self, node_id: DefIndex) -> Rc<[ast::Attribute]> { + pub fn get_item_attrs(&self, + node_id: DefIndex, + dep_graph: &DepGraph) -> Rc<[ast::Attribute]> { let (node_as, node_index) = (node_id.address_space().index(), node_id.as_array_index()); if self.is_proc_macro(node_id) { return Rc::new([]); } + dep_graph.read(DepNode::MetaData(self.local_def_id(node_id))); + if let Some(&Some(ref val)) = self.attribute_cache.borrow()[node_as].get(node_index) { return val.clone(); @@ -924,7 +938,10 @@ impl<'a, 'tcx> CrateMetadata { .collect() } - pub fn get_implementations_for_trait(&self, filter: Option, result: &mut Vec) { + pub fn get_implementations_for_trait(&self, + filter: Option, + dep_graph: &DepGraph, + result: &mut Vec) { // Do a reverse lookup beforehand to avoid touching the crate_num // hash map in the loop below. let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) { @@ -935,7 +952,8 @@ impl<'a, 'tcx> CrateMetadata { }; // FIXME(eddyb) Make this O(1) instead of O(n). - for trait_impls in self.root.impls.decode(self) { + let dep_node = self.metadata_dep_node(GlobalMetaDataKind::Impls); + for trait_impls in self.root.impls.get(dep_graph, dep_node).decode(self) { if filter.is_some() && filter != Some(trait_impls.trait_id) { continue; } @@ -958,13 +976,29 @@ impl<'a, 'tcx> CrateMetadata { } - pub fn get_native_libraries(&self) -> Vec { - self.root.native_libraries.decode(self).collect() + pub fn get_native_libraries(&self, + dep_graph: &DepGraph) + -> Vec { + let dep_node = self.metadata_dep_node(GlobalMetaDataKind::NativeLibraries); + self.root + .native_libraries + .get(dep_graph, dep_node) + .decode(self) + .collect() } - pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> { + pub fn get_dylib_dependency_formats(&self, + dep_graph: &DepGraph) + -> Vec<(CrateNum, LinkagePreference)> { + let def_id = DefId { + krate: self.cnum, + index: CRATE_DEF_INDEX, + }; + let dep_node = DepNode::GlobalMetaData(def_id, + GlobalMetaDataKind::DylibDependencyFormats); self.root .dylib_dependency_formats + .get(dep_graph, dep_node) .decode(self) .enumerate() .flat_map(|(i, link)| { @@ -974,8 +1008,13 @@ impl<'a, 'tcx> CrateMetadata { .collect() } - pub fn get_missing_lang_items(&self) -> Vec { - self.root.lang_items_missing.decode(self).collect() + pub fn get_missing_lang_items(&self, dep_graph: &DepGraph) -> Vec { + let dep_node = self.metadata_dep_node(GlobalMetaDataKind::LangItemsMissing); + self.root + .lang_items_missing + .get(dep_graph, dep_node) + .decode(self) + .collect() } pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec { @@ -988,8 +1027,13 @@ impl<'a, 'tcx> CrateMetadata { arg_names.decode(self).collect() } - pub fn get_exported_symbols(&self) -> Vec { - self.exported_symbols.iter().map(|&index| self.local_def_id(index)).collect() + pub fn get_exported_symbols(&self, dep_graph: &DepGraph) -> Vec { + let dep_node = self.metadata_dep_node(GlobalMetaDataKind::ExportedSymbols); + self.exported_symbols + .get(dep_graph, dep_node) + .iter() + .map(|&index| self.local_def_id(index)) + .collect() } pub fn get_macro(&self, id: DefIndex) -> (ast::Name, MacroDef) { @@ -1018,8 +1062,11 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn is_dllimport_foreign_item(&self, id: DefIndex) -> bool { - self.dllimport_foreign_items.contains(&id) + pub fn is_dllimport_foreign_item(&self, id: DefIndex, dep_graph: &DepGraph) -> bool { + let dep_node = self.metadata_dep_node(GlobalMetaDataKind::NativeLibraries); + self.dllimport_foreign_items + .get(dep_graph, dep_node) + .contains(&id) } pub fn is_default_impl(&self, impl_id: DefIndex) -> bool { @@ -1097,121 +1144,62 @@ impl<'a, 'tcx> CrateMetadata { let external_codemap = self.root.codemap.decode(self); let imported_filemaps = external_codemap.map(|filemap_to_import| { - // Try to find an existing FileMap that can be reused for the filemap to - // be imported. A FileMap is reusable if it is exactly the same, just - // positioned at a different offset within the codemap. - let reusable_filemap = { - local_codemap.files - .borrow() - .iter() - .find(|fm| are_equal_modulo_startpos(&fm, &filemap_to_import)) - .map(|rc| rc.clone()) - }; - - match reusable_filemap { - Some(fm) => { - - debug!("CrateMetaData::imported_filemaps reuse \ - filemap {:?} original (start_pos {:?} end_pos {:?}) \ - translated (start_pos {:?} end_pos {:?})", - filemap_to_import.name, - filemap_to_import.start_pos, filemap_to_import.end_pos, - fm.start_pos, fm.end_pos); - - cstore::ImportedFileMap { - original_start_pos: filemap_to_import.start_pos, - original_end_pos: filemap_to_import.end_pos, - translated_filemap: fm, - } - } - None => { - // We can't reuse an existing FileMap, so allocate a new one - // containing the information we need. - let syntax_pos::FileMap { name, - name_was_remapped, - start_pos, - end_pos, - lines, - multibyte_chars, - .. } = filemap_to_import; - - let source_length = (end_pos - start_pos).to_usize(); - - // Translate line-start positions and multibyte character - // position into frame of reference local to file. - // `CodeMap::new_imported_filemap()` will then translate those - // coordinates to their new global frame of reference when the - // offset of the FileMap is known. - let mut lines = lines.into_inner(); - for pos in &mut lines { - *pos = *pos - start_pos; - } - let mut multibyte_chars = multibyte_chars.into_inner(); - for mbc in &mut multibyte_chars { - mbc.pos = mbc.pos - start_pos; - } + // We can't reuse an existing FileMap, so allocate a new one + // containing the information we need. + let syntax_pos::FileMap { name, + name_was_remapped, + start_pos, + end_pos, + lines, + multibyte_chars, + .. } = filemap_to_import; + + let source_length = (end_pos - start_pos).to_usize(); + + // Translate line-start positions and multibyte character + // position into frame of reference local to file. + // `CodeMap::new_imported_filemap()` will then translate those + // coordinates to their new global frame of reference when the + // offset of the FileMap is known. + let mut lines = lines.into_inner(); + for pos in &mut lines { + *pos = *pos - start_pos; + } + let mut multibyte_chars = multibyte_chars.into_inner(); + for mbc in &mut multibyte_chars { + mbc.pos = mbc.pos - start_pos; + } - let local_version = local_codemap.new_imported_filemap(name, - name_was_remapped, - source_length, - lines, - multibyte_chars); - debug!("CrateMetaData::imported_filemaps alloc \ - filemap {:?} original (start_pos {:?} end_pos {:?}) \ - translated (start_pos {:?} end_pos {:?})", - local_version.name, start_pos, end_pos, - local_version.start_pos, local_version.end_pos); - - cstore::ImportedFileMap { - original_start_pos: start_pos, - original_end_pos: end_pos, - translated_filemap: local_version, - } - } - } - }) - .collect(); + let local_version = local_codemap.new_imported_filemap(name, + name_was_remapped, + self.cnum.as_u32(), + source_length, + lines, + multibyte_chars); + debug!("CrateMetaData::imported_filemaps alloc \ + filemap {:?} original (start_pos {:?} end_pos {:?}) \ + translated (start_pos {:?} end_pos {:?})", + local_version.name, start_pos, end_pos, + local_version.start_pos, local_version.end_pos); + + cstore::ImportedFileMap { + original_start_pos: start_pos, + original_end_pos: end_pos, + translated_filemap: local_version, + } + }).collect(); // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref. *self.codemap_import_info.borrow_mut() = imported_filemaps; self.codemap_import_info.borrow() } -} - -fn are_equal_modulo_startpos(fm1: &syntax_pos::FileMap, fm2: &syntax_pos::FileMap) -> bool { - if fm1.byte_length() != fm2.byte_length() { - return false; - } - - if fm1.name != fm2.name { - return false; - } - - let lines1 = fm1.lines.borrow(); - let lines2 = fm2.lines.borrow(); - - if lines1.len() != lines2.len() { - return false; - } - - for (&line1, &line2) in lines1.iter().zip(lines2.iter()) { - if (line1 - fm1.start_pos) != (line2 - fm2.start_pos) { - return false; - } - } - - let multibytes1 = fm1.multibyte_chars.borrow(); - let multibytes2 = fm2.multibyte_chars.borrow(); - if multibytes1.len() != multibytes2.len() { - return false; - } + pub fn metadata_dep_node(&self, kind: GlobalMetaDataKind) -> DepNode { + let def_id = DefId { + krate: self.cnum, + index: CRATE_DEF_INDEX, + }; - for (mb1, mb2) in multibytes1.iter().zip(multibytes2.iter()) { - if (mb1.bytes != mb2.bytes) || ((mb1.pos - fm1.start_pos) != (mb2.pos - fm2.start_pos)) { - return false; - } + DepNode::GlobalMetaData(def_id, kind) } - - true } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 796cb8c4d65..fa4ebed1618 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -8,14 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use cstore; use index::Index; +use index_builder::{FromId, IndexBuilder, Untracked}; +use isolated_encoder::IsolatedEncoder; use schema::*; use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary, - EncodedMetadata, EncodedMetadataHash}; + EncodedMetadata, EncodedMetadataHashes}; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE}; use rustc::hir::map::definitions::DefPathTable; +use rustc::dep_graph::{DepNode, GlobalMetaDataKind}; +use rustc::ich::{StableHashingContext, Fingerprint}; use rustc::middle::dependency_format::Linkage; use rustc::middle::lang_items; use rustc::mir; @@ -26,12 +29,15 @@ use rustc::session::config::{self, CrateTypeProcMacro}; use rustc::util::nodemap::{FxHashMap, NodeSet}; use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; +use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; + use std::hash::Hash; use std::intrinsics; use std::io::prelude::*; use std::io::Cursor; use std::path::Path; use std::rc::Rc; +use std::sync::Arc; use std::u32; use syntax::ast::{self, CRATE_NODE_ID}; use syntax::codemap::Spanned; @@ -44,20 +50,18 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; use rustc::hir::intravisit; -use super::index_builder::{FromId, IndexBuilder, Untracked, EntryBuilder}; - pub struct EncodeContext<'a, 'tcx: 'a> { opaque: opaque::Encoder<'a>, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, link_meta: &'a LinkMeta, - cstore: &'a cstore::CStore, exported_symbols: &'a NodeSet, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, predicate_shorthands: FxHashMap, usize>, - pub metadata_hashes: Vec, + pub metadata_hashes: EncodedMetadataHashes, + pub compute_ich: bool, } macro_rules! encoder_methods { @@ -134,6 +138,7 @@ impl<'a, 'tcx> SpecializedEncoder> for EncodeContext } impl<'a, 'tcx> EncodeContext<'a, 'tcx> { + pub fn position(&self) -> usize { self.opaque.position() } @@ -237,11 +242,240 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { Ok(()) } + + // Encodes something that corresponds to a single DepNode::GlobalMetaData + // and registers the Fingerprint in the `metadata_hashes` map. + pub fn tracked<'x, DATA, R>(&'x mut self, + dep_node: DepNode<()>, + op: fn(&mut IsolatedEncoder<'x, 'a, 'tcx>, DATA) -> R, + data: DATA) + -> Tracked { + let mut entry_builder = IsolatedEncoder::new(self); + let ret = op(&mut entry_builder, data); + let (fingerprint, this) = entry_builder.finish(); + + if let Some(fingerprint) = fingerprint { + this.metadata_hashes.global_hashes.push((dep_node, fingerprint)); + } + + Tracked::new(ret) + } + + fn encode_info_for_items(&mut self) -> Index { + let krate = self.tcx.hir.krate(); + let mut index = IndexBuilder::new(self); + index.record(DefId::local(CRATE_DEF_INDEX), + IsolatedEncoder::encode_info_for_mod, + FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public))); + let mut visitor = EncodeVisitor { index: index }; + krate.visit_all_item_likes(&mut visitor.as_deep_visitor()); + for macro_def in &krate.exported_macros { + visitor.visit_macro_def(macro_def); + } + visitor.index.into_items() + } + + fn encode_def_path_table(&mut self) -> Lazy { + let definitions = self.tcx.hir.definitions(); + self.lazy(definitions.def_path_table()) + } + + fn encode_codemap(&mut self) -> LazySeq { + let codemap = self.tcx.sess.codemap(); + let all_filemaps = codemap.files(); + + let hcx = &mut StableHashingContext::new(self.tcx); + let (working_dir, working_dir_was_remapped) = self.tcx.sess.working_dir.clone(); + + let adapted = all_filemaps.iter() + .filter(|filemap| { + // No need to re-export imported filemaps, as any downstream + // crate will import them from their original source. + !filemap.is_imported() + }) + .map(|filemap| { + // When exporting FileMaps, we expand all paths to absolute + // paths because any relative paths are potentially relative to + // a wrong directory. + // However, if a path has been modified via + // `-Zremap-path-prefix` we assume the user has already set + // things up the way they want and don't touch the path values + // anymore. + let name = Path::new(&filemap.name); + if filemap.name_was_remapped || + (name.is_relative() && working_dir_was_remapped) { + // This path of this FileMap has been modified by + // path-remapping, so we use it verbatim (and avoid cloning + // the whole map in the process). + filemap.clone() + } else { + let mut adapted = (**filemap).clone(); + let abs_path = Path::new(&working_dir).join(name) + .to_string_lossy() + .into_owned(); + adapted.name = abs_path; + Rc::new(adapted) + } + }); + + let filemaps: Vec<_> = if self.compute_ich { + adapted.inspect(|filemap| { + let mut hasher = StableHasher::new(); + filemap.hash_stable(hcx, &mut hasher); + let fingerprint = hasher.finish(); + let dep_node = DepNode::FileMap((), Arc::new(filemap.name.clone())); + self.metadata_hashes.global_hashes.push((dep_node, fingerprint)); + }).collect() + } else { + adapted.collect() + }; + + self.lazy_seq_ref(filemaps.iter().map(|fm| &**fm)) + } + + fn encode_crate_root(&mut self) -> Lazy { + let mut i = self.position(); + + let crate_deps = self.tracked( + DepNode::GlobalMetaData((), GlobalMetaDataKind::CrateDeps), + IsolatedEncoder::encode_crate_deps, + ()); + let dylib_dependency_formats = self.tracked( + DepNode::GlobalMetaData((), GlobalMetaDataKind::DylibDependencyFormats), + IsolatedEncoder::encode_dylib_dependency_formats, + ()); + let dep_bytes = self.position() - i; + + // Encode the language items. + i = self.position(); + let lang_items = self.tracked( + DepNode::GlobalMetaData((), GlobalMetaDataKind::LangItems), + IsolatedEncoder::encode_lang_items, + ()); + + let lang_items_missing = self.tracked( + DepNode::GlobalMetaData((), GlobalMetaDataKind::LangItemsMissing), + IsolatedEncoder::encode_lang_items_missing, + ()); + let lang_item_bytes = self.position() - i; + + // Encode the native libraries used + i = self.position(); + let native_libraries = self.tracked( + DepNode::GlobalMetaData((), GlobalMetaDataKind::NativeLibraries), + IsolatedEncoder::encode_native_libraries, + ()); + let native_lib_bytes = self.position() - i; + + // Encode codemap + i = self.position(); + let codemap = self.encode_codemap(); + let codemap_bytes = self.position() - i; + + // Encode DefPathTable + i = self.position(); + let def_path_table = self.encode_def_path_table(); + let def_path_table_bytes = self.position() - i; + + // Encode the def IDs of impls, for coherence checking. + i = self.position(); + let impls = self.tracked( + DepNode::GlobalMetaData((), GlobalMetaDataKind::Impls), + IsolatedEncoder::encode_impls, + ()); + let impl_bytes = self.position() - i; + + // Encode exported symbols info. + i = self.position(); + let exported_symbols = self.tracked( + DepNode::GlobalMetaData((), GlobalMetaDataKind::ExportedSymbols), + IsolatedEncoder::encode_exported_symbols, + self.exported_symbols); + let exported_symbols_bytes = self.position() - i; + + // Encode and index the items. + i = self.position(); + let items = self.encode_info_for_items(); + let item_bytes = self.position() - i; + + i = self.position(); + let index = items.write_index(&mut self.opaque.cursor); + let index_bytes = self.position() - i; + + let tcx = self.tcx; + let link_meta = self.link_meta; + let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro); + let root = self.lazy(&CrateRoot { + name: tcx.crate_name(LOCAL_CRATE), + triple: tcx.sess.opts.target_triple.clone(), + hash: link_meta.crate_hash, + disambiguator: tcx.sess.local_crate_disambiguator(), + panic_strategy: Tracked::new(tcx.sess.panic_strategy()), + plugin_registrar_fn: tcx.sess + .plugin_registrar_fn + .get() + .map(|id| tcx.hir.local_def_id(id).index), + macro_derive_registrar: if is_proc_macro { + let id = tcx.sess.derive_registrar_fn.get().unwrap(); + Some(tcx.hir.local_def_id(id).index) + } else { + None + }, + + crate_deps: crate_deps, + dylib_dependency_formats: dylib_dependency_formats, + lang_items: lang_items, + lang_items_missing: lang_items_missing, + native_libraries: native_libraries, + codemap: codemap, + def_path_table: def_path_table, + impls: impls, + exported_symbols: exported_symbols, + index: index, + }); + + let total_bytes = self.position(); + + self.metadata_hashes.global_hashes.push(( + DepNode::GlobalMetaData((), GlobalMetaDataKind::Krate), + Fingerprint::from_smaller_hash(link_meta.crate_hash.as_u64()) + )); + + if self.tcx.sess.meta_stats() { + let mut zero_bytes = 0; + for e in self.opaque.cursor.get_ref() { + if *e == 0 { + zero_bytes += 1; + } + } + + println!("metadata stats:"); + println!(" dep bytes: {}", dep_bytes); + println!(" lang item bytes: {}", lang_item_bytes); + println!(" native bytes: {}", native_lib_bytes); + println!(" codemap bytes: {}", codemap_bytes); + println!(" impl bytes: {}", impl_bytes); + println!(" exp. symbols bytes: {}", exported_symbols_bytes); + println!(" def-path table bytes: {}", def_path_table_bytes); + println!(" item bytes: {}", item_bytes); + println!(" index bytes: {}", index_bytes); + println!(" zero bytes: {}", zero_bytes); + println!(" total bytes: {}", total_bytes); + } + + root + } } -impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { +// These are methods for encoding various things. They are meant to be used with +// IndexBuilder::record() and EncodeContext::tracked(). They actually +// would not have to be methods of IsolatedEncoder (free standing functions +// taking IsolatedEncoder as first argument would be just fine) but by making +// them methods we don't have to repeat the lengthy `<'a, 'b: 'a, 'tcx: 'b>` +// clause again and again. +impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq { - debug!("EntryBuilder::encode_variances_of({:?})", def_id); + debug!("IsolatedEncoder::encode_variances_of({:?})", def_id); let tcx = self.tcx; self.lazy_seq_from_slice(&tcx.variances_of(def_id)) } @@ -249,7 +483,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { fn encode_item_type(&mut self, def_id: DefId) -> Lazy> { let tcx = self.tcx; let ty = tcx.type_of(def_id); - debug!("EntryBuilder::encode_item_type({:?}) => {:?}", def_id, ty); + debug!("IsolatedEncoder::encode_item_type({:?}) => {:?}", def_id, ty); self.lazy(&ty) } @@ -265,7 +499,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; let def_id = variant.did; - debug!("EntryBuilder::encode_enum_variant_info({:?})", def_id); + debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id); let data = VariantData { ctor_kind: variant.ctor_kind, @@ -306,7 +540,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { -> Entry<'tcx> { let tcx = self.tcx; let def_id = tcx.hir.local_def_id(id); - debug!("EntryBuilder::encode_info_for_mod({:?})", def_id); + debug!("IsolatedEncoder::encode_info_for_mod({:?})", def_id); let data = ModData { reexports: match tcx.export_map.get(&id) { @@ -338,22 +572,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { mir: None } } -} - -impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { - fn encode_fields(&mut self, adt_def_id: DefId) { - let def = self.tcx.adt_def(adt_def_id); - for (variant_index, variant) in def.variants.iter().enumerate() { - for (field_index, field) in variant.fields.iter().enumerate() { - self.record(field.did, - EntryBuilder::encode_field, - (adt_def_id, Untracked((variant_index, field_index)))); - } - } - } -} -impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { /// Encode data for the given field of the given variant of the /// given ADT. The indices of the variant/field are untracked: /// this is ok because we will have to lookup the adt-def by its @@ -370,7 +589,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { let field = &variant.fields[field_index]; let def_id = field.did; - debug!("EntryBuilder::encode_field({:?})", def_id); + debug!("IsolatedEncoder::encode_field({:?})", def_id); let variant_id = tcx.hir.as_local_node_id(variant.did).unwrap(); let variant_data = tcx.hir.expect_variant_data(variant_id); @@ -396,7 +615,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { } fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> { - debug!("EntryBuilder::encode_struct_ctor({:?})", def_id); + debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id); let tcx = self.tcx; let variant = tcx.adt_def(adt_def_id).struct_variant(); @@ -438,19 +657,19 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { } fn encode_generics(&mut self, def_id: DefId) -> Lazy { - debug!("EntryBuilder::encode_generics({:?})", def_id); + debug!("IsolatedEncoder::encode_generics({:?})", def_id); let tcx = self.tcx; self.lazy(tcx.generics_of(def_id)) } fn encode_predicates(&mut self, def_id: DefId) -> Lazy> { - debug!("EntryBuilder::encode_predicates({:?})", def_id); + debug!("IsolatedEncoder::encode_predicates({:?})", def_id); let tcx = self.tcx; self.lazy(&tcx.predicates_of(def_id)) } fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("EntryBuilder::encode_info_for_trait_item({:?})", def_id); + debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); @@ -533,7 +752,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { } fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("EntryBuilder::encode_info_for_impl_item({:?})", def_id); + debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id); let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let ast_item = self.tcx.hir.expect_impl_item(node_id); let impl_item = self.tcx.associated_item(def_id); @@ -631,7 +850,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { // Encodes the inherent implementations of a structure, enumeration, or trait. fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq { - debug!("EntryBuilder::encode_inherent_implementations({:?})", def_id); + debug!("IsolatedEncoder::encode_inherent_implementations({:?})", def_id); let implementations = self.tcx.inherent_impls(def_id); if implementations.is_empty() { LazySeq::empty() @@ -644,19 +863,19 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { } fn encode_stability(&mut self, def_id: DefId) -> Option> { - debug!("EntryBuilder::encode_stability({:?})", def_id); + debug!("IsolatedEncoder::encode_stability({:?})", def_id); self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab)) } fn encode_deprecation(&mut self, def_id: DefId) -> Option> { - debug!("EntryBuilder::encode_deprecation({:?})", def_id); + debug!("IsolatedEncoder::encode_deprecation({:?})", def_id); self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr)) } fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> { let tcx = self.tcx; - debug!("EntryBuilder::encode_info_for_item({:?})", def_id); + debug!("IsolatedEncoder::encode_info_for_item({:?})", def_id); let kind = match item.node { hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic, @@ -902,224 +1121,38 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { mir: None, } } -} -impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { - /// In some cases, along with the item itself, we also - /// encode some sub-items. Usually we want some info from the item - /// so it's easier to do that here then to wait until we would encounter - /// normally in the visitor walk. - fn encode_addl_info_for_item(&mut self, item: &hir::Item) { - let def_id = self.tcx.hir.local_def_id(item.id); - match item.node { - hir::ItemStatic(..) | - hir::ItemConst(..) | - hir::ItemFn(..) | - hir::ItemMod(..) | - hir::ItemForeignMod(..) | - hir::ItemGlobalAsm(..) | - hir::ItemExternCrate(..) | - hir::ItemUse(..) | - hir::ItemDefaultImpl(..) | - hir::ItemTy(..) => { - // no sub-item recording needed in these cases - } - hir::ItemEnum(..) => { - self.encode_fields(def_id); + fn encode_info_for_ty_param(&mut self, + (def_id, Untracked(has_default)): (DefId, Untracked)) + -> Entry<'tcx> { + debug!("IsolatedEncoder::encode_info_for_ty_param({:?})", def_id); + let tcx = self.tcx; + Entry { + kind: EntryKind::Type, + visibility: self.lazy(&ty::Visibility::Public), + span: self.lazy(&tcx.def_span(def_id)), + attributes: LazySeq::empty(), + children: LazySeq::empty(), + stability: None, + deprecation: None, - let def = self.tcx.adt_def(def_id); - for (i, variant) in def.variants.iter().enumerate() { - self.record(variant.did, - EntryBuilder::encode_enum_variant_info, - (def_id, Untracked(i))); - } - } - hir::ItemStruct(ref struct_def, _) => { - self.encode_fields(def_id); + ty: if has_default { + Some(self.encode_item_type(def_id)) + } else { + None + }, + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: None, + predicates: None, - // If the struct has a constructor, encode it. - if !struct_def.is_struct() { - let ctor_def_id = self.tcx.hir.local_def_id(struct_def.id()); - self.record(ctor_def_id, - EntryBuilder::encode_struct_ctor, - (def_id, ctor_def_id)); - } - } - hir::ItemUnion(..) => { - self.encode_fields(def_id); - } - hir::ItemImpl(..) => { - for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { - self.record(trait_item_def_id, - EntryBuilder::encode_info_for_impl_item, - trait_item_def_id); - } - } - hir::ItemTrait(..) => { - for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { - self.record(item_def_id, - EntryBuilder::encode_info_for_trait_item, - item_def_id); - } - } - } - } -} - -impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { - fn encode_info_for_foreign_item(&mut self, - (def_id, nitem): (DefId, &hir::ForeignItem)) - -> Entry<'tcx> { - let tcx = self.tcx; - - debug!("EntryBuilder::encode_info_for_foreign_item({:?})", def_id); - - let kind = match nitem.node { - hir::ForeignItemFn(_, ref names, _) => { - let data = FnData { - constness: hir::Constness::NotConst, - arg_names: self.encode_fn_arg_names(names), - }; - EntryKind::ForeignFn(self.lazy(&data)) - } - hir::ForeignItemStatic(_, true) => EntryKind::ForeignMutStatic, - hir::ForeignItemStatic(_, false) => EntryKind::ForeignImmStatic, - }; - - Entry { - kind: kind, - visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.id, tcx)), - span: self.lazy(&nitem.span), - attributes: self.encode_attributes(&nitem.attrs), - children: LazySeq::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - - ast: None, - mir: None, - } - } -} - -struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> { - index: IndexBuilder<'a, 'b, 'tcx>, -} - -impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.index.tcx.hir) - } - fn visit_expr(&mut self, ex: &'tcx hir::Expr) { - intravisit::walk_expr(self, ex); - self.index.encode_info_for_expr(ex); - } - fn visit_item(&mut self, item: &'tcx hir::Item) { - intravisit::walk_item(self, item); - let def_id = self.index.tcx.hir.local_def_id(item.id); - match item.node { - hir::ItemExternCrate(_) | - hir::ItemUse(..) => (), // ignore these - _ => self.index.record(def_id, EntryBuilder::encode_info_for_item, (def_id, item)), - } - self.index.encode_addl_info_for_item(item); - } - fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) { - intravisit::walk_foreign_item(self, ni); - let def_id = self.index.tcx.hir.local_def_id(ni.id); - self.index.record(def_id, - EntryBuilder::encode_info_for_foreign_item, - (def_id, ni)); - } - fn visit_variant(&mut self, - v: &'tcx hir::Variant, - g: &'tcx hir::Generics, - id: ast::NodeId) { - intravisit::walk_variant(self, v, g, id); - - if let Some(discr) = v.node.disr_expr { - let def_id = self.index.tcx.hir.body_owner_def_id(discr); - self.index.record(def_id, EntryBuilder::encode_info_for_embedded_const, def_id); - } - } - fn visit_generics(&mut self, generics: &'tcx hir::Generics) { - intravisit::walk_generics(self, generics); - self.index.encode_info_for_generics(generics); - } - fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - intravisit::walk_ty(self, ty); - self.index.encode_info_for_ty(ty); - } - fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) { - let def_id = self.index.tcx.hir.local_def_id(macro_def.id); - self.index.record(def_id, EntryBuilder::encode_info_for_macro_def, macro_def); - } -} - -impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { - fn encode_info_for_generics(&mut self, generics: &hir::Generics) { - for ty_param in &generics.ty_params { - let def_id = self.tcx.hir.local_def_id(ty_param.id); - let has_default = Untracked(ty_param.default.is_some()); - self.record(def_id, EntryBuilder::encode_info_for_ty_param, (def_id, has_default)); - } - } - - fn encode_info_for_ty(&mut self, ty: &hir::Ty) { - if let hir::TyImplTrait(_) = ty.node { - let def_id = self.tcx.hir.local_def_id(ty.id); - self.record(def_id, EntryBuilder::encode_info_for_anon_ty, def_id); - } - } - - fn encode_info_for_expr(&mut self, expr: &hir::Expr) { - match expr.node { - hir::ExprClosure(..) => { - let def_id = self.tcx.hir.local_def_id(expr.id); - self.record(def_id, EntryBuilder::encode_info_for_closure, def_id); - } - _ => {} - } - } -} - -impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { - fn encode_info_for_ty_param(&mut self, - (def_id, Untracked(has_default)): (DefId, Untracked)) - -> Entry<'tcx> { - debug!("EntryBuilder::encode_info_for_ty_param({:?})", def_id); - let tcx = self.tcx; - Entry { - kind: EntryKind::Type, - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), - stability: None, - deprecation: None, - - ty: if has_default { - Some(self.encode_item_type(def_id)) - } else { - None - }, - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), - generics: None, - predicates: None, - - ast: None, - mir: None, + ast: None, + mir: None, } } fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("EntryBuilder::encode_info_for_anon_ty({:?})", def_id); + debug!("IsolatedEncoder::encode_info_for_anon_ty({:?})", def_id); let tcx = self.tcx; Entry { kind: EntryKind::Type, @@ -1142,7 +1175,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { } fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("EntryBuilder::encode_info_for_closure({:?})", def_id); + debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id); let tcx = self.tcx; let data = ClosureData { @@ -1171,7 +1204,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { } fn encode_info_for_embedded_const(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("EntryBuilder::encode_info_for_embedded_const({:?})", def_id); + debug!("IsolatedEncoder::encode_info_for_embedded_const({:?})", def_id); let tcx = self.tcx; let id = tcx.hir.as_local_node_id(def_id).unwrap(); let body = tcx.hir.body_owned_by(id); @@ -1198,154 +1231,70 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq { // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because - // we really on the HashStable specialization for [Attribute] + // we rely on the HashStable specialization for [Attribute] // to properly filter things out. self.lazy_seq_from_slice(attrs) } -} -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - fn encode_info_for_items(&mut self) -> Index { - let krate = self.tcx.hir.krate(); - let mut index = IndexBuilder::new(self); - index.record(DefId::local(CRATE_DEF_INDEX), - EntryBuilder::encode_info_for_mod, - FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public))); - let mut visitor = EncodeVisitor { index: index }; - krate.visit_all_item_likes(&mut visitor.as_deep_visitor()); - for macro_def in &krate.exported_macros { - visitor.visit_macro_def(macro_def); - } - visitor.index.into_items() + fn encode_native_libraries(&mut self, _: ()) -> LazySeq { + let used_libraries = self.tcx.sess.cstore.used_libraries(); + self.lazy_seq(used_libraries) } - fn encode_crate_deps(&mut self) -> LazySeq { - fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc)> { - // Pull the cnums and name,vers,hash out of cstore - let mut deps = Vec::new(); - cstore.iter_crate_data(|cnum, val| { - deps.push((cnum, val.clone())); - }); + fn encode_crate_deps(&mut self, _: ()) -> LazySeq { + let cstore = &*self.tcx.sess.cstore; + let crates = cstore.crates(); + + let mut deps = crates + .iter() + .map(|&cnum| { + let dep = CrateDep { + name: cstore.original_crate_name(cnum), + hash: cstore.crate_hash(cnum), + kind: cstore.dep_kind(cnum), + }; + (cnum, dep) + }) + .collect::>(); - // Sort by cnum - deps.sort_by(|kv1, kv2| kv1.0.cmp(&kv2.0)); + deps.sort_by_key(|&(cnum, _)| cnum); + { // Sanity-check the crate numbers let mut expected_cnum = 1; for &(n, _) in &deps { assert_eq!(n, CrateNum::new(expected_cnum)); expected_cnum += 1; } - - deps } // We're just going to write a list of crate 'name-hash-version's, with // the assumption that they are numbered 1 to n. // FIXME (#2166): This is not nearly enough to support correct versioning // but is enough to get transitive crate dependencies working. - let deps = get_ordered_deps(self.cstore); - self.lazy_seq(deps.iter().map(|&(_, ref dep)| { - CrateDep { - name: dep.name(), - hash: dep.hash(), - kind: dep.dep_kind.get(), - } - })) + self.lazy_seq_ref(deps.iter().map(|&(_, ref dep)| dep)) } - fn encode_lang_items(&mut self) -> (LazySeq<(DefIndex, usize)>, LazySeq) { + fn encode_lang_items(&mut self, _: ()) -> LazySeq<(DefIndex, usize)> { let tcx = self.tcx; let lang_items = tcx.lang_items.items().iter(); - (self.lazy_seq(lang_items.enumerate().filter_map(|(i, &opt_def_id)| { + self.lazy_seq(lang_items.enumerate().filter_map(|(i, &opt_def_id)| { if let Some(def_id) = opt_def_id { if def_id.is_local() { return Some((def_id.index, i)); } } None - })), - self.lazy_seq_ref(&tcx.lang_items.missing)) - } - - fn encode_native_libraries(&mut self) -> LazySeq { - let used_libraries = self.tcx.sess.cstore.used_libraries(); - self.lazy_seq(used_libraries) - } - - fn encode_codemap(&mut self) -> LazySeq { - let codemap = self.tcx.sess.codemap(); - let all_filemaps = codemap.files.borrow(); - let adapted = all_filemaps.iter() - .filter(|filemap| { - // No need to re-export imported filemaps, as any downstream - // crate will import them from their original source. - !filemap.is_imported() - }) - .map(|filemap| { - // When exporting FileMaps, we expand all paths to absolute - // paths because any relative paths are potentially relative to - // a wrong directory. - // However, if a path has been modified via - // `-Zremap-path-prefix` we assume the user has already set - // things up the way they want and don't touch the path values - // anymore. - let name = Path::new(&filemap.name); - let (ref working_dir, working_dir_was_remapped) = self.tcx.sess.working_dir; - if filemap.name_was_remapped || - (name.is_relative() && working_dir_was_remapped) { - // This path of this FileMap has been modified by - // path-remapping, so we use it verbatim (and avoid cloning - // the whole map in the process). - filemap.clone() - } else { - let mut adapted = (**filemap).clone(); - let abs_path = Path::new(working_dir).join(name) - .to_string_lossy() - .into_owned(); - adapted.name = abs_path; - Rc::new(adapted) - } - }) - .collect::>(); - - self.lazy_seq_ref(adapted.iter().map(|fm| &**fm)) - } - - fn encode_def_path_table(&mut self) -> Lazy { - let definitions = self.tcx.hir.definitions(); - self.lazy(definitions.def_path_table()) - } -} - -struct ImplVisitor<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - impls: FxHashMap>, -} - -impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> { - fn visit_item(&mut self, item: &hir::Item) { - if let hir::ItemImpl(..) = item.node { - let impl_id = self.tcx.hir.local_def_id(item.id); - if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) { - self.impls - .entry(trait_ref.def_id) - .or_insert(vec![]) - .push(impl_id.index); - } - } + })) } - fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem) {} - - fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { - // handled in `visit_item` above + fn encode_lang_items_missing(&mut self, _: ()) -> LazySeq { + let tcx = self.tcx; + self.lazy_seq_ref(&tcx.lang_items.missing) } -} -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { /// Encodes an index, mapping each trait to its (local) implementations. - fn encode_impls(&mut self) -> LazySeq { + fn encode_impls(&mut self, _: ()) -> LazySeq { let mut visitor = ImplVisitor { tcx: self.tcx, impls: FxHashMap(), @@ -1371,13 +1320,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // middle::reachable module but filters out items that either don't have a // symbol associated with them (they weren't translated) or if they're an FFI // definition (as that's not defined in this crate). - fn encode_exported_symbols(&mut self) -> LazySeq { - let exported_symbols = self.exported_symbols; + fn encode_exported_symbols(&mut self, exported_symbols: &NodeSet) -> LazySeq { let tcx = self.tcx; self.lazy_seq(exported_symbols.iter().map(|&id| tcx.hir.local_def_id(id).index)) } - fn encode_dylib_dependency_formats(&mut self) -> LazySeq> { + fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq> { match self.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) { Some(arr) => { self.lazy_seq(arr.iter().map(|slot| { @@ -1393,111 +1341,221 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { None => LazySeq::empty(), } } -} -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - fn encode_crate_root(&mut self) -> Lazy { - let mut i = self.position(); - let crate_deps = self.encode_crate_deps(); - let dylib_dependency_formats = self.encode_dylib_dependency_formats(); - let dep_bytes = self.position() - i; + fn encode_info_for_foreign_item(&mut self, + (def_id, nitem): (DefId, &hir::ForeignItem)) + -> Entry<'tcx> { + let tcx = self.tcx; - // Encode the language items. - i = self.position(); - let (lang_items, lang_items_missing) = self.encode_lang_items(); - let lang_item_bytes = self.position() - i; + debug!("IsolatedEncoder::encode_info_for_foreign_item({:?})", def_id); - // Encode the native libraries used - i = self.position(); - let native_libraries = self.encode_native_libraries(); - let native_lib_bytes = self.position() - i; + let kind = match nitem.node { + hir::ForeignItemFn(_, ref names, _) => { + let data = FnData { + constness: hir::Constness::NotConst, + arg_names: self.encode_fn_arg_names(names), + }; + EntryKind::ForeignFn(self.lazy(&data)) + } + hir::ForeignItemStatic(_, true) => EntryKind::ForeignMutStatic, + hir::ForeignItemStatic(_, false) => EntryKind::ForeignImmStatic, + }; - // Encode codemap - i = self.position(); - let codemap = self.encode_codemap(); - let codemap_bytes = self.position() - i; + Entry { + kind: kind, + visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.id, tcx)), + span: self.lazy(&nitem.span), + attributes: self.encode_attributes(&nitem.attrs), + children: LazySeq::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), - // Encode DefPathTable - i = self.position(); - let def_path_table = self.encode_def_path_table(); - let def_path_table_bytes = self.position() - i; + ty: Some(self.encode_item_type(def_id)), + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), - // Encode the def IDs of impls, for coherence checking. - i = self.position(); - let impls = self.encode_impls(); - let impl_bytes = self.position() - i; + ast: None, + mir: None, + } + } +} - // Encode exported symbols info. - i = self.position(); - let exported_symbols = self.encode_exported_symbols(); - let exported_symbols_bytes = self.position() - i; +struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> { + index: IndexBuilder<'a, 'b, 'tcx>, +} - // Encode and index the items. - i = self.position(); - let items = self.encode_info_for_items(); - let item_bytes = self.position() - i; +impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::OnlyBodies(&self.index.tcx.hir) + } + fn visit_expr(&mut self, ex: &'tcx hir::Expr) { + intravisit::walk_expr(self, ex); + self.index.encode_info_for_expr(ex); + } + fn visit_item(&mut self, item: &'tcx hir::Item) { + intravisit::walk_item(self, item); + let def_id = self.index.tcx.hir.local_def_id(item.id); + match item.node { + hir::ItemExternCrate(_) | + hir::ItemUse(..) => (), // ignore these + _ => self.index.record(def_id, IsolatedEncoder::encode_info_for_item, (def_id, item)), + } + self.index.encode_addl_info_for_item(item); + } + fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) { + intravisit::walk_foreign_item(self, ni); + let def_id = self.index.tcx.hir.local_def_id(ni.id); + self.index.record(def_id, + IsolatedEncoder::encode_info_for_foreign_item, + (def_id, ni)); + } + fn visit_variant(&mut self, + v: &'tcx hir::Variant, + g: &'tcx hir::Generics, + id: ast::NodeId) { + intravisit::walk_variant(self, v, g, id); - i = self.position(); - let index = items.write_index(&mut self.opaque.cursor); - let index_bytes = self.position() - i; + if let Some(discr) = v.node.disr_expr { + let def_id = self.index.tcx.hir.body_owner_def_id(discr); + self.index.record(def_id, IsolatedEncoder::encode_info_for_embedded_const, def_id); + } + } + fn visit_generics(&mut self, generics: &'tcx hir::Generics) { + intravisit::walk_generics(self, generics); + self.index.encode_info_for_generics(generics); + } + fn visit_ty(&mut self, ty: &'tcx hir::Ty) { + intravisit::walk_ty(self, ty); + self.index.encode_info_for_ty(ty); + } + fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) { + let def_id = self.index.tcx.hir.local_def_id(macro_def.id); + self.index.record(def_id, IsolatedEncoder::encode_info_for_macro_def, macro_def); + } +} - let tcx = self.tcx; - let link_meta = self.link_meta; - let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro); - let root = self.lazy(&CrateRoot { - name: tcx.crate_name(LOCAL_CRATE), - triple: tcx.sess.opts.target_triple.clone(), - hash: link_meta.crate_hash, - disambiguator: tcx.sess.local_crate_disambiguator(), - panic_strategy: tcx.sess.panic_strategy(), - plugin_registrar_fn: tcx.sess - .plugin_registrar_fn - .get() - .map(|id| tcx.hir.local_def_id(id).index), - macro_derive_registrar: if is_proc_macro { - let id = tcx.sess.derive_registrar_fn.get().unwrap(); - Some(tcx.hir.local_def_id(id).index) - } else { - None - }, +impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { + fn encode_fields(&mut self, adt_def_id: DefId) { + let def = self.tcx.adt_def(adt_def_id); + for (variant_index, variant) in def.variants.iter().enumerate() { + for (field_index, field) in variant.fields.iter().enumerate() { + self.record(field.did, + IsolatedEncoder::encode_field, + (adt_def_id, Untracked((variant_index, field_index)))); + } + } + } - crate_deps: crate_deps, - dylib_dependency_formats: dylib_dependency_formats, - lang_items: lang_items, - lang_items_missing: lang_items_missing, - native_libraries: native_libraries, - codemap: codemap, - def_path_table: def_path_table, - impls: impls, - exported_symbols: exported_symbols, - index: index, - }); + fn encode_info_for_generics(&mut self, generics: &hir::Generics) { + for ty_param in &generics.ty_params { + let def_id = self.tcx.hir.local_def_id(ty_param.id); + let has_default = Untracked(ty_param.default.is_some()); + self.record(def_id, IsolatedEncoder::encode_info_for_ty_param, (def_id, has_default)); + } + } - let total_bytes = self.position(); + fn encode_info_for_ty(&mut self, ty: &hir::Ty) { + if let hir::TyImplTrait(_) = ty.node { + let def_id = self.tcx.hir.local_def_id(ty.id); + self.record(def_id, IsolatedEncoder::encode_info_for_anon_ty, def_id); + } + } - if self.tcx.sess.meta_stats() { - let mut zero_bytes = 0; - for e in self.opaque.cursor.get_ref() { - if *e == 0 { - zero_bytes += 1; + fn encode_info_for_expr(&mut self, expr: &hir::Expr) { + match expr.node { + hir::ExprClosure(..) => { + let def_id = self.tcx.hir.local_def_id(expr.id); + self.record(def_id, IsolatedEncoder::encode_info_for_closure, def_id); + } + _ => {} + } + } + + /// In some cases, along with the item itself, we also + /// encode some sub-items. Usually we want some info from the item + /// so it's easier to do that here then to wait until we would encounter + /// normally in the visitor walk. + fn encode_addl_info_for_item(&mut self, item: &hir::Item) { + let def_id = self.tcx.hir.local_def_id(item.id); + match item.node { + hir::ItemStatic(..) | + hir::ItemConst(..) | + hir::ItemFn(..) | + hir::ItemMod(..) | + hir::ItemForeignMod(..) | + hir::ItemGlobalAsm(..) | + hir::ItemExternCrate(..) | + hir::ItemUse(..) | + hir::ItemDefaultImpl(..) | + hir::ItemTy(..) => { + // no sub-item recording needed in these cases + } + hir::ItemEnum(..) => { + self.encode_fields(def_id); + + let def = self.tcx.adt_def(def_id); + for (i, variant) in def.variants.iter().enumerate() { + self.record(variant.did, + IsolatedEncoder::encode_enum_variant_info, + (def_id, Untracked(i))); } } + hir::ItemStruct(ref struct_def, _) => { + self.encode_fields(def_id); - println!("metadata stats:"); - println!(" dep bytes: {}", dep_bytes); - println!(" lang item bytes: {}", lang_item_bytes); - println!(" native bytes: {}", native_lib_bytes); - println!(" codemap bytes: {}", codemap_bytes); - println!(" impl bytes: {}", impl_bytes); - println!(" exp. symbols bytes: {}", exported_symbols_bytes); - println!(" def-path table bytes: {}", def_path_table_bytes); - println!(" item bytes: {}", item_bytes); - println!(" index bytes: {}", index_bytes); - println!(" zero bytes: {}", zero_bytes); - println!(" total bytes: {}", total_bytes); + // If the struct has a constructor, encode it. + if !struct_def.is_struct() { + let ctor_def_id = self.tcx.hir.local_def_id(struct_def.id()); + self.record(ctor_def_id, + IsolatedEncoder::encode_struct_ctor, + (def_id, ctor_def_id)); + } + } + hir::ItemUnion(..) => { + self.encode_fields(def_id); + } + hir::ItemImpl(..) => { + for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { + self.record(trait_item_def_id, + IsolatedEncoder::encode_info_for_impl_item, + trait_item_def_id); + } + } + hir::ItemTrait(..) => { + for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { + self.record(item_def_id, + IsolatedEncoder::encode_info_for_trait_item, + item_def_id); + } + } } + } +} - root +struct ImplVisitor<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + impls: FxHashMap>, +} + +impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> { + fn visit_item(&mut self, item: &hir::Item) { + if let hir::ItemImpl(..) = item.node { + let impl_id = self.tcx.hir.local_def_id(item.id); + if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) { + self.impls + .entry(trait_ref.def_id) + .or_insert(vec![]) + .push(impl_id.index); + } + } + } + + fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem) {} + + fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { + // handled in `visit_item` above } } @@ -1525,7 +1583,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // generated regardless of trailing bytes that end up in it. pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - cstore: &cstore::CStore, link_meta: &LinkMeta, exported_symbols: &NodeSet) -> EncodedMetadata @@ -1533,20 +1590,24 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut cursor = Cursor::new(vec![]); cursor.write_all(METADATA_HEADER).unwrap(); - // Will be filed with the root position after encoding everything. + // Will be filled with the root position after encoding everything. cursor.write_all(&[0, 0, 0, 0]).unwrap(); + let compute_ich = (tcx.sess.opts.debugging_opts.query_dep_graph || + tcx.sess.opts.debugging_opts.incremental_cc) && + tcx.sess.opts.build_dep_graph(); + let (root, metadata_hashes) = { let mut ecx = EncodeContext { opaque: opaque::Encoder::new(&mut cursor), tcx: tcx, link_meta: link_meta, - cstore: cstore, exported_symbols: exported_symbols, lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), - metadata_hashes: Vec::new(), + metadata_hashes: EncodedMetadataHashes::new(), + compute_ich: compute_ich, }; // Encode the rustc version string in a predictable location. diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index 01f948866b8..478202aeba4 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -58,20 +58,16 @@ use encoder::EncodeContext; use index::Index; use schema::*; +use isolated_encoder::IsolatedEncoder; use rustc::hir; use rustc::hir::def_id::DefId; -use rustc::ich::{StableHashingContext, Fingerprint}; use rustc::middle::cstore::EncodedMetadataHash; use rustc::ty::TyCtxt; use syntax::ast; use std::ops::{Deref, DerefMut}; -use rustc_data_structures::accumulate_vec::AccumulateVec; -use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; -use rustc_serialize::Encodable; - /// Builder that can encode new items, adding them into the index. /// Item encoding cannot be nested. pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> { @@ -119,7 +115,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { /// content system. pub fn record<'x, DATA>(&'x mut self, id: DefId, - op: fn(&mut EntryBuilder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>, + op: fn(&mut IsolatedEncoder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>, data: DATA) where DATA: DepGraphRead { @@ -132,29 +128,19 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { // unclear whether that would be a win since hashing is cheap enough. let _task = tcx.dep_graph.in_ignore(); - let compute_ich = (tcx.sess.opts.debugging_opts.query_dep_graph || - tcx.sess.opts.debugging_opts.incremental_cc) && - tcx.sess.opts.build_dep_graph(); - let ecx: &'x mut EncodeContext<'b, 'tcx> = &mut *self.ecx; - let mut entry_builder = EntryBuilder { - tcx: tcx, - ecx: ecx, - hcx: if compute_ich { - Some((StableHashingContext::new(tcx), StableHasher::new())) - } else { - None - } - }; - + let mut entry_builder = IsolatedEncoder::new(ecx); let entry = op(&mut entry_builder, data); + let entry = entry_builder.lazy(&entry); - if let Some((ref mut hcx, ref mut hasher)) = entry_builder.hcx { - entry.hash_stable(hcx, hasher); + let (fingerprint, ecx) = entry_builder.finish(); + if let Some(hash) = fingerprint { + ecx.metadata_hashes.entry_hashes.push(EncodedMetadataHash { + def_index: id.index, + hash: hash, + }); } - let entry = entry_builder.ecx.lazy(&entry); - entry_builder.finish(id); self.items.record(id, entry); } @@ -257,91 +243,3 @@ impl DepGraphRead for FromId { tcx.hir.read(self.0); } } - -pub struct EntryBuilder<'a, 'b: 'a, 'tcx: 'b> { - pub tcx: TyCtxt<'b, 'tcx, 'tcx>, - ecx: &'a mut EncodeContext<'b, 'tcx>, - hcx: Option<(StableHashingContext<'b, 'tcx>, StableHasher)>, -} - -impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { - - pub fn finish(self, def_id: DefId) { - if let Some((_, hasher)) = self.hcx { - let hash = hasher.finish(); - self.ecx.metadata_hashes.push(EncodedMetadataHash { - def_index: def_id.index, - hash: hash, - }); - } - } - - pub fn lazy(&mut self, value: &T) -> Lazy - where T: Encodable + HashStable> - { - if let Some((ref mut hcx, ref mut hasher)) = self.hcx { - value.hash_stable(hcx, hasher); - debug!("metadata-hash: {:?}", hasher); - } - self.ecx.lazy(value) - } - - pub fn lazy_seq(&mut self, iter: I) -> LazySeq - where I: IntoIterator, - T: Encodable + HashStable> - { - if let Some((ref mut hcx, ref mut hasher)) = self.hcx { - let iter = iter.into_iter(); - let (lower_bound, upper_bound) = iter.size_hint(); - - if upper_bound == Some(lower_bound) { - lower_bound.hash_stable(hcx, hasher); - let mut num_items_hashed = 0; - let ret = self.ecx.lazy_seq(iter.inspect(|item| { - item.hash_stable(hcx, hasher); - num_items_hashed += 1; - })); - - // Sometimes items in a sequence are filtered out without being - // hashed (e.g. for &[ast::Attribute]) and this code path cannot - // handle that correctly, so we want to make sure we didn't hit - // it by accident. - if lower_bound != num_items_hashed { - bug!("Hashed a different number of items ({}) than expected ({})", - num_items_hashed, - lower_bound); - } - debug!("metadata-hash: {:?}", hasher); - ret - } else { - // Collect into a vec so we know the length of the sequence - let items: AccumulateVec<[T; 32]> = iter.collect(); - items.hash_stable(hcx, hasher); - debug!("metadata-hash: {:?}", hasher); - self.ecx.lazy_seq(items) - } - } else { - self.ecx.lazy_seq(iter) - } - } - - pub fn lazy_seq_from_slice(&mut self, slice: &[T]) -> LazySeq - where T: Encodable + HashStable> - { - if let Some((ref mut hcx, ref mut hasher)) = self.hcx { - slice.hash_stable(hcx, hasher); - debug!("metadata-hash: {:?}", hasher); - } - self.ecx.lazy_seq_ref(slice.iter()) - } - - pub fn lazy_seq_ref_from_slice(&mut self, slice: &[&T]) -> LazySeq - where T: Encodable + HashStable> - { - if let Some((ref mut hcx, ref mut hasher)) = self.hcx { - slice.hash_stable(hcx, hasher); - debug!("metadata-hash: {:?}", hasher); - } - self.ecx.lazy_seq_ref(slice.iter().map(|x| *x)) - } -} diff --git a/src/librustc_metadata/isolated_encoder.rs b/src/librustc_metadata/isolated_encoder.rs new file mode 100644 index 00000000000..7722a7b10c9 --- /dev/null +++ b/src/librustc_metadata/isolated_encoder.rs @@ -0,0 +1,160 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use encoder::EncodeContext; +use schema::{Lazy, LazySeq}; + +use rustc::ich::{StableHashingContext, Fingerprint}; +use rustc::ty::TyCtxt; + +use rustc_data_structures::accumulate_vec::AccumulateVec; +use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; +use rustc_serialize::Encodable; + +/// The IsolatedEncoder provides facilities to write to crate metadata while +/// making sure that anything going through it is also feed into an ICH hasher. +pub struct IsolatedEncoder<'a, 'b: 'a, 'tcx: 'b> { + pub tcx: TyCtxt<'b, 'tcx, 'tcx>, + ecx: &'a mut EncodeContext<'b, 'tcx>, + hcx: Option<(StableHashingContext<'b, 'tcx>, StableHasher)>, +} + +impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { + + pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self { + let tcx = ecx.tcx; + let compute_ich = ecx.compute_ich; + IsolatedEncoder { + tcx: tcx, + ecx: ecx, + hcx: if compute_ich { + Some((StableHashingContext::new(tcx), StableHasher::new())) + } else { + None + } + } + } + + pub fn finish(self) -> (Option, &'a mut EncodeContext<'b, 'tcx>) { + if let Some((_, hasher)) = self.hcx { + (Some(hasher.finish()), self.ecx) + } else { + (None, self.ecx) + } + } + + pub fn lazy(&mut self, value: &T) -> Lazy + where T: Encodable + HashStable> + { + if let Some((ref mut hcx, ref mut hasher)) = self.hcx { + value.hash_stable(hcx, hasher); + debug!("metadata-hash: {:?}", hasher); + } + self.ecx.lazy(value) + } + + pub fn lazy_seq(&mut self, iter: I) -> LazySeq + where I: IntoIterator, + T: Encodable + HashStable> + { + if let Some((ref mut hcx, ref mut hasher)) = self.hcx { + let iter = iter.into_iter(); + let (lower_bound, upper_bound) = iter.size_hint(); + + if upper_bound == Some(lower_bound) { + lower_bound.hash_stable(hcx, hasher); + let mut num_items_hashed = 0; + let ret = self.ecx.lazy_seq(iter.inspect(|item| { + item.hash_stable(hcx, hasher); + num_items_hashed += 1; + })); + + // Sometimes items in a sequence are filtered out without being + // hashed (e.g. for &[ast::Attribute]) and this code path cannot + // handle that correctly, so we want to make sure we didn't hit + // it by accident. + if lower_bound != num_items_hashed { + bug!("Hashed a different number of items ({}) than expected ({})", + num_items_hashed, + lower_bound); + } + debug!("metadata-hash: {:?}", hasher); + ret + } else { + // Collect into a vec so we know the length of the sequence + let items: AccumulateVec<[T; 32]> = iter.collect(); + items.hash_stable(hcx, hasher); + debug!("metadata-hash: {:?}", hasher); + self.ecx.lazy_seq(items) + } + } else { + self.ecx.lazy_seq(iter) + } + } + + pub fn lazy_seq_ref<'x, I, T>(&mut self, iter: I) -> LazySeq + where I: IntoIterator, + T: 'x + Encodable + HashStable> + { + if let Some((ref mut hcx, ref mut hasher)) = self.hcx { + let iter = iter.into_iter(); + let (lower_bound, upper_bound) = iter.size_hint(); + + if upper_bound == Some(lower_bound) { + lower_bound.hash_stable(hcx, hasher); + let mut num_items_hashed = 0; + let ret = self.ecx.lazy_seq_ref(iter.inspect(|item| { + item.hash_stable(hcx, hasher); + num_items_hashed += 1; + })); + + // Sometimes items in a sequence are filtered out without being + // hashed (e.g. for &[ast::Attribute]) and this code path cannot + // handle that correctly, so we want to make sure we didn't hit + // it by accident. + if lower_bound != num_items_hashed { + bug!("Hashed a different number of items ({}) than expected ({})", + num_items_hashed, + lower_bound); + } + debug!("metadata-hash: {:?}", hasher); + ret + } else { + // Collect into a vec so we know the length of the sequence + let items: AccumulateVec<[&'x T; 32]> = iter.collect(); + items.hash_stable(hcx, hasher); + debug!("metadata-hash: {:?}", hasher); + self.ecx.lazy_seq_ref(items.iter().map(|x| *x)) + } + } else { + self.ecx.lazy_seq_ref(iter) + } + } + + pub fn lazy_seq_from_slice(&mut self, slice: &[T]) -> LazySeq + where T: Encodable + HashStable> + { + if let Some((ref mut hcx, ref mut hasher)) = self.hcx { + slice.hash_stable(hcx, hasher); + debug!("metadata-hash: {:?}", hasher); + } + self.ecx.lazy_seq_ref(slice.iter()) + } + + pub fn lazy_seq_ref_from_slice(&mut self, slice: &[&T]) -> LazySeq + where T: Encodable + HashStable> + { + if let Some((ref mut hcx, ref mut hasher)) = self.hcx { + slice.hash_stable(hcx, hasher); + debug!("metadata-hash: {:?}", hasher); + } + self.ecx.lazy_seq_ref(slice.iter().map(|x| *x)) + } +} diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index b9e142ac650..90eb2bc0f6a 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -57,6 +57,7 @@ mod index; mod encoder; mod decoder; mod cstore_impl; +mod isolated_encoder; mod schema; pub mod creader; diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 5870903e771..5abe1adfb6f 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -13,7 +13,7 @@ use index; use rustc::hir; use rustc::hir::def::{self, CtorKind}; -use rustc::hir::def_id::{DefIndex, DefId}; +use rustc::hir::def_id::{DefIndex, DefId, CrateNum}; use rustc::ich::StableHashingContext; use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary}; use rustc::middle::lang_items; @@ -32,6 +32,8 @@ use std::mem; use rustc_data_structures::stable_hasher::{StableHasher, HashStable, StableHasherResult}; +use rustc::dep_graph::{DepGraph, DepNode}; + pub fn rustc_version() -> String { format!("rustc {}", option_env!("CFG_VERSION").unwrap_or("unknown version")) @@ -186,25 +188,59 @@ pub enum LazyState { Previous(usize), } +/// A `Tracked` wraps a value so that one can only access it when specifying +/// the `DepNode` for that value. This makes it harder to forget registering +/// reads. +#[derive(RustcEncodable, RustcDecodable)] +pub struct Tracked { + state: T, +} + +impl Tracked { + pub fn new(state: T) -> Tracked { + Tracked { + state: state, + } + } + + pub fn get(&self, dep_graph: &DepGraph, dep_node: DepNode) -> &T { + dep_graph.read(dep_node); + &self.state + } + + pub fn get_untracked(&self) -> &T { + &self.state + } + + pub fn map(&self, f: F) -> Tracked + where F: FnOnce(&T) -> R + { + Tracked { + state: f(&self.state), + } + } +} + + #[derive(RustcEncodable, RustcDecodable)] pub struct CrateRoot { pub name: Symbol, pub triple: String, pub hash: hir::svh::Svh, pub disambiguator: Symbol, - pub panic_strategy: PanicStrategy, + pub panic_strategy: Tracked, pub plugin_registrar_fn: Option, pub macro_derive_registrar: Option, - pub crate_deps: LazySeq, - pub dylib_dependency_formats: LazySeq>, - pub lang_items: LazySeq<(DefIndex, usize)>, - pub lang_items_missing: LazySeq, - pub native_libraries: LazySeq, + pub crate_deps: Tracked>, + pub dylib_dependency_formats: Tracked>>, + pub lang_items: Tracked>, + pub lang_items_missing: Tracked>, + pub native_libraries: Tracked>, pub codemap: LazySeq, pub def_path_table: Lazy, - pub impls: LazySeq, - pub exported_symbols: LazySeq, + pub impls: Tracked>, + pub exported_symbols: Tracked>, pub index: LazySeq, } @@ -215,12 +251,35 @@ pub struct CrateDep { pub kind: DepKind, } +impl_stable_hash_for!(struct CrateDep { + name, + hash, + kind +}); + #[derive(RustcEncodable, RustcDecodable)] pub struct TraitImpls { pub trait_id: (u32, DefIndex), pub impls: LazySeq, } +impl<'a, 'tcx> HashStable> for TraitImpls { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'tcx>, + hasher: &mut StableHasher) { + let TraitImpls { + trait_id: (krate, def_index), + ref impls, + } = *self; + + DefId { + krate: CrateNum::from_u32(krate), + index: def_index + }.hash_stable(hcx, hasher); + impls.hash_stable(hcx, hasher); + } +} + #[derive(RustcEncodable, RustcDecodable)] pub struct Entry<'tcx> { pub kind: EntryKind<'tcx>, diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 56ff5ebb069..8689e176f7a 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -754,10 +754,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, }).max().unwrap(); if kind == MetadataKind::None { - return (metadata_llcx, metadata_llmod, EncodedMetadata { - raw_data: vec![], - hashes: vec![], - }); + return (metadata_llcx, metadata_llmod, EncodedMetadata::new()); } let cstore = &tcx.sess.cstore; diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 8a88ec3a672..0c8be1d4f24 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -21,8 +21,8 @@ pub use syntax_pos::*; pub use syntax_pos::hygiene::{ExpnFormat, ExpnInfo, NameAndSpan}; pub use self::ExpnFormat::*; -use std::cell::RefCell; -use std::path::{Path,PathBuf}; +use std::cell::{RefCell, Ref}; +use std::path::{Path, PathBuf}; use std::rc::Rc; use std::env; @@ -103,11 +103,18 @@ impl FileLoader for RealFileLoader { // pub struct CodeMap { - pub files: RefCell>>, + // The `files` field should not be visible outside of libsyntax so that we + // can do proper dependency tracking. + pub(super) files: RefCell>>, file_loader: Box, // This is used to apply the file path remapping as specified via // -Zremap-path-prefix to all FileMaps allocated within this CodeMap. path_mapping: FilePathMapping, + // The CodeMap will invoke this callback whenever a specific FileMap is + // accessed. The callback starts out as a no-op but when the dependency + // graph becomes available later during the compilation process, it is + // be replaced with something that notifies the dep-tracking system. + dep_tracking_callback: RefCell>, } impl CodeMap { @@ -116,6 +123,7 @@ impl CodeMap { files: RefCell::new(Vec::new()), file_loader: Box::new(RealFileLoader), path_mapping: path_mapping, + dep_tracking_callback: RefCell::new(Box::new(|_| {})), } } @@ -126,6 +134,7 @@ impl CodeMap { files: RefCell::new(Vec::new()), file_loader: file_loader, path_mapping: path_mapping, + dep_tracking_callback: RefCell::new(Box::new(|_| {})), } } @@ -133,6 +142,10 @@ impl CodeMap { &self.path_mapping } + pub fn set_dep_tracking_callback(&self, cb: Box) { + *self.dep_tracking_callback.borrow_mut() = cb; + } + pub fn file_exists(&self, path: &Path) -> bool { self.file_loader.file_exists(path) } @@ -142,6 +155,19 @@ impl CodeMap { Ok(self.new_filemap(path.to_str().unwrap().to_string(), src)) } + pub fn files(&self) -> Ref>> { + let files = self.files.borrow(); + for file in files.iter() { + (self.dep_tracking_callback.borrow())(file); + } + files + } + + /// Only use this if you do your own dependency tracking! + pub fn files_untracked(&self) -> Ref>> { + self.files.borrow() + } + fn next_start_pos(&self) -> usize { let files = self.files.borrow(); match files.last() { @@ -170,6 +196,7 @@ impl CodeMap { let filemap = Rc::new(FileMap { name: filename, name_was_remapped: was_remapped, + crate_of_origin: 0, src: Some(Rc::new(src)), start_pos: Pos::from_usize(start_pos), end_pos: Pos::from_usize(end_pos), @@ -204,6 +231,7 @@ impl CodeMap { pub fn new_imported_filemap(&self, filename: FileName, name_was_remapped: bool, + crate_of_origin: u32, source_len: usize, mut file_local_lines: Vec, mut file_local_multibyte_chars: Vec) @@ -225,6 +253,7 @@ impl CodeMap { let filemap = Rc::new(FileMap { name: filename, name_was_remapped: name_was_remapped, + crate_of_origin: crate_of_origin, src: None, start_pos: start_pos, end_pos: end_pos, @@ -282,6 +311,8 @@ impl CodeMap { let files = self.files.borrow(); let f = (*files)[idx].clone(); + (self.dep_tracking_callback.borrow())(&f); + match f.lookup_line(pos) { Some(line) => Ok(FileMapAndLine { fm: f, line: line }), None => Err(f) @@ -471,6 +502,7 @@ impl CodeMap { pub fn get_filemap(&self, filename: &str) -> Option> { for fm in self.files.borrow().iter() { if filename == fm.name { + (self.dep_tracking_callback.borrow())(&fm); return Some(fm.clone()); } } @@ -481,6 +513,7 @@ impl CodeMap { pub fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos { let idx = self.lookup_filemap_idx(bpos); let fm = (*self.files.borrow())[idx].clone(); + (self.dep_tracking_callback.borrow())(&fm); let offset = bpos - fm.start_pos; FileMapAndBytePos {fm: fm, pos: offset} } @@ -491,6 +524,8 @@ impl CodeMap { let files = self.files.borrow(); let map = &(*files)[idx]; + (self.dep_tracking_callback.borrow())(map); + // The number of extra bytes due to multibyte chars in the FileMap let mut total_extra_bytes = 0; @@ -536,7 +571,7 @@ impl CodeMap { } pub fn count_lines(&self) -> usize { - self.files.borrow().iter().fold(0, |a, f| a + f.count_lines()) + self.files().iter().fold(0, |a, f| a + f.count_lines()) } } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index f46b4fcb715..ec56098aa97 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -377,6 +377,8 @@ pub struct FileMap { pub name: FileName, /// True if the `name` field above has been modified by -Zremap-path-prefix pub name_was_remapped: bool, + /// Indicates which crate this FileMap was imported from. + pub crate_of_origin: u32, /// The complete source code pub src: Option>, /// The start position of this source in the CodeMap @@ -491,6 +493,8 @@ impl Decodable for FileMap { Ok(FileMap { name: name, name_was_remapped: name_was_remapped, + // `crate_of_origin` has to be set by the importer. + crate_of_origin: 0xEFFF_FFFF, start_pos: start_pos, end_pos: end_pos, src: None, diff --git a/src/test/incremental/remapped_paths_cc/auxiliary/extern_crate.rs b/src/test/incremental/remapped_paths_cc/auxiliary/extern_crate.rs new file mode 100644 index 00000000000..09db90d618b --- /dev/null +++ b/src/test/incremental/remapped_paths_cc/auxiliary/extern_crate.rs @@ -0,0 +1,24 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +// aux-build:extern_crate.rs +//[rpass1] compile-flags: -g +//[rpass2] compile-flags: -g +//[rpass3] compile-flags: -g -Zremap-path-prefix-from={{src-base}} -Zremap-path-prefix-to=/the/src + +#![feature(rustc_attrs)] +#![crate_type="rlib"] + +#[inline(always)] +pub fn inline_fn() { + println!("test"); +} diff --git a/src/test/incremental/remapped_paths_cc/main.rs b/src/test/incremental/remapped_paths_cc/main.rs new file mode 100644 index 00000000000..8a8c658accc --- /dev/null +++ b/src/test/incremental/remapped_paths_cc/main.rs @@ -0,0 +1,42 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// revisions:rpass1 rpass2 rpass3 +// compile-flags: -Z query-dep-graph -g +// aux-build:extern_crate.rs + + +// This test case makes sure that we detect if paths emitted into debuginfo +// are changed, even when the change happens in an external crate. + +#![feature(rustc_attrs)] + +#![rustc_partition_reused(module="main", cfg="rpass2")] +#![rustc_partition_reused(module="main-some_mod", cfg="rpass2")] +#![rustc_partition_reused(module="main", cfg="rpass3")] +#![rustc_partition_translated(module="main-some_mod", cfg="rpass3")] + +extern crate extern_crate; + +#[rustc_clean(label="TransCrateItem", cfg="rpass2")] +#[rustc_clean(label="TransCrateItem", cfg="rpass3")] +fn main() { + some_mod::some_fn(); +} + +mod some_mod { + use extern_crate; + + #[rustc_clean(label="TransCrateItem", cfg="rpass2")] + #[rustc_dirty(label="TransCrateItem", cfg="rpass3")] + pub fn some_fn() { + extern_crate::inline_fn(); + } +} -- cgit 1.4.1-3-g733a5 From dd87eabd83296baa4c2214d2cf3aeef24f753ba7 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 4 May 2017 14:17:23 +0200 Subject: Remove need for &format!(...) or &&"" dances in `span_label` calls --- src/librustc/hir/check_attr.rs | 4 +- src/librustc/infer/error_reporting/mod.rs | 4 +- src/librustc/lint/context.rs | 4 +- src/librustc/middle/const_val.rs | 2 +- src/librustc/middle/effect.rs | 2 +- src/librustc/middle/entry.rs | 8 +-- src/librustc/middle/intrinsicck.rs | 4 +- src/librustc/middle/resolve_lifetime.rs | 14 ++--- src/librustc/traits/error_reporting.rs | 22 +++---- src/librustc/ty/maps.rs | 2 +- src/librustc_borrowck/borrowck/check_loans.rs | 50 ++++++++-------- .../borrowck/gather_loans/move_error.rs | 12 ++-- src/librustc_borrowck/borrowck/mod.rs | 60 +++++++++---------- src/librustc_const_eval/check_match.rs | 26 ++++---- src/librustc_errors/diagnostic.rs | 5 +- src/librustc_errors/diagnostic_builder.rs | 6 +- src/librustc_incremental/assert_dep_graph.rs | 6 +- src/librustc_incremental/persist/dirty_clean.rs | 2 +- src/librustc_lint/unused.rs | 2 +- src/librustc_metadata/creader.rs | 6 +- src/librustc_metadata/locator.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 16 ++--- src/librustc_passes/ast_validation.rs | 6 +- src/librustc_passes/consts.rs | 2 +- src/librustc_passes/loops.rs | 8 +-- src/librustc_passes/static_recursion.rs | 2 +- src/librustc_privacy/lib.rs | 6 +- src/librustc_resolve/lib.rs | 70 +++++++++++----------- src/librustc_resolve/macros.rs | 2 +- src/librustc_resolve/resolve_imports.rs | 6 +- src/librustc_typeck/astconv.rs | 30 +++++----- src/librustc_typeck/check/_match.rs | 22 +++---- src/librustc_typeck/check/autoderef.rs | 2 +- src/librustc_typeck/check/callee.rs | 2 +- src/librustc_typeck/check/cast.rs | 4 +- src/librustc_typeck/check/coercion.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 18 +++--- src/librustc_typeck/check/intrinsic.rs | 8 +-- src/librustc_typeck/check/method/confirm.rs | 4 +- src/librustc_typeck/check/method/suggest.rs | 6 +- src/librustc_typeck/check/mod.rs | 66 ++++++++++---------- src/librustc_typeck/check/op.rs | 6 +- src/librustc_typeck/check/wfcheck.rs | 6 +- src/librustc_typeck/coherence/builtin.rs | 10 ++-- src/librustc_typeck/coherence/inherent_impls.rs | 4 +- .../coherence/inherent_impls_overlap.rs | 4 +- src/librustc_typeck/coherence/mod.rs | 2 +- src/librustc_typeck/coherence/orphan.rs | 4 +- src/librustc_typeck/coherence/overlap.rs | 4 +- src/librustc_typeck/collect.rs | 8 +-- src/librustc_typeck/impl_wf_check.rs | 6 +- src/librustc_typeck/lib.rs | 6 +- src/librustdoc/html/format.rs | 4 +- src/libstd/fs.rs | 2 +- src/libsyntax/attr.rs | 3 +- src/libsyntax/parse/parser.rs | 16 ++--- 56 files changed, 305 insertions(+), 305 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index bf292ccb8d8..f553c03d09b 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -43,7 +43,7 @@ impl<'a> CheckAttrVisitor<'a> { fn check_inline(&self, attr: &ast::Attribute, target: Target) { if target != Target::Fn { struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function") - .span_label(attr.span, &format!("requires a function")) + .span_label(attr.span, "requires a function") .emit(); } } @@ -123,7 +123,7 @@ impl<'a> CheckAttrVisitor<'a> { _ => continue, }; struct_span_err!(self.sess, attr.span, E0517, "{}", message) - .span_label(attr.span, &format!("requires {}", label)) + .span_label(attr.span, format!("requires {}", label)) .emit(); } if conflicting_reprs > 1 { diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 8f2bdd4e85c..4c27bade0f7 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -668,9 +668,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - diag.span_label(span, &terr); + diag.span_label(span, terr.to_string()); if let Some((sp, msg)) = secondary_span { - diag.span_label(sp, &msg); + diag.span_label(sp, msg); } self.note_error_origin(diag, &cause); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 6947e7c3f40..6f3e84247f7 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -680,12 +680,12 @@ pub trait LintContext<'tcx>: Sized { "{}({}) overruled by outer forbid({})", level.as_str(), lint_name, lint_name); - diag_builder.span_label(span, &format!("overruled by previous forbid")); + diag_builder.span_label(span, "overruled by previous forbid"); match now_source { LintSource::Default => &mut diag_builder, LintSource::Node(_, forbid_source_span) => { diag_builder.span_label(forbid_source_span, - &format!("`forbid` level set here")) + "`forbid` level set here") }, LintSource::CommandLine(_) => { diag_builder.note("`forbid` lint level was set on command line") diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index 74026abe64d..3bbaf5c9299 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -197,7 +197,7 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> { { match self.description() { ConstEvalErrDescription::Simple(message) => { - diag.span_label(self.span, &message); + diag.span_label(self.span, message); } } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index d2b8ed8c297..e03948db368 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> { struct_span_err!( self.tcx.sess, span, E0133, "{} requires unsafe function or block", description) - .span_label(span, &description) + .span_label(span, description) .emit(); } } diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 8da7560387f..24748b6cf65 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -128,8 +128,8 @@ fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) { } else { struct_span_err!(ctxt.session, item.span, E0137, "multiple functions with a #[main] attribute") - .span_label(item.span, &format!("additional #[main] function")) - .span_label(ctxt.attr_main_fn.unwrap().1, &format!("first #[main] function")) + .span_label(item.span, "additional #[main] function") + .span_label(ctxt.attr_main_fn.unwrap().1, "first #[main] function") .emit(); } }, @@ -141,8 +141,8 @@ fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) { ctxt.session, item.span, E0138, "multiple 'start' functions") .span_label(ctxt.start_fn.unwrap().1, - &format!("previous `start` function here")) - .span_label(item.span, &format!("multiple `start` functions")) + "previous `start` function here") + .span_label(item.span, "multiple `start` functions") .emit(); } }, diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 435dd05358d..a759a9061f8 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -92,7 +92,7 @@ impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> { struct_span_err!(self.infcx.tcx.sess, span, E0591, "`{}` is zero-sized and can't be transmuted to `{}`", from, to) - .span_note(span, &format!("cast with `as` to a pointer instead")) + .span_note(span, "cast with `as` to a pointer instead") .emit(); return; } @@ -126,7 +126,7 @@ impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> { from, skeleton_string(from, sk_from), to, skeleton_string(to, sk_to)) .span_label(span, - &format!("transmuting between {} and {}", + format!("transmuting between {} and {}", skeleton_string(from, sk_from), skeleton_string(to, sk_to))) .emit(); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index a8ba708cc2c..67b8dfb2d8e 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -574,9 +574,9 @@ fn signal_shadowing_problem(sess: &Session, name: ast::Name, orig: Original, sha {} name that is already in scope", shadower.kind.desc(), name, orig.kind.desc())) }; - err.span_label(orig.span, &"first declared here"); + err.span_label(orig.span, "first declared here"); err.span_label(shadower.span, - &format!("lifetime {} already in scope", name)); + format!("lifetime {} already in scope", name)); err.emit(); } @@ -919,7 +919,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } else { struct_span_err!(self.sess, lifetime_ref.span, E0261, "use of undeclared lifetime name `{}`", lifetime_ref.name) - .span_label(lifetime_ref.span, &format!("undeclared lifetime")) + .span_label(lifetime_ref.span, "undeclared lifetime") .emit(); } } @@ -1328,7 +1328,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } else { format!("expected lifetime parameter") }; - err.span_label(span, &msg); + err.span_label(span, msg); if let Some(params) = error { if lifetime_refs.len() == 1 { @@ -1438,7 +1438,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let mut err = struct_span_err!(self.sess, lifetime.span, E0262, "invalid lifetime parameter name: `{}`", lifetime.name); err.span_label(lifetime.span, - &format!("{} is a reserved lifetime name", lifetime.name)); + format!("{} is a reserved lifetime name", lifetime.name)); err.emit(); } } @@ -1452,9 +1452,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { "lifetime name `{}` declared twice in the same scope", lifetime_j.lifetime.name) .span_label(lifetime_j.lifetime.span, - &format!("declared twice")) + "declared twice") .span_label(lifetime_i.lifetime.span, - &format!("previous declaration here")) + "previous declaration here") .emit(); } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index e846d74febf..152e3353994 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -484,12 +484,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Some(trait_item_span) = self.tcx.hir.span_if_local(trait_item_def_id) { let span = self.tcx.sess.codemap().def_span(trait_item_span); - err.span_label(span, &format!("definition of `{}` from trait", item_name)); + err.span_label(span, format!("definition of `{}` from trait", item_name)); } err.span_label( error_span, - &format!("impl has extra requirement {}", requirement)); + format!("impl has extra requirement {}", requirement)); if let Some(node_id) = lint_id { self.tcx.sess.add_lint_diagnostic(EXTRA_REQUIREMENT_IN_IMPL, @@ -582,7 +582,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } err.span_label(span, - &format!("{}the trait `{}` is not implemented for `{}`", + format!("{}the trait `{}` is not implemented for `{}`", pre_message, trait_ref, trait_ref.self_ty())); @@ -738,11 +738,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { expected_ref, found_ref); - err.span_label(span, &format!("{}", type_error)); + err.span_label(span, format!("{}", type_error)); if let Some(sp) = found_span { - err.span_label(span, &format!("requires `{}`", found_ref)); - err.span_label(sp, &format!("implements `{}`", expected_ref)); + err.span_label(span, format!("requires `{}`", found_ref)); + err.span_label(sp, format!("implements `{}`", expected_ref)); } err @@ -765,12 +765,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if expected == 1 { "" } else { "s" }, if expected == 1 { "is" } else { "are" }); - err.span_label(span, &format!("expected {} that takes {} argument{}", + err.span_label(span, format!("expected {} that takes {} argument{}", if is_closure { "closure" } else { "function" }, expected, if expected == 1 { "" } else { "s" })); if let Some(span) = found_span { - err.span_label(span, &format!("takes {} argument{}", + err.span_label(span, format!("takes {} argument{}", found, if found == 1 { "" } else { "s" })); } @@ -789,7 +789,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let mut err = struct_span_err!(self.sess, span, E0072, "recursive type `{}` has infinite size", self.item_path_str(type_def_id)); - err.span_label(span, &format!("recursive type has infinite size")); + err.span_label(span, "recursive type has infinite size"); err.help(&format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \ at some point to make `{}` representable", self.item_path_str(type_def_id))); @@ -808,7 +808,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.sess, span, E0038, "the trait `{}` cannot be made into an object", trait_str); - err.span_label(span, &format!("the trait `{}` cannot be made into an object", trait_str)); + err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str)); let mut reported_violations = FxHashSet(); for violation in violations { @@ -1043,7 +1043,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { "type annotations needed"); for (target_span, label_message) in labels { - err.span_label(target_span, &label_message); + err.span_label(target_span, label_message); } err.emit(); diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index a737e7caa3e..82a4c1e1e62 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -181,7 +181,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let mut err = struct_span_err!(self.sess, span, E0391, "unsupported cyclic reference between types/traits detected"); - err.span_label(span, &format!("cyclic reference")); + err.span_label(span, "cyclic reference"); err.span_note(stack[0].0, &format!("the cycle begins when {}...", stack[0].1.describe(self))); diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 1c5a6c3985c..adabbe11f5e 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -469,13 +469,13 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { nl, new_loan_msg); err.span_label( old_loan.span, - &format!("first mutable borrow occurs here{}", old_loan_msg)); + format!("first mutable borrow occurs here{}", old_loan_msg)); err.span_label( new_loan.span, - &format!("second mutable borrow occurs here{}", new_loan_msg)); + format!("second mutable borrow occurs here{}", new_loan_msg)); err.span_label( previous_end_span, - &format!("first borrow ends here")); + "first borrow ends here"); err } @@ -486,13 +486,13 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { nl); err.span_label( old_loan.span, - &format!("first closure is constructed here")); + "first closure is constructed here"); err.span_label( new_loan.span, - &format!("second closure is constructed here")); + "second closure is constructed here"); err.span_label( previous_end_span, - &format!("borrow from first closure ends here")); + "borrow from first closure ends here"); err } @@ -503,13 +503,13 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { nl, ol_pronoun, old_loan_msg); err.span_label( new_loan.span, - &format!("closure construction occurs here{}", new_loan_msg)); + format!("closure construction occurs here{}", new_loan_msg)); err.span_label( old_loan.span, - &format!("borrow occurs here{}", old_loan_msg)); + format!("borrow occurs here{}", old_loan_msg)); err.span_label( previous_end_span, - &format!("borrow ends here")); + "borrow ends here"); err } @@ -520,13 +520,13 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { nl, new_loan_msg, new_loan.kind.to_user_str()); err.span_label( new_loan.span, - &format!("borrow occurs here{}", new_loan_msg)); + format!("borrow occurs here{}", new_loan_msg)); err.span_label( old_loan.span, - &format!("closure construction occurs here{}", old_loan_msg)); + format!("closure construction occurs here{}", old_loan_msg)); err.span_label( previous_end_span, - &format!("borrow from closure ends here")); + "borrow from closure ends here"); err } @@ -542,17 +542,17 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { old_loan_msg); err.span_label( new_loan.span, - &format!("{} borrow occurs here{}", + format!("{} borrow occurs here{}", new_loan.kind.to_user_str(), new_loan_msg)); err.span_label( old_loan.span, - &format!("{} borrow occurs here{}", + format!("{} borrow occurs here{}", old_loan.kind.to_user_str(), old_loan_msg)); err.span_label( previous_end_span, - &format!("{} borrow ends here", + format!("{} borrow ends here", old_loan.kind.to_user_str())); err } @@ -562,7 +562,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { euv::ClosureCapture(span) => { err.span_label( span, - &format!("borrow occurs due to use of `{}` in closure", nl)); + format!("borrow occurs due to use of `{}` in closure", nl)); } _ => { } } @@ -571,7 +571,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { euv::ClosureCapture(span) => { err.span_label( span, - &format!("previous borrow occurs due to use of `{}` in closure", + format!("previous borrow occurs due to use of `{}` in closure", ol)); } _ => { } @@ -633,11 +633,11 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { "cannot use `{}` because it was mutably borrowed", &self.bccx.loan_path_to_string(copy_path)) .span_label(loan_span, - &format!("borrow of `{}` occurs here", + format!("borrow of `{}` occurs here", &self.bccx.loan_path_to_string(&loan_path)) ) .span_label(span, - &format!("use of borrowed `{}`", + format!("use of borrowed `{}`", &self.bccx.loan_path_to_string(&loan_path))) .emit(); } @@ -662,12 +662,12 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { &self.bccx.loan_path_to_string(move_path)); err.span_label( loan_span, - &format!("borrow of `{}` occurs here", + format!("borrow of `{}` occurs here", &self.bccx.loan_path_to_string(&loan_path)) ); err.span_label( span, - &format!("move into closure occurs here") + "move into closure occurs here" ); err } @@ -679,12 +679,12 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { &self.bccx.loan_path_to_string(move_path)); err.span_label( loan_span, - &format!("borrow of `{}` occurs here", + format!("borrow of `{}` occurs here", &self.bccx.loan_path_to_string(&loan_path)) ); err.span_label( span, - &format!("move out of `{}` occurs here", + format!("move out of `{}` occurs here", &self.bccx.loan_path_to_string(move_path)) ); err @@ -857,10 +857,10 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { "cannot assign to `{}` because it is borrowed", self.bccx.loan_path_to_string(loan_path)) .span_label(loan.span, - &format!("borrow of `{}` occurs here", + format!("borrow of `{}` occurs here", self.bccx.loan_path_to_string(loan_path))) .span_label(span, - &format!("assignment to borrowed `{}` occurs here", + format!("assignment to borrowed `{}` occurs here", self.bccx.loan_path_to_string(loan_path))) .emit(); } diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index b7ce9d98233..1ee6d565d0d 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -94,7 +94,7 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, errors: &Vec(bccx: &BorrowckCtxt<'a, 'tcx>, move_from.descriptive_string(bccx.tcx)); err.span_label( move_from.span, - &format!("cannot move out of {}", move_from.descriptive_string(bccx.tcx)) + format!("cannot move out of {}", move_from.descriptive_string(bccx.tcx)) ); err } @@ -160,7 +160,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, "cannot move out of type `{}`, \ a non-copy array", b.ty); - err.span_label(move_from.span, &format!("cannot move out of here")); + err.span_label(move_from.span, "cannot move out of here"); err } (_, Kind::Pattern) => { @@ -177,7 +177,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, "cannot move out of type `{}`, \ which implements the `Drop` trait", b.ty); - err.span_label(move_from.span, &format!("cannot move out of here")); + err.span_label(move_from.span, "cannot move out of here"); err }, _ => { @@ -198,12 +198,12 @@ fn note_move_destination(mut err: DiagnosticBuilder, if is_first_note { err.span_label( move_to_span, - &format!("hint: to prevent move, use `ref {0}` or `ref mut {0}`", + format!("hint: to prevent move, use `ref {0}` or `ref mut {0}`", pat_name)); err } else { err.span_label(move_to_span, - &format!("...and here (use `ref {0}` or `ref mut {0}`)", + format!("...and here (use `ref {0}` or `ref mut {0}`)", pat_name)); err } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index f8073455bd0..7eb73a87532 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -546,7 +546,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { "{} of possibly uninitialized variable: `{}`", verb, self.loan_path_to_string(lp)) - .span_label(use_span, &format!("use of possibly uninitialized `{}`", + .span_label(use_span, format!("use of possibly uninitialized `{}`", self.loan_path_to_string(lp))) .emit(); return; @@ -616,12 +616,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { err = if use_span == move_span { err.span_label( use_span, - &format!("value moved{} here in previous iteration of loop", + format!("value moved{} here in previous iteration of loop", move_note)); err } else { - err.span_label(use_span, &format!("value {} here after move", verb_participle)) - .span_label(move_span, &format!("value moved{} here", move_note)); + err.span_label(use_span, format!("value {} here after move", verb_participle)) + .span_label(move_span, format!("value moved{} here", move_note)); err }; @@ -657,9 +657,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess, span, E0384, "re-assignment of immutable variable `{}`", self.loan_path_to_string(lp)); - err.span_label(span, &format!("re-assignment of immutable variable")); + err.span_label(span, "re-assignment of immutable variable"); if span != assign.span { - err.span_label(assign.span, &format!("first assignment to `{}`", + err.span_label(assign.span, format!("first assignment to `{}`", self.loan_path_to_string(lp))); } err.emit(); @@ -821,7 +821,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { let mut err = struct_span_err!( self.tcx.sess, span, E0389, "{} in a `&` reference", prefix); - err.span_label(span, &"assignment into an immutable reference"); + err.span_label(span, "assignment into an immutable reference"); err } }; @@ -914,7 +914,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } db.span_label( let_span, - &format!("consider changing this to `mut {}`", snippet) + format!("consider changing this to `mut {}`", snippet) ); } } @@ -927,7 +927,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { if let Ok(snippet) = snippet { db.span_label( let_span, - &format!("consider changing this to `{}`", + format!("consider changing this to `{}`", snippet.replace("ref ", "ref mut ")) ); } @@ -936,7 +936,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { if let (Some(local_ty), is_implicit_self) = self.local_ty(node_id) { if let Some(msg) = self.suggest_mut_for_immutable(local_ty, is_implicit_self) { - db.span_label(local_ty.span, &msg); + db.span_label(local_ty.span, msg); } } } @@ -950,7 +950,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { if let hir_map::Node::NodeField(ref field) = self.tcx.hir.get(node_id) { if let Some(msg) = self.suggest_mut_for_immutable(&field.ty, false) { - db.span_label(field.ty.span, &msg); + db.span_label(field.ty.span, msg); } } } @@ -975,10 +975,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { which is owned by the current function", cmt_path_or_string) .span_label(capture_span, - &format!("{} is borrowed here", + format!("{} is borrowed here", cmt_path_or_string)) .span_label(err.span, - &format!("may outlive borrowed value {}", + format!("may outlive borrowed value {}", cmt_path_or_string)) .span_suggestion(err.span, &format!("to force the closure to take ownership of {} \ @@ -1029,15 +1029,15 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { match db.span.primary_span() { Some(primary) => { db.span = MultiSpan::from_span(s); - db.span_label(primary, &format!("capture occurs here")); - db.span_label(s, &"does not live long enough"); + db.span_label(primary, "capture occurs here"); + db.span_label(s, "does not live long enough"); true } None => false } } _ => { - db.span_label(error_span, &"does not live long enough"); + db.span_label(error_span, "does not live long enough"); false } }; @@ -1049,7 +1049,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { (Some(s1), Some(s2)) if s1 == s2 => { if !is_closure { db.span = MultiSpan::from_span(s1); - db.span_label(error_span, &value_msg); + db.span_label(error_span, value_msg); let msg = match opt_loan_path(&err.cmt) { None => value_kind.to_string(), Some(lp) => { @@ -1057,29 +1057,29 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } }; db.span_label(s1, - &format!("{} dropped here while still borrowed", msg)); + format!("{} dropped here while still borrowed", msg)); } else { - db.span_label(s1, &format!("{} dropped before borrower", value_kind)); + db.span_label(s1, format!("{} dropped before borrower", value_kind)); } db.note("values in a scope are dropped in the opposite order \ they are created"); } (Some(s1), Some(s2)) if !is_closure => { db.span = MultiSpan::from_span(s2); - db.span_label(error_span, &value_msg); + db.span_label(error_span, value_msg); let msg = match opt_loan_path(&err.cmt) { None => value_kind.to_string(), Some(lp) => { format!("`{}`", self.loan_path_to_string(&lp)) } }; - db.span_label(s2, &format!("{} dropped here while still borrowed", msg)); - db.span_label(s1, &format!("{} needs to live until here", value_kind)); + db.span_label(s2, format!("{} dropped here while still borrowed", msg)); + db.span_label(s1, format!("{} needs to live until here", value_kind)); } _ => { match sub_span { Some(s) => { - db.span_label(s, &format!("{} needs to live until here", + db.span_label(s, format!("{} needs to live until here", value_kind)); } None => { @@ -1092,7 +1092,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } match super_span { Some(s) => { - db.span_label(s, &format!("{} only lives until here", value_kind)); + db.span_label(s, format!("{} only lives until here", value_kind)); } None => { self.tcx.note_and_explain_region( @@ -1162,23 +1162,23 @@ before rustc 1.16, this temporary lived longer - see issue #39283 \ } _ => { if let Categorization::Deref(..) = err.cmt.cat { - db.span_label(*error_span, &"cannot borrow as mutable"); + db.span_label(*error_span, "cannot borrow as mutable"); } else if let Categorization::Local(local_id) = err.cmt.cat { let span = self.tcx.hir.span(local_id); if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { if snippet.starts_with("ref mut ") || snippet.starts_with("&mut ") { - db.span_label(*error_span, &format!("cannot reborrow mutably")); - db.span_label(*error_span, &format!("try removing `&mut` here")); + db.span_label(*error_span, "cannot reborrow mutably"); + db.span_label(*error_span, "try removing `&mut` here"); } else { - db.span_label(*error_span, &format!("cannot borrow mutably")); + db.span_label(*error_span, "cannot borrow mutably"); } } else { - db.span_label(*error_span, &format!("cannot borrow mutably")); + db.span_label(*error_span, "cannot borrow mutably"); } } else if let Categorization::Interior(ref cmt, _) = err.cmt.cat { if let mc::MutabilityCategory::McImmutable = cmt.mutbl { db.span_label(*error_span, - &"cannot mutably borrow immutable field"); + "cannot mutably borrow immutable field"); } } } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 6ec5f38aa5b..cd31290eb55 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -258,7 +258,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { "refutable pattern in {}: `{}` not covered", origin, pattern_string ); - diag.span_label(pat.span, &format!("pattern `{}` not covered", pattern_string)); + diag.span_label(pat.span, format!("pattern `{}` not covered", pattern_string)); diag.emit(); }); } @@ -328,7 +328,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, let span = first_pat.0.span; struct_span_err!(cx.tcx.sess, span, E0162, "irrefutable if-let pattern") - .span_label(span, &format!("irrefutable pattern")) + .span_label(span, "irrefutable pattern") .emit(); printed_if_let_err = true; } @@ -355,7 +355,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, 1 => { struct_span_err!(cx.tcx.sess, span, E0165, "irrefutable while-let pattern") - .span_label(span, &format!("irrefutable pattern")) + .span_label(span, "irrefutable pattern") .emit(); }, _ => bug!(), @@ -369,7 +369,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, diagnostic.set_span(pat.span); // if we had a catchall pattern, hint at that if let Some(catchall) = catchall { - diagnostic.span_label(pat.span, &"this is an unreachable pattern"); + diagnostic.span_label(pat.span, "this is an unreachable pattern"); diagnostic.span_note(catchall, "this pattern matches any value"); } cx.tcx.sess.add_lint_diagnostic(lint::builtin::UNREACHABLE_PATTERNS, @@ -426,7 +426,7 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, "refutable pattern in `for` loop binding: \ `{}` not covered", pattern_string) - .span_label(sp, &format!("pattern `{}` not covered", pattern_string)) + .span_label(sp, format!("pattern `{}` not covered", pattern_string)) .emit(); }, _ => { @@ -453,7 +453,7 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, create_e0004(cx.tcx.sess, sp, format!("non-exhaustive patterns: {} not covered", joined_patterns)) - .span_label(sp, &label_text) + .span_label(sp, label_text) .emit(); }, } @@ -485,18 +485,18 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, if sub.map_or(false, |p| p.contains_bindings()) { struct_span_err!(cx.tcx.sess, p.span, E0007, "cannot bind by-move with sub-bindings") - .span_label(p.span, &format!("binds an already bound by-move value by moving it")) + .span_label(p.span, "binds an already bound by-move value by moving it") .emit(); } else if has_guard { struct_span_err!(cx.tcx.sess, p.span, E0008, "cannot bind by-move into a pattern guard") - .span_label(p.span, &format!("moves value into pattern guard")) + .span_label(p.span, "moves value into pattern guard") .emit(); } else if by_ref_span.is_some() { struct_span_err!(cx.tcx.sess, p.span, E0009, "cannot bind by-move and by-ref in the same pattern") - .span_label(p.span, &format!("by-move pattern here")) - .span_label(by_ref_span.unwrap(), &format!("both by-ref and by-move used")) + .span_label(p.span, "by-move pattern here") + .span_label(by_ref_span.unwrap(), "both by-ref and by-move used") .emit(); } }; @@ -546,7 +546,7 @@ impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> { ty::MutBorrow => { struct_span_err!(self.cx.tcx.sess, span, E0301, "cannot mutably borrow in a pattern guard") - .span_label(span, &format!("borrowed mutably in pattern guard")) + .span_label(span, "borrowed mutably in pattern guard") .emit(); } ty::ImmBorrow | ty::UniqueImmBorrow => {} @@ -557,7 +557,7 @@ impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> { match mode { MutateMode::JustWrite | MutateMode::WriteAndRead => { struct_span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard") - .span_label(span, &format!("assignment in pattern guard")) + .span_label(span, "assignment in pattern guard") .emit(); } MutateMode::Init => {} @@ -588,7 +588,7 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> { if !self.bindings_allowed { struct_span_err!(self.cx.tcx.sess, pat.span, E0303, "pattern bindings are not allowed after an `@`") - .span_label(pat.span, &format!("not allowed after `@`")) + .span_label(pat.span, "not allowed after `@`") .emit(); } diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 38fa35ecb12..0822f713499 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -114,9 +114,8 @@ impl Diagnostic { /// all, and you just supplied a `Span` to create the diagnostic, /// then the snippet will just include that `Span`, which is /// called the primary span. - pub fn span_label(&mut self, span: Span, label: &fmt::Display) - -> &mut Self { - self.span.push_span_label(span, format!("{}", label)); + pub fn span_label>(&mut self, span: Span, label: T) -> &mut Self { + self.span.push_span_label(span, label.into()); self } diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 9dfd47b8464..a9c2bbeba2a 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -112,8 +112,10 @@ impl<'a> DiagnosticBuilder<'a> { /// all, and you just supplied a `Span` to create the diagnostic, /// then the snippet will just include that `Span`, which is /// called the primary span. - forward!(pub fn span_label(&mut self, span: Span, label: &fmt::Display) - -> &mut Self); + pub fn span_label>(&mut self, span: Span, label: T) -> &mut Self { + self.diagnostic.span_label(span, label); + self + } forward!(pub fn note_expected_found(&mut self, label: &fmt::Display, diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 7905128bb6e..39fe2188f68 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -154,7 +154,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { None => { self.tcx.sess.span_fatal( attr.span, - &format!("missing DepNode variant")); + "missing DepNode variant"); } }; self.then_this_would_need.push((attr.span, @@ -201,7 +201,7 @@ fn check_paths<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for &(target_span, _, _, _) in then_this_would_need { tcx.sess.span_err( target_span, - &format!("no #[rustc_if_this_changed] annotation detected")); + "no #[rustc_if_this_changed] annotation detected"); } return; @@ -219,7 +219,7 @@ fn check_paths<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } else { tcx.sess.span_err( target_span, - &format!("OK")); + "OK"); } } } diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index b73b3e161f9..5facfe36efd 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -383,7 +383,7 @@ fn check_config(tcx: TyCtxt, attr: &Attribute) -> bool { tcx.sess.span_fatal( attr.span, - &format!("no cfg attribute")); + "no cfg attribute"); } fn expect_associated_value(tcx: TyCtxt, item: &NestedMetaItem) -> ast::Name { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 86bf209ccf8..93ff609a280 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -215,7 +215,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedUnsafe { let mut db = cx.struct_span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block"); - db.span_label(blk.span, &"unnecessary `unsafe` block"); + db.span_label(blk.span, "unnecessary `unsafe` block"); if let Some((kind, id)) = is_enclosed(cx, blk.id) { db.span_note(cx.tcx.hir.span(id), &format!("because it's nested under this `unsafe` {}", kind)); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 966e814e337..325511c9787 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -88,7 +88,7 @@ fn register_native_lib(sess: &Session, Some(span) => { struct_span_err!(sess, span, E0454, "#[link(name = \"\")] given with empty name") - .span_label(span, &format!("empty name given")) + .span_label(span, "empty name given") .emit(); } None => { @@ -1029,7 +1029,7 @@ impl<'a> CrateLoader<'a> { Some(k) => { struct_span_err!(self.sess, m.span, E0458, "unknown kind: `{}`", k) - .span_label(m.span, &format!("unknown kind")).emit(); + .span_label(m.span, "unknown kind").emit(); cstore::NativeUnknown } None => cstore::NativeUnknown @@ -1042,7 +1042,7 @@ impl<'a> CrateLoader<'a> { None => { struct_span_err!(self.sess, m.span, E0459, "#[link(...)] specified without `name = \"foo\"`") - .span_label(m.span, &format!("missing `name` argument")).emit(); + .span_label(m.span, "missing `name` argument").emit(); Symbol::intern("foo") } }; diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index e8bc8b01652..84bb82de370 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -367,7 +367,7 @@ impl<'a> Context<'a> { && self.triple != config::host_triple() { err.note(&format!("the `{}` target may not be installed", self.triple)); } - err.span_label(self.span, &format!("can't find crate")); + err.span_label(self.span, "can't find crate"); err }; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 4b1c82f383f..0d592b4d72b 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -242,9 +242,9 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { to the crate attributes to enable"); } else { self.find_drop_implementation_method_span() - .map(|span| err.span_label(span, &format!("destructor defined here"))); + .map(|span| err.span_label(span, "destructor defined here")); - err.span_label(self.span, &format!("constants cannot have destructors")); + err.span_label(self.span, "constants cannot have destructors"); } err.emit(); @@ -291,8 +291,8 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { "cannot refer to statics by value, use a constant instead" }; struct_span_err!(self.tcx.sess, self.span, E0394, "{}", msg) - .span_label(self.span, &format!("referring to another static by value")) - .note(&format!("use the address-of operator or a constant instead")) + .span_label(self.span, "referring to another static by value") + .note("use the address-of operator or a constant instead") .emit(); // Replace STATIC with NOT_CONST to avoid further errors. @@ -529,7 +529,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { "raw pointers cannot be dereferenced in {}s", this.mode) .span_label(this.span, - &format!("dereference of raw pointer in constant")) + "dereference of raw pointer in constant") .emit(); } } @@ -645,7 +645,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { struct_span_err!(self.tcx.sess, self.span, E0017, "references in {}s may only refer \ to immutable values", self.mode) - .span_label(self.span, &format!("{}s require immutable values", + .span_label(self.span, format!("{}s require immutable values", self.mode)) .emit(); } @@ -713,7 +713,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { self.mode) .span_label( self.span, - &format!("comparing raw pointers in static")) + "comparing raw pointers in static") .emit(); } } @@ -724,7 +724,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { if self.mode != Mode::Fn { struct_span_err!(self.tcx.sess, self.span, E0010, "allocations are not allowed in {}s", self.mode) - .span_label(self.span, &format!("allocation not allowed in {}s", self.mode)) + .span_label(self.span, format!("allocation not allowed in {}s", self.mode)) .emit(); } } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 8c45a666945..d7fee7f3110 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -55,7 +55,7 @@ impl<'a> AstValidator<'a> { E0449, "unnecessary visibility qualifier"); if vis == &Visibility::Public { - err.span_label(span, &format!("`pub` not needed here")); + err.span_label(span, "`pub` not needed here"); } if let Some(note) = note { err.note(note); @@ -80,7 +80,7 @@ impl<'a> AstValidator<'a> { Constness::Const => { struct_span_err!(self.session, constness.span, E0379, "trait fns cannot be declared const") - .span_label(constness.span, &format!("trait fns cannot be const")) + .span_label(constness.span, "trait fns cannot be const") .emit(); } _ => {} @@ -272,7 +272,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { E0130, "patterns aren't allowed in foreign function \ declarations"); - err.span_label(span, &format!("pattern not allowed in foreign function")); + err.span_label(span, "pattern not allowed in foreign function"); if is_recent { err.span_note(span, "this is a recent error, see issue #35203 for more details"); diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 608238dfe37..a0998b1bd1b 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -180,7 +180,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { Ok(Ordering::Greater) => { struct_span_err!(self.tcx.sess, start.span, E0030, "lower range bound must be less than or equal to upper") - .span_label(start.span, &format!("lower bound larger than upper bound")) + .span_label(start.span, "lower bound larger than upper bound") .emit(); } Err(ErrorReported) => {} diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 2ea235af103..21a4c007fb1 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -118,7 +118,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { "`break` with value from a `{}` loop", kind.name()) .span_label(e.span, - &format!("can only break with a value inside `loop`")) + "can only break with a value inside `loop`") .emit(); } } @@ -154,12 +154,12 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { Loop(_) => {} Closure => { struct_span_err!(self.sess, span, E0267, "`{}` inside of a closure", name) - .span_label(span, &format!("cannot break inside of a closure")) + .span_label(span, "cannot break inside of a closure") .emit(); } Normal => { struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name) - .span_label(span, &format!("cannot break outside of a loop")) + .span_label(span, "cannot break outside of a loop") .emit(); } } @@ -169,7 +169,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { struct_span_err!(self.sess, span, E0590, "`break` or `continue` with no label in the condition of a `while` loop") .span_label(span, - &format!("unlabeled `{}` in the condition of a `while` loop", cf_type)) + format!("unlabeled `{}` in the condition of a `while` loop", cf_type)) .emit(); } } diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs index d0bf49b7b33..8d455adc23c 100644 --- a/src/librustc_passes/static_recursion.rs +++ b/src/librustc_passes/static_recursion.rs @@ -138,7 +138,7 @@ impl<'a, 'b: 'a, 'hir: 'b> CheckItemRecursionVisitor<'a, 'b, 'hir> { }); if !any_static { struct_span_err!(self.sess, span, E0265, "recursive constant") - .span_label(span, &format!("recursion not allowed in constant")) + .span_label(span, "recursion not allowed in constant") .emit(); } return; diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 82c91727293..f63102433c1 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -433,7 +433,7 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { if !def.is_enum() && !field.vis.is_accessible_from(self.current_item, self.tcx) { struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private", field.name, def.variant_descr(), self.tcx.item_path_str(def.did)) - .span_label(span, &format!("field `{}` is private", field.name)) + .span_label(span, format!("field `{}` is private", field.name)) .emit(); } } @@ -926,7 +926,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<' if self.has_pub_restricted || self.has_old_errors { let mut err = struct_span_err!(self.tcx.sess, self.span, E0446, "private type `{}` in public interface", ty); - err.span_label(self.span, &format!("can't leak private type")); + err.span_label(self.span, "can't leak private type"); err.emit(); } else { self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC, @@ -961,7 +961,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<' if self.has_pub_restricted || self.has_old_errors { struct_span_err!(self.tcx.sess, self.span, E0445, "private trait `{}` in public interface", trait_ref) - .span_label(self.span, &format!( + .span_label(self.span, format!( "private trait can't be public")) .emit(); } else { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a4e9a8be49f..ac556270886 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -183,7 +183,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, E0401, "can't use type parameters from outer function; \ try using a local type parameter instead"); - err.span_label(span, &format!("use of type variable from outer function")); + err.span_label(span, "use of type variable from outer function"); err } ResolutionError::OuterTypeParameterContext => { @@ -199,8 +199,8 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, "the name `{}` is already used for a type parameter \ in this type parameter list", name); - err.span_label(span, &format!("already used")); - err.span_label(first_use_span.clone(), &format!("first use of `{}`", name)); + err.span_label(span, "already used"); + err.span_label(first_use_span.clone(), format!("first use of `{}`", name)); err } ResolutionError::MethodNotMemberOfTrait(method, trait_) => { @@ -210,7 +210,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, "method `{}` is not a member of trait `{}`", method, trait_); - err.span_label(span, &format!("not a member of trait `{}`", trait_)); + err.span_label(span, format!("not a member of trait `{}`", trait_)); err } ResolutionError::TypeNotMemberOfTrait(type_, trait_) => { @@ -220,7 +220,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, "type `{}` is not a member of trait `{}`", type_, trait_); - err.span_label(span, &format!("not a member of trait `{}`", trait_)); + err.span_label(span, format!("not a member of trait `{}`", trait_)); err } ResolutionError::ConstNotMemberOfTrait(const_, trait_) => { @@ -230,7 +230,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, "const `{}` is not a member of trait `{}`", const_, trait_); - err.span_label(span, &format!("not a member of trait `{}`", trait_)); + err.span_label(span, format!("not a member of trait `{}`", trait_)); err } ResolutionError::VariableNotBoundInPattern(binding_error) => { @@ -239,11 +239,11 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, let msg = format!("variable `{}` is not bound in all patterns", binding_error.name); let mut err = resolver.session.struct_span_err_with_code(msp, &msg, "E0408"); for sp in target_sp { - err.span_label(sp, &format!("pattern doesn't bind `{}`", binding_error.name)); + err.span_label(sp, format!("pattern doesn't bind `{}`", binding_error.name)); } let origin_sp = binding_error.origin.iter().map(|x| *x).collect::>(); for sp in origin_sp { - err.span_label(sp, &"variable not in all patterns"); + err.span_label(sp, "variable not in all patterns"); } err } @@ -255,8 +255,8 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, "variable `{}` is bound in inconsistent \ ways within the same match arm", variable_name); - err.span_label(span, &format!("bound in different ways")); - err.span_label(first_binding_span, &format!("first binding")); + err.span_label(span, "bound in different ways"); + err.span_label(first_binding_span, "first binding"); err } ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => { @@ -265,7 +265,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, E0415, "identifier `{}` is bound more than once in this parameter list", identifier); - err.span_label(span, &format!("used as parameter more than once")); + err.span_label(span, "used as parameter more than once"); err } ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => { @@ -274,7 +274,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, E0416, "identifier `{}` is bound more than once in the same pattern", identifier); - err.span_label(span, &format!("used in a pattern more than once")); + err.span_label(span, "used in a pattern more than once"); err } ResolutionError::UndeclaredLabel(name) => { @@ -283,7 +283,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, E0426, "use of undeclared label `{}`", name); - err.span_label(span, &format!("undeclared label `{}`",&name)); + err.span_label(span, format!("undeclared label `{}`", name)); err } ResolutionError::SelfImportsOnlyAllowedWithin => { @@ -313,14 +313,14 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, }; let mut err = struct_span_err!(resolver.session, span, E0432, "{}", msg); if let Some((_, p)) = name { - err.span_label(span, &p); + err.span_label(span, p); } err } ResolutionError::FailedToResolve(msg) => { let mut err = struct_span_err!(resolver.session, span, E0433, "failed to resolve. {}", msg); - err.span_label(span, &msg); + err.span_label(span, msg); err } ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => { @@ -336,7 +336,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, span, E0435, "attempt to use a non-constant value in a constant"); - err.span_label(span, &format!("non-constant used with constant")); + err.span_label(span, "non-constant used with constant"); err } ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => { @@ -345,9 +345,9 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, span, E0530, "{}s cannot shadow {}s", what_binding, shadows_what); - err.span_label(span, &format!("cannot be named the same as a {}", shadows_what)); + err.span_label(span, format!("cannot be named the same as a {}", shadows_what)); let participle = if binding.is_import() { "imported" } else { "defined" }; - let msg = &format!("a {} `{}` is {} here", shadows_what, name, participle); + let msg = format!("a {} `{}` is {} here", shadows_what, name, participle); err.span_label(binding.span, msg); err } @@ -355,7 +355,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, let mut err = struct_span_err!(resolver.session, span, E0128, "type parameters with a default cannot use \ forward declared identifiers"); - err.span_label(span, &format!("defaulted type parameters \ + err.span_label(span, format!("defaulted type parameters \ cannot be forward declared")); err } @@ -2256,13 +2256,13 @@ impl<'a> Resolver<'a> { if is_self_type(path, ns) { __diagnostic_used!(E0411); err.code("E0411".into()); - err.span_label(span, &format!("`Self` is only available in traits and impls")); + err.span_label(span, "`Self` is only available in traits and impls"); return err; } if is_self_value(path, ns) { __diagnostic_used!(E0424); err.code("E0424".into()); - err.span_label(span, &format!("`self` value is only available in \ + err.span_label(span, format!("`self` value is only available in \ methods with `self` parameter")); return err; } @@ -2294,18 +2294,18 @@ impl<'a> Resolver<'a> { let self_is_available = this.self_value_is_available(path[0].ctxt); match candidate { AssocSuggestion::Field => { - err.span_label(span, &format!("did you mean `self.{}`?", path_str)); + err.span_label(span, format!("did you mean `self.{}`?", path_str)); if !self_is_available { - err.span_label(span, &format!("`self` value is only available in \ + err.span_label(span, format!("`self` value is only available in \ methods with `self` parameter")); } } AssocSuggestion::MethodWithSelf if self_is_available => { - err.span_label(span, &format!("did you mean `self.{}(...)`?", + err.span_label(span, format!("did you mean `self.{}(...)`?", path_str)); } AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => { - err.span_label(span, &format!("did you mean `Self::{}`?", path_str)); + err.span_label(span, format!("did you mean `Self::{}`?", path_str)); } } return err; @@ -2316,7 +2316,7 @@ impl<'a> Resolver<'a> { // Try Levenshtein. if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected) { - err.span_label(ident_span, &format!("did you mean `{}`?", candidate)); + err.span_label(ident_span, format!("did you mean `{}`?", candidate)); levenshtein_worked = true; } @@ -2324,21 +2324,21 @@ impl<'a> Resolver<'a> { if let Some(def) = def { match (def, source) { (Def::Macro(..), _) => { - err.span_label(span, &format!("did you mean `{}!(...)`?", path_str)); + err.span_label(span, format!("did you mean `{}!(...)`?", path_str)); return err; } (Def::TyAlias(..), PathSource::Trait) => { - err.span_label(span, &format!("type aliases cannot be used for traits")); + err.span_label(span, "type aliases cannot be used for traits"); return err; } (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node { ExprKind::Field(_, ident) => { - err.span_label(parent.span, &format!("did you mean `{}::{}`?", + err.span_label(parent.span, format!("did you mean `{}::{}`?", path_str, ident.node)); return err; } ExprKind::MethodCall(ident, ..) => { - err.span_label(parent.span, &format!("did you mean `{}::{}(...)`?", + err.span_label(parent.span, format!("did you mean `{}::{}(...)`?", path_str, ident.node)); return err; } @@ -2349,12 +2349,12 @@ impl<'a> Resolver<'a> { if let Some((ctor_def, ctor_vis)) = this.struct_constructors.get(&def_id).cloned() { if is_expected(ctor_def) && !this.is_accessible(ctor_vis) { - err.span_label(span, &format!("constructor is not visible \ + err.span_label(span, format!("constructor is not visible \ here due to private fields")); } } } - err.span_label(span, &format!("did you mean `{} {{ /* fields */ }}`?", + err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", path_str)); return err; } @@ -2364,7 +2364,7 @@ impl<'a> Resolver<'a> { // Fallback label. if !levenshtein_worked { - err.span_label(base_span, &fallback_label); + err.span_label(base_span, fallback_label); } err }; @@ -3374,9 +3374,9 @@ impl<'a> Resolver<'a> { }, }; - err.span_label(span, &format!("`{}` already {}", name, participle)); + err.span_label(span, format!("`{}` already {}", name, participle)); if old_binding.span != syntax_pos::DUMMY_SP { - err.span_label(old_binding.span, &format!("previous {} of `{}` here", noun, name)); + err.span_label(old_binding.span, format!("previous {} of `{}` here", noun, name)); } err.emit(); self.name_already_seen.insert(name, span); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 030e3936de9..106f421f39e 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -630,7 +630,7 @@ impl<'a> Resolver<'a> { err.help(&format!("did you mean `{}`?", suggestion)); } } else { - err.help(&format!("have you added the `#[macro_use]` on the module/import?")); + err.help("have you added the `#[macro_use]` on the module/import?"); } } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 43654c8ce6f..804e1ea740f 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -539,7 +539,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { Ok(binding) if !binding.is_importable() => { let msg = format!("`{}` is not directly importable", target); struct_span_err!(this.session, directive.span, E0253, "{}", &msg) - .span_label(directive.span, &format!("cannot be imported directly")) + .span_label(directive.span, "cannot be imported directly") .emit(); // Do not import this illegal binding. Import a dummy binding and pretend // everything is fine @@ -701,7 +701,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } else if ns == TypeNS { struct_span_err!(self.session, directive.span, E0365, "`{}` is private, and cannot be reexported", ident) - .span_label(directive.span, &format!("reexport of private `{}`", ident)) + .span_label(directive.span, format!("reexport of private `{}`", ident)) .note(&format!("consider declaring type or module `{}` with `pub`", ident)) .emit(); } else { @@ -794,7 +794,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let msg = format!("a macro named `{}` has already been exported", ident); self.session.struct_span_err(span, &msg) - .span_label(span, &format!("`{}` already exported", ident)) + .span_label(span, format!("`{}` already exported", ident)) .span_note(binding.span, "previous macro export here") .emit(); } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 33b0aa3dbff..adcb3d682ca 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -163,7 +163,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { hir::ParenthesizedParameters(..) => { struct_span_err!(tcx.sess, span, E0214, "parenthesized parameters may only be used with a trait") - .span_label(span, &format!("only traits may use parentheses")) + .span_label(span, "only traits may use parentheses") .emit(); return Substs::for_item(tcx, def_id, |_, _| { @@ -294,7 +294,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { struct_span_err!(tcx.sess, span, E0393, "the type parameter `{}` must be explicitly specified", def.name) - .span_label(span, &format!("missing reference to `{}`", def.name)) + .span_label(span, format!("missing reference to `{}`", def.name)) .note(&format!("because of the default `Self` reference, \ type parameters must be specified on object types")) .emit(); @@ -635,7 +635,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let span = b.trait_ref.path.span; struct_span_err!(self.tcx().sess, span, E0225, "only Send/Sync traits can be used as additional traits in a trait object") - .span_label(span, &format!("non-Send/Sync additional trait")) + .span_label(span, "non-Send/Sync additional trait") .emit(); } @@ -684,7 +684,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { "the value of the associated type `{}` (from the trait `{}`) must be specified", name, tcx.item_path_str(trait_def_id)) - .span_label(span, &format!( + .span_label(span, format!( "missing associated type `{}` value", name)) .emit(); } @@ -730,7 +730,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { trait_str: &str, name: &str) { struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type") - .span_label(span, &format!("ambiguous associated type")) + .span_label(span, "ambiguous associated type") .note(&format!("specify the type using the syntax `<{} as {}>::{}`", type_str, trait_str, name)) .emit(); @@ -784,7 +784,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { "associated type `{}` not found for `{}`", assoc_name, ty_param_name) - .span_label(span, &format!("associated type `{}` not found", assoc_name)) + .span_label(span, format!("associated type `{}` not found", assoc_name)) .emit(); return Err(ErrorReported); } @@ -797,7 +797,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { "ambiguous associated type `{}` in bounds of `{}`", assoc_name, ty_param_name); - err.span_label(span, &format!("ambiguous associated type `{}`", assoc_name)); + err.span_label(span, format!("ambiguous associated type `{}`", assoc_name)); for bound in bounds { let bound_span = self.tcx().associated_items(bound.def_id()).find(|item| { @@ -806,7 +806,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { .and_then(|item| self.tcx().hir.span_if_local(item.def_id)); if let Some(span) = bound_span { - err.span_label(span, &format!("ambiguous `{}` from `{}`", + err.span_label(span, format!("ambiguous `{}` from `{}`", assoc_name, bound)); } else { @@ -951,7 +951,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { for typ in segment.parameters.types() { struct_span_err!(self.tcx().sess, typ.span, E0109, "type parameters are not allowed on this type") - .span_label(typ.span, &format!("type parameter not allowed")) + .span_label(typ.span, "type parameter not allowed") .emit(); break; } @@ -959,7 +959,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { struct_span_err!(self.tcx().sess, lifetime.span, E0110, "lifetime parameters are not allowed on this type") .span_label(lifetime.span, - &format!("lifetime parameter not allowed on this type")) + "lifetime parameter not allowed on this type") .emit(); break; } @@ -973,7 +973,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { pub fn prohibit_projection(&self, span: Span) { let mut err = struct_span_err!(self.tcx().sess, span, E0229, "associated type bindings are not allowed here"); - err.span_label(span, &format!("associate type not allowed here")).emit(); + err.span_label(span, "associate type not allowed here").emit(); } // Check a type Path and convert it to a Ty. @@ -1214,7 +1214,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { hir::TyTypeof(ref _e) => { struct_span_err!(tcx.sess, ast_ty.span, E0516, "`typeof` is a reserved keyword but unimplemented") - .span_label(ast_ty.span, &format!("reserved keyword")) + .span_label(ast_ty.span, "reserved keyword") .emit(); tcx.types.err @@ -1426,7 +1426,7 @@ fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize, "wrong number of type arguments: {} {}, found {}", expected, required, supplied) .span_label(span, - &format!("{} {} type argument{}", + format!("{} {} type argument{}", expected, required, arguments_plural)) @@ -1444,7 +1444,7 @@ fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize, expected, supplied) .span_label( span, - &format!("{} type argument{}", + format!("{} type argument{}", if accepted == 0 { "expected no" } else { &expected }, arguments_plural) ) @@ -1470,7 +1470,7 @@ fn report_lifetime_number_error(tcx: TyCtxt, span: Span, number: usize, expected struct_span_err!(tcx.sess, span, E0107, "wrong number of lifetime parameters: expected {}, found {}", expected, number) - .span_label(span, &label) + .span_label(span, label) .emit(); } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index ac10dfd36e2..bbe34f37950 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -97,7 +97,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { struct_span_err!(tcx.sess, span, E0029, "only char and numeric types are allowed in range patterns") - .span_label(span, &format!("ranges require char or numeric types")) + .span_label(span, "ranges require char or numeric types") .note(&format!("start type: {}", self.ty_to_string(lhs_ty))) .note(&format!("end type: {}", self.ty_to_string(rhs_ty))) .emit(); @@ -263,7 +263,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.sess, pat.span, E0527, "pattern requires {} elements but array has {}", min_len, size) - .span_label(pat.span, &format!("expected {} elements",size)) + .span_label(pat.span, format!("expected {} elements",size)) .emit(); } (inner_ty, tcx.types.err) @@ -274,7 +274,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "pattern requires at least {} elements but array has {}", min_len, size) .span_label(pat.span, - &format!("pattern cannot match array of {} elements", size)) + format!("pattern cannot match array of {} elements", size)) .emit(); (inner_ty, tcx.types.err) } @@ -297,7 +297,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } err.span_label( pat.span, - &format!("pattern cannot match with input type `{}`", expected_ty) + format!("pattern cannot match with input type `{}`", expected_ty) ).emit(); } (tcx.types.err, tcx.types.err) @@ -379,7 +379,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let type_str = self.ty_to_string(expected); struct_span_err!(self.tcx.sess, span, E0033, "type `{}` cannot be dereferenced", type_str) - .span_label(span, &format!("type `{}` cannot be dereferenced", type_str)) + .span_label(span, format!("type `{}` cannot be dereferenced", type_str)) .emit(); return false } @@ -593,7 +593,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { def.kind_name(), hir::print::to_string(&tcx.hir, |s| s.print_qpath(qpath, false))); struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg) - .span_label(pat.span, &format!("not a tuple variant or struct")).emit(); + .span_label(pat.span, "not a tuple variant or struct").emit(); on_error(); }; @@ -642,7 +642,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "this pattern has {} field{}, but the corresponding {} has {} field{}", subpats.len(), subpats_ending, def.kind_name(), variant.fields.len(), fields_ending) - .span_label(pat.span, &format!("expected {} field{}, found {}", + .span_label(pat.span, format!("expected {} field{}, found {}", variant.fields.len(), fields_ending, subpats.len())) .emit(); on_error(); @@ -683,8 +683,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { in the pattern", field.name) .span_label(span, - &format!("multiple uses of `{}` in pattern", field.name)) - .span_label(*occupied.get(), &format!("first use of `{}`", field.name)) + format!("multiple uses of `{}` in pattern", field.name)) + .span_label(*occupied.get(), format!("first use of `{}`", field.name)) .emit(); tcx.types.err } @@ -703,7 +703,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.item_path_str(variant.did), field.name) .span_label(span, - &format!("{} `{}` does not have field `{}`", + format!("{} `{}` does not have field `{}`", kind_name, tcx.item_path_str(variant.did), field.name)) @@ -732,7 +732,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { struct_span_err!(tcx.sess, span, E0027, "pattern does not mention field `{}`", field.name) - .span_label(span, &format!("missing field `{}`", field.name)) + .span_label(span, format!("missing field `{}`", field.name)) .emit(); } } diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index c9584f1d9e1..f03451c04ed 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -62,7 +62,7 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> { E0055, "reached the recursion limit while auto-dereferencing {:?}", self.cur_ty) - .span_label(self.span, &format!("deref recursion limit reached")) + .span_label(self.span, "deref recursion limit reached") .help(&format!( "consider adding a `#[recursion_limit=\"{}\"]` attribute to your crate", suggested_limit)) diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 7a49309e005..dde5f598a68 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -27,7 +27,7 @@ use rustc::hir; pub fn check_legal_trait_for_method_call(tcx: TyCtxt, span: Span, trait_id: DefId) { if tcx.lang_items.drop_trait() == Some(trait_id) { struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method") - .span_label(span, &format!("explicit destructor calls not allowed")) + .span_label(span, "explicit destructor calls not allowed") .emit(); } } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 32b363ed755..72ce7d3b5ed 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -155,7 +155,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { }, self.expr_ty); err.span_label(error_span, - &format!("cannot cast `{}` as `{}`", + format!("cannot cast `{}` as `{}`", fcx.ty_to_string(self.expr_ty), cast_ty)); if let Ok(snippet) = fcx.sess().codemap().span_to_snippet(self.expr.span) { @@ -200,7 +200,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } CastError::CastToBool => { struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`") - .span_label(self.span, &format!("unsupported cast")) + .span_label(self.span, "unsupported cast") .help("compare with zero instead") .emit(); } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index b0b57aee5b2..c228fc6b24a 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1144,7 +1144,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> db = struct_span_err!( fcx.tcx.sess, cause.span, E0069, "`return;` in a function whose return type is not `()`"); - db.span_label(cause.span, &format!("return type is not ()")); + db.span_label(cause.span, "return type is not ()"); } _ => { db = fcx.report_mismatched_types(cause, expected, found, err); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 9ed5528e867..0579bb15fd6 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -402,7 +402,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "lifetime parameters or bounds on method `{}` do not match the \ trait declaration", impl_m.name) - .span_label(span, &format!("lifetimes do not match trait")) + .span_label(span, "lifetimes do not match trait") .emit(); return Err(ErrorReported); } @@ -534,9 +534,9 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, not in the trait", trait_m.name, self_descr); - err.span_label(impl_m_span, &format!("`{}` used in impl", self_descr)); + err.span_label(impl_m_span, format!("`{}` used in impl", self_descr)); if let Some(span) = tcx.hir.span_if_local(trait_m.def_id) { - err.span_label(span, &format!("trait declared without `{}`", self_descr)); + err.span_label(span, format!("trait declared without `{}`", self_descr)); } err.emit(); return Err(ErrorReported); @@ -552,9 +552,9 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_m.name, self_descr); err.span_label(impl_m_span, - &format!("expected `{}` in impl", self_descr)); + format!("expected `{}` in impl", self_descr)); if let Some(span) = tcx.hir.span_if_local(trait_m.def_id) { - err.span_label(span, &format!("`{}` used in trait", self_descr)); + err.span_label(span, format!("`{}` used in trait", self_descr)); } err.emit(); return Err(ErrorReported); @@ -606,7 +606,7 @@ fn compare_number_of_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let Some(span) = trait_item_span { err.span_label(span, - &format!("expected {}", + format!("expected {}", &if num_trait_m_type_params != 1 { format!("{} type parameters", num_trait_m_type_params) } else { @@ -617,7 +617,7 @@ fn compare_number_of_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } err.span_label(span, - &format!("found {}{}", + format!("found {}{}", &if num_impl_m_type_params != 1 { format!("{} type parameters", num_impl_m_type_params) } else { @@ -696,7 +696,7 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_number_args); if let Some(trait_span) = trait_span { err.span_label(trait_span, - &format!("trait requires {}", + format!("trait requires {}", &if trait_number_args != 1 { format!("{} parameters", trait_number_args) } else { @@ -704,7 +704,7 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, })); } err.span_label(impl_span, - &format!("expected {}, found {}", + format!("expected {}, found {}", &if trait_number_args != 1 { format!("{} parameters", trait_number_args) } else { diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 2a97bc1d98f..60067e6a6ec 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -57,7 +57,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "intrinsic has wrong number of type \ parameters: found {}, expected {}", i_n_tps, n_tps) - .span_label(span, &format!("expected {} type parameter", n_tps)) + .span_label(span, format!("expected {} type parameter", n_tps)) .emit(); } else { require_same_types(tcx, @@ -101,7 +101,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, op => { struct_span_err!(tcx.sess, it.span, E0092, "unrecognized atomic operation function: `{}`", op) - .span_label(it.span, &format!("unrecognized atomic operation")) + .span_label(it.span, "unrecognized atomic operation") .emit(); return; } @@ -305,7 +305,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct_span_err!(tcx.sess, it.span, E0093, "unrecognized intrinsic function: `{}`", *other) - .span_label(it.span, &format!("unrecognized intrinsic")) + .span_label(it.span, "unrecognized intrinsic") .emit(); return; } @@ -505,7 +505,7 @@ fn match_intrinsic_type_to_type<'a, 'tcx>( } } _ => simple_error(&format!("`{}`", t), - &format!("tuple")), + "tuple"), } } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index aad14bc975d..fdde4e9fef4 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -285,7 +285,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { self.span, E0035, "does not take type parameters") - .span_label(self.span, &"called with unneeded type parameters") + .span_label(self.span, "called with unneeded type parameters") .emit(); } else { struct_span_err!(self.tcx.sess, @@ -296,7 +296,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { num_method_types, num_supplied_types) .span_label(self.span, - &format!("Passed {} type argument{}, expected {}", + format!("Passed {} type argument{}, expected {}", num_supplied_types, if num_supplied_types != 1 { "s" } else { "" }, num_method_types)) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 4b975d7b324..c7ec379b0de 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -209,9 +209,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expr_string, item_name)); } - err.span_label(span, &"field, not a method"); + err.span_label(span, "field, not a method"); } else { - err.span_label(span, &"private field, not a method"); + err.span_label(span, "private field, not a method"); } break; } @@ -272,7 +272,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span, E0034, "multiple applicable items in scope"); - err.span_label(span, &format!("multiple `{}` found", item_name)); + err.span_label(span, format!("multiple `{}` found", item_name)); report_candidates(&mut err, sources); err.emit(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2e29aeeb022..127ffc60cf4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1130,7 +1130,7 @@ fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct_span_err!( tcx.sess, attr.span, E0232, "this attribute must have a value") - .span_label(attr.span, &format!("attribute requires a value")) + .span_label(attr.span, "attribute requires a value") .note(&format!("eg `#[rustc_on_unimplemented = \"foo\"]`")) .emit(); } @@ -1146,12 +1146,12 @@ fn report_forbidden_specialization<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "`{}` specializes an item from a parent `impl`, but \ that item is not marked `default`", impl_item.name); - err.span_label(impl_item.span, &format!("cannot specialize default item `{}`", + err.span_label(impl_item.span, format!("cannot specialize default item `{}`", impl_item.name)); match tcx.span_of_impl(parent_impl) { Ok(span) => { - err.span_label(span, &"parent `impl` is here"); + err.span_label(span, "parent `impl` is here"); err.note(&format!("to specialize, `{}` in the parent `impl` must be marked `default`", impl_item.name)); } @@ -1226,11 +1226,11 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, which doesn't match its trait `{}`", ty_impl_item.name, impl_trait_ref); - err.span_label(impl_item.span, &format!("does not match trait")); + err.span_label(impl_item.span, "does not match trait"); // We can only get the spans from local trait definition // Same for E0324 and E0325 if let Some(trait_span) = tcx.hir.span_if_local(ty_trait_item.def_id) { - err.span_label(trait_span, &format!("item in trait")); + err.span_label(trait_span, "item in trait"); } err.emit() } @@ -1262,9 +1262,9 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, which doesn't match its trait `{}`", ty_impl_item.name, impl_trait_ref); - err.span_label(impl_item.span, &format!("does not match trait")); + err.span_label(impl_item.span, "does not match trait"); if let Some(trait_span) = tcx.hir.span_if_local(ty_trait_item.def_id) { - err.span_label(trait_span, &format!("item in trait")); + err.span_label(trait_span, "item in trait"); } err.emit() } @@ -1280,9 +1280,9 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, which doesn't match its trait `{}`", ty_impl_item.name, impl_trait_ref); - err.span_label(impl_item.span, &format!("does not match trait")); + err.span_label(impl_item.span, "does not match trait"); if let Some(trait_span) = tcx.hir.span_if_local(ty_trait_item.def_id) { - err.span_label(trait_span, &format!("item in trait")); + err.span_label(trait_span, "item in trait"); } err.emit() } @@ -1331,13 +1331,13 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, missing_items.iter() .map(|trait_item| trait_item.name.to_string()) .collect::>().join("`, `")); - err.span_label(impl_span, &format!("missing `{}` in implementation", + err.span_label(impl_span, format!("missing `{}` in implementation", missing_items.iter() .map(|trait_item| trait_item.name.to_string()) .collect::>().join("`, `"))); for trait_item in missing_items { if let Some(span) = tcx.hir.span_if_local(trait_item.def_id) { - err.span_label(span, &format!("`{}` from trait", trait_item.name)); + err.span_label(span, format!("`{}` from trait", trait_item.name)); } else { err.note(&format!("`{}` from trait: `{}`", trait_item.name, @@ -1377,7 +1377,7 @@ fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Representability::SelfRecursive(spans) => { let mut err = tcx.recursive_type_with_infinite_size_error(item_def_id); for span in spans { - err.span_label(span, &"recursive without indirection"); + err.span_label(span, "recursive without indirection"); } err.emit(); return false @@ -1399,7 +1399,7 @@ pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId let e = fields[0].ty(tcx, substs); if !fields.iter().all(|f| f.ty(tcx, substs) == e) { struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous") - .span_label(sp, &format!("SIMD elements must have the same type")) + .span_label(sp, "SIMD elements must have the same type") .emit(); return; } @@ -1471,7 +1471,7 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct_span_err!( tcx.sess, sp, E0084, "unsupported representation for zero-variant enum") - .span_label(sp, &format!("unsupported enum representation")) + .span_label(sp, "unsupported enum representation") .emit(); } @@ -1505,8 +1505,8 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; struct_span_err!(tcx.sess, span, E0081, "discriminant value `{}` already exists", disr_vals[i]) - .span_label(i_span, &format!("first use of `{}`", disr_vals[i])) - .span_label(span , &format!("enum already has `{}`", disr_vals[i])) + .span_label(i_span, format!("first use of `{}`", disr_vals[i])) + .span_label(span , format!("enum already has `{}`", disr_vals[i])) .emit(); } disr_vals.push(discr); @@ -2401,12 +2401,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if arg_count == 1 {" was"} else {"s were"}), error_code); - err.span_label(sp, &format!("expected {}{} parameter{}", + err.span_label(sp, format!("expected {}{} parameter{}", if variadic {"at least "} else {""}, expected_count, if expected_count == 1 {""} else {"s"})); if let Some(def_s) = def_span { - err.span_label(def_s, &format!("defined here")); + err.span_label(def_s, "defined here"); } err.emit(); } @@ -2938,10 +2938,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(suggested_field_name) = Self::suggest_field_name(def.struct_variant(), field, vec![]) { err.span_label(field.span, - &format!("did you mean `{}`?", suggested_field_name)); + format!("did you mean `{}`?", suggested_field_name)); } else { err.span_label(field.span, - &format!("unknown field")); + "unknown field"); }; } ty::TyRawPtr(..) => { @@ -3076,15 +3076,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { &field.name, skip_fields.collect()) { err.span_label(field.name.span, - &format!("field does not exist - did you mean `{}`?", field_name)); + format!("field does not exist - did you mean `{}`?", field_name)); } else { match ty.sty { ty::TyAdt(adt, ..) if adt.is_enum() => { - err.span_label(field.name.span, &format!("`{}::{}` does not have this field", + err.span_label(field.name.span, format!("`{}::{}` does not have this field", ty, variant.name)); } _ => { - err.span_label(field.name.span, &format!("`{}` does not have this field", ty)); + err.span_label(field.name.span, format!("`{}` does not have this field", ty)); } } }; @@ -3149,10 +3149,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "field `{}` specified more than once", field.name.node); - err.span_label(field.name.span, &format!("used more than once")); + err.span_label(field.name.span, "used more than once"); if let Some(prev_span) = seen_fields.get(&field.name.node) { - err.span_label(*prev_span, &format!("first use of `{}`", field.name.node)); + err.span_label(*prev_span, format!("first use of `{}`", field.name.node)); } err.emit(); @@ -3199,7 +3199,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { remaining_fields_names, truncated_fields_error, adt_ty) - .span_label(span, &format!("missing {}{}", + .span_label(span, format!("missing {}{}", remaining_fields_names, truncated_fields_error)) .emit(); @@ -3266,7 +3266,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { struct_span_err!(self.tcx.sess, path_span, E0071, "expected struct, variant or union type, found {}", ty.sort_string(self.tcx)) - .span_label(path_span, &format!("not a struct")) + .span_label(path_span, "not a struct") .emit(); None } @@ -3625,7 +3625,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "invalid left-hand side expression") .span_label( expr.span, - &format!("left-hand of expression not valid")) + "left-hand of expression not valid") .emit(); } @@ -4517,7 +4517,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "too many lifetime parameters provided: \ expected at most {}, found {}", expected_text, actual_text) - .span_label(span, &format!("expected {}", expected_text)) + .span_label(span, format!("expected {}", expected_text)) .emit(); } else if lifetimes.len() > 0 && lifetimes.len() < lifetime_defs.len() { let expected_text = count_lifetime_params(lifetime_defs.len()); @@ -4526,7 +4526,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "too few lifetime parameters provided: \ expected {}, found {}", expected_text, actual_text) - .span_label(span, &format!("expected {}", expected_text)) + .span_label(span, format!("expected {}", expected_text)) .emit(); } @@ -4551,7 +4551,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "too many type parameters provided: \ expected at most {}, found {}", expected_text, actual_text) - .span_label(span, &format!("expected {}", expected_text)) + .span_label(span, format!("expected {}", expected_text)) .emit(); // To prevent derived errors to accumulate due to extra @@ -4565,7 +4565,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "too few type parameters provided: \ expected {}, found {}", expected_text, actual_text) - .span_label(span, &format!("expected {}", expected_text)) + .span_label(span, format!("expected {}", expected_text)) .emit(); } @@ -4654,7 +4654,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct_span_err!(tcx.sess, param.span, E0091, "type parameter `{}` is unused", param.name) - .span_label(param.span, &format!("unused type parameter")) + .span_label(param.span, "unused type parameter") .emit(); } } diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index d3d65ce4a62..59cb61d9b97 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -50,7 +50,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { E0067, "invalid left-hand side expression") .span_label( lhs_expr.span, - &format!("invalid expression for left-hand side")) + "invalid expression for left-hand side") .emit(); } ty @@ -203,7 +203,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { op.node.as_str(), lhs_ty) .span_label(lhs_expr.span, - &format!("cannot use `{}=` on type `{}`", + format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty)) .emit(); } else { @@ -278,7 +278,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let TyRef(_, r_ty) = rhs_ty.sty { if l_ty.ty.sty == TyStr && r_ty.ty.sty == TyStr { err.span_label(expr.span, - &"`+` can't be used to concatenate two `&str` strings"); + "`+` can't be used to concatenate two `&str` strings"); let codemap = self.tcx.sess.codemap(); let suggestion = match codemap.span_to_snippet(lhs_expr.span) { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 1887eaef360..93529aecac0 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -684,7 +684,7 @@ fn error_392<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast: -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!(tcx.sess, span, E0392, "parameter `{}` is never used", param_name); - err.span_label(span, &format!("unused type parameter")); + err.span_label(span, "unused type parameter"); err } @@ -692,7 +692,7 @@ fn error_194(tcx: TyCtxt, span: Span, trait_decl_span: Span, name: ast::Name) { struct_span_err!(tcx.sess, span, E0194, "type parameter `{}` shadows another type parameter of the same name", name) - .span_label(span, &format!("shadows another type parameter")) - .span_label(trait_decl_span, &format!("first `{}` declared here", name)) + .span_label(span, "shadows another type parameter") + .span_label(trait_decl_span, format!("first `{}` declared here", name)) .emit(); } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 49785d8850f..743bfbb44ab 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -74,7 +74,7 @@ fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, E0120, "the Drop trait may only be implemented on \ structures") - .span_label(span, &format!("implementing Drop requires a struct")) + .span_label(span, "implementing Drop requires a struct") .emit(); } _ => { @@ -130,7 +130,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "the trait `Copy` may not be implemented for this type") .span_label( tcx.def_span(field.did), - &"this field does not implement `Copy`") + "this field does not implement `Copy`") .emit() } Err(CopyImplementationError::NotAnAdt) => { @@ -145,7 +145,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span, E0206, "the trait `Copy` may not be implemented for this type") - .span_label(span, &format!("type is not a structure or enumeration")) + .span_label(span, "type is not a structure or enumeration") .emit(); } Err(CopyImplementationError::HasDestructor) => { @@ -154,7 +154,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, E0184, "the trait `Copy` may not be implemented for this type; the \ type has a destructor") - .span_label(span, &format!("Copy not allowed on types with destructors")) + .span_label(span, "Copy not allowed on types with destructors") .emit(); } } @@ -310,7 +310,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) .collect::>() .join(", "))); - err.span_label(span, &format!("requires multiple coercions")); + err.span_label(span, "requires multiple coercions"); err.emit(); return err_info; } diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index 238952865c7..f7ebc210442 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -259,7 +259,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty.span, E0118, "no base type found for inherent implementation") - .span_label(ty.span, &format!("impl requires a base type")) + .span_label(ty.span, "impl requires a base type") .note(&format!("either implement a trait on it or create a newtype \ to wrap it instead")) .emit(); @@ -296,7 +296,7 @@ impl<'a, 'tcx> InherentCollect<'a, 'tcx> { "cannot define inherent `impl` for a type outside of the crate \ where the type is defined") .span_label(item.span, - &format!("impl for type defined outside of crate.")) + "impl for type defined outside of crate.") .note("define and implement a trait or new type instead") .emit(); } diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index 34aec8ef1ac..2751e1ff38a 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -56,9 +56,9 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { "duplicate definitions with name `{}`", name) .span_label(self.tcx.span_of_impl(item1).unwrap(), - &format!("duplicate definitions for `{}`", name)) + format!("duplicate definitions for `{}`", name)) .span_label(self.tcx.span_of_impl(item2).unwrap(), - &format!("other definition for `{}`", name)) + format!("other definition for `{}`", name)) .emit(); } } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 56ae9d54575..8b9dc20315d 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -62,7 +62,7 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_d span, E0322, "explicit impls for the `Sized` trait are not permitted") - .span_label(span, &format!("impl of 'Sized' not allowed")) + .span_label(span, "impl of 'Sized' not allowed") .emit(); return; } diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 8ded3003c78..097720adad4 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -48,7 +48,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { E0117, "only traits defined in the current crate can be \ implemented for arbitrary types") - .span_label(item.span, &format!("impl doesn't use types inside crate")) + .span_label(item.span, "impl doesn't use types inside crate") .note(&format!("the impl does not reference any types defined in \ this crate")) .note("define and implement a trait or new type instead") @@ -153,7 +153,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { "cannot create default implementations for traits outside \ the crate they're defined in; define a new trait instead") .span_label(item_trait_ref.path.span, - &format!("`{}` trait not defined in this crate", + format!("`{}` trait not defined in this crate", self.tcx.hir.node_to_pretty_string(item_trait_ref.ref_id))) .emit(); return; diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 383a9e0e695..f479dc2e6ab 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -60,9 +60,9 @@ pub fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { match tcx.span_of_impl(overlap.with_impl) { Ok(span) => { - err.span_label(span, &format!("first implementation here")); + err.span_label(span, "first implementation here"); err.span_label(tcx.span_of_impl(impl_def_id).unwrap(), - &format!("conflicting implementation{}", + format!("conflicting implementation{}", overlap.self_desc .map_or(String::new(), |ty| format!(" for `{}`", ty)))); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index f44f74830cb..ec200241ee6 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -220,7 +220,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { span, E0121, "the type placeholder `_` is not allowed within types on item signatures" - ).span_label(span, &format!("not allowed in type signatures")) + ).span_label(span, "not allowed in type signatures") .emit(); self.tcx().types.err } @@ -568,7 +568,7 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } else { struct_span_err!(tcx.sess, variant.span, E0370, "enum discriminant overflowed") - .span_label(variant.span, &format!("overflowed on value after {}", + .span_label(variant.span, format!("overflowed on value after {}", prev_discr.unwrap())) .note(&format!("explicitly set `{} = {}` if that is desired outcome", variant.node.name, wrapped_discr)) @@ -604,8 +604,8 @@ fn convert_struct_variant<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct_span_err!(tcx.sess, f.span, E0124, "field `{}` is already declared", f.name) - .span_label(f.span, &"field already declared") - .span_label(prev_span, &format!("`{}` first declared here", f.name)) + .span_label(f.span, "field already declared") + .span_label(prev_span, format!("`{}` first declared here", f.name)) .emit(); } else { seen_fields.insert(f.name, f.span); diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 1c44572fbb4..6b4f08d3d4c 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -166,7 +166,7 @@ fn report_unused_parameter(tcx: TyCtxt, "the {} parameter `{}` is not constrained by the \ impl trait, self type, or predicates", kind, name) - .span_label(span, &format!("unconstrained {} parameter", kind)) + .span_label(span, format!("unconstrained {} parameter", kind)) .emit(); } @@ -188,9 +188,9 @@ fn enforce_impl_items_are_distinct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "duplicate definitions with name `{}`:", impl_item.name); err.span_label(*entry.get(), - &format!("previous definition of `{}` here", + format!("previous definition of `{}` here", impl_item.name)); - err.span_label(impl_item.span, &format!("duplicate definition")); + err.span_label(impl_item.span, "duplicate definition"); err.emit(); } Vacant(entry) => { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index c1456e79782..84de4ff2b7b 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -143,7 +143,7 @@ fn require_c_abi_if_variadic(tcx: TyCtxt, if decl.variadic && abi != Abi::C { let mut err = struct_span_err!(tcx.sess, span, E0045, "variadic function must have C calling convention"); - err.span_label(span, &("variadics require C calling conventions").to_string()) + err.span_label(span, "variadics require C calling conventions") .emit(); } } @@ -190,7 +190,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct_span_err!(tcx.sess, generics.span, E0131, "main function is not allowed to have type parameters") .span_label(generics.span, - &format!("main cannot have type parameters")) + "main cannot have type parameters") .emit(); return; } @@ -240,7 +240,7 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct_span_err!(tcx.sess, ps.span, E0132, "start function is not allowed to have type parameters") .span_label(ps.span, - &format!("start function cannot have type parameters")) + "start function cannot have type parameters") .emit(); return; } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 0f47265a1aa..5db82e23bbf 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -687,9 +687,9 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool, } } clean::Vector(ref t) if is_not_debug => { - primitive_link(f, PrimitiveType::Slice, &format!("["))?; + primitive_link(f, PrimitiveType::Slice, "[")?; fmt::Display::fmt(t, f)?; - primitive_link(f, PrimitiveType::Slice, &format!("]")) + primitive_link(f, PrimitiveType::Slice, "]") } clean::Vector(ref t) => write!(f, "[{:?}]", t), clean::FixedVector(ref t, ref s) if is_not_debug => { diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 6b1267d89b6..528d903b8b0 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -2412,7 +2412,7 @@ mod tests { let tmpdir = tmpdir(); let unicode = tmpdir.path(); - let unicode = unicode.join(&format!("test-각丁ー再见")); + let unicode = unicode.join("test-각丁ー再见"); check!(fs::create_dir(&unicode)); assert!(unicode.exists()); assert!(!Path::new("test/unicode-bogus-path-각丁ー再见").exists()); diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 82492d97627..0980b73e80c 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -511,8 +511,7 @@ pub fn find_export_name_attr(diag: &Handler, attrs: &[Attribute]) -> Option Parser<'a> { label_sp }; if self.span.contains(sp) { - err.span_label(self.span, &label_exp); + err.span_label(self.span, label_exp); } else { - err.span_label(sp, &label_exp); - err.span_label(self.span, &"unexpected token"); + err.span_label(sp, label_exp); + err.span_label(self.span, "unexpected token"); } Err(err) } @@ -1512,10 +1512,10 @@ impl<'a> Parser<'a> { err.span_suggestion(sum_span, "try adding parentheses:", sum_with_parens); } TyKind::Ptr(..) | TyKind::BareFn(..) => { - err.span_label(sum_span, &"perhaps you forgot parentheses?"); + err.span_label(sum_span, "perhaps you forgot parentheses?"); } _ => { - err.span_label(sum_span, &"expected a path"); + err.span_label(sum_span, "expected a path"); }, } err.emit(); @@ -2556,7 +2556,7 @@ impl<'a> Parser<'a> { let fstr = n.as_str(); let mut err = self.diagnostic().struct_span_err(self.prev_span, &format!("unexpected token: `{}`", n)); - err.span_label(self.prev_span, &"unexpected token"); + err.span_label(self.prev_span, "unexpected token"); if fstr.chars().all(|x| "0123456789.".contains(x)) { let float = match fstr.parse::().ok() { Some(f) => f, @@ -2708,7 +2708,7 @@ impl<'a> Parser<'a> { let span_of_tilde = lo; let mut err = self.diagnostic().struct_span_err(span_of_tilde, "`~` can not be used as a unary operator"); - err.span_label(span_of_tilde, &"did you mean `!`?"); + err.span_label(span_of_tilde, "did you mean `!`?"); err.help("use `!` instead of `~` if you meant to perform bitwise negation"); err.emit(); (span, self.mk_unary(UnOp::Not, e)) @@ -4792,7 +4792,7 @@ impl<'a> Parser<'a> { sp, &format!("missing `fn`, `type`, or `const` for {}-item declaration", item_type)); - err.span_label(sp, &"missing `fn`, `type`, or `const`"); + err.span_label(sp, "missing `fn`, `type`, or `const`"); err } -- cgit 1.4.1-3-g733a5 From 0e8e45c74068b72301f9045f0efc38ba8b51e0a4 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Mon, 8 May 2017 22:29:24 +0900 Subject: Allow bare CR in ////-style comment. --- src/libsyntax/parse/lexer/mod.rs | 2 +- .../lex-bare-cr-string-literal-doc-comment.rs | 6 ++++++ src/test/run-pass/lex-bare-cr-nondoc-comment.rs | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/lex-bare-cr-nondoc-comment.rs (limited to 'src/libsyntax') diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 7d2a1b3c4a4..ded1f0b599a 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -504,7 +504,7 @@ impl<'a> StringReader<'a> { self.bump(); // line comments starting with "///" or "//!" are doc-comments - let doc_comment = self.ch_is('/') || self.ch_is('!'); + let doc_comment = (self.ch_is('/') && !self.nextch_is('/')) || self.ch_is('!'); let start_bpos = self.pos - BytePos(2); while !self.is_eof() { diff --git a/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs b/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs index f8943057543..ac085d47511 100644 --- a/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs +++ b/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs @@ -21,6 +21,12 @@ pub fn bar() {} //~^^ ERROR: bare CR not allowed in block doc-comment fn main() { + //! doc comment with bare CR: ' ' + //~^ ERROR: bare CR not allowed in doc-comment + + /*! block doc comment with bare CR: ' ' */ + //~^ ERROR: bare CR not allowed in block doc-comment + // the following string literal has a bare CR in it let _s = "foo bar"; //~ ERROR: bare CR not allowed in string diff --git a/src/test/run-pass/lex-bare-cr-nondoc-comment.rs b/src/test/run-pass/lex-bare-cr-nondoc-comment.rs new file mode 100644 index 00000000000..ba949ca8881 --- /dev/null +++ b/src/test/run-pass/lex-bare-cr-nondoc-comment.rs @@ -0,0 +1,18 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-cr + +// nondoc comment with bare CR: ' ' +//// nondoc comment with bare CR: ' ' +/* block nondoc comment with bare CR: ' ' */ + +fn main() { +} -- cgit 1.4.1-3-g733a5