From 1add949ef0e424e3b144e33d55938c873ac5050e Mon Sep 17 00:00:00 2001 From: Paul Emmerich Date: Thu, 11 Jul 2019 22:23:00 +0200 Subject: [PATCH 001/618] libtest: add --show-output option this new flag enables printing the captured stdout of successful tests utilizing the already existing display_output test runner option --- src/librustdoc/markdown.rs | 2 +- src/librustdoc/test.rs | 2 +- src/libtest/lib.rs | 16 +++++++++++----- src/libtest/tests.rs | 11 +++++++++++ 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 50a647f244db5..21a7c39f72e92 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -154,6 +154,6 @@ pub fn test(mut options: Options, diag: &errors::Handler) -> i32 { options.test_args.insert(0, "rustdoctest".to_string()); testing::test_main(&options.test_args, collector.tests, - testing::Options::new().display_output(options.display_warnings)); + Some(testing::Options::new().display_output(options.display_warnings))); 0 } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 63545ab45bf64..562d98a4a4327 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -120,7 +120,7 @@ pub fn run(options: Options) -> i32 { testing::test_main( &test_args, tests, - testing::Options::new().display_output(display_warnings) + Some(testing::Options::new().display_output(display_warnings)) ); 0 diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 53bf67bdf671f..a1ce45dad4e9e 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -272,7 +272,7 @@ impl Options { // 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, options: Options) { +pub fn test_main(args: &[String], tests: Vec, options: Option) { let mut opts = match parse_opts(args) { Some(Ok(o)) => o, Some(Err(msg)) => { @@ -281,8 +281,9 @@ pub fn test_main(args: &[String], tests: Vec, options: Options) { } None => return, }; - - opts.options = options; + if let Some(options) = options { + opts.options = options; + } if opts.list { if let Err(e) = list_tests_console(&opts, tests) { eprintln!("error: io error when listing tests: {:?}", e); @@ -323,7 +324,7 @@ pub fn test_main_static(tests: &[&TestDescAndFn]) { _ => panic!("non-static tests passed to test::test_main_static"), }) .collect(); - test_main(&args, owned_tests, Options::new()) + test_main(&args, owned_tests, None) } /// Invoked when unit tests terminate. Should panic if the unit @@ -468,6 +469,11 @@ fn optgroups() -> getopts::Options { json = Output a json document", "pretty|terse|json", ) + .optflag( + "", + "show-output", + "Show captured stdout of successful tests" + ) .optopt( "Z", "", @@ -667,7 +673,7 @@ pub fn parse_opts(args: &[String]) -> Option { format, test_threads, skip: matches.opt_strs("skip"), - options: Options::new(), + options: Options::new().display_output(matches.opt_present("show-output")), }; Some(Ok(test_opts)) diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs index d8734d8caa03e..5956526e89403 100644 --- a/src/libtest/tests.rs +++ b/src/libtest/tests.rs @@ -160,6 +160,17 @@ fn parse_ignored_flag() { assert_eq!(opts.run_ignored, RunIgnored::Only); } +#[test] +fn parse_show_output_flag() { + let args = vec![ + "progname".to_string(), + "filter".to_string(), + "--show-output".to_string(), + ]; + let opts = parse_opts(&args).unwrap().unwrap(); + assert!(opts.options.display_output); +} + #[test] fn parse_include_ignored_flag() { let args = vec![ From 409a41dc24fe72e6d8bf3c2252efb13c94d921c5 Mon Sep 17 00:00:00 2001 From: Paul Emmerich Date: Fri, 12 Jul 2019 01:56:43 +0200 Subject: [PATCH 002/618] libtest: support display_output in JSON formatter --- src/libtest/formatters/json.rs | 71 +++++++++++-------- src/libtest/formatters/mod.rs | 1 + src/libtest/formatters/pretty.rs | 8 ++- src/libtest/formatters/terse.rs | 8 ++- src/libtest/lib.rs | 2 +- .../run-make-fulldeps/libtest-json/Makefile | 12 ++-- src/test/run-make-fulldeps/libtest-json/f.rs | 3 +- .../{output.json => output-default.json} | 2 +- .../libtest-json/output-stdout-success.json | 10 +++ 9 files changed, 77 insertions(+), 40 deletions(-) rename src/test/run-make-fulldeps/libtest-json/{output.json => output-default.json} (91%) create mode 100644 src/test/run-make-fulldeps/libtest-json/output-stdout-success.json diff --git a/src/libtest/formatters/json.rs b/src/libtest/formatters/json.rs index a06497f98626a..e0bea4ce54530 100644 --- a/src/libtest/formatters/json.rs +++ b/src/libtest/formatters/json.rs @@ -9,44 +9,57 @@ impl JsonFormatter { Self { out } } - fn write_message(&mut self, s: &str) -> io::Result<()> { + fn writeln_message(&mut self, s: &str) -> io::Result<()> { assert!(!s.contains('\n')); self.out.write_all(s.as_ref())?; self.out.write_all(b"\n") } + fn write_message(&mut self, s: &str) -> io::Result<()> { + assert!(!s.contains('\n')); + + self.out.write_all(s.as_ref()) + } + fn write_event( &mut self, ty: &str, name: &str, evt: &str, - extra: Option, + stdout: Option>, + extra: Option<&str>, ) -> io::Result<()> { - if let Some(extras) = extra { + self.write_message(&*format!( + r#"{{ "type": "{}", "name": "{}", "event": "{}""#, + ty, name, evt + ))?; + if let Some(stdout) = stdout { self.write_message(&*format!( - r#"{{ "type": "{}", "name": "{}", "event": "{}", {} }}"#, - ty, name, evt, extras - )) - } else { + r#", "stdout": "{}""#, + EscapedString(stdout) + ))?; + } + if let Some(extra) = extra { self.write_message(&*format!( - r#"{{ "type": "{}", "name": "{}", "event": "{}" }}"#, - ty, name, evt - )) + r#", {}"#, + extra + ))?; } + self.writeln_message(" }") } } impl OutputFormatter for JsonFormatter { fn write_run_start(&mut self, test_count: usize) -> io::Result<()> { - self.write_message(&*format!( + self.writeln_message(&*format!( r#"{{ "type": "suite", "event": "started", "test_count": {} }}"#, test_count )) } fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> { - self.write_message(&*format!( + self.writeln_message(&*format!( r#"{{ "type": "test", "event": "started", "name": "{}" }}"#, desc.name )) @@ -57,34 +70,30 @@ impl OutputFormatter for JsonFormatter { desc: &TestDesc, result: &TestResult, stdout: &[u8], + state: &ConsoleTestState, ) -> io::Result<()> { + let stdout = if (state.options.display_output || *result != TrOk) && stdout.len() > 0 { + Some(String::from_utf8_lossy(stdout)) + } else { + None + }; match *result { - TrOk => self.write_event("test", desc.name.as_slice(), "ok", None), - - TrFailed => { - let extra_data = if stdout.len() > 0 { - Some(format!( - r#""stdout": "{}""#, - EscapedString(String::from_utf8_lossy(stdout)) - )) - } else { - None - }; + TrOk => self.write_event("test", desc.name.as_slice(), "ok", stdout, None), - self.write_event("test", desc.name.as_slice(), "failed", extra_data) - } + TrFailed => self.write_event("test", desc.name.as_slice(), "failed", stdout, None), TrFailedMsg(ref m) => self.write_event( "test", desc.name.as_slice(), "failed", - Some(format!(r#""message": "{}""#, EscapedString(m))), + stdout, + Some(&*format!(r#""message": "{}""#, EscapedString(m))), ), - TrIgnored => self.write_event("test", desc.name.as_slice(), "ignored", None), + TrIgnored => self.write_event("test", desc.name.as_slice(), "ignored", stdout, None), TrAllowedFail => { - self.write_event("test", desc.name.as_slice(), "allowed_failure", None) + self.write_event("test", desc.name.as_slice(), "allowed_failure", stdout, None) } TrBench(ref bs) => { @@ -105,20 +114,20 @@ impl OutputFormatter for JsonFormatter { desc.name, median, deviation, mbps ); - self.write_message(&*line) + self.writeln_message(&*line) } } } fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> { - self.write_message(&*format!( + self.writeln_message(&*format!( r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#, desc.name )) } fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result { - self.write_message(&*format!( + self.writeln_message(&*format!( "{{ \"type\": \"suite\", \ \"event\": \"{}\", \ \"passed\": {}, \ diff --git a/src/libtest/formatters/mod.rs b/src/libtest/formatters/mod.rs index be5f6a65039b7..cc30b06e5ec38 100644 --- a/src/libtest/formatters/mod.rs +++ b/src/libtest/formatters/mod.rs @@ -17,6 +17,7 @@ pub(crate) trait OutputFormatter { desc: &TestDesc, result: &TestResult, stdout: &[u8], + state: &ConsoleTestState, ) -> io::Result<()>; fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result; } diff --git a/src/libtest/formatters/pretty.rs b/src/libtest/formatters/pretty.rs index 4af00428ca87e..88331406a64d0 100644 --- a/src/libtest/formatters/pretty.rs +++ b/src/libtest/formatters/pretty.rs @@ -162,7 +162,13 @@ impl OutputFormatter for PrettyFormatter { Ok(()) } - fn write_result(&mut self, desc: &TestDesc, result: &TestResult, _: &[u8]) -> io::Result<()> { + fn write_result( + &mut self, + desc: &TestDesc, + result: &TestResult, + _: &[u8], + _: &ConsoleTestState, + ) -> io::Result<()> { if self.is_multithreaded { self.write_test_name(desc)?; } diff --git a/src/libtest/formatters/terse.rs b/src/libtest/formatters/terse.rs index 1400fba5d6092..d10b0c5807d57 100644 --- a/src/libtest/formatters/terse.rs +++ b/src/libtest/formatters/terse.rs @@ -170,7 +170,13 @@ impl OutputFormatter for TerseFormatter { Ok(()) } - fn write_result(&mut self, desc: &TestDesc, result: &TestResult, _: &[u8]) -> io::Result<()> { + fn write_result( + &mut self, + desc: &TestDesc, + result: &TestResult, + _: &[u8], + _: &ConsoleTestState, + ) -> io::Result<()> { match *result { TrOk => self.write_ok(), TrFailed | TrFailedMsg(_) => self.write_failed(), diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index a1ce45dad4e9e..6e00e02b3c809 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -906,7 +906,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu TeTimeout(ref test) => out.write_timeout(test), TeResult(test, result, stdout) => { st.write_log_result(&test, &result)?; - out.write_result(&test, &result, &*stdout)?; + out.write_result(&test, &result, &*stdout, &st)?; match result { TrOk => { st.passed += 1; diff --git a/src/test/run-make-fulldeps/libtest-json/Makefile b/src/test/run-make-fulldeps/libtest-json/Makefile index a0bc8cf6688bc..8339e230bbe92 100644 --- a/src/test/run-make-fulldeps/libtest-json/Makefile +++ b/src/test/run-make-fulldeps/libtest-json/Makefile @@ -2,13 +2,17 @@ # Test expected libtest's JSON output -OUTPUT_FILE := $(TMPDIR)/libtest-json-output.json +OUTPUT_FILE_DEFAULT := $(TMPDIR)/libtest-json-output-default.json +OUTPUT_FILE_STDOUT_SUCCESS := $(TMPDIR)/libtest-json-output-stdout-success.json all: $(RUSTC) --test f.rs - RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json > $(OUTPUT_FILE) || true + RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json > $(OUTPUT_FILE_DEFAULT) || true + RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json --show-output > $(OUTPUT_FILE_STDOUT_SUCCESS) || true - cat $(OUTPUT_FILE) | "$(PYTHON)" validate_json.py + cat $(OUTPUT_FILE_DEFAULT) | "$(PYTHON)" validate_json.py + cat $(OUTPUT_FILE_STDOUT_SUCCESS) | "$(PYTHON)" validate_json.py # Compare to output file - diff output.json $(OUTPUT_FILE) + diff output-default.json $(OUTPUT_FILE_DEFAULT) + diff output-stdout-success.json $(OUTPUT_FILE_STDOUT_SUCCESS) diff --git a/src/test/run-make-fulldeps/libtest-json/f.rs b/src/test/run-make-fulldeps/libtest-json/f.rs index f5e44c2c24407..95ff36bd764ec 100644 --- a/src/test/run-make-fulldeps/libtest-json/f.rs +++ b/src/test/run-make-fulldeps/libtest-json/f.rs @@ -1,11 +1,12 @@ #[test] fn a() { + println!("print from successful test"); // Should pass } #[test] fn b() { - assert!(false) + assert!(false); } #[test] diff --git a/src/test/run-make-fulldeps/libtest-json/output.json b/src/test/run-make-fulldeps/libtest-json/output-default.json similarity index 91% rename from src/test/run-make-fulldeps/libtest-json/output.json rename to src/test/run-make-fulldeps/libtest-json/output-default.json index 0caf268aa007f..8046d72221703 100644 --- a/src/test/run-make-fulldeps/libtest-json/output.json +++ b/src/test/run-make-fulldeps/libtest-json/output-default.json @@ -2,7 +2,7 @@ { "type": "test", "event": "started", "name": "a" } { "type": "test", "name": "a", "event": "ok" } { "type": "test", "event": "started", "name": "b" } -{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:8:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.\n" } +{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.\n" } { "type": "test", "event": "started", "name": "c" } { "type": "test", "name": "c", "event": "ok" } { "type": "test", "event": "started", "name": "d" } diff --git a/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json new file mode 100644 index 0000000000000..303316278d8ab --- /dev/null +++ b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json @@ -0,0 +1,10 @@ +{ "type": "suite", "event": "started", "test_count": 4 } +{ "type": "test", "event": "started", "name": "a" } +{ "type": "test", "name": "a", "event": "ok", "stdout": "print from successful test\n" } +{ "type": "test", "event": "started", "name": "b" } +{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.\n" } +{ "type": "test", "event": "started", "name": "c" } +{ "type": "test", "name": "c", "event": "ok", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:15:5\n" } +{ "type": "test", "event": "started", "name": "d" } +{ "type": "test", "name": "d", "event": "ignored" } +{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "allowed_fail": 0, "ignored": 1, "measured": 0, "filtered_out": 0 } From cb873c5a87a70661ba4c9a6575374a738dd59481 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 16 Jul 2019 18:29:50 +0200 Subject: [PATCH 003/618] code formatting --- src/librustdoc/html/render.rs | 18 ++++++++++-------- src/librustdoc/html/static/main.js | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3cd520fd4b50b..9813c36397e2e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2575,13 +2575,14 @@ fn document(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item) -> fmt } /// Render md_text as markdown. -fn render_markdown(w: &mut fmt::Formatter<'_>, - cx: &Context, - md_text: &str, - links: Vec<(String, String)>, - prefix: &str, - is_hidden: bool) - -> fmt::Result { +fn render_markdown( + w: &mut fmt::Formatter<'_>, + cx: &Context, + md_text: &str, + links: Vec<(String, String)>, + prefix: &str, + is_hidden: bool, +) -> fmt::Result { let mut ids = cx.id_map.borrow_mut(); write!(w, "
{}{}
", if is_hidden { " hidden" } else { "" }, @@ -2595,7 +2596,8 @@ fn document_short( cx: &Context, item: &clean::Item, link: AssocItemLink<'_>, - prefix: &str, is_hidden: bool + prefix: &str, + is_hidden: bool, ) -> fmt::Result { if let Some(s) = item.doc_value() { let markdown = if s.contains('\n') { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 82d2c11b2497b..bc49d34b15bb3 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -3,7 +3,7 @@ // Local js definitions: /* global addClass, getCurrentValue, hasClass */ -/* global isHidden onEach, removeClass, updateLocalStorage */ +/* global isHidden, onEach, removeClass, updateLocalStorage */ if (!String.prototype.startsWith) { String.prototype.startsWith = function(searchString, position) { From 145ae1b26375b8e003d39df402dbff24030fa774 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 16 Jul 2019 18:32:14 +0200 Subject: [PATCH 004/618] hide default trait methods by default --- src/librustdoc/html/render.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 9813c36397e2e..b8d774dac2f64 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -4250,9 +4250,10 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt RenderMode::ForDeref { mut_: deref_mut_ } => should_render_item(&item, deref_mut_), }; - let (is_hidden, extra_class) = if trait_.is_none() || - item.doc_value().is_some() || - item.inner.is_associated() { + let (is_hidden, extra_class) = if (trait_.is_none() || + item.doc_value().is_some() || + item.inner.is_associated()) && + !is_default_item { (false, "") } else { (true, " hidden") From f7656b65764bf2134ffdd605bc182263c79fc508 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 16 Jul 2019 23:24:10 +0200 Subject: [PATCH 005/618] Update tests --- src/test/rustdoc/assoc-consts.rs | 2 +- src/test/rustdoc/inline_cross/assoc-items.rs | 6 +++--- .../rustdoc/inline_cross/impl-inline-without-trait.rs | 2 +- src/test/rustdoc/manual_impl.rs | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs index ee622e74a08dc..bb6af7995a0ad 100644 --- a/src/test/rustdoc/assoc-consts.rs +++ b/src/test/rustdoc/assoc-consts.rs @@ -95,5 +95,5 @@ impl Qux for Bar { /// Docs for QUX_DEFAULT1 in impl. const QUX_DEFAULT1: i16 = 7; // @has - '//*[@id="associatedconstant.QUX_DEFAULT2"]' 'const QUX_DEFAULT2: u32' - // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT2 in trait." + // @has - '//*[@class="docblock hidden"]' "Docs for QUX_DEFAULT2 in trait." } diff --git a/src/test/rustdoc/inline_cross/assoc-items.rs b/src/test/rustdoc/inline_cross/assoc-items.rs index d4f05bab5cabf..7eb3e43cb114e 100644 --- a/src/test/rustdoc/inline_cross/assoc-items.rs +++ b/src/test/rustdoc/inline_cross/assoc-items.rs @@ -16,15 +16,15 @@ extern crate assoc_items; // @has - '//*[@id="associatedconstant.ConstNoDefault"]' 'const ConstNoDefault: i16' // @has - '//*[@class="docblock"]' 'dox for ConstNoDefault' // @has - '//*[@id="associatedconstant.ConstWithDefault"]' 'const ConstWithDefault: u16' -// @has - '//*[@class="docblock"]' 'docs for ConstWithDefault' +// @has - '//*[@class="docblock hidden"]' 'docs for ConstWithDefault' // @has - '//*[@id="associatedtype.TypeNoDefault"]' 'type TypeNoDefault = i32' // @has - '//*[@class="docblock"]' 'dox for TypeNoDefault' // @has - '//*[@id="associatedtype.TypeWithDefault"]' 'type TypeWithDefault = u32' -// @has - '//*[@class="docblock"]' 'docs for TypeWithDefault' +// @has - '//*[@class="docblock hidden"]' 'docs for TypeWithDefault' // @has - '//*[@id="method.method_no_default"]' 'fn method_no_default()' // @has - '//*[@class="docblock"]' 'dox for method_no_default' // @has - '//*[@id="method.method_with_default"]' 'fn method_with_default()' -// @has - '//*[@class="docblock"]' 'docs for method_with_default' +// @has - '//*[@class="docblock hidden"]' 'docs for method_with_default' pub use assoc_items::MyStruct; // @has foo/trait.MyTrait.html diff --git a/src/test/rustdoc/inline_cross/impl-inline-without-trait.rs b/src/test/rustdoc/inline_cross/impl-inline-without-trait.rs index cadeccb60c817..4591bb526ae77 100644 --- a/src/test/rustdoc/inline_cross/impl-inline-without-trait.rs +++ b/src/test/rustdoc/inline_cross/impl-inline-without-trait.rs @@ -8,5 +8,5 @@ extern crate impl_inline_without_trait; // @has 'foo/struct.MyStruct.html' // @has - '//*[@id="method.my_trait_method"]' 'fn my_trait_method()' -// @has - '//*[@class="docblock"]' 'docs for my_trait_method' +// @has - '//*[@class="docblock hidden"]' 'docs for my_trait_method' pub use impl_inline_without_trait::MyStruct; diff --git a/src/test/rustdoc/manual_impl.rs b/src/test/rustdoc/manual_impl.rs index c9e4f4e0d3037..11ddab5f7ff26 100644 --- a/src/test/rustdoc/manual_impl.rs +++ b/src/test/rustdoc/manual_impl.rs @@ -24,10 +24,10 @@ pub trait T { // @has - '//*[@class="docblock"]' 'Docs associated with the S1 trait implementation.' // @has - '//*[@class="docblock"]' 'Docs associated with the S1 trait a_method implementation.' // @!has - '//*[@class="docblock"]' 'Docs associated with the trait a_method definition.' -// @has - '//*[@class="docblock"]' 'Docs associated with the trait b_method definition.' -// @has - '//*[@class="docblock"]' 'Docs associated with the trait c_method definition.' +// @has - '//*[@class="docblock hidden"]' 'Docs associated with the trait b_method definition.' +// @has - '//*[@class="docblock hidden"]' 'Docs associated with the trait c_method definition.' // @!has - '//*[@class="docblock"]' 'There is another line' -// @has - '//*[@class="docblock"]' 'Read more' +// @has - '//*[@class="docblock hidden"]' 'Read more' pub struct S1(usize); /// Docs associated with the S1 trait implementation. @@ -44,7 +44,7 @@ impl T for S1 { // @has - '//*[@class="docblock"]' 'Docs associated with the S2 trait c_method implementation.' // @!has - '//*[@class="docblock"]' 'Docs associated with the trait a_method definition.' // @!has - '//*[@class="docblock"]' 'Docs associated with the trait c_method definition.' -// @has - '//*[@class="docblock"]' 'Docs associated with the trait b_method definition.' +// @has - '//*[@class="docblock hidden"]' 'Docs associated with the trait b_method definition.' pub struct S2(usize); /// Docs associated with the S2 trait implementation. From a0ab5a3651f5cb30efa2f82a3ee15a7df479080a Mon Sep 17 00:00:00 2001 From: ksqsf Date: Thu, 1 Aug 2019 00:26:47 +0800 Subject: [PATCH 006/618] Add Result::cloned{,_err} and Result::copied{,_err} --- src/libcore/result.rs | 160 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 559877ddd5a1c..a8f0f422cb4d7 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -820,6 +820,166 @@ impl Result { } } +impl Result<&T, E> { + /// Maps a `Result<&T, E>` to a `Result` by copying the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_copied)] + /// let val = 12; + /// let x = Ok(&val); + /// assert_eq!(x, Ok(&12)); + /// let copied = x.copied(); + /// assert_eq!(copied, Ok(12)); + /// ``` + #[unstable(feature = "result_copied", reason = "newly added", issue = "XXXXX")] + fn copied(self) -> Result { + self.map(|&t| t) + } +} + +impl Result<&mut T, E> { + /// Maps a `Result<&mut T, E>` to a `Result` by copying the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_copied)] + /// let val = 12; + /// let x = Ok(&mut val); + /// assert_eq!(x, Ok(&mut 12)); + /// let copied = x.copied(); + /// assert_eq!(copied, Ok(12)); + /// ``` + #[unstable(feature = "result_copied", reason = "newly added", issue = "XXXXX")] + fn copied(self) -> Result { + self.map(|&mut t| t) + } +} + +impl Result { + /// Maps a `Result` to a `Result` by copying the contents of the + /// `Err` part. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_copied)] + /// let val = 12; + /// let x = Err(&val); + /// assert_eq!(x, Err(&12)); + /// let copied = x.copied_err(); + /// assert_eq!(copied, Err(12)); + /// ``` + #[unstable(feature = "result_copied", reason = "newly added", issue = "XXXXX")] + fn copied_err(self) -> Result { + self.map_err(|&e| e) + } +} + +impl Result { + /// Maps a `Result` to a `Result` by copying the contents of the + /// `Err` part. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_copied)] + /// let val = 12; + /// let x = Err(&mut val); + /// assert_eq!(x, Err(&mut 12)); + /// let copied = x.copied(); + /// assert_eq!(cloned, Err(12)); + /// ``` + #[unstable(feature = "result_copied", reason = "newly added", issue = "XXXXX")] + fn copied_err(self) -> Result { + self.map_err(|&mut e| e) + } +} + +impl Result<&T, E> { + /// Maps a `Result<&T, E>` to a `Result` by cloning the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_cloned)] + /// let val = 12; + /// let x = Ok(&val); + /// assert_eq!(x, Ok(&12)); + /// let cloned = x.cloned(); + /// assert_eq!(cloned, Ok(12)); + /// ``` + #[unstable(feature = "result_cloned", reason = "newly added", issue = "XXXXX")] + fn cloned(self) -> Result { + self.map(|t| t.clone()) + } +} + +impl Result<&mut T, E> { + /// Maps a `Result<&mut T, E>` to a `Result` by cloning the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_cloned)] + /// let val = 12; + /// let x = Ok(&mut val); + /// assert_eq!(x, Ok(&mut 12)); + /// let cloned = x.cloned(); + /// assert_eq!(cloned, Ok(12)); + /// ``` + #[unstable(feature = "result_cloned", reason = "newly added", issue = "XXXXX")] + fn cloned(self) -> Result { + self.map(|t| t.clone()) + } +} + +impl Result { + /// Maps a `Result` to a `Result` by cloning the contents of the + /// `Err` part. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_cloned)] + /// let val = 12; + /// let x = Err(&mut val); + /// assert_eq!(x, Err(&mut 12)); + /// let cloned = x.cloned(); + /// assert_eq!(cloned, Err(12)); + /// ``` + #[unstable(feature = "result_cloned", reason = "newly added", issue = "XXXXX")] + fn cloned_err(self) -> Result { + self.map_err(|e| e.clone()) + } +} + +impl Result { + /// Maps a `Result` to a `Result` by cloning the contents of the + /// `Err` part. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_cloned)] + /// let val = 12; + /// let x = Err(&mut val); + /// assert_eq!(x, Err(&mut 12)); + /// let cloned = x.cloned(); + /// assert_eq!(cloned, Err(12)); + /// ``` + #[unstable(feature = "result_cloned", reason = "newly added", issue = "XXXXX")] + fn cloned_err(self) -> Result { + self.map_err(|e| e.clone()) + } +} + impl Result { /// Unwraps a result, yielding the content of an [`Ok`]. /// From c784720f3a2d0b66142da3c9a9fd6039f5d3a036 Mon Sep 17 00:00:00 2001 From: ksqsf Date: Thu, 1 Aug 2019 00:55:36 +0800 Subject: [PATCH 007/618] Fix issue and impl --- src/libcore/result.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index a8f0f422cb4d7..31584972b9f68 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -834,7 +834,7 @@ impl Result<&T, E> { /// let copied = x.copied(); /// assert_eq!(copied, Ok(12)); /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "XXXXX")] + #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] fn copied(self) -> Result { self.map(|&t| t) } @@ -854,7 +854,7 @@ impl Result<&mut T, E> { /// let copied = x.copied(); /// assert_eq!(copied, Ok(12)); /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "XXXXX")] + #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] fn copied(self) -> Result { self.map(|&mut t| t) } @@ -874,7 +874,7 @@ impl Result { /// let copied = x.copied_err(); /// assert_eq!(copied, Err(12)); /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "XXXXX")] + #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] fn copied_err(self) -> Result { self.map_err(|&e| e) } @@ -894,7 +894,7 @@ impl Result { /// let copied = x.copied(); /// assert_eq!(cloned, Err(12)); /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "XXXXX")] + #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] fn copied_err(self) -> Result { self.map_err(|&mut e| e) } @@ -914,7 +914,7 @@ impl Result<&T, E> { /// let cloned = x.cloned(); /// assert_eq!(cloned, Ok(12)); /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "XXXXX")] + #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] fn cloned(self) -> Result { self.map(|t| t.clone()) } @@ -934,13 +934,13 @@ impl Result<&mut T, E> { /// let cloned = x.cloned(); /// assert_eq!(cloned, Ok(12)); /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "XXXXX")] + #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] fn cloned(self) -> Result { self.map(|t| t.clone()) } } -impl Result { +impl Result { /// Maps a `Result` to a `Result` by cloning the contents of the /// `Err` part. /// @@ -954,7 +954,7 @@ impl Result { /// let cloned = x.cloned(); /// assert_eq!(cloned, Err(12)); /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "XXXXX")] + #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] fn cloned_err(self) -> Result { self.map_err(|e| e.clone()) } @@ -974,7 +974,7 @@ impl Result { /// let cloned = x.cloned(); /// assert_eq!(cloned, Err(12)); /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "XXXXX")] + #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] fn cloned_err(self) -> Result { self.map_err(|e| e.clone()) } From 5a36b0dba1d7a350bba04b1abf256f057b3d1079 Mon Sep 17 00:00:00 2001 From: ksqsf Date: Thu, 1 Aug 2019 01:09:07 +0800 Subject: [PATCH 008/618] Make these methods public --- src/libcore/result.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 31584972b9f68..77cb447b95460 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -835,7 +835,7 @@ impl Result<&T, E> { /// assert_eq!(copied, Ok(12)); /// ``` #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - fn copied(self) -> Result { + pub fn copied(self) -> Result { self.map(|&t| t) } } @@ -855,7 +855,7 @@ impl Result<&mut T, E> { /// assert_eq!(copied, Ok(12)); /// ``` #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - fn copied(self) -> Result { + pub fn copied(self) -> Result { self.map(|&mut t| t) } } @@ -875,7 +875,7 @@ impl Result { /// assert_eq!(copied, Err(12)); /// ``` #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - fn copied_err(self) -> Result { + pub fn copied_err(self) -> Result { self.map_err(|&e| e) } } @@ -895,7 +895,7 @@ impl Result { /// assert_eq!(cloned, Err(12)); /// ``` #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - fn copied_err(self) -> Result { + pub fn copied_err(self) -> Result { self.map_err(|&mut e| e) } } @@ -915,7 +915,7 @@ impl Result<&T, E> { /// assert_eq!(cloned, Ok(12)); /// ``` #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - fn cloned(self) -> Result { + pub fn cloned(self) -> Result { self.map(|t| t.clone()) } } @@ -935,7 +935,7 @@ impl Result<&mut T, E> { /// assert_eq!(cloned, Ok(12)); /// ``` #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - fn cloned(self) -> Result { + pub fn cloned(self) -> Result { self.map(|t| t.clone()) } } @@ -955,7 +955,7 @@ impl Result { /// assert_eq!(cloned, Err(12)); /// ``` #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - fn cloned_err(self) -> Result { + pub fn cloned_err(self) -> Result { self.map_err(|e| e.clone()) } } @@ -975,7 +975,7 @@ impl Result { /// assert_eq!(cloned, Err(12)); /// ``` #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - fn cloned_err(self) -> Result { + pub fn cloned_err(self) -> Result { self.map_err(|e| e.clone()) } } From 6c130817623426697d8ebdf5d505487bd11ee2f6 Mon Sep 17 00:00:00 2001 From: ksqsf Date: Thu, 1 Aug 2019 02:35:14 +0800 Subject: [PATCH 009/618] Rename {copied,cloned} to {copied,cloned}_ok, and add {copied,cloned} to copy/clone both Ok and Err --- src/libcore/result.rs | 144 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 140 insertions(+), 4 deletions(-) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 77cb447b95460..0aa8fcb69b9c6 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -835,7 +835,7 @@ impl Result<&T, E> { /// assert_eq!(copied, Ok(12)); /// ``` #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied(self) -> Result { + pub fn copied_ok(self) -> Result { self.map(|&t| t) } } @@ -855,7 +855,7 @@ impl Result<&mut T, E> { /// assert_eq!(copied, Ok(12)); /// ``` #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied(self) -> Result { + pub fn copied_ok(self) -> Result { self.map(|&mut t| t) } } @@ -900,6 +900,74 @@ impl Result { } } +impl Result<&T, &E> { + /// Maps a `Result<&T, &E>` to a `Result` by copying the + /// contents of the result. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_copied)] + /// assert_eq!(Err(&1), Err(1)); + /// assert_eq!(Ok(&42), Ok(42)); + /// ``` + #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] + pub fn copied(self) -> Result { + self.copied_ok().copied_err() + } +} + +impl Result<&mut T, &E> { + /// Maps a `Result<&mut T, &E>` to a `Result` by copying the + /// contents of the result. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_copied)] + /// assert_eq!(Err(&1), Err(1)); + /// assert_eq!(Ok(&mut 42), Ok(42)); + /// ``` + #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] + pub fn copied(self) -> Result { + self.copied_ok().copied_err() + } +} + +impl Result<&T, &mut E> { + /// Maps a `Result<&T, &mut E>` to a `Result` by copying the + /// contents of the result. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_copied)] + /// assert_eq!(Err(&mut 1), Err(1)); + /// assert_eq!(Ok(&42), Ok(42)); + /// ``` + #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] + pub fn copied(self) -> Result { + self.copied_ok().copied_err() + } +} + +impl Result<&mut T, &mut E> { + /// Maps a `Result<&mut T, &mut E>` to a `Result` by copying + /// the contents of the result. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_copied)] + /// assert_eq!(Err(&mut 1), Err(1)); + /// assert_eq!(Ok(&mut 42), Ok(42)); + /// ``` + #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] + pub fn copied(self) -> Result { + self.copied_ok().copied_err() + } +} + impl Result<&T, E> { /// Maps a `Result<&T, E>` to a `Result` by cloning the contents of the /// `Ok` part. @@ -915,7 +983,7 @@ impl Result<&T, E> { /// assert_eq!(cloned, Ok(12)); /// ``` #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned(self) -> Result { + pub fn cloned_ok(self) -> Result { self.map(|t| t.clone()) } } @@ -935,7 +1003,7 @@ impl Result<&mut T, E> { /// assert_eq!(cloned, Ok(12)); /// ``` #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned(self) -> Result { + pub fn cloned_ok(self) -> Result { self.map(|t| t.clone()) } } @@ -980,6 +1048,74 @@ impl Result { } } +impl Result<&T, &E> { + /// Maps a `Result<&T, &E>` to a `Result` by cloning the contents of the + /// result. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_cloned)] + /// assert_eq!(Err(&1).cloned(), Err(1)); + /// assert_eq!(Ok(&42).cloned(), Ok(42)); + /// ``` + #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] + pub fn cloned(self) -> Result { + self.cloned_ok().cloned_err() + } +} + +impl Result<&mut T, &E> { + /// Maps a `Result<&mut T, &E>` to a `Result` by cloning the + /// contents of the result. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_cloned)] + /// assert_eq!(Err(&1).cloned(), Err(1)); + /// assert_eq!(Ok(&mut 42).cloned(), Ok(42)); + /// ``` + #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] + pub fn cloned(self) -> Result { + self.cloned_ok().cloned_err() + } +} + +impl Result<&T, &mut E> { + /// Maps a `Result<&T, &mut E>` to a `Result` by cloning the + /// contents of the result. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_cloned)] + /// assert_eq!(Err(&mut 1).cloned(), Err(1)); + /// assert_eq!(Ok(&42).cloned(), Ok(42)); + /// ``` + #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] + pub fn cloned(self) -> Result { + self.cloned_ok().cloned_err() + } +} + +impl Result<&mut T, &mut E> { + /// Maps a `Result<&mut T, &mut E>` to a `Result` by cloning + /// the contents of the result. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_cloned)] + /// assert_eq!(Err(&mut 1).cloned(), Err(1)); + /// assert_eq!(Ok(&mut 42).cloned(), Ok(42)); + /// ``` + #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] + pub fn cloned(self) -> Result { + self.cloned_ok().cloned_err() + } +} + impl Result { /// Unwraps a result, yielding the content of an [`Ok`]. /// From 4b2f598986e135f0eb070a9be87a5a963e8ff3d4 Mon Sep 17 00:00:00 2001 From: ksqsf Date: Thu, 1 Aug 2019 13:38:23 +0800 Subject: [PATCH 010/618] Revert "cloned/copied" This reverts commit 6c130817623426697d8ebdf5d505487bd11ee2f6. --- src/libcore/result.rs | 144 ++---------------------------------------- 1 file changed, 4 insertions(+), 140 deletions(-) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 0aa8fcb69b9c6..77cb447b95460 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -835,7 +835,7 @@ impl Result<&T, E> { /// assert_eq!(copied, Ok(12)); /// ``` #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied_ok(self) -> Result { + pub fn copied(self) -> Result { self.map(|&t| t) } } @@ -855,7 +855,7 @@ impl Result<&mut T, E> { /// assert_eq!(copied, Ok(12)); /// ``` #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied_ok(self) -> Result { + pub fn copied(self) -> Result { self.map(|&mut t| t) } } @@ -900,74 +900,6 @@ impl Result { } } -impl Result<&T, &E> { - /// Maps a `Result<&T, &E>` to a `Result` by copying the - /// contents of the result. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_copied)] - /// assert_eq!(Err(&1), Err(1)); - /// assert_eq!(Ok(&42), Ok(42)); - /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied(self) -> Result { - self.copied_ok().copied_err() - } -} - -impl Result<&mut T, &E> { - /// Maps a `Result<&mut T, &E>` to a `Result` by copying the - /// contents of the result. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_copied)] - /// assert_eq!(Err(&1), Err(1)); - /// assert_eq!(Ok(&mut 42), Ok(42)); - /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied(self) -> Result { - self.copied_ok().copied_err() - } -} - -impl Result<&T, &mut E> { - /// Maps a `Result<&T, &mut E>` to a `Result` by copying the - /// contents of the result. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_copied)] - /// assert_eq!(Err(&mut 1), Err(1)); - /// assert_eq!(Ok(&42), Ok(42)); - /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied(self) -> Result { - self.copied_ok().copied_err() - } -} - -impl Result<&mut T, &mut E> { - /// Maps a `Result<&mut T, &mut E>` to a `Result` by copying - /// the contents of the result. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_copied)] - /// assert_eq!(Err(&mut 1), Err(1)); - /// assert_eq!(Ok(&mut 42), Ok(42)); - /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied(self) -> Result { - self.copied_ok().copied_err() - } -} - impl Result<&T, E> { /// Maps a `Result<&T, E>` to a `Result` by cloning the contents of the /// `Ok` part. @@ -983,7 +915,7 @@ impl Result<&T, E> { /// assert_eq!(cloned, Ok(12)); /// ``` #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned_ok(self) -> Result { + pub fn cloned(self) -> Result { self.map(|t| t.clone()) } } @@ -1003,7 +935,7 @@ impl Result<&mut T, E> { /// assert_eq!(cloned, Ok(12)); /// ``` #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned_ok(self) -> Result { + pub fn cloned(self) -> Result { self.map(|t| t.clone()) } } @@ -1048,74 +980,6 @@ impl Result { } } -impl Result<&T, &E> { - /// Maps a `Result<&T, &E>` to a `Result` by cloning the contents of the - /// result. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_cloned)] - /// assert_eq!(Err(&1).cloned(), Err(1)); - /// assert_eq!(Ok(&42).cloned(), Ok(42)); - /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned(self) -> Result { - self.cloned_ok().cloned_err() - } -} - -impl Result<&mut T, &E> { - /// Maps a `Result<&mut T, &E>` to a `Result` by cloning the - /// contents of the result. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_cloned)] - /// assert_eq!(Err(&1).cloned(), Err(1)); - /// assert_eq!(Ok(&mut 42).cloned(), Ok(42)); - /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned(self) -> Result { - self.cloned_ok().cloned_err() - } -} - -impl Result<&T, &mut E> { - /// Maps a `Result<&T, &mut E>` to a `Result` by cloning the - /// contents of the result. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_cloned)] - /// assert_eq!(Err(&mut 1).cloned(), Err(1)); - /// assert_eq!(Ok(&42).cloned(), Ok(42)); - /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned(self) -> Result { - self.cloned_ok().cloned_err() - } -} - -impl Result<&mut T, &mut E> { - /// Maps a `Result<&mut T, &mut E>` to a `Result` by cloning - /// the contents of the result. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_cloned)] - /// assert_eq!(Err(&mut 1).cloned(), Err(1)); - /// assert_eq!(Ok(&mut 42).cloned(), Ok(42)); - /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned(self) -> Result { - self.cloned_ok().cloned_err() - } -} - impl Result { /// Unwraps a result, yielding the content of an [`Ok`]. /// From 9733f0d16382c728e502c3efb4f38a19270f8202 Mon Sep 17 00:00:00 2001 From: ksqsf Date: Thu, 1 Aug 2019 17:12:13 +0800 Subject: [PATCH 011/618] Fix doc tests --- src/libcore/result.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 77cb447b95460..7b9f6d9ff8a61 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -829,7 +829,7 @@ impl Result<&T, E> { /// ``` /// #![feature(result_copied)] /// let val = 12; - /// let x = Ok(&val); + /// let x: Result<&i32, i32> = Ok(&val); /// assert_eq!(x, Ok(&12)); /// let copied = x.copied(); /// assert_eq!(copied, Ok(12)); @@ -848,8 +848,8 @@ impl Result<&mut T, E> { /// /// ``` /// #![feature(result_copied)] - /// let val = 12; - /// let x = Ok(&mut val); + /// let mut val = 12; + /// let x: Result<&mut i32, i32> = Ok(&mut val); /// assert_eq!(x, Ok(&mut 12)); /// let copied = x.copied(); /// assert_eq!(copied, Ok(12)); @@ -869,7 +869,7 @@ impl Result { /// ``` /// #![feature(result_copied)] /// let val = 12; - /// let x = Err(&val); + /// let x: Result = Err(&val); /// assert_eq!(x, Err(&12)); /// let copied = x.copied_err(); /// assert_eq!(copied, Err(12)); @@ -888,11 +888,11 @@ impl Result { /// /// ``` /// #![feature(result_copied)] - /// let val = 12; - /// let x = Err(&mut val); + /// let mut val = 12; + /// let x: Result = Err(&mut val); /// assert_eq!(x, Err(&mut 12)); - /// let copied = x.copied(); - /// assert_eq!(cloned, Err(12)); + /// let copied = x.copied_err(); + /// assert_eq!(copied, Err(12)); /// ``` #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] pub fn copied_err(self) -> Result { @@ -909,7 +909,7 @@ impl Result<&T, E> { /// ``` /// #![feature(result_cloned)] /// let val = 12; - /// let x = Ok(&val); + /// let x: Result<&i32, i32> = Ok(&val); /// assert_eq!(x, Ok(&12)); /// let cloned = x.cloned(); /// assert_eq!(cloned, Ok(12)); @@ -928,8 +928,8 @@ impl Result<&mut T, E> { /// /// ``` /// #![feature(result_cloned)] - /// let val = 12; - /// let x = Ok(&mut val); + /// let mut val = 12; + /// let x: Result<&mut i32, i32> = Ok(&mut val); /// assert_eq!(x, Ok(&mut 12)); /// let cloned = x.cloned(); /// assert_eq!(cloned, Ok(12)); @@ -949,9 +949,9 @@ impl Result { /// ``` /// #![feature(result_cloned)] /// let val = 12; - /// let x = Err(&mut val); - /// assert_eq!(x, Err(&mut 12)); - /// let cloned = x.cloned(); + /// let x: Result = Err(&val); + /// assert_eq!(x, Err(&12)); + /// let cloned = x.cloned_err(); /// assert_eq!(cloned, Err(12)); /// ``` #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] @@ -968,10 +968,10 @@ impl Result { /// /// ``` /// #![feature(result_cloned)] - /// let val = 12; - /// let x = Err(&mut val); + /// let mut val = 12; + /// let x: Result = Err(&mut val); /// assert_eq!(x, Err(&mut 12)); - /// let cloned = x.cloned(); + /// let cloned = x.cloned_err(); /// assert_eq!(cloned, Err(12)); /// ``` #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] From 61e52866352339326600fe694e92373f2e07fd79 Mon Sep 17 00:00:00 2001 From: ksqsf Date: Fri, 2 Aug 2019 13:58:55 +0800 Subject: [PATCH 012/618] Remove Err variants of cloned and copied --- src/libcore/result.rs | 79 ------------------------------------------- 1 file changed, 79 deletions(-) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 7b9f6d9ff8a61..935e48574fdf5 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -860,46 +860,6 @@ impl Result<&mut T, E> { } } -impl Result { - /// Maps a `Result` to a `Result` by copying the contents of the - /// `Err` part. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_copied)] - /// let val = 12; - /// let x: Result = Err(&val); - /// assert_eq!(x, Err(&12)); - /// let copied = x.copied_err(); - /// assert_eq!(copied, Err(12)); - /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied_err(self) -> Result { - self.map_err(|&e| e) - } -} - -impl Result { - /// Maps a `Result` to a `Result` by copying the contents of the - /// `Err` part. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_copied)] - /// let mut val = 12; - /// let x: Result = Err(&mut val); - /// assert_eq!(x, Err(&mut 12)); - /// let copied = x.copied_err(); - /// assert_eq!(copied, Err(12)); - /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied_err(self) -> Result { - self.map_err(|&mut e| e) - } -} - impl Result<&T, E> { /// Maps a `Result<&T, E>` to a `Result` by cloning the contents of the /// `Ok` part. @@ -940,45 +900,6 @@ impl Result<&mut T, E> { } } -impl Result { - /// Maps a `Result` to a `Result` by cloning the contents of the - /// `Err` part. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_cloned)] - /// let val = 12; - /// let x: Result = Err(&val); - /// assert_eq!(x, Err(&12)); - /// let cloned = x.cloned_err(); - /// assert_eq!(cloned, Err(12)); - /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned_err(self) -> Result { - self.map_err(|e| e.clone()) - } -} - -impl Result { - /// Maps a `Result` to a `Result` by cloning the contents of the - /// `Err` part. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_cloned)] - /// let mut val = 12; - /// let x: Result = Err(&mut val); - /// assert_eq!(x, Err(&mut 12)); - /// let cloned = x.cloned_err(); - /// assert_eq!(cloned, Err(12)); - /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned_err(self) -> Result { - self.map_err(|e| e.clone()) - } -} impl Result { /// Unwraps a result, yielding the content of an [`Ok`]. From ae1e7cace3971b2ed7e2e75fca74c554a36fbfd3 Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Thu, 25 Jul 2019 00:35:24 +0200 Subject: [PATCH 013/618] Match the loop examples --- src/libstd/keyword_docs.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index f5018485ef7bc..5ca518358d7d9 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -681,14 +681,15 @@ mod while_keyword { } /// # break; /// } /// -/// let mut i = 0; +/// let mut i = 1; /// loop { /// println!("i is {}", i); -/// if i > 10 { +/// if i > 100 { /// break; /// } -/// i += 1; +/// i *= 2; /// } +/// assert_eq!(i, 128); /// ``` /// /// Unlike the other kinds of loops in Rust (`while`, `while let`, and `for`), loops can be used as From 7b8273c2e873b814b7c115eabae398d6f11d695b Mon Sep 17 00:00:00 2001 From: newpavlov Date: Tue, 13 Aug 2019 17:21:45 +0300 Subject: [PATCH 014/618] Re-enable Redox builder (take 2) --- Cargo.lock | 120 ++++++++++++------------ src/ci/docker/dist-various-1/Dockerfile | 6 +- 2 files changed, 62 insertions(+), 64 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ab6731e4d433d..38dba4f629885 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,7 +92,7 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -105,7 +105,7 @@ dependencies = [ "backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -117,7 +117,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -162,7 +162,7 @@ dependencies = [ "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -269,7 +269,7 @@ dependencies = [ "jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -453,7 +453,7 @@ name = "commoncrypto-sys" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -473,7 +473,7 @@ dependencies = [ "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -492,7 +492,7 @@ dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -523,7 +523,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -658,7 +658,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "curl-sys 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -672,7 +672,7 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", @@ -780,7 +780,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -791,7 +791,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -904,7 +904,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -919,7 +919,7 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -964,7 +964,7 @@ name = "fs2" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1054,7 +1054,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1063,7 +1063,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1348,7 +1348,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1385,7 +1385,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1393,7 +1393,7 @@ name = "jobserver" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1441,7 +1441,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.60" +version = "0.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-std-workspace-core 1.0.0", @@ -1465,7 +1465,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1478,7 +1478,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1487,7 +1487,7 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1500,7 +1500,7 @@ version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1565,7 +1565,7 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1675,7 +1675,7 @@ name = "memmap" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1725,7 +1725,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1743,7 +1743,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1757,7 +1757,7 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1782,7 +1782,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1832,7 +1832,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1849,7 +1849,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1892,7 +1892,7 @@ name = "num_cpus" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1917,7 +1917,7 @@ dependencies = [ "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1940,7 +1940,7 @@ version = "0.9.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-src 111.3.0+1.1.1c (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1979,7 +1979,7 @@ version = "0.0.0" dependencies = [ "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1990,7 +1990,7 @@ dependencies = [ "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "unwind 0.0.0", ] @@ -2008,7 +2008,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2230,7 +2230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2247,7 +2247,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2320,7 +2320,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2778,7 +2778,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2867,7 +2867,7 @@ dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3372,7 +3372,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3480,7 +3480,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3512,7 +3512,7 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3535,7 +3535,7 @@ dependencies = [ "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "panic_abort 0.0.0", "panic_unwind 0.0.0", "profiler_builtins 0.0.0", @@ -3712,7 +3712,7 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3723,7 +3723,7 @@ version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3776,7 +3776,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3796,7 +3796,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3832,7 +3832,7 @@ name = "time" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3923,7 +3923,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3955,7 +3955,7 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4026,7 +4026,7 @@ dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4160,7 +4160,7 @@ dependencies = [ "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4329,7 +4329,7 @@ name = "xattr" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4482,7 +4482,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" +"checksum libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)" = "c665266eb592905e8503ba3403020f4b8794d26263f412ca33171600eca9a6fa" "checksum libflate 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "90c6f86f4b0caa347206f916f8b687b51d77c6ef8ff18d52dd007491fd580529" "checksum libgit2-sys 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4c179ed6d19cd3a051e68c177fbbc214e79ac4724fac3a850ec9f3d3eb8a5578" "checksum libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d75d7966bda4730b722d1eab8e668df445368a24394bae9fc1e8dc0ab3dbe4f4" diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index ae2ea8ef95a6a..105791194628b 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -104,9 +104,7 @@ ENV TARGETS=$TARGETS,armv5te-unknown-linux-musleabi ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf ENV TARGETS=$TARGETS,aarch64-unknown-linux-musl ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu -# FIXME: temporarily disable the redox builder, -# see: https://github.com/rust-lang/rust/issues/63160 -# ENV TARGETS=$TARGETS,x86_64-unknown-redox +ENV TARGETS=$TARGETS,x86_64-unknown-redox ENV TARGETS=$TARGETS,thumbv6m-none-eabi ENV TARGETS=$TARGETS,thumbv7m-none-eabi ENV TARGETS=$TARGETS,thumbv7em-none-eabi @@ -132,7 +130,7 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \ AR_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar \ CXX_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ - + ENV RUST_CONFIGURE_ARGS \ --musl-root-armv5te=/musl-armv5te \ --musl-root-arm=/musl-arm \ From 070c83d5a96d26240824abdb3c38ecdb860710f5 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Mon, 5 Aug 2019 11:32:27 +0200 Subject: [PATCH 015/618] add contains benchmarks --- .../tiny_list/tests.rs | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/librustc_data_structures/tiny_list/tests.rs b/src/librustc_data_structures/tiny_list/tests.rs index 8374659e1e67b..0142631590cc9 100644 --- a/src/librustc_data_structures/tiny_list/tests.rs +++ b/src/librustc_data_structures/tiny_list/tests.rs @@ -1,7 +1,7 @@ use super::*; extern crate test; -use test::Bencher; +use test::{Bencher, black_box}; #[test] fn test_contains_and_insert() { @@ -98,36 +98,59 @@ fn test_remove_single() { #[bench] fn bench_insert_empty(b: &mut Bencher) { b.iter(|| { - let mut list = TinyList::new(); + let mut list = black_box(TinyList::new()); list.insert(1); + list }) } #[bench] fn bench_insert_one(b: &mut Bencher) { b.iter(|| { - let mut list = TinyList::new_single(0); + let mut list = black_box(TinyList::new_single(0)); list.insert(1); + list }) } +#[bench] +fn bench_contains_empty(b: &mut Bencher) { + b.iter(|| { + black_box(TinyList::new()).contains(&1) + }); +} + +#[bench] +fn bench_contains_unknown(b: &mut Bencher) { + b.iter(|| { + black_box(TinyList::new_single(0)).contains(&1) + }); +} + +#[bench] +fn bench_contains_one(b: &mut Bencher) { + b.iter(|| { + black_box(TinyList::new_single(1)).contains(&1) + }); +} + #[bench] fn bench_remove_empty(b: &mut Bencher) { b.iter(|| { - TinyList::new().remove(&1) + black_box(TinyList::new()).remove(&1) }); } #[bench] fn bench_remove_unknown(b: &mut Bencher) { b.iter(|| { - TinyList::new_single(0).remove(&1) + black_box(TinyList::new_single(0)).remove(&1) }); } #[bench] fn bench_remove_one(b: &mut Bencher) { b.iter(|| { - TinyList::new_single(1).remove(&1) + black_box(TinyList::new_single(1)).remove(&1) }); } From 45f14a8c9026b33dc278000a5fc120e9667806ff Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Wed, 17 Jul 2019 08:19:29 +0200 Subject: [PATCH 016/618] refactor `len` and `contains` to iterate instead of recurse --- src/librustc_data_structures/tiny_list.rs | 56 +++++++---------------- 1 file changed, 16 insertions(+), 40 deletions(-) diff --git a/src/librustc_data_structures/tiny_list.rs b/src/librustc_data_structures/tiny_list.rs index 1c0d9360f2511..ea771d9f20f8b 100644 --- a/src/librustc_data_structures/tiny_list.rs +++ b/src/librustc_data_structures/tiny_list.rs @@ -20,7 +20,6 @@ pub struct TinyList { } impl TinyList { - #[inline] pub fn new() -> TinyList { TinyList { @@ -60,20 +59,24 @@ impl TinyList { #[inline] pub fn contains(&self, data: &T) -> bool { - if let Some(ref head) = self.head { - head.contains(data) - } else { - false + let mut elem = self.head.as_ref(); + while let Some(ref e) = elem { + if &e.data == data { + return true; + } + elem = e.next.as_ref().map(|e| &**e); } + false } #[inline] pub fn len(&self) -> usize { - if let Some(ref head) = self.head { - head.len() - } else { - 0 + let (mut elem, mut count) = (self.head.as_ref(), 0); + while let Some(ref e) = elem { + count += 1; + elem = e.next.as_ref().map(|e| &**e); } + count } } @@ -84,40 +87,13 @@ struct Element { } impl Element { - fn remove_next(&mut self, data: &T) -> bool { - let new_next = if let Some(ref mut next) = self.next { - if next.data != *data { - return next.remove_next(data) - } else { - next.next.take() - } - } else { - return false + let new_next = match self.next { + Some(ref mut next) if next.data == *data => next.next.take(), + Some(ref mut next) => return next.remove_next(data), + None => return false, }; - self.next = new_next; - true } - - fn len(&self) -> usize { - if let Some(ref next) = self.next { - 1 + next.len() - } else { - 1 - } - } - - fn contains(&self, data: &T) -> bool { - if self.data == *data { - return true - } - - if let Some(ref next) = self.next { - next.contains(data) - } else { - false - } - } } From 9b9eecf964235f781806ce3e026c1522eb35e013 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Sat, 13 Jul 2019 04:00:06 +0200 Subject: [PATCH 017/618] Store allocation size, make bytes, undef_mask private Direct access to the bytes was previously a problem (#62931) where components would read their contents without properly checking relocations and/or definedness. Making bytes private instead of purely renaming them also helps in allowing amendments to their allocation scheme (such as eliding allocation for undef of constant regions). --- src/librustc/ich/impls_ty.rs | 8 +++++- src/librustc/mir/interpret/allocation.rs | 35 ++++++++++++++++++------ src/librustc/ty/print/pretty.rs | 10 +++++-- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 0ddc9211f9811..e33991bb1b6f8 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -176,15 +176,21 @@ impl<'a> HashStable> for mir::interpret::Allocation { hasher: &mut StableHasher, ) { let mir::interpret::Allocation { - bytes, relocations, undef_mask, align, mutability, + relocations, align, mutability, size, extra: _, + .. /* private bytes and undef_mask */ } = self; + + let bytes = self.inspect_with_undef_and_ptr_outside_interpreter(0..self.len()); + let undef_mask = self.undef_mask(); + bytes.hash_stable(hcx, hasher); relocations.len().hash_stable(hcx, hasher); for reloc in relocations.iter() { reloc.hash_stable(hcx, hasher); } undef_mask.hash_stable(hcx, hasher); + size.hash_stable(hcx, hasher); align.hash_stable(hcx, hasher); mutability.hash_stable(hcx, hasher); } diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index ce04cca96e0f9..61b237c0bb395 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -16,15 +16,17 @@ use std::borrow::Cow; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct Allocation { /// The actual bytes of the allocation. - /// Note that the bytes of a pointer represent the offset of the pointer - pub bytes: Vec, + /// Note that the bytes of a pointer represent the offset of the pointer. + bytes: Vec, /// Maps from byte addresses to extra data for each pointer. /// Only the first byte of a pointer is inserted into the map; i.e., /// every entry in this map applies to `pointer_size` consecutive bytes starting /// at the given offset. pub relocations: Relocations, - /// Denotes undefined memory. Reading from undefined memory is forbidden in miri - pub undef_mask: UndefMask, + /// Denotes which part of this allocation is initialized. + undef_mask: UndefMask, + /// The size of the allocation. Currently, must always equal `bytes.len()`. + pub size: Size, /// The alignment of the allocation to detect unaligned reads. pub align: Align, /// Whether the allocation is mutable. @@ -85,11 +87,12 @@ impl Allocation { /// Creates a read-only allocation initialized by the given bytes pub fn from_bytes<'a>(slice: impl Into>, align: Align) -> Self { let bytes = slice.into().into_owned(); - let undef_mask = UndefMask::new(Size::from_bytes(bytes.len() as u64), true); + let size = Size::from_bytes(bytes.len() as u64); Self { bytes, relocations: Relocations::new(), - undef_mask, + undef_mask: UndefMask::new(size, true), + size, align, mutability: Mutability::Immutable, extra: (), @@ -106,6 +109,7 @@ impl Allocation { bytes: vec![0; size.bytes() as usize], relocations: Relocations::new(), undef_mask: UndefMask::new(size, false), + size, align, mutability: Mutability::Mutable, extra: (), @@ -113,6 +117,21 @@ impl Allocation { } } +/// Raw accessors. Provide access to otherwise private bytes. +impl Allocation { + pub fn len(&self) -> usize { + self.size.bytes() as usize + } + + /// Look at a slice which may describe undefined bytes or describe a relocation. This differs + /// from `get_bytes_with_undef_and_ptr` in that it does no relocation checks (even on the + /// edges) at all. It further ignores `AllocationExtra` callbacks. + /// This must not be used for reads affecting the interpreter execution. + pub fn inspect_with_undef_and_ptr_outside_interpreter(&self, range: Range) -> &[u8] { + &self.bytes[range] + } +} + impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Allocation {} /// Byte accessors @@ -132,9 +151,9 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { ); let end = end.bytes() as usize; assert!( - end <= self.bytes.len(), + end <= self.len(), "Out-of-bounds access at offset {}, size {} in allocation of size {}", - offset.bytes(), size.bytes(), self.bytes.len() + offset.bytes(), size.bytes(), self.len() ); (offset.bytes() as usize)..end } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index bf6741dde43b5..a72ecdb5745bb 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -944,10 +944,16 @@ pub trait PrettyPrinter<'tcx>: .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap()) }, (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { - Some(&data.bytes[start..end]) + // The `inspect` here is okay since we checked the bounds, and there are no + // relocations (we have an active slice reference here). We don't use this + // result to affect interpreter execution. + Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end)) }, (ConstValue::Slice { data, start, end }, ty::Str) => { - let slice = &data.bytes[start..end]; + // The `inspect` here is okay since we checked the bounds, and there are no + // relocations (we have an active `str` reference here). We don't use this + // result to affect interpreter execution. + let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); let s = ::std::str::from_utf8(slice) .expect("non utf8 str from miri"); p!(write("{:?}", s)); From 2228b3f08631b5e9b32e6b6c82e758fe4bcbbd60 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Sat, 17 Aug 2019 19:49:51 +0200 Subject: [PATCH 018/618] Derive HashStable for Allocation Requires a manual implementation for Relocations since dereferencing to SortedMap is not always implemented but that one is far more trivial. Added fields could otherwise be silently forgotten since private fields make destructing outside the module possible only with `..` pattern which would then also be applicable to newly added public fields. --- src/librustc/ich/impls_ty.rs | 26 ++++++++---------------- src/librustc/mir/interpret/allocation.rs | 13 +++++++++++- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index e33991bb1b6f8..be7669fcad875 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -168,31 +168,21 @@ impl<'a> HashStable> for mir::interpret::AllocId { } } -// Allocations treat their relocations specially -impl<'a> HashStable> for mir::interpret::Allocation { +// `Relocations` with default type parameters is a sorted map. +impl<'a, Tag> HashStable> +for mir::interpret::Relocations +where + Tag: HashStable>, +{ fn hash_stable( &self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher, ) { - let mir::interpret::Allocation { - relocations, align, mutability, size, - extra: _, - .. /* private bytes and undef_mask */ - } = self; - - let bytes = self.inspect_with_undef_and_ptr_outside_interpreter(0..self.len()); - let undef_mask = self.undef_mask(); - - bytes.hash_stable(hcx, hasher); - relocations.len().hash_stable(hcx, hasher); - for reloc in relocations.iter() { + self.len().hash_stable(hcx, hasher); + for reloc in self.iter() { reloc.hash_stable(hcx, hasher); } - undef_mask.hash_stable(hcx, hasher); - size.hash_stable(hcx, hasher); - align.hash_stable(hcx, hasher); - mutability.hash_stable(hcx, hasher); } } diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 61b237c0bb395..363fcaae5b266 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -13,7 +13,18 @@ use rustc_data_structures::sorted_map::SortedMap; use rustc_target::abi::HasDataLayout; use std::borrow::Cow; -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive( + Clone, + Debug, + Eq, + PartialEq, + PartialOrd, + Ord, + Hash, + RustcEncodable, + RustcDecodable, + HashStable, +)] pub struct Allocation { /// The actual bytes of the allocation. /// Note that the bytes of a pointer represent the offset of the pointer. From 98cff6928925256faffbe3e9ce9f14d0dfdbb6c0 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Tue, 30 Jul 2019 23:38:02 +0200 Subject: [PATCH 019/618] Move copy of undef_mask into allocation This also means that the compressed representation chosen may be optimized together with any changes to the undef_mask. --- src/librustc/mir/interpret/allocation.rs | 85 ++++++++++++++++++++++++ src/librustc_mir/interpret/memory.rs | 58 +--------------- 2 files changed, 88 insertions(+), 55 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 363fcaae5b266..e0ada7e2f11a3 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -566,6 +566,91 @@ impl<'tcx, Tag, Extra> Allocation { } } +/// Run-length encoding of the undef mask. +/// Used to copy parts of a mask multiple times to another allocation. +pub struct AllocationDefinedness { + ranges: smallvec::SmallVec::<[u64; 1]>, + first: bool, +} + +/// Transferring the definedness mask to other allocations. +impl Allocation { + /// Creates a run-length encoding of the undef_mask. + pub fn compress_defined_range( + &self, + src: Pointer, + size: Size, + ) -> AllocationDefinedness { + // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`), + // a naive undef mask copying algorithm would repeatedly have to read the undef mask from + // the source and write it to the destination. Even if we optimized the memory accesses, + // we'd be doing all of this `repeat` times. + // Therefor we precompute a compressed version of the undef mask of the source value and + // then write it back `repeat` times without computing any more information from the source. + + // a precomputed cache for ranges of defined/undefined bits + // 0000010010001110 will become + // [5, 1, 2, 1, 3, 3, 1] + // where each element toggles the state + + let mut ranges = smallvec::SmallVec::<[u64; 1]>::new(); + let first = self.undef_mask.get(src.offset); + let mut cur_len = 1; + let mut cur = first; + + for i in 1..size.bytes() { + // FIXME: optimize to bitshift the current undef block's bits and read the top bit + if self.undef_mask.get(src.offset + Size::from_bytes(i)) == cur { + cur_len += 1; + } else { + ranges.push(cur_len); + cur_len = 1; + cur = !cur; + } + } + + ranges.push(cur_len); + + AllocationDefinedness { ranges, first, } + } + + /// Apply multiple instances of the run-length encoding to the undef_mask. + pub fn mark_compressed_range( + &mut self, + defined: &AllocationDefinedness, + dest: Pointer, + size: Size, + repeat: u64, + ) { + // an optimization where we can just overwrite an entire range of definedness bits if + // they are going to be uniformly `1` or `0`. + if defined.ranges.len() <= 1 { + self.undef_mask.set_range_inbounds( + dest.offset, + dest.offset + size * repeat, + defined.first, + ); + return; + } + + for mut j in 0..repeat { + j *= size.bytes(); + j += dest.offset.bytes(); + let mut cur = defined.first; + for range in &defined.ranges { + let old_j = j; + j += range; + self.undef_mask.set_range_inbounds( + Size::from_bytes(old_j), + Size::from_bytes(j), + cur, + ); + cur = !cur; + } + } + } +} + /// Relocations #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct Relocations(SortedMap); diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index aef09df4537be..f572651f02b56 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -894,65 +894,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // The bits have to be saved locally before writing to dest in case src and dest overlap. assert_eq!(size.bytes() as usize as u64, size.bytes()); - let undef_mask = &self.get(src.alloc_id)?.undef_mask; - - // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`), - // a naive undef mask copying algorithm would repeatedly have to read the undef mask from - // the source and write it to the destination. Even if we optimized the memory accesses, - // we'd be doing all of this `repeat` times. - // Therefor we precompute a compressed version of the undef mask of the source value and - // then write it back `repeat` times without computing any more information from the source. - - // a precomputed cache for ranges of defined/undefined bits - // 0000010010001110 will become - // [5, 1, 2, 1, 3, 3, 1] - // where each element toggles the state - let mut ranges = smallvec::SmallVec::<[u64; 1]>::new(); - let first = undef_mask.get(src.offset); - let mut cur_len = 1; - let mut cur = first; - for i in 1..size.bytes() { - // FIXME: optimize to bitshift the current undef block's bits and read the top bit - if undef_mask.get(src.offset + Size::from_bytes(i)) == cur { - cur_len += 1; - } else { - ranges.push(cur_len); - cur_len = 1; - cur = !cur; - } - } + let src_alloc = self.get(src.alloc_id)?; + let compressed = src_alloc.compress_defined_range(src, size); // now fill in all the data let dest_allocation = self.get_mut(dest.alloc_id)?; - // an optimization where we can just overwrite an entire range of definedness bits if - // they are going to be uniformly `1` or `0`. - if ranges.is_empty() { - dest_allocation.undef_mask.set_range_inbounds( - dest.offset, - dest.offset + size * repeat, - first, - ); - return Ok(()) - } + dest_allocation.mark_compressed_range(&compressed, dest, size, repeat); - // remember to fill in the trailing bits - ranges.push(cur_len); - - for mut j in 0..repeat { - j *= size.bytes(); - j += dest.offset.bytes(); - let mut cur = first; - for range in &ranges { - let old_j = j; - j += range; - dest_allocation.undef_mask.set_range_inbounds( - Size::from_bytes(old_j), - Size::from_bytes(j), - cur, - ); - cur = !cur; - } - } Ok(()) } From 5d75654cce9bb174b874ff7d8eb2ccd70e9b268f Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Sat, 17 Aug 2019 19:15:36 +0000 Subject: [PATCH 020/618] fix Cargo.lock --- Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 59571bc7f6d54..c0e85c6487dee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3529,7 +3529,6 @@ dependencies = [ "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "panic_abort 0.0.0", "panic_unwind 0.0.0", "profiler_builtins 0.0.0", From e0f73052a93eee54400b7d4f788181b28bb54b4d Mon Sep 17 00:00:00 2001 From: GrayJack Date: Sun, 18 Aug 2019 07:13:33 -0300 Subject: [PATCH 021/618] Constify LinkedList new function --- src/liballoc/collections/linked_list.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index a14a3fe9994ab..816a71f255798 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -276,7 +276,7 @@ impl LinkedList { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> Self { + pub const fn new() -> Self { LinkedList { head: None, tail: None, From 6896ed383dbd3a847ef39b713449fc0393292828 Mon Sep 17 00:00:00 2001 From: newpavlov Date: Mon, 19 Aug 2019 09:47:58 +0300 Subject: [PATCH 022/618] use wasi crate --- src/libstd/sys/wasi/args.rs | 16 +- src/libstd/sys/wasi/ext/fs.rs | 8 +- src/libstd/sys/wasi/ext/io.rs | 8 +- src/libstd/sys/wasi/fd.rs | 302 +++++++++++----------------------- src/libstd/sys/wasi/fs.rs | 176 +++++++++----------- src/libstd/sys/wasi/io.rs | 11 +- src/libstd/sys/wasi/mod.rs | 31 ++-- src/libstd/sys/wasi/os.rs | 29 +--- src/libstd/sys/wasi/stdio.rs | 11 +- src/libstd/sys/wasi/thread.rs | 4 +- src/libstd/sys/wasi/time.rs | 29 ++-- 11 files changed, 249 insertions(+), 376 deletions(-) diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs index 8b4b354d9fc20..679bb1b2cbe30 100644 --- a/src/libstd/sys/wasi/args.rs +++ b/src/libstd/sys/wasi/args.rs @@ -27,14 +27,24 @@ pub fn args() -> Args { }) } +fn cvt_wasi(r: u16) -> crate::io::Result<()> { + if r != 0 { + Err(Error::from_raw_os_error(r as i32)) + } else { + Ok(()) + } +} + fn maybe_args() -> io::Result { + // FIXME: replace with safe functions + use wasi::wasi_unstable::raw::{__wasi_args_sizes_get, __wasi_args_get}; unsafe { let (mut argc, mut argv_buf_size) = (0, 0); - cvt_wasi(libc::__wasi_args_sizes_get(&mut argc, &mut argv_buf_size))?; + cvt_wasi(__wasi_args_sizes_get(&mut argc, &mut argv_buf_size))?; - let mut argc = vec![core::ptr::null_mut::(); argc]; + let mut argc = vec![core::ptr::null_mut::(); argc]; let mut argv_buf = vec![0; argv_buf_size]; - cvt_wasi(libc::__wasi_args_get(argc.as_mut_ptr(), argv_buf.as_mut_ptr()))?; + cvt_wasi(__wasi_args_get(argc.as_mut_ptr(), argv_buf.as_mut_ptr()))?; let args = argc.into_iter() .map(|ptr| CStr::from_ptr(ptr).to_bytes().to_vec()) diff --git a/src/libstd/sys/wasi/ext/fs.rs b/src/libstd/sys/wasi/ext/fs.rs index 0ec4122f385da..ecd509f01dabd 100644 --- a/src/libstd/sys/wasi/ext/fs.rs +++ b/src/libstd/sys/wasi/ext/fs.rs @@ -336,16 +336,16 @@ pub trait FileTypeExt { impl FileTypeExt for fs::FileType { fn is_block_device(&self) -> bool { - self.as_inner().bits() == libc::__WASI_FILETYPE_BLOCK_DEVICE + self.as_inner().bits() == wasi::FILETYPE_BLOCK_DEVICE } fn is_character_device(&self) -> bool { - self.as_inner().bits() == libc::__WASI_FILETYPE_CHARACTER_DEVICE + self.as_inner().bits() == wasi::FILETYPE_CHARACTER_DEVICE } fn is_socket_dgram(&self) -> bool { - self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_DGRAM + self.as_inner().bits() == wasi::FILETYPE_SOCKET_DGRAM } fn is_socket_stream(&self) -> bool { - self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_STREAM + self.as_inner().bits() == wasi::FILETYPE_SOCKET_STREAM } } diff --git a/src/libstd/sys/wasi/ext/io.rs b/src/libstd/sys/wasi/ext/io.rs index 12afd1d42dc19..c843144f0c406 100644 --- a/src/libstd/sys/wasi/ext/io.rs +++ b/src/libstd/sys/wasi/ext/io.rs @@ -8,6 +8,8 @@ use crate::sys; use crate::net; use crate::sys_common::{AsInner, FromInner, IntoInner}; +use wasi::wasi_unstable as wasi; + /// Raw file descriptors. pub type RawFd = u32; @@ -125,18 +127,18 @@ impl IntoRawFd for fs::File { impl AsRawFd for io::Stdin { fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO as u32 + wasi::STDIN_FD } } impl AsRawFd for io::Stdout { fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO as u32 + wasi::STDOUT_FD } } impl AsRawFd for io::Stderr { fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO as u32 + wasi::STDERR_FD } } diff --git a/src/libstd/sys/wasi/fd.rs b/src/libstd/sys/wasi/fd.rs index 25692ec086801..93fe8add326c8 100644 --- a/src/libstd/sys/wasi/fd.rs +++ b/src/libstd/sys/wasi/fd.rs @@ -3,348 +3,240 @@ use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::net::Shutdown; -use crate::sys::cvt_wasi; -use libc::{self, c_char, c_void}; +use wasi::wasi_unstable as wasi; #[derive(Debug)] pub struct WasiFd { - fd: libc::__wasi_fd_t, + fd: wasi::Fd, } -// FIXME: these should probably all be fancier structs, builders, enums, etc -pub type LookupFlags = u32; -pub type FdFlags = u16; -pub type Advice = u8; -pub type Rights = u64; -pub type Oflags = u16; -pub type DirCookie = u64; -pub type Timestamp = u64; -pub type FstFlags = u16; -pub type RiFlags = u16; -pub type RoFlags = u16; -pub type SiFlags = u16; - -fn iovec(a: &mut [IoSliceMut<'_>]) -> (*const libc::__wasi_iovec_t, usize) { +fn iovec(a: &mut [IoSliceMut<'_>]) -> &[wasi::IoVec] { assert_eq!( mem::size_of::>(), - mem::size_of::() + mem::size_of::() ); assert_eq!( mem::align_of::>(), - mem::align_of::() + mem::align_of::() ); - (a.as_ptr() as *const libc::__wasi_iovec_t, a.len()) + /// SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout + unsafe { mem::transmute(a) } } -fn ciovec(a: &[IoSlice<'_>]) -> (*const libc::__wasi_ciovec_t, usize) { +fn ciovec(a: &[IoSlice<'_>]) -> &[wasi::CIoVec] { assert_eq!( mem::size_of::>(), - mem::size_of::() + mem::size_of::() ); assert_eq!( mem::align_of::>(), - mem::align_of::() + mem::align_of::() ); - (a.as_ptr() as *const libc::__wasi_ciovec_t, a.len()) + /// SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout + unsafe { mem::transmute(a) } } impl WasiFd { - pub unsafe fn from_raw(fd: libc::__wasi_fd_t) -> WasiFd { + pub unsafe fn from_raw(fd: wasi::Fd) -> WasiFd { WasiFd { fd } } - pub fn into_raw(self) -> libc::__wasi_fd_t { + pub fn into_raw(self) -> wasi::Fd { let ret = self.fd; mem::forget(self); ret } - pub fn as_raw(&self) -> libc::__wasi_fd_t { + pub fn as_raw(&self) -> wasi::Fd { self.fd } pub fn datasync(&self) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_datasync(self.fd) }) + wasi::fd_datasync(self.fd).map_err(From::from) } pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - let mut read = 0; - let (ptr, len) = iovec(bufs); - cvt_wasi(unsafe { libc::__wasi_fd_pread(self.fd, ptr, len, offset, &mut read) })?; - Ok(read) + wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(From::from) } pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - let mut read = 0; - let (ptr, len) = ciovec(bufs); - cvt_wasi(unsafe { libc::__wasi_fd_pwrite(self.fd, ptr, len, offset, &mut read) })?; - Ok(read) + wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(From::from) } pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - let mut read = 0; - let (ptr, len) = iovec(bufs); - cvt_wasi(unsafe { libc::__wasi_fd_read(self.fd, ptr, len, &mut read) })?; - Ok(read) + wasi::fd_read(self.fd, iovec(bufs)).map_err(From::from) } pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result { - let mut read = 0; - let (ptr, len) = ciovec(bufs); - cvt_wasi(unsafe { libc::__wasi_fd_write(self.fd, ptr, len, &mut read) })?; - Ok(read) + wasi::fd_write(self.fd, ciovec(bufs)).map_err(From::from) } pub fn seek(&self, pos: SeekFrom) -> io::Result { let (whence, offset) = match pos { - SeekFrom::Start(pos) => (libc::__WASI_WHENCE_SET, pos as i64), - SeekFrom::End(pos) => (libc::__WASI_WHENCE_END, pos), - SeekFrom::Current(pos) => (libc::__WASI_WHENCE_CUR, pos), + SeekFrom::Start(pos) => (wasi::WHENCE_SET, pos as i64), + SeekFrom::End(pos) => (wasi::WHENCE_END, pos), + SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos), }; - let mut pos = 0; - cvt_wasi(unsafe { libc::__wasi_fd_seek(self.fd, offset, whence, &mut pos) })?; - Ok(pos) + wasi::fd_seek(self.fd, offset, whence).map_err(From::from) } pub fn tell(&self) -> io::Result { - let mut pos = 0; - cvt_wasi(unsafe { libc::__wasi_fd_tell(self.fd, &mut pos) })?; - Ok(pos) + wasi::fd_tell(self.fd).map_err(From::from) } // FIXME: __wasi_fd_fdstat_get - pub fn set_flags(&self, flags: FdFlags) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_flags(self.fd, flags) }) + pub fn set_flags(&self, flags: wasi::FdFlags) -> io::Result<()> { + wasi::fd_fdstat_set_flags(self.fd, flags).map_err(From::from) } - pub fn set_rights(&self, base: Rights, inheriting: Rights) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_rights(self.fd, base, inheriting) }) + pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> { + wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(From::from) } pub fn sync(&self) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_sync(self.fd) }) + wasi::fd_sync(self.fd).map_err(From::from) } - pub fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_advise(self.fd, offset, len, advice as u8) }) + pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> { + wasi::fd_advise(self.fd, offset, len, advice).map_err(From::from) } pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_allocate(self.fd, offset, len) }) + wasi::fd_allocate(self.fd, offset, len).map_err(From::from) } pub fn create_directory(&self, path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_create_directory(self.fd, path.as_ptr() as *const c_char, path.len()) - }) + wasi::path_create_directory(self.fd, path).map_err(From::from) } pub fn link( &self, - old_flags: LookupFlags, + old_flags: wasi::LookupFlags, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8], ) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_link( - self.fd, - old_flags, - old_path.as_ptr() as *const c_char, - old_path.len(), - new_fd.fd, - new_path.as_ptr() as *const c_char, - new_path.len(), - ) - }) + wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path) + .map_err(From::from) } pub fn open( &self, - dirflags: LookupFlags, + dirflags: wasi::LookupFlags, path: &[u8], - oflags: Oflags, - fs_rights_base: Rights, - fs_rights_inheriting: Rights, - fs_flags: FdFlags, + oflags: wasi::OFlags, + fs_rights_base: wasi::Rights, + fs_rights_inheriting: wasi::Rights, + fs_flags: wasi::FdFlags, ) -> io::Result { - unsafe { - let mut fd = 0; - cvt_wasi(libc::__wasi_path_open( - self.fd, - dirflags, - path.as_ptr() as *const c_char, - path.len(), - oflags, - fs_rights_base, - fs_rights_inheriting, - fs_flags, - &mut fd, - ))?; - Ok(WasiFd::from_raw(fd)) - } - } - - pub fn readdir(&self, buf: &mut [u8], cookie: DirCookie) -> io::Result { - let mut used = 0; - cvt_wasi(unsafe { - libc::__wasi_fd_readdir( - self.fd, - buf.as_mut_ptr() as *mut c_void, - buf.len(), - cookie, - &mut used, - ) - })?; - Ok(used) + let fd = wasi_path_open( + self.fd, + dirflags, + path, + oflags, + fs_rights_base, + fs_rights_inheriting, + fs_flags, + )?; + Ok(WasiFd::from_raw(fd)) + } + + pub fn readdir(&self, buf: &mut [u8], cookie: wasi::DirCookie) -> io::Result { + wasi::fd_readdir(self.fd, buf, cookie).map_err(From::from) } pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result { - let mut used = 0; - cvt_wasi(unsafe { - libc::__wasi_path_readlink( - self.fd, - path.as_ptr() as *const c_char, - path.len(), - buf.as_mut_ptr() as *mut c_char, - buf.len(), - &mut used, - ) - })?; - Ok(used) + wasi::path_readlink(self.fd, path, buf).map_err(From::from) } pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_rename( - self.fd, - old_path.as_ptr() as *const c_char, - old_path.len(), - new_fd.fd, - new_path.as_ptr() as *const c_char, - new_path.len(), - ) - }) + wasi::path_rename(self.fd, old_path, new_fd.fd, new_path) + .map_err(From::from) } - pub fn filestat_get(&self, buf: *mut libc::__wasi_filestat_t) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_filestat_get(self.fd, buf) }) + pub fn filestat_get(&self) -> io::Result { + wasi::fd_filestat_get(self.fd, buf).map_err(From::from) } pub fn filestat_set_times( &self, - atim: Timestamp, - mtim: Timestamp, - fstflags: FstFlags, + atim: wasi::Timestamp, + mtim: wasi::Timestamp, + fstflags: wasi::FstFlags, ) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_times(self.fd, atim, mtim, fstflags) }) + wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags) + .map_err(From::from) } pub fn filestat_set_size(&self, size: u64) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_size(self.fd, size) }) + wasi::fd_filestat_set_size(self.fd, size).map_err(From::from) } pub fn path_filestat_get( &self, - flags: LookupFlags, + flags: wasi::LookupFlags, path: &[u8], - buf: *mut libc::__wasi_filestat_t, - ) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_filestat_get( - self.fd, - flags, - path.as_ptr() as *const c_char, - path.len(), - buf, - ) - }) + ) -> io::Result { + wasi::path_filestat_get(self.fd, flags, path).map_err(From::from) } pub fn path_filestat_set_times( &self, - flags: LookupFlags, + flags: wasi::LookupFlags, path: &[u8], - atim: Timestamp, - mtim: Timestamp, - fstflags: FstFlags, + atim: wasi::Timestamp, + mtim: wasi::Timestamp, + fstflags: wasi::FstFlags, ) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_filestat_set_times( - self.fd, - flags, - path.as_ptr() as *const c_char, - path.len(), - atim, - mtim, - fstflags, - ) - }) + wasi::path_filestat_set_times( + self.fd, + flags, + path, + atim, + mtim, + fstflags, + ).map_err(From::from) } pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_symlink( - old_path.as_ptr() as *const c_char, - old_path.len(), - self.fd, - new_path.as_ptr() as *const c_char, - new_path.len(), - ) - }) + wasi::path_symlink(old_path, self.fd, new_path).map_err(From::from) } pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_unlink_file(self.fd, path.as_ptr() as *const c_char, path.len()) - }) + wasi::path_unlink_file(self.fd, path).map_err(From::from) } pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_remove_directory(self.fd, path.as_ptr() as *const c_char, path.len()) - }) + wasi::path_remove_directory(self.fd, path).map_err(From::from) } pub fn sock_recv( &self, ri_data: &mut [IoSliceMut<'_>], - ri_flags: RiFlags, - ) -> io::Result<(usize, RoFlags)> { - let mut ro_datalen = 0; - let mut ro_flags = 0; - let (ptr, len) = iovec(ri_data); - cvt_wasi(unsafe { - libc::__wasi_sock_recv(self.fd, ptr, len, ri_flags, &mut ro_datalen, &mut ro_flags) - })?; - Ok((ro_datalen, ro_flags)) + ri_flags: wasi::RiFlags, + ) -> io::Result<(usize, wasi::RoFlags)> { + wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(From::from) } - pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: SiFlags) -> io::Result { - let mut so_datalen = 0; - let (ptr, len) = ciovec(si_data); - cvt_wasi(unsafe { libc::__wasi_sock_send(self.fd, ptr, len, si_flags, &mut so_datalen) })?; - Ok(so_datalen) + pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::SiFlags) -> io::Result { + wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(From::from) } pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> { let how = match how { - Shutdown::Read => libc::__WASI_SHUT_RD, - Shutdown::Write => libc::__WASI_SHUT_WR, - Shutdown::Both => libc::__WASI_SHUT_WR | libc::__WASI_SHUT_RD, + Shutdown::Read => WASI::SHUT_RD, + Shutdown::Write => WASI::SHUT_WR, + Shutdown::Both => WASI::SHUT_WR | WASI::SHUT_RD, }; - cvt_wasi(unsafe { libc::__wasi_sock_shutdown(self.fd, how) })?; - Ok(()) + wasi::sock_shutdown(self.fd, how).map_err(From::from) } } impl Drop for WasiFd { fn drop(&mut self) { - unsafe { - // FIXME: can we handle the return code here even though we can't on - // unix? - libc::__wasi_fd_close(self.fd); - } + // FIXME: can we handle the return code here even though we can't on + // unix? + let _ = wasi::fd_close(self.fd); } } diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs index 172c60385b317..f23ecfc2bcd22 100644 --- a/src/libstd/sys/wasi/fs.rs +++ b/src/libstd/sys/wasi/fs.rs @@ -15,13 +15,15 @@ use crate::sys_common::FromInner; pub use crate::sys_common::fs::copy; pub use crate::sys_common::fs::remove_dir_all; +use wasi::wasi_unstable as wasi; + pub struct File { fd: WasiFd, } #[derive(Clone)] pub struct FileAttr { - meta: libc::__wasi_filestat_t, + meta: wasi::FileStat, } pub struct ReadDir { @@ -38,7 +40,7 @@ struct ReadDirInner { } pub struct DirEntry { - meta: libc::__wasi_dirent_t, + meta: wasi::Dirent, name: Vec, inner: Arc, } @@ -47,11 +49,11 @@ pub struct DirEntry { pub struct OpenOptions { read: bool, write: bool, - dirflags: libc::__wasi_lookupflags_t, - fdflags: libc::__wasi_fdflags_t, - oflags: libc::__wasi_oflags_t, - rights_base: Option, - rights_inheriting: Option, + dirflags: wasi::LookupFlags, + fdflags: wasi::FdFlags, + oflags: wasi::OFlags, + rights_base: Option, + rights_inheriting: Option, } #[derive(Clone, PartialEq, Eq, Debug)] @@ -61,7 +63,7 @@ pub struct FilePermissions { #[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)] pub struct FileType { - bits: libc::__wasi_filetype_t, + bits: wasi::FileType, } #[derive(Debug)] @@ -101,7 +103,7 @@ impl FileAttr { Ok(SystemTime::from_wasi_timestamp(self.meta.st_ctim)) } - pub fn as_wasi(&self) -> &libc::__wasi_filestat_t { + pub fn as_wasi(&self) -> &wasi::FileStat { &self.meta } } @@ -118,18 +120,18 @@ impl FilePermissions { impl FileType { pub fn is_dir(&self) -> bool { - self.bits == libc::__WASI_FILETYPE_DIRECTORY + self.bits == wasi::FILETYPE_DIRECTORY } pub fn is_file(&self) -> bool { - self.bits == libc::__WASI_FILETYPE_REGULAR_FILE + self.bits == wasi::FILETYPE_REGULAR_FILE } pub fn is_symlink(&self) -> bool { - self.bits == libc::__WASI_FILETYPE_SYMBOLIC_LINK + self.bits == wasi::FILETYPE_SYMBOLIC_LINK } - pub fn bits(&self) -> libc::__wasi_filetype_t { + pub fn bits(&self) -> wasi::FileType { self.bits } } @@ -173,7 +175,7 @@ impl Iterator for ReadDir { // must have been truncated at the end of the buffer, so reset our // offset so we can go back and reread into the buffer, picking up // where we last left off. - let dirent_size = mem::size_of::(); + let dirent_size = mem::size_of::(); if data.len() < dirent_size { assert!(self.cookie.is_some()); assert!(self.buf.len() >= dirent_size); @@ -182,7 +184,7 @@ impl Iterator for ReadDir { } let (dirent, data) = data.split_at(dirent_size); let dirent = - unsafe { ptr::read_unaligned(dirent.as_ptr() as *const libc::__wasi_dirent_t) }; + unsafe { ptr::read_unaligned(dirent.as_ptr() as *const wasi::Dirent) }; // If the file name was truncated, then we need to reinvoke // `readdir` so we truncate our buffer to start over and reread this @@ -241,7 +243,7 @@ impl DirEntry { }) } - pub fn ino(&self) -> libc::__wasi_inode_t { + pub fn ino(&self) -> wasi::Inode { self.meta.d_ino } } @@ -249,7 +251,7 @@ impl DirEntry { impl OpenOptions { pub fn new() -> OpenOptions { let mut base = OpenOptions::default(); - base.dirflags = libc::__WASI_LOOKUP_SYMLINK_FOLLOW; + base.dirflags = wasi::LOOKUP_SYMLINK_FOLLOW; return base; } @@ -262,23 +264,23 @@ impl OpenOptions { } pub fn truncate(&mut self, truncate: bool) { - self.oflag(libc::__WASI_O_TRUNC, truncate); + self.oflag(wasi::O_TRUNC, truncate); } pub fn create(&mut self, create: bool) { - self.oflag(libc::__WASI_O_CREAT, create); + self.oflag(wasi::O_CREAT, create); } pub fn create_new(&mut self, create_new: bool) { - self.oflag(libc::__WASI_O_EXCL, create_new); - self.oflag(libc::__WASI_O_CREAT, create_new); + self.oflag(wasi::O_EXCL, create_new); + self.oflag(wasi::O_CREAT, create_new); } pub fn directory(&mut self, directory: bool) { - self.oflag(libc::__WASI_O_DIRECTORY, directory); + self.oflag(wasi::O_DIRECTORY, directory); } - fn oflag(&mut self, bit: libc::__wasi_oflags_t, set: bool) { + fn oflag(&mut self, bit: wasi::OFlags, set: bool) { if set { self.oflags |= bit; } else { @@ -287,26 +289,26 @@ impl OpenOptions { } pub fn append(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_APPEND, set); + self.fdflag(wasi::FDFLAG_APPEND, set); } pub fn dsync(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_DSYNC, set); + self.fdflag(wasi::FDFLAG_DSYNC, set); } pub fn nonblock(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_NONBLOCK, set); + self.fdflag(wasi::FDFLAG_NONBLOCK, set); } pub fn rsync(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_RSYNC, set); + self.fdflag(wasi::FDFLAG_RSYNC, set); } pub fn sync(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_SYNC, set); + self.fdflag(wasi::FDFLAG_SYNC, set); } - fn fdflag(&mut self, bit: libc::__wasi_fdflags_t, set: bool) { + fn fdflag(&mut self, bit: wasi::FdFlags, set: bool) { if set { self.fdflags |= bit; } else { @@ -314,15 +316,15 @@ impl OpenOptions { } } - pub fn fs_rights_base(&mut self, rights: libc::__wasi_rights_t) { + pub fn fs_rights_base(&mut self, rights: wasi::Rights) { self.rights_base = Some(rights); } - pub fn fs_rights_inheriting(&mut self, rights: libc::__wasi_rights_t) { + pub fn fs_rights_inheriting(&mut self, rights: wasi::Rights) { self.rights_inheriting = Some(rights); } - fn rights_base(&self) -> libc::__wasi_rights_t { + fn rights_base(&self) -> wasi::Rights { if let Some(rights) = self.rights_base { return rights; } @@ -334,52 +336,52 @@ impl OpenOptions { // based on that. let mut base = 0; if self.read { - base |= libc::__WASI_RIGHT_FD_READ; - base |= libc::__WASI_RIGHT_FD_READDIR; + base |= wasi::RIGHT_FD_READ; + base |= wasi::RIGHT_FD_READDIR; } if self.write { - base |= libc::__WASI_RIGHT_FD_WRITE; - base |= libc::__WASI_RIGHT_FD_DATASYNC; - base |= libc::__WASI_RIGHT_FD_ALLOCATE; - base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_SIZE; + base |= wasi::RIGHT_FD_WRITE; + base |= wasi::RIGHT_FD_DATASYNC; + base |= wasi::RIGHT_FD_ALLOCATE; + base |= wasi::RIGHT_FD_FILESTAT_SET_SIZE; } // FIXME: some of these should probably be read-only or write-only... - base |= libc::__WASI_RIGHT_FD_ADVISE; - base |= libc::__WASI_RIGHT_FD_FDSTAT_SET_FLAGS; - base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_TIMES; - base |= libc::__WASI_RIGHT_FD_SEEK; - base |= libc::__WASI_RIGHT_FD_SYNC; - base |= libc::__WASI_RIGHT_FD_TELL; - base |= libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY; - base |= libc::__WASI_RIGHT_PATH_CREATE_FILE; - base |= libc::__WASI_RIGHT_PATH_FILESTAT_GET; - base |= libc::__WASI_RIGHT_PATH_LINK_SOURCE; - base |= libc::__WASI_RIGHT_PATH_LINK_TARGET; - base |= libc::__WASI_RIGHT_PATH_OPEN; - base |= libc::__WASI_RIGHT_PATH_READLINK; - base |= libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY; - base |= libc::__WASI_RIGHT_PATH_RENAME_SOURCE; - base |= libc::__WASI_RIGHT_PATH_RENAME_TARGET; - base |= libc::__WASI_RIGHT_PATH_SYMLINK; - base |= libc::__WASI_RIGHT_PATH_UNLINK_FILE; - base |= libc::__WASI_RIGHT_POLL_FD_READWRITE; + base |= wasi::RIGHT_FD_ADVISE; + base |= wasi::RIGHT_FD_FDSTAT_SET_FLAGS; + base |= wasi::RIGHT_FD_FILESTAT_SET_TIMES; + base |= wasi::RIGHT_FD_SEEK; + base |= wasi::RIGHT_FD_SYNC; + base |= wasi::RIGHT_FD_TELL; + base |= wasi::RIGHT_PATH_CREATE_DIRECTORY; + base |= wasi::RIGHT_PATH_CREATE_FILE; + base |= wasi::RIGHT_PATH_FILESTAT_GET; + base |= wasi::RIGHT_PATH_LINK_SOURCE; + base |= wasi::RIGHT_PATH_LINK_TARGET; + base |= wasi::RIGHT_PATH_OPEN; + base |= wasi::RIGHT_PATH_READLINK; + base |= wasi::RIGHT_PATH_REMOVE_DIRECTORY; + base |= wasi::RIGHT_PATH_RENAME_SOURCE; + base |= wasi::RIGHT_PATH_RENAME_TARGET; + base |= wasi::RIGHT_PATH_SYMLINK; + base |= wasi::RIGHT_PATH_UNLINK_FILE; + base |= wasi::RIGHT_POLL_FD_READWRITE; return base; } - fn rights_inheriting(&self) -> libc::__wasi_rights_t { + fn rights_inheriting(&self) -> wasi::Rights { self.rights_inheriting.unwrap_or_else(|| self.rights_base()) } - pub fn lookup_flags(&mut self, flags: libc::__wasi_lookupflags_t) { + pub fn lookup_flags(&mut self, flags: wasi::LookupFlags) { self.dirflags = flags; } } impl File { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result { - let (dir, file) = open_parent(path, libc::__WASI_RIGHT_PATH_OPEN)?; + let (dir, file) = open_parent(path, wasi::RIGHT_PATH_OPEN)?; open_at(&dir, &file, opts) } @@ -388,14 +390,12 @@ impl File { } pub fn file_attr(&self) -> io::Result { - let mut ret = FileAttr::zero(); - self.fd.filestat_get(&mut ret.meta)?; - Ok(ret) + self.fd.filestat_get().map_ok(|meta| FileAttr { meta }) } pub fn metadata_at( &self, - flags: libc::__wasi_lookupflags_t, + flags: wasi::LookupFlags, path: &Path, ) -> io::Result { metadata_at(&self.fd, flags, path) @@ -477,7 +477,7 @@ impl DirBuilder { } pub fn mkdir(&self, p: &Path) -> io::Result<()> { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_CREATE_DIRECTORY)?; dir.create_directory(file.as_os_str().as_bytes()) } } @@ -508,13 +508,13 @@ pub fn readdir(p: &Path) -> io::Result { } pub fn unlink(p: &Path) -> io::Result<()> { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_UNLINK_FILE)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_UNLINK_FILE)?; dir.unlink_file(file.as_os_str().as_bytes()) } pub fn rename(old: &Path, new: &Path) -> io::Result<()> { - let (old, old_file) = open_parent(old, libc::__WASI_RIGHT_PATH_RENAME_SOURCE)?; - let (new, new_file) = open_parent(new, libc::__WASI_RIGHT_PATH_RENAME_TARGET)?; + let (old, old_file) = open_parent(old, wasi::RIGHT_PATH_RENAME_SOURCE)?; + let (new, new_file) = open_parent(new, wasi::RIGHT_PATH_RENAME_TARGET)?; old.rename( old_file.as_os_str().as_bytes(), &new, @@ -529,12 +529,12 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { } pub fn rmdir(p: &Path) -> io::Result<()> { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_REMOVE_DIRECTORY)?; dir.remove_directory(file.as_os_str().as_bytes()) } pub fn readlink(p: &Path) -> io::Result { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_READLINK)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_READLINK)?; read_link(&dir, &file) } @@ -570,15 +570,15 @@ fn read_link(fd: &WasiFd, file: &Path) -> io::Result { } pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { - let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_SYMLINK)?; + let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_SYMLINK)?; dst.symlink(src.as_os_str().as_bytes(), dst_file.as_os_str().as_bytes()) } pub fn link(src: &Path, dst: &Path) -> io::Result<()> { - let (src, src_file) = open_parent(src, libc::__WASI_RIGHT_PATH_LINK_SOURCE)?; - let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_LINK_TARGET)?; + let (src, src_file) = open_parent(src, wasi::RIGHT_PATH_LINK_SOURCE)?; + let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_LINK_TARGET)?; src.link( - libc::__WASI_LOOKUP_SYMLINK_FOLLOW, + wasi::LOOKUP_SYMLINK_FOLLOW, src_file.as_os_str().as_bytes(), &dst, dst_file.as_os_str().as_bytes(), @@ -586,23 +586,22 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> { } pub fn stat(p: &Path) -> io::Result { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?; - metadata_at(&dir, libc::__WASI_LOOKUP_SYMLINK_FOLLOW, &file) + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?; + metadata_at(&dir, wasi::LOOKUP_SYMLINK_FOLLOW, &file) } pub fn lstat(p: &Path) -> io::Result { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?; metadata_at(&dir, 0, &file) } fn metadata_at( fd: &WasiFd, - flags: libc::__wasi_lookupflags_t, + flags: wasi::LookupFlags, path: &Path, ) -> io::Result { - let mut ret = FileAttr::zero(); - fd.path_filestat_get(flags, path.as_os_str().as_bytes(), &mut ret.meta)?; - Ok(ret) + fd.path_filestat_get(flags, path.as_os_str().as_bytes()) + .map_ok(|meta| FileAttr { meta }) } pub fn canonicalize(_p: &Path) -> io::Result { @@ -652,12 +651,12 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result { /// to any preopened file descriptor. fn open_parent( p: &Path, - rights: libc::__wasi_rights_t, + rights: wasi::Rights, ) -> io::Result<(ManuallyDrop, PathBuf)> { let p = CString::new(p.as_os_str().as_bytes())?; unsafe { let mut ret = ptr::null(); - let fd = __wasilibc_find_relpath(p.as_ptr(), rights, 0, &mut ret); + let fd = libc::__wasilibc_find_relpath(p.as_ptr(), rights, 0, &mut ret); if fd == -1 { let msg = format!( "failed to find a preopened file descriptor \ @@ -677,15 +676,4 @@ fn open_parent( return Ok((ManuallyDrop::new(WasiFd::from_raw(fd as u32)), path)); } - - // FIXME(rust-lang/libc#1314) use the `libc` crate for this when the API - // there is published - extern "C" { - pub fn __wasilibc_find_relpath( - path: *const libc::c_char, - rights_base: libc::__wasi_rights_t, - rights_inheriting: libc::__wasi_rights_t, - relative_path: *mut *const libc::c_char, - ) -> libc::c_int; - } } diff --git a/src/libstd/sys/wasi/io.rs b/src/libstd/sys/wasi/io.rs index ffecca5d1b6ff..ebea3a03e439f 100644 --- a/src/libstd/sys/wasi/io.rs +++ b/src/libstd/sys/wasi/io.rs @@ -1,11 +1,12 @@ use crate::marker::PhantomData; use crate::slice; -use libc::{__wasi_ciovec_t, __wasi_iovec_t, c_void}; +use wasi::wasi_unstable as wasi; +use core::ffi::c_void; #[repr(transparent)] pub struct IoSlice<'a> { - vec: __wasi_ciovec_t, + vec: wasi::CIoVec, _p: PhantomData<&'a [u8]>, } @@ -13,7 +14,7 @@ impl<'a> IoSlice<'a> { #[inline] pub fn new(buf: &'a [u8]) -> IoSlice<'a> { IoSlice { - vec: __wasi_ciovec_t { + vec: wasi::CIoVec { buf: buf.as_ptr() as *const c_void, buf_len: buf.len(), }, @@ -43,7 +44,7 @@ impl<'a> IoSlice<'a> { #[repr(transparent)] pub struct IoSliceMut<'a> { - vec: __wasi_iovec_t, + vec: wasi::IoVec, _p: PhantomData<&'a mut [u8]>, } @@ -51,7 +52,7 @@ impl<'a> IoSliceMut<'a> { #[inline] pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { IoSliceMut { - vec: __wasi_iovec_t { + vec: wasi::IoVec { buf: buf.as_mut_ptr() as *mut c_void, buf_len: buf.len() }, diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs index f842869e08ee6..0a16c29e5af53 100644 --- a/src/libstd/sys/wasi/mod.rs +++ b/src/libstd/sys/wasi/mod.rs @@ -14,10 +14,10 @@ //! compiling for wasm. That way it's a compile time error for something that's //! guaranteed to be a runtime error! -use libc; -use crate::io::{Error, ErrorKind}; +use crate::io; use crate::mem; use crate::os::raw::c_char; +use wasi::wasi_unstable as wasi; pub mod alloc; pub mod args; @@ -60,12 +60,12 @@ pub fn unsupported() -> crate::io::Result { Err(unsupported_err()) } -pub fn unsupported_err() -> Error { - Error::new(ErrorKind::Other, "operation not supported on wasm yet") +pub fn unsupported_err() -> io::Error { + io::Error::new(io::ErrorKind::Other, "operation not supported on wasm yet") } -pub fn decode_error_kind(_code: i32) -> ErrorKind { - ErrorKind::Other +pub fn decode_error_kind(_code: i32) -> io::ErrorKind { + io::ErrorKind::Other } // This enum is used as the storage for a bunch of types which can't actually @@ -83,15 +83,18 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize { } pub unsafe fn abort_internal() -> ! { - libc::abort() + wasi::proc_exit(127) } pub fn hashmap_random_keys() -> (u64, u64) { let mut ret = (0u64, 0u64); unsafe { - let base = &mut ret as *mut (u64, u64) as *mut libc::c_void; + let base = &mut ret as *mut (u64, u64) as *mut core::ffi::c_void; let len = mem::size_of_val(&ret); - cvt_wasi(libc::__wasi_random_get(base, len)).unwrap(); + let ret = wasi::raw::__wasi_random_get(base, len); + if ret != 0 { + panic!("__wasi_random_get failure") + } } return ret } @@ -113,16 +116,14 @@ impl_is_minus_one! { i8 i16 i32 i64 isize } pub fn cvt(t: T) -> crate::io::Result { if t.is_minus_one() { - Err(Error::last_os_error()) + Err(io::Error::last_os_error()) } else { Ok(t) } } -pub fn cvt_wasi(r: u16) -> crate::io::Result<()> { - if r != libc::__WASI_ESUCCESS { - Err(Error::from_raw_os_error(r as i32)) - } else { - Ok(()) +impl From for io::Error { + fn from(err: wasi::Error) -> Self { + Self::from_raw_os_error(err as i32) } } diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs index 822ea02a11b89..026ff71de345b 100644 --- a/src/libstd/sys/wasi/os.rs +++ b/src/libstd/sys/wasi/os.rs @@ -12,6 +12,8 @@ use crate::sys::memchr; use crate::sys::{cvt, unsupported, Void}; use crate::vec; +use wasi::wasi_unstable as wasi; + #[cfg(not(target_feature = "atomics"))] pub unsafe fn env_lock() -> impl Any { // No need for a lock if we're single-threaded, but this function will need @@ -19,29 +21,11 @@ pub unsafe fn env_lock() -> impl Any { } pub fn errno() -> i32 { - extern { - #[thread_local] - static errno: libc::c_int; - } - - unsafe { errno as i32 } + panic!("unsupported") } pub fn error_string(errno: i32) -> String { - extern { - fn strerror_r(errnum: libc::c_int, buf: *mut libc::c_char, - buflen: libc::size_t) -> libc::c_int; - } - - let mut buf = [0 as libc::c_char; 1024]; - - let p = buf.as_mut_ptr(); - unsafe { - if strerror_r(errno as libc::c_int, p, buf.len()) < 0 { - panic!("strerror_r failure"); - } - str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned() - } + wasi::error_string(errno).to_string() } pub fn getcwd() -> io::Result { @@ -105,6 +89,7 @@ impl Iterator for Env { pub fn env() -> Env { unsafe { let _guard = env_lock(); + // FIXME: replace with wasi::environ_get let mut environ = libc::environ; let mut result = Vec::new(); while environ != ptr::null_mut() && *environ != ptr::null_mut() { @@ -174,9 +159,7 @@ pub fn home_dir() -> Option { } pub fn exit(code: i32) -> ! { - unsafe { - libc::exit(code) - } + unsafe { wasi::proc_exit(code as u32) } } pub fn getpid() -> u32 { diff --git a/src/libstd/sys/wasi/stdio.rs b/src/libstd/sys/wasi/stdio.rs index 2bf8d803c01bb..dc6a6ef375a1c 100644 --- a/src/libstd/sys/wasi/stdio.rs +++ b/src/libstd/sys/wasi/stdio.rs @@ -1,8 +1,9 @@ use crate::io::{self, IoSlice, IoSliceMut}; -use crate::libc; use crate::mem::ManuallyDrop; use crate::sys::fd::WasiFd; +use wasi::wasi_unstable as wasi; + pub struct Stdin; pub struct Stdout; pub struct Stderr; @@ -17,7 +18,7 @@ impl Stdin { } pub fn read_vectored(&self, data: &mut [IoSliceMut<'_>]) -> io::Result { - ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDIN_FILENO as u32) }) + ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDIN_FD) }) .read(data) } } @@ -32,7 +33,7 @@ impl Stdout { } pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result { - ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDOUT_FILENO as u32) }) + ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDOUT_FD) }) .write(data) } @@ -51,7 +52,7 @@ impl Stderr { } pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result { - ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDERR_FILENO as u32) }) + ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDERR_FD) }) .write(data) } @@ -73,7 +74,7 @@ impl io::Write for Stderr { pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE; pub fn is_ebadf(err: &io::Error) -> bool { - err.raw_os_error() == Some(libc::__WASI_EBADF as i32) + err.raw_os_error() == Some(wasi::EBADF as i32) } pub fn panic_output() -> Option { diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index 5e69e4d948fee..9e0726432d9c4 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -19,8 +19,8 @@ impl Thread { } pub fn yield_now() { - let ret = unsafe { libc::__wasi_sched_yield() }; - debug_assert_eq!(ret, 0); + let ret = wasi::sched_yield(); + debug_assert_eq!(ret, Ok(())); } pub fn set_name(_name: &CStr) { diff --git a/src/libstd/sys/wasi/time.rs b/src/libstd/sys/wasi/time.rs index 3f14c80928c67..4c89a1781b9ef 100644 --- a/src/libstd/sys/wasi/time.rs +++ b/src/libstd/sys/wasi/time.rs @@ -1,7 +1,6 @@ use crate::time::Duration; use crate::mem; -use crate::sys::cvt_wasi; -use libc; +use wasi::wasi_unstable as wasi; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant(Duration); @@ -12,23 +11,19 @@ pub struct SystemTime(Duration); pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); fn current_time(clock: u32) -> Duration { - unsafe { - let mut ts = mem::zeroed(); - cvt_wasi(libc::__wasi_clock_time_get( - clock, - 1, // precision... seems ignored though? - &mut ts, - )).unwrap(); - Duration::new( - (ts / 1_000_000_000) as u64, - (ts % 1_000_000_000) as u32, - ) - } + let ts = wasi::clock_time_get( + clock, + 1, // precision... seems ignored though? + ).unwrap(); + Duration::new( + (ts / 1_000_000_000) as u64, + (ts % 1_000_000_000) as u32, + ) } impl Instant { pub fn now() -> Instant { - Instant(current_time(libc::__WASI_CLOCK_MONOTONIC)) + Instant(current_time(wasi::CLOCK_MONOTONIC)) } pub const fn zero() -> Instant { @@ -54,10 +49,10 @@ impl Instant { impl SystemTime { pub fn now() -> SystemTime { - SystemTime(current_time(libc::__WASI_CLOCK_REALTIME)) + SystemTime(current_time(wasi::CLOCK_REALTIME)) } - pub fn from_wasi_timestamp(ts: libc::__wasi_timestamp_t) -> SystemTime { + pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime { SystemTime(Duration::from_nanos(ts)) } From 23cc850ff18652c7b75fa423f9dfff5526a239a7 Mon Sep 17 00:00:00 2001 From: newpavlov Date: Mon, 19 Aug 2019 10:44:08 +0300 Subject: [PATCH 023/618] return 0 from errno function --- src/libstd/sys/wasi/os.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs index 026ff71de345b..8411878eeccd9 100644 --- a/src/libstd/sys/wasi/os.rs +++ b/src/libstd/sys/wasi/os.rs @@ -21,7 +21,7 @@ pub unsafe fn env_lock() -> impl Any { } pub fn errno() -> i32 { - panic!("unsupported") + 0 } pub fn error_string(errno: i32) -> String { From b78367d8e8c3273b2cdeefc4ce55897e08e592b2 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 21 Jun 2019 12:23:05 +0900 Subject: [PATCH 024/618] Support `impl Trait` in inlined documentation --- src/librustdoc/clean/inline.rs | 9 +- src/librustdoc/clean/mod.rs | 91 +++++++++++++++---- src/librustdoc/core.rs | 24 ++++- .../inline_cross/auxiliary/impl_trait_aux.rs | 7 ++ src/test/rustdoc/inline_cross/impl_trait.rs | 13 +++ 5 files changed, 122 insertions(+), 22 deletions(-) create mode 100644 src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs create mode 100644 src/test/rustdoc/inline_cross/impl_trait.rs diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 6f93c95edef08..bcabefa51fab1 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -217,8 +217,9 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function { }; let predicates = cx.tcx.predicates_of(did); - let generics = (cx.tcx.generics_of(did), &predicates).clean(cx); - let decl = (did, sig).clean(cx); + let (generics, decl) = clean::enter_impl_trait(cx, || { + ((cx.tcx.generics_of(did), &predicates).clean(cx), (did, sig).clean(cx)) + }); let (all_types, ret_types) = clean::get_all_types(&generics, &decl, cx); clean::Function { decl, @@ -372,7 +373,9 @@ pub fn build_impl(cx: &DocContext<'_>, did: DefId, attrs: Option>, None } }).collect::>(), - (tcx.generics_of(did), &predicates).clean(cx), + clean::enter_impl_trait(cx, || { + (tcx.generics_of(did), &predicates).clean(cx) + }), ) }; let polarity = tcx.impl_polarity(did); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9b4803ce41e29..d3065f1679316 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -45,7 +45,7 @@ use std::cell::RefCell; use std::sync::Arc; use std::u32; -use crate::core::{self, DocContext}; +use crate::core::{self, DocContext, ImplTraitParam}; use crate::doctree; use crate::html::render::{cache, ExternalLocation}; use crate::html::item_type::ItemType; @@ -1540,7 +1540,7 @@ impl Clean for ty::GenericParamDef { ty::GenericParamDefKind::Lifetime => { (self.name.to_string(), GenericParamDefKind::Lifetime) } - ty::GenericParamDefKind::Type { has_default, .. } => { + ty::GenericParamDefKind::Type { has_default, synthetic, .. } => { cx.renderinfo.borrow_mut().external_param_names .insert(self.def_id, self.name.clean(cx)); let default = if has_default { @@ -1552,7 +1552,7 @@ impl Clean for ty::GenericParamDef { did: self.def_id, bounds: vec![], // These are filled in from the where-clauses. default, - synthetic: None, + synthetic, }) } ty::GenericParamDefKind::Const { .. } => { @@ -1641,7 +1641,7 @@ impl Clean for hir::Generics { match param.kind { GenericParamDefKind::Lifetime => unreachable!(), GenericParamDefKind::Type { did, ref bounds, .. } => { - cx.impl_trait_bounds.borrow_mut().insert(did, bounds.clone()); + cx.impl_trait_bounds.borrow_mut().insert(did.into(), bounds.clone()); } GenericParamDefKind::Const { .. } => unreachable!(), } @@ -1696,25 +1696,76 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, let (gens, preds) = *self; + // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses, + // since `Clean for ty::Predicate` would consume them. + let mut impl_trait = FxHashMap::>::default(); + // Bounds in the type_params and lifetimes fields are repeated in the // predicates field (see rustc_typeck::collect::ty_generics), so remove // them. - let stripped_typarams = gens.params.iter().filter_map(|param| match param.kind { - ty::GenericParamDefKind::Lifetime => None, - ty::GenericParamDefKind::Type { .. } => { - if param.name.as_symbol() == kw::SelfUpper { - assert_eq!(param.index, 0); - return None; + let stripped_typarams = gens.params.iter() + .filter_map(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => None, + ty::GenericParamDefKind::Type { synthetic, .. } => { + if param.name.as_symbol() == kw::SelfUpper { + assert_eq!(param.index, 0); + return None; + } + if synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) { + impl_trait.insert(param.index.into(), vec![]); + return None; + } + Some(param.clean(cx)) } - Some(param.clean(cx)) - } - ty::GenericParamDefKind::Const { .. } => None, - }).collect::>(); + ty::GenericParamDefKind::Const { .. } => None, + }).collect::>(); let mut where_predicates = preds.predicates.iter() - .flat_map(|(p, _)| p.clean(cx)) + .flat_map(|(p, _)| { + let param_idx = if let Some(trait_ref) = p.to_opt_poly_trait_ref() { + if let ty::Param(param) = trait_ref.self_ty().sty { + Some(param.index) + } else { + None + } + } else if let Some(outlives) = p.to_opt_type_outlives() { + if let ty::Param(param) = outlives.skip_binder().0.sty { + Some(param.index) + } else { + None + } + } else { + None + }; + + let p = p.clean(cx)?; + + if let Some(b) = param_idx.and_then(|i| impl_trait.get_mut(&i.into())) { + b.extend( + p.get_bounds() + .into_iter() + .flatten() + .cloned() + .filter(|b| !b.is_sized_bound(cx)) + ); + return None; + } + + Some(p) + }) .collect::>(); + // Move `TraitPredicate`s to the front. + for (_, bounds) in impl_trait.iter_mut() { + bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b { + false + } else { + true + }); + } + + cx.impl_trait_bounds.borrow_mut().extend(impl_trait); + // Type parameters and have a Sized bound by default unless removed with // ?Sized. Scan through the predicates and mark any type parameter with // a Sized bound, removing the bounds as we find them. @@ -2791,7 +2842,7 @@ impl Clean for hir::Ty { if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() { return new_ty; } - if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) { + if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) { return ImplTrait(bounds); } } @@ -3082,7 +3133,13 @@ impl<'tcx> Clean for Ty<'tcx> { ty::Projection(ref data) => data.clean(cx), - ty::Param(ref p) => Generic(p.name.to_string()), + ty::Param(ref p) => { + if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&p.index.into()) { + ImplTrait(bounds) + } else { + Generic(p.name.to_string()) + } + } ty::Opaque(def_id, substs) => { // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 87381f224d0bb..592a24fa4ae1a 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -61,8 +61,8 @@ pub struct DocContext<'tcx> { pub lt_substs: RefCell>, /// Table `DefId` of const parameter -> substituted const pub ct_substs: RefCell>, - /// Table DefId of `impl Trait` in argument position -> bounds - pub impl_trait_bounds: RefCell>>, + /// Table synthetic type parameter for `impl Trait` in argument position -> bounds + pub impl_trait_bounds: RefCell>>, pub fake_def_ids: RefCell>, pub all_fake_def_ids: RefCell>, /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`. @@ -459,3 +459,23 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt }) }) } + +/// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter +/// for `impl Trait` in argument position. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub enum ImplTraitParam { + DefId(DefId), + ParamIndex(u32), +} + +impl From for ImplTraitParam { + fn from(did: DefId) -> Self { + ImplTraitParam::DefId(did) + } +} + +impl From for ImplTraitParam { + fn from(idx: u32) -> Self { + ImplTraitParam::ParamIndex(idx) + } +} diff --git a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs new file mode 100644 index 0000000000000..7807acbc4d61d --- /dev/null +++ b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs @@ -0,0 +1,7 @@ +pub fn func<'a>(_x: impl Clone + Into> + 'a) {} + +pub struct Foo; + +impl Foo { + pub fn method<'a>(_x: impl Clone + Into> + 'a) {} +} diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs new file mode 100644 index 0000000000000..091baa9773ecf --- /dev/null +++ b/src/test/rustdoc/inline_cross/impl_trait.rs @@ -0,0 +1,13 @@ +// aux-build:impl_trait_aux.rs + +extern crate impl_trait_aux; + +// @has impl_trait/fn.func.html +// @has - '//pre[@class="rust fn"]' "pub fn func<'a>(_x: impl Clone + Into> + 'a)" +// @!has - '//pre[@class="rust fn"]' 'where' +pub use impl_trait_aux::func; + +// @has impl_trait/struct.Foo.html +// @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into> + 'a)" +// @!has - '//code[@id="method.v"]' 'where' +pub use impl_trait_aux::Foo; From 9beff38382a88ceafcb6e83636535c07eacad345 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 8 Jul 2019 17:59:26 +0900 Subject: [PATCH 025/618] Associated type bound for inlined impl Trait doc --- src/librustdoc/clean/mod.rs | 93 +++++++++++++----- src/librustdoc/clean/simplify.rs | 96 ++++++++++--------- .../inline_cross/auxiliary/impl_trait_aux.rs | 4 + src/test/rustdoc/inline_cross/impl_trait.rs | 6 ++ 4 files changed, 131 insertions(+), 68 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d3065f1679316..bde1826c7fd5a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1698,7 +1698,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses, // since `Clean for ty::Predicate` would consume them. - let mut impl_trait = FxHashMap::>::default(); + let mut impl_trait = FxHashMap::>::default(); // Bounds in the type_params and lifetimes fields are repeated in the // predicates field (see rustc_typeck::collect::ty_generics), so remove @@ -1720,41 +1720,73 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericParamDefKind::Const { .. } => None, }).collect::>(); + // (param index, def id of trait) -> (name, type) + let mut impl_trait_proj = FxHashMap::<(u32, DefId), Vec<(String, Type)>>::default(); + let mut where_predicates = preds.predicates.iter() .flat_map(|(p, _)| { - let param_idx = if let Some(trait_ref) = p.to_opt_poly_trait_ref() { - if let ty::Param(param) = trait_ref.self_ty().sty { - Some(param.index) - } else { - None - } - } else if let Some(outlives) = p.to_opt_type_outlives() { - if let ty::Param(param) = outlives.skip_binder().0.sty { - Some(param.index) - } else { - None + let param_idx = (|| { + if let Some(trait_ref) = p.to_opt_poly_trait_ref() { + if let ty::Param(param) = trait_ref.self_ty().sty { + return Some(param.index); + } + } else if let Some(outlives) = p.to_opt_type_outlives() { + if let ty::Param(param) = outlives.skip_binder().0.sty { + return Some(param.index); + } + } else if let ty::Predicate::Projection(proj) = p { + if let ty::Param(param) = proj.skip_binder().projection_ty.self_ty().sty { + return Some(param.index); + } } - } else { + None - }; + })(); let p = p.clean(cx)?; - if let Some(b) = param_idx.and_then(|i| impl_trait.get_mut(&i.into())) { - b.extend( - p.get_bounds() - .into_iter() - .flatten() - .cloned() - .filter(|b| !b.is_sized_bound(cx)) - ); - return None; + if let Some(param_idx) = param_idx { + if let Some(b) = impl_trait.get_mut(¶m_idx.into()) { + b.extend( + p.get_bounds() + .into_iter() + .flatten() + .cloned() + .filter(|b| !b.is_sized_bound(cx)) + ); + + let proj = match &p { + WherePredicate::EqPredicate { lhs, rhs } => Some((lhs, rhs)) + .and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs))), + _ => None, + }; + if let Some(((_, trait_did, name), rhs)) = proj { + impl_trait_proj + .entry((param_idx, trait_did)) + .or_default() + .push((name.to_string(), rhs.clone())); + } + + return None; + } } Some(p) }) .collect::>(); + for ((param_idx, trait_did), bounds) in impl_trait_proj { + for (name, rhs) in bounds { + simplify::merge_bounds( + cx, + impl_trait.get_mut(¶m_idx.into()).unwrap(), + trait_did, + &name, + &rhs, + ); + } + } + // Move `TraitPredicate`s to the front. for (_, bounds) in impl_trait.iter_mut() { bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b { @@ -2664,6 +2696,21 @@ impl Type { _ => false, } } + + pub fn projection(&self) -> Option<(&Type, DefId, &str)> { + let (self_, trait_, name) = match self { + QPath { ref self_type, ref trait_, ref name } => { + (self_type, trait_, name) + } + _ => return None, + }; + let trait_did = match **trait_ { + ResolvedPath { did, .. } => did, + _ => return None, + }; + Some((&self_, trait_did, name)) + } + } impl GetDefId for Type { diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 3801c42307fc6..8758ab1969116 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -53,58 +53,21 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> Vec { // Look for equality predicates on associated types that can be merged into // general bound predicates equalities.retain(|&(ref lhs, ref rhs)| { - let (self_, trait_, name) = match *lhs { - clean::QPath { ref self_type, ref trait_, ref name } => { - (self_type, trait_, name) - } - _ => return true, - }; - let generic = match **self_ { - clean::Generic(ref s) => s, - _ => return true, + let (self_, trait_did, name) = if let Some(p) = lhs.projection() { + p + } else { + return true; }; - let trait_did = match **trait_ { - clean::ResolvedPath { did, .. } => did, + let generic = match self_ { + clean::Generic(s) => s, _ => return true, }; let bounds = match params.get_mut(generic) { Some(bound) => bound, None => return true, }; - !bounds.iter_mut().any(|b| { - let trait_ref = match *b { - clean::GenericBound::TraitBound(ref mut tr, _) => tr, - clean::GenericBound::Outlives(..) => return false, - }; - let (did, path) = match trait_ref.trait_ { - clean::ResolvedPath { did, ref mut path, ..} => (did, path), - _ => return false, - }; - // If this QPath's trait `trait_did` is the same as, or a supertrait - // of, the bound's trait `did` then we can keep going, otherwise - // this is just a plain old equality bound. - if !trait_is_same_or_supertrait(cx, did, trait_did) { - return false - } - let last = path.segments.last_mut().expect("segments were empty"); - match last.args { - PP::AngleBracketed { ref mut bindings, .. } => { - bindings.push(clean::TypeBinding { - name: name.clone(), - kind: clean::TypeBindingKind::Equality { - ty: rhs.clone(), - }, - }); - } - PP::Parenthesized { ref mut output, .. } => { - assert!(output.is_none()); - if *rhs != clean::Type::Tuple(Vec::new()) { - *output = Some(rhs.clone()); - } - } - }; - true - }) + + merge_bounds(cx, bounds, trait_did, name, rhs) }); // And finally, let's reassemble everything @@ -127,6 +90,49 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> Vec { clauses } +pub fn merge_bounds( + cx: &clean::DocContext<'_>, + bounds: &mut Vec, + trait_did: DefId, + name: &str, + rhs: &clean::Type, +) -> bool { + !bounds.iter_mut().any(|b| { + let trait_ref = match *b { + clean::GenericBound::TraitBound(ref mut tr, _) => tr, + clean::GenericBound::Outlives(..) => return false, + }; + let (did, path) = match trait_ref.trait_ { + clean::ResolvedPath { did, ref mut path, ..} => (did, path), + _ => return false, + }; + // If this QPath's trait `trait_did` is the same as, or a supertrait + // of, the bound's trait `did` then we can keep going, otherwise + // this is just a plain old equality bound. + if !trait_is_same_or_supertrait(cx, did, trait_did) { + return false + } + let last = path.segments.last_mut().expect("segments were empty"); + match last.args { + PP::AngleBracketed { ref mut bindings, .. } => { + bindings.push(clean::TypeBinding { + name: name.to_string(), + kind: clean::TypeBindingKind::Equality { + ty: rhs.clone(), + }, + }); + } + PP::Parenthesized { ref mut output, .. } => { + assert!(output.is_none()); + if *rhs != clean::Type::Tuple(Vec::new()) { + *output = Some(rhs.clone()); + } + } + }; + true + }) +} + pub fn ty_params(mut params: Vec) -> Vec { for param in &mut params { match param.kind { diff --git a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs index 7807acbc4d61d..7b6e665b85f19 100644 --- a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs +++ b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs @@ -1,5 +1,9 @@ +use std::ops::Deref; + pub fn func<'a>(_x: impl Clone + Into> + 'a) {} +pub fn func2(_x: impl Deref> + Iterator, _y: impl Iterator) {} + pub struct Foo; impl Foo { diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs index 091baa9773ecf..20d193aad16dc 100644 --- a/src/test/rustdoc/inline_cross/impl_trait.rs +++ b/src/test/rustdoc/inline_cross/impl_trait.rs @@ -7,6 +7,12 @@ extern crate impl_trait_aux; // @!has - '//pre[@class="rust fn"]' 'where' pub use impl_trait_aux::func; +// @has impl_trait/fn.func2.html +// @has - '//pre[@class="rust fn"]' "_x: impl Deref> + Iterator," +// @has - '//pre[@class="rust fn"]' "_y: impl Iterator)" +// @!has - '//pre[@class="rust fn"]' 'where' +pub use impl_trait_aux::func2; + // @has impl_trait/struct.Foo.html // @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into> + 'a)" // @!has - '//code[@id="method.v"]' 'where' From 5f9e26382f3d8a1a90f866d1089e74ab9cf5b152 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 8 Jul 2019 20:42:45 +0900 Subject: [PATCH 026/618] Support nested `impl Trait` --- src/librustdoc/clean/mod.rs | 58 +++++++++++-------- .../inline_cross/auxiliary/impl_trait_aux.rs | 2 + src/test/rustdoc/inline_cross/impl_trait.rs | 6 ++ 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index bde1826c7fd5a..93e650d6d61ae 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1720,11 +1720,13 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericParamDefKind::Const { .. } => None, }).collect::>(); - // (param index, def id of trait) -> (name, type) - let mut impl_trait_proj = FxHashMap::<(u32, DefId), Vec<(String, Type)>>::default(); + // param index -> [(DefId of trait, associated type name, type)] + let mut impl_trait_proj = + FxHashMap::)>>::default(); let mut where_predicates = preds.predicates.iter() .flat_map(|(p, _)| { + let mut projection = None; let param_idx = (|| { if let Some(trait_ref) = p.to_opt_poly_trait_ref() { if let ty::Param(param) = trait_ref.self_ty().sty { @@ -1734,8 +1736,9 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, if let ty::Param(param) = outlives.skip_binder().0.sty { return Some(param.index); } - } else if let ty::Predicate::Projection(proj) = p { - if let ty::Param(param) = proj.skip_binder().projection_ty.self_ty().sty { + } else if let ty::Predicate::Projection(p) = p { + if let ty::Param(param) = p.skip_binder().projection_ty.self_ty().sty { + projection = Some(p); return Some(param.index); } } @@ -1755,16 +1758,15 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, .filter(|b| !b.is_sized_bound(cx)) ); - let proj = match &p { - WherePredicate::EqPredicate { lhs, rhs } => Some((lhs, rhs)) - .and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs))), - _ => None, - }; - if let Some(((_, trait_did, name), rhs)) = proj { + let proj = projection + .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty)); + if let Some(((_, trait_did, name), rhs)) = + proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs))) + { impl_trait_proj - .entry((param_idx, trait_did)) + .entry(param_idx) .or_default() - .push((name.to_string(), rhs.clone())); + .push((trait_did, name.to_string(), rhs)); } return None; @@ -1775,18 +1777,6 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, }) .collect::>(); - for ((param_idx, trait_did), bounds) in impl_trait_proj { - for (name, rhs) in bounds { - simplify::merge_bounds( - cx, - impl_trait.get_mut(¶m_idx.into()).unwrap(), - trait_did, - &name, - &rhs, - ); - } - } - // Move `TraitPredicate`s to the front. for (_, bounds) in impl_trait.iter_mut() { bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b { @@ -1796,7 +1786,25 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, }); } - cx.impl_trait_bounds.borrow_mut().extend(impl_trait); + for (param, mut bounds) in impl_trait { + if let crate::core::ImplTraitParam::ParamIndex(idx) = param { + if let Some(proj) = impl_trait_proj.remove(&idx) { + for (trait_did, name, rhs) in proj { + simplify::merge_bounds( + cx, + &mut bounds, + trait_did, + &name, + &rhs.clean(cx), + ); + } + } + } else { + unreachable!(); + } + + cx.impl_trait_bounds.borrow_mut().insert(param, bounds); + } // Type parameters and have a Sized bound by default unless removed with // ?Sized. Scan through the predicates and mark any type parameter with diff --git a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs index 7b6e665b85f19..e0f7c6d08ce2f 100644 --- a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs +++ b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs @@ -4,6 +4,8 @@ pub fn func<'a>(_x: impl Clone + Into> + 'a) {} pub fn func2(_x: impl Deref> + Iterator, _y: impl Iterator) {} +pub fn func3(_x: impl Iterator> + Clone) {} + pub struct Foo; impl Foo { diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs index 20d193aad16dc..b08a070dcb74d 100644 --- a/src/test/rustdoc/inline_cross/impl_trait.rs +++ b/src/test/rustdoc/inline_cross/impl_trait.rs @@ -8,11 +8,17 @@ extern crate impl_trait_aux; pub use impl_trait_aux::func; // @has impl_trait/fn.func2.html +// @has - '//pre[@class="rust fn"]' "func2(" // @has - '//pre[@class="rust fn"]' "_x: impl Deref> + Iterator," // @has - '//pre[@class="rust fn"]' "_y: impl Iterator)" // @!has - '//pre[@class="rust fn"]' 'where' pub use impl_trait_aux::func2; +// @has impl_trait/fn.func3.html +// @has - '//pre[@class="rust fn"]' "func3(_x: impl Clone + Iterator>)" +// @!has - '//pre[@class="rust fn"]' 'where' +pub use impl_trait_aux::func3; + // @has impl_trait/struct.Foo.html // @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into> + 'a)" // @!has - '//code[@id="method.v"]' 'where' From cc6dbb4f237ae0d84db5994cd075065efe05306b Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 8 Jul 2019 20:45:59 +0900 Subject: [PATCH 027/618] Fix tidy --- src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs | 5 ++++- src/test/rustdoc/inline_cross/impl_trait.rs | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs index e0f7c6d08ce2f..24efe4297103f 100644 --- a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs +++ b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs @@ -2,7 +2,10 @@ use std::ops::Deref; pub fn func<'a>(_x: impl Clone + Into> + 'a) {} -pub fn func2(_x: impl Deref> + Iterator, _y: impl Iterator) {} +pub fn func2( + _x: impl Deref> + Iterator, + _y: impl Iterator, +) {} pub fn func3(_x: impl Iterator> + Clone) {} diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs index b08a070dcb74d..3a9f2f880798d 100644 --- a/src/test/rustdoc/inline_cross/impl_trait.rs +++ b/src/test/rustdoc/inline_cross/impl_trait.rs @@ -15,7 +15,8 @@ pub use impl_trait_aux::func; pub use impl_trait_aux::func2; // @has impl_trait/fn.func3.html -// @has - '//pre[@class="rust fn"]' "func3(_x: impl Clone + Iterator>)" +// @has - '//pre[@class="rust fn"]' "func3(" +// @has - '//pre[@class="rust fn"]' "_x: impl Clone + Iterator>)" // @!has - '//pre[@class="rust fn"]' 'where' pub use impl_trait_aux::func3; From 3620456fafa04505c23511aa07d34f704ee7c84b Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 9 Jul 2019 16:37:55 +0900 Subject: [PATCH 028/618] Use BTreeMap for deterministic iter order --- src/librustdoc/clean/mod.rs | 9 ++++----- src/librustdoc/core.rs | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 93e650d6d61ae..37ee79aa9e4f1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1693,12 +1693,13 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, &'a &'tcx ty::GenericPredicates<'tcx>) { fn clean(&self, cx: &DocContext<'_>) -> Generics { use self::WherePredicate as WP; + use std::collections::BTreeMap; let (gens, preds) = *self; // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses, // since `Clean for ty::Predicate` would consume them. - let mut impl_trait = FxHashMap::>::default(); + let mut impl_trait = BTreeMap::>::default(); // Bounds in the type_params and lifetimes fields are repeated in the // predicates field (see rustc_typeck::collect::ty_generics), so remove @@ -1777,16 +1778,14 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, }) .collect::>(); - // Move `TraitPredicate`s to the front. - for (_, bounds) in impl_trait.iter_mut() { + for (param, mut bounds) in impl_trait { + // Move trait bounds to the front. bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b { false } else { true }); - } - for (param, mut bounds) in impl_trait { if let crate::core::ImplTraitParam::ParamIndex(idx) = param { if let Some(proj) = impl_trait_proj.remove(&idx) { for (trait_did, name, rhs) in proj { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 592a24fa4ae1a..04e69613d4b0f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -462,7 +462,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt /// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter /// for `impl Trait` in argument position. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum ImplTraitParam { DefId(DefId), ParamIndex(u32), From 1fe6160c7e4b584795c66f21683064f62803acf0 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 9 Jul 2019 16:59:34 +0900 Subject: [PATCH 029/618] Fix ICE with `impl Trait` in type bounds --- src/librustdoc/clean/mod.rs | 13 ++++++++++--- .../inline_cross/auxiliary/impl_trait_aux.rs | 2 ++ src/test/rustdoc/inline_cross/impl_trait.rs | 6 ++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 37ee79aa9e4f1..ba792a413b3c4 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1725,7 +1725,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, let mut impl_trait_proj = FxHashMap::)>>::default(); - let mut where_predicates = preds.predicates.iter() + let where_predicates = preds.predicates.iter() .flat_map(|(p, _)| { let mut projection = None; let param_idx = (|| { @@ -1747,10 +1747,10 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, None })(); - let p = p.clean(cx)?; - if let Some(param_idx) = param_idx { if let Some(b) = impl_trait.get_mut(¶m_idx.into()) { + let p = p.clean(cx)?; + b.extend( p.get_bounds() .into_iter() @@ -1805,6 +1805,13 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, cx.impl_trait_bounds.borrow_mut().insert(param, bounds); } + // Now that `cx.impl_trait_bounds` is populated, we can process + // remaining predicates which could contain `impl Trait`. + let mut where_predicates = where_predicates + .into_iter() + .flat_map(|p| p.clean(cx)) + .collect::>(); + // Type parameters and have a Sized bound by default unless removed with // ?Sized. Scan through the predicates and mark any type parameter with // a Sized bound, removing the bounds as we find them. diff --git a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs index 24efe4297103f..21c733a9bc98e 100644 --- a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs +++ b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs @@ -9,6 +9,8 @@ pub fn func2( pub fn func3(_x: impl Iterator> + Clone) {} +pub fn func4>(_x: T) {} + pub struct Foo; impl Foo { diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs index 3a9f2f880798d..b1e3f8d145b5f 100644 --- a/src/test/rustdoc/inline_cross/impl_trait.rs +++ b/src/test/rustdoc/inline_cross/impl_trait.rs @@ -20,6 +20,12 @@ pub use impl_trait_aux::func2; // @!has - '//pre[@class="rust fn"]' 'where' pub use impl_trait_aux::func3; + +// @has impl_trait/fn.func4.html +// @has - '//pre[@class="rust fn"]' "func4(" +// @has - '//pre[@class="rust fn"]' "T: Iterator," +pub use impl_trait_aux::func4; + // @has impl_trait/struct.Foo.html // @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into> + 'a)" // @!has - '//code[@id="method.v"]' 'where' From c4569347b260fa1ae00ede021e39f2a3227da4ad Mon Sep 17 00:00:00 2001 From: Phosphorus15 Date: Mon, 19 Aug 2019 17:22:08 +0800 Subject: [PATCH 030/618] Added negative cases for `asinh` according to IEEE-754. --- src/libstd/f32.rs | 15 +++++++++++---- src/libstd/f64.rs | 15 +++++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index f649170c40372..653108cbeceae 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -908,10 +908,17 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f32 { - if self == NEG_INFINITY { - NEG_INFINITY - } else { - (self + ((self * self) + 1.0).sqrt()).ln() + match self { + x if x == NEG_INFINITY => NEG_INFINITY, + x if x.is_sign_negative() => { + let v = (x + ((x * x) + 1.0).sqrt()).ln(); + if v.is_sign_negative() { + v + } else { + -v + } + } + x => (x + ((x * x) + 1.0).sqrt()).ln() } } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index f61630997dcdb..e5f963d873672 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -831,10 +831,17 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f64 { - if self == NEG_INFINITY { - NEG_INFINITY - } else { - (self + ((self * self) + 1.0).sqrt()).ln() + match self { + x if x == NEG_INFINITY => NEG_INFINITY, + x if x.is_sign_negative() => { + let v = (x + ((x * x) + 1.0).sqrt()).ln(); + if v.is_sign_negative() { + v + } else { + -v + } + } + x => (x + ((x * x) + 1.0).sqrt()).ln() } } From 64e3a10a82e6abad20f4a56750dac4cdd5df19ab Mon Sep 17 00:00:00 2001 From: Phosphorus15 Date: Mon, 19 Aug 2019 17:29:37 +0800 Subject: [PATCH 031/618] test cases for both `f32` and `f64` on asinh(-0.0) --- src/libstd/f32.rs | 1 + src/libstd/f64.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 653108cbeceae..ba75650fc4cb0 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -1495,6 +1495,7 @@ mod tests { assert_eq!(inf.asinh(), inf); assert_eq!(neg_inf.asinh(), neg_inf); assert!(nan.asinh().is_nan()); + assert!((-0.0f32).asinh().is_sign_negative()); // issue 63271 assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32); assert_approx_eq!((-2.0f32).asinh(), -1.443635475178810342493276740273105f32); } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index e5f963d873672..62c659739de79 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -1441,6 +1441,7 @@ mod tests { assert_eq!(inf.asinh(), inf); assert_eq!(neg_inf.asinh(), neg_inf); assert!(nan.asinh().is_nan()); + assert!((-0.0f64).asinh().is_sign_negative()); // issue 63271 assert_approx_eq!(2.0f64.asinh(), 1.443635475178810342493276740273105f64); assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64); } From cb52065d55e5ba1383aa155880a5e6661e6415a7 Mon Sep 17 00:00:00 2001 From: newpavlov Date: Mon, 19 Aug 2019 13:31:41 +0300 Subject: [PATCH 032/618] replace libc::nanosleep with wasi::poll_oneoff --- src/libstd/sys/wasi/thread.rs | 37 ++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index 9e0726432d9c4..eedc584dde500 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -1,7 +1,7 @@ use crate::cmp; use crate::ffi::CStr; use crate::io; -use crate::sys::cvt; +use crate::mem; use crate::sys::{unsupported, Void}; use crate::time::Duration; use libc; @@ -28,19 +28,28 @@ impl Thread { } pub fn sleep(dur: Duration) { - let mut secs = dur.as_secs(); - let mut nsecs = dur.subsec_nanos() as i32; - - unsafe { - while secs > 0 || nsecs > 0 { - let mut ts = libc::timespec { - tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t, - tv_nsec: nsecs, - }; - secs -= ts.tv_sec as u64; - cvt(libc::nanosleep(&ts, &mut ts)).unwrap(); - nsecs = 0; - } + let nanos = dur.as_nanos(); + assert!(nanos <= u64::max_value() as u128); + + let clock = wasi::raw::__wasi_subscription_u_clock_t { + identifier: 0, + clock_id: wasi::CLOCK_MONOTONIC, + timeout: nanos as u64, + precision: 0, + flags: 0, + }; + + let in_ = [wasi::Subscription { + userdata: 0, + type_: wasi::EVENTTYPE_CLOCK, + u: wasi::raw::__wasi_subscription_u { clock: clock }, + }]; + let mut out: [wasi::Event; 1] = [unsafe { mem::zeroed() }]; + let n = wasi::poll_oneoff(&in_, &mut out).unwrap(); + let wasi::Event { userdata, error, type_, .. } = out[0]; + match (n, userdata, error) { + (1, 0, 0) if type_ == wasi::EVENTTYPE_CLOCK => {} + _ => panic!("thread::sleep(): unexpected result of poll_oneof"), } } From 75a553fa27ffa293a21be5c5138b2b9fd69adfd2 Mon Sep 17 00:00:00 2001 From: newpavlov Date: Mon, 19 Aug 2019 13:50:22 +0300 Subject: [PATCH 033/618] remove to_string --- src/libstd/sys/wasi/os.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs index 8411878eeccd9..091ff3480bf85 100644 --- a/src/libstd/sys/wasi/os.rs +++ b/src/libstd/sys/wasi/os.rs @@ -25,7 +25,7 @@ pub fn errno() -> i32 { } pub fn error_string(errno: i32) -> String { - wasi::error_string(errno).to_string() + wasi::error_string(errno) } pub fn getcwd() -> io::Result { From 7a4f0aece871f9850f83db4760a6fea4f595dc8d Mon Sep 17 00:00:00 2001 From: newpavlov Date: Mon, 19 Aug 2019 14:54:37 +0300 Subject: [PATCH 034/618] use wasi::get_args --- src/libstd/sys/wasi/args.rs | 42 +++++-------------------------------- 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs index 679bb1b2cbe30..e2fe0548f1266 100644 --- a/src/libstd/sys/wasi/args.rs +++ b/src/libstd/sys/wasi/args.rs @@ -13,47 +13,15 @@ pub unsafe fn cleanup() { } pub struct Args { - iter: vec::IntoIter, + iter: vec::IntoIter>, _dont_send_or_sync_me: PhantomData<*mut ()>, } /// Returns the command line arguments pub fn args() -> Args { - maybe_args().unwrap_or_else(|_| { - Args { - iter: Vec::new().into_iter(), - _dont_send_or_sync_me: PhantomData - } - }) -} - -fn cvt_wasi(r: u16) -> crate::io::Result<()> { - if r != 0 { - Err(Error::from_raw_os_error(r as i32)) - } else { - Ok(()) - } -} - -fn maybe_args() -> io::Result { - // FIXME: replace with safe functions - use wasi::wasi_unstable::raw::{__wasi_args_sizes_get, __wasi_args_get}; - unsafe { - let (mut argc, mut argv_buf_size) = (0, 0); - cvt_wasi(__wasi_args_sizes_get(&mut argc, &mut argv_buf_size))?; - - let mut argc = vec![core::ptr::null_mut::(); argc]; - let mut argv_buf = vec![0; argv_buf_size]; - cvt_wasi(__wasi_args_get(argc.as_mut_ptr(), argv_buf.as_mut_ptr()))?; - - let args = argc.into_iter() - .map(|ptr| CStr::from_ptr(ptr).to_bytes().to_vec()) - .map(|bytes| OsString::from_vec(bytes)) - .collect::>(); - Ok(Args { - iter: args.into_iter(), - _dont_send_or_sync_me: PhantomData, - }) + Args { + iter: wasi::get_args().unwrap_or(Vec::new()), + _dont_send_or_sync_me: PhantomData } } @@ -66,7 +34,7 @@ impl Args { impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { - self.iter.next() + self.iter.next().map(OsString::from_vec) } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() From 52d2871e10202279b7039f4ad6d4485093fb99cc Mon Sep 17 00:00:00 2001 From: newpavlov Date: Mon, 19 Aug 2019 15:18:02 +0300 Subject: [PATCH 035/618] use wasi::get_environ --- src/libstd/sys/wasi/args.rs | 1 - src/libstd/sys/wasi/os.rs | 46 ++++++++++++++----------------------- 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs index e2fe0548f1266..23ab2051bf6f6 100644 --- a/src/libstd/sys/wasi/args.rs +++ b/src/libstd/sys/wasi/args.rs @@ -1,6 +1,5 @@ use crate::ffi::CStr; use crate::io; -use crate::sys::cvt_wasi; use crate::ffi::OsString; use crate::marker::PhantomData; use crate::os::wasi::ffi::OsStringExt; diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs index 091ff3480bf85..65c80c838dc82 100644 --- a/src/libstd/sys/wasi/os.rs +++ b/src/libstd/sys/wasi/os.rs @@ -75,45 +75,33 @@ pub fn current_exe() -> io::Result { } pub struct Env { - iter: vec::IntoIter<(OsString, OsString)>, + iter: Vec>, _dont_send_or_sync_me: PhantomData<*mut ()>, } impl Iterator for Env { type Item = (OsString, OsString); - fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() } + fn next(&mut self) -> Option<(OsString, OsString)> { + self.iter.next().and_then(|input| { + // See src/libstd/sys/unix/os.rs, same as that + if input.is_empty() { + return None; + } + let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); + pos.map(|p| ( + OsStringExt::from_vec(input[..p].to_vec()), + OsStringExt::from_vec(input[p+1..].to_vec()), + )) + }) + } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } pub fn env() -> Env { - unsafe { - let _guard = env_lock(); - // FIXME: replace with wasi::environ_get - let mut environ = libc::environ; - let mut result = Vec::new(); - while environ != ptr::null_mut() && *environ != ptr::null_mut() { - if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { - result.push(key_value); - } - environ = environ.offset(1); - } - return Env { - iter: result.into_iter(), - _dont_send_or_sync_me: PhantomData, - } - } - - // See src/libstd/sys/unix/os.rs, same as that - fn parse(input: &[u8]) -> Option<(OsString, OsString)> { - if input.is_empty() { - return None; - } - let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); - pos.map(|p| ( - OsStringExt::from_vec(input[..p].to_vec()), - OsStringExt::from_vec(input[p+1..].to_vec()), - )) + Env { + iter: wasi::get_environ().unwrap_or(Vec::new()), + _dont_send_or_sync_me: PhantomData, } } From 8394dbba7a46cd480b0934331b2654663d487e7b Mon Sep 17 00:00:00 2001 From: newpavlov Date: Mon, 19 Aug 2019 15:18:39 +0300 Subject: [PATCH 036/618] remove libc import --- src/libstd/sys/wasi/thread.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index eedc584dde500..a399d1f844cb0 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -4,7 +4,6 @@ use crate::io; use crate::mem; use crate::sys::{unsupported, Void}; use crate::time::Duration; -use libc; pub struct Thread(Void); From 338fc7d042ac868e2c92bfedf2b6850bac1970c9 Mon Sep 17 00:00:00 2001 From: newpavlov Date: Mon, 19 Aug 2019 15:32:37 +0300 Subject: [PATCH 037/618] use non-zero clock id --- src/libstd/sys/wasi/thread.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index a399d1f844cb0..7a2246de86c4f 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -31,7 +31,7 @@ impl Thread { assert!(nanos <= u64::max_value() as u128); let clock = wasi::raw::__wasi_subscription_u_clock_t { - identifier: 0, + identifier: 0x0123_45678, clock_id: wasi::CLOCK_MONOTONIC, timeout: nanos as u64, precision: 0, @@ -47,7 +47,7 @@ impl Thread { let n = wasi::poll_oneoff(&in_, &mut out).unwrap(); let wasi::Event { userdata, error, type_, .. } = out[0]; match (n, userdata, error) { - (1, 0, 0) if type_ == wasi::EVENTTYPE_CLOCK => {} + (1, 0x0123_45678, 0) if type_ == wasi::EVENTTYPE_CLOCK => {} _ => panic!("thread::sleep(): unexpected result of poll_oneof"), } } From 7658a13c650e3dd931250f6039c4f12bcc77534f Mon Sep 17 00:00:00 2001 From: newpavlov Date: Mon, 19 Aug 2019 15:33:05 +0300 Subject: [PATCH 038/618] typo fix --- src/libstd/sys/wasi/thread.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index 7a2246de86c4f..f9e2433dca064 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -48,7 +48,7 @@ impl Thread { let wasi::Event { userdata, error, type_, .. } = out[0]; match (n, userdata, error) { (1, 0x0123_45678, 0) if type_ == wasi::EVENTTYPE_CLOCK => {} - _ => panic!("thread::sleep(): unexpected result of poll_oneof"), + _ => panic!("thread::sleep(): unexpected result of poll_oneoff"), } } From e5ba80a87c54ab7770d9c300dacd0976f74e563e Mon Sep 17 00:00:00 2001 From: newpavlov Date: Mon, 19 Aug 2019 15:36:30 +0300 Subject: [PATCH 039/618] use const --- src/libstd/sys/wasi/thread.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index f9e2433dca064..a6c8f2487013b 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -30,8 +30,10 @@ impl Thread { let nanos = dur.as_nanos(); assert!(nanos <= u64::max_value() as u128); + const CLOCK_ID: wasi::Userdata = 0x0123_45678; + let clock = wasi::raw::__wasi_subscription_u_clock_t { - identifier: 0x0123_45678, + identifier: CLOCK_ID, clock_id: wasi::CLOCK_MONOTONIC, timeout: nanos as u64, precision: 0, @@ -47,7 +49,7 @@ impl Thread { let n = wasi::poll_oneoff(&in_, &mut out).unwrap(); let wasi::Event { userdata, error, type_, .. } = out[0]; match (n, userdata, error) { - (1, 0x0123_45678, 0) if type_ == wasi::EVENTTYPE_CLOCK => {} + (1, CLOCK_ID, 0) if type_ == wasi::EVENTTYPE_CLOCK => {} _ => panic!("thread::sleep(): unexpected result of poll_oneoff"), } } From c05237686f994144f2f0bae68dc5b337b06e9a97 Mon Sep 17 00:00:00 2001 From: newpavlov Date: Mon, 19 Aug 2019 16:01:21 +0300 Subject: [PATCH 040/618] fix --- src/libstd/sys/wasi/args.rs | 2 +- src/libstd/sys/wasi/os.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs index 23ab2051bf6f6..14aa391912ed2 100644 --- a/src/libstd/sys/wasi/args.rs +++ b/src/libstd/sys/wasi/args.rs @@ -19,7 +19,7 @@ pub struct Args { /// Returns the command line arguments pub fn args() -> Args { Args { - iter: wasi::get_args().unwrap_or(Vec::new()), + iter: wasi::get_args().unwrap_or(Vec::new()).into_iter(), _dont_send_or_sync_me: PhantomData } } diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs index 65c80c838dc82..04eee3ef28ff1 100644 --- a/src/libstd/sys/wasi/os.rs +++ b/src/libstd/sys/wasi/os.rs @@ -75,7 +75,7 @@ pub fn current_exe() -> io::Result { } pub struct Env { - iter: Vec>, + iter: vec::IntoIter>, _dont_send_or_sync_me: PhantomData<*mut ()>, } @@ -100,7 +100,7 @@ impl Iterator for Env { pub fn env() -> Env { Env { - iter: wasi::get_environ().unwrap_or(Vec::new()), + iter: wasi::get_environ().unwrap_or(Vec::new()).into_iter(), _dont_send_or_sync_me: PhantomData, } } From 0ec2e9fcebd18d98a32884786e1c4bbaf3db1ce0 Mon Sep 17 00:00:00 2001 From: Tom Milligan Date: Mon, 19 Aug 2019 15:19:26 +0100 Subject: [PATCH 041/618] librustdoc: warn on empty doc test --- .../passes/check_code_block_syntax.rs | 37 ++++++++++++++----- src/test/rustdoc-ui/invalid-syntax.rs | 10 +++++ src/test/rustdoc-ui/invalid-syntax.stderr | 22 +++++++++++ 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 357e17d2d1bc4..5c4159433c7b2 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -32,27 +32,39 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { dox[code_block.code].to_owned(), ); - let has_errors = { - let mut has_errors = false; + let validation_status = { + let mut has_syntax_errors = false; + let mut only_whitespace = true; + // even if there is a syntax error, we need to run the lexer over the whole file let mut lexer = Lexer::new(&sess, source_file, None); loop { match lexer.next_token().kind { token::Eof => break, - token::Unknown(..) => has_errors = true, - _ => (), + token::Whitespace => (), + token::Unknown(..) => has_syntax_errors = true, + _ => only_whitespace = false, } } - has_errors + + if has_syntax_errors { + Some(CodeBlockInvalid::SyntaxError) + } else if only_whitespace { + Some(CodeBlockInvalid::Empty) + } else { + None + } }; - if has_errors { + if let Some(code_block_invalid) = validation_status { let mut diag = if let Some(sp) = super::source_span_for_markdown_range(self.cx, &dox, &code_block.range, &item.attrs) { - let mut diag = self - .cx - .sess() - .struct_span_warn(sp, "could not parse code block as Rust code"); + let warning_message = match code_block_invalid { + CodeBlockInvalid::SyntaxError => "could not parse code block as Rust code", + CodeBlockInvalid::Empty => "Rust code block is empty", + }; + + let mut diag = self.cx.sess().struct_span_warn(sp, warning_message); if code_block.syntax.is_none() && code_block.is_fenced { let sp = sp.from_inner(InnerSpan::new(0, 3)); @@ -96,3 +108,8 @@ impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> { self.fold_item_recur(item) } } + +enum CodeBlockInvalid { + SyntaxError, + Empty, +} diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs index 2b02d47d4b851..3ef66e273d0d0 100644 --- a/src/test/rustdoc-ui/invalid-syntax.rs +++ b/src/test/rustdoc-ui/invalid-syntax.rs @@ -64,3 +64,13 @@ pub fn blargh() {} /// \_ #[doc = "```"] pub fn crazy_attrs() {} + +/// ```rust +/// ``` +pub fn empty_rust() {} + +/// ``` +/// +/// +/// ``` +pub fn empty_rust_with_whitespace() {} diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr index 3bebbecb9dfcf..36209e2927771 100644 --- a/src/test/rustdoc-ui/invalid-syntax.stderr +++ b/src/test/rustdoc-ui/invalid-syntax.stderr @@ -179,6 +179,28 @@ LL | | #[doc = "```"] | = help: mark blocks that do not contain Rust code as text: ```text +warning: Rust code block is empty + --> $DIR/invalid-syntax.rs:68:5 + | +LL | /// ```rust + | _____^ +LL | | /// ``` + | |_______^ + +warning: Rust code block is empty + --> $DIR/invalid-syntax.rs:72:5 + | +LL | /// ``` + | _____^ +LL | | /// +LL | | /// +LL | | /// ``` + | |_______^ +help: mark blocks that do not contain Rust code as text + | +LL | /// ```text + | ^^^^^^^ + error: unknown start of token: \ --> :1:1 | From 1417f53863c6afb1b90aef2d1c518cc8449a77f2 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Mon, 19 Aug 2019 19:58:35 +0000 Subject: [PATCH 042/618] fix cfg --- src/libstd/sys/unix/process/process_unix.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 327d82e60cff3..ea0e8b38e2b53 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -183,18 +183,16 @@ impl Command { cvt(libc::setgid(u as gid_t))?; } if let Some(u) = self.get_uid() { + // When dropping privileges from root, the `setgroups` call + // will remove any extraneous groups. If we don't call this, + // then even though our uid has dropped, we may still have + // groups that enable us to do super-user things. This will + // fail if we aren't root, so don't bother checking the + // return value, this is just done as an optimistic + // privilege dropping function. //FIXME: Redox kernel does not support setgroups yet - if cfg!(not(target_os = "redox")) { - // When dropping privileges from root, the `setgroups` call - // will remove any extraneous groups. If we don't call this, - // then even though our uid has dropped, we may still have - // groups that enable us to do super-user things. This will - // fail if we aren't root, so don't bother checking the - // return value, this is just done as an optimistic - // privilege dropping function. - let _ = libc::setgroups(0, ptr::null()); - } - + #[cfg(not(target_os = "redox"))] + let _ = libc::setgroups(0, ptr::null()); cvt(libc::setuid(u as uid_t))?; } } From 1dd2d3076df1ff8eb3b722769d9025c3a7f59458 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Mon, 19 Aug 2019 20:01:02 +0000 Subject: [PATCH 043/618] cfg fix 2 --- src/libstd/sys/unix/process/process_unix.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index ea0e8b38e2b53..c05484df330ae 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -178,7 +178,8 @@ impl Command { cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO))?; } - if cfg!(not(any(target_os = "l4re"))) { + #[cfg(not(any(target_os = "l4re")))] + { if let Some(u) = self.get_gid() { cvt(libc::setgid(u as gid_t))?; } From 34c9f8c6490bb1179c504bccd51b2827c05f10db Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Mon, 19 Aug 2019 20:02:50 +0000 Subject: [PATCH 044/618] remove any from cfgs --- src/libstd/sys/unix/process/process_unix.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index c05484df330ae..7e0986d8eeb6a 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -178,7 +178,7 @@ impl Command { cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO))?; } - #[cfg(not(any(target_os = "l4re")))] + #[cfg(not(target_os = "l4re"))] { if let Some(u) = self.get_gid() { cvt(libc::setgid(u as gid_t))?; @@ -202,7 +202,7 @@ impl Command { } // emscripten has no signal support. - #[cfg(not(any(target_os = "emscripten")))] + #[cfg(not(target_os = "emscripten"))] { use crate::mem::MaybeUninit; // Reset signal handling so the child process starts in a From 859657f2c5dbe2cf55cf7a7665383a81e676bdf3 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 1 Aug 2019 11:06:52 -0700 Subject: [PATCH 045/618] Use named arguments for formatting usage message. It was getting a bit awkward. --- src/librustc_driver/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index fdd0773b73ae2..cd030f3c9184e 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -777,13 +777,13 @@ fn usage(verbose: bool, include_unstable_options: bool) { } else { "\n --help -v Print the full set of options rustc accepts" }; - println!("{}\nAdditional help: + println!("{options}\nAdditional help: -C help Print codegen options -W help \ - Print 'lint' options and default settings{}{}\n", - options.usage(message), - nightly_help, - verbose_help); + Print 'lint' options and default settings{nightly}{verbose}\n", + options = options.usage(message), + nightly = nightly_help, + verbose = verbose_help); } fn print_wall_help() { From d2219c2e2e287d50c0f9761203d26d5fe3b0e639 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 30 Jul 2019 15:57:10 -0700 Subject: [PATCH 046/618] rustc: implement argsfiles for command line This makes `rustc` support `@path` arguments on the command line. The `path` is opened and the file is interpreted as new command line options which are logically inserted at that point in the command-line. The options in the file are one per line. The file is UTF-8 encoded, and may have either Unix or Windows line endings. It does not support recursive use of `@path`. This is useful for very large command lines, or when command-lines are being generated into files by other tooling. --- src/doc/rustc/src/command-line-arguments.md | 7 + src/librustc_driver/args/mod.rs | 84 ++++++++++ src/librustc_driver/args/tests.rs | 145 ++++++++++++++++++ src/librustc_driver/lib.rs | 21 ++- src/test/ui/commandline-argfile-badutf8.args | 2 + src/test/ui/commandline-argfile-badutf8.rs | 14 ++ .../ui/commandline-argfile-badutf8.stderr | 2 + src/test/ui/commandline-argfile-missing.rs | 16 ++ .../ui/commandline-argfile-missing.stderr | 2 + src/test/ui/commandline-argfile.args | 2 + src/test/ui/commandline-argfile.rs | 13 ++ 11 files changed, 304 insertions(+), 4 deletions(-) create mode 100644 src/librustc_driver/args/mod.rs create mode 100644 src/librustc_driver/args/tests.rs create mode 100644 src/test/ui/commandline-argfile-badutf8.args create mode 100644 src/test/ui/commandline-argfile-badutf8.rs create mode 100644 src/test/ui/commandline-argfile-badutf8.stderr create mode 100644 src/test/ui/commandline-argfile-missing.rs create mode 100644 src/test/ui/commandline-argfile-missing.stderr create mode 100644 src/test/ui/commandline-argfile.args create mode 100644 src/test/ui/commandline-argfile.rs diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index d774e465118b3..5eea9c8687900 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -304,3 +304,10 @@ to customize the output: Note that it is invalid to combine the `--json` argument with the `--color` argument, and it is required to combine `--json` with `--error-format=json`. + +## `@path`: load command-line flags from a path + +If you specify `@path` on the command-line, then it will open `path` and read +command line options from it. These options are one per line; a blank line indicates +an empty option. The file can use Unix or Windows style line endings, and must be +encoded as UTF-8. diff --git a/src/librustc_driver/args/mod.rs b/src/librustc_driver/args/mod.rs new file mode 100644 index 0000000000000..a59f9afd8beb5 --- /dev/null +++ b/src/librustc_driver/args/mod.rs @@ -0,0 +1,84 @@ +use std::env; +use std::error; +use std::fmt; +use std::fs; +use std::io; +use std::str; +use std::sync::atomic::{AtomicBool, Ordering}; + +#[cfg(test)] +mod tests; + +static USED_ARGSFILE_FEATURE: AtomicBool = AtomicBool::new(false); + +pub fn used_unstable_argsfile() -> bool { + USED_ARGSFILE_FEATURE.load(Ordering::Relaxed) +} + +pub struct ArgsIter { + base: env::ArgsOs, + file: std::vec::IntoIter, +} + +impl ArgsIter { + pub fn new() -> Self { + ArgsIter { base: env::args_os(), file: vec![].into_iter() } + } +} + +impl Iterator for ArgsIter { + type Item = Result; + + fn next(&mut self) -> Option { + loop { + if let Some(line) = self.file.next() { + return Some(Ok(line)); + } + + let arg = + self.base.next().map(|arg| arg.into_string().map_err(|_| Error::Utf8Error(None))); + match arg { + Some(Err(err)) => return Some(Err(err)), + Some(Ok(ref arg)) if arg.starts_with("@") => { + let path = &arg[1..]; + let file = match fs::read_to_string(path) { + Ok(file) => { + USED_ARGSFILE_FEATURE.store(true, Ordering::Relaxed); + file + } + Err(ref err) if err.kind() == io::ErrorKind::InvalidData => { + return Some(Err(Error::Utf8Error(Some(path.to_string())))); + } + Err(err) => return Some(Err(Error::IOError(path.to_string(), err))), + }; + self.file = + file.lines().map(ToString::to_string).collect::>().into_iter(); + } + Some(Ok(arg)) => return Some(Ok(arg)), + None => return None, + } + } + } +} + +#[derive(Debug)] +pub enum Error { + Utf8Error(Option), + IOError(String, io::Error), +} + +impl fmt::Display for Error { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::Utf8Error(None) => write!(fmt, "Utf8 error"), + Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {}", path), + Error::IOError(path, err) => write!(fmt, "IO Error: {}: {}", path, err), + } + } +} + +impl error::Error for Error { + fn description(&self) -> &'static str { + "argument error" + } +} diff --git a/src/librustc_driver/args/tests.rs b/src/librustc_driver/args/tests.rs new file mode 100644 index 0000000000000..080dd5cb746c3 --- /dev/null +++ b/src/librustc_driver/args/tests.rs @@ -0,0 +1,145 @@ +use super::*; + +use std::str; + +fn want_args(v: impl IntoIterator) -> Vec { + v.into_iter().map(String::from).collect() +} + +fn got_args(file: &[u8]) -> Result, Error> { + let ret = str::from_utf8(file) + .map_err(|_| Error::Utf8Error(None))? + .lines() + .map(ToString::to_string) + .collect::>(); + Ok(ret) +} + +#[test] +fn nothing() { + let file = b""; + + assert_eq!(got_args(file).unwrap(), want_args(vec![])); +} + +#[test] +fn empty() { + let file = b"\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec![""])); +} + +#[test] +fn simple() { + let file = b"foo"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"])); +} + +#[test] +fn simple_eol() { + let file = b"foo\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"])); +} + +#[test] +fn multi() { + let file = b"foo\nbar"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); +} + +#[test] +fn multi_eol() { + let file = b"foo\nbar\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); +} + +#[test] +fn multi_empty() { + let file = b"foo\n\nbar"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); +} + +#[test] +fn multi_empty_eol() { + let file = b"foo\n\nbar\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); +} + +#[test] +fn multi_empty_start() { + let file = b"\nfoo\nbar"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["", "foo", "bar"])); +} + +#[test] +fn multi_empty_end() { + let file = b"foo\nbar\n\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar", ""])); +} + +#[test] +fn simple_eol_crlf() { + let file = b"foo\r\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"])); +} + +#[test] +fn multi_crlf() { + let file = b"foo\r\nbar"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); +} + +#[test] +fn multi_eol_crlf() { + let file = b"foo\r\nbar\r\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); +} + +#[test] +fn multi_empty_crlf() { + let file = b"foo\r\n\r\nbar"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); +} + +#[test] +fn multi_empty_eol_crlf() { + let file = b"foo\r\n\r\nbar\r\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); +} + +#[test] +fn multi_empty_start_crlf() { + let file = b"\r\nfoo\r\nbar"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["", "foo", "bar"])); +} + +#[test] +fn multi_empty_end_crlf() { + let file = b"foo\r\nbar\r\n\r\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar", ""])); +} + +#[test] +fn bad_utf8() { + let file = b"foo\x80foo"; + + match got_args(file).unwrap_err() { + Error::Utf8Error(_) => (), + bad => panic!("bad err: {:?}", bad), + } +} diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index cd030f3c9184e..4843c1a951b31 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -66,6 +66,7 @@ use syntax::symbol::sym; use syntax_pos::{DUMMY_SP, MultiSpan, FileName}; pub mod pretty; +mod args; /// Exit status code used for successful compilation and help output. pub const EXIT_SUCCESS: i32 = 0; @@ -777,11 +778,17 @@ fn usage(verbose: bool, include_unstable_options: bool) { } else { "\n --help -v Print the full set of options rustc accepts" }; - println!("{options}\nAdditional help: + let at_path = if verbose && nightly_options::is_nightly_build() { + " @path Read newline separated options from `path`\n" + } else { + "" + }; + println!("{options}{at_path}\nAdditional help: -C help Print codegen options -W help \ Print 'lint' options and default settings{nightly}{verbose}\n", options = options.usage(message), + at_path = at_path, nightly = nightly_help, verbose = verbose_help); } @@ -1008,6 +1015,12 @@ pub fn handle_options(args: &[String]) -> Option { // (unstable option being used on stable) nightly_options::check_nightly_options(&matches, &config::rustc_optgroups()); + // Late check to see if @file was used without unstable options enabled + if crate::args::used_unstable_argsfile() && !nightly_options::is_unstable_enabled(&matches) { + early_error(ErrorOutputType::default(), + "@path is unstable - use -Z unstable-options to enable its use"); + } + if matches.opt_present("h") || matches.opt_present("help") { // Only show unstable options in --help if we accept unstable options. usage(matches.opt_present("verbose"), nightly_options::is_unstable_enabled(&matches)); @@ -1186,10 +1199,10 @@ pub fn main() { init_rustc_env_logger(); let mut callbacks = TimePassesCallbacks::default(); let result = report_ices_to_stderr_if_any(|| { - let args = env::args_os().enumerate() - .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| { + let args = args::ArgsIter::new().enumerate() + .map(|(i, arg)| arg.unwrap_or_else(|err| { early_error(ErrorOutputType::default(), - &format!("Argument {} is not valid Unicode: {:?}", i, arg)) + &format!("Argument {} is not valid: {}", i, err)) })) .collect::>(); run_compiler(&args, &mut callbacks, None, None) diff --git a/src/test/ui/commandline-argfile-badutf8.args b/src/test/ui/commandline-argfile-badutf8.args new file mode 100644 index 0000000000000..c070b0c2400d8 --- /dev/null +++ b/src/test/ui/commandline-argfile-badutf8.args @@ -0,0 +1,2 @@ +--cfg +unbroken€ \ No newline at end of file diff --git a/src/test/ui/commandline-argfile-badutf8.rs b/src/test/ui/commandline-argfile-badutf8.rs new file mode 100644 index 0000000000000..c017e7b5ea60b --- /dev/null +++ b/src/test/ui/commandline-argfile-badutf8.rs @@ -0,0 +1,14 @@ +// Check to see if we can get parameters from an @argsfile file +// +// build-fail +// normalize-stderr-test: "Argument \d+" -> "Argument $$N" +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/src/test/ui/commandline-argfile-badutf8.stderr b/src/test/ui/commandline-argfile-badutf8.stderr new file mode 100644 index 0000000000000..cd8a03e34eac9 --- /dev/null +++ b/src/test/ui/commandline-argfile-badutf8.stderr @@ -0,0 +1,2 @@ +error: Argument $N is not valid: Utf8 error in $DIR/commandline-argfile-badutf8.args + diff --git a/src/test/ui/commandline-argfile-missing.rs b/src/test/ui/commandline-argfile-missing.rs new file mode 100644 index 0000000000000..34faf07633599 --- /dev/null +++ b/src/test/ui/commandline-argfile-missing.rs @@ -0,0 +1,16 @@ +// Check to see if we can get parameters from an @argsfile file +// +// build-fail +// normalize-stderr-test: "Argument \d+" -> "Argument $$N" +// normalize-stderr-test: "os error \d+" -> "os error $$ERR" +// normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/src/test/ui/commandline-argfile-missing.stderr b/src/test/ui/commandline-argfile-missing.stderr new file mode 100644 index 0000000000000..c0017782f2eb3 --- /dev/null +++ b/src/test/ui/commandline-argfile-missing.stderr @@ -0,0 +1,2 @@ +error: Argument $N is not valid: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) + diff --git a/src/test/ui/commandline-argfile.args b/src/test/ui/commandline-argfile.args new file mode 100644 index 0000000000000..972938bf6c8dd --- /dev/null +++ b/src/test/ui/commandline-argfile.args @@ -0,0 +1,2 @@ +--cfg +unbroken \ No newline at end of file diff --git a/src/test/ui/commandline-argfile.rs b/src/test/ui/commandline-argfile.rs new file mode 100644 index 0000000000000..fc1ba0c8d677d --- /dev/null +++ b/src/test/ui/commandline-argfile.rs @@ -0,0 +1,13 @@ +// Check to see if we can get parameters from an @argsfile file +// +// build-pass +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} From 535efa4afd3bb5a141eae8579f54aa641ccedaa2 Mon Sep 17 00:00:00 2001 From: Phosphorus15 Date: Tue, 20 Aug 2019 12:39:12 +0800 Subject: [PATCH 047/618] Used `copysign` to avoid unnecessary branches. --- src/libstd/f32.rs | 10 +--------- src/libstd/f64.rs | 10 +--------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index ba75650fc4cb0..dcb035993ae39 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -910,15 +910,7 @@ impl f32 { pub fn asinh(self) -> f32 { match self { x if x == NEG_INFINITY => NEG_INFINITY, - x if x.is_sign_negative() => { - let v = (x + ((x * x) + 1.0).sqrt()).ln(); - if v.is_sign_negative() { - v - } else { - -v - } - } - x => (x + ((x * x) + 1.0).sqrt()).ln() + x => (x + ((x * x) + 1.0).sqrt()).ln().copysign(self) } } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 62c659739de79..076b6340d89bc 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -833,15 +833,7 @@ impl f64 { pub fn asinh(self) -> f64 { match self { x if x == NEG_INFINITY => NEG_INFINITY, - x if x.is_sign_negative() => { - let v = (x + ((x * x) + 1.0).sqrt()).ln(); - if v.is_sign_negative() { - v - } else { - -v - } - } - x => (x + ((x * x) + 1.0).sqrt()).ln() + x => (x + ((x * x) + 1.0).sqrt()).ln().copysign(self) } } From e33d8707c8ed516fd798c835acf7e1567293cf9a Mon Sep 17 00:00:00 2001 From: Phosphorus15 Date: Tue, 20 Aug 2019 15:12:41 +0800 Subject: [PATCH 048/618] Refined implementations of `asinh` and `acosh` --- src/libstd/f32.rs | 14 ++++++++------ src/libstd/f64.rs | 39 +++++++++++++++++++++------------------ 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index dcb035993ae39..f8f38cb75ab77 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -908,9 +908,10 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f32 { - match self { - x if x == NEG_INFINITY => NEG_INFINITY, - x => (x + ((x * x) + 1.0).sqrt()).ln().copysign(self) + if self == NEG_INFINITY { + NEG_INFINITY + } else { + (self + ((self * self) + 1.0).sqrt()).ln().copysign(self) } } @@ -931,9 +932,10 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f32 { - match self { - x if x < 1.0 => crate::f32::NAN, - x => (x + ((x * x) - 1.0).sqrt()).ln(), + if self < 1.0 { + crate::f32::NAN + } else { + (self + ((self * self) - 1.0).sqrt()).ln() } } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 076b6340d89bc..06f68bc72e764 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -244,7 +244,7 @@ impl f64 { pub fn div_euclid(self, rhs: f64) -> f64 { let q = (self / rhs).trunc(); if self % rhs < 0.0 { - return if rhs > 0.0 { q - 1.0 } else { q + 1.0 } + return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }; } q } @@ -437,9 +437,9 @@ impl f64 { pub fn log2(self) -> f64 { self.log_wrapper(|n| { #[cfg(target_os = "android")] - return crate::sys::android::log2f64(n); + return crate::sys::android::log2f64(n); #[cfg(not(target_os = "android"))] - return unsafe { intrinsics::log2f64(n) }; + return unsafe { intrinsics::log2f64(n) }; }) } @@ -481,16 +481,16 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[rustc_deprecated(since = "1.10.0", - reason = "you probably meant `(self - other).abs()`: \ + reason = "you probably meant `(self - other).abs()`: \ this operation is `(self - other).max(0.0)` \ except that `abs_sub` also propagates NaNs (also \ known as `fdim` in C). If you truly need the positive \ difference, consider using that expression or the C function \ `fdim`, depending on how you wish to handle NaN (please consider \ filing an issue describing your use-case too).")] - pub fn abs_sub(self, other: f64) -> f64 { - unsafe { cmath::fdim(self, other) } - } + pub fn abs_sub(self, other: f64) -> f64 { + unsafe { cmath::fdim(self, other) } + } /// Takes the cubic root of a number. /// @@ -831,9 +831,10 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f64 { - match self { - x if x == NEG_INFINITY => NEG_INFINITY, - x => (x + ((x * x) + 1.0).sqrt()).ln().copysign(self) + if self == NEG_INFINITY { + NEG_INFINITY + } else { + (self + ((self * self) + 1.0).sqrt()).ln().copysign(self) } } @@ -852,9 +853,10 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f64 { - match self { - x if x < 1.0 => NAN, - x => (x + ((x * x) - 1.0).sqrt()).ln(), + if self < 1.0 { + NAN + } else { + (self + ((self * self) - 1.0).sqrt()).ln() } } @@ -1187,7 +1189,7 @@ mod tests { assert_eq!((-0f64).abs(), 0f64); assert_eq!((-1f64).abs(), 1f64); assert_eq!(NEG_INFINITY.abs(), INFINITY); - assert_eq!((1f64/NEG_INFINITY).abs(), 0f64); + assert_eq!((1f64 / NEG_INFINITY).abs(), 0f64); assert!(NAN.abs().is_nan()); } @@ -1199,7 +1201,7 @@ mod tests { assert_eq!((-0f64).signum(), -1f64); assert_eq!((-1f64).signum(), -1f64); assert_eq!(NEG_INFINITY.signum(), -1f64); - assert_eq!((1f64/NEG_INFINITY).signum(), -1f64); + assert_eq!((1f64 / NEG_INFINITY).signum(), -1f64); assert!(NAN.signum().is_nan()); } @@ -1211,7 +1213,7 @@ mod tests { assert!(!(-0f64).is_sign_positive()); assert!(!(-1f64).is_sign_positive()); assert!(!NEG_INFINITY.is_sign_positive()); - assert!(!(1f64/NEG_INFINITY).is_sign_positive()); + assert!(!(1f64 / NEG_INFINITY).is_sign_positive()); assert!(NAN.is_sign_positive()); assert!(!(-NAN).is_sign_positive()); } @@ -1224,7 +1226,7 @@ mod tests { assert!((-0f64).is_sign_negative()); assert!((-1f64).is_sign_negative()); assert!(NEG_INFINITY.is_sign_negative()); - assert!((1f64/NEG_INFINITY).is_sign_negative()); + assert!((1f64 / NEG_INFINITY).is_sign_negative()); assert!(!NAN.is_sign_negative()); assert!((-NAN).is_sign_negative()); } @@ -1433,7 +1435,8 @@ mod tests { assert_eq!(inf.asinh(), inf); assert_eq!(neg_inf.asinh(), neg_inf); assert!(nan.asinh().is_nan()); - assert!((-0.0f64).asinh().is_sign_negative()); // issue 63271 + assert!((-0.0f64).asinh().is_sign_negative()); + // issue 63271 assert_approx_eq!(2.0f64.asinh(), 1.443635475178810342493276740273105f64); assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64); } From 0be01fa655439787283aa85779befb4e23f1b337 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 20 Aug 2019 16:21:47 +0900 Subject: [PATCH 049/618] Update rustfmt to 1.4.5 --- Cargo.lock | 2 +- src/tools/rustfmt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9e7dd54e13532..06d13dac9daca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3546,7 +3546,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.4" +version = "1.4.5" dependencies = [ "annotate-snippets", "atty", diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 0462008de87d2..9792ff05297c0 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 0462008de87d2757e8ef1dc26f2c54dd789a59a8 +Subproject commit 9792ff05297c0a5c40942b346c9b0341b9e7c0ee From bd1dc7cf92f22913ea34ada119393a9a6c880fa4 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Tue, 20 Aug 2019 10:26:10 +0000 Subject: [PATCH 050/618] fix libc checksum --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 2412d5e9627ff..fbe9e462025bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1571,7 +1571,7 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" name = "libc" version = "0.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" +checksum = "c665266eb592905e8503ba3403020f4b8794d26263f412ca33171600eca9a6fa" dependencies = [ "rustc-std-workspace-core", ] From 744442d19a76c4dd39f5fa2a2bbd74638e8569ec Mon Sep 17 00:00:00 2001 From: newpavlov Date: Tue, 20 Aug 2019 15:43:34 +0300 Subject: [PATCH 051/618] fix C incompatibilities --- src/libstd/sys/wasi/mod.rs | 2 +- src/libstd/sys/wasi/os.rs | 67 ++++++++++++++++++++++++++------------ 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs index 0a16c29e5af53..28b49996d1433 100644 --- a/src/libstd/sys/wasi/mod.rs +++ b/src/libstd/sys/wasi/mod.rs @@ -83,7 +83,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize { } pub unsafe fn abort_internal() -> ! { - wasi::proc_exit(127) + libc::abort() } pub fn hashmap_random_keys() -> (u64, u64) { diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs index 04eee3ef28ff1..dca58179e0c8d 100644 --- a/src/libstd/sys/wasi/os.rs +++ b/src/libstd/sys/wasi/os.rs @@ -21,11 +21,24 @@ pub unsafe fn env_lock() -> impl Any { } pub fn errno() -> i32 { - 0 + extern { + #[thread_local] + static errno: libc::c_int; + } + + unsafe { errno as i32 } } pub fn error_string(errno: i32) -> String { - wasi::error_string(errno) + let mut buf = [0 as libc::c_char; 1024]; + + let p = buf.as_mut_ptr(); + unsafe { + if libc::strerror_r(errno as libc::c_int, p, buf.len()) < 0 { + panic!("strerror_r failure"); + } + str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned() + } } pub fn getcwd() -> io::Result { @@ -73,35 +86,45 @@ impl StdError for JoinPathsError { pub fn current_exe() -> io::Result { unsupported() } - pub struct Env { - iter: vec::IntoIter>, + iter: vec::IntoIter<(OsString, OsString)>, _dont_send_or_sync_me: PhantomData<*mut ()>, } impl Iterator for Env { type Item = (OsString, OsString); - fn next(&mut self) -> Option<(OsString, OsString)> { - self.iter.next().and_then(|input| { - // See src/libstd/sys/unix/os.rs, same as that - if input.is_empty() { - return None; - } - let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); - pos.map(|p| ( - OsStringExt::from_vec(input[..p].to_vec()), - OsStringExt::from_vec(input[p+1..].to_vec()), - )) - }) - } + fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } pub fn env() -> Env { - Env { - iter: wasi::get_environ().unwrap_or(Vec::new()).into_iter(), - _dont_send_or_sync_me: PhantomData, + unsafe { + let _guard = env_lock(); + let mut environ = libc::environ; + let mut result = Vec::new(); + while environ != ptr::null_mut() && *environ != ptr::null_mut() { + if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { + result.push(key_value); + } + environ = environ.offset(1); + } + return Env { + iter: result.into_iter(), + _dont_send_or_sync_me: PhantomData, + } + } + + // See src/libstd/sys/unix/os.rs, same as that + fn parse(input: &[u8]) -> Option<(OsString, OsString)> { + if input.is_empty() { + return None; + } + let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); + pos.map(|p| ( + OsStringExt::from_vec(input[..p].to_vec()), + OsStringExt::from_vec(input[p+1..].to_vec()), + )) } } @@ -147,7 +170,9 @@ pub fn home_dir() -> Option { } pub fn exit(code: i32) -> ! { - unsafe { wasi::proc_exit(code as u32) } + unsafe { + libc::exit(code) + } } pub fn getpid() -> u32 { From 99ce39b30a296354409c5161c4a5bc833f5f72d0 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 19 Aug 2019 18:04:25 -0400 Subject: [PATCH 052/618] Load error codes via build script instead of JSON parsing This scans the tree for `error_codes.rs` and loads all of them. --- Cargo.lock | 1 + src/tools/error_index_generator/Cargo.toml | 4 ++ src/tools/error_index_generator/build.rs | 64 ++++++++++++++++++++++ src/tools/error_index_generator/main.rs | 46 +++++----------- 4 files changed, 84 insertions(+), 31 deletions(-) create mode 100644 src/tools/error_index_generator/build.rs diff --git a/Cargo.lock b/Cargo.lock index 910d6ba22c16f..82bfc671355aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -946,6 +946,7 @@ name = "error_index_generator" version = "0.0.0" dependencies = [ "rustdoc", + "walkdir", ] [[package]] diff --git a/src/tools/error_index_generator/Cargo.toml b/src/tools/error_index_generator/Cargo.toml index 116be234f3ceb..992af261b8352 100644 --- a/src/tools/error_index_generator/Cargo.toml +++ b/src/tools/error_index_generator/Cargo.toml @@ -3,10 +3,14 @@ authors = ["The Rust Project Developers"] name = "error_index_generator" version = "0.0.0" edition = "2018" +build = "build.rs" [dependencies] rustdoc = { path = "../../librustdoc" } +[build-dependencies] +walkdir = "2" + [[bin]] name = "error_index_generator" path = "main.rs" diff --git a/src/tools/error_index_generator/build.rs b/src/tools/error_index_generator/build.rs new file mode 100644 index 0000000000000..2ac7351fce469 --- /dev/null +++ b/src/tools/error_index_generator/build.rs @@ -0,0 +1,64 @@ +use walkdir::WalkDir; +use std::path::PathBuf; +use std::{env, fs}; + +fn main() { + // The src directory (we are in src/tools/error_index_generator) + // Note that we could skip one of the .. but this ensures we at least loosely find the right + // directory. + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let dest = out_dir.join("error_codes.rs"); + let mut idx = 0; + for entry in WalkDir::new("../../../src") { + let entry = entry.unwrap(); + if entry.file_name() == "error_codes.rs" { + println!("cargo:rerun-if-changed={}", entry.path().to_str().unwrap()); + let file = fs::read_to_string(entry.path()).unwrap() + .replace("use syntax::{register_diagnostics, register_long_diagnostics};", "") + .replace("use syntax::register_diagnostics;", "") + .replace("use syntax::register_long_diagnostics;", ""); + let contents = format!("(|| {{\n{}\n}})();", file); + + fs::write(&out_dir.join(&format!("error_{}.rs", idx)), &contents).unwrap(); + + idx += 1; + } + } + + let mut all = String::new(); + all.push_str("fn register_all() -> Vec<(&'static str, Option<&'static str>)> {\n"); + all.push_str("let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new();\n"); + all.push_str(r#" +macro_rules! register_diagnostics { + ($($code:tt),*) => {{ + long_codes.extend([$( + stringify!($code), + )*].iter().cloned().map(|s| (s, None)).collect::>()); + }}; + ($($code:tt),*,) => {{ + long_codes.extend([$( + stringify!($code), + )*].iter().cloned().map(|s| (s, None))); + }} +} + +macro_rules! register_long_diagnostics { + ($($code:tt: $description:tt),*) => { + {long_codes.extend([$( + (stringify!($code), Some(stringify!($description))), + )*].iter());} + }; + ($($code:tt: $description:tt),*,) => { + {long_codes.extend([$( + (stringify!($code), Some(stringify!($description))), + )*].iter());} + } +}"#); + for idx in 0..idx { + all.push_str(&format!(r#"include!(concat!(env!("OUT_DIR"), "/error_{}.rs"));"#, idx)); + } + all.push_str("\nlong_codes\n"); + all.push_str("}\n"); + + fs::write(&dest, all).unwrap(); +} diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index a9d1d9997f6ef..b35d304e760fe 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -2,22 +2,20 @@ extern crate env_logger; extern crate syntax; -extern crate serialize as rustc_serialize; use std::collections::BTreeMap; use std::env; use std::error::Error; -use std::fs::{self, read_dir, File}; +use std::fs::File; use std::io::Write; use std::path::Path; use std::path::PathBuf; use std::cell::RefCell; use syntax::edition::DEFAULT_EDITION; -use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata}; +use syntax::diagnostics::metadata::{ErrorMetadataMap, ErrorMetadata}; use rustdoc::html::markdown::{Markdown, IdMap, ErrorCodes, Playground}; -use rustc_serialize::json; enum OutputFormat { HTML(HTMLFormatter), @@ -80,11 +78,7 @@ impl Formatter for HTMLFormatter { Some(_) => "error-described", None => "error-undescribed", }; - let use_desc = match info.use_site { - Some(_) => "error-used", - None => "error-unused", - }; - write!(output, "
", desc_desc, use_desc)?; + write!(output, "
", desc_desc)?; // Error title (with self-link). write!(output, @@ -199,25 +193,6 @@ impl Formatter for MarkdownFormatter { } } -/// Loads all the metadata files from `metadata_dir` into an in-memory map. -fn load_all_errors(metadata_dir: &Path) -> Result> { - let mut all_errors = BTreeMap::new(); - - for entry in read_dir(metadata_dir)? { - let path = entry?.path(); - - let metadata_str = fs::read_to_string(&path)?; - - let some_errors: ErrorMetadataMap = json::decode(&metadata_str)?; - - for (err_code, info) in some_errors { - all_errors.insert(err_code, info); - } - } - - Ok(all_errors) -} - /// Output an HTML page for the errors in `err_map` to `output_path`. fn render_error_page(err_map: &ErrorMetadataMap, output_path: &Path, formatter: T) -> Result<(), Box> { @@ -234,9 +209,16 @@ fn render_error_page(err_map: &ErrorMetadataMap, output_path: &Pat } fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box> { - let build_arch = env::var("CFG_BUILD")?; - let metadata_dir = get_metadata_dir(&build_arch); - let err_map = load_all_errors(&metadata_dir)?; + let long_codes = register_all(); + let mut err_map = BTreeMap::new(); + for (code, desc) in long_codes { + err_map.insert(code.to_string(), ErrorMetadata { + description: desc.map(String::from), + // FIXME: this indicates that the error code is not used, which may not be true. + // We currently do not use this information. + use_site: None, + }); + } match format { OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s), OutputFormat::HTML(h) => render_error_page(&err_map, dst, h)?, @@ -272,3 +254,5 @@ fn main() { panic!("{}", e.description()); } } + +include!(concat!(env!("OUT_DIR"), "/error_codes.rs")); From 72e2cfd93438ef0109cbaca9f961efa5ac6d4f84 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 19 Aug 2019 18:26:08 -0400 Subject: [PATCH 053/618] Remove serialization of diagnostics to files This is no longer used by the index generator and was always an unstable compiler detail, so strip it out. This also leaves in RUSTC_ERROR_METADATA_DST since the stage0 compiler still needs it to be set. --- src/bootstrap/doc.rs | 3 +- src/bootstrap/test.rs | 3 +- src/libsyntax/diagnostics/metadata.rs | 93 ------------------------- src/libsyntax/diagnostics/plugin.rs | 34 ++------- src/libsyntax/lib.rs | 1 - src/tools/error_index_generator/main.rs | 11 +-- 6 files changed, 13 insertions(+), 132 deletions(-) delete mode 100644 src/libsyntax/diagnostics/metadata.rs diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 36229720e42cd..4f96c12fc1ddd 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -825,8 +825,7 @@ impl Step for ErrorIndex { index.arg(crate::channel::CFG_RELEASE_NUM); // FIXME: shouldn't have to pass this env var - index.env("CFG_BUILD", &builder.config.build) - .env("RUSTC_ERROR_METADATA_DST", builder.extended_error_dir()); + index.env("CFG_BUILD", &builder.config.build); builder.run(&mut index); } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index c2c134bfd1d7d..87bd5cbacfffa 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1535,8 +1535,7 @@ impl Step for ErrorIndex { ); tool.arg("markdown") .arg(&output) - .env("CFG_BUILD", &builder.config.build) - .env("RUSTC_ERROR_METADATA_DST", builder.extended_error_dir()); + .env("CFG_BUILD", &builder.config.build); builder.info(&format!("Testing error-index stage{}", compiler.stage)); let _time = util::timeit(&builder); diff --git a/src/libsyntax/diagnostics/metadata.rs b/src/libsyntax/diagnostics/metadata.rs deleted file mode 100644 index 53f37bb10bdc0..0000000000000 --- a/src/libsyntax/diagnostics/metadata.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! This module contains utilities for outputting metadata for diagnostic errors. -//! -//! Each set of errors is mapped to a metadata file by a name, which is -//! currently always a crate name. - -use std::collections::BTreeMap; -use std::env; -use std::fs::{remove_file, create_dir_all, File}; -use std::io::Write; -use std::path::PathBuf; -use std::error::Error; -use rustc_serialize::json::as_json; - -use syntax_pos::{Span, FileName}; - -use crate::ext::base::ExtCtxt; -use crate::diagnostics::plugin::{ErrorMap, ErrorInfo}; - -/// JSON encodable/decodable version of `ErrorInfo`. -#[derive(PartialEq, RustcDecodable, RustcEncodable)] -pub struct ErrorMetadata { - pub description: Option, - pub use_site: Option -} - -/// Mapping from error codes to metadata that can be (de)serialized. -pub type ErrorMetadataMap = BTreeMap; - -/// JSON encodable error location type with filename and line number. -#[derive(PartialEq, RustcDecodable, RustcEncodable)] -pub struct ErrorLocation { - pub filename: FileName, - pub line: usize -} - -impl ErrorLocation { - /// Creates an error location from a span. - pub fn from_span(ecx: &ExtCtxt<'_>, sp: Span) -> ErrorLocation { - let loc = ecx.source_map().lookup_char_pos(sp.lo()); - ErrorLocation { - filename: loc.file.name.clone(), - line: loc.line - } - } -} - -/// Gets the directory where metadata for a given `prefix` should be stored. -/// -/// See `output_metadata`. -pub fn get_metadata_dir(prefix: &str) -> PathBuf { - env::var_os("RUSTC_ERROR_METADATA_DST") - .map(PathBuf::from) - .expect("env var `RUSTC_ERROR_METADATA_DST` isn't set") - .join(prefix) -} - -/// Map `name` to a path in the given directory: /.json -fn get_metadata_path(directory: PathBuf, name: &str) -> PathBuf { - directory.join(format!("{}.json", name)) -} - -/// Write metadata for the errors in `err_map` to disk, to a file corresponding to `prefix/name`. -/// -/// For our current purposes the prefix is the target architecture and the name is a crate name. -/// If an error occurs steps will be taken to ensure that no file is created. -pub fn output_metadata(ecx: &ExtCtxt<'_>, prefix: &str, name: &str, err_map: &ErrorMap) - -> Result<(), Box> -{ - // Create the directory to place the file in. - let metadata_dir = get_metadata_dir(prefix); - create_dir_all(&metadata_dir)?; - - // Open the metadata file. - let metadata_path = get_metadata_path(metadata_dir, name); - let mut metadata_file = File::create(&metadata_path)?; - - // Construct a serializable map. - let json_map = err_map.iter().map(|(k, &ErrorInfo { description, use_site })| { - let key = k.as_str().to_string(); - let value = ErrorMetadata { - description: description.map(|n| n.as_str().to_string()), - use_site: use_site.map(|sp| ErrorLocation::from_span(ecx, sp)) - }; - (key, value) - }).collect::(); - - // Write the data to the file, deleting it if the write fails. - let result = write!(&mut metadata_file, "{}", as_json(&json_map)); - if result.is_err() { - remove_file(&metadata_path)?; - } - Ok(result?) -} diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 9618b5acfb0f1..e9a55af52e878 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -1,5 +1,4 @@ use std::collections::BTreeMap; -use std::env; use crate::ast::{self, Ident, Name}; use crate::source_map; @@ -12,8 +11,6 @@ use crate::tokenstream::{TokenTree}; use smallvec::smallvec; use syntax_pos::Span; -use crate::diagnostics::metadata::output_metadata; - pub use errors::*; // Maximum width of any line in an extended error description (inclusive). @@ -127,36 +124,13 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt<'_>, token_tree: &[TokenTree]) -> Box { assert_eq!(token_tree.len(), 3); - let (crate_name, ident) = match (&token_tree[0], &token_tree[2]) { - ( - // Crate name. - &TokenTree::Token(Token { kind: token::Ident(crate_name, _), .. }), - // DIAGNOSTICS ident. - &TokenTree::Token(Token { kind: token::Ident(name, _), span }) - ) => (crate_name, Ident::new(name, span)), + let ident = match &token_tree[2] { + // DIAGNOSTICS ident. + &TokenTree::Token(Token { kind: token::Ident(name, _), span }) + => Ident::new(name, span), _ => unreachable!() }; - // Output error metadata to `tmp/extended-errors//.json` - if let Ok(target_triple) = env::var("CFG_COMPILER_HOST_TRIPLE") { - ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { - if let Err(e) = output_metadata(ecx, - &target_triple, - &crate_name.as_str(), - diagnostics) { - ecx.span_bug(span, &format!( - "error writing metadata for triple `{}` and crate `{}`, error: {}, \ - cause: {:?}", - target_triple, crate_name, e.description(), e.source() - )); - } - }); - } else { - ecx.span_err(span, &format!( - "failed to write metadata for crate `{}` because $CFG_COMPILER_HOST_TRIPLE is not set", - crate_name)); - } - // Construct the output expression. let (count, expr) = ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 8ac48d8d74a42..1741932c1b80e 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -124,7 +124,6 @@ pub mod diagnostics { #[macro_use] pub mod macros; pub mod plugin; - pub mod metadata; } // N.B., this module needs to be declared first so diagnostics are diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index b35d304e760fe..c4826a0c31d6c 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -13,10 +13,16 @@ use std::path::PathBuf; use std::cell::RefCell; use syntax::edition::DEFAULT_EDITION; -use syntax::diagnostics::metadata::{ErrorMetadataMap, ErrorMetadata}; use rustdoc::html::markdown::{Markdown, IdMap, ErrorCodes, Playground}; +pub struct ErrorMetadata { + pub description: Option, +} + +/// Mapping from error codes to metadata that can be (de)serialized. +pub type ErrorMetadataMap = BTreeMap; + enum OutputFormat { HTML(HTMLFormatter), Markdown(MarkdownFormatter), @@ -214,9 +220,6 @@ fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box Date: Tue, 20 Aug 2019 19:16:01 +0300 Subject: [PATCH 054/618] use new get_args --- src/libstd/sys/wasi/args.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs index 14aa391912ed2..2d0ddea385afd 100644 --- a/src/libstd/sys/wasi/args.rs +++ b/src/libstd/sys/wasi/args.rs @@ -12,14 +12,16 @@ pub unsafe fn cleanup() { } pub struct Args { - iter: vec::IntoIter>, + iter: vec::IntoIter, _dont_send_or_sync_me: PhantomData<*mut ()>, } /// Returns the command line arguments pub fn args() -> Args { + let mut buf = Vec::new(); + let _ = wasi::get_args(|arg| buf.push(OsString::from_vec(arg.to_vec()))); Args { - iter: wasi::get_args().unwrap_or(Vec::new()).into_iter(), + iter: buf.into_iter(), _dont_send_or_sync_me: PhantomData } } @@ -33,7 +35,7 @@ impl Args { impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { - self.iter.next().map(OsString::from_vec) + self.iter.next() } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() From 7d92cf4826706669c7e1938fb879d91f572b717a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 20 Aug 2019 10:46:35 -0700 Subject: [PATCH 055/618] Bump toml dependency. Just removing an old/duplicated dependency from the workspace. --- Cargo.lock | 25 ++++++++----------------- src/bootstrap/Cargo.toml | 2 +- src/tools/build-manifest/Cargo.toml | 2 +- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a07a2f0c3da6..7f2ed3823f108 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -185,7 +185,7 @@ dependencies = [ "serde", "serde_json", "time", - "toml 0.4.10", + "toml", ] [[package]] @@ -202,7 +202,7 @@ name = "build-manifest" version = "0.1.0" dependencies = [ "serde", - "toml 0.4.10", + "toml", ] [[package]] @@ -316,7 +316,7 @@ dependencies = [ "tar", "tempfile", "termcolor", - "toml 0.5.3", + "toml", "unicode-width", "url 2.1.0", "walkdir", @@ -442,7 +442,7 @@ dependencies = [ "semver", "serde", "smallvec", - "toml 0.5.3", + "toml", "unicode-normalization", "url 2.1.0", ] @@ -1785,7 +1785,7 @@ dependencies = [ "serde_json", "shlex", "tempfile", - "toml 0.5.3", + "toml", "toml-query", ] @@ -2760,7 +2760,7 @@ dependencies = [ "tokio", "tokio-process", "tokio-timer", - "toml 0.5.3", + "toml", "url 1.7.2", "walkdir", ] @@ -3582,7 +3582,7 @@ dependencies = [ "serde_json", "structopt", "term 0.6.0", - "toml 0.5.3", + "toml", "unicode-segmentation", "unicode-width", "unicode_categories", @@ -4374,15 +4374,6 @@ dependencies = [ "tokio-reactor", ] -[[package]] -name = "toml" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" -dependencies = [ - "serde", -] - [[package]] name = "toml" version = "0.5.3" @@ -4403,7 +4394,7 @@ dependencies = [ "is-match", "lazy_static 1.3.0", "regex", - "toml 0.5.3", + "toml", "toml-query_derive", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 589ee9276a5a3..c27c318f5ad07 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -44,7 +44,7 @@ cc = "1.0.35" libc = "0.2" serde = { version = "1.0.8", features = ["derive"] } serde_json = "1.0.2" -toml = "0.4" +toml = "0.5" lazy_static = "1.3.0" time = "0.1" petgraph = "0.4.13" diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index 63b6399bb9034..c364479d8db13 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -5,5 +5,5 @@ authors = ["Alex Crichton "] edition = "2018" [dependencies] -toml = "0.4" +toml = "0.5" serde = { version = "1.0", features = ["derive"] } From 777a12c3a4533e70baa46391e8c557950191a7c7 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 20 Aug 2019 17:07:42 +0200 Subject: [PATCH 056/618] Use dedicated type for spans in pre-expansion gating. --- src/libsyntax/feature_gate.rs | 15 ++++++++------ src/libsyntax/parse/attr.rs | 5 ++--- src/libsyntax/parse/mod.rs | 32 +++++++++++++++++------------- src/libsyntax/parse/parser/expr.rs | 8 ++++---- src/libsyntax/parse/parser/pat.rs | 2 +- 5 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index bbc3ae2822558..df86ba790d6a6 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -2438,16 +2438,19 @@ pub fn check_crate(krate: &ast::Crate, }; macro_rules! gate_all { + ($gate:ident, $msg:literal) => { gate_all!($gate, $gate, $msg); }; ($spans:ident, $gate:ident, $msg:literal) => { - for span in &*sess.$spans.borrow() { gate_feature!(&ctx, $gate, *span, $msg); } + for span in &*sess.gated_spans.$spans.borrow() { + gate_feature!(&ctx, $gate, *span, $msg); + } } } - gate_all!(param_attr_spans, param_attrs, "attributes on function parameters are unstable"); - gate_all!(let_chains_spans, let_chains, "`let` expressions in this position are experimental"); - gate_all!(async_closure_spans, async_closure, "async closures are unstable"); - gate_all!(yield_spans, generators, "yield syntax is experimental"); - gate_all!(or_pattern_spans, or_patterns, "or-patterns syntax is experimental"); + gate_all!(param_attrs, "attributes on function parameters are unstable"); + gate_all!(let_chains, "`let` expressions in this position are experimental"); + gate_all!(async_closure, "async closures are unstable"); + gate_all!(yields, generators, "yield syntax is experimental"); + gate_all!(or_patterns, "or-patterns syntax is experimental"); let visitor = &mut PostExpansionVisitor { context: &ctx, diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index a42da1123600a..c703058e7952d 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -21,9 +21,8 @@ const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ impl<'a> Parser<'a> { crate fn parse_arg_attributes(&mut self) -> PResult<'a, Vec> { let attrs = self.parse_outer_attributes()?; - attrs.iter().for_each(|a| - self.sess.param_attr_spans.borrow_mut().push(a.span) - ); + self.sess.gated_spans.param_attrs.borrow_mut() + .extend(attrs.iter().map(|a| a.span)); Ok(attrs) } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index b1f3612a839a2..b1af4806e2d78 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -39,6 +39,22 @@ crate mod unescape_error_reporting; pub type PResult<'a, T> = Result>; +/// Collected spans during parsing for places where a certain feature was +/// used and should be feature gated accordingly in `check_crate`. +#[derive(Default)] +pub struct GatedSpans { + /// Spans collected for gating `param_attrs`, e.g. `fn foo(#[attr] x: u8) {}`. + pub param_attrs: Lock>, + /// Spans collected for gating `let_chains`, e.g. `if a && let b = c {}`. + pub let_chains: Lock>, + /// Spans collected for gating `async_closure`, e.g. `async || ..`. + pub async_closure: Lock>, + /// Spans collected for gating `yield e?` expressions (`generators` gate). + pub yields: Lock>, + /// Spans collected for gating `or_patterns`, e.g. `Some(Foo | Bar)`. + pub or_patterns: Lock>, +} + /// Info about a parsing session. pub struct ParseSess { pub span_diagnostic: Handler, @@ -58,16 +74,8 @@ pub struct ParseSess { /// operation token that followed it, but that the parser cannot identify without further /// analysis. pub ambiguous_block_expr_parse: Lock>, - pub param_attr_spans: Lock>, - // Places where `let` exprs were used and should be feature gated according to `let_chains`. - pub let_chains_spans: Lock>, - // Places where `async || ..` exprs were used and should be feature gated. - pub async_closure_spans: Lock>, - // Places where `yield e?` exprs were used and should be feature gated. - pub yield_spans: Lock>, pub injected_crate_name: Once, - // Places where or-patterns e.g. `Some(Foo | Bar)` were used and should be feature gated. - pub or_pattern_spans: Lock>, + pub gated_spans: GatedSpans, } impl ParseSess { @@ -93,12 +101,8 @@ impl ParseSess { buffered_lints: Lock::new(vec![]), edition: ExpnId::root().expn_data().edition, ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), - param_attr_spans: Lock::new(Vec::new()), - let_chains_spans: Lock::new(Vec::new()), - async_closure_spans: Lock::new(Vec::new()), - yield_spans: Lock::new(Vec::new()), injected_crate_name: Once::new(), - or_pattern_spans: Lock::new(Vec::new()), + gated_spans: GatedSpans::default(), } } diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index ccc6bd1506709..5da9b75d53b04 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -999,7 +999,7 @@ impl<'a> Parser<'a> { } let span = lo.to(hi); - self.sess.yield_spans.borrow_mut().push(span); + self.sess.gated_spans.yields.borrow_mut().push(span); } else if self.eat_keyword(kw::Let) { return self.parse_let_expr(attrs); } else if is_span_rust_2018 && self.eat_keyword(kw::Await) { @@ -1111,7 +1111,7 @@ impl<'a> Parser<'a> { }; if asyncness.is_async() { // Feature gate `async ||` closures. - self.sess.async_closure_spans.borrow_mut().push(self.prev_span); + self.sess.gated_spans.async_closure.borrow_mut().push(self.prev_span); } let capture_clause = self.parse_capture_clause(); @@ -1234,7 +1234,7 @@ impl<'a> Parser<'a> { if let ExprKind::Let(..) = cond.node { // Remove the last feature gating of a `let` expression since it's stable. - let last = self.sess.let_chains_spans.borrow_mut().pop(); + let last = self.sess.gated_spans.let_chains.borrow_mut().pop(); debug_assert_eq!(cond.span, last.unwrap()); } @@ -1252,7 +1252,7 @@ impl<'a> Parser<'a> { |this| this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into()) )?; let span = lo.to(expr.span); - self.sess.let_chains_spans.borrow_mut().push(span); + self.sess.gated_spans.let_chains.borrow_mut().push(span); Ok(self.mk_expr(span, ExprKind::Let(pats, expr), attrs)) } diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index fd458aec74331..8cfa6abbe6270 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -123,7 +123,7 @@ impl<'a> Parser<'a> { let or_pattern_span = lo.to(self.prev_span); - self.sess.or_pattern_spans.borrow_mut().push(or_pattern_span); + self.sess.gated_spans.or_patterns.borrow_mut().push(or_pattern_span); Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats))) } From d9497749a87440d836495da6d40a5ce667a67ccb Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 19 Aug 2019 19:02:12 -0700 Subject: [PATCH 057/618] Move argfile expansion into run_compiler This will make @path work with miri and other non-standard entrypoints. Also since this simplifies librustc_driver::args, move it into a simple source file. Also remove the tests since they're doing nothing more than checking `str::lines` has the right behaviour. --- src/librustc_driver/args.rs | 53 +++++++ src/librustc_driver/args/mod.rs | 84 ---------- src/librustc_driver/args/tests.rs | 145 ------------------ src/librustc_driver/lib.rs | 20 ++- src/test/ui/commandline-argfile-badutf8.rs | 1 - .../ui/commandline-argfile-badutf8.stderr | 2 +- src/test/ui/commandline-argfile-missing.rs | 2 +- .../ui/commandline-argfile-missing.stderr | 2 +- 8 files changed, 70 insertions(+), 239 deletions(-) create mode 100644 src/librustc_driver/args.rs delete mode 100644 src/librustc_driver/args/mod.rs delete mode 100644 src/librustc_driver/args/tests.rs diff --git a/src/librustc_driver/args.rs b/src/librustc_driver/args.rs new file mode 100644 index 0000000000000..0906d358badd4 --- /dev/null +++ b/src/librustc_driver/args.rs @@ -0,0 +1,53 @@ +use std::error; +use std::fmt; +use std::fs; +use std::io; +use std::str; +use std::sync::atomic::{AtomicBool, Ordering}; + +static USED_ARGSFILE_FEATURE: AtomicBool = AtomicBool::new(false); + +pub fn used_unstable_argsfile() -> bool { + USED_ARGSFILE_FEATURE.load(Ordering::Relaxed) +} + +pub fn arg_expand(arg: String) -> Result, Error> { + if arg.starts_with("@") { + let path = &arg[1..]; + let file = match fs::read_to_string(path) { + Ok(file) => { + USED_ARGSFILE_FEATURE.store(true, Ordering::Relaxed); + file + } + Err(ref err) if err.kind() == io::ErrorKind::InvalidData => { + return Err(Error::Utf8Error(Some(path.to_string()))); + } + Err(err) => return Err(Error::IOError(path.to_string(), err)), + }; + Ok(file.lines().map(ToString::to_string).collect()) + } else { + Ok(vec![arg]) + } +} + +#[derive(Debug)] +pub enum Error { + Utf8Error(Option), + IOError(String, io::Error), +} + +impl fmt::Display for Error { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::Utf8Error(None) => write!(fmt, "Utf8 error"), + Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {}", path), + Error::IOError(path, err) => write!(fmt, "IO Error: {}: {}", path, err), + } + } +} + +impl error::Error for Error { + fn description(&self) -> &'static str { + "argument error" + } +} diff --git a/src/librustc_driver/args/mod.rs b/src/librustc_driver/args/mod.rs deleted file mode 100644 index a59f9afd8beb5..0000000000000 --- a/src/librustc_driver/args/mod.rs +++ /dev/null @@ -1,84 +0,0 @@ -use std::env; -use std::error; -use std::fmt; -use std::fs; -use std::io; -use std::str; -use std::sync::atomic::{AtomicBool, Ordering}; - -#[cfg(test)] -mod tests; - -static USED_ARGSFILE_FEATURE: AtomicBool = AtomicBool::new(false); - -pub fn used_unstable_argsfile() -> bool { - USED_ARGSFILE_FEATURE.load(Ordering::Relaxed) -} - -pub struct ArgsIter { - base: env::ArgsOs, - file: std::vec::IntoIter, -} - -impl ArgsIter { - pub fn new() -> Self { - ArgsIter { base: env::args_os(), file: vec![].into_iter() } - } -} - -impl Iterator for ArgsIter { - type Item = Result; - - fn next(&mut self) -> Option { - loop { - if let Some(line) = self.file.next() { - return Some(Ok(line)); - } - - let arg = - self.base.next().map(|arg| arg.into_string().map_err(|_| Error::Utf8Error(None))); - match arg { - Some(Err(err)) => return Some(Err(err)), - Some(Ok(ref arg)) if arg.starts_with("@") => { - let path = &arg[1..]; - let file = match fs::read_to_string(path) { - Ok(file) => { - USED_ARGSFILE_FEATURE.store(true, Ordering::Relaxed); - file - } - Err(ref err) if err.kind() == io::ErrorKind::InvalidData => { - return Some(Err(Error::Utf8Error(Some(path.to_string())))); - } - Err(err) => return Some(Err(Error::IOError(path.to_string(), err))), - }; - self.file = - file.lines().map(ToString::to_string).collect::>().into_iter(); - } - Some(Ok(arg)) => return Some(Ok(arg)), - None => return None, - } - } - } -} - -#[derive(Debug)] -pub enum Error { - Utf8Error(Option), - IOError(String, io::Error), -} - -impl fmt::Display for Error { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Error::Utf8Error(None) => write!(fmt, "Utf8 error"), - Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {}", path), - Error::IOError(path, err) => write!(fmt, "IO Error: {}: {}", path, err), - } - } -} - -impl error::Error for Error { - fn description(&self) -> &'static str { - "argument error" - } -} diff --git a/src/librustc_driver/args/tests.rs b/src/librustc_driver/args/tests.rs deleted file mode 100644 index 080dd5cb746c3..0000000000000 --- a/src/librustc_driver/args/tests.rs +++ /dev/null @@ -1,145 +0,0 @@ -use super::*; - -use std::str; - -fn want_args(v: impl IntoIterator) -> Vec { - v.into_iter().map(String::from).collect() -} - -fn got_args(file: &[u8]) -> Result, Error> { - let ret = str::from_utf8(file) - .map_err(|_| Error::Utf8Error(None))? - .lines() - .map(ToString::to_string) - .collect::>(); - Ok(ret) -} - -#[test] -fn nothing() { - let file = b""; - - assert_eq!(got_args(file).unwrap(), want_args(vec![])); -} - -#[test] -fn empty() { - let file = b"\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec![""])); -} - -#[test] -fn simple() { - let file = b"foo"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"])); -} - -#[test] -fn simple_eol() { - let file = b"foo\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"])); -} - -#[test] -fn multi() { - let file = b"foo\nbar"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); -} - -#[test] -fn multi_eol() { - let file = b"foo\nbar\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); -} - -#[test] -fn multi_empty() { - let file = b"foo\n\nbar"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); -} - -#[test] -fn multi_empty_eol() { - let file = b"foo\n\nbar\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); -} - -#[test] -fn multi_empty_start() { - let file = b"\nfoo\nbar"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["", "foo", "bar"])); -} - -#[test] -fn multi_empty_end() { - let file = b"foo\nbar\n\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar", ""])); -} - -#[test] -fn simple_eol_crlf() { - let file = b"foo\r\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"])); -} - -#[test] -fn multi_crlf() { - let file = b"foo\r\nbar"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); -} - -#[test] -fn multi_eol_crlf() { - let file = b"foo\r\nbar\r\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); -} - -#[test] -fn multi_empty_crlf() { - let file = b"foo\r\n\r\nbar"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); -} - -#[test] -fn multi_empty_eol_crlf() { - let file = b"foo\r\n\r\nbar\r\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); -} - -#[test] -fn multi_empty_start_crlf() { - let file = b"\r\nfoo\r\nbar"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["", "foo", "bar"])); -} - -#[test] -fn multi_empty_end_crlf() { - let file = b"foo\r\nbar\r\n\r\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar", ""])); -} - -#[test] -fn bad_utf8() { - let file = b"foo\x80foo"; - - match got_args(file).unwrap_err() { - Error::Utf8Error(_) => (), - bad => panic!("bad err: {:?}", bad), - } -} diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 4843c1a951b31..2cec404c3d7f6 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -140,14 +140,22 @@ impl Callbacks for TimePassesCallbacks { // See comments on CompilerCalls below for details about the callbacks argument. // The FileLoader provides a way to load files from sources other than the file system. pub fn run_compiler( - args: &[String], + at_args: &[String], callbacks: &mut (dyn Callbacks + Send), file_loader: Option>, emitter: Option> ) -> interface::Result<()> { + let mut args = Vec::new(); + for arg in at_args { + match args::arg_expand(arg.clone()) { + Ok(arg) => args.extend(arg), + Err(err) => early_error(ErrorOutputType::default(), + &format!("Failed to load argument file: {}", err)), + } + } let diagnostic_output = emitter.map(|emitter| DiagnosticOutput::Raw(emitter)) .unwrap_or(DiagnosticOutput::Default); - let matches = match handle_options(args) { + let matches = match handle_options(&args) { Some(matches) => matches, None => return Ok(()), }; @@ -1199,10 +1207,10 @@ pub fn main() { init_rustc_env_logger(); let mut callbacks = TimePassesCallbacks::default(); let result = report_ices_to_stderr_if_any(|| { - let args = args::ArgsIter::new().enumerate() - .map(|(i, arg)| arg.unwrap_or_else(|err| { - early_error(ErrorOutputType::default(), - &format!("Argument {} is not valid: {}", i, err)) + let args = env::args_os().enumerate() + .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| { + early_error(ErrorOutputType::default(), + &format!("Argument {} is not valid Unicode: {:?}", i, arg)) })) .collect::>(); run_compiler(&args, &mut callbacks, None, None) diff --git a/src/test/ui/commandline-argfile-badutf8.rs b/src/test/ui/commandline-argfile-badutf8.rs index c017e7b5ea60b..161715685b57f 100644 --- a/src/test/ui/commandline-argfile-badutf8.rs +++ b/src/test/ui/commandline-argfile-badutf8.rs @@ -1,7 +1,6 @@ // Check to see if we can get parameters from an @argsfile file // // build-fail -// normalize-stderr-test: "Argument \d+" -> "Argument $$N" // compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args #[cfg(not(cmdline_set))] diff --git a/src/test/ui/commandline-argfile-badutf8.stderr b/src/test/ui/commandline-argfile-badutf8.stderr index cd8a03e34eac9..9af6fc0a518df 100644 --- a/src/test/ui/commandline-argfile-badutf8.stderr +++ b/src/test/ui/commandline-argfile-badutf8.stderr @@ -1,2 +1,2 @@ -error: Argument $N is not valid: Utf8 error in $DIR/commandline-argfile-badutf8.args +error: Failed to load argument file: Utf8 error in $DIR/commandline-argfile-badutf8.args diff --git a/src/test/ui/commandline-argfile-missing.rs b/src/test/ui/commandline-argfile-missing.rs index 34faf07633599..a29b4ab062de3 100644 --- a/src/test/ui/commandline-argfile-missing.rs +++ b/src/test/ui/commandline-argfile-missing.rs @@ -1,7 +1,7 @@ // Check to see if we can get parameters from an @argsfile file // +// ignore-tidy-linelength // build-fail -// normalize-stderr-test: "Argument \d+" -> "Argument $$N" // normalize-stderr-test: "os error \d+" -> "os error $$ERR" // normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " // compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args diff --git a/src/test/ui/commandline-argfile-missing.stderr b/src/test/ui/commandline-argfile-missing.stderr index c0017782f2eb3..179ad83100419 100644 --- a/src/test/ui/commandline-argfile-missing.stderr +++ b/src/test/ui/commandline-argfile-missing.stderr @@ -1,2 +1,2 @@ -error: Argument $N is not valid: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) +error: Failed to load argument file: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) From 7ee4f1da8c75b44501c01fb3e754c1732dad76c3 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 20 Aug 2019 18:10:43 +0200 Subject: [PATCH 058/618] Allow 'default async fn' to parse. --- src/libsyntax/parse/parser/item.rs | 1 + .../ui/specialization/issue-63716-parse-async.rs | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 src/test/ui/specialization/issue-63716-parse-async.rs diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 72819c9966035..03d7e92212382 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -825,6 +825,7 @@ impl<'a> Parser<'a> { self.is_keyword_ahead(1, &[ kw::Impl, kw::Const, + kw::Async, kw::Fn, kw::Unsafe, kw::Extern, diff --git a/src/test/ui/specialization/issue-63716-parse-async.rs b/src/test/ui/specialization/issue-63716-parse-async.rs new file mode 100644 index 0000000000000..c3764ffaab83f --- /dev/null +++ b/src/test/ui/specialization/issue-63716-parse-async.rs @@ -0,0 +1,14 @@ +// Ensure that `default async fn` will parse. +// See issue #63716 for details. + +// check-pass +// edition:2018 + +#![feature(specialization)] + +fn main() {} + +#[cfg(FALSE)] +impl Foo for Bar { + default async fn baz() {} +} From 13c1db981905ea61d2d4ef7bf067b7d495a7f219 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 20 Aug 2019 14:03:13 -0700 Subject: [PATCH 059/618] Update books --- src/doc/embedded-book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/embedded-book b/src/doc/embedded-book index c5da1e11915d3..432ca26686c11 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit c5da1e11915d3f28266168baaf55822f7e3fe999 +Subproject commit 432ca26686c11d396eed6a59499f93ce1bf2433c diff --git a/src/doc/nomicon b/src/doc/nomicon index 8a7d05615e5bc..38b9a76bc8b59 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 8a7d05615e5bc0a7fb961b4919c44f5221ee54da +Subproject commit 38b9a76bc8b59ac862663807fc51c9b757337fd6 diff --git a/src/doc/reference b/src/doc/reference index b4b3536839042..d191a0cdd3b92 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit b4b3536839042a6743fc76f0d9ad2a812020aeaa +Subproject commit d191a0cdd3b92648e0f1e53b13140a14677cc65b diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index f2c15ba5ee89a..580839d90aacd 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit f2c15ba5ee89ae9469a2cf60494977749901d764 +Subproject commit 580839d90aacd537f0293697096fa8355bc4e673 From 0c5220dc364a389935b5bd99f5f8e4ebbf47f6f8 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 18 Aug 2019 23:59:46 +0200 Subject: [PATCH 060/618] Test that Wrapping arithmetic ops are implemented for all int types --- src/libcore/num/wrapping.rs | 8 +++ src/test/ui/wrapping-int-combinations.rs | 73 ++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 src/test/ui/wrapping-int-combinations.rs diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index fd129a306d1c5..59a10ae99bb6a 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -18,6 +18,8 @@ macro_rules! sh_impl_signed { } } } + forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShlAssign<$f> for Wrapping<$t> { @@ -41,6 +43,8 @@ macro_rules! sh_impl_signed { } } } + forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShrAssign<$f> for Wrapping<$t> { @@ -64,6 +68,8 @@ macro_rules! sh_impl_unsigned { Wrapping(self.0.wrapping_shl((other & self::shift_max::$t as $f) as u32)) } } + forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShlAssign<$f> for Wrapping<$t> { @@ -83,6 +89,8 @@ macro_rules! sh_impl_unsigned { Wrapping(self.0.wrapping_shr((other & self::shift_max::$t as $f) as u32)) } } + forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShrAssign<$f> for Wrapping<$t> { diff --git a/src/test/ui/wrapping-int-combinations.rs b/src/test/ui/wrapping-int-combinations.rs new file mode 100644 index 0000000000000..e09f7232bd2fb --- /dev/null +++ b/src/test/ui/wrapping-int-combinations.rs @@ -0,0 +1,73 @@ +// run-pass + +use std::num::Wrapping; + +macro_rules! wrapping_operation { + ($result:expr, $lhs:ident $op:tt $rhs:expr) => { + assert_eq!($result, $lhs $op $rhs); + assert_eq!($result, &$lhs $op $rhs); + assert_eq!($result, $lhs $op &$rhs); + assert_eq!($result, &$lhs $op &$rhs); + }; + ($result:expr, $op:tt $expr:expr) => { + assert_eq!($result, $op $expr); + assert_eq!($result, $op &$expr); + }; +} + +macro_rules! wrapping_assignment { + ($result:expr, $lhs:ident $op:tt $rhs:expr) => { + let mut lhs1 = $lhs; + lhs1 $op $rhs; + assert_eq!($result, lhs1); + + let mut lhs2 = $lhs; + lhs2 $op &$rhs; + assert_eq!($result, lhs2); + }; +} + +macro_rules! wrapping_test { + ($type:ty, $min:expr, $max:expr) => { + let zero: Wrapping<$type> = Wrapping(0); + let one: Wrapping<$type> = Wrapping(1); + let min: Wrapping<$type> = Wrapping($min); + let max: Wrapping<$type> = Wrapping($max); + + wrapping_operation!(min, max + one); + wrapping_assignment!(min, max += one); + wrapping_operation!(max, min - one); + wrapping_assignment!(max, min -= one); + wrapping_operation!(max, max * one); + wrapping_assignment!(max, max *= one); + wrapping_operation!(max, max / one); + wrapping_assignment!(max, max /= one); + wrapping_operation!(zero, max % one); + wrapping_assignment!(zero, max %= one); + wrapping_operation!(zero, zero & max); + wrapping_assignment!(zero, zero &= max); + wrapping_operation!(max, zero | max); + wrapping_assignment!(max, zero |= max); + wrapping_operation!(zero, max ^ max); + wrapping_assignment!(zero, max ^= max); + wrapping_operation!(zero, zero << 1usize); + wrapping_assignment!(zero, zero <<= 1usize); + wrapping_operation!(zero, zero >> 1usize); + wrapping_assignment!(zero, zero >>= 1usize); + wrapping_operation!(zero, -zero); + wrapping_operation!(max, !min); + }; +} + +fn main() { + wrapping_test!(i8, std::i8::MIN, std::i8::MAX); + wrapping_test!(i16, std::i16::MIN, std::i16::MAX); + wrapping_test!(i32, std::i32::MIN, std::i32::MAX); + wrapping_test!(i64, std::i64::MIN, std::i64::MAX); + wrapping_test!(i128, std::i128::MIN, std::i128::MAX); + wrapping_test!(u8, std::u8::MIN, std::u8::MAX); + wrapping_test!(u16, std::u16::MIN, std::u16::MAX); + wrapping_test!(u32, std::u32::MIN, std::u32::MAX); + wrapping_test!(u64, std::u64::MIN, std::u64::MAX); + wrapping_test!(u128, std::u128::MIN, std::u128::MAX); +} From 418eb181ca5777fb06e29a2acf37a5c641340538 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 21 Aug 2019 00:23:08 +0200 Subject: [PATCH 061/618] async_await was stabilized in 1.39.0, not 1.38.0. --- src/libsyntax/feature_gate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index bce0b07db1c23..f7aaf5cd22a3d 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -855,7 +855,7 @@ declare_features! ( // Allows `const _: TYPE = VALUE`. (accepted, underscore_const_names, "1.37.0", Some(54912), None), // Allows free and inherent `async fn`s, `async` blocks, and `.await` expressions. - (accepted, async_await, "1.38.0", Some(50547), None), + (accepted, async_await, "1.39.0", Some(50547), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features From 40cb69da59f2c759dadf40c1d86d1d11a995d3dd Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Wed, 21 Aug 2019 00:15:11 +0000 Subject: [PATCH 062/618] fix libtest --- src/libtest/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index ef66c4df99da7..709c12f60fc41 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -965,12 +965,11 @@ fn use_color(opts: &TestOpts) -> bool { #[cfg(any( target_os = "cloudabi", - target_os = "redox", all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx") ))] fn stdout_isatty() -> bool { - // FIXME: Implement isatty on Redox and SGX + // FIXME: Implement isatty on SGX false } #[cfg(unix)] From 82cb2076072546c958fbe0e3c28f87849e42817a Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Wed, 21 Aug 2019 00:18:05 +0000 Subject: [PATCH 063/618] fix num_cpus --- src/libtest/lib.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 709c12f60fc41..216112cb6e0be 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1192,12 +1192,6 @@ fn get_concurrency() -> usize { } } - #[cfg(target_os = "redox")] - fn num_cpus() -> usize { - // FIXME: Implement num_cpus on Redox - 1 - } - #[cfg(target_os = "vxworks")] fn num_cpus() -> usize { // FIXME: Implement num_cpus on vxWorks @@ -1220,7 +1214,8 @@ fn get_concurrency() -> usize { target_os = "ios", target_os = "linux", target_os = "macos", - target_os = "solaris" + target_os = "solaris", + target_os = "redox", ))] fn num_cpus() -> usize { unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize } From 7dbc4b95fc274ac23453e1f4c3b01e22cc4e7836 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 21 Aug 2019 02:29:08 +0200 Subject: [PATCH 064/618] Remove some duplication when resolving constants --- src/librustc/ty/relate.rs | 24 +++--------------------- src/librustc/ty/sty.rs | 24 +++++++++++++++++------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 945e3e158eafb..565447dd7e1af 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -8,7 +8,7 @@ use crate::hir::def_id::DefId; use crate::ty::subst::{Kind, UnpackedKind, SubstsRef}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use crate::ty::error::{ExpectedFound, TypeError}; -use crate::mir::interpret::{ConstValue, Scalar, GlobalId}; +use crate::mir::interpret::{ConstValue, Scalar}; use std::rc::Rc; use std::iter; use rustc_target::spec::abi; @@ -551,26 +551,8 @@ pub fn super_relate_consts>( let tcx = relation.tcx(); let eagerly_eval = |x: &'tcx ty::Const<'tcx>| { - if let ConstValue::Unevaluated(def_id, substs) = x.val { - // FIXME(eddyb) get the right param_env. - let param_env = ty::ParamEnv::empty(); - if !substs.has_local_value() { - let instance = ty::Instance::resolve( - tcx.global_tcx(), - param_env, - def_id, - substs, - ); - if let Some(instance) = instance { - let cid = GlobalId { - instance, - promoted: None, - }; - if let Ok(ct) = tcx.const_eval(param_env.and(cid)) { - return ct.val; - } - } - } + if !x.val.has_local_value() { + return x.eval(tcx, relation.param_env()).val; } x.val }; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 2b173068b38e4..da66fdf5b1b1b 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2299,23 +2299,33 @@ impl<'tcx> Const<'tcx> { assert_eq!(self.ty, ty); // if `ty` does not depend on generic parameters, use an empty param_env let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size; + self.eval(tcx, param_env).val.try_to_bits(size) + } + + #[inline] + pub fn eval( + &self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ) -> &Const<'tcx> { + // FIXME(const_generics): this doesn't work right now, + // because it tries to relate an `Infer` to a `Param`. match self.val { - // FIXME(const_generics): this doesn't work right now, - // because it tries to relate an `Infer` to a `Param`. ConstValue::Unevaluated(did, substs) => { // if `substs` has no unresolved components, use and empty param_env let (param_env, substs) = param_env.with_reveal_all().and(substs).into_parts(); // try to resolve e.g. associated constants to their definition on an impl - let instance = ty::Instance::resolve(tcx, param_env, did, substs)?; + let instance = match ty::Instance::resolve(tcx, param_env, did, substs) { + Some(instance) => instance, + None => return self, + }; let gid = GlobalId { instance, promoted: None, }; - let evaluated = tcx.const_eval(param_env.and(gid)).ok()?; - evaluated.val.try_to_bits(size) + tcx.const_eval(param_env.and(gid)).unwrap_or(self) }, - // otherwise just extract a `ConstValue`'s bits if possible - _ => self.val.try_to_bits(size), + _ => self, } } From 0337cc117d3c972b7b98e5c09212d58d3d16a009 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 21 Aug 2019 00:37:17 +0000 Subject: [PATCH 065/618] Use more optimal Ord implementation for integers --- src/libcore/cmp.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index cb9feb074dd70..74e9ceb510a99 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -1012,9 +1012,9 @@ mod impls { impl Ord for $t { #[inline] fn cmp(&self, other: &$t) -> Ordering { - if *self == *other { Equal } - else if *self < *other { Less } - else { Greater } + if *self < *other { Less } + else if *self > *other { Greater } + else { Equal } } } )*) From 88fd9450aa2111fcbe981006a9c391d57775ec14 Mon Sep 17 00:00:00 2001 From: newpavlov Date: Wed, 21 Aug 2019 04:16:05 +0300 Subject: [PATCH 066/618] update args --- src/libstd/sys/wasi/args.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs index 2d0ddea385afd..de9ca62469d5d 100644 --- a/src/libstd/sys/wasi/args.rs +++ b/src/libstd/sys/wasi/args.rs @@ -18,8 +18,14 @@ pub struct Args { /// Returns the command line arguments pub fn args() -> Args { - let mut buf = Vec::new(); - let _ = wasi::get_args(|arg| buf.push(OsString::from_vec(arg.to_vec()))); + let buf = wasi::args_sizes_get().and_then(|args_sizes| { + let mut buf = Vec::with_capacity(args_sizes.get_count()); + wasi::get_args(args_sizes, |arg| { + let arg = OsString::from_vec(arg.to_vec()); + buf.push(arg); + })?; + Ok(buf) + }).unwrap_or(vec![]); Args { iter: buf.into_iter(), _dont_send_or_sync_me: PhantomData From 96983fc53009a2a2d2f93e7cec012634800be1fa Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 21 Aug 2019 06:25:37 +0000 Subject: [PATCH 067/618] Add comment to avoid accidentally remove the changes. --- src/libcore/cmp.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 74e9ceb510a99..167a9dd1c3620 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -1012,6 +1012,8 @@ mod impls { impl Ord for $t { #[inline] fn cmp(&self, other: &$t) -> Ordering { + // The order here is important to generate more optimal assembly. + // See for more info. if *self < *other { Less } else if *self > *other { Greater } else { Equal } From 9b8514bb873c4bf8cfa1b5342c7b79f0fab5614a Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 21 Aug 2019 09:06:55 +0200 Subject: [PATCH 068/618] ci: move libc mirrors to the rust-lang-ci-mirrors bucket --- src/ci/docker/dist-various-1/install-mipsel-musl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/dist-various-1/install-mipsel-musl.sh b/src/ci/docker/dist-various-1/install-mipsel-musl.sh index 9ae41218ee4fb..de8c359d16757 100755 --- a/src/ci/docker/dist-various-1/install-mipsel-musl.sh +++ b/src/ci/docker/dist-various-1/install-mipsel-musl.sh @@ -5,7 +5,7 @@ mkdir /usr/local/mipsel-linux-musl # Note that this originally came from: # https://downloads.openwrt.org/snapshots/trunk/malta/generic/ # OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 -URL="https://rust-lang-ci2.s3.amazonaws.com/libc" +URL="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc" FILE="OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2" curl -L "$URL/$FILE" | tar xjf - -C /usr/local/mipsel-linux-musl --strip-components=2 From 4d50b249d76c6335a04d0210f3118fb3bc8d1cbc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 21 Aug 2019 09:37:23 +0200 Subject: [PATCH 069/618] update Miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index 4f6f264c305ea..d77fe6c63ca4c 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 4f6f264c305ea30f1de90ad0c2f341e84d972b2e +Subproject commit d77fe6c63ca4c50b207a1161def90c9e57368d5b From c076d30ce45cc0ad573bc15d8f1c11db261924f3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 27 May 2019 15:57:44 +0200 Subject: [PATCH 070/618] take into account the system theme --- src/librustdoc/html/static/rustdoc.css | 15 +++++++++++++++ src/librustdoc/html/static/storage.js | 16 +++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 59d10668f11ab..244b24af43f35 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -54,6 +54,21 @@ box-sizing: border-box; } +/* This part handles the "default" theme being used depending on the system one. */ +html { + content: ""; +} +@media (prefers-color-scheme: light) { + html { + content: "light"; + } +} +@media (prefers-color-scheme: dark) { + html { + content: "dark"; + } +} + /* General structure and fonts */ body { diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index e3927350d1104..86efc7815602f 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -86,7 +86,7 @@ function getCurrentValue(name) { return null; } -function switchTheme(styleElem, mainStyleElem, newTheme) { +function switchTheme(styleElem, mainStyleElem, newTheme, skipStorage) { var fullBasicCss = "rustdoc" + resourcesSuffix + ".css"; var fullNewTheme = newTheme + resourcesSuffix + ".css"; var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme); @@ -109,8 +109,18 @@ function switchTheme(styleElem, mainStyleElem, newTheme) { }); if (found === true) { styleElem.href = newHref; - updateLocalStorage("rustdoc-theme", newTheme); + // If this new value comes from a system setting or from the previously saved theme, no + // need to save it. + if (skipStorage !== true) { + updateLocalStorage("rustdoc-theme", newTheme); + } } } -switchTheme(currentTheme, mainTheme, getCurrentValue("rustdoc-theme") || "light"); +function getSystemValue() { + return getComputedStyle(document.documentElement).getPropertyValue('content'); +} + +switchTheme(currentTheme, mainTheme, + getCurrentValue("rustdoc-theme") || getSystemValue() || "light", + true); From 5a446c1ea9b829f291fe2d29b3ec7f1eabe8f26e Mon Sep 17 00:00:00 2001 From: Ferdia McKeogh Date: Wed, 21 Aug 2019 09:13:51 +0100 Subject: [PATCH 071/618] Fix `window.hashchange is not a function` --- src/librustdoc/html/static/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 82d2c11b2497b..1f5a9447f46b3 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -344,7 +344,7 @@ if (!DOMTokenList.prototype.remove) { var set_fragment = function(name) { if (browserSupportsHistoryApi()) { history.replaceState(null, null, "#" + name); - window.hashchange(); + highlightSourceLines(null); } else { location.replace("#" + name); } From 1dd56aa3047851891e6a1923e8fec3569d0fc89f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 19 Aug 2019 23:10:07 +0300 Subject: [PATCH 072/618] Add a test for an opaque macro eagerly expanding its arguments --- src/test/ui/hygiene/eager-from-opaque.rs | 18 ++++++++++++++++++ src/test/ui/hygiene/eager-from-opaque.stderr | 8 ++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/test/ui/hygiene/eager-from-opaque.rs create mode 100644 src/test/ui/hygiene/eager-from-opaque.stderr diff --git a/src/test/ui/hygiene/eager-from-opaque.rs b/src/test/ui/hygiene/eager-from-opaque.rs new file mode 100644 index 0000000000000..57925d626b9d1 --- /dev/null +++ b/src/test/ui/hygiene/eager-from-opaque.rs @@ -0,0 +1,18 @@ +// Opaque macro can eagerly expand its input without breaking its resolution. +// Regression test for issue #63685. + +macro_rules! foo { + () => { + "foo" + }; +} + +macro_rules! bar { + () => { + foo!() //~ ERROR cannot find macro `foo!` in this scope + }; +} + +fn main() { + format_args!(bar!()); +} diff --git a/src/test/ui/hygiene/eager-from-opaque.stderr b/src/test/ui/hygiene/eager-from-opaque.stderr new file mode 100644 index 0000000000000..8db96e6ac95e5 --- /dev/null +++ b/src/test/ui/hygiene/eager-from-opaque.stderr @@ -0,0 +1,8 @@ +error: cannot find macro `foo!` in this scope + --> $DIR/eager-from-opaque.rs:12:9 + | +LL | foo!() + | ^^^ + +error: aborting due to previous error + From 96032aa5efd82c3cddc485332162614b9b8dd3dd Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 19 Aug 2019 23:35:25 +0300 Subject: [PATCH 073/618] expand: Keep the correct current expansion ID for eager expansions Solve the problem of `ParentScope` entries for eager expansions not exising in the resolver map by creating them on demand. --- src/librustc_resolve/macros.rs | 4 +++- src/libsyntax/ext/expand.rs | 1 - src/test/ui/hygiene/eager-from-opaque.stderr | 3 +++ src/test/ui/macros/derive-in-eager-expansion-hang.stderr | 3 +++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 01ad67252a387..8a7a30813c1e0 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -142,7 +142,9 @@ impl<'a> base::Resolver for Resolver<'a> { fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: ExpnId, force: bool) -> Result>, Indeterminate> { - let parent_scope = self.invocation_parent_scopes[&invoc_id]; + let inherited_parent_scope = self.invocation_parent_scopes[&invoc_id]; + let parent_scope = *self.invocation_parent_scopes.entry(invoc.expansion_data.id) + .or_insert(inherited_parent_scope); let (path, kind, derives, after_derive) = match invoc.kind { InvocationKind::Attr { ref attr, ref derives, after_derive, .. } => (&attr.path, MacroKind::Attr, self.arenas.alloc_ast_paths(derives), after_derive), diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index c1d52c9745529..5ac234b78d0fe 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -318,7 +318,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { progress = true; let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data; self.cx.current_expansion = invoc.expansion_data.clone(); - self.cx.current_expansion.id = scope; // FIXME(jseyfried): Refactor out the following logic let (expanded_fragment, new_invocations) = if let Some(ext) = ext { diff --git a/src/test/ui/hygiene/eager-from-opaque.stderr b/src/test/ui/hygiene/eager-from-opaque.stderr index 8db96e6ac95e5..f696e6caff7ca 100644 --- a/src/test/ui/hygiene/eager-from-opaque.stderr +++ b/src/test/ui/hygiene/eager-from-opaque.stderr @@ -3,6 +3,9 @@ error: cannot find macro `foo!` in this scope | LL | foo!() | ^^^ +... +LL | format_args!(bar!()); + | ------ in this macro invocation error: aborting due to previous error diff --git a/src/test/ui/macros/derive-in-eager-expansion-hang.stderr b/src/test/ui/macros/derive-in-eager-expansion-hang.stderr index 1ef9427666bc5..5ca4088e585db 100644 --- a/src/test/ui/macros/derive-in-eager-expansion-hang.stderr +++ b/src/test/ui/macros/derive-in-eager-expansion-hang.stderr @@ -8,6 +8,9 @@ LL | | LL | | "" LL | | } | |_____^ +... +LL | format_args!(hang!()); + | ------- in this macro invocation help: you might be missing a string literal to format with | LL | format_args!("{}", hang!()); From a83c35692fa5fc65ec9860599501f1a5a5e98214 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 19 Aug 2019 23:44:57 +0300 Subject: [PATCH 074/618] expand: Do not do questionable span adjustment before eagerly expanding an expression Maybe it made sense when it was introduced, but now it's doing something incorrect. --- src/libsyntax/ext/base.rs | 5 +---- src/test/ui/hygiene/eager-from-opaque.rs | 4 +++- src/test/ui/hygiene/eager-from-opaque.stderr | 11 ----------- 3 files changed, 4 insertions(+), 16 deletions(-) delete mode 100644 src/test/ui/hygiene/eager-from-opaque.stderr diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index b0a4a6af9839c..376df4062b116 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -908,12 +908,9 @@ impl<'a> ExtCtxt<'a> { /// compilation on error, merely emits a non-fatal error and returns `None`. pub fn expr_to_spanned_string<'a>( cx: &'a mut ExtCtxt<'_>, - mut expr: P, + expr: P, err_msg: &str, ) -> Result<(Symbol, ast::StrStyle, Span), Option>> { - // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation. - expr.span = expr.span.apply_mark(cx.current_expansion.id); - // Perform eager expansion on the expression. // We want to be able to handle e.g., `concat!("foo", "bar")`. let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); diff --git a/src/test/ui/hygiene/eager-from-opaque.rs b/src/test/ui/hygiene/eager-from-opaque.rs index 57925d626b9d1..6f3215dd697f3 100644 --- a/src/test/ui/hygiene/eager-from-opaque.rs +++ b/src/test/ui/hygiene/eager-from-opaque.rs @@ -1,6 +1,8 @@ // Opaque macro can eagerly expand its input without breaking its resolution. // Regression test for issue #63685. +// check-pass + macro_rules! foo { () => { "foo" @@ -9,7 +11,7 @@ macro_rules! foo { macro_rules! bar { () => { - foo!() //~ ERROR cannot find macro `foo!` in this scope + foo!() }; } diff --git a/src/test/ui/hygiene/eager-from-opaque.stderr b/src/test/ui/hygiene/eager-from-opaque.stderr deleted file mode 100644 index f696e6caff7ca..0000000000000 --- a/src/test/ui/hygiene/eager-from-opaque.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: cannot find macro `foo!` in this scope - --> $DIR/eager-from-opaque.rs:12:9 - | -LL | foo!() - | ^^^ -... -LL | format_args!(bar!()); - | ------ in this macro invocation - -error: aborting due to previous error - From 93d369bc2b65e822d001a8d08f99c6bbaf105ee5 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 20 Aug 2019 00:24:28 +0300 Subject: [PATCH 075/618] resolve/expand: Rename some things for clarity and add comments --- src/librustc_resolve/macros.rs | 36 +++++++++++++++++++++------------- src/libsyntax/ext/base.rs | 5 +++-- src/libsyntax/ext/expand.rs | 6 ++++-- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 8a7a30813c1e0..719167eb057b2 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -140,11 +140,23 @@ impl<'a> base::Resolver for Resolver<'a> { ImportResolver { r: self }.resolve_imports() } - fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: ExpnId, force: bool) - -> Result>, Indeterminate> { - let inherited_parent_scope = self.invocation_parent_scopes[&invoc_id]; - let parent_scope = *self.invocation_parent_scopes.entry(invoc.expansion_data.id) - .or_insert(inherited_parent_scope); + fn resolve_macro_invocation( + &mut self, invoc: &Invocation, eager_expansion_root: ExpnId, force: bool + ) -> Result>, Indeterminate> { + let invoc_id = invoc.expansion_data.id; + let parent_scope = match self.invocation_parent_scopes.get(&invoc_id) { + Some(parent_scope) => *parent_scope, + None => { + // If there's no entry in the table, then we are resolving an eagerly expanded + // macro, which should inherit its parent scope from its eager expansion root - + // the macro that requested this eager expansion. + let parent_scope = *self.invocation_parent_scopes.get(&eager_expansion_root) + .expect("non-eager expansion without a parent scope"); + self.invocation_parent_scopes.insert(invoc_id, parent_scope); + parent_scope + } + }; + let (path, kind, derives, after_derive) = match invoc.kind { InvocationKind::Attr { ref attr, ref derives, after_derive, .. } => (&attr.path, MacroKind::Attr, self.arenas.alloc_ast_paths(derives), after_derive), @@ -163,7 +175,7 @@ impl<'a> base::Resolver for Resolver<'a> { match self.resolve_macro_path(path, Some(MacroKind::Derive), &parent_scope, true, force) { Ok((Some(ref ext), _)) if ext.is_derive_copy => { - self.add_derives(invoc.expansion_data.id, SpecialDerives::COPY); + self.add_derives(invoc_id, SpecialDerives::COPY); return Ok(None); } Err(Determinacy::Undetermined) => result = Err(Indeterminate), @@ -180,19 +192,15 @@ impl<'a> base::Resolver for Resolver<'a> { let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, force)?; let span = invoc.span(); - invoc.expansion_data.id.set_expn_data( - ext.expn_data(parent_scope.expansion, span, fast_print_path(path)) - ); + invoc_id.set_expn_data(ext.expn_data(parent_scope.expansion, span, fast_print_path(path))); if let Res::Def(_, def_id) = res { if after_derive { self.session.span_err(span, "macro attributes must be placed before `#[derive]`"); } - self.macro_defs.insert(invoc.expansion_data.id, def_id); - let normal_module_def_id = - self.macro_def_scope(invoc.expansion_data.id).normal_ancestor_id; - self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.id, - normal_module_def_id); + self.macro_defs.insert(invoc_id, def_id); + let normal_module_def_id = self.macro_def_scope(invoc_id).normal_ancestor_id; + self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id); } Ok(Some(ext)) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 376df4062b116..075e6a8001336 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -682,8 +682,9 @@ pub trait Resolver { fn resolve_imports(&mut self); - fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: ExpnId, force: bool) - -> Result>, Indeterminate>; + fn resolve_macro_invocation( + &mut self, invoc: &Invocation, eager_expansion_root: ExpnId, force: bool + ) -> Result>, Indeterminate>; fn check_unused_macros(&self); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 5ac234b78d0fe..72f2c1375e7a2 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -305,9 +305,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { continue }; - let scope = + let eager_expansion_root = if self.monotonic { invoc.expansion_data.id } else { orig_expansion_data.id }; - let ext = match self.cx.resolver.resolve_macro_invocation(&invoc, scope, force) { + let ext = match self.cx.resolver.resolve_macro_invocation( + &invoc, eager_expansion_root, force + ) { Ok(ext) => ext, Err(Indeterminate) => { undetermined_invocations.push(invoc); From d8c5bc7ec6ea2501bdbd2853551aa83175d6e8d0 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Tue, 30 Jul 2019 23:10:51 +0200 Subject: [PATCH 076/618] Replace usage of alloc.bytes in interpret There is now a dedicate `len` method which avoids the need to access the bytes. Access the length as `Size` can also be done by a direct member. The constructors guarantee that these representations are convertable. Access which relies on the bytes, such as snapshot, can use direct raw access by reference as it does not care about undef and relocations or properly checks them seperately. --- src/librustc/mir/interpret/allocation.rs | 2 ++ src/librustc_mir/interpret/intrinsics.rs | 2 +- .../interpret/intrinsics/type_name.rs | 2 +- src/librustc_mir/interpret/memory.rs | 25 +++++++++++-------- src/librustc_mir/interpret/snapshot.rs | 20 +++++++++++++-- 5 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index e0ada7e2f11a3..bfbfffeb3b8c6 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -13,6 +13,8 @@ use rustc_data_structures::sorted_map::SortedMap; use rustc_target::abi::HasDataLayout; use std::borrow::Cow; +// NOTE: When adding new fields, make sure to adjust the Snapshot impl in +// `src/librustc_mir/interpret/snapshot.rs`. #[derive( Clone, Debug, diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 89c5be137a4e5..a48a4abf796b2 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -81,7 +81,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let alloc = alloc_type_name(self.tcx.tcx, substs.type_at(0)); let name_id = self.tcx.alloc_map.lock().create_memory_alloc(alloc); let id_ptr = self.memory.tag_static_base_pointer(name_id.into()); - let alloc_len = alloc.bytes.len() as u64; + let alloc_len = alloc.size.bytes(); let name_val = Immediate::new_slice(Scalar::Ptr(id_ptr), alloc_len, self); self.write_immediate(name_val, dest)?; } diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs index f207cfc6b39cd..032d16a49db4b 100644 --- a/src/librustc_mir/interpret/intrinsics/type_name.rs +++ b/src/librustc_mir/interpret/intrinsics/type_name.rs @@ -221,7 +221,7 @@ pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> val: ConstValue::Slice { data: alloc, start: 0, - end: alloc.bytes.len(), + end: alloc.len(), }, ty: tcx.mk_static_str(), }) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index f572651f02b56..15180265ad29f 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -210,7 +210,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let new_ptr = self.allocate(new_size, new_align, kind); let old_size = match old_size_and_align { Some((size, _align)) => size, - None => Size::from_bytes(self.get(ptr.alloc_id)?.bytes.len() as u64), + None => self.get(ptr.alloc_id)?.size, }; self.copy( ptr, @@ -271,20 +271,20 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { )) } if let Some((size, align)) = old_size_and_align { - if size.bytes() != alloc.bytes.len() as u64 || align != alloc.align { - let bytes = Size::from_bytes(alloc.bytes.len() as u64); + if size != alloc.size || align != alloc.align { + let bytes = alloc.size; throw_unsup!(IncorrectAllocationInformation(size, bytes, align, alloc.align)) } } // Let the machine take some extra action - let size = Size::from_bytes(alloc.bytes.len() as u64); + let size = alloc.size; AllocationExtra::memory_deallocated(&mut alloc, ptr, size)?; // Don't forget to remember size and align of this now-dead allocation let old = self.dead_alloc_map.insert( ptr.alloc_id, - (Size::from_bytes(alloc.bytes.len() as u64), alloc.align) + (alloc.size, alloc.align) ); if old.is_some() { bug!("Nothing can be deallocated twice"); @@ -555,7 +555,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // a) cause cycles in case `id` refers to a static // b) duplicate a static's allocation in miri if let Some((_, alloc)) = self.alloc_map.get(id) { - return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)); + return Ok((alloc.size, alloc.align)); } // # Function pointers @@ -583,7 +583,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Some(GlobalAlloc::Memory(alloc)) => // Need to duplicate the logic here, because the global allocations have // different associated types than the interpreter-local ones. - Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)), + Ok((alloc.size, alloc.align)), Some(GlobalAlloc::Function(_)) => bug!("We already checked function pointers above"), // The rest must be dead. @@ -645,7 +645,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let prefix_len = msg.len(); let mut relocations = vec![]; - for i in 0..(alloc.bytes.len() as u64) { + for i in 0..alloc.size.bytes() { let i = Size::from_bytes(i); if let Some(&(_, target_id)) = alloc.relocations.get(&i) { if allocs_seen.insert(target_id) { @@ -655,7 +655,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } if alloc.undef_mask.is_range_defined(i, i + Size::from_bytes(1)).is_ok() { // this `as usize` is fine, since `i` came from a `usize` - write!(msg, "{:02x} ", alloc.bytes[i.bytes() as usize]).unwrap(); + let i = i.bytes() as usize; + + // Checked definedness (and thus range) and relocations. This access also doesn't + // influence interpreter execution but is only for debugging. + let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(i..i+1); + write!(msg, "{:02x} ", bytes[0]).unwrap(); } else { msg.push_str("__ "); } @@ -664,7 +669,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { trace!( "{}({} bytes, alignment {}){}", msg, - alloc.bytes.len(), + alloc.size.bytes(), alloc.align.bytes(), extra ); diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 47289064f4d0d..0f0c422d8d3f4 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -15,7 +15,7 @@ use rustc::mir::interpret::{ }; use rustc::ty::{self, TyCtxt}; -use rustc::ty::layout::Align; +use rustc::ty::layout::{Align, Size}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -276,6 +276,7 @@ struct AllocationSnapshot<'a> { relocations: Relocations<(), AllocIdSnapshot<'a>>, undef_mask: &'a UndefMask, align: &'a Align, + size: &'a Size, mutability: &'a Mutability, } @@ -285,12 +286,27 @@ impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation type Item = AllocationSnapshot<'a>; fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - let Allocation { bytes, relocations, undef_mask, align, mutability, extra: () } = self; + let Allocation { + relocations, + size, + align, + mutability, + extra: (), + .. + } = self; + + let all_bytes = 0..self.len(); + // This 'inspect' is okay since following access respects undef and relocations. This does + // influence interpreter exeuction, but only to detect the error of cycles in evalution + // dependencies. + let bytes = self.inspect_with_undef_and_ptr_outside_interpreter(all_bytes); + let undef_mask = self.undef_mask(); AllocationSnapshot { bytes, undef_mask, align, + size, mutability, relocations: relocations.snapshot(ctx), } From 7b941e368fac6612eacf3423eac0149ef5ca3bb3 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Wed, 14 Aug 2019 02:26:18 +0200 Subject: [PATCH 077/618] Expose encapsulated undef mask as immutable --- src/librustc/mir/interpret/allocation.rs | 5 +++++ src/librustc_mir/interpret/memory.rs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index bfbfffeb3b8c6..d3f87f16313d0 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -143,6 +143,11 @@ impl Allocation { pub fn inspect_with_undef_and_ptr_outside_interpreter(&self, range: Range) -> &[u8] { &self.bytes[range] } + + /// View the undef mask. + pub fn undef_mask(&self) -> &UndefMask { + &self.undef_mask + } } impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Allocation {} diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 15180265ad29f..f7576a41e0f00 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -653,7 +653,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } relocations.push((i, target_id)); } - if alloc.undef_mask.is_range_defined(i, i + Size::from_bytes(1)).is_ok() { + if alloc.undef_mask().is_range_defined(i, i + Size::from_bytes(1)).is_ok() { // this `as usize` is fine, since `i` came from a `usize` let i = i.bytes() as usize; From df58fcffbcc2dea6eb31934424ce74b3636c5b68 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Wed, 14 Aug 2019 04:40:03 +0200 Subject: [PATCH 078/618] Fix codegen with explicit allocation byte access --- src/librustc_codegen_llvm/consts.rs | 55 +++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 0077df3cf5eea..26eb870cfc0d4 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -35,11 +35,21 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll assert_eq!(offset as usize as u64, offset); let offset = offset as usize; if offset > next_offset { - llvals.push(cx.const_bytes(&alloc.bytes[next_offset..offset])); + // This `inspect` is okay since we have check that it is not within a relocation, it is + // within the bounds of the allocation, and it doesn't affect interpreter execution (we + // inspect the result after interpreter execution). Any undef byte is replaced with + // some arbitrary byte value. + // + // FIXME: relay undef bytes to codegen as undef const bytes + let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(next_offset..offset); + llvals.push(cx.const_bytes(bytes)); } let ptr_offset = read_target_uint( dl.endian, - &alloc.bytes[offset..(offset + pointer_size)], + // This `inspect` is okay since it is within the bounds of the allocation, it doesn't + // affect interpreter execution (we inspect the result after interpreter execution), + // and we properly interpret the relocation as a relocation pointer offset. + alloc.inspect_with_undef_and_ptr_outside_interpreter(offset..(offset + pointer_size)), ).expect("const_alloc_to_llvm: could not read relocation pointer") as u64; llvals.push(cx.scalar_to_backend( Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(), @@ -51,8 +61,16 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll )); next_offset = offset + pointer_size; } - if alloc.bytes.len() >= next_offset { - llvals.push(cx.const_bytes(&alloc.bytes[next_offset ..])); + if alloc.len() >= next_offset { + let range = next_offset..alloc.len(); + // This `inspect` is okay since we have check that it is after all relocations, it is + // within the bounds of the allocation, and it doesn't affect interpreter execution (we + // inspect the result after interpreter execution). Any undef byte is replaced with some + // arbitrary byte value. + // + // FIXME: relay undef bytes to codegen as undef const bytes + let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(range); + llvals.push(cx.const_bytes(bytes)); } cx.const_struct(&llvals, true) @@ -437,7 +455,23 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { // // We could remove this hack whenever we decide to drop macOS 10.10 support. if self.tcx.sess.target.target.options.is_like_osx { - let sect_name = if alloc.bytes.iter().all(|b| *b == 0) { + assert_eq!(alloc.relocations.len(), 0); + + let is_zeroed = { + // Treats undefined bytes as if they were defined with the byte value that + // happens to be currently assigned in mir. This is valid since reading + // undef bytes may yield arbitrary values. + // + // FIXME: ignore undef bytes even with representation `!= 0`. + // + // The `inspect` method is okay here because we checked relocations, and + // because we are doing this access to inspect the final interpreter state + // (not as part of the interpreter execution). + alloc.inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len()) + .iter() + .all(|b| *b == 0) + }; + let sect_name = if is_zeroed { CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0") } else { CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0") @@ -456,10 +490,17 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { section.as_str().as_ptr() as *const _, section.as_str().len() as c_uint, ); + assert!(alloc.relocations.is_empty()); + + // The `inspect` method is okay here because we checked relocations, and + // because we are doing this access to inspect the final interpreter state (not + // as part of the interpreter execution). + let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter( + 0..alloc.len()); let alloc = llvm::LLVMMDStringInContext( self.llcx, - alloc.bytes.as_ptr() as *const _, - alloc.bytes.len() as c_uint, + bytes.as_ptr() as *const _, + bytes.len() as c_uint, ); let data = [section, alloc]; let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2); From fe2dc919726d17dbe3568f1cb9de34c73b7f1dff Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 21 Aug 2019 12:53:11 +0300 Subject: [PATCH 079/618] Add a regression test for issue #63460 --- src/test/ui/hygiene/eager-from-opaque-2.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/test/ui/hygiene/eager-from-opaque-2.rs diff --git a/src/test/ui/hygiene/eager-from-opaque-2.rs b/src/test/ui/hygiene/eager-from-opaque-2.rs new file mode 100644 index 0000000000000..220e5526745c3 --- /dev/null +++ b/src/test/ui/hygiene/eager-from-opaque-2.rs @@ -0,0 +1,22 @@ +// Regression test for the issue #63460. + +// check-pass + +#[macro_export] +macro_rules! separator { + () => { "/" }; +} + +#[macro_export] +macro_rules! concat_separator { + ( $e:literal, $($other:literal),+ ) => { + concat!($e, $crate::separator!(), $crate::concat_separator!($($other),+)) + }; + ( $e:literal ) => { + $e + } +} + +fn main() { + println!("{}", concat_separator!(2, 3, 4)) +} From 5cf43bdd54a3e25c8d60da9179fd1bb38213d68e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Wed, 21 Aug 2019 12:14:00 +0200 Subject: [PATCH 080/618] Run Clippy without json-rendered flag --- src/bootstrap/builder.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 955809e80747b..4e49aaa16eae1 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -875,8 +875,7 @@ impl<'a> Builder<'a> { } if cmd == "clippy" { - extra_args.push_str("-Zforce-unstable-if-unmarked -Zunstable-options \ - --json-rendered=termcolor"); + extra_args.push_str("-Zforce-unstable-if-unmarked"); } if !extra_args.is_empty() { From a8d7ea74a463b0a31817c00a6bb09e9146e97834 Mon Sep 17 00:00:00 2001 From: Artem Varaksa Date: Wed, 21 Aug 2019 13:17:59 +0300 Subject: [PATCH 081/618] improve diagnostics: break/continue wrong context --- src/librustc_passes/error_codes.rs | 2 +- src/librustc_passes/loops.rs | 37 +++++++++---------- src/test/ui/array-break-length.stderr | 8 ++-- ...block-control-flow-static-semantics.stderr | 16 ++++++-- src/test/ui/break-outside-loop.stderr | 21 +++++++---- .../closure-array-break-length.stderr | 12 +++--- src/test/ui/error-codes/E0267.stderr | 4 +- src/test/ui/error-codes/E0268.stderr | 4 +- src/test/ui/issues/issue-28105.stderr | 8 ++-- src/test/ui/issues/issue-43162.stderr | 8 ++-- src/test/ui/issues/issue-50576.stderr | 8 ++-- src/test/ui/issues/issue-50581.stderr | 4 +- 12 files changed, 73 insertions(+), 59 deletions(-) diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs index cd33943e77e20..a30cd8a627fe3 100644 --- a/src/librustc_passes/error_codes.rs +++ b/src/librustc_passes/error_codes.rs @@ -131,7 +131,7 @@ be taken. Erroneous code example: ```compile_fail,E0268 fn some_func() { - break; // error: `break` outside of loop + break; // error: `break` outside of a loop } ``` diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 1547e607b9c61..4549ac8c668c5 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -16,8 +16,8 @@ use errors::Applicability; enum Context { Normal, Loop(hir::LoopSource), - Closure, - AsyncClosure, + Closure(Span), + AsyncClosure(Span), LabeledBlock, AnonConst, } @@ -58,11 +58,11 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { hir::ExprKind::Loop(ref b, _, source) => { self.with_context(Loop(source), |v| v.visit_block(&b)); } - hir::ExprKind::Closure(_, ref function_decl, b, _, movability) => { + hir::ExprKind::Closure(_, ref function_decl, b, span, movability) => { let cx = if let Some(GeneratorMovability::Static) = movability { - AsyncClosure + AsyncClosure(span) } else { - Closure + Closure(span) }; self.visit_fn_decl(&function_decl); self.with_context(cx, |v| v.visit_nested_body(b)); @@ -170,23 +170,22 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { } fn require_break_cx(&self, name: &str, span: Span) { - match self.cx { - LabeledBlock | Loop(_) => {} - Closure => { - struct_span_err!(self.sess, span, E0267, "`{}` inside of a closure", name) - .span_label(span, "cannot break inside of a closure") + let err_inside_of = |article, r#type, closure_span| { + struct_span_err!(self.sess, span, E0267, "`{}` inside of {} {}", name, article, r#type) + .span_label(span, format!("cannot `{}` inside of {} {}", name, article, r#type)) + .span_label(closure_span, &format!("enclosing {}", r#type)) .emit(); - } - AsyncClosure => { - struct_span_err!(self.sess, span, E0267, "`{}` inside of an async block", name) - .span_label(span, "cannot break inside of an async block") - .emit(); - } + }; + + match self.cx { + LabeledBlock | Loop(_) => {}, + Closure(closure_span) => err_inside_of("a", "closure", closure_span), + AsyncClosure(closure_span) => err_inside_of("an", "`async` block", closure_span), Normal | AnonConst => { - struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name) - .span_label(span, "cannot break outside of a loop") + struct_span_err!(self.sess, span, E0268, "`{}` outside of a loop", name) + .span_label(span, format!("cannot `{}` outside of a loop", name)) .emit(); - } + }, } } diff --git a/src/test/ui/array-break-length.stderr b/src/test/ui/array-break-length.stderr index 0e0dc8f623e68..45f529bafe728 100644 --- a/src/test/ui/array-break-length.stderr +++ b/src/test/ui/array-break-length.stderr @@ -1,14 +1,14 @@ -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/array-break-length.rs:3:17 | LL | |_: [_; break]| {} - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop -error[E0268]: `continue` outside of loop +error[E0268]: `continue` outside of a loop --> $DIR/array-break-length.rs:8:17 | LL | |_: [_; continue]| {} - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `continue` outside of a loop error[E0308]: mismatched types --> $DIR/array-break-length.rs:3:9 diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr index bc42a46ae1021..b33c8afe6b864 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -1,14 +1,22 @@ error[E0267]: `break` inside of an async block --> $DIR/async-block-control-flow-static-semantics.rs:33:9 | -LL | break 0u8; - | ^^^^^^^^^ cannot break inside of an async block +LL | async { + | ___________- +LL | | break 0u8; + | | ^^^^^^^^^ cannot `break` inside of an `async` block +LL | | }; + | |_____- enclosing `async` block error[E0267]: `break` inside of an async block --> $DIR/async-block-control-flow-static-semantics.rs:40:13 | -LL | break 0u8; - | ^^^^^^^^^ cannot break inside of an async block +LL | async { + | _______________- +LL | | break 0u8; + | | ^^^^^^^^^ cannot `break` inside of an `async` block +LL | | }; + | |_________- enclosing `async` block error[E0308]: mismatched types --> $DIR/async-block-control-flow-static-semantics.rs:13:43 diff --git a/src/test/ui/break-outside-loop.stderr b/src/test/ui/break-outside-loop.stderr index 8f4656ab394cd..8b686356055a3 100644 --- a/src/test/ui/break-outside-loop.stderr +++ b/src/test/ui/break-outside-loop.stderr @@ -1,32 +1,37 @@ -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/break-outside-loop.rs:10:15 | LL | let pth = break; - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop -error[E0268]: `continue` outside of loop +error[E0268]: `continue` outside of a loop --> $DIR/break-outside-loop.rs:11:17 | LL | if cond() { continue } - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `continue` outside of a loop error[E0267]: `break` inside of a closure --> $DIR/break-outside-loop.rs:17:25 | +LL | foo(|| { + | -- enclosing closure LL | if cond() { break } - | ^^^^^ cannot break inside of a closure + | ^^^^^ cannot `break` inside of a closure error[E0267]: `continue` inside of a closure --> $DIR/break-outside-loop.rs:18:25 | +LL | foo(|| { + | -- enclosing closure +LL | if cond() { break } LL | if cond() { continue } - | ^^^^^^^^ cannot break inside of a closure + | ^^^^^^^^ cannot `continue` inside of a closure -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/break-outside-loop.rs:24:25 | LL | let unconstrained = break; - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop error: aborting due to 5 previous errors diff --git a/src/test/ui/closures/closure-array-break-length.stderr b/src/test/ui/closures/closure-array-break-length.stderr index 46fbd3e0fae0b..18da4a94e6f05 100644 --- a/src/test/ui/closures/closure-array-break-length.stderr +++ b/src/test/ui/closures/closure-array-break-length.stderr @@ -1,20 +1,20 @@ -error[E0268]: `continue` outside of loop +error[E0268]: `continue` outside of a loop --> $DIR/closure-array-break-length.rs:2:13 | LL | |_: [_; continue]| {}; - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `continue` outside of a loop -error[E0268]: `continue` outside of loop +error[E0268]: `continue` outside of a loop --> $DIR/closure-array-break-length.rs:4:19 | LL | while |_: [_; continue]| {} {} - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `continue` outside of a loop -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/closure-array-break-length.rs:7:19 | LL | while |_: [_; break]| {} {} - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop error[E0308]: mismatched types --> $DIR/closure-array-break-length.rs:4:11 diff --git a/src/test/ui/error-codes/E0267.stderr b/src/test/ui/error-codes/E0267.stderr index b14cfd1a52d47..1f8657373efec 100644 --- a/src/test/ui/error-codes/E0267.stderr +++ b/src/test/ui/error-codes/E0267.stderr @@ -2,7 +2,9 @@ error[E0267]: `break` inside of a closure --> $DIR/E0267.rs:2:18 | LL | let w = || { break; }; - | ^^^^^ cannot break inside of a closure + | -- ^^^^^ cannot `break` inside of a closure + | | + | enclosing closure error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0268.stderr b/src/test/ui/error-codes/E0268.stderr index 3c77e7f3df2be..c926f9e487494 100644 --- a/src/test/ui/error-codes/E0268.stderr +++ b/src/test/ui/error-codes/E0268.stderr @@ -1,8 +1,8 @@ -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/E0268.rs:2:5 | LL | break; - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop error: aborting due to previous error diff --git a/src/test/ui/issues/issue-28105.stderr b/src/test/ui/issues/issue-28105.stderr index 0e1b90e65209b..42ed838d7c037 100644 --- a/src/test/ui/issues/issue-28105.stderr +++ b/src/test/ui/issues/issue-28105.stderr @@ -1,14 +1,14 @@ -error[E0268]: `continue` outside of loop +error[E0268]: `continue` outside of a loop --> $DIR/issue-28105.rs:4:5 | LL | continue - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `continue` outside of a loop -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/issue-28105.rs:6:5 | LL | break - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-43162.stderr b/src/test/ui/issues/issue-43162.stderr index 6d3e8b5ba2323..c729c05ff229e 100644 --- a/src/test/ui/issues/issue-43162.stderr +++ b/src/test/ui/issues/issue-43162.stderr @@ -1,14 +1,14 @@ -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/issue-43162.rs:3:5 | LL | break true; - | ^^^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^^^ cannot `break` outside of a loop -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/issue-43162.rs:7:5 | LL | break {}; - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `break` outside of a loop error[E0308]: mismatched types --> $DIR/issue-43162.rs:1:13 diff --git a/src/test/ui/issues/issue-50576.stderr b/src/test/ui/issues/issue-50576.stderr index 95619eeed9a46..9fea1411080f5 100644 --- a/src/test/ui/issues/issue-50576.stderr +++ b/src/test/ui/issues/issue-50576.stderr @@ -4,17 +4,17 @@ error[E0426]: use of undeclared label `'L` LL | |bool: [u8; break 'L]| 0; | ^^ undeclared label `'L` -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/issue-50576.rs:2:17 | LL | |bool: [u8; break 'L]| 0; - | ^^^^^^^^ cannot break outside of a loop + | ^^^^^^^^ cannot `break` outside of a loop -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/issue-50576.rs:5:16 | LL | Vec::<[u8; break]>::new(); - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-50581.stderr b/src/test/ui/issues/issue-50581.stderr index 01a5f9b3c4432..35d6fc49cedc8 100644 --- a/src/test/ui/issues/issue-50581.stderr +++ b/src/test/ui/issues/issue-50581.stderr @@ -1,8 +1,8 @@ -error[E0268]: `break` outside of loop +error[E0268]: `break` outside of a loop --> $DIR/issue-50581.rs:2:14 | LL | |_: [u8; break]| (); - | ^^^^^ cannot break outside of a loop + | ^^^^^ cannot `break` outside of a loop error: aborting due to previous error From 1bd94241b756bda09c6e079f806c25440a3b2c81 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 21 Aug 2019 12:49:01 +0200 Subject: [PATCH 082/618] Replaced skipStorage with saveTheme variable --- src/librustdoc/html/render.rs | 2 +- src/librustdoc/html/static/storage.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index ea97cea942820..211c4157da828 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -914,7 +914,7 @@ themePicker.onblur = handleThemeButtonsBlur; var but = document.createElement('button'); but.innerHTML = item; but.onclick = function(el) {{ - switchTheme(currentTheme, mainTheme, item); + switchTheme(currentTheme, mainTheme, item, true); }}; but.onblur = handleThemeButtonsBlur; themes.appendChild(but); diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index 86efc7815602f..c55b1e414436c 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -86,7 +86,7 @@ function getCurrentValue(name) { return null; } -function switchTheme(styleElem, mainStyleElem, newTheme, skipStorage) { +function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) { var fullBasicCss = "rustdoc" + resourcesSuffix + ".css"; var fullNewTheme = newTheme + resourcesSuffix + ".css"; var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme); @@ -111,7 +111,7 @@ function switchTheme(styleElem, mainStyleElem, newTheme, skipStorage) { styleElem.href = newHref; // If this new value comes from a system setting or from the previously saved theme, no // need to save it. - if (skipStorage !== true) { + if (saveTheme === true) { updateLocalStorage("rustdoc-theme", newTheme); } } @@ -123,4 +123,4 @@ function getSystemValue() { switchTheme(currentTheme, mainTheme, getCurrentValue("rustdoc-theme") || getSystemValue() || "light", - true); + false); From 3375b05cd03a60cd7e2df0e21e232c73ff8a01cb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 21 Aug 2019 13:10:06 +0200 Subject: [PATCH 083/618] Fix confusion in theme picker functions --- src/librustdoc/html/render.rs | 16 ++++++++-------- src/librustdoc/html/static/main.js | 12 ++++++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index ea97cea942820..ae988f6f9cafe 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -876,22 +876,22 @@ r#"var themes = document.getElementById("theme-choices"); var themePicker = document.getElementById("theme-picker"); function showThemeButtonState() {{ - themes.style.display = "none"; - themePicker.style.borderBottomRightRadius = "3px"; - themePicker.style.borderBottomLeftRadius = "3px"; -}} - -function hideThemeButtonState() {{ themes.style.display = "block"; themePicker.style.borderBottomRightRadius = "0"; themePicker.style.borderBottomLeftRadius = "0"; }} +function hideThemeButtonState() {{ + themes.style.display = "none"; + themePicker.style.borderBottomRightRadius = "3px"; + themePicker.style.borderBottomLeftRadius = "3px"; +}} + function switchThemeButtonState() {{ if (themes.style.display === "block") {{ - showThemeButtonState(); - }} else {{ hideThemeButtonState(); + }} else {{ + showThemeButtonState(); }} }}; diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 82d2c11b2497b..3d0f00095aca3 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -105,9 +105,9 @@ if (!DOMTokenList.prototype.remove) { sidebar.appendChild(div); } } - var themePicker = document.getElementsByClassName("theme-picker"); - if (themePicker && themePicker.length > 0) { - themePicker[0].style.display = "none"; + var themePickers = document.getElementsByClassName("theme-picker"); + if (themePickers && themePickers.length > 0) { + themePickers[0].style.display = "none"; } } @@ -123,9 +123,9 @@ if (!DOMTokenList.prototype.remove) { filler.remove(); } document.getElementsByTagName("body")[0].style.marginTop = ""; - var themePicker = document.getElementsByClassName("theme-picker"); - if (themePicker && themePicker.length > 0) { - themePicker[0].style.display = null; + var themePickers = document.getElementsByClassName("theme-picker"); + if (themePickers && themePickers.length > 0) { + themePickers[0].style.display = null; } } From dd7082e3d259f04a11d3ae49ab2742bcecdd3a5e Mon Sep 17 00:00:00 2001 From: Artem Varaksa Date: Wed, 21 Aug 2019 14:32:38 +0300 Subject: [PATCH 084/618] `r#type` -> `ty` --- src/librustc_passes/loops.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 4549ac8c668c5..dbfbec32a6fbf 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -170,10 +170,10 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { } fn require_break_cx(&self, name: &str, span: Span) { - let err_inside_of = |article, r#type, closure_span| { - struct_span_err!(self.sess, span, E0267, "`{}` inside of {} {}", name, article, r#type) - .span_label(span, format!("cannot `{}` inside of {} {}", name, article, r#type)) - .span_label(closure_span, &format!("enclosing {}", r#type)) + let err_inside_of = |article, ty, closure_span| { + struct_span_err!(self.sess, span, E0267, "`{}` inside of {} {}", name, article, ty) + .span_label(span, format!("cannot `{}` inside of {} {}", name, article, ty)) + .span_label(closure_span, &format!("enclosing {}", ty)) .emit(); }; From 39260d9016db6925414541ad2dce6502dded3a64 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Wed, 21 Aug 2019 14:10:40 +0200 Subject: [PATCH 085/618] make abs, wrapping_abs, and overflowing_abs const functions --- src/libcore/num/mod.rs | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index b46e06f8d8ada..df1c00ccd184f 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1401,12 +1401,8 @@ $EndFeature, " ```"), #[stable(feature = "no_panic_abs", since = "1.13.0")] #[inline] - pub fn wrapping_abs(self) -> Self { - if self.is_negative() { - self.wrapping_neg() - } else { - self - } + pub const fn wrapping_abs(self) -> Self { + (self ^ (self >> ($BITS - 1))).wrapping_sub(self >> ($BITS - 1)) } } @@ -1764,12 +1760,8 @@ $EndFeature, " ```"), #[stable(feature = "no_panic_abs", since = "1.13.0")] #[inline] - pub fn overflowing_abs(self) -> (Self, bool) { - if self.is_negative() { - self.overflowing_neg() - } else { - (self, false) - } + pub const fn overflowing_abs(self) -> (Self, bool) { + (self ^ (self >> ($BITS - 1))).overflowing_sub(self >> ($BITS - 1)) } } @@ -1973,15 +1965,11 @@ $EndFeature, " #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[rustc_inherit_overflow_checks] - pub fn abs(self) -> Self { - if self.is_negative() { - // Note that the #[inline] above means that the overflow - // semantics of this negation depend on the crate we're being - // inlined into. - -self - } else { - self - } + pub const fn abs(self) -> Self { + // Note that the #[inline] above means that the overflow + // semantics of the subtraction depend on the crate we're being + // inlined into. + (self ^ (self >> ($BITS - 1))) - (self >> ($BITS - 1)) } } From 600a64bdb576cde946b71faa6e7ad6d15e84ff39 Mon Sep 17 00:00:00 2001 From: Artem Varaksa Date: Wed, 21 Aug 2019 15:13:13 +0300 Subject: [PATCH 086/618] more `--bless`ing + test error annotations fixes --- src/test/ui/array-break-length.rs | 4 ++-- .../async-block-control-flow-static-semantics.rs | 4 ++-- .../async-block-control-flow-static-semantics.stderr | 4 ++-- src/test/ui/break-outside-loop.rs | 6 +++--- src/test/ui/closures/closure-array-break-length.rs | 6 +++--- src/test/ui/issues/issue-28105.rs | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/test/ui/array-break-length.rs b/src/test/ui/array-break-length.rs index 2696aea5e8993..959f4a2babbf8 100644 --- a/src/test/ui/array-break-length.rs +++ b/src/test/ui/array-break-length.rs @@ -1,11 +1,11 @@ fn main() { loop { - |_: [_; break]| {} //~ ERROR: `break` outside of loop + |_: [_; break]| {} //~ ERROR: `break` outside of a loop //~^ ERROR mismatched types } loop { - |_: [_; continue]| {} //~ ERROR: `continue` outside of loop + |_: [_; continue]| {} //~ ERROR: `continue` outside of a loop //~^ ERROR mismatched types } } diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs index 90d75118f8e42..753a4e491550f 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs @@ -30,14 +30,14 @@ async fn return_targets_async_block_not_async_fn() -> u8 { fn no_break_in_async_block() { async { - break 0u8; //~ ERROR `break` inside of an async block + break 0u8; //~ ERROR `break` inside of an `async` block }; } fn no_break_in_async_block_even_with_outer_loop() { loop { async { - break 0u8; //~ ERROR `break` inside of an async block + break 0u8; //~ ERROR `break` inside of an `async` block }; } } diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr index b33c8afe6b864..c36caa5586fb0 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -1,4 +1,4 @@ -error[E0267]: `break` inside of an async block +error[E0267]: `break` inside of an `async` block --> $DIR/async-block-control-flow-static-semantics.rs:33:9 | LL | async { @@ -8,7 +8,7 @@ LL | | break 0u8; LL | | }; | |_____- enclosing `async` block -error[E0267]: `break` inside of an async block +error[E0267]: `break` inside of an `async` block --> $DIR/async-block-control-flow-static-semantics.rs:40:13 | LL | async { diff --git a/src/test/ui/break-outside-loop.rs b/src/test/ui/break-outside-loop.rs index fef298f7c3919..c424c25c646bd 100644 --- a/src/test/ui/break-outside-loop.rs +++ b/src/test/ui/break-outside-loop.rs @@ -7,8 +7,8 @@ fn cond() -> bool { true } fn foo(_: F) where F: FnOnce() {} fn main() { - let pth = break; //~ ERROR: `break` outside of loop - if cond() { continue } //~ ERROR: `continue` outside of loop + let pth = break; //~ ERROR: `break` outside of a loop + if cond() { continue } //~ ERROR: `continue` outside of a loop while cond() { if cond() { break } @@ -21,5 +21,5 @@ fn main() { let rs: Foo = Foo{t: pth}; - let unconstrained = break; //~ ERROR: `break` outside of loop + let unconstrained = break; //~ ERROR: `break` outside of a loop } diff --git a/src/test/ui/closures/closure-array-break-length.rs b/src/test/ui/closures/closure-array-break-length.rs index a7f16d70ba860..f3567db1fac9c 100644 --- a/src/test/ui/closures/closure-array-break-length.rs +++ b/src/test/ui/closures/closure-array-break-length.rs @@ -1,9 +1,9 @@ fn main() { - |_: [_; continue]| {}; //~ ERROR: `continue` outside of loop + |_: [_; continue]| {}; //~ ERROR: `continue` outside of a loop - while |_: [_; continue]| {} {} //~ ERROR: `continue` outside of loop + while |_: [_; continue]| {} {} //~ ERROR: `continue` outside of a loop //~^ ERROR mismatched types - while |_: [_; break]| {} {} //~ ERROR: `break` outside of loop + while |_: [_; break]| {} {} //~ ERROR: `break` outside of a loop //~^ ERROR mismatched types } diff --git a/src/test/ui/issues/issue-28105.rs b/src/test/ui/issues/issue-28105.rs index 6026cbb82ae75..1e8d2d6ccf132 100644 --- a/src/test/ui/issues/issue-28105.rs +++ b/src/test/ui/issues/issue-28105.rs @@ -1,8 +1,8 @@ // Make sure that a continue span actually contains the keyword. fn main() { - continue //~ ERROR `continue` outside of loop + continue //~ ERROR `continue` outside of a loop ; - break //~ ERROR `break` outside of loop + break //~ ERROR `break` outside of a loop ; } From adee559659774054497fc36afea0076c334c0bb2 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Wed, 21 Aug 2019 15:40:12 +0200 Subject: [PATCH 087/618] test const abs, wrapping_abs, and overflowing_abs --- src/test/ui/consts/const-int-overflowing-rpass.rs | 8 ++++++++ src/test/ui/consts/const-int-sign-rpass.rs | 6 ++++++ src/test/ui/consts/const-int-wrapping-rpass.rs | 8 ++++++++ 3 files changed, 22 insertions(+) diff --git a/src/test/ui/consts/const-int-overflowing-rpass.rs b/src/test/ui/consts/const-int-overflowing-rpass.rs index b619c7908aa22..9be87a6447cda 100644 --- a/src/test/ui/consts/const-int-overflowing-rpass.rs +++ b/src/test/ui/consts/const-int-overflowing-rpass.rs @@ -18,6 +18,10 @@ const SHR_B: (u32, bool) = 0x10u32.overflowing_shr(132); const NEG_A: (u32, bool) = 0u32.overflowing_neg(); const NEG_B: (u32, bool) = core::u32::MAX.overflowing_neg(); +const ABS_POS: (i32, bool) = 10i32.overflowing_abs(); +const ABS_NEG: (i32, bool) = (-10i32).overflowing_abs(); +const ABS_MIN: (i32, bool) = i32::min_value().overflowing_abs(); + fn main() { assert_eq!(ADD_A, (7, false)); assert_eq!(ADD_B, (0, true)); @@ -36,4 +40,8 @@ fn main() { assert_eq!(NEG_A, (0, false)); assert_eq!(NEG_B, (1, true)); + + assert_eq!(ABS_POS, (10, false)); + assert_eq!(ABS_NEG, (10, false)); + assert_eq!(ABS_MIN, (i32::min_value(), true)); } diff --git a/src/test/ui/consts/const-int-sign-rpass.rs b/src/test/ui/consts/const-int-sign-rpass.rs index 05726cb228647..dc46fce39a93c 100644 --- a/src/test/ui/consts/const-int-sign-rpass.rs +++ b/src/test/ui/consts/const-int-sign-rpass.rs @@ -11,6 +11,9 @@ const SIGNUM_POS: i32 = 10i32.signum(); const SIGNUM_NIL: i32 = 0i32.signum(); const SIGNUM_NEG: i32 = (-42i32).signum(); +const ABS_A: i32 = 10i32.abs(); +const ABS_B: i32 = (-10i32).abs(); + fn main() { assert!(NEGATIVE_A); assert!(!NEGATIVE_B); @@ -20,4 +23,7 @@ fn main() { assert_eq!(SIGNUM_POS, 1); assert_eq!(SIGNUM_NIL, 0); assert_eq!(SIGNUM_NEG, -1); + + assert_eq!(ABS_A, 10); + assert_eq!(ABS_B, 10); } diff --git a/src/test/ui/consts/const-int-wrapping-rpass.rs b/src/test/ui/consts/const-int-wrapping-rpass.rs index 73147d7912d19..2bbad99a52a90 100644 --- a/src/test/ui/consts/const-int-wrapping-rpass.rs +++ b/src/test/ui/consts/const-int-wrapping-rpass.rs @@ -18,6 +18,10 @@ const SHR_B: u32 = 128u32.wrapping_shr(128); const NEG_A: u32 = 5u32.wrapping_neg(); const NEG_B: u32 = 1234567890u32.wrapping_neg(); +const ABS_POS: i32 = 10i32.wrapping_abs(); +const ABS_NEG: i32 = (-10i32).wrapping_abs(); +const ABS_MIN: i32 = i32::min_value().wrapping_abs(); + fn main() { assert_eq!(ADD_A, 255); assert_eq!(ADD_B, 199); @@ -36,4 +40,8 @@ fn main() { assert_eq!(NEG_A, 4294967291); assert_eq!(NEG_B, 3060399406); + + assert_eq!(ABS_POS, 10); + assert_eq!(ABS_NEG, 10); + assert_eq!(ABS_MIN, i32::min_value()); } From a47e3c077cd7f201dbbf12140c12663df0fcda6f Mon Sep 17 00:00:00 2001 From: newpavlov Date: Wed, 21 Aug 2019 17:57:22 +0300 Subject: [PATCH 088/618] fixes --- src/libstd/sys/wasi/args.rs | 6 +-- src/libstd/sys/wasi/ext/fs.rs | 2 + src/libstd/sys/wasi/ext/io.rs | 2 +- src/libstd/sys/wasi/fd.rs | 76 +++++++++++++++++------------------ src/libstd/sys/wasi/fs.rs | 16 +++----- src/libstd/sys/wasi/io.rs | 2 +- src/libstd/sys/wasi/mod.rs | 27 +++++++------ src/libstd/sys/wasi/os.rs | 2 - src/libstd/sys/wasi/stdio.rs | 4 +- src/libstd/sys/wasi/thread.rs | 3 +- src/libstd/sys/wasi/time.rs | 3 +- 11 files changed, 69 insertions(+), 74 deletions(-) diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs index de9ca62469d5d..3280c4990dc66 100644 --- a/src/libstd/sys/wasi/args.rs +++ b/src/libstd/sys/wasi/args.rs @@ -1,10 +1,10 @@ -use crate::ffi::CStr; -use crate::io; use crate::ffi::OsString; use crate::marker::PhantomData; use crate::os::wasi::ffi::OsStringExt; use crate::vec; +use ::wasi::wasi_unstable as wasi; + pub unsafe fn init(_argc: isize, _argv: *const *const u8) { } @@ -20,7 +20,7 @@ pub struct Args { pub fn args() -> Args { let buf = wasi::args_sizes_get().and_then(|args_sizes| { let mut buf = Vec::with_capacity(args_sizes.get_count()); - wasi::get_args(args_sizes, |arg| { + wasi::args_get(args_sizes, |arg| { let arg = OsString::from_vec(arg.to_vec()); buf.push(arg); })?; diff --git a/src/libstd/sys/wasi/ext/fs.rs b/src/libstd/sys/wasi/ext/fs.rs index ecd509f01dabd..9fa4abfd171b5 100644 --- a/src/libstd/sys/wasi/ext/fs.rs +++ b/src/libstd/sys/wasi/ext/fs.rs @@ -8,6 +8,8 @@ use crate::os::wasi::ffi::OsStrExt; use crate::path::{Path, PathBuf}; use crate::sys_common::{AsInner, AsInnerMut, FromInner}; +use ::wasi::wasi_unstable as wasi; + /// WASI-specific extensions to [`File`]. /// /// [`File`]: ../../../../std/fs/struct.File.html diff --git a/src/libstd/sys/wasi/ext/io.rs b/src/libstd/sys/wasi/ext/io.rs index c843144f0c406..f1839df380112 100644 --- a/src/libstd/sys/wasi/ext/io.rs +++ b/src/libstd/sys/wasi/ext/io.rs @@ -8,7 +8,7 @@ use crate::sys; use crate::net; use crate::sys_common::{AsInner, FromInner, IntoInner}; -use wasi::wasi_unstable as wasi; +use ::wasi::wasi_unstable as wasi; /// Raw file descriptors. pub type RawFd = u32; diff --git a/src/libstd/sys/wasi/fd.rs b/src/libstd/sys/wasi/fd.rs index 93fe8add326c8..275e1319be6ad 100644 --- a/src/libstd/sys/wasi/fd.rs +++ b/src/libstd/sys/wasi/fd.rs @@ -3,14 +3,15 @@ use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::net::Shutdown; -use wasi::wasi_unstable as wasi; +use super::err2io; +use ::wasi::wasi_unstable as wasi; #[derive(Debug)] pub struct WasiFd { fd: wasi::Fd, } -fn iovec(a: &mut [IoSliceMut<'_>]) -> &[wasi::IoVec] { +fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::IoVec] { assert_eq!( mem::size_of::>(), mem::size_of::() @@ -23,7 +24,7 @@ fn iovec(a: &mut [IoSliceMut<'_>]) -> &[wasi::IoVec] { unsafe { mem::transmute(a) } } -fn ciovec(a: &[IoSlice<'_>]) -> &[wasi::CIoVec] { +fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::CIoVec] { assert_eq!( mem::size_of::>(), mem::size_of::() @@ -52,23 +53,23 @@ impl WasiFd { } pub fn datasync(&self) -> io::Result<()> { - wasi::fd_datasync(self.fd).map_err(From::from) + wasi::fd_datasync(self.fd).map_err(err2io) } pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(From::from) + wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) } pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(From::from) + wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) } pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - wasi::fd_read(self.fd, iovec(bufs)).map_err(From::from) + wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) } pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result { - wasi::fd_write(self.fd, ciovec(bufs)).map_err(From::from) + wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) } pub fn seek(&self, pos: SeekFrom) -> io::Result { @@ -77,37 +78,37 @@ impl WasiFd { SeekFrom::End(pos) => (wasi::WHENCE_END, pos), SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos), }; - wasi::fd_seek(self.fd, offset, whence).map_err(From::from) + wasi::fd_seek(self.fd, offset, whence).map_err(err2io) } pub fn tell(&self) -> io::Result { - wasi::fd_tell(self.fd).map_err(From::from) + wasi::fd_tell(self.fd).map_err(err2io) } // FIXME: __wasi_fd_fdstat_get pub fn set_flags(&self, flags: wasi::FdFlags) -> io::Result<()> { - wasi::fd_fdstat_set_flags(self.fd, flags).map_err(From::from) + wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) } pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> { - wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(From::from) + wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(err2io) } pub fn sync(&self) -> io::Result<()> { - wasi::fd_sync(self.fd).map_err(From::from) + wasi::fd_sync(self.fd).map_err(err2io) } pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> { - wasi::fd_advise(self.fd, offset, len, advice).map_err(From::from) + wasi::fd_advise(self.fd, offset, len, advice).map_err(err2io) } pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> { - wasi::fd_allocate(self.fd, offset, len).map_err(From::from) + wasi::fd_allocate(self.fd, offset, len).map_err(err2io) } pub fn create_directory(&self, path: &[u8]) -> io::Result<()> { - wasi::path_create_directory(self.fd, path).map_err(From::from) + wasi::path_create_directory(self.fd, path).map_err(err2io) } pub fn link( @@ -118,7 +119,7 @@ impl WasiFd { new_path: &[u8], ) -> io::Result<()> { wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path) - .map_err(From::from) + .map_err(err2io) } pub fn open( @@ -130,7 +131,7 @@ impl WasiFd { fs_rights_inheriting: wasi::Rights, fs_flags: wasi::FdFlags, ) -> io::Result { - let fd = wasi_path_open( + wasi::path_open( self.fd, dirflags, path, @@ -138,25 +139,24 @@ impl WasiFd { fs_rights_base, fs_rights_inheriting, fs_flags, - )?; - Ok(WasiFd::from_raw(fd)) + ).map(|fd| unsafe { WasiFd::from_raw(fd) }).map_err(err2io) } pub fn readdir(&self, buf: &mut [u8], cookie: wasi::DirCookie) -> io::Result { - wasi::fd_readdir(self.fd, buf, cookie).map_err(From::from) + wasi::fd_readdir(self.fd, buf, cookie).map_err(err2io) } pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result { - wasi::path_readlink(self.fd, path, buf).map_err(From::from) + wasi::path_readlink(self.fd, path, buf).map_err(err2io) } pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> { wasi::path_rename(self.fd, old_path, new_fd.fd, new_path) - .map_err(From::from) + .map_err(err2io) } - pub fn filestat_get(&self) -> io::Result { - wasi::fd_filestat_get(self.fd, buf).map_err(From::from) + pub fn filestat_get(&self) -> io::Result { + wasi::fd_filestat_get(self.fd).map_err(err2io) } pub fn filestat_set_times( @@ -166,11 +166,11 @@ impl WasiFd { fstflags: wasi::FstFlags, ) -> io::Result<()> { wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags) - .map_err(From::from) + .map_err(err2io) } pub fn filestat_set_size(&self, size: u64) -> io::Result<()> { - wasi::fd_filestat_set_size(self.fd, size).map_err(From::from) + wasi::fd_filestat_set_size(self.fd, size).map_err(err2io) } pub fn path_filestat_get( @@ -178,7 +178,7 @@ impl WasiFd { flags: wasi::LookupFlags, path: &[u8], ) -> io::Result { - wasi::path_filestat_get(self.fd, flags, path).map_err(From::from) + wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) } pub fn path_filestat_set_times( @@ -196,19 +196,19 @@ impl WasiFd { atim, mtim, fstflags, - ).map_err(From::from) + ).map_err(err2io) } pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> { - wasi::path_symlink(old_path, self.fd, new_path).map_err(From::from) + wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) } pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> { - wasi::path_unlink_file(self.fd, path).map_err(From::from) + wasi::path_unlink_file(self.fd, path).map_err(err2io) } pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> { - wasi::path_remove_directory(self.fd, path).map_err(From::from) + wasi::path_remove_directory(self.fd, path).map_err(err2io) } pub fn sock_recv( @@ -216,20 +216,20 @@ impl WasiFd { ri_data: &mut [IoSliceMut<'_>], ri_flags: wasi::RiFlags, ) -> io::Result<(usize, wasi::RoFlags)> { - wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(From::from) + wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) } pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::SiFlags) -> io::Result { - wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(From::from) + wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) } pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> { let how = match how { - Shutdown::Read => WASI::SHUT_RD, - Shutdown::Write => WASI::SHUT_WR, - Shutdown::Both => WASI::SHUT_WR | WASI::SHUT_RD, + Shutdown::Read => wasi::SHUT_RD, + Shutdown::Write => wasi::SHUT_WR, + Shutdown::Both => wasi::SHUT_WR | wasi::SHUT_RD, }; - wasi::sock_shutdown(self.fd, how).map_err(From::from) + wasi::sock_shutdown(self.fd, how).map_err(err2io) } } diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs index f23ecfc2bcd22..4113f6a2e09c0 100644 --- a/src/libstd/sys/wasi/fs.rs +++ b/src/libstd/sys/wasi/fs.rs @@ -7,7 +7,7 @@ use crate::os::wasi::ffi::{OsStrExt, OsStringExt}; use crate::path::{Path, PathBuf}; use crate::ptr; use crate::sync::Arc; -use crate::sys::fd::{DirCookie, WasiFd}; +use crate::sys::fd::WasiFd; use crate::sys::time::SystemTime; use crate::sys::unsupported; use crate::sys_common::FromInner; @@ -15,7 +15,7 @@ use crate::sys_common::FromInner; pub use crate::sys_common::fs::copy; pub use crate::sys_common::fs::remove_dir_all; -use wasi::wasi_unstable as wasi; +use ::wasi::wasi_unstable as wasi; pub struct File { fd: WasiFd, @@ -28,7 +28,7 @@ pub struct FileAttr { pub struct ReadDir { inner: Arc, - cookie: Option, + cookie: Option, buf: Vec, offset: usize, cap: usize, @@ -70,12 +70,6 @@ pub struct FileType { pub struct DirBuilder {} impl FileAttr { - fn zero() -> FileAttr { - FileAttr { - meta: unsafe { mem::zeroed() }, - } - } - pub fn size(&self) -> u64 { self.meta.st_size } @@ -390,7 +384,7 @@ impl File { } pub fn file_attr(&self) -> io::Result { - self.fd.filestat_get().map_ok(|meta| FileAttr { meta }) + self.fd.filestat_get().map(|meta| FileAttr { meta }) } pub fn metadata_at( @@ -601,7 +595,7 @@ fn metadata_at( path: &Path, ) -> io::Result { fd.path_filestat_get(flags, path.as_os_str().as_bytes()) - .map_ok(|meta| FileAttr { meta }) + .map(|meta| FileAttr { meta }) } pub fn canonicalize(_p: &Path) -> io::Result { diff --git a/src/libstd/sys/wasi/io.rs b/src/libstd/sys/wasi/io.rs index ebea3a03e439f..4be92faed308f 100644 --- a/src/libstd/sys/wasi/io.rs +++ b/src/libstd/sys/wasi/io.rs @@ -1,7 +1,7 @@ use crate::marker::PhantomData; use crate::slice; -use wasi::wasi_unstable as wasi; +use ::wasi::wasi_unstable as wasi; use core::ffi::c_void; #[repr(transparent)] diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs index 28b49996d1433..89f7c887aafc0 100644 --- a/src/libstd/sys/wasi/mod.rs +++ b/src/libstd/sys/wasi/mod.rs @@ -14,10 +14,10 @@ //! compiling for wasm. That way it's a compile time error for something that's //! guaranteed to be a runtime error! -use crate::io; +use crate::io as std_io; use crate::mem; use crate::os::raw::c_char; -use wasi::wasi_unstable as wasi; +use ::wasi::wasi_unstable as wasi; pub mod alloc; pub mod args; @@ -56,16 +56,19 @@ pub mod ext; pub fn init() { } -pub fn unsupported() -> crate::io::Result { +pub fn unsupported() -> std_io::Result { Err(unsupported_err()) } -pub fn unsupported_err() -> io::Error { - io::Error::new(io::ErrorKind::Other, "operation not supported on wasm yet") +pub fn unsupported_err() -> std_io::Error { + std_io::Error::new( + std_io::ErrorKind::Other, + "operation not supported on wasm yet", + ) } -pub fn decode_error_kind(_code: i32) -> io::ErrorKind { - io::ErrorKind::Other +pub fn decode_error_kind(_code: i32) -> std_io::ErrorKind { + std_io::ErrorKind::Other } // This enum is used as the storage for a bunch of types which can't actually @@ -114,16 +117,14 @@ macro_rules! impl_is_minus_one { impl_is_minus_one! { i8 i16 i32 i64 isize } -pub fn cvt(t: T) -> crate::io::Result { +pub fn cvt(t: T) -> std_io::Result { if t.is_minus_one() { - Err(io::Error::last_os_error()) + Err(std_io::Error::last_os_error()) } else { Ok(t) } } -impl From for io::Error { - fn from(err: wasi::Error) -> Self { - Self::from_raw_os_error(err as i32) - } +fn err2io(err: wasi::Error) -> std_io::Error { + std_io::Error::from_raw_os_error(err.get() as i32) } diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs index dca58179e0c8d..7ee23c9a35ec7 100644 --- a/src/libstd/sys/wasi/os.rs +++ b/src/libstd/sys/wasi/os.rs @@ -12,8 +12,6 @@ use crate::sys::memchr; use crate::sys::{cvt, unsupported, Void}; use crate::vec; -use wasi::wasi_unstable as wasi; - #[cfg(not(target_feature = "atomics"))] pub unsafe fn env_lock() -> impl Any { // No need for a lock if we're single-threaded, but this function will need diff --git a/src/libstd/sys/wasi/stdio.rs b/src/libstd/sys/wasi/stdio.rs index dc6a6ef375a1c..1d57b9922e599 100644 --- a/src/libstd/sys/wasi/stdio.rs +++ b/src/libstd/sys/wasi/stdio.rs @@ -2,7 +2,7 @@ use crate::io::{self, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; use crate::sys::fd::WasiFd; -use wasi::wasi_unstable as wasi; +use ::wasi::wasi_unstable as wasi; pub struct Stdin; pub struct Stdout; @@ -74,7 +74,7 @@ impl io::Write for Stderr { pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE; pub fn is_ebadf(err: &io::Error) -> bool { - err.raw_os_error() == Some(wasi::EBADF as i32) + err.raw_os_error() == Some(wasi::EBADF.get() as i32) } pub fn panic_output() -> Option { diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index a6c8f2487013b..dc5a72e82a354 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -1,10 +1,11 @@ -use crate::cmp; use crate::ffi::CStr; use crate::io; use crate::mem; use crate::sys::{unsupported, Void}; use crate::time::Duration; +use ::wasi::wasi_unstable as wasi; + pub struct Thread(Void); pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; diff --git a/src/libstd/sys/wasi/time.rs b/src/libstd/sys/wasi/time.rs index 4c89a1781b9ef..4394a22f9c233 100644 --- a/src/libstd/sys/wasi/time.rs +++ b/src/libstd/sys/wasi/time.rs @@ -1,6 +1,5 @@ use crate::time::Duration; -use crate::mem; -use wasi::wasi_unstable as wasi; +use ::wasi::wasi_unstable as wasi; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant(Duration); From a9900be9f41176003c0a1a613686b2e443342466 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 21 Aug 2019 10:16:57 -0500 Subject: [PATCH 089/618] add amanjeev --- src/tools/publish_toolstate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index b8dcba3afc3a1..648838d26efe9 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -34,7 +34,7 @@ '@ryankurte @thejpster @therealprof' ), 'edition-guide': '@ehuss @Centril @steveklabnik', - 'rustc-guide': '@mark-i-m @spastorino' + 'rustc-guide': '@mark-i-m @spastorino @amanjeev' } REPOS = { From 9f14526f738370efc519143eeee3e43101774a8b Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Mon, 19 Aug 2019 11:06:15 -0500 Subject: [PATCH 090/618] update rustc-guide --- src/doc/rustc-guide | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-guide b/src/doc/rustc-guide index 6f4ba673ff9d4..6e25a3d0d3573 160000 --- a/src/doc/rustc-guide +++ b/src/doc/rustc-guide @@ -1 +1 @@ -Subproject commit 6f4ba673ff9d4613e98415bc095347a6a0031e9c +Subproject commit 6e25a3d0d3573eb42b2e2339f1219e969d1b3dee From f5b16f6212d2d72d505d4d6b1dedc2c9c61dd014 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 21 Aug 2019 15:50:43 +0000 Subject: [PATCH 091/618] Add codegen test for integers compare --- src/test/codegen/integer-cmp.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/test/codegen/integer-cmp.rs diff --git a/src/test/codegen/integer-cmp.rs b/src/test/codegen/integer-cmp.rs new file mode 100644 index 0000000000000..1373b12e3721c --- /dev/null +++ b/src/test/codegen/integer-cmp.rs @@ -0,0 +1,28 @@ +// This is test for more optimal Ord implementation for integers. +// See for more info. + +// compile-flags: -C opt-level=3 + +#![crate_type = "lib"] + +use std::cmp::Ordering; + +// CHECK-LABEL: @cmp_signed +#[no_mangle] +pub fn cmp_signed(a: i64, b: i64) -> Ordering { +// CHECK: icmp slt +// CHECK: icmp sgt +// CHECK: zext i1 +// CHECK: select i1 + a.cmp(&b) +} + +// CHECK-LABEL: @cmp_unsigned +#[no_mangle] +pub fn cmp_unsigned(a: u32, b: u32) -> Ordering { +// CHECK: icmp ult +// CHECK: icmp ugt +// CHECK: zext i1 +// CHECK: select i1 + a.cmp(&b) +} From 926f36400f1667edec92959d8b640dea5084674c Mon Sep 17 00:00:00 2001 From: newpavlov Date: Wed, 21 Aug 2019 19:36:12 +0300 Subject: [PATCH 092/618] move cvt --- src/libstd/Cargo.toml | 1 + src/libstd/sys/wasi/mod.rs | 23 ----------------------- src/libstd/sys/wasi/os.rs | 25 ++++++++++++++++++++++++- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index bb77a5bdea493..d801b051357a4 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -24,6 +24,7 @@ compiler_builtins = { version = "0.1.16" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] } +wasi = { git = "https://github.com/newpavlov/rust-wasi", branch = "safe_rework", features = ['rustc-dep-of-std', 'alloc'] } [dependencies.backtrace] version = "0.3.35" diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs index 89f7c887aafc0..f87e4d16fcdac 100644 --- a/src/libstd/sys/wasi/mod.rs +++ b/src/libstd/sys/wasi/mod.rs @@ -102,29 +102,6 @@ pub fn hashmap_random_keys() -> (u64, u64) { return ret } -#[doc(hidden)] -pub trait IsMinusOne { - fn is_minus_one(&self) -> bool; -} - -macro_rules! impl_is_minus_one { - ($($t:ident)*) => ($(impl IsMinusOne for $t { - fn is_minus_one(&self) -> bool { - *self == -1 - } - })*) -} - -impl_is_minus_one! { i8 i16 i32 i64 isize } - -pub fn cvt(t: T) -> std_io::Result { - if t.is_minus_one() { - Err(std_io::Error::last_os_error()) - } else { - Ok(t) - } -} - fn err2io(err: wasi::Error) -> std_io::Error { std_io::Error::from_raw_os_error(err.get() as i32) } diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs index 7ee23c9a35ec7..feee840782550 100644 --- a/src/libstd/sys/wasi/os.rs +++ b/src/libstd/sys/wasi/os.rs @@ -9,7 +9,7 @@ use crate::path::{self, PathBuf}; use crate::ptr; use crate::str; use crate::sys::memchr; -use crate::sys::{cvt, unsupported, Void}; +use crate::sys::{unsupported, Void}; use crate::vec; #[cfg(not(target_feature = "atomics"))] @@ -176,3 +176,26 @@ pub fn exit(code: i32) -> ! { pub fn getpid() -> u32 { panic!("unsupported"); } + +#[doc(hidden)] +pub trait IsMinusOne { + fn is_minus_one(&self) -> bool; +} + +macro_rules! impl_is_minus_one { + ($($t:ident)*) => ($(impl IsMinusOne for $t { + fn is_minus_one(&self) -> bool { + *self == -1 + } + })*) +} + +impl_is_minus_one! { i8 i16 i32 i64 isize } + +fn cvt(t: T) -> io::Result { + if t.is_minus_one() { + Err(io::Error::last_os_error()) + } else { + Ok(t) + } +} From 2ff1f45ead012271823aa8c9693717b493b72fa6 Mon Sep 17 00:00:00 2001 From: newpavlov Date: Wed, 21 Aug 2019 20:16:52 +0300 Subject: [PATCH 093/618] revert num_cpus change --- src/libtest/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 216112cb6e0be..5e0f19fe553d9 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1198,6 +1198,12 @@ fn get_concurrency() -> usize { 1 } + #[cfg(target_os = "redox")] + fn num_cpus() -> usize { + // FIXME: Implement num_cpus on Redox + 1 + } + #[cfg(any( all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx") @@ -1215,7 +1221,6 @@ fn get_concurrency() -> usize { target_os = "linux", target_os = "macos", target_os = "solaris", - target_os = "redox", ))] fn num_cpus() -> usize { unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize } From 0e668e0496fcc13fa042be416b64ba6823669cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 24 Jul 2019 17:58:29 -0700 Subject: [PATCH 094/618] Strip code to the left and right in diagnostics for long lines --- src/librustc_errors/emitter.rs | 150 ++++++++++++++---- src/test/ui/inline-asm-bad-operand.stderr | 4 +- ...0-unused-variable-in-struct-pattern.stderr | 4 +- .../ui/methods/method-missing-call.stderr | 4 +- ...-on-type-no-recursive-stack-closure.stderr | 10 +- .../ui/regions/regions-name-undeclared.stderr | 8 +- 6 files changed, 133 insertions(+), 47 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 361b5cd935712..007c6369c7bd0 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -179,6 +179,7 @@ pub struct EmitterWriter { sm: Option>, short_message: bool, teach: bool, + strip_margin: bool, ui_testing: bool, } @@ -201,6 +202,7 @@ impl EmitterWriter { sm: source_map, short_message, teach, + strip_margin: false, ui_testing: false, } } @@ -217,6 +219,7 @@ impl EmitterWriter { sm: source_map, short_message, teach, + strip_margin: false, ui_testing: false, } } @@ -234,12 +237,29 @@ impl EmitterWriter { } } - fn render_source_line(&self, - buffer: &mut StyledBuffer, - file: Lrc, - line: &Line, - width_offset: usize, - code_offset: usize) -> Vec<(usize, Style)> { + fn render_source_line( + &self, + buffer: &mut StyledBuffer, + file: Lrc, + line: &Line, + width_offset: usize, + code_offset: usize, + margin: usize, + right_span_margin: usize + ) -> Vec<(usize, Style)> { + // Draw: + // + // LL | ... code ... + // | ^^-^ span label + // | | + // | secondary span label + // + // ^^ ^ ^^^ ^^^^ ^^^ we don't care about code too far to the right of a span, we trim it + // | | | | + // | | | actual code found in your source code and the spans we use to mark it + // | | when there's too much wasted space to the left, we trim it to focus where it matters + // | vertical divider between the column number and the code + // column number if line.line_index == 0 { return Vec::new(); } @@ -251,12 +271,28 @@ impl EmitterWriter { let line_offset = buffer.num_lines(); - // First create the source line we will highlight. - buffer.puts(line_offset, code_offset, &source_string, Style::Quotation); - buffer.puts(line_offset, - 0, - &self.maybe_anonymized(line.line_index), - Style::LineNumber); + let left_margin = std::cmp::min(margin, source_string.len()); + let right_margin = if source_string.len() > right_span_margin + 120 { + right_span_margin + 120 + } else { + source_string.len() + }; + // Create the source line we will highlight. + buffer.puts( + line_offset, + code_offset, + &source_string[left_margin..right_margin], // On long lines, we strip the source line + Style::Quotation, + ); + if margin > 0 { // We have stripped some code/whitespace from the beginning, make it clear. + buffer.puts(line_offset, code_offset, "...", Style::LineNumber); + } + if right_margin != source_string.len() { + // We have stripped some code after the right-most span end, make it clear we did so. + let offset = code_offset + right_margin - left_margin; + buffer.puts(line_offset, offset, "...", Style::LineNumber); + } + buffer.puts(line_offset, 0, &self.maybe_anonymized(line.line_index), Style::LineNumber); draw_col_separator(buffer, line_offset, width_offset - 2); @@ -279,18 +315,13 @@ impl EmitterWriter { if line.annotations.len() == 1 { if let Some(ref ann) = line.annotations.get(0) { if let AnnotationType::MultilineStart(depth) = ann.annotation_type { - if source_string.chars() - .take(ann.start_col) - .all(|c| c.is_whitespace()) { + if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) { let style = if ann.is_primary { Style::UnderlinePrimary } else { Style::UnderlineSecondary }; - buffer.putc(line_offset, - width_offset + depth - 1, - '/', - style); + buffer.putc(line_offset, width_offset + depth - 1, '/', style); return vec![(depth, style)]; } } @@ -515,13 +546,13 @@ impl EmitterWriter { '_', line_offset + pos, width_offset + depth, - code_offset + annotation.start_col, + code_offset + annotation.start_col - margin, style); } _ if self.teach => { buffer.set_style_range(line_offset, - code_offset + annotation.start_col, - code_offset + annotation.end_col, + code_offset + annotation.start_col - margin, + code_offset + annotation.end_col - margin, style, annotation.is_primary); } @@ -551,7 +582,7 @@ impl EmitterWriter { if pos > 1 && (annotation.has_label() || annotation.takes_space()) { for p in line_offset + 1..=line_offset + pos { buffer.putc(p, - code_offset + annotation.start_col, + code_offset + annotation.start_col - margin, '|', style); } @@ -595,9 +626,9 @@ impl EmitterWriter { Style::LabelSecondary }; let (pos, col) = if pos == 0 { - (pos + 1, annotation.end_col + 1) + (pos + 1, annotation.end_col + 1 - margin) } else { - (pos + 2, annotation.start_col) + (pos + 2, annotation.start_col - margin) }; if let Some(ref label) = annotation.label { buffer.puts(line_offset + pos, @@ -639,7 +670,7 @@ impl EmitterWriter { }; for p in annotation.start_col..annotation.end_col { buffer.putc(line_offset + 1, - code_offset + p, + code_offset + p - margin, underline, style); } @@ -1037,6 +1068,51 @@ impl EmitterWriter { // Contains the vertical lines' positions for active multiline annotations let mut multilines = FxHashMap::default(); + // Get the left-side margin to remove it + let mut margin = std::usize::MAX; + for line_idx in 0..annotated_file.lines.len() { + let file = annotated_file.file.clone(); + let line = &annotated_file.lines[line_idx]; + if let Some(source_string) = file.get_line(line.line_index - 1) { + let leading_whitespace = source_string + .chars() + .take_while(|c| c.is_whitespace()) + .count(); + if source_string.chars().any(|c| !c.is_whitespace()) { + margin = std::cmp::min(margin, leading_whitespace); + } + } + } + if margin >= 20 { // On errors with generous margins, trim it + margin = margin - 16; // Keep at least 4 spaces margin + } else if margin == std::usize::MAX || !self.strip_margin { + margin = 0; + } + + // Left-most column any visible span points at. + let mut span_left_margin = std::usize::MAX; + for line in &annotated_file.lines { + for ann in &line.annotations { + span_left_margin = std::cmp::min(span_left_margin, ann.start_col); + span_left_margin = std::cmp::min(span_left_margin, ann.end_col); + } + } + if span_left_margin == std::usize::MAX { + span_left_margin = 0; + } + if span_left_margin > 160 { + margin = std::cmp::max(margin, span_left_margin - 100); + } + + // Right-most column any visible span points at. + let mut span_right_margin = 0; + for line in &annotated_file.lines { + for ann in &line.annotations { + span_right_margin = std::cmp::max(span_right_margin, ann.start_col); + span_right_margin = std::cmp::max(span_right_margin, ann.end_col); + } + } + // Next, output the annotate source for this file for line_idx in 0..annotated_file.lines.len() { let previous_buffer_line = buffer.num_lines(); @@ -1048,11 +1124,15 @@ impl EmitterWriter { width_offset + annotated_file.multiline_depth + 1 }; - let depths = self.render_source_line(&mut buffer, - annotated_file.file.clone(), - &annotated_file.lines[line_idx], - width_offset, - code_offset); + let depths = self.render_source_line( + &mut buffer, + annotated_file.file.clone(), + &annotated_file.lines[line_idx], + width_offset, + code_offset, + margin, + span_right_margin, + ); let mut to_add = FxHashMap::default(); @@ -1107,9 +1187,15 @@ impl EmitterWriter { draw_col_separator(&mut buffer, last_buffer_line_num, 1 + max_line_num_len); + let left_margin = std::cmp::min(margin, unannotated_line.len()); + let right_margin = if unannotated_line.len() > span_right_margin + 120 { + span_right_margin + 120 + } else { + unannotated_line.len() + }; buffer.puts(last_buffer_line_num, code_offset, - &unannotated_line, + &unannotated_line[left_margin..right_margin], Style::Quotation); for (depth, style) in &multilines { diff --git a/src/test/ui/inline-asm-bad-operand.stderr b/src/test/ui/inline-asm-bad-operand.stderr index 4554da7b798ea..d5c1cf51dafaa 100644 --- a/src/test/ui/inline-asm-bad-operand.stderr +++ b/src/test/ui/inline-asm-bad-operand.stderr @@ -37,8 +37,8 @@ LL | asm!("mov sp, $0"::"r"(addr), error[E0669]: invalid value for constraint in inline assembly --> $DIR/inline-asm-bad-operand.rs:56:32 | -LL | "r"("hello e0669")); - | ^^^^^^^^^^^^^ +LL | ... "r"("hello e0669")); + | ^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr index a0b34d220c8d9..3262662a2a5e6 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -38,8 +38,8 @@ LL | if let SoulHistory { corridors_of_light, warning: variable `hours_are_suns` is assigned to, but never used --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:30 | -LL | mut hours_are_suns, - | ^^^^^^^^^^^^^^ +LL | ... mut hours_are_suns, + | ^^^^^^^^^^^^^^ | = note: consider using `_hours_are_suns` instead diff --git a/src/test/ui/methods/method-missing-call.stderr b/src/test/ui/methods/method-missing-call.stderr index 3ab5f66a0c3f6..fe44d3a29dab5 100644 --- a/src/test/ui/methods/method-missing-call.stderr +++ b/src/test/ui/methods/method-missing-call.stderr @@ -1,8 +1,8 @@ error[E0615]: attempted to take value of method `get_x` on type `Point` --> $DIR/method-missing-call.rs:22:26 | -LL | .get_x; - | ^^^^^ help: use parentheses to call the method: `get_x()` +LL | ... .get_x; + | ^^^^^ help: use parentheses to call the method: `get_x()` error[E0615]: attempted to take value of method `filter_map` on type `std::iter::Filter, [closure@$DIR/method-missing-call.rs:27:20: 27:25]>, [closure@$DIR/method-missing-call.rs:28:23: 28:35]>` --> $DIR/method-missing-call.rs:29:16 diff --git a/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr index 483c364752b7b..6eff7b06d53a5 100644 --- a/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr +++ b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr @@ -1,11 +1,11 @@ error[E0499]: cannot borrow `*f` as mutable more than once at a time --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:20:27 | -LL | (f.c)(f, true); - | ----- ^ second mutable borrow occurs here - | | - | first mutable borrow occurs here - | first borrow later used by call +LL | ... (f.c)(f, true); + | ----- ^ second mutable borrow occurs here + | | + | first mutable borrow occurs here + | first borrow later used by call error[E0382]: borrow of moved value: `f` --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:32:5 diff --git a/src/test/ui/regions/regions-name-undeclared.stderr b/src/test/ui/regions/regions-name-undeclared.stderr index 4840d751f7f57..fe0345c3a380c 100644 --- a/src/test/ui/regions/regions-name-undeclared.stderr +++ b/src/test/ui/regions/regions-name-undeclared.stderr @@ -49,14 +49,14 @@ LL | fn fn_types(a: &'a isize, error[E0261]: use of undeclared lifetime name `'b` --> $DIR/regions-name-undeclared.rs:42:36 | -LL | &'b isize, - | ^^ undeclared lifetime +LL | ... &'b isize, + | ^^ undeclared lifetime error[E0261]: use of undeclared lifetime name `'b` --> $DIR/regions-name-undeclared.rs:45:36 | -LL | &'b isize)>, - | ^^ undeclared lifetime +LL | ... &'b isize)>, + | ^^ undeclared lifetime error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-name-undeclared.rs:46:17 From 266b878334cecce3a0636ddbb95318f7a5669f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 13 Aug 2019 19:09:28 -0700 Subject: [PATCH 095/618] clean up --- src/librustc_errors/emitter.rs | 220 +++++++++++++----- ...-on-type-no-recursive-stack-closure.stderr | 10 +- 2 files changed, 162 insertions(+), 68 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 007c6369c7bd0..b7615fef04909 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -57,6 +57,80 @@ impl HumanReadableErrorType { } } +#[derive(Clone, Copy, Debug)] +struct Margin { + pub whitespace_left: usize, + pub span_left: usize, + pub span_right: usize, + pub line_len: usize, + pub computed_left: usize, + pub computed_right: usize, + pub column_width: usize, + pub label_right: usize, +} + +impl Margin { + fn new( + whitespace_left: usize, + span_left: usize, + span_right: usize, + label_right: usize, + ) -> Self { + Margin { + whitespace_left, + span_left, + span_right, + line_len: 0, + computed_left: 0, + computed_right: 0, + column_width: 140, + label_right, + } + } + + fn was_cut_left(&self) -> bool { + self.computed_left > 0 + } + + fn was_cut_right(&self) -> bool { + self.computed_right < self.line_len + } + + fn compute(&mut self) { + self.computed_left = if self.whitespace_left > 20 { + self.whitespace_left - 16 // We want some padding. + } else { + 0 + }; + self.computed_right = self.column_width + self.computed_left; + + if self.computed_right - self.computed_left > self.column_width { + // Trimming only whitespace isn't enough, let's get craftier. + if self.label_right - self.whitespace_left <= self.column_width { + self.computed_left = self.whitespace_left; + self.computed_right = self.computed_left + self.column_width; + } else if self.label_right - self.span_left - 20 <= self.column_width { + self.computed_left = self.span_left - 20; + self.computed_right = self.computed_left + self.column_width; + } else if self.label_right - self.span_left <= self.column_width { + self.computed_left = self.span_left; + self.computed_right = self.computed_left + self.column_width; + } else if self.span_right - self.span_left <= self.column_width { + self.computed_left = self.span_left; + self.computed_right = self.computed_left + self.column_width; + } else { // mostly give up but still don't show the full line + self.computed_left = self.span_left; + self.computed_right = self.span_right; + } + } + self.computed_left = std::cmp::min(self.computed_left, self.line_len); + if self.computed_right > self.line_len { + self.computed_right = self.line_len; + } + self.computed_right = std::cmp::min(self.computed_right, self.line_len); + } +} + const ANONYMIZED_LINE_NUM: &str = "LL"; /// Emitter trait for emitting errors. @@ -179,7 +253,6 @@ pub struct EmitterWriter { sm: Option>, short_message: bool, teach: bool, - strip_margin: bool, ui_testing: bool, } @@ -202,7 +275,6 @@ impl EmitterWriter { sm: source_map, short_message, teach, - strip_margin: false, ui_testing: false, } } @@ -219,7 +291,6 @@ impl EmitterWriter { sm: source_map, short_message, teach, - strip_margin: false, ui_testing: false, } } @@ -244,8 +315,7 @@ impl EmitterWriter { line: &Line, width_offset: usize, code_offset: usize, - margin: usize, - right_span_margin: usize + mut margin: Margin, ) -> Vec<(usize, Style)> { // Draw: // @@ -260,6 +330,7 @@ impl EmitterWriter { // | | when there's too much wasted space to the left, we trim it to focus where it matters // | vertical divider between the column number and the code // column number + if line.line_index == 0 { return Vec::new(); } @@ -271,26 +342,27 @@ impl EmitterWriter { let line_offset = buffer.num_lines(); - let left_margin = std::cmp::min(margin, source_string.len()); - let right_margin = if source_string.len() > right_span_margin + 120 { - right_span_margin + 120 - } else { - source_string.len() - }; + margin.line_len = source_string.len(); + margin.compute(); // Create the source line we will highlight. buffer.puts( line_offset, code_offset, - &source_string[left_margin..right_margin], // On long lines, we strip the source line + // On long lines, we strip the source line + &source_string[margin.computed_left..margin.computed_right], Style::Quotation, ); - if margin > 0 { // We have stripped some code/whitespace from the beginning, make it clear. + if margin.was_cut_left() { // We have stripped some code/whitespace from the beginning, make it clear. buffer.puts(line_offset, code_offset, "...", Style::LineNumber); } - if right_margin != source_string.len() { + if margin.was_cut_right() { // We have stripped some code after the right-most span end, make it clear we did so. - let offset = code_offset + right_margin - left_margin; - buffer.puts(line_offset, offset, "...", Style::LineNumber); + buffer.puts( + line_offset, + margin.computed_right - margin.computed_left + code_offset, + "...", + Style::LineNumber, + ); } buffer.puts(line_offset, 0, &self.maybe_anonymized(line.line_index), Style::LineNumber); @@ -546,13 +618,13 @@ impl EmitterWriter { '_', line_offset + pos, width_offset + depth, - code_offset + annotation.start_col - margin, + code_offset + annotation.start_col - margin.computed_left, style); } _ if self.teach => { buffer.set_style_range(line_offset, - code_offset + annotation.start_col - margin, - code_offset + annotation.end_col - margin, + code_offset + annotation.start_col - margin.computed_left, + code_offset + annotation.end_col - margin.computed_left, style, annotation.is_primary); } @@ -582,7 +654,7 @@ impl EmitterWriter { if pos > 1 && (annotation.has_label() || annotation.takes_space()) { for p in line_offset + 1..=line_offset + pos { buffer.putc(p, - code_offset + annotation.start_col - margin, + code_offset + annotation.start_col - margin.computed_left, '|', style); } @@ -626,9 +698,9 @@ impl EmitterWriter { Style::LabelSecondary }; let (pos, col) = if pos == 0 { - (pos + 1, annotation.end_col + 1 - margin) + (pos + 1, annotation.end_col + 1 - margin.computed_left) } else { - (pos + 2, annotation.start_col - margin) + (pos + 2, annotation.start_col - margin.computed_left) }; if let Some(ref label) = annotation.label { buffer.puts(line_offset + pos, @@ -670,7 +742,7 @@ impl EmitterWriter { }; for p in annotation.start_col..annotation.end_col { buffer.putc(line_offset + 1, - code_offset + p - margin, + code_offset + p - margin.computed_left, underline, style); } @@ -1010,22 +1082,30 @@ impl EmitterWriter { let buffer_msg_line_offset = buffer.num_lines(); buffer.prepend(buffer_msg_line_offset, "--> ", Style::LineNumber); - buffer.append(buffer_msg_line_offset, - &format!("{}:{}:{}", - loc.file.name, - sm.doctest_offset_line(&loc.file.name, loc.line), - loc.col.0 + 1), - Style::LineAndColumn); + buffer.append( + buffer_msg_line_offset, + &format!( + "{}:{}:{}", + loc.file.name, + sm.doctest_offset_line(&loc.file.name, loc.line), + loc.col.0 + 1, + ), + Style::LineAndColumn, + ); for _ in 0..max_line_num_len { buffer.prepend(buffer_msg_line_offset, " ", Style::NoStyle); } } else { - buffer.prepend(0, - &format!("{}:{}:{}: ", - loc.file.name, - sm.doctest_offset_line(&loc.file.name, loc.line), - loc.col.0 + 1), - Style::LineAndColumn); + buffer.prepend( + 0, + &format!( + "{}:{}:{}: ", + loc.file.name, + sm.doctest_offset_line(&loc.file.name, loc.line), + loc.col.0 + 1, + ), + Style::LineAndColumn, + ); } } else if !self.short_message { // remember where we are in the output buffer for easy reference @@ -1069,7 +1149,7 @@ impl EmitterWriter { let mut multilines = FxHashMap::default(); // Get the left-side margin to remove it - let mut margin = std::usize::MAX; + let mut whitespace_margin = std::usize::MAX; for line_idx in 0..annotated_file.lines.len() { let file = annotated_file.file.clone(); let line = &annotated_file.lines[line_idx]; @@ -1079,14 +1159,15 @@ impl EmitterWriter { .take_while(|c| c.is_whitespace()) .count(); if source_string.chars().any(|c| !c.is_whitespace()) { - margin = std::cmp::min(margin, leading_whitespace); + whitespace_margin = std::cmp::min( + whitespace_margin, + leading_whitespace, + ); } } } - if margin >= 20 { // On errors with generous margins, trim it - margin = margin - 16; // Keep at least 4 spaces margin - } else if margin == std::usize::MAX || !self.strip_margin { - margin = 0; + if whitespace_margin == std::usize::MAX { + whitespace_margin = 0; } // Left-most column any visible span points at. @@ -1100,18 +1181,27 @@ impl EmitterWriter { if span_left_margin == std::usize::MAX { span_left_margin = 0; } - if span_left_margin > 160 { - margin = std::cmp::max(margin, span_left_margin - 100); - } // Right-most column any visible span points at. let mut span_right_margin = 0; + let mut label_right_margin = 0; for line in &annotated_file.lines { for ann in &line.annotations { span_right_margin = std::cmp::max(span_right_margin, ann.start_col); span_right_margin = std::cmp::max(span_right_margin, ann.end_col); + label_right_margin = std::cmp::max( + label_right_margin, + // TODO: account for labels not in the same line + ann.end_col + ann.label.as_ref().map(|l| l.len() + 1).unwrap_or(0), + ); } } + let margin = Margin::new( + whitespace_margin, + span_left_margin, + span_right_margin, + label_right_margin, + ); // Next, output the annotate source for this file for line_idx in 0..annotated_file.lines.len() { @@ -1131,7 +1221,6 @@ impl EmitterWriter { width_offset, code_offset, margin, - span_right_margin, ); let mut to_add = FxHashMap::default(); @@ -1179,24 +1268,29 @@ impl EmitterWriter { let last_buffer_line_num = buffer.num_lines(); - buffer.puts(last_buffer_line_num, - 0, - &self.maybe_anonymized(annotated_file.lines[line_idx + 1] - .line_index - 1), - Style::LineNumber); - draw_col_separator(&mut buffer, - last_buffer_line_num, - 1 + max_line_num_len); - let left_margin = std::cmp::min(margin, unannotated_line.len()); - let right_margin = if unannotated_line.len() > span_right_margin + 120 { - span_right_margin + 120 - } else { - unannotated_line.len() - }; - buffer.puts(last_buffer_line_num, - code_offset, - &unannotated_line[left_margin..right_margin], - Style::Quotation); + buffer.puts( + last_buffer_line_num, + 0, + &self.maybe_anonymized( + annotated_file.lines[line_idx + 1].line_index - 1, + ), + Style::LineNumber, + ); + draw_col_separator( + &mut buffer, + last_buffer_line_num, + 1 + max_line_num_len, + ); + + let mut margin = margin; + margin.line_len = unannotated_line.len(); + margin.compute(); + buffer.puts( + last_buffer_line_num, + code_offset, + &unannotated_line[margin.computed_left..margin.computed_right], + Style::Quotation, + ); for (depth, style) in &multilines { draw_multiline_line(&mut buffer, diff --git a/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr index 6eff7b06d53a5..483c364752b7b 100644 --- a/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr +++ b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr @@ -1,11 +1,11 @@ error[E0499]: cannot borrow `*f` as mutable more than once at a time --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:20:27 | -LL | ... (f.c)(f, true); - | ----- ^ second mutable borrow occurs here - | | - | first mutable borrow occurs here - | first borrow later used by call +LL | (f.c)(f, true); + | ----- ^ second mutable borrow occurs here + | | + | first mutable borrow occurs here + | first borrow later used by call error[E0382]: borrow of moved value: `f` --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:32:5 From f08b036cc78ca225a8d3e25fc138ed3a210c611f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 14 Aug 2019 09:34:09 -0700 Subject: [PATCH 096/618] Introduce `term-size` dependency and consider term width when trimming --- Cargo.lock | 12 + src/librustc_errors/Cargo.toml | 1 + src/librustc_errors/emitter.rs | 252 +++++++++++------- src/test/ui/inline-asm-bad-operand.stderr | 4 +- ...0-unused-variable-in-struct-pattern.stderr | 4 +- .../ui/lint/lint-stability-deprecated.stderr | 36 +-- .../ui/methods/method-missing-call.stderr | 4 +- .../ui/regions/regions-name-undeclared.stderr | 8 +- .../non-whitespace-trimming-2.rs | 6 + .../non-whitespace-trimming-2.stderr | 12 + .../terminal-width/non-whitespace-trimming.rs | 6 + .../non-whitespace-trimming.stderr | 12 + .../terminal-width/whitespace-trimming-2.rs | 8 + .../whitespace-trimming-2.stderr | 14 + .../ui/terminal-width/whitespace-trimming.rs | 6 + .../terminal-width/whitespace-trimming.stderr | 12 + src/tools/tidy/src/deps.rs | 1 + 17 files changed, 277 insertions(+), 121 deletions(-) create mode 100644 src/test/ui/terminal-width/non-whitespace-trimming-2.rs create mode 100644 src/test/ui/terminal-width/non-whitespace-trimming-2.stderr create mode 100644 src/test/ui/terminal-width/non-whitespace-trimming.rs create mode 100644 src/test/ui/terminal-width/non-whitespace-trimming.stderr create mode 100644 src/test/ui/terminal-width/whitespace-trimming-2.rs create mode 100644 src/test/ui/terminal-width/whitespace-trimming-2.stderr create mode 100644 src/test/ui/terminal-width/whitespace-trimming.rs create mode 100644 src/test/ui/terminal-width/whitespace-trimming.stderr diff --git a/Cargo.lock b/Cargo.lock index 06c455b3c910d..16baa7436cb81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3219,6 +3219,7 @@ dependencies = [ "rustc_data_structures", "serialize", "syntax_pos", + "term_size", "termcolor", "unicode-width", ] @@ -4090,6 +4091,17 @@ dependencies = [ "winapi 0.3.6", ] +[[package]] +name = "term_size" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" +dependencies = [ + "kernel32-sys", + "libc", + "winapi 0.2.8", +] + [[package]] name = "termcolor" version = "1.0.4" diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml index 32f121f18f689..1541845bb55f6 100644 --- a/src/librustc_errors/Cargo.toml +++ b/src/librustc_errors/Cargo.toml @@ -18,3 +18,4 @@ unicode-width = "0.1.4" atty = "0.2" termcolor = "1.0" annotate-snippets = "0.6.1" +term_size = "0.3.1" diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index b7615fef04909..6bb151d19b32b 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -24,7 +24,7 @@ use rustc_data_structures::sync::Lrc; use std::borrow::Cow; use std::io::prelude::*; use std::io; -use std::cmp::{min, Reverse}; +use std::cmp::{min, max, Reverse}; use std::path::Path; use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter, Ansi}; use termcolor::{WriteColor, Color, Buffer}; @@ -59,13 +59,20 @@ impl HumanReadableErrorType { #[derive(Clone, Copy, Debug)] struct Margin { + /// The available whitespace in the left that can be consumed when centering. pub whitespace_left: usize, + /// The column of the beginning of left-most span. pub span_left: usize, + /// The column of the end of right-most span. pub span_right: usize, - pub line_len: usize, + /// The beginning of the line to be displayed. pub computed_left: usize, + /// The end of the line to be displayed. pub computed_right: usize, + /// The current width of the terminal. 140 by default and in tests. pub column_width: usize, + /// The end column of a span label, including the span. Doesn't account for labels not in the + /// same line as the span. pub label_right: usize, } @@ -75,59 +82,92 @@ impl Margin { span_left: usize, span_right: usize, label_right: usize, + column_width: usize, + max_line_len: usize, ) -> Self { - Margin { - whitespace_left, - span_left, - span_right, - line_len: 0, + // The 6 is padding to give a bit of room for `...` when displaying: + // ``` + // error: message + // --> file.rs:16:58 + // | + // 16 | ... fn foo(self) -> Self::Bar { + // | ^^^^^^^^^ + // ``` + + let mut m = Margin { + whitespace_left: if whitespace_left >= 6 { whitespace_left - 6 } else { 0 }, + span_left: if span_left >= 6 { span_left - 6 } else { 0 }, + span_right: span_right + 6, computed_left: 0, computed_right: 0, - column_width: 140, - label_right, - } + column_width, + label_right: label_right + 6, + }; + m.compute(max_line_len); + m } fn was_cut_left(&self) -> bool { self.computed_left > 0 } - fn was_cut_right(&self) -> bool { - self.computed_right < self.line_len + fn was_cut_right(&self, line_len: usize) -> bool { + let right = if self.computed_right == self.span_right || + self.computed_right == self.label_right + { + // Account for the "..." padding given above. Otherwise we end up with code lines that + // do fit but end in "..." as if they were trimmed. + self.computed_right - 6 + } else { + self.computed_right + }; + right < line_len && line_len > self.computed_left + self.column_width } - fn compute(&mut self) { + fn compute(&mut self, max_line_len: usize) { + // When there's a lot of whitespace (>20), we want to trim it as it is useless. self.computed_left = if self.whitespace_left > 20 { self.whitespace_left - 16 // We want some padding. } else { 0 }; - self.computed_right = self.column_width + self.computed_left; + // We want to show as much as possible, max_line_len is the right-most boundary for the + // relevant code. + self.computed_right = max(max_line_len, self.computed_left); if self.computed_right - self.computed_left > self.column_width { // Trimming only whitespace isn't enough, let's get craftier. if self.label_right - self.whitespace_left <= self.column_width { + // Attempt to fit the code window only trimming whitespace. self.computed_left = self.whitespace_left; self.computed_right = self.computed_left + self.column_width; - } else if self.label_right - self.span_left - 20 <= self.column_width { - self.computed_left = self.span_left - 20; - self.computed_right = self.computed_left + self.column_width; } else if self.label_right - self.span_left <= self.column_width { + // Attempt to fit the code window considering only the spans and labels. self.computed_left = self.span_left; self.computed_right = self.computed_left + self.column_width; } else if self.span_right - self.span_left <= self.column_width { + // Attempt to fit the code window considering the spans and labels plus padding. self.computed_left = self.span_left; self.computed_right = self.computed_left + self.column_width; - } else { // mostly give up but still don't show the full line + } else { // Mostly give up but still don't show the full line. self.computed_left = self.span_left; self.computed_right = self.span_right; } } - self.computed_left = std::cmp::min(self.computed_left, self.line_len); - if self.computed_right > self.line_len { - self.computed_right = self.line_len; + } + + fn left(&self, line_len: usize) -> usize { + min(self.computed_left, line_len) + } + + fn right(&self, line_len: usize) -> usize { + if max(line_len, self.computed_left) - self.computed_left <= self.column_width { + line_len + } else if self.computed_right > line_len { + line_len + } else { + self.computed_right } - self.computed_right = std::cmp::min(self.computed_right, self.line_len); } } @@ -308,6 +348,42 @@ impl EmitterWriter { } } + fn draw_line( + &self, + buffer: &mut StyledBuffer, + source_string: &str, + line_index: usize, + line_offset: usize, + width_offset: usize, + code_offset: usize, + margin: Margin, + ) { + let line_len = source_string.len(); + // Create the source line we will highlight. + buffer.puts( + line_offset, + code_offset, + // On long lines, we strip the source line + &source_string[margin.left(line_len)..margin.right(line_len)], + Style::Quotation, + ); + if margin.was_cut_left() { // We have stripped some code/whitespace from the beginning, make it clear. + buffer.puts(line_offset, code_offset, "...", Style::LineNumber); + } + if margin.was_cut_right(line_len) { + // We have stripped some code after the right-most span end, make it clear we did so. + buffer.puts( + line_offset, + margin.right(line_len) - margin.left(line_len) + code_offset - 3, + "...", + Style::LineNumber, + ); + } + buffer.puts(line_offset, 0, &self.maybe_anonymized(line_index), Style::LineNumber); + + draw_col_separator(buffer, line_offset, width_offset - 2); + } + fn render_source_line( &self, buffer: &mut StyledBuffer, @@ -315,7 +391,7 @@ impl EmitterWriter { line: &Line, width_offset: usize, code_offset: usize, - mut margin: Margin, + margin: Margin, ) -> Vec<(usize, Style)> { // Draw: // @@ -342,31 +418,15 @@ impl EmitterWriter { let line_offset = buffer.num_lines(); - margin.line_len = source_string.len(); - margin.compute(); - // Create the source line we will highlight. - buffer.puts( + self.draw_line( + buffer, + &source_string, + line.line_index, line_offset, + width_offset, code_offset, - // On long lines, we strip the source line - &source_string[margin.computed_left..margin.computed_right], - Style::Quotation, + margin, ); - if margin.was_cut_left() { // We have stripped some code/whitespace from the beginning, make it clear. - buffer.puts(line_offset, code_offset, "...", Style::LineNumber); - } - if margin.was_cut_right() { - // We have stripped some code after the right-most span end, make it clear we did so. - buffer.puts( - line_offset, - margin.computed_right - margin.computed_left + code_offset, - "...", - Style::LineNumber, - ); - } - buffer.puts(line_offset, 0, &self.maybe_anonymized(line.line_index), Style::LineNumber); - - draw_col_separator(buffer, line_offset, width_offset - 2); // Special case when there's only one annotation involved, it is the start of a multiline // span and there's no text at the beginning of the code line. Instead of doing the whole @@ -614,19 +674,23 @@ impl EmitterWriter { match annotation.annotation_type { AnnotationType::MultilineStart(depth) | AnnotationType::MultilineEnd(depth) => { - draw_range(buffer, - '_', - line_offset + pos, - width_offset + depth, - code_offset + annotation.start_col - margin.computed_left, - style); + draw_range( + buffer, + '_', + line_offset + pos, + width_offset + depth, + code_offset + annotation.start_col - margin.computed_left, + style, + ); } _ if self.teach => { - buffer.set_style_range(line_offset, - code_offset + annotation.start_col - margin.computed_left, - code_offset + annotation.end_col - margin.computed_left, - style, - annotation.is_primary); + buffer.set_style_range( + line_offset, + code_offset + annotation.start_col - margin.computed_left, + code_offset + annotation.end_col - margin.computed_left, + style, + annotation.is_primary, + ); } _ => {} } @@ -1159,7 +1223,7 @@ impl EmitterWriter { .take_while(|c| c.is_whitespace()) .count(); if source_string.chars().any(|c| !c.is_whitespace()) { - whitespace_margin = std::cmp::min( + whitespace_margin = min( whitespace_margin, leading_whitespace, ); @@ -1174,8 +1238,8 @@ impl EmitterWriter { let mut span_left_margin = std::usize::MAX; for line in &annotated_file.lines { for ann in &line.annotations { - span_left_margin = std::cmp::min(span_left_margin, ann.start_col); - span_left_margin = std::cmp::min(span_left_margin, ann.end_col); + span_left_margin = min(span_left_margin, ann.start_col); + span_left_margin = min(span_left_margin, ann.end_col); } } if span_left_margin == std::usize::MAX { @@ -1185,35 +1249,49 @@ impl EmitterWriter { // Right-most column any visible span points at. let mut span_right_margin = 0; let mut label_right_margin = 0; + let mut max_line_len = 0; for line in &annotated_file.lines { + max_line_len = max( + max_line_len, + annotated_file.file.get_line(line.line_index - 1).map(|s| s.len()).unwrap_or(0), + ); for ann in &line.annotations { - span_right_margin = std::cmp::max(span_right_margin, ann.start_col); - span_right_margin = std::cmp::max(span_right_margin, ann.end_col); - label_right_margin = std::cmp::max( + span_right_margin = max(span_right_margin, ann.start_col); + span_right_margin = max(span_right_margin, ann.end_col); + label_right_margin = max( label_right_margin, // TODO: account for labels not in the same line ann.end_col + ann.label.as_ref().map(|l| l.len() + 1).unwrap_or(0), ); } } + + let width_offset = 3 + max_line_num_len; + let code_offset = if annotated_file.multiline_depth == 0 { + width_offset + } else { + width_offset + annotated_file.multiline_depth + 1 + }; + + let column_width = if self.ui_testing { + 140 + } else { + term_size::dimensions().map(|(w, _)| w - code_offset).unwrap_or(140) + }; + let margin = Margin::new( whitespace_margin, span_left_margin, span_right_margin, label_right_margin, + column_width, + max_line_len, ); // Next, output the annotate source for this file for line_idx in 0..annotated_file.lines.len() { let previous_buffer_line = buffer.num_lines(); - let width_offset = 3 + max_line_num_len; - let code_offset = if annotated_file.multiline_depth == 0 { - width_offset - } else { - width_offset + annotated_file.multiline_depth + 1 - }; - let depths = self.render_source_line( &mut buffer, annotated_file.file.clone(), @@ -1268,36 +1346,24 @@ impl EmitterWriter { let last_buffer_line_num = buffer.num_lines(); - buffer.puts( - last_buffer_line_num, - 0, - &self.maybe_anonymized( - annotated_file.lines[line_idx + 1].line_index - 1, - ), - Style::LineNumber, - ); - draw_col_separator( + self.draw_line( &mut buffer, + &unannotated_line, + annotated_file.lines[line_idx + 1].line_index - 1, last_buffer_line_num, - 1 + max_line_num_len, - ); - - let mut margin = margin; - margin.line_len = unannotated_line.len(); - margin.compute(); - buffer.puts( - last_buffer_line_num, + width_offset, code_offset, - &unannotated_line[margin.computed_left..margin.computed_right], - Style::Quotation, + margin, ); for (depth, style) in &multilines { - draw_multiline_line(&mut buffer, - last_buffer_line_num, - width_offset, - *depth, - *style); + draw_multiline_line( + &mut buffer, + last_buffer_line_num, + width_offset, + *depth, + *style, + ); } } } diff --git a/src/test/ui/inline-asm-bad-operand.stderr b/src/test/ui/inline-asm-bad-operand.stderr index d5c1cf51dafaa..55523bad6c507 100644 --- a/src/test/ui/inline-asm-bad-operand.stderr +++ b/src/test/ui/inline-asm-bad-operand.stderr @@ -37,8 +37,8 @@ LL | asm!("mov sp, $0"::"r"(addr), error[E0669]: invalid value for constraint in inline assembly --> $DIR/inline-asm-bad-operand.rs:56:32 | -LL | ... "r"("hello e0669")); - | ^^^^^^^^^^^^^ +LL | ... "r"("hello e0669")); + | ^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr index 3262662a2a5e6..a0b34d220c8d9 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -38,8 +38,8 @@ LL | if let SoulHistory { corridors_of_light, warning: variable `hours_are_suns` is assigned to, but never used --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:30 | -LL | ... mut hours_are_suns, - | ^^^^^^^^^^^^^^ +LL | mut hours_are_suns, + | ^^^^^^^^^^^^^^ | = note: consider using `_hours_are_suns` instead diff --git a/src/test/ui/lint/lint-stability-deprecated.stderr b/src/test/ui/lint/lint-stability-deprecated.stderr index 8132a66df8a0f..62380135b333b 100644 --- a/src/test/ui/lint/lint-stability-deprecated.stderr +++ b/src/test/ui/lint/lint-stability-deprecated.stderr @@ -67,14 +67,14 @@ LL | deprecated_unstable_text(); warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:57:9 | -LL | Trait::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... Trait::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:59:9 | -LL | ::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::DeprecatedStruct': text --> $DIR/lint-stability-deprecated.rs:106:17 @@ -181,14 +181,14 @@ LL | ::trait_deprecated_unstable(&foo); warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:155:9 | -LL | Trait::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... Trait::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:157:9 | -LL | ::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::DeprecatedTrait': text --> $DIR/lint-stability-deprecated.rs:185:10 @@ -421,20 +421,20 @@ LL | ::trait_deprecated_unstable(&foo); warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:53:13 | -LL | foo.method_deprecated_unstable_text(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... foo.method_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:54:9 | -LL | Foo::method_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... Foo::method_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:55:9 | -LL | ::method_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::method_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:56:13 @@ -445,8 +445,8 @@ LL | foo.trait_deprecated_unstable_text(); warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:58:9 | -LL | ::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::DeprecatedStruct::i': text --> $DIR/lint-stability-deprecated.rs:107:13 @@ -505,8 +505,8 @@ LL | foo.trait_deprecated_unstable_text(); warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text --> $DIR/lint-stability-deprecated.rs:156:9 | -LL | ::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text --> $DIR/lint-stability-deprecated.rs:173:13 diff --git a/src/test/ui/methods/method-missing-call.stderr b/src/test/ui/methods/method-missing-call.stderr index fe44d3a29dab5..3ab5f66a0c3f6 100644 --- a/src/test/ui/methods/method-missing-call.stderr +++ b/src/test/ui/methods/method-missing-call.stderr @@ -1,8 +1,8 @@ error[E0615]: attempted to take value of method `get_x` on type `Point` --> $DIR/method-missing-call.rs:22:26 | -LL | ... .get_x; - | ^^^^^ help: use parentheses to call the method: `get_x()` +LL | .get_x; + | ^^^^^ help: use parentheses to call the method: `get_x()` error[E0615]: attempted to take value of method `filter_map` on type `std::iter::Filter, [closure@$DIR/method-missing-call.rs:27:20: 27:25]>, [closure@$DIR/method-missing-call.rs:28:23: 28:35]>` --> $DIR/method-missing-call.rs:29:16 diff --git a/src/test/ui/regions/regions-name-undeclared.stderr b/src/test/ui/regions/regions-name-undeclared.stderr index fe0345c3a380c..5f6a48a35f368 100644 --- a/src/test/ui/regions/regions-name-undeclared.stderr +++ b/src/test/ui/regions/regions-name-undeclared.stderr @@ -49,14 +49,14 @@ LL | fn fn_types(a: &'a isize, error[E0261]: use of undeclared lifetime name `'b` --> $DIR/regions-name-undeclared.rs:42:36 | -LL | ... &'b isize, - | ^^ undeclared lifetime +LL | ... &'b isize, + | ^^ undeclared lifetime error[E0261]: use of undeclared lifetime name `'b` --> $DIR/regions-name-undeclared.rs:45:36 | -LL | ... &'b isize)>, - | ^^ undeclared lifetime +LL | ... &'b isize)>, + | ^^ undeclared lifetime error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-name-undeclared.rs:46:17 diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-2.rs b/src/test/ui/terminal-width/non-whitespace-trimming-2.rs new file mode 100644 index 0000000000000..31e979702ffd4 --- /dev/null +++ b/src/test/ui/terminal-width/non-whitespace-trimming-2.rs @@ -0,0 +1,6 @@ +// ignore-tidy-length + +fn main() { + let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); +//~^ ERROR mismatched types +} diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-2.stderr b/src/test/ui/terminal-width/non-whitespace-trimming-2.stderr new file mode 100644 index 0000000000000..3821d86e23a84 --- /dev/null +++ b/src/test/ui/terminal-width/non-whitespace-trimming-2.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/non-whitespace-trimming-2.rs:4:241 + | +LL | ... = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = ();... + | ^^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/terminal-width/non-whitespace-trimming.rs b/src/test/ui/terminal-width/non-whitespace-trimming.rs new file mode 100644 index 0000000000000..791e8a592d1ab --- /dev/null +++ b/src/test/ui/terminal-width/non-whitespace-trimming.rs @@ -0,0 +1,6 @@ +// ignore-tidy-length + +fn main() { + let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); +//~^ ERROR mismatched types +} diff --git a/src/test/ui/terminal-width/non-whitespace-trimming.stderr b/src/test/ui/terminal-width/non-whitespace-trimming.stderr new file mode 100644 index 0000000000000..36e6d8045a8b6 --- /dev/null +++ b/src/test/ui/terminal-width/non-whitespace-trimming.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/non-whitespace-trimming.rs:4:241 + | +LL | ... = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); + | ^^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/terminal-width/whitespace-trimming-2.rs b/src/test/ui/terminal-width/whitespace-trimming-2.rs new file mode 100644 index 0000000000000..bc02c685dc950 --- /dev/null +++ b/src/test/ui/terminal-width/whitespace-trimming-2.rs @@ -0,0 +1,8 @@ +// ignore-tidy-length + +fn foo() -> usize { + () +//~^ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/terminal-width/whitespace-trimming-2.stderr b/src/test/ui/terminal-width/whitespace-trimming-2.stderr new file mode 100644 index 0000000000000..38df5a9e9a01f --- /dev/null +++ b/src/test/ui/terminal-width/whitespace-trimming-2.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/whitespace-trimming-2.rs:4:187 + | +LL | ...-> usize { + | ----- expected `usize` because of return type +LL | ... () + | ^^ expected usize, found () + | + = note: expected type `usize` + found type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/terminal-width/whitespace-trimming.rs b/src/test/ui/terminal-width/whitespace-trimming.rs new file mode 100644 index 0000000000000..427ed1e72e48a --- /dev/null +++ b/src/test/ui/terminal-width/whitespace-trimming.rs @@ -0,0 +1,6 @@ +// ignore-tidy-length + +fn main() { + let _: () = 42; +//~^ ERROR mismatched types +} diff --git a/src/test/ui/terminal-width/whitespace-trimming.stderr b/src/test/ui/terminal-width/whitespace-trimming.stderr new file mode 100644 index 0000000000000..45a804b9f6a46 --- /dev/null +++ b/src/test/ui/terminal-width/whitespace-trimming.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/whitespace-trimming.rs:4:193 + | +LL | ... let _: () = 42; + | ^^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index de54eb8f57312..92f60b2ddab73 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -159,6 +159,7 @@ const WHITELIST: &[Crate<'_>] = &[ Crate("termcolor"), Crate("terminon"), Crate("termion"), + Crate("term_size"), Crate("thread_local"), Crate("ucd-util"), Crate("unicode-width"), From 45a6be545891f4a8f19f0dce801b67fdccf435ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 14 Aug 2019 11:44:56 -0700 Subject: [PATCH 097/618] Fix tidy --- src/librustc_errors/emitter.rs | 21 +++++++++---------- .../non-whitespace-trimming-2.rs | 2 +- .../terminal-width/non-whitespace-trimming.rs | 2 +- .../terminal-width/whitespace-trimming-2.rs | 2 +- .../ui/terminal-width/whitespace-trimming.rs | 2 +- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 6bb151d19b32b..a78a4365633f7 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -367,7 +367,8 @@ impl EmitterWriter { &source_string[margin.left(line_len)..margin.right(line_len)], Style::Quotation, ); - if margin.was_cut_left() { // We have stripped some code/whitespace from the beginning, make it clear. + if margin.was_cut_left() { + // We have stripped some code/whitespace from the beginning, make it clear. buffer.puts(line_offset, code_offset, "...", Style::LineNumber); } if margin.was_cut_right(line_len) { @@ -403,7 +404,7 @@ impl EmitterWriter { // ^^ ^ ^^^ ^^^^ ^^^ we don't care about code too far to the right of a span, we trim it // | | | | // | | | actual code found in your source code and the spans we use to mark it - // | | when there's too much wasted space to the left, we trim it to focus where it matters + // | | when there's too much wasted space to the left, trim it // | vertical divider between the column number and the code // column number @@ -1251,18 +1252,16 @@ impl EmitterWriter { let mut label_right_margin = 0; let mut max_line_len = 0; for line in &annotated_file.lines { - max_line_len = max( - max_line_len, - annotated_file.file.get_line(line.line_index - 1).map(|s| s.len()).unwrap_or(0), - ); + max_line_len = max(max_line_len, annotated_file.file + .get_line(line.line_index - 1) + .map(|s| s.len()) + .unwrap_or(0)); for ann in &line.annotations { span_right_margin = max(span_right_margin, ann.start_col); span_right_margin = max(span_right_margin, ann.end_col); - label_right_margin = max( - label_right_margin, - // TODO: account for labels not in the same line - ann.end_col + ann.label.as_ref().map(|l| l.len() + 1).unwrap_or(0), - ); + // FIXME: account for labels not in the same line + let label_right = ann.label.as_ref().map(|l| l.len() + 1).unwrap_or(0); + label_right_margin = max(label_right_margin, ann.end_col + label_right); } } diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-2.rs b/src/test/ui/terminal-width/non-whitespace-trimming-2.rs index 31e979702ffd4..b1ef6b95f25ce 100644 --- a/src/test/ui/terminal-width/non-whitespace-trimming-2.rs +++ b/src/test/ui/terminal-width/non-whitespace-trimming-2.rs @@ -1,4 +1,4 @@ -// ignore-tidy-length +// ignore-tidy-linelength fn main() { let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); diff --git a/src/test/ui/terminal-width/non-whitespace-trimming.rs b/src/test/ui/terminal-width/non-whitespace-trimming.rs index 791e8a592d1ab..f6c8d345c652e 100644 --- a/src/test/ui/terminal-width/non-whitespace-trimming.rs +++ b/src/test/ui/terminal-width/non-whitespace-trimming.rs @@ -1,4 +1,4 @@ -// ignore-tidy-length +// ignore-tidy-linelength fn main() { let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); diff --git a/src/test/ui/terminal-width/whitespace-trimming-2.rs b/src/test/ui/terminal-width/whitespace-trimming-2.rs index bc02c685dc950..c68f678aab349 100644 --- a/src/test/ui/terminal-width/whitespace-trimming-2.rs +++ b/src/test/ui/terminal-width/whitespace-trimming-2.rs @@ -1,4 +1,4 @@ -// ignore-tidy-length +// ignore-tidy-linelength fn foo() -> usize { () diff --git a/src/test/ui/terminal-width/whitespace-trimming.rs b/src/test/ui/terminal-width/whitespace-trimming.rs index 427ed1e72e48a..f747bcf17e0b4 100644 --- a/src/test/ui/terminal-width/whitespace-trimming.rs +++ b/src/test/ui/terminal-width/whitespace-trimming.rs @@ -1,4 +1,4 @@ -// ignore-tidy-length +// ignore-tidy-linelength fn main() { let _: () = 42; From de2e9fe2c476021c7589d840a3b3ae870e0a75d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 14 Aug 2019 14:09:37 -0700 Subject: [PATCH 098/618] Center trim on the span labels and handle unicode --- src/librustc_errors/emitter.rs | 57 ++++++++++++------- .../non-whitespace-trimming-2.rs | 2 +- .../non-whitespace-trimming-2.stderr | 6 +- .../non-whitespace-trimming.stderr | 4 +- 4 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index a78a4365633f7..d20e700b355a1 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -143,11 +143,13 @@ impl Margin { self.computed_right = self.computed_left + self.column_width; } else if self.label_right - self.span_left <= self.column_width { // Attempt to fit the code window considering only the spans and labels. - self.computed_left = self.span_left; + let padding_left = (self.column_width - (self.label_right - self.span_left)) / 2; + self.computed_left = self.span_left - padding_left; self.computed_right = self.computed_left + self.column_width; } else if self.span_right - self.span_left <= self.column_width { // Attempt to fit the code window considering the spans and labels plus padding. - self.computed_left = self.span_left; + let padding_left = (self.column_width - (self.span_right - self.span_left)) / 2; + self.computed_left = self.span_left - padding_left; self.computed_right = self.computed_left + self.column_width; } else { // Mostly give up but still don't show the full line. self.computed_left = self.span_left; @@ -360,13 +362,11 @@ impl EmitterWriter { ) { let line_len = source_string.len(); // Create the source line we will highlight. - buffer.puts( - line_offset, - code_offset, - // On long lines, we strip the source line - &source_string[margin.left(line_len)..margin.right(line_len)], - Style::Quotation, - ); + let left = margin.left(line_len); + let right = margin.right(line_len); + // On long lines, we strip the source line, accounting for unicode. + let code: String = source_string.chars().skip(left).take(right - left).collect(); + buffer.puts(line_offset, code_offset, &code, Style::Quotation); if margin.was_cut_left() { // We have stripped some code/whitespace from the beginning, make it clear. buffer.puts(line_offset, code_offset, "...", Style::LineNumber); @@ -419,6 +419,8 @@ impl EmitterWriter { let line_offset = buffer.num_lines(); + let left = margin.left(source_string.len()); // Left trim + self.draw_line( buffer, &source_string, @@ -680,15 +682,15 @@ impl EmitterWriter { '_', line_offset + pos, width_offset + depth, - code_offset + annotation.start_col - margin.computed_left, + code_offset + annotation.start_col - left, style, ); } _ if self.teach => { buffer.set_style_range( line_offset, - code_offset + annotation.start_col - margin.computed_left, - code_offset + annotation.end_col - margin.computed_left, + code_offset + annotation.start_col - left, + code_offset + annotation.end_col - left, style, annotation.is_primary, ); @@ -763,15 +765,20 @@ impl EmitterWriter { Style::LabelSecondary }; let (pos, col) = if pos == 0 { - (pos + 1, annotation.end_col + 1 - margin.computed_left) + (pos + 1, if annotation.end_col + 1 > left { + annotation.end_col + 1 - left + } else { + 0 + }) } else { - (pos + 2, annotation.start_col - margin.computed_left) + (pos + 2, if annotation.start_col > left { + annotation.start_col - left + } else { + 0 + }) }; if let Some(ref label) = annotation.label { - buffer.puts(line_offset + pos, - code_offset + col, - &label, - style); + buffer.puts(line_offset + pos, code_offset + col, &label, style); } } @@ -806,10 +813,16 @@ impl EmitterWriter { ('-', Style::UnderlineSecondary) }; for p in annotation.start_col..annotation.end_col { - buffer.putc(line_offset + 1, - code_offset + p - margin.computed_left, - underline, - style); + buffer.putc( + line_offset + 1, + if code_offset + p > left { + code_offset + p - left + } else { + 0 + }, + underline, + style, + ); } } annotations_position.iter().filter_map(|&(_, annotation)| { diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-2.rs b/src/test/ui/terminal-width/non-whitespace-trimming-2.rs index b1ef6b95f25ce..abd9e189a7537 100644 --- a/src/test/ui/terminal-width/non-whitespace-trimming-2.rs +++ b/src/test/ui/terminal-width/non-whitespace-trimming-2.rs @@ -1,6 +1,6 @@ // ignore-tidy-linelength fn main() { - let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); + let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _: usize = 4; let _: usize = 5; let _: usize = 6; let _: usize = 7; let _: usize = 8; let _: usize = 9; let _: usize = 10; let _: usize = 11; let _: usize = 12; let _: usize = 13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _: usize = 4; let _: usize = 5; let _: usize = 6; let _: usize = 7; let _: usize = 8; let _: usize = 9; let _: usize = 10; let _: usize = 11; let _: usize = 12; let _: usize = 13; let _: usize = 14; let _: usize = 15; //~^ ERROR mismatched types } diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-2.stderr b/src/test/ui/terminal-width/non-whitespace-trimming-2.stderr index 3821d86e23a84..bf1699f5cabbb 100644 --- a/src/test/ui/terminal-width/non-whitespace-trimming-2.stderr +++ b/src/test/ui/terminal-width/non-whitespace-trimming-2.stderr @@ -1,8 +1,8 @@ error[E0308]: mismatched types - --> $DIR/non-whitespace-trimming-2.rs:4:241 + --> $DIR/non-whitespace-trimming-2.rs:4:311 | -LL | ... = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = ();... - | ^^ expected (), found integer +LL | ...; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _:... + | ^^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/terminal-width/non-whitespace-trimming.stderr b/src/test/ui/terminal-width/non-whitespace-trimming.stderr index 36e6d8045a8b6..622713eb5f6fc 100644 --- a/src/test/ui/terminal-width/non-whitespace-trimming.stderr +++ b/src/test/ui/terminal-width/non-whitespace-trimming.stderr @@ -1,8 +1,8 @@ error[E0308]: mismatched types --> $DIR/non-whitespace-trimming.rs:4:241 | -LL | ... = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); - | ^^ expected (), found integer +LL | ...) = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = ()... + | ^^ expected (), found integer | = note: expected type `()` found type `{integer}` From 9980796d6d29f532e9a49a5b3767285e2a5e2d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 14 Aug 2019 17:06:09 -0700 Subject: [PATCH 099/618] Further unicode checks --- src/librustc_errors/emitter.rs | 30 ++++++++++++------- .../non-whitespace-trimming-unicode.rs | 6 ++++ .../non-whitespace-trimming-unicode.stderr | 12 ++++++++ 3 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/terminal-width/non-whitespace-trimming-unicode.rs create mode 100644 src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index d20e700b355a1..83c55c0da2b4f 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -148,7 +148,7 @@ impl Margin { self.computed_right = self.computed_left + self.column_width; } else if self.span_right - self.span_left <= self.column_width { // Attempt to fit the code window considering the spans and labels plus padding. - let padding_left = (self.column_width - (self.span_right - self.span_left)) / 2; + let padding_left = (self.column_width - (self.span_right - self.span_left)) / 5 * 2; self.computed_left = self.span_left - padding_left; self.computed_right = self.computed_left + self.column_width; } else { // Mostly give up but still don't show the full line. @@ -365,7 +365,18 @@ impl EmitterWriter { let left = margin.left(line_len); let right = margin.right(line_len); // On long lines, we strip the source line, accounting for unicode. - let code: String = source_string.chars().skip(left).take(right - left).collect(); + let mut taken = 0; + let code: String = source_string.chars().skip(left).take_while(|ch| { + // Make sure that the trimming on the right will fall within the terminal width. + // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. + // For now, just accept that sometimes the code line will be longer than desired. + let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1); + if taken + next > right - left { + return false; + } + taken += next; + true + }).collect(); buffer.puts(line_offset, code_offset, &code, Style::Quotation); if margin.was_cut_left() { // We have stripped some code/whitespace from the beginning, make it clear. @@ -373,12 +384,7 @@ impl EmitterWriter { } if margin.was_cut_right(line_len) { // We have stripped some code after the right-most span end, make it clear we did so. - buffer.puts( - line_offset, - margin.right(line_len) - margin.left(line_len) + code_offset - 3, - "...", - Style::LineNumber, - ); + buffer.puts(line_offset, code_offset + taken - 3, "...", Style::LineNumber); } buffer.puts(line_offset, 0, &self.maybe_anonymized(line_index), Style::LineNumber); @@ -420,6 +426,10 @@ impl EmitterWriter { let line_offset = buffer.num_lines(); let left = margin.left(source_string.len()); // Left trim + // Account for unicode characters of width !=0 that were removed. + let left = source_string.chars().take(left).fold(0, |acc, ch| { + acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) + }); self.draw_line( buffer, @@ -1465,7 +1475,7 @@ impl EmitterWriter { // ...or trailing spaces. Account for substitutions containing unicode // characters. let sub_len = part.snippet.trim().chars().fold(0, |acc, ch| { - acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0) + acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) }); let underline_start = (span_start_pos + start) as isize + offset; @@ -1488,7 +1498,7 @@ impl EmitterWriter { // length of the code after substitution let full_sub_len = part.snippet.chars().fold(0, |acc, ch| { - acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0) as isize + acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) as isize }); // length of the code to be substituted diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-unicode.rs b/src/test/ui/terminal-width/non-whitespace-trimming-unicode.rs new file mode 100644 index 0000000000000..8d4d1b1627940 --- /dev/null +++ b/src/test/ui/terminal-width/non-whitespace-trimming-unicode.rs @@ -0,0 +1,6 @@ +// ignore-tidy-linelength + +fn main() { + let _: &str = "🦀☀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓ ☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄♅♆♇â™â™”♕♖♗♘♙♚♛♜â™â™žâ™Ÿâ™ â™¡â™¢â™£â™¤â™¥â™¦â™§â™¨â™©â™ªâ™«â™¬â™­â™®â™¯â™°â™±â™²â™³â™´â™µâ™¶â™·â™¸â™¹â™ºâ™»â™¼â™½â™¾â™¿âš€âšâš‚⚃⚄⚅⚆⚈⚉4🦀☀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄♅♆♇â™â™”♕♖♗♘♙♚♛♜â™â™žâ™Ÿâ™ â™¡â™¢â™£â™¤â™¥â™¦â™§â™¨â™©â™ªâ™«â™¬â™­â™®â™¯â™°â™±â™²â™³â™´â™µâ™¶â™·â™¸â™¹â™ºâ™»â™¼â™½â™¾â™¿âš€âšâš‚⚃⚄⚅⚆⚈⚉4🦀🦀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄♅♆♇â™â™”♕♖♗♘♙♚♛♜â™â™žâ™Ÿâ™ â™¡â™¢â™£â™¤â™¥â™¦â™§â™¨â™©â™ªâ™«â™¬â™­â™®â™¯â™°â™±â™²â™³â™´â™µâ™¶â™·â™¸â™¹â™ºâ™»â™¼â™½â™¾â™¿âš€âšâš‚⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓ ☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄♅♆♇â™â™”♕♖♗♘♙♚♛♜â™â™žâ™Ÿâ™ â™¡â™¢â™£â™¤â™¥â™¦â™§â™¨â™©â™ªâ™«â™¬â™­â™®â™¯â™°â™±â™²â™³â™´â™µâ™¶â™·â™¸â™¹â™ºâ™»â™¼â™½â™¾â™¿âš€âšâš‚⚃⚄⚅⚆⚈⚉4🦀☀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄♅♆♇â™â™”♕♖♗♘♙♚♛♜â™â™žâ™Ÿâ™ â™¡â™¢â™£â™¤â™¥â™¦â™§â™¨â™©â™ªâ™«â™¬â™­â™®â™¯â™°â™±â™²â™³â™´â™µâ™¶â™·â™¸â™¹â™ºâ™»â™¼â™½â™¾â™¿âš€âšâš‚⚃⚄⚅⚆⚈⚉4🦀🦀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄♅♆♇â™â™”♕♖♗♘♙♚♛♜â™â™žâ™Ÿâ™ â™¡â™¢â™£â™¤â™¥â™¦â™§â™¨â™©â™ªâ™«â™¬â™­â™®â™¯â™°â™±â™²â™³â™´â™µâ™¶â™·â™¸â™¹â™ºâ™»â™¼â™½â™¾â™¿âš€âšâš‚⚃⚄⚅⚆⚈⚉4"; +//~^ ERROR mismatched types +} diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr b/src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr new file mode 100644 index 0000000000000..b56b1948d9e07 --- /dev/null +++ b/src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/non-whitespace-trimming-unicode.rs:4:415 + | +LL | ...♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀âšâš‚⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓ ☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄♅♆... + | ^^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 21f2e9334567b64436f4e6525c5c98adafd16ca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 14 Aug 2019 17:57:28 -0700 Subject: [PATCH 100/618] Add terminal_width debugging flag --- src/librustc/session/config.rs | 2 ++ src/librustc/session/mod.rs | 6 ++++-- src/librustc_driver/lib.rs | 12 +++++++----- src/librustc_errors/emitter.rs | 24 +++++++++++++++++------- src/librustc_errors/lib.rs | 2 +- src/librustdoc/core.rs | 1 + src/librustdoc/test.rs | 2 +- src/libsyntax/json.rs | 2 +- src/libsyntax/parse/lexer/tests.rs | 9 ++++++++- src/libsyntax/tests.rs | 13 ++++++++----- 10 files changed, 50 insertions(+), 23 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 8e3b910e0da3a..89481e9eafde5 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1292,6 +1292,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "show macro backtraces even for non-local macros"), teach: bool = (false, parse_bool, [TRACKED], "show extended diagnostic help"), + terminal_width: Option = (None, parse_opt_uint, [UNTRACKED], + "set the current terminal width"), continue_parse_after_error: bool = (false, parse_bool, [TRACKED], "attempt to recover from parse errors (experimental)"), dep_tasks: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 61dac678912df..f01883d9634cd 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -1055,6 +1055,7 @@ fn default_emitter( Some(source_map.clone()), short, sopts.debugging_opts.teach, + sopts.debugging_opts.terminal_width, ), Some(dst) => EmitterWriter::new( dst, @@ -1062,6 +1063,7 @@ fn default_emitter( short, false, // no teach messages when writing to a buffer false, // no colors when writing to a buffer + None, // no terminal width ), }; Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing)) @@ -1375,7 +1377,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { let emitter: Box = match output { config::ErrorOutputType::HumanReadable(kind) => { let (short, color_config) = kind.unzip(); - Box::new(EmitterWriter::stderr(color_config, None, short, false)) + Box::new(EmitterWriter::stderr(color_config, None, short, false, None)) } config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::basic(pretty, json_rendered)), @@ -1389,7 +1391,7 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) { let emitter: Box = match output { config::ErrorOutputType::HumanReadable(kind) => { let (short, color_config) = kind.unzip(); - Box::new(EmitterWriter::stderr(color_config, None, short, false)) + Box::new(EmitterWriter::stderr(color_config, None, short, false, None)) } config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::basic(pretty, json_rendered)), diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index b19ea513b7575..3d94d51f17ec0 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1135,11 +1135,13 @@ pub fn report_ices_to_stderr_if_any R, R>(f: F) -> Result, source_map: Option>, teach: bool, + terminal_width: Option, ) -> EmitterWriter { let (short, color_config) = self.unzip(); - EmitterWriter::new(dst, source_map, short, teach, color_config.suggests_using_colors()) + let color = color_config.suggests_using_colors(); + EmitterWriter::new(dst, source_map, short, teach, color, terminal_width) } } @@ -296,6 +298,7 @@ pub struct EmitterWriter { short_message: bool, teach: bool, ui_testing: bool, + terminal_width: Option, } #[derive(Debug)] @@ -306,11 +309,13 @@ pub struct FileWithAnnotatedLines { } impl EmitterWriter { - pub fn stderr(color_config: ColorConfig, - source_map: Option>, - short_message: bool, - teach: bool) - -> EmitterWriter { + pub fn stderr( + color_config: ColorConfig, + source_map: Option>, + short_message: bool, + teach: bool, + terminal_width: Option, + ) -> EmitterWriter { let dst = Destination::from_stderr(color_config); EmitterWriter { dst, @@ -318,6 +323,7 @@ impl EmitterWriter { short_message, teach, ui_testing: false, + terminal_width, } } @@ -327,6 +333,7 @@ impl EmitterWriter { short_message: bool, teach: bool, colored: bool, + terminal_width: Option, ) -> EmitterWriter { EmitterWriter { dst: Raw(dst, colored), @@ -334,6 +341,7 @@ impl EmitterWriter { short_message, teach, ui_testing: false, + terminal_width, } } @@ -1295,7 +1303,9 @@ impl EmitterWriter { width_offset + annotated_file.multiline_depth + 1 }; - let column_width = if self.ui_testing { + let column_width = if let Some(width) = self.terminal_width { + width + } else if self.ui_testing { 140 } else { term_size::dimensions().map(|(w, _)| w - code_offset).unwrap_or(140) diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 4018a667bf264..6585633e00af8 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -383,7 +383,7 @@ impl Handler { cm: Option>, flags: HandlerFlags) -> Handler { - let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false, false)); + let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false, false, None)); Handler::with_emitter_and_flags(emitter, flags) } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 87381f224d0bb..98362464771e0 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -193,6 +193,7 @@ pub fn new_handler(error_format: ErrorOutputType, source_map.map(|cm| cm as _), short, sessopts.debugging_opts.teach, + sessopts.debugging_opts.terminal_width, ).ui_testing(ui_testing) ) }, diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 83a8d3fc10999..8db0eb15929dc 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -427,7 +427,7 @@ pub fn make_test(s: &str, // Any errors in parsing should also appear when the doctest is compiled for real, so just // send all the errors that libsyntax emits directly into a `Sink` instead of stderr. let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let emitter = EmitterWriter::new(box io::sink(), None, false, false, false); + let emitter = EmitterWriter::new(box io::sink(), None, false, false, false, None); // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser let handler = Handler::with_emitter(false, None, box emitter); let sess = ParseSess::with_span_handler(handler, cm); diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 83c9c692bd30c..ada46f7bc5a74 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -219,7 +219,7 @@ impl Diagnostic { } let buf = BufWriter::default(); let output = buf.clone(); - je.json_rendered.new_emitter(Box::new(buf), Some(je.sm.clone()), false) + je.json_rendered.new_emitter(Box::new(buf), Some(je.sm.clone()), false, None) .ui_testing(je.ui_testing).emit_diagnostic(db); let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); let output = String::from_utf8(output).unwrap(); diff --git a/src/libsyntax/parse/lexer/tests.rs b/src/libsyntax/parse/lexer/tests.rs index a915aa42fd15a..963ad2c0b8f11 100644 --- a/src/libsyntax/parse/lexer/tests.rs +++ b/src/libsyntax/parse/lexer/tests.rs @@ -10,7 +10,14 @@ use errors::{Handler, emitter::EmitterWriter}; use syntax_pos::{BytePos, Span}; fn mk_sess(sm: Lrc) -> ParseSess { - let emitter = EmitterWriter::new(Box::new(io::sink()), Some(sm.clone()), false, false, false); + let emitter = errors::emitter::EmitterWriter::new( + Box::new(io::sink()), + Some(sm.clone()), + false, + false, + false, + None, + ); ParseSess::with_span_handler(Handler::with_emitter(true, None, Box::new(emitter)), sm) } diff --git a/src/libsyntax/tests.rs b/src/libsyntax/tests.rs index 4c0e1e3704dff..c472212bc2096 100644 --- a/src/libsyntax/tests.rs +++ b/src/libsyntax/tests.rs @@ -144,11 +144,14 @@ fn test_harness(file_text: &str, span_labels: Vec, expected_output: & println!("text: {:?}", source_map.span_to_snippet(span)); } - let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }), - Some(source_map.clone()), - false, - false, - false); + let emitter = EmitterWriter::new( + Box::new(Shared { data: output.clone() }), + Some(source_map.clone()), + false, + false, + false, + None, + ); let handler = Handler::with_emitter(true, None, Box::new(emitter)); handler.span_err(msp, "foo"); From cc2272fe879f662bc2623fe6d96b358ed011e382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 21 Aug 2019 12:00:36 -0700 Subject: [PATCH 101/618] Formatting --- src/libsyntax/parse/lexer/tests.rs | 69 +++++++++++++++++++----------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/src/libsyntax/parse/lexer/tests.rs b/src/libsyntax/parse/lexer/tests.rs index 963ad2c0b8f11..6faaa01321db5 100644 --- a/src/libsyntax/parse/lexer/tests.rs +++ b/src/libsyntax/parse/lexer/tests.rs @@ -35,10 +35,11 @@ fn t1() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - let mut string_reader = setup(&sm, - &sh, - "/* my source file */ fn main() { println!(\"zebra\"); }\n" - .to_string()); + let mut string_reader = setup( + &sm, + &sh, + "/* my source file */ fn main() { println!(\"zebra\"); }\n".to_string(), + ); assert_eq!(string_reader.next_token(), token::Comment); assert_eq!(string_reader.next_token(), token::Whitespace); let tok1 = string_reader.next_token(); @@ -134,8 +135,10 @@ fn character_a() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "'a'".to_string()).next_token(), - mk_lit(token::Char, "a", None)); + assert_eq!( + setup(&sm, &sh, "'a'".to_string()).next_token(), + mk_lit(token::Char, "a", None), + ); }) } @@ -144,8 +147,10 @@ fn character_space() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "' '".to_string()).next_token(), - mk_lit(token::Char, " ", None)); + assert_eq!( + setup(&sm, &sh, "' '".to_string()).next_token(), + mk_lit(token::Char, " ", None), + ); }) } @@ -154,8 +159,10 @@ fn character_escaped() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "'\\n'".to_string()).next_token(), - mk_lit(token::Char, "\\n", None)); + assert_eq!( + setup(&sm, &sh, "'\\n'".to_string()).next_token(), + mk_lit(token::Char, "\\n", None), + ); }) } @@ -164,8 +171,10 @@ fn lifetime_name() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "'abc".to_string()).next_token(), - token::Lifetime(Symbol::intern("'abc"))); + assert_eq!( + setup(&sm, &sh, "'abc".to_string()).next_token(), + token::Lifetime(Symbol::intern("'abc")), + ); }) } @@ -174,8 +183,10 @@ fn raw_string() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()).next_token(), - mk_lit(token::StrRaw(3), "\"#a\\b\x00c\"", None)); + assert_eq!( + setup(&sm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()).next_token(), + mk_lit(token::StrRaw(3), "\"#a\\b\x00c\"", None), + ); }) } @@ -186,11 +197,15 @@ fn literal_suffixes() { let sh = mk_sess(sm.clone()); macro_rules! test { ($input: expr, $tok_type: ident, $tok_contents: expr) => {{ - assert_eq!(setup(&sm, &sh, format!("{}suffix", $input)).next_token(), - mk_lit(token::$tok_type, $tok_contents, Some("suffix"))); + assert_eq!( + setup(&sm, &sh, format!("{}suffix", $input)).next_token(), + mk_lit(token::$tok_type, $tok_contents, Some("suffix")), + ); // with a whitespace separator: - assert_eq!(setup(&sm, &sh, format!("{} suffix", $input)).next_token(), - mk_lit(token::$tok_type, $tok_contents, None)); + assert_eq!( + setup(&sm, &sh, format!("{} suffix", $input)).next_token(), + mk_lit(token::$tok_type, $tok_contents, None), + ); }} } @@ -204,12 +219,18 @@ fn literal_suffixes() { test!("1.0", Float, "1.0"); test!("1.0e10", Float, "1.0e10"); - assert_eq!(setup(&sm, &sh, "2us".to_string()).next_token(), - mk_lit(token::Integer, "2", Some("us"))); - assert_eq!(setup(&sm, &sh, "r###\"raw\"###suffix".to_string()).next_token(), - mk_lit(token::StrRaw(3), "raw", Some("suffix"))); - assert_eq!(setup(&sm, &sh, "br###\"raw\"###suffix".to_string()).next_token(), - mk_lit(token::ByteStrRaw(3), "raw", Some("suffix"))); + assert_eq!( + setup(&sm, &sh, "2us".to_string()).next_token(), + mk_lit(token::Integer, "2", Some("us")), + ); + assert_eq!( + setup(&sm, &sh, "r###\"raw\"###suffix".to_string()).next_token(), + mk_lit(token::StrRaw(3), "raw", Some("suffix")), + ); + assert_eq!( + setup(&sm, &sh, "br###\"raw\"###suffix".to_string()).next_token(), + mk_lit(token::ByteStrRaw(3), "raw", Some("suffix")), + ); }) } From aaf4dc35e33eea8b658b82a307b81e63e8b214f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 21 Aug 2019 14:26:52 -0700 Subject: [PATCH 102/618] fix rebase --- src/libsyntax/parse/lexer/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/parse/lexer/tests.rs b/src/libsyntax/parse/lexer/tests.rs index 6faaa01321db5..652ae95c85349 100644 --- a/src/libsyntax/parse/lexer/tests.rs +++ b/src/libsyntax/parse/lexer/tests.rs @@ -10,7 +10,7 @@ use errors::{Handler, emitter::EmitterWriter}; use syntax_pos::{BytePos, Span}; fn mk_sess(sm: Lrc) -> ParseSess { - let emitter = errors::emitter::EmitterWriter::new( + let emitter = EmitterWriter::new( Box::new(io::sink()), Some(sm.clone()), false, From 1c829877824aeda82e78ed3a0ecb12a3cb0b2d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 21 Aug 2019 11:46:31 -0700 Subject: [PATCH 103/618] Fix typo in E0308 if/else label --- src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/ty/error.rs | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 84687b8cab5c0..9be73cf3c6d16 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1650,7 +1650,7 @@ impl<'tcx> ObligationCause<'tcx> { hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have compatible types", _ => "match arms have compatible types", }, - IfExpression { .. } => "if and else have compatible types", + IfExpression { .. } => "if and else have incompatible types", IfExpressionWithNoElse => "if missing an else returns ()", MainFunctionType => "`main` function has the correct type", StartFunctionType => "`start` function has the correct type", diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index d6d17a67e01e9..6daecd7ae941a 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -247,13 +247,15 @@ impl<'tcx> ty::TyS<'tcx> { } impl<'tcx> TyCtxt<'tcx> { - pub fn note_and_explain_type_err(self, - db: &mut DiagnosticBuilder<'_>, - err: &TypeError<'tcx>, - sp: Span) { + pub fn note_and_explain_type_err( + self, + db: &mut DiagnosticBuilder<'_>, + err: &TypeError<'tcx>, + sp: Span, + ) { use self::TypeError::*; - match err.clone() { + match err { Sorts(values) => { let expected_str = values.expected.sort_string(self); let found_str = values.found.sort_string(self); @@ -261,6 +263,15 @@ impl<'tcx> TyCtxt<'tcx> { db.note("no two closures, even if identical, have the same type"); db.help("consider boxing your closure and/or using it as a trait object"); } + if expected_str == found_str && expected_str == "opaque type" { // Issue #63167 + db.note("distinct uses of `impl Trait` result in different opaque types"); + let e_str = values.expected.to_string(); + let f_str = values.found.to_string(); + if &e_str == &f_str && &e_str == "impl std::future::Future" { + db.help("if both futures resolve to the same type, consider `await`ing \ + on both of them"); + } + } if let (ty::Infer(ty::IntVar(_)), ty::Float(_)) = (&values.found.sty, &values.expected.sty) // Issue #53280 { From ba8e09415b00fdfcda8feeb1cf233f2f065ef6c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 21 Aug 2019 11:49:51 -0700 Subject: [PATCH 104/618] Add clarification on E0308 about opaque types --- src/librustc/ty/error.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 6daecd7ae941a..c1593799286ef 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -268,6 +268,7 @@ impl<'tcx> TyCtxt<'tcx> { let e_str = values.expected.to_string(); let f_str = values.found.to_string(); if &e_str == &f_str && &e_str == "impl std::future::Future" { + // FIXME: use non-string based check. db.help("if both futures resolve to the same type, consider `await`ing \ on both of them"); } From 8c07d7814d2eb2cab14e5c57313e68880b60a14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 15 Aug 2019 18:58:20 -0700 Subject: [PATCH 105/618] When declaring a declarative macro in an item it's only accessible inside it --- src/librustc/hir/map/mod.rs | 13 +++--- src/librustc_privacy/lib.rs | 60 +++++++++++++++------------ src/test/ui/macros/macro-in-fn.rs | 9 ++++ src/test/ui/macros/macro-in-fn.stderr | 8 ++++ 4 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/macros/macro-in-fn.rs create mode 100644 src/test/ui/macros/macro-in-fn.stderr diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 7292428ec378c..5bf310ce8d956 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -514,8 +514,11 @@ impl<'hir> Map<'hir> { &self.forest.krate.attrs } - pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId) - { + pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId) { + self.get_if_module(module).expect("not a module") + } + + pub fn get_if_module(&self, module: DefId) -> Option<(&'hir Mod, Span, HirId)> { let hir_id = self.as_local_hir_id(module).unwrap(); self.read(hir_id); match self.find_entry(hir_id).unwrap().node { @@ -523,9 +526,9 @@ impl<'hir> Map<'hir> { span, node: ItemKind::Mod(ref m), .. - }) => (m, span, hir_id), - Node::Crate => (&self.forest.krate.module, self.forest.krate.span, hir_id), - _ => panic!("not a module") + }) => Some((m, span, hir_id)), + Node::Crate => Some((&self.forest.krate.module, self.forest.krate.span, hir_id)), + _ => None, } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index bca77621e553e..dc787d2253884 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -508,39 +508,45 @@ impl EmbargoVisitor<'tcx> { } } - fn update_macro_reachable_mod( - &mut self, - reachable_mod: hir::HirId, - defining_mod: DefId, - ) { - let module_def_id = self.tcx.hir().local_def_id(reachable_mod); - let module = self.tcx.hir().get_module(module_def_id).0; - for item_id in &module.item_ids { - let hir_id = item_id.id; - let item_def_id = self.tcx.hir().local_def_id(hir_id); - if let Some(def_kind) = self.tcx.def_kind(item_def_id) { - let item = self.tcx.hir().expect_item(hir_id); - let vis = ty::Visibility::from_hir(&item.vis, hir_id, self.tcx); - self.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod); + fn update_macro_reachable_mod(&mut self, reachable_mod: hir::HirId, defining_mod: DefId) { + let set_vis = |this: &mut Self, hir_id: hir::HirId| { + let item_def_id = this.tcx.hir().local_def_id(hir_id); + if let Some(def_kind) = this.tcx.def_kind(item_def_id) { + let item = this.tcx.hir().expect_item(hir_id); + let vis = ty::Visibility::from_hir(&item.vis, hir_id, this.tcx); + this.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod); } - } + }; - if let Some(exports) = self.tcx.module_exports(module_def_id) { - for export in exports { - if export.vis.is_accessible_from(defining_mod, self.tcx) { - if let Res::Def(def_kind, def_id) = export.res { - let vis = def_id_visibility(self.tcx, def_id).0; - if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) { - self.update_macro_reachable_def( - hir_id, - def_kind, - vis, - defining_mod, - ); + let module_def_id = self.tcx.hir().local_def_id(reachable_mod); + if let Some((module, _, _)) = self.tcx.hir().get_if_module(module_def_id) { + for item_id in &module.item_ids { + let hir_id = item_id.id; + set_vis(self, hir_id); + } + if let Some(exports) = self.tcx.module_exports(module_def_id) { + for export in exports { + if export.vis.is_accessible_from(defining_mod, self.tcx) { + if let Res::Def(def_kind, def_id) = export.res { + let vis = def_id_visibility(self.tcx, def_id).0; + if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) { + self.update_macro_reachable_def( + hir_id, + def_kind, + vis, + defining_mod, + ); + } } } } } + } else if let Some(hir::Node::Item(hir::Item { + hir_id, + .. + })) = self.tcx.hir().get_if_local(module_def_id) { // #63164 + // `macro` defined inside of an item is only visible inside of that item's scope. + set_vis(self, *hir_id); } } diff --git a/src/test/ui/macros/macro-in-fn.rs b/src/test/ui/macros/macro-in-fn.rs new file mode 100644 index 0000000000000..1e46346fc01ea --- /dev/null +++ b/src/test/ui/macros/macro-in-fn.rs @@ -0,0 +1,9 @@ +#![feature(decl_macro)] + +pub fn moo() { + pub macro ABC() {{}} +} + +fn main() { + ABC!(); //~ ERROR cannot find macro `ABC!` in this scope +} diff --git a/src/test/ui/macros/macro-in-fn.stderr b/src/test/ui/macros/macro-in-fn.stderr new file mode 100644 index 0000000000000..0c35fe65aa285 --- /dev/null +++ b/src/test/ui/macros/macro-in-fn.stderr @@ -0,0 +1,8 @@ +error: cannot find macro `ABC!` in this scope + --> $DIR/macro-in-fn.rs:8:5 + | +LL | ABC!(); + | ^^^ + +error: aborting due to previous error + From 4971667f175e7e3d84b7a87f46633b3e069e48ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 21 Aug 2019 16:11:01 -0700 Subject: [PATCH 106/618] review comments --- src/librustc/hir/map/mod.rs | 20 ++++++---- src/librustc_privacy/lib.rs | 54 +++++++++++---------------- src/test/ui/macros/macro-in-fn.rs | 5 +-- src/test/ui/macros/macro-in-fn.stderr | 8 ---- 4 files changed, 36 insertions(+), 51 deletions(-) delete mode 100644 src/test/ui/macros/macro-in-fn.stderr diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 5bf310ce8d956..f80e527dfd9b7 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -515,10 +515,6 @@ impl<'hir> Map<'hir> { } pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId) { - self.get_if_module(module).expect("not a module") - } - - pub fn get_if_module(&self, module: DefId) -> Option<(&'hir Mod, Span, HirId)> { let hir_id = self.as_local_hir_id(module).unwrap(); self.read(hir_id); match self.find_entry(hir_id).unwrap().node { @@ -526,9 +522,9 @@ impl<'hir> Map<'hir> { span, node: ItemKind::Mod(ref m), .. - }) => Some((m, span, hir_id)), - Node::Crate => Some((&self.forest.krate.module, self.forest.krate.span, hir_id)), - _ => None, + }) => (m, span, hir_id), + Node::Crate => (&self.forest.krate.module, self.forest.krate.span, hir_id), + node => panic!("not a module: {:?}", node), } } @@ -682,6 +678,16 @@ impl<'hir> Map<'hir> { } } + /// Wether `hir_id` corresponds to a `mod` or a crate. + pub fn is_hir_id_module(&self, hir_id: HirId) -> bool { + match self.lookup(hir_id) { + Some(Entry { node: Node::Item(Item { node: ItemKind::Mod(_), .. }), .. }) | + Some(Entry { node: Node::Crate, .. }) => true, + _ => false, + } + } + + /// If there is some error when walking the parents (e.g., a node does not /// have a parent in the map or a node can't be found), then we return the /// last good `HirId` we found. Note that reaching the crate root (`id == 0`), diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index dc787d2253884..146058963b69d 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -509,44 +509,28 @@ impl EmbargoVisitor<'tcx> { } fn update_macro_reachable_mod(&mut self, reachable_mod: hir::HirId, defining_mod: DefId) { - let set_vis = |this: &mut Self, hir_id: hir::HirId| { - let item_def_id = this.tcx.hir().local_def_id(hir_id); - if let Some(def_kind) = this.tcx.def_kind(item_def_id) { - let item = this.tcx.hir().expect_item(hir_id); - let vis = ty::Visibility::from_hir(&item.vis, hir_id, this.tcx); - this.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod); - } - }; - let module_def_id = self.tcx.hir().local_def_id(reachable_mod); - if let Some((module, _, _)) = self.tcx.hir().get_if_module(module_def_id) { - for item_id in &module.item_ids { - let hir_id = item_id.id; - set_vis(self, hir_id); + let module = self.tcx.hir().get_module(module_def_id).0; + for item_id in &module.item_ids { + let hir_id = item_id.id; + let item_def_id = self.tcx.hir().local_def_id(hir_id); + if let Some(def_kind) = self.tcx.def_kind(item_def_id) { + let item = self.tcx.hir().expect_item(hir_id); + let vis = ty::Visibility::from_hir(&item.vis, hir_id, self.tcx); + self.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod); } - if let Some(exports) = self.tcx.module_exports(module_def_id) { - for export in exports { - if export.vis.is_accessible_from(defining_mod, self.tcx) { - if let Res::Def(def_kind, def_id) = export.res { - let vis = def_id_visibility(self.tcx, def_id).0; - if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) { - self.update_macro_reachable_def( - hir_id, - def_kind, - vis, - defining_mod, - ); - } + } + if let Some(exports) = self.tcx.module_exports(module_def_id) { + for export in exports { + if export.vis.is_accessible_from(defining_mod, self.tcx) { + if let Res::Def(def_kind, def_id) = export.res { + let vis = def_id_visibility(self.tcx, def_id).0; + if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) { + self.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod); } } } } - } else if let Some(hir::Node::Item(hir::Item { - hir_id, - .. - })) = self.tcx.hir().get_if_local(module_def_id) { // #63164 - // `macro` defined inside of an item is only visible inside of that item's scope. - set_vis(self, *hir_id); } } @@ -898,10 +882,14 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { self.tcx.hir().local_def_id(md.hir_id) ).unwrap(); let mut module_id = self.tcx.hir().as_local_hir_id(macro_module_def_id).unwrap(); + if !self.tcx.hir().is_hir_id_module(module_id) { + // `module_id` doesn't correspond to a `mod`, return early (#63164). + return; + } let level = if md.vis.node.is_pub() { self.get(module_id) } else { None }; let new_level = self.update(md.hir_id, level); if new_level.is_none() { - return + return; } loop { diff --git a/src/test/ui/macros/macro-in-fn.rs b/src/test/ui/macros/macro-in-fn.rs index 1e46346fc01ea..d354fe4a7dbfa 100644 --- a/src/test/ui/macros/macro-in-fn.rs +++ b/src/test/ui/macros/macro-in-fn.rs @@ -1,9 +1,8 @@ +// run-pass #![feature(decl_macro)] pub fn moo() { pub macro ABC() {{}} } -fn main() { - ABC!(); //~ ERROR cannot find macro `ABC!` in this scope -} +fn main() {} diff --git a/src/test/ui/macros/macro-in-fn.stderr b/src/test/ui/macros/macro-in-fn.stderr deleted file mode 100644 index 0c35fe65aa285..0000000000000 --- a/src/test/ui/macros/macro-in-fn.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: cannot find macro `ABC!` in this scope - --> $DIR/macro-in-fn.rs:8:5 - | -LL | ABC!(); - | ^^^ - -error: aborting due to previous error - From 053afa7aec67d0bc8dc23e8217d77846ca9fc3ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 5 Aug 2019 19:23:46 -0700 Subject: [PATCH 107/618] Do not complain about unused code when used in `impl` `Self` type --- src/librustc/middle/dead.rs | 26 ++++++++++---- src/test/ui/derive-uninhabited-enum-38885.rs | 11 +++--- .../ui/derive-uninhabited-enum-38885.stderr | 14 +++----- .../ui/lint/lint-dead-code-const-and-self.rs | 35 +++++++++++++++++++ 4 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/lint/lint-dead-code-const-and-self.rs diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 8ce8bb52566c6..d4805a7c78322 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -30,10 +30,11 @@ fn should_explore(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { Some(Node::Item(..)) | Some(Node::ImplItem(..)) | Some(Node::ForeignItem(..)) | - Some(Node::TraitItem(..)) => - true, - _ => - false + Some(Node::TraitItem(..)) | + Some(Node::Variant(..)) | + Some(Node::AnonConst(..)) | + Some(Node::Pat(..)) => true, + _ => false } } @@ -75,7 +76,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { self.check_def_id(res.def_id()); } _ if self.in_pat => {}, - Res::PrimTy(..) | Res::SelfTy(..) | Res::SelfCtor(..) | + Res::PrimTy(..) | Res::SelfCtor(..) | Res::Local(..) => {} Res::Def(DefKind::Ctor(CtorOf::Variant, ..), ctor_def_id) => { let variant_id = self.tcx.parent(ctor_def_id).unwrap(); @@ -92,6 +93,14 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { self.check_def_id(variant_id); } } + Res::SelfTy(t, i) => { + if let Some(t) = t { + self.check_def_id(t); + } + if let Some(i) = i { + self.check_def_id(i); + } + } Res::ToolMod | Res::NonMacroAttr(..) | Res::Err => {} _ => { self.check_def_id(res.def_id()); @@ -271,7 +280,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { let res = self.tables.qpath_res(path, pat.hir_id); self.handle_field_pattern_match(pat, res, fields); } - PatKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => { + PatKind::Path(ref qpath) => { let res = self.tables.qpath_res(qpath, pat.hir_id); self.handle_res(res); } @@ -298,6 +307,11 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { } intravisit::walk_ty(self, ty); } + + fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { + self.live_symbols.insert(c.hir_id); + intravisit::walk_anon_const(self, c); + } } fn has_allow_dead_code_or_lang_attr( diff --git a/src/test/ui/derive-uninhabited-enum-38885.rs b/src/test/ui/derive-uninhabited-enum-38885.rs index 2c4d64e4e6063..010464adf5bce 100644 --- a/src/test/ui/derive-uninhabited-enum-38885.rs +++ b/src/test/ui/derive-uninhabited-enum-38885.rs @@ -5,12 +5,15 @@ // when deriving Debug on an empty enum #[derive(Debug)] -enum Void {} //~ WARN never used +enum Void {} #[derive(Debug)] -enum Foo { //~ WARN never used +enum Foo { Bar(u8), - Void(Void), + Void(Void), //~ WARN never used } -fn main() {} +fn main() { + let x = Foo::Bar(42); + println!("{:?}", x); +} diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr index 941c98b5506b2..a3ed6798a7039 100644 --- a/src/test/ui/derive-uninhabited-enum-38885.stderr +++ b/src/test/ui/derive-uninhabited-enum-38885.stderr @@ -1,14 +1,8 @@ -warning: enum is never used: `Void` - --> $DIR/derive-uninhabited-enum-38885.rs:8:1 +warning: variant is never constructed: `Void` + --> $DIR/derive-uninhabited-enum-38885.rs:13:5 | -LL | enum Void {} - | ^^^^^^^^^ +LL | Void(Void), + | ^^^^^^^^^^ | = note: `-W dead-code` implied by `-W unused` -warning: enum is never used: `Foo` - --> $DIR/derive-uninhabited-enum-38885.rs:11:1 - | -LL | enum Foo { - | ^^^^^^^^ - diff --git a/src/test/ui/lint/lint-dead-code-const-and-self.rs b/src/test/ui/lint/lint-dead-code-const-and-self.rs new file mode 100644 index 0000000000000..1a7b3f43cda14 --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-const-and-self.rs @@ -0,0 +1,35 @@ +// check-pass + +#![deny(dead_code)] + +const TLC: usize = 4; + +trait Tr { fn doit(&self); } + +impl Tr for [usize; TLC] { + fn doit(&self) { + println!("called 4"); + } +} + +struct X; +struct Y; +struct Z; + +trait Foo { + type Ty; + fn foo() -> Self::Ty; +} + +impl Foo for X { + type Ty = Z; + fn foo() -> Self::Ty { + unimplemented!() + } +} + +fn main() { + let s = [0,1,2,3]; + s.doit(); + X::foo(); +} From 352d97e6b7a3ddfd1f4de1d592fcf95d8a507f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 21 Aug 2019 16:30:11 -0700 Subject: [PATCH 108/618] Add more tests covering more cases --- .../lint-dead-code-empty-unused-enum-pub.rs | 6 +++++ .../lint/lint-dead-code-empty-unused-enum.rs | 5 ++++ .../lint-dead-code-empty-unused-enum.stderr | 15 +++++++++++ .../ui/lint/lint-dead-code-unused-enum.rs | 11 ++++++++ .../ui/lint/lint-dead-code-unused-enum.stderr | 27 +++++++++++++++++++ .../lint/lint-dead-code-unused-variant-pub.rs | 14 ++++++++++ .../ui/lint/lint-dead-code-unused-variant.rs | 13 +++++++++ .../lint/lint-dead-code-unused-variant.stderr | 15 +++++++++++ 8 files changed, 106 insertions(+) create mode 100644 src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs create mode 100644 src/test/ui/lint/lint-dead-code-empty-unused-enum.rs create mode 100644 src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr create mode 100644 src/test/ui/lint/lint-dead-code-unused-enum.rs create mode 100644 src/test/ui/lint/lint-dead-code-unused-enum.stderr create mode 100644 src/test/ui/lint/lint-dead-code-unused-variant-pub.rs create mode 100644 src/test/ui/lint/lint-dead-code-unused-variant.rs create mode 100644 src/test/ui/lint/lint-dead-code-unused-variant.stderr diff --git a/src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs b/src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs new file mode 100644 index 0000000000000..2b06fcb69ceee --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs @@ -0,0 +1,6 @@ +// run-pass +#![deny(unused)] + +pub enum E {} + +fn main() {} diff --git a/src/test/ui/lint/lint-dead-code-empty-unused-enum.rs b/src/test/ui/lint/lint-dead-code-empty-unused-enum.rs new file mode 100644 index 0000000000000..834681d77e613 --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-empty-unused-enum.rs @@ -0,0 +1,5 @@ +#![deny(unused)] + +enum E {} //~ ERROR enum is never used + +fn main() {} diff --git a/src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr b/src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr new file mode 100644 index 0000000000000..4e3bebfc48bde --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr @@ -0,0 +1,15 @@ +error: enum is never used: `E` + --> $DIR/lint-dead-code-empty-unused-enum.rs:3:1 + | +LL | enum E {} + | ^^^^^^ + | +note: lint level defined here + --> $DIR/lint-dead-code-empty-unused-enum.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-dead-code-unused-enum.rs b/src/test/ui/lint/lint-dead-code-unused-enum.rs new file mode 100644 index 0000000000000..e57fac259c5d5 --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-unused-enum.rs @@ -0,0 +1,11 @@ +#![deny(unused)] + +struct F; //~ ERROR struct is never constructed +struct B; //~ ERROR struct is never constructed + +enum E { //~ ERROR enum is never used + Foo(F), + Bar(B), +} + +fn main() {} diff --git a/src/test/ui/lint/lint-dead-code-unused-enum.stderr b/src/test/ui/lint/lint-dead-code-unused-enum.stderr new file mode 100644 index 0000000000000..ea711e7b05ee6 --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-unused-enum.stderr @@ -0,0 +1,27 @@ +error: struct is never constructed: `F` + --> $DIR/lint-dead-code-unused-enum.rs:3:1 + | +LL | struct F; + | ^^^^^^^^^ + | +note: lint level defined here + --> $DIR/lint-dead-code-unused-enum.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: struct is never constructed: `B` + --> $DIR/lint-dead-code-unused-enum.rs:4:1 + | +LL | struct B; + | ^^^^^^^^^ + +error: enum is never used: `E` + --> $DIR/lint-dead-code-unused-enum.rs:6:1 + | +LL | enum E { + | ^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/lint/lint-dead-code-unused-variant-pub.rs b/src/test/ui/lint/lint-dead-code-unused-variant-pub.rs new file mode 100644 index 0000000000000..918300ba79354 --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-unused-variant-pub.rs @@ -0,0 +1,14 @@ +// run-pass +#![deny(unused)] + +pub struct F; +pub struct B; + +pub enum E { + Foo(F), + Bar(B), +} + +fn main() { + let _ = E::Foo(F); +} diff --git a/src/test/ui/lint/lint-dead-code-unused-variant.rs b/src/test/ui/lint/lint-dead-code-unused-variant.rs new file mode 100644 index 0000000000000..69ab29042e5a4 --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-unused-variant.rs @@ -0,0 +1,13 @@ +#![deny(unused)] + +struct F; +struct B; + +enum E { + Foo(F), + Bar(B), //~ ERROR variant is never constructed +} + +fn main() { + let _ = E::Foo(F); +} diff --git a/src/test/ui/lint/lint-dead-code-unused-variant.stderr b/src/test/ui/lint/lint-dead-code-unused-variant.stderr new file mode 100644 index 0000000000000..919996ec30020 --- /dev/null +++ b/src/test/ui/lint/lint-dead-code-unused-variant.stderr @@ -0,0 +1,15 @@ +error: variant is never constructed: `Bar` + --> $DIR/lint-dead-code-unused-variant.rs:8:5 + | +LL | Bar(B), + | ^^^^^^ + | +note: lint level defined here + --> $DIR/lint-dead-code-unused-variant.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: aborting due to previous error + From a710c610b2ea1550014e9f6bd20e5e4aed8a716c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 21 Aug 2019 15:35:38 -0700 Subject: [PATCH 109/618] review comments: reword and add test --- src/librustc/ty/error.rs | 4 ++-- src/test/ui/suggestions/opaque-type-error.rs | 24 +++++++++++++++++++ .../ui/suggestions/opaque-type-error.stderr | 20 ++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/suggestions/opaque-type-error.rs create mode 100644 src/test/ui/suggestions/opaque-type-error.stderr diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index c1593799286ef..c70006b68d69a 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -269,8 +269,8 @@ impl<'tcx> TyCtxt<'tcx> { let f_str = values.found.to_string(); if &e_str == &f_str && &e_str == "impl std::future::Future" { // FIXME: use non-string based check. - db.help("if both futures resolve to the same type, consider `await`ing \ - on both of them"); + db.help("if both `Future`s have the same `Output` type, consider \ + `.await`ing on both of them"); } } if let (ty::Infer(ty::IntVar(_)), ty::Float(_)) = diff --git a/src/test/ui/suggestions/opaque-type-error.rs b/src/test/ui/suggestions/opaque-type-error.rs new file mode 100644 index 0000000000000..979bb60d48c12 --- /dev/null +++ b/src/test/ui/suggestions/opaque-type-error.rs @@ -0,0 +1,24 @@ +// edition:2018 +use core::future::Future; + +async fn base_thing() -> Result<(), ()> { + Ok(()) +} + +fn thing_one() -> impl Future> { + base_thing() +} + +fn thing_two() -> impl Future> { + base_thing() +} + +async fn thing() -> Result<(), ()> { + if true { + thing_one() + } else { + thing_two() //~ ERROR if and else have incompatible types + }.await +} + +fn main() {} diff --git a/src/test/ui/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr new file mode 100644 index 0000000000000..3c9ea05aeceb2 --- /dev/null +++ b/src/test/ui/suggestions/opaque-type-error.stderr @@ -0,0 +1,20 @@ +error[E0308]: if and else have incompatible types + --> $DIR/opaque-type-error.rs:20:9 + | +LL | / if true { +LL | | thing_one() + | | ----------- expected because of this +LL | | } else { +LL | | thing_two() + | | ^^^^^^^^^^^ expected opaque type, found a different opaque type +LL | | }.await + | |_____- if and else have incompatible types + | + = note: expected type `impl std::future::Future` (opaque type) + found type `impl std::future::Future` (opaque type) + = note: distinct uses of `impl Trait` result in different opaque types + = help: if both `Future`s have the same `Output` type, consider `.await`ing on both of them + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 4f613ffeb000642ef2f7f3c2e3f25b5bd1938b5a Mon Sep 17 00:00:00 2001 From: YangHau Date: Tue, 20 Aug 2019 19:46:23 +0800 Subject: [PATCH 110/618] Fix naming misspelling --- ...terger-atomic.rs => non-integer-atomic.rs} | 0 ...tomic.stderr => non-integer-atomic.stderr} | 32 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) rename src/test/ui/{non-interger-atomic.rs => non-integer-atomic.rs} (100%) rename src/test/ui/{non-interger-atomic.stderr => non-integer-atomic.stderr} (83%) diff --git a/src/test/ui/non-interger-atomic.rs b/src/test/ui/non-integer-atomic.rs similarity index 100% rename from src/test/ui/non-interger-atomic.rs rename to src/test/ui/non-integer-atomic.rs diff --git a/src/test/ui/non-interger-atomic.stderr b/src/test/ui/non-integer-atomic.stderr similarity index 83% rename from src/test/ui/non-interger-atomic.stderr rename to src/test/ui/non-integer-atomic.stderr index 7d1130d238e2c..b3cf788d834d8 100644 --- a/src/test/ui/non-interger-atomic.stderr +++ b/src/test/ui/non-integer-atomic.stderr @@ -1,95 +1,95 @@ error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `bool` - --> $DIR/non-interger-atomic.rs:13:5 + --> $DIR/non-integer-atomic.rs:13:5 | LL | intrinsics::atomic_load(p); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `bool` - --> $DIR/non-interger-atomic.rs:18:5 + --> $DIR/non-integer-atomic.rs:18:5 | LL | intrinsics::atomic_store(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `bool` - --> $DIR/non-interger-atomic.rs:23:5 + --> $DIR/non-integer-atomic.rs:23:5 | LL | intrinsics::atomic_xchg(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `bool` - --> $DIR/non-interger-atomic.rs:28:5 + --> $DIR/non-integer-atomic.rs:28:5 | LL | intrinsics::atomic_cxchg(p, v, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `Foo` - --> $DIR/non-interger-atomic.rs:33:5 + --> $DIR/non-integer-atomic.rs:33:5 | LL | intrinsics::atomic_load(p); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `Foo` - --> $DIR/non-interger-atomic.rs:38:5 + --> $DIR/non-integer-atomic.rs:38:5 | LL | intrinsics::atomic_store(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `Foo` - --> $DIR/non-interger-atomic.rs:43:5 + --> $DIR/non-integer-atomic.rs:43:5 | LL | intrinsics::atomic_xchg(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `Foo` - --> $DIR/non-interger-atomic.rs:48:5 + --> $DIR/non-integer-atomic.rs:48:5 | LL | intrinsics::atomic_cxchg(p, v, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()` - --> $DIR/non-interger-atomic.rs:53:5 + --> $DIR/non-integer-atomic.rs:53:5 | LL | intrinsics::atomic_load(p); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()` - --> $DIR/non-interger-atomic.rs:58:5 + --> $DIR/non-integer-atomic.rs:58:5 | LL | intrinsics::atomic_store(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()` - --> $DIR/non-interger-atomic.rs:63:5 + --> $DIR/non-integer-atomic.rs:63:5 | LL | intrinsics::atomic_xchg(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()` - --> $DIR/non-interger-atomic.rs:68:5 + --> $DIR/non-integer-atomic.rs:68:5 | LL | intrinsics::atomic_cxchg(p, v, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]` - --> $DIR/non-interger-atomic.rs:73:5 + --> $DIR/non-integer-atomic.rs:73:5 | LL | intrinsics::atomic_load(p); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]` - --> $DIR/non-interger-atomic.rs:78:5 + --> $DIR/non-integer-atomic.rs:78:5 | LL | intrinsics::atomic_store(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]` - --> $DIR/non-interger-atomic.rs:83:5 + --> $DIR/non-integer-atomic.rs:83:5 | LL | intrinsics::atomic_xchg(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]` - --> $DIR/non-interger-atomic.rs:88:5 + --> $DIR/non-integer-atomic.rs:88:5 | LL | intrinsics::atomic_cxchg(p, v, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 6ce242fb6e46bad46c64ae662091e18594521a4b Mon Sep 17 00:00:00 2001 From: Jeremy Stucki Date: Thu, 22 Aug 2019 10:06:25 +0200 Subject: [PATCH 111/618] Update .mailmap --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index c5ecfb54fca52..98902a7212099 100644 --- a/.mailmap +++ b/.mailmap @@ -117,6 +117,7 @@ Jason Toffaletti Jason Toffaletti Jauhien Piatlicki Jauhien Piatlicki Jay True Jeremy Letang +Jeremy Stucki Jethro Beekman Jihyun Yu Jihyun Yu jihyun From b7ad3f9fc4b293fd5ada4b975910be26105e5847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Thu, 22 Aug 2019 11:44:57 +0200 Subject: [PATCH 112/618] Apply clippy::redundant_field_names suggestion --- src/build_helper/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index a1aa18922b5c5..131d2034675e3 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -262,7 +262,7 @@ pub fn native_lib_boilerplate( if !up_to_date(Path::new("build.rs"), ×tamp) || !up_to_date(src_dir, ×tamp) { Ok(NativeLibBoilerplate { src_dir: src_dir.to_path_buf(), - out_dir: out_dir, + out_dir, }) } else { Err(()) From 7f4aba40fcdc00c41438a77d202276eaf5b58a8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Thu, 22 Aug 2019 11:47:36 +0200 Subject: [PATCH 113/618] Apply clippy::needless_return suggestions --- src/libcore/iter/adapters/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index a63434abd6c9f..f50781890ab22 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -1309,7 +1309,7 @@ impl DoubleEndedIterator for Peekable where I: DoubleEndedIterator { Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { match self.peeked.take() { - Some(None) => return Try::from_ok(init), + Some(None) => Try::from_ok(init), Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() { Ok(acc) => f(acc, v), Err(e) => { @@ -1326,7 +1326,7 @@ impl DoubleEndedIterator for Peekable where I: DoubleEndedIterator { where Fold: FnMut(Acc, Self::Item) -> Acc, { match self.peeked { - Some(None) => return init, + Some(None) => init, Some(Some(v)) => { let acc = self.iter.rfold(init, &mut fold); fold(acc, v) From edabcddf4dbcc70228ac1db03b10df60decaf83a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Thu, 22 Aug 2019 11:51:59 +0200 Subject: [PATCH 114/618] Apply clippy::let_and_return suggestion --- src/libcore/slice/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index bfbbb15c8d488..931768564ca3c 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3026,8 +3026,7 @@ macro_rules! len { if size == 0 { // This _cannot_ use `unchecked_sub` because we depend on wrapping // to represent the length of long ZST slice iterators. - let diff = ($self.end as usize).wrapping_sub(start as usize); - diff + ($self.end as usize).wrapping_sub(start as usize) } else { // We know that `start <= end`, so can do better than `offset_from`, // which needs to deal in signed. By setting appropriate flags here From 666180c3242169fa40ec462617e96ebf831fc62d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 4 Aug 2019 16:20:00 -0400 Subject: [PATCH 115/618] Move 'tcx lifetime on MirPass --- src/librustc_mir/transform/add_call_guards.rs | 4 ++-- src/librustc_mir/transform/add_moves_for_packed_drops.rs | 4 ++-- src/librustc_mir/transform/add_retag.rs | 4 ++-- src/librustc_mir/transform/cleanup_post_borrowck.rs | 4 ++-- src/librustc_mir/transform/const_prop.rs | 4 ++-- src/librustc_mir/transform/copy_prop.rs | 4 ++-- src/librustc_mir/transform/deaggregator.rs | 4 ++-- src/librustc_mir/transform/dump_mir.rs | 4 ++-- src/librustc_mir/transform/elaborate_drops.rs | 4 ++-- src/librustc_mir/transform/erase_regions.rs | 4 ++-- src/librustc_mir/transform/generator.rs | 4 ++-- src/librustc_mir/transform/inline.rs | 4 ++-- src/librustc_mir/transform/instcombine.rs | 4 ++-- src/librustc_mir/transform/mod.rs | 8 ++++---- src/librustc_mir/transform/no_landing_pads.rs | 4 ++-- src/librustc_mir/transform/qualify_consts.rs | 4 ++-- src/librustc_mir/transform/remove_noop_landing_pads.rs | 4 ++-- src/librustc_mir/transform/rustc_peek.rs | 4 ++-- src/librustc_mir/transform/simplify.rs | 8 ++++---- src/librustc_mir/transform/simplify_branches.rs | 4 ++-- src/librustc_mir/transform/uniform_array_move_out.rs | 8 ++++---- 21 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index c08c33bc6ff8b..15ecc6c37920b 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -30,8 +30,8 @@ pub use self::AddCallGuards::*; * */ -impl MirPass for AddCallGuards { - fn run_pass<'tcx>(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for AddCallGuards { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { self.add_call_guards(body); } } diff --git a/src/librustc_mir/transform/add_moves_for_packed_drops.rs b/src/librustc_mir/transform/add_moves_for_packed_drops.rs index 426e16698d74d..052631ddff371 100644 --- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs +++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs @@ -39,8 +39,8 @@ use crate::util; pub struct AddMovesForPackedDrops; -impl MirPass for AddMovesForPackedDrops { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { debug!("add_moves_for_packed_drops({:?} @ {:?})", src, body.span); add_moves_for_packed_drops(tcx, body, src.def_id()); } diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index 524a19e3434f3..0fd75cd57b2ac 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -65,8 +65,8 @@ fn may_be_reference<'tcx>(ty: Ty<'tcx>) -> bool { } } -impl MirPass for AddRetag { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for AddRetag { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { if !tcx.sess.opts.debugging_opts.mir_emit_retag { return; } diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index 6ee14160bbd1b..ede1cb62f9451 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -26,8 +26,8 @@ pub struct CleanupNonCodegenStatements; pub struct DeleteNonCodegenStatements; -impl MirPass for CleanupNonCodegenStatements { - fn run_pass<'tcx>(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut delete = DeleteNonCodegenStatements; delete.visit_body(body); } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 98d8ca58ee164..ac442a496e535 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -33,8 +33,8 @@ use crate::transform::{MirPass, MirSource}; pub struct ConstProp; -impl MirPass for ConstProp { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for ConstProp { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { // will be evaluated by miri and produce its errors there if source.promoted.is_some() { return; diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index 7c9eeb5a57741..f3a523a813413 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -29,8 +29,8 @@ use crate::util::def_use::DefUseAnalysis; pub struct CopyPropagation; -impl MirPass for CopyPropagation { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for CopyPropagation { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { // We only run when the MIR optimization level is > 1. // This avoids a slow pass, and messing up debug info. if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 { diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index 1b42a0dffb894..1fc7ce09aa647 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -5,8 +5,8 @@ use crate::util::expand_aggregate; pub struct Deaggregator; -impl MirPass for Deaggregator { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for Deaggregator { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); let local_decls = &*local_decls; for bb in basic_blocks { diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index a6fb555f20bd0..ed0eff943a165 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -13,12 +13,12 @@ use crate::util as mir_util; pub struct Marker(pub &'static str); -impl MirPass for Marker { +impl<'tcx> MirPass<'tcx> for Marker { fn name(&self) -> Cow<'_, str> { Cow::Borrowed(self.0) } - fn run_pass<'tcx>(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut Body<'tcx>) { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut Body<'tcx>) { } } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 4480d1e0a05b8..7a5c00c859629 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -20,8 +20,8 @@ use syntax_pos::Span; pub struct ElaborateDrops; -impl MirPass for ElaborateDrops { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for ElaborateDrops { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", src, body.span); let def_id = src.def_id(); diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 5a29ea21a7a04..21ca339eb968b 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -49,8 +49,8 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { pub struct EraseRegions; -impl MirPass for EraseRegions { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for EraseRegions { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { EraseRegionsVisitor::new(tcx).visit_body(body); } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index f694188024031..d87331195dd24 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -1115,8 +1115,8 @@ where }).collect() } -impl MirPass for StateTransform { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for StateTransform { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { let yield_ty = if let Some(yield_ty) = body.yield_ty { yield_ty } else { diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index bc7bd39be488e..57aac2b0eac99 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -37,8 +37,8 @@ struct CallSite<'tcx> { location: SourceInfo, } -impl MirPass for Inline { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for Inline { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { Inliner { tcx, source }.run_pass(body); } diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index b2d063a1f4e10..abe41606e8079 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -11,8 +11,8 @@ use crate::transform::{MirPass, MirSource}; pub struct InstCombine; -impl MirPass for InstCombine { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for InstCombine { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { // We only run when optimizing MIR (at any level). if tcx.sess.opts.debugging_opts.mir_opt_level == 0 { return diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 61d0b1f3485b6..255635b933385 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -137,12 +137,12 @@ pub fn default_name() -> Cow<'static, str> { /// A streamlined trait that you can implement to create a pass; the /// pass will be named after the type, and it will consist of a main /// loop that goes over each available MIR and applies `run_pass`. -pub trait MirPass { +pub trait MirPass<'tcx> { fn name(&self) -> Cow<'_, str> { default_name::() } - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>); + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>); } pub fn run_passes( @@ -150,7 +150,7 @@ pub fn run_passes( body: &mut Body<'tcx>, instance: InstanceDef<'tcx>, mir_phase: MirPhase, - passes: &[&dyn MirPass], + passes: &[&dyn MirPass<'tcx>], ) { let phase_index = mir_phase.phase_index(); @@ -164,7 +164,7 @@ pub fn run_passes( promoted, }; let mut index = 0; - let mut run_pass = |pass: &dyn MirPass| { + let mut run_pass = |pass: &dyn MirPass<'tcx>| { let run_hooks = |body: &_, index, is_after| { dump_mir::on_mir_pass(tcx, &format_args!("{:03}-{:03}", phase_index, index), &pass.name(), source, body, is_after); diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs index 841db80fc7dbb..762bb5d44839f 100644 --- a/src/librustc_mir/transform/no_landing_pads.rs +++ b/src/librustc_mir/transform/no_landing_pads.rs @@ -8,8 +8,8 @@ use crate::transform::{MirPass, MirSource}; pub struct NoLandingPads; -impl MirPass for NoLandingPads { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for NoLandingPads { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { no_landing_pads(tcx, body) } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 649cccc36c346..1fe45a2c4240b 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1572,8 +1572,8 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> (u8, &BitSet) { pub struct QualifyAndPromoteConstants; -impl MirPass for QualifyAndPromoteConstants { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. if body.return_ty().references_error() { tcx.sess.delay_span_bug(body.span, "QualifyAndPromoteConstants: MIR had errors"); diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index adba9097d12df..73089a2106f6b 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -18,8 +18,8 @@ pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) RemoveNoopLandingPads.remove_nop_landing_pads(body) } -impl MirPass for RemoveNoopLandingPads { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { remove_noop_landing_pads(tcx, body); } } diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 598de3a77e61c..1d3bf247387a7 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -23,8 +23,8 @@ use crate::dataflow::has_rustc_mir_with; pub struct SanityCheck; -impl MirPass for SanityCheck { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for SanityCheck { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let def_id = src.def_id(); if !tcx.has_attr(def_id, sym::rustc_mir) { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 2eed9d453f233..d4599ee08aa46 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -52,12 +52,12 @@ pub fn simplify_cfg(body: &mut Body<'_>) { body.basic_blocks_mut().raw.shrink_to_fit(); } -impl MirPass for SimplifyCfg { +impl<'tcx> MirPass<'tcx> for SimplifyCfg { fn name(&self) -> Cow<'_, str> { Cow::Borrowed(&self.label) } - fn run_pass<'tcx>(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body); simplify_cfg(body); } @@ -292,8 +292,8 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) { pub struct SimplifyLocals; -impl MirPass for SimplifyLocals { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for SimplifyLocals { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut marker = DeclMarker { locals: BitSet::new_empty(body.local_decls.len()) }; marker.visit_body(body); // Return pointer and arguments are always live diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 9ffa3db4c2eb0..0a509666d34ae 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -14,12 +14,12 @@ impl SimplifyBranches { } } -impl MirPass for SimplifyBranches { +impl<'tcx> MirPass<'tcx> for SimplifyBranches { fn name(&self) -> Cow<'_, str> { Cow::Borrowed(&self.label) } - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env(src.def_id()); for block in body.basic_blocks_mut() { let terminator = block.terminator_mut(); diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index 60489e7fa3668..8199a252e78b0 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -36,8 +36,8 @@ use crate::util::patch::MirPatch; pub struct UniformArrayMoveOut; -impl MirPass for UniformArrayMoveOut { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for UniformArrayMoveOut { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut patch = MirPatch::new(body); let param_env = tcx.param_env(src.def_id()); { @@ -184,8 +184,8 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> { pub struct RestoreSubsliceArrayMoveOut; -impl MirPass for RestoreSubsliceArrayMoveOut { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut patch = MirPatch::new(body); let param_env = tcx.param_env(src.def_id()); { From 73814654b29604ded9dff105e4156639980d2f2c Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 4 Aug 2019 16:20:21 -0400 Subject: [PATCH 116/618] Move promoted out of mir::Body --- src/librustc/arena.rs | 10 +++ src/librustc/mir/mod.rs | 9 -- src/librustc/query/mod.rs | 14 +++- src/librustc/ty/context.rs | 12 ++- src/librustc_metadata/cstore_impl.rs | 9 ++ src/librustc_metadata/decoder.rs | 10 ++- src/librustc_metadata/encoder.rs | 64 +++++++++------ src/librustc_metadata/schema.rs | 2 + src/librustc_mir/borrow_check/mod.rs | 13 ++- src/librustc_mir/borrow_check/nll/mod.rs | 8 +- src/librustc_mir/borrow_check/nll/renumber.rs | 19 +++-- .../borrow_check/nll/type_check/mod.rs | 11 ++- src/librustc_mir/build/mod.rs | 1 - src/librustc_mir/const_eval.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 33 ++++---- src/librustc_mir/shim.rs | 4 - src/librustc_mir/transform/const_prop.rs | 28 ++----- src/librustc_mir/transform/inline.rs | 9 +- src/librustc_mir/transform/mod.rs | 82 ++++++++++++++++--- src/librustc_mir/transform/promote_consts.rs | 20 +++-- src/librustc_mir/transform/qualify_consts.rs | 19 ++++- 21 files changed, 253 insertions(+), 126 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index e8c3914e695ad..a38dbbdd50c57 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -25,6 +25,16 @@ macro_rules! arena_types { [] adt_def: rustc::ty::AdtDef, [] steal_mir: rustc::ty::steal::Steal>, [] mir: rustc::mir::Body<$tcx>, + [] steal_promoted: rustc::ty::steal::Steal< + rustc_data_structures::indexed_vec::IndexVec< + rustc::mir::Promoted, + rustc::mir::Body<$tcx> + > + >, + [] promoted: rustc_data_structures::indexed_vec::IndexVec< + rustc::mir::Promoted, + rustc::mir::Body<$tcx> + >, [] tables: rustc::ty::TypeckTables<$tcx>, [] const_allocs: rustc::mir::interpret::Allocation, [] vtable_method: Option<( diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 11701a6637744..66f5eaeeda1c7 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -108,11 +108,6 @@ pub struct Body<'tcx> { /// needn't) be tracked across crates. pub source_scope_local_data: ClearCrossCrate>, - /// Rvalues promoted from this function, such as borrows of constants. - /// Each of them is the Body of a constant with the fn's type parameters - /// in scope, but a separate set of locals. - pub promoted: IndexVec>, - /// Yields type of the function, if it is a generator. pub yield_ty: Option>, @@ -174,7 +169,6 @@ impl<'tcx> Body<'tcx> { basic_blocks: IndexVec>, source_scopes: IndexVec, source_scope_local_data: ClearCrossCrate>, - promoted: IndexVec>, yield_ty: Option>, local_decls: LocalDecls<'tcx>, user_type_annotations: CanonicalUserTypeAnnotations<'tcx>, @@ -196,7 +190,6 @@ impl<'tcx> Body<'tcx> { basic_blocks, source_scopes, source_scope_local_data, - promoted, yield_ty, generator_drop: None, generator_layout: None, @@ -418,7 +411,6 @@ impl_stable_hash_for!(struct Body<'tcx> { basic_blocks, source_scopes, source_scope_local_data, - promoted, yield_ty, generator_drop, generator_layout, @@ -3032,7 +3024,6 @@ BraceStructTypeFoldableImpl! { basic_blocks, source_scopes, source_scope_local_data, - promoted, yield_ty, generator_drop, generator_layout, diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 5ab1b90642a6a..e1dbaeb5b173d 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -110,7 +110,7 @@ rustc_queries! { no_hash } - query mir_validated(_: DefId) -> &'tcx Steal> { + query mir_validated(_: DefId) -> (&'tcx Steal>, &'tcx Steal>>) { no_hash } @@ -125,7 +125,17 @@ rustc_queries! { } } - query promoted_mir(key: DefId) -> &'tcx IndexVec> { } + query promoted_mir(key: DefId) -> &'tcx IndexVec> { + cache_on_disk_if { key.is_local() } + load_cached(tcx, id) { + let promoted: Option< + rustc_data_structures::indexed_vec::IndexVec< + crate::mir::Promoted, + crate::mir::Body<'tcx> + >> = tcx.queries.on_disk_cache.try_load_query_result(tcx, id); + promoted.map(|p| &*tcx.arena.alloc(p)) + } + } } TypeChecking { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index e72efdb057ab1..9f316e93111a3 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -21,7 +21,7 @@ use crate::middle::cstore::EncodedMetadata; use crate::middle::lang_items; use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use crate::middle::stability; -use crate::mir::{Body, interpret, ProjectionKind}; +use crate::mir::{Body, interpret, ProjectionKind, Promoted}; use crate::mir::interpret::{ConstValue, Allocation, Scalar}; use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, Subst}; use crate::ty::ReprOptions; @@ -1096,6 +1096,16 @@ impl<'tcx> TyCtxt<'tcx> { self.arena.alloc(Steal::new(mir)) } + pub fn alloc_steal_promoted(self, promoted: IndexVec>) -> + &'tcx Steal>> { + self.arena.alloc(Steal::new(promoted)) + } + + pub fn intern_promoted(self, promoted: IndexVec>) -> + &'tcx IndexVec> { + self.arena.alloc(promoted) + } + pub fn alloc_adt_def( self, did: DefId, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index a66da32fa4d75..7aeeef00ea934 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -136,6 +136,15 @@ provide! { <'tcx> tcx, def_id, other, cdata, mir } + promoted_mir => { + let promoted = cdata.maybe_get_promoted_mir(tcx, def_id.index).unwrap_or_else(|| { + bug!("get_promoted_mir: missing promoted MIR for `{:?}`", def_id) + }); + + let promoted = tcx.arena.alloc(promoted); + + promoted + } mir_const_qualif => { (cdata.mir_const_qualif(def_id.index), tcx.arena.alloc(BitSet::new_empty(0))) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index da96728d2dec9..128e30be79929 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -3,6 +3,7 @@ use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule, FullProcMacro}; use crate::schema::*; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::{Lrc, ReadGuard}; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc::hir; @@ -17,7 +18,7 @@ use rustc::mir::interpret::AllocDecodingSession; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::codec::TyDecoder; -use rustc::mir::Body; +use rustc::mir::{Body, Promoted}; use rustc::util::captures::Captures; use std::io; @@ -923,6 +924,13 @@ impl<'a, 'tcx> CrateMetadata { } } + pub fn maybe_get_promoted_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Option>> { + match self.is_proc_macro(id) { + true => None, + false => self.entry(id).promoted_mir.map(|promoted| promoted.decode((self, tcx)),) + } + } + pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { match self.entry(id).kind { EntryKind::Const(qualif, _) | diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index df3320c64a960..f3863fd788ae0 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -8,6 +8,7 @@ use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LocalDefId, use rustc::hir::GenericParamKind; use rustc::hir::map::definitions::DefPathTable; use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::indexed_vec::IndexVec; use rustc::middle::dependency_format::Linkage; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel, metadata_symbol_name}; @@ -623,6 +624,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -677,6 +679,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -713,7 +716,8 @@ impl EncodeContext<'tcx> { predicates: None, predicates_defined_on: None, - mir: None + mir: None, + promoted_mir: None, } } @@ -748,6 +752,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: None, + promoted_mir: None, } } @@ -808,6 +813,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -923,6 +929,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -1022,6 +1029,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: if mir { self.encode_optimized_mir(def_id) } else { None }, + promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, } } @@ -1052,6 +1060,16 @@ impl EncodeContext<'tcx> { } } + fn encode_promoted_mir(&mut self, def_id: DefId) -> Option>>> { + debug!("EncodeContext::encode_promoted_mir({:?})", def_id); + if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { + let promoted = self.tcx.promoted_mir(def_id); + Some(self.lazy(promoted)) + } else { + None + } + } + // Encodes the inherent implementations of a structure, enumeration, or trait. fn encode_inherent_implementations(&mut self, def_id: DefId) -> Lazy<[DefIndex]> { debug!("EncodeContext::encode_inherent_implementations({:?})", def_id); @@ -1202,6 +1220,20 @@ impl EncodeContext<'tcx> { hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), }; + let mir = match item.node { + hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true, + hir::ItemKind::Fn(_, header, ..) => { + let generics = tcx.generics_of(def_id); + let needs_inline = + (generics.requires_monomorphization(tcx) || + tcx.codegen_fn_attrs(def_id).requests_inline()) && + !self.metadata_output_only(); + let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; + needs_inline || header.constness == hir::Constness::Const || always_encode_mir + } + _ => false, + }; + Entry { kind, visibility: self.lazy(ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), @@ -1301,29 +1333,8 @@ impl EncodeContext<'tcx> { _ => None, // not *wrong* for other kinds of items, but not needed }, - mir: match item.node { - hir::ItemKind::Static(..) => { - self.encode_optimized_mir(def_id) - } - hir::ItemKind::Const(..) => self.encode_optimized_mir(def_id), - hir::ItemKind::Fn(_, header, ..) => { - let generics = tcx.generics_of(def_id); - let needs_inline = - (generics.requires_monomorphization(tcx) || - tcx.codegen_fn_attrs(def_id).requests_inline()) && - !self.metadata_output_only(); - let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; - if needs_inline - || header.constness == hir::Constness::Const - || always_encode_mir - { - self.encode_optimized_mir(def_id) - } else { - None - } - } - _ => None, - }, + mir: if mir { self.encode_optimized_mir(def_id) } else { None }, + promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, } } @@ -1350,6 +1361,7 @@ impl EncodeContext<'tcx> { predicates: None, predicates_defined_on: None, mir: None, + promoted_mir: None, } } @@ -1376,6 +1388,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: None, + promoted_mir: None, } } @@ -1436,6 +1449,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -1464,6 +1478,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -1675,6 +1690,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: None, + promoted_mir: None, } } } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index f37877b437e15..72a4b527c93d0 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -11,6 +11,7 @@ use rustc::session::CrateDisambiguator; use rustc::session::config::SymbolManglingVersion; use rustc::ty::{self, Ty, ReprOptions}; use rustc_target::spec::{PanicStrategy, TargetTriple}; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::svh::Svh; use syntax::{ast, attr}; @@ -231,6 +232,7 @@ pub struct Entry<'tcx> { pub predicates_defined_on: Option>>, pub mir: Option>>, + pub promoted_mir: Option>>>, } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index de27aec2b2990..05b396681ac06 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -13,7 +13,7 @@ use rustc::mir::{ ClearCrossCrate, Local, Location, Body, Mutability, Operand, Place, PlaceBase, PlaceRef, Static, StaticKind }; -use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind}; +use rustc::mir::{Field, Projection, ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt}; @@ -22,6 +22,7 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level}; use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::dominators::Dominators; +use rustc_data_structures::indexed_vec::IndexVec; use smallvec::SmallVec; use std::collections::BTreeMap; @@ -86,12 +87,13 @@ pub fn provide(providers: &mut Providers<'_>) { } fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> { - let input_body = tcx.mir_validated(def_id); + let (input_body, promoted) = tcx.mir_validated(def_id); debug!("run query mir_borrowck: {}", tcx.def_path_str(def_id)); let opt_closure_req = tcx.infer_ctxt().enter(|infcx| { let input_body: &Body<'_> = &input_body.borrow(); - do_mir_borrowck(&infcx, input_body, def_id) + let promoted: &IndexVec<_, _> = &promoted.borrow(); + do_mir_borrowck(&infcx, input_body, promoted, def_id) }); debug!("mir_borrowck done"); @@ -101,6 +103,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> { fn do_mir_borrowck<'a, 'tcx>( infcx: &InferCtxt<'a, 'tcx>, input_body: &Body<'tcx>, + input_promoted: &IndexVec>, def_id: DefId, ) -> BorrowCheckResult<'tcx> { debug!("do_mir_borrowck(def_id = {:?})", def_id); @@ -147,7 +150,8 @@ fn do_mir_borrowck<'a, 'tcx>( // be modified (in place) to contain non-lexical lifetimes. It // will have a lifetime tied to the inference context. let mut body: Body<'tcx> = input_body.clone(); - let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body); + let mut promoted: IndexVec> = input_promoted.clone(); + let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted); let body = &body; // no further changes let location_table = &LocationTable::new(body); @@ -184,6 +188,7 @@ fn do_mir_borrowck<'a, 'tcx>( def_id, free_regions, body, + &promoted, &upvars, location_table, param_env, diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index d65cdde303ca0..11ec154e5b5c1 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -11,8 +11,9 @@ use crate::transform::MirSource; use crate::borrow_check::Upvar; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Body}; +use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Body, Promoted}; use rustc::ty::{self, RegionKind, RegionVid}; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::Diagnostic; use std::fmt::Debug; use std::env; @@ -52,6 +53,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( def_id: DefId, param_env: ty::ParamEnv<'tcx>, body: &mut Body<'tcx>, + promoted: &mut IndexVec>, ) -> UniversalRegions<'tcx> { debug!("replace_regions_in_mir(def_id={:?})", def_id); @@ -59,7 +61,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( let universal_regions = UniversalRegions::new(infcx, def_id, param_env); // Replace all remaining regions with fresh inference variables. - renumber::renumber_mir(infcx, body); + renumber::renumber_mir(infcx, body, promoted); let source = MirSource::item(def_id); mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, body, |_, _| Ok(())); @@ -75,6 +77,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( def_id: DefId, universal_regions: UniversalRegions<'tcx>, body: &Body<'tcx>, + promoted: &IndexVec>, upvars: &[Upvar], location_table: &LocationTable, param_env: ty::ParamEnv<'tcx>, @@ -105,6 +108,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( infcx, param_env, body, + promoted, def_id, &universal_regions, location_table, diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index c1d1185cf177a..4e3ffb7af1601 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,16 +1,18 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable}; -use rustc::mir::{Location, Body}; +use rustc::mir::{Location, Body, Promoted}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; +use rustc_data_structures::indexed_vec::IndexVec; /// Replaces all free regions appearing in the MIR with fresh /// inference variables, returning the number of variables created. -pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, 'tcx>, body: &mut Body<'tcx>) { +pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, 'tcx>, body: &mut Body<'tcx>, promoted: &mut IndexVec>) { debug!("renumber_mir()"); debug!("renumber_mir: body.arg_count={:?}", body.arg_count); let mut visitor = NLLVisitor { infcx }; + visitor.visit_promoted(promoted); visitor.visit_body(body); } @@ -41,17 +43,16 @@ impl<'a, 'tcx> NLLVisitor<'a, 'tcx> { { renumber_regions(self.infcx, value) } -} -impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { - fn visit_body(&mut self, body: &mut Body<'tcx>) { - for promoted in body.promoted.iter_mut() { - self.visit_body(promoted); + fn visit_promoted(&mut self, promoted: &mut IndexVec>) { + debug!("visiting promoted mir"); + for body in promoted.iter_mut() { + self.visit_body(body); } - - self.super_body(body); } +} +impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) { debug!("visit_ty(ty={:?}, ty_context={:?})", ty, ty_context); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 9ff0c6ca6a546..4b4477756bacc 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -112,6 +112,7 @@ pub(crate) fn type_check<'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, + promoted: &IndexVec>, mir_def_id: DefId, universal_regions: &Rc>, location_table: &LocationTable, @@ -157,6 +158,7 @@ pub(crate) fn type_check<'tcx>( mir_def_id, param_env, body, + promoted, ®ion_bound_pairs, implicit_region_bound, &mut borrowck_context, @@ -180,6 +182,7 @@ fn type_check_internal<'a, 'tcx, R>( mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, body: &'a Body<'tcx>, + promoted: &'a IndexVec>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, @@ -197,7 +200,7 @@ fn type_check_internal<'a, 'tcx, R>( universal_region_relations, ); let errors_reported = { - let mut verifier = TypeVerifier::new(&mut checker, body); + let mut verifier = TypeVerifier::new(&mut checker, body, promoted); verifier.visit_body(body); verifier.errors_reported }; @@ -254,6 +257,7 @@ enum FieldAccessError { struct TypeVerifier<'a, 'b, 'tcx> { cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, + promoted: &'b IndexVec>, last_span: Span, mir_def_id: DefId, errors_reported: bool, @@ -380,9 +384,10 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { - fn new(cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>) -> Self { + fn new(cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, promoted: &'b IndexVec>) -> Self { TypeVerifier { body, + promoted, mir_def_id: cx.mir_def_id, cx, last_span: body.span, @@ -442,7 +447,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { match kind { StaticKind::Promoted(promoted) => { if !self.errors_reported { - let promoted_body = &self.body.promoted[*promoted]; + let promoted_body = &self.promoted[*promoted]; self.sanitize_promoted(promoted_body, location); let promoted_ty = promoted_body.return_ty(); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 4e970aee42cf4..3e3558fc60062 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -763,7 +763,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.basic_blocks, self.source_scopes, ClearCrossCrate::Set(self.source_scope_local_data), - IndexVec::new(), yield_ty, self.local_decls, self.canonical_user_type_annotations, diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 76ee76a74562b..4ab5c9cc1c498 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -667,7 +667,7 @@ pub fn const_eval_raw_provider<'tcx>( let res = ecx.load_mir(cid.instance.def); res.map(|body| { if let Some(index) = cid.promoted { - &body.promoted[index] + &tcx.promoted_mir(def_id)[index] } else { body } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 12d763bb7910a..9d80163f30f9d 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -185,7 +185,7 @@ use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind, Instance}; use rustc::ty::print::obsolete::DefPathBasedNames; use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc::session::config::EntryFnType; -use rustc::mir::{self, Location, PlaceBase, Promoted, Static, StaticKind}; +use rustc::mir::{self, Location, PlaceBase, Static, StaticKind}; use rustc::mir::visit::Visitor as MirVisitor; use rustc::mir::mono::{MonoItem, InstantiationMode}; use rustc::mir::interpret::{Scalar, GlobalId, GlobalAlloc, ErrorHandled}; @@ -1222,6 +1222,7 @@ fn collect_neighbours<'tcx>( instance: Instance<'tcx>, output: &mut Vec>, ) { + debug!("collect_neighbours: {:?}", instance.def_id()); let body = tcx.instance_mir(instance.def); MirNeighborCollector { @@ -1230,20 +1231,22 @@ fn collect_neighbours<'tcx>( output, param_substs: instance.substs, }.visit_body(&body); - let param_env = ty::ParamEnv::reveal_all(); - for i in 0..body.promoted.len() { - use rustc_data_structures::indexed_vec::Idx; - let i = Promoted::new(i); - let cid = GlobalId { - instance, - promoted: Some(i), - }; - match tcx.const_eval(param_env.and(cid)) { - Ok(val) => collect_const(tcx, val, instance.substs, output), - Err(ErrorHandled::Reported) => {}, - Err(ErrorHandled::TooGeneric) => span_bug!( - body.promoted[i].span, "collection encountered polymorphic constant", - ), + + if let ty::InstanceDef::Item(def_id) = instance.def { + let param_env = ty::ParamEnv::reveal_all(); + let promoted = tcx.promoted_mir(def_id); + for (promoted, promoted_body) in promoted.iter_enumerated() { + let cid = GlobalId { + instance, + promoted: Some(promoted), + }; + match tcx.const_eval(param_env.and(cid)) { + Ok(val) => collect_const(tcx, val, instance.substs, output), + Err(ErrorHandled::Reported) => {}, + Err(ErrorHandled::TooGeneric) => span_bug!( + promoted_body.span, "collection encountered polymorphic constant", + ), + } } } } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 3e02f6c3725fd..9d31015f84558 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -201,7 +201,6 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) SourceScopeData { span: span, parent_scope: None }, 1 ), ClearCrossCrate::Clear, - IndexVec::new(), None, local_decls_for_sig(&sig, span), IndexVec::new(), @@ -369,7 +368,6 @@ impl CloneShimBuilder<'tcx> { SourceScopeData { span: self.span, parent_scope: None }, 1 ), ClearCrossCrate::Clear, - IndexVec::new(), None, self.local_decls, IndexVec::new(), @@ -813,7 +811,6 @@ fn build_call_shim<'tcx>( SourceScopeData { span: span, parent_scope: None }, 1 ), ClearCrossCrate::Clear, - IndexVec::new(), None, local_decls, IndexVec::new(), @@ -900,7 +897,6 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> { SourceScopeData { span: span, parent_scope: None }, 1 ), ClearCrossCrate::Clear, - IndexVec::new(), None, local_decls, IndexVec::new(), diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index ac442a496e535..790595b4feef9 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -8,7 +8,7 @@ use rustc::mir::{ AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, Local, NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem, - SourceScope, SourceScopeLocalData, LocalDecl, Promoted, + SourceScope, SourceScopeLocalData, LocalDecl, }; use rustc::mir::visit::{ Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext, @@ -64,17 +64,12 @@ impl<'tcx> MirPass<'tcx> for ConstProp { &mut body.source_scope_local_data, ClearCrossCrate::Clear ); - let promoted = std::mem::replace( - &mut body.promoted, - IndexVec::new() - ); let dummy_body = &Body::new( body.basic_blocks().clone(), Default::default(), ClearCrossCrate::Clear, - Default::default(), None, body.local_decls.clone(), Default::default(), @@ -92,22 +87,17 @@ impl<'tcx> MirPass<'tcx> for ConstProp { body, dummy_body, source_scope_local_data, - promoted, tcx, source ); optimization_finder.visit_body(body); // put back the data we stole from `mir` - let (source_scope_local_data, promoted) = optimization_finder.release_stolen_data(); + let source_scope_local_data = optimization_finder.release_stolen_data(); std::mem::replace( &mut body.source_scope_local_data, source_scope_local_data ); - std::mem::replace( - &mut body.promoted, - promoted - ); trace!("ConstProp done for {:?}", source.def_id()); } @@ -124,7 +114,6 @@ struct ConstPropagator<'mir, 'tcx> { param_env: ParamEnv<'tcx>, source_scope_local_data: ClearCrossCrate>, local_decls: IndexVec>, - promoted: IndexVec>, } impl<'mir, 'tcx> LayoutOf for ConstPropagator<'mir, 'tcx> { @@ -155,7 +144,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { body: &Body<'tcx>, dummy_body: &'mir Body<'tcx>, source_scope_local_data: ClearCrossCrate>, - promoted: IndexVec>, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, ) -> ConstPropagator<'mir, 'tcx> { @@ -184,17 +172,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { source_scope_local_data, //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it local_decls: body.local_decls.clone(), - promoted, } } - fn release_stolen_data( - self, - ) -> ( - ClearCrossCrate>, - IndexVec>, - ) { - (self.source_scope_local_data, self.promoted) + fn release_stolen_data(self) -> ClearCrossCrate> { + self.source_scope_local_data } fn get_const(&self, local: Local) -> Option> { @@ -318,7 +300,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // cannot use `const_eval` here, because that would require having the MIR // for the current function available, but we're producing said MIR right now let res = self.use_ecx(source_info, |this| { - let body = &this.promoted[*promoted]; + let body = &this.tcx.promoted_mir(this.source.def_id())[*promoted]; eval_promoted(this.tcx, cid, body, this.param_env) })?; trace!("evaluated promoted {:?} to {:?}", promoted, res); diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 57aac2b0eac99..19a8769ce1633 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -394,7 +394,7 @@ impl Inliner<'tcx> { let mut local_map = IndexVec::with_capacity(callee_body.local_decls.len()); let mut scope_map = IndexVec::with_capacity(callee_body.source_scopes.len()); - let mut promoted_map = IndexVec::with_capacity(callee_body.promoted.len()); + let promoted_map = IndexVec::with_capacity(self.tcx.promoted_mir(callsite.callee).len()); for mut scope in callee_body.source_scopes.iter().cloned() { if scope.parent_scope.is_none() { @@ -420,9 +420,10 @@ impl Inliner<'tcx> { local_map.push(idx); } - promoted_map.extend( - callee_body.promoted.iter().cloned().map(|p| caller_body.promoted.push(p)) - ); + //TODO fixme + //promoted_map.extend( + // self.tcx.promoted_mir(callsite.callee).iter().cloned().map(|p| caller_body.promoted.push(p)) + //); // If the call is something like `a[*i] = f(i)`, where // `i : &mut usize`, then just duplicating the `a[*i]` diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 255635b933385..a78e78331ee3f 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -184,13 +184,6 @@ pub fn run_passes( }; run_passes(body, None); - - for (index, promoted_body) in body.promoted.iter_enumerated_mut() { - run_passes(promoted_body, Some(index)); - - //Let's make sure we don't miss any nested instances - assert!(promoted_body.promoted.is_empty()) - } } fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { @@ -207,7 +200,7 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { tcx.alloc_steal_mir(body) } -fn mir_validated(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Steal> { +fn mir_validated(tcx: TyCtxt<'tcx>, def_id: DefId) -> (&'tcx Steal>, &'tcx Steal>>) { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); if let hir::BodyOwnerKind::Const = tcx.hir().body_owner_kind(hir_id) { // Ensure that we compute the `mir_const_qualif` for constants at @@ -216,12 +209,14 @@ fn mir_validated(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Steal> { } let mut body = tcx.mir_const(def_id).steal(); + let qualify_and_promote_pass = qualify_consts::QualifyAndPromoteConstants::default(); run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Validated, &[ // What we need to run borrowck etc. - &qualify_consts::QualifyAndPromoteConstants, + &qualify_and_promote_pass, &simplify::SimplifyCfg::new("qualify-consts"), ]); - tcx.alloc_steal_mir(body) + let promoted = qualify_and_promote_pass.promoted.into_inner(); + (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted.unwrap_or_else(|| IndexVec::new()))) } fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { @@ -241,7 +236,8 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { tcx.ensure().borrowck(def_id); } - let mut body = tcx.mir_validated(def_id).steal(); + let (body, _) = tcx.mir_validated(def_id); + let mut body = body.steal(); run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Optimized, &[ // Remove all things only needed by analysis &no_landing_pads::NoLandingPads, @@ -297,6 +293,66 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { } fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec> { - let body = tcx.optimized_mir(def_id); - &body.promoted + if tcx.is_constructor(def_id) { + return tcx.intern_promoted(IndexVec::new()); + } + + tcx.ensure().mir_borrowck(def_id); + let (_, promoted) = tcx.mir_validated(def_id); + let mut promoted = promoted.steal(); + + for mut body in promoted.iter_mut() { + run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Optimized, &[ + // Remove all things only needed by analysis + &no_landing_pads::NoLandingPads, + &simplify_branches::SimplifyBranches::new("initial"), + &remove_noop_landing_pads::RemoveNoopLandingPads, + &cleanup_post_borrowck::CleanupNonCodegenStatements, + + &simplify::SimplifyCfg::new("early-opt"), + + // These next passes must be executed together + &add_call_guards::CriticalCallEdges, + &elaborate_drops::ElaborateDrops, + &no_landing_pads::NoLandingPads, + // AddMovesForPackedDrops needs to run after drop + // elaboration. + &add_moves_for_packed_drops::AddMovesForPackedDrops, + // AddRetag needs to run after ElaborateDrops, and it needs + // an AllCallEdges pass right before it. Otherwise it should + // run fairly late, but before optimizations begin. + &add_call_guards::AllCallEdges, + &add_retag::AddRetag, + + &simplify::SimplifyCfg::new("elaborate-drops"), + + // No lifetime analysis based on borrowing can be done from here on out. + + // From here on out, regions are gone. + &erase_regions::EraseRegions, + + // Optimizations begin. + &uniform_array_move_out::RestoreSubsliceArrayMoveOut, + &inline::Inline, + + // Lowering generator control-flow and variables + // has to happen before we do anything else to them. + &generator::StateTransform, + + &instcombine::InstCombine, + &const_prop::ConstProp, + &simplify_branches::SimplifyBranches::new("after-const-prop"), + &deaggregator::Deaggregator, + ©_prop::CopyPropagation, + &simplify_branches::SimplifyBranches::new("after-copy-prop"), + &remove_noop_landing_pads::RemoveNoopLandingPads, + &simplify::SimplifyCfg::new("final"), + &simplify::SimplifyLocals, + + &add_call_guards::CriticalCallEdges, + &dump_mir::Marker("PreCodegen"), + ]); + } + + tcx.intern_promoted(promoted) } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 3090b63a7e993..7015e2c087faa 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -293,10 +293,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { new_temp } - fn promote_candidate(mut self, candidate: Candidate) { + fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Option> { let mut operand = { let promoted = &mut self.promoted; - let promoted_id = Promoted::new(self.source.promoted.len()); + let promoted_id = Promoted::new(next_promoted_id); let mut promoted_place = |ty, span| { promoted.span = span; promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span); @@ -353,7 +353,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { // a function requiring a constant argument and as that constant value // providing a value whose computation contains another call to a function // requiring a constant argument. - TerminatorKind::Goto { .. } => return, + TerminatorKind::Goto { .. } => return None, _ => bug!() } } @@ -368,7 +368,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let span = self.promoted.span; self.assign(RETURN_PLACE, Rvalue::Use(operand), span); - self.source.promoted.push(self.promoted); + Some(self.promoted) } } @@ -389,10 +389,12 @@ pub fn promote_candidates<'tcx>( tcx: TyCtxt<'tcx>, mut temps: IndexVec, candidates: Vec, -) { +) -> IndexVec> { // Visit candidates in reverse, in case they're nested. debug!("promote_candidates({:?})", candidates); + let mut promotions = IndexVec::new(); + for candidate in candidates.into_iter().rev() { match candidate { Candidate::Repeat(Location { block, statement_index }) | @@ -426,7 +428,6 @@ pub fn promote_candidates<'tcx>( // memory usage? body.source_scopes.clone(), body.source_scope_local_data.clone(), - IndexVec::new(), None, initial_locals, IndexVec::new(), @@ -440,7 +441,10 @@ pub fn promote_candidates<'tcx>( temps: &mut temps, keep_original: false }; - promoter.promote_candidate(candidate); + + if let Some(promoted) = promoter.promote_candidate(candidate, promotions.len()) { + promotions.push(promoted); + } } // Eliminate assignments to, and drops of promoted temps. @@ -474,4 +478,6 @@ pub fn promote_candidates<'tcx>( _ => {} } } + + promotions } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 1fe45a2c4240b..dd4db479cc00b 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -25,6 +25,7 @@ use syntax::feature_gate::{emit_feature_err, GateIssue}; use syntax::symbol::sym; use syntax_pos::{Span, DUMMY_SP}; +use std::cell::Cell; use std::fmt; use std::ops::{Deref, Index, IndexMut}; use std::usize; @@ -1570,9 +1571,19 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> (u8, &BitSet) { Checker::new(tcx, def_id, body, Mode::Const).check_const() } -pub struct QualifyAndPromoteConstants; +pub struct QualifyAndPromoteConstants<'tcx> { + pub promoted: Cell>>>, +} + +impl<'tcx> Default for QualifyAndPromoteConstants<'tcx> { + fn default() -> Self { + QualifyAndPromoteConstants { + promoted: Cell::new(None), + } + } +} -impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { +impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. if body.return_ty().references_error() { @@ -1649,7 +1660,9 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { }; // Do the actual promotion, now that we know what's viable. - promote_consts::promote_candidates(body, tcx, temps, candidates); + self.promoted.set( + Some(promote_consts::promote_candidates(body, tcx, temps, candidates)) + ); } else { if !body.control_flow_destroyed.is_empty() { let mut locals = body.vars_iter(); From f13faf58d92d2d6154acc8cf50bf5d237a3a4118 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 5 Aug 2019 20:01:59 -0400 Subject: [PATCH 117/618] Remove eval_promoted const-prop hack --- src/librustc_mir/const_eval.rs | 23 +++------------------- src/librustc_mir/interpret/eval_context.rs | 6 +++++- src/librustc_mir/transform/const_prop.rs | 7 ++----- 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 4ab5c9cc1c498..67d63e52b2bfa 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -49,17 +49,6 @@ pub(crate) fn mk_eval_cx<'mir, 'tcx>( InterpCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new(), Default::default()) } -pub(crate) fn eval_promoted<'mir, 'tcx>( - tcx: TyCtxt<'tcx>, - cid: GlobalId<'tcx>, - body: &'mir mir::Body<'tcx>, - param_env: ty::ParamEnv<'tcx>, -) -> InterpResult<'tcx, MPlaceTy<'tcx>> { - let span = tcx.def_span(cid.instance.def_id()); - let mut ecx = mk_eval_cx(tcx, span, param_env); - eval_body_using_ecx(&mut ecx, cid, body, param_env) -} - fn op_to_const<'tcx>( ecx: &CompileTimeEvalContext<'_, 'tcx>, op: OpTy<'tcx>, @@ -360,7 +349,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } } // This is a const fn. Call it. - Ok(Some(match ecx.load_mir(instance.def) { + Ok(Some(match ecx.load_mir(instance.def, None) { Ok(body) => body, Err(err) => { if let err_unsup!(NoMirFor(ref path)) = err.kind { @@ -664,14 +653,8 @@ pub fn const_eval_raw_provider<'tcx>( Default::default() ); - let res = ecx.load_mir(cid.instance.def); - res.map(|body| { - if let Some(index) = cid.promoted { - &tcx.promoted_mir(def_id)[index] - } else { - body - } - }).and_then( + let res = ecx.load_mir(cid.instance.def, cid.promoted); + res.and_then( |body| eval_body_using_ecx(&mut ecx, cid, body, key.param_env) ).and_then(|place| { Ok(RawConst { diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 6f48396cdd7cf..ac01d436bdc9b 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -294,6 +294,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn load_mir( &self, instance: ty::InstanceDef<'tcx>, + promoted: Option, ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { // do not continue if typeck errors occurred (can only occur in local crate) let did = instance.def_id(); @@ -303,7 +304,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { { throw_inval!(TypeckError) } - trace!("load mir {:?}", instance); + trace!("load mir(instance={:?}, promoted={:?})", instance, promoted); + if let Some(promoted) = promoted { + return Ok(&self.tcx.promoted_mir(did)[promoted]); + } match instance { ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) { Ok(self.tcx.optimized_mir(did)) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 790595b4feef9..9aeef16ba1e38 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -27,7 +27,7 @@ use crate::interpret::{ ImmTy, MemoryKind, StackPopCleanup, LocalValue, LocalState, }; use crate::const_eval::{ - CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx, + CompileTimeInterpreter, error_to_const_error, mk_eval_cx, }; use crate::transform::{MirPass, MirSource}; @@ -297,11 +297,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { instance, promoted: Some(*promoted), }; - // cannot use `const_eval` here, because that would require having the MIR - // for the current function available, but we're producing said MIR right now let res = self.use_ecx(source_info, |this| { - let body = &this.tcx.promoted_mir(this.source.def_id())[*promoted]; - eval_promoted(this.tcx, cid, body, this.param_env) + this.ecx.const_eval_raw(cid) })?; trace!("evaluated promoted {:?} to {:?}", promoted, res); res.into() From 4d62545687d0c10577eb75c058c0662e6b261395 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 5 Aug 2019 21:11:55 -0400 Subject: [PATCH 118/618] Move def_id out add substsref --- src/librustc/mir/mod.rs | 18 ++++---- src/librustc/mir/visit.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 6 ++- src/librustc_codegen_ssa/mir/place.rs | 21 +++++++--- .../borrow_check/error_reporting.rs | 8 ++-- src/librustc_mir/borrow_check/mod.rs | 9 ++-- .../borrow_check/mutability_errors.rs | 5 ++- .../borrow_check/nll/type_check/mod.rs | 8 ++-- src/librustc_mir/borrow_check/place_ext.rs | 4 +- .../borrow_check/places_conflict.rs | 8 ++-- src/librustc_mir/build/expr/as_place.rs | 3 +- src/librustc_mir/interpret/place.rs | 6 +-- src/librustc_mir/monomorphize/collector.rs | 41 +++++++++---------- src/librustc_mir/transform/check_unsafety.rs | 4 +- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_mir/transform/inline.rs | 24 ++++------- src/librustc_mir/transform/promote_consts.rs | 41 +++++++++++++++---- src/librustc_mir/transform/qualify_consts.rs | 16 ++++---- .../transform/qualify_min_const_fn.rs | 4 +- 19 files changed, 134 insertions(+), 96 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 66f5eaeeda1c7..69e98583b191c 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1732,20 +1732,22 @@ pub enum PlaceBase<'tcx> { #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct Static<'tcx> { pub ty: Ty<'tcx>, - pub kind: StaticKind, + pub kind: StaticKind<'tcx>, + pub def_id: DefId, } #[derive( Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable, )] -pub enum StaticKind { - Promoted(Promoted), - Static(DefId), +pub enum StaticKind<'tcx> { + Promoted(Promoted, SubstsRef<'tcx>), + Static, } impl_stable_hash_for!(struct Static<'tcx> { ty, - kind + kind, + def_id }); /// The `Projection` data structure defines things of the form `base.x`, `*b` or `b[index]`. @@ -2106,10 +2108,12 @@ impl Debug for PlaceBase<'_> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { match *self { PlaceBase::Local(id) => write!(fmt, "{:?}", id), - PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static(def_id) }) => { + PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static, def_id }) => { write!(fmt, "({}: {:?})", ty::tls::with(|tcx| tcx.def_path_str(def_id)), ty) } - PlaceBase::Static(box self::Static { ty, kind: StaticKind::Promoted(promoted) }) => { + PlaceBase::Static(box self::Static { + ty, kind: StaticKind::Promoted(promoted, _), def_id: _ + }) => { write!(fmt, "({:?}: {:?})", promoted, ty) } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 2d16e7bcc8371..ac0e784d8bd12 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -708,7 +708,7 @@ macro_rules! make_mir_visitor { PlaceBase::Local(local) => { self.visit_local(local, context, location); } - PlaceBase::Static(box Static { kind: _, ty }) => { + PlaceBase::Static(box Static { kind: _, ty, def_id: _ }) => { self.visit_ty(& $($mutability)? *ty, TyContext::Location(location)); } } diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index dbce5ce4896a7..d2a7571fde1e2 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -609,8 +609,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Operand::Copy( Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted), + kind: StaticKind::Promoted(promoted, _), ty, + def_id: _, }), projection: None, } @@ -618,8 +619,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Operand::Move( Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted), + kind: StaticKind::Promoted(promoted, _), ty, + def_id: _, }), projection: None, } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index a632838ba2442..f7b94ea134cfc 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -1,4 +1,5 @@ -use rustc::ty::{self, Ty}; +use rustc::ty::{self, Instance, Ty}; +use rustc::ty::subst::Subst; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::mir; use rustc::mir::tcx::PlaceTy; @@ -454,16 +455,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::PlaceRef { base: mir::PlaceBase::Static(box mir::Static { ty, - kind: mir::StaticKind::Promoted(promoted), + kind: mir::StaticKind::Promoted(promoted, substs), + def_id, }), projection: None, } => { + debug!("promoted={:?}, def_id={:?}, substs={:?}, self_substs={:?}", promoted, def_id, substs, self.instance.substs); let param_env = ty::ParamEnv::reveal_all(); + let instance = Instance::new(*def_id, substs.subst(bx.tcx(), self.instance.substs)); + debug!("instance: {:?}", instance); let cid = mir::interpret::GlobalId { - instance: self.instance, + instance: instance, promoted: Some(*promoted), }; - let layout = cx.layout_of(self.monomorphize(&ty)); + let mono_ty = tcx.subst_and_normalize_erasing_regions( + instance.substs, + param_env, + ty, + ); + let layout = cx.layout_of(mono_ty); match bx.tcx().const_eval(param_env.and(cid)) { Ok(val) => match val.val { mir::interpret::ConstValue::ByRef { alloc, offset } => { @@ -487,7 +497,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::PlaceRef { base: mir::PlaceBase::Static(box mir::Static { ty, - kind: mir::StaticKind::Static(def_id), + kind: mir::StaticKind::Static, + def_id, }), projection: None, } => { diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 99899aa390c4a..251d4b727c754 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -159,7 +159,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), projection: None, @@ -169,7 +169,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Static(def_id), + kind: StaticKind::Static, + def_id, .. }), projection: None, @@ -440,7 +441,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { pub fn is_place_thread_local(&self, place_ref: PlaceRef<'cx, 'tcx>) -> bool { if let PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Static(def_id), + kind: StaticKind::Static, + def_id, .. }), projection: None, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 05b396681ac06..33cec78f3dfd5 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1467,13 +1467,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { assert!(root_place.projection.is_none()); let (might_be_alive, will_be_dropped) = match root_place.base { PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }) => { (true, false) } PlaceBase::Static(box Static { - kind: StaticKind::Static(_), + kind: StaticKind::Static, .. }) => { // Thread-locals might be dropped after the function exits, but @@ -2155,7 +2155,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // `Place::Promoted` if the promotion weren't 100% legal. So we just forward this PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), projection: None, @@ -2167,7 +2167,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }), PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Static(def_id), + kind: StaticKind::Static, + def_id, .. }), projection: None, diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 937c6383be341..091b3eeb05f6c 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -149,7 +149,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), projection: None, @@ -158,7 +158,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Static(def_id), + kind: StaticKind::Static, + def_id, .. }), projection: None, diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 4b4477756bacc..35dd5b5d7eb19 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -421,7 +421,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let mut place_ty = match place_base { PlaceBase::Local(index) => PlaceTy::from_ty(self.body.local_decls[*index].ty), - PlaceBase::Static(box Static { kind, ty: sty }) => { + PlaceBase::Static(box Static { kind, ty: sty, def_id }) => { let sty = self.sanitize_type(place, sty); let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, @@ -445,7 +445,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { }; }; match kind { - StaticKind::Promoted(promoted) => { + StaticKind::Promoted(promoted, _) => { if !self.errors_reported { let promoted_body = &self.promoted[*promoted]; self.sanitize_promoted(promoted_body, location); @@ -454,7 +454,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { check_err(self, place, promoted_ty, sty); } } - StaticKind::Static(def_id) => { + StaticKind::Static => { let ty = self.tcx().type_of(*def_id); let ty = self.cx.normalize(ty, location); @@ -471,7 +471,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let is_promoted = match place { Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), projection: None, diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs index 72d5588c34120..5caba637ccc4a 100644 --- a/src/librustc_mir/borrow_check/place_ext.rs +++ b/src/librustc_mir/borrow_check/place_ext.rs @@ -46,9 +46,9 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { } } } - PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) => + PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_, _), .. }) => false, - PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => { + PlaceBase::Static(box Static{ kind: StaticKind::Static, def_id, .. }) => { tcx.is_mutable_static(*def_id) } }; diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 4dd2794f11301..4f469174b392d 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -329,11 +329,11 @@ fn place_base_conflict<'tcx>( } (PlaceBase::Static(s1), PlaceBase::Static(s2)) => { match (&s1.kind, &s2.kind) { - (StaticKind::Static(def_id_1), StaticKind::Static(def_id_2)) => { - if def_id_1 != def_id_2 { + (StaticKind::Static, StaticKind::Static) => { + if s1.def_id != s2.def_id { debug!("place_element_conflict: DISJOINT-STATIC"); Overlap::Disjoint - } else if tcx.is_mutable_static(*def_id_1) { + } else if tcx.is_mutable_static(s1.def_id) { // We ignore mutable statics - they can only be unsafe code. debug!("place_element_conflict: IGNORE-STATIC-MUT"); Overlap::Disjoint @@ -342,7 +342,7 @@ fn place_base_conflict<'tcx>( Overlap::EqualOrDisjoint } }, - (StaticKind::Promoted(promoted_1), StaticKind::Promoted(promoted_2)) => { + (StaticKind::Promoted(promoted_1, _), StaticKind::Promoted(promoted_2, _)) => { if promoted_1 == promoted_2 { if let ty::Array(_, len) = s1.ty.sty { if let Some(0) = len.try_eval_usize(tcx, param_env) { diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 7005f274e0e7d..98cf4bba1c75f 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -126,7 +126,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::StaticRef { id } => block.and(Place { base: PlaceBase::Static(Box::new(Static { ty: expr.ty, - kind: StaticKind::Static(id), + kind: StaticKind::Static, + def_id: id, })), projection: None, }), diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 85f9cbd37589a..23c9e7fdf67ce 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -585,7 +585,7 @@ where use rustc::mir::StaticKind; Ok(match place_static.kind { - StaticKind::Promoted(promoted) => { + StaticKind::Promoted(promoted, _) => { let instance = self.frame().instance; self.const_eval_raw(GlobalId { instance, @@ -593,11 +593,11 @@ where })? } - StaticKind::Static(def_id) => { + StaticKind::Static => { let ty = place_static.ty; assert!(!ty.needs_subst()); let layout = self.layout_of(ty)?; - let instance = ty::Instance::mono(*self.tcx, def_id); + let instance = ty::Instance::mono(*self.tcx, place_static.def_id); let cid = GlobalId { instance, promoted: None diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 9d80163f30f9d..512ace1a4728c 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -180,7 +180,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::interpret::{AllocId, ConstValue}; use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem}; -use rustc::ty::subst::{InternalSubsts, SubstsRef}; +use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind, Instance}; use rustc::ty::print::obsolete::DefPathBasedNames; use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast}; @@ -661,7 +661,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { _context: mir::visit::PlaceContext, location: Location) { match place_base { - PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. }) => { + PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }) => { debug!("visiting static {:?} @ {:?}", def_id, location); let tcx = self.tcx; @@ -670,8 +670,23 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.output.push(MonoItem::Static(*def_id)); } } - PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => { - // FIXME: should we handle promoteds here instead of eagerly in collect_neighbours? + PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted, substs), def_id, .. }) => { + debug!("collecting promoted(def_id: {:?}, promoted: {:?}, substs: {:?})", def_id, promoted, substs); + debug!("param_substs: {:?}", self.param_substs); + let param_env = ty::ParamEnv::reveal_all(); + let cid = GlobalId { + instance: Instance::new(*def_id, substs.subst(self.tcx, self.param_substs)), + promoted: Some(*promoted), + }; + debug!("cid: {:?}", cid); + match self.tcx.const_eval(param_env.and(cid)) { + Ok(val) => collect_const(self.tcx, val, substs, self.output), + Err(ErrorHandled::Reported) => {}, + Err(ErrorHandled::TooGeneric) => { + let span = self.tcx.promoted_mir(*def_id)[*promoted].span; + span_bug!(span, "collection encountered polymorphic constant") + }, + } } PlaceBase::Local(_) => { // Locals have no relevance for collector @@ -1231,24 +1246,6 @@ fn collect_neighbours<'tcx>( output, param_substs: instance.substs, }.visit_body(&body); - - if let ty::InstanceDef::Item(def_id) = instance.def { - let param_env = ty::ParamEnv::reveal_all(); - let promoted = tcx.promoted_mir(def_id); - for (promoted, promoted_body) in promoted.iter_enumerated() { - let cid = GlobalId { - instance, - promoted: Some(promoted), - }; - match tcx.const_eval(param_env.and(cid)) { - Ok(val) => collect_const(tcx, val, instance.substs, output), - Err(ErrorHandled::Reported) => {}, - Err(ErrorHandled::TooGeneric) => span_bug!( - promoted_body.span, "collection encountered polymorphic constant", - ), - } - } - } } fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String { diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index d5c5267a119d3..539922c54d12d 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -205,10 +205,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { PlaceBase::Local(..) => { // Locals are safe. } - PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => { + PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => { bug!("unsafety checking should happen before promotion") } - PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. }) => { + PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }) => { if self.tcx.is_mutable_static(*def_id) { self.require_unsafe("use of mutable static", "mutable statics can be mutated by multiple threads: aliasing \ diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 9aeef16ba1e38..b6146b6b7227d 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -285,7 +285,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { place.iterate(|place_base, place_projection| { let mut eval = match place_base { PlaceBase::Local(loc) => self.get_const(*loc).clone()?, - PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..}) => { + PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted, _), ..}) => { let generics = self.tcx.generics_of(self.source.def_id()); if generics.requires_monomorphization(self.tcx) { // FIXME: can't handle code with generics diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 19a8769ce1633..533e08f5e1fd3 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -394,7 +394,6 @@ impl Inliner<'tcx> { let mut local_map = IndexVec::with_capacity(callee_body.local_decls.len()); let mut scope_map = IndexVec::with_capacity(callee_body.source_scopes.len()); - let promoted_map = IndexVec::with_capacity(self.tcx.promoted_mir(callsite.callee).len()); for mut scope in callee_body.source_scopes.iter().cloned() { if scope.parent_scope.is_none() { @@ -420,11 +419,6 @@ impl Inliner<'tcx> { local_map.push(idx); } - //TODO fixme - //promoted_map.extend( - // self.tcx.promoted_mir(callsite.callee).iter().cloned().map(|p| caller_body.promoted.push(p)) - //); - // If the call is something like `a[*i] = f(i)`, where // `i : &mut usize`, then just duplicating the `a[*i]` // Place could result in two different locations if `f` @@ -485,12 +479,12 @@ impl Inliner<'tcx> { args: &args, local_map, scope_map, - promoted_map, - _callsite: callsite, + callsite, destination: dest, return_block, cleanup_block: cleanup, - in_cleanup_block: false + in_cleanup_block: false, + tcx: self.tcx, }; @@ -645,12 +639,12 @@ struct Integrator<'a, 'tcx> { args: &'a [Local], local_map: IndexVec, scope_map: IndexVec, - promoted_map: IndexVec, - _callsite: CallSite<'tcx>, + callsite: CallSite<'tcx>, destination: Place<'tcx>, return_block: BasicBlock, cleanup_block: Option, in_cleanup_block: bool, + tcx: TyCtxt<'tcx>, } impl<'a, 'tcx> Integrator<'a, 'tcx> { @@ -701,14 +695,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { }, Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted), + kind: StaticKind::Promoted(_, substs), .. }), projection: None, } => { - if let Some(p) = self.promoted_map.get(*promoted).cloned() { - *promoted = p; - } + let adjusted_substs = substs.subst(self.tcx, self.callsite.substs); + debug!("replacing substs {:?} with {:?}", substs, adjusted_substs); + *substs = adjusted_substs; }, _ => self.super_place(place, _ctxt, _location) } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 7015e2c087faa..cb0ce77d5c014 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -12,9 +12,11 @@ //! initialization and can otherwise silence errors, if //! move analysis runs after promotion on broken MIR. +use rustc::hir::def_id::DefId; use rustc::mir::*; use rustc::mir::visit::{PlaceContext, MutatingUseContext, MutVisitor, Visitor}; use rustc::mir::traversal::ReversePostorder; +use rustc::ty::subst::InternalSubsts; use rustc::ty::TyCtxt; use syntax_pos::Span; @@ -293,17 +295,18 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { new_temp } - fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Option> { + fn promote_candidate(mut self, def_id: DefId, candidate: Candidate, next_promoted_id: usize) -> Option> { let mut operand = { let promoted = &mut self.promoted; let promoted_id = Promoted::new(next_promoted_id); - let mut promoted_place = |ty, span| { + let mut promoted_place = |ty, substs, span| { promoted.span = span; promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span); Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted_id), - ty + kind: StaticKind::Promoted(promoted_id, substs), + ty, + def_id, }), projection: None, } @@ -319,7 +322,14 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let span = statement.source_info.span; Operand::Move(Place { - base: mem::replace(&mut place.base, promoted_place(ty, span).base), + base: mem::replace( + &mut place.base, + promoted_place( + ty, + InternalSubsts::identity_for_item(self.tcx, def_id), + span, + ).base + ), projection: None, }) } @@ -332,7 +342,16 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { StatementKind::Assign(_, box Rvalue::Repeat(ref mut operand, _)) => { let ty = operand.ty(local_decls, self.tcx); let span = statement.source_info.span; - mem::replace(operand, Operand::Copy(promoted_place(ty, span))) + mem::replace( + operand, + Operand::Copy( + promoted_place( + ty, + InternalSubsts::identity_for_item(self.tcx, def_id), + span, + ) + ) + ) } _ => bug!() } @@ -343,7 +362,12 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { TerminatorKind::Call { ref mut args, .. } => { let ty = args[index].ty(local_decls, self.tcx); let span = terminator.source_info.span; - let operand = Operand::Copy(promoted_place(ty, span)); + let operand = + Operand::Copy( + promoted_place( + ty, + InternalSubsts::identity_for_item(self.tcx, def_id), + span)); mem::replace(&mut args[index], operand) } // We expected a `TerminatorKind::Call` for which we'd like to promote an @@ -385,6 +409,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { } pub fn promote_candidates<'tcx>( + def_id: DefId, body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>, mut temps: IndexVec, @@ -442,7 +467,7 @@ pub fn promote_candidates<'tcx>( keep_original: false }; - if let Some(promoted) = promoter.promote_candidate(candidate, promotions.len()) { + if let Some(promoted) = promoter.promote_candidate(def_id, candidate, promotions.len()) { promotions.push(promoted); } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index dd4db479cc00b..70a394ad98330 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -223,7 +223,7 @@ trait Qualif { } => Self::in_local(cx, *local), PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), projection: None, @@ -434,13 +434,13 @@ impl Qualif for IsNotPromotable { fn in_static(cx: &ConstCx<'_, 'tcx>, static_: &Static<'tcx>) -> bool { match static_.kind { - StaticKind::Promoted(_) => unreachable!(), - StaticKind::Static(def_id) => { + StaticKind::Promoted(_, _) => unreachable!(), + StaticKind::Static => { // Only allow statics (not consts) to refer to other statics. let allowed = cx.mode == Mode::Static || cx.mode == Mode::StaticMut; !allowed || - cx.tcx.get_attrs(def_id).iter().any( + cx.tcx.get_attrs(static_.def_id).iter().any( |attr| attr.check_name(sym::thread_local) ) } @@ -873,7 +873,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { dest_projection = &proj.base; }, (&PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), None) => bug!("promoteds don't exist yet during promotion"), (&PlaceBase::Static(box Static{ kind: _, .. }), None) => { @@ -1028,10 +1028,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { self.super_place_base(place_base, context, location); match place_base { PlaceBase::Local(_) => {} - PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) => { + PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_, _), .. }) => { unreachable!() } - PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => { + PlaceBase::Static(box Static{ kind: StaticKind::Static, def_id, .. }) => { if self.tcx .get_attrs(*def_id) .iter() @@ -1661,7 +1661,7 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { // Do the actual promotion, now that we know what's viable. self.promoted.set( - Some(promote_consts::promote_candidates(body, tcx, temps, candidates)) + Some(promote_consts::promote_candidates(def_id, body, tcx, temps, candidates)) ); } else { if !body.control_flow_destroyed.is_empty() { diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 334d0cee9fbe7..56093527aee24 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -264,11 +264,11 @@ fn check_place( } match place_base { - PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. }) => { + PlaceBase::Static(box Static { kind: StaticKind::Static, .. }) => { Err((span, "cannot access `static` items in const fn".into())) } PlaceBase::Local(_) - | PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => Ok(()), + | PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => Ok(()), } }) } From 34fe28bc67817db6743654f8eef8bbf8244f57bf Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Wed, 14 Aug 2019 08:08:17 -0400 Subject: [PATCH 119/618] Fix tidy --- src/librustc/query/mod.rs | 6 +++++- src/librustc_codegen_ssa/mir/place.rs | 1 - src/librustc_metadata/decoder.rs | 3 ++- src/librustc_metadata/encoder.rs | 3 ++- src/librustc_mir/borrow_check/mod.rs | 3 ++- src/librustc_mir/borrow_check/nll/renumber.rs | 6 +++++- src/librustc_mir/borrow_check/nll/type_check/mod.rs | 6 +++++- src/librustc_mir/monomorphize/collector.rs | 9 +++++---- src/librustc_mir/transform/mod.rs | 10 +++++++--- src/librustc_mir/transform/promote_consts.rs | 7 ++++++- 10 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index e1dbaeb5b173d..c4f7ca51f4a7a 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -110,7 +110,11 @@ rustc_queries! { no_hash } - query mir_validated(_: DefId) -> (&'tcx Steal>, &'tcx Steal>>) { + query mir_validated(_: DefId) -> + ( + &'tcx Steal>, + &'tcx Steal>> + ) { no_hash } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index f7b94ea134cfc..b08093c3a71eb 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -460,7 +460,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }), projection: None, } => { - debug!("promoted={:?}, def_id={:?}, substs={:?}, self_substs={:?}", promoted, def_id, substs, self.instance.substs); let param_env = ty::ParamEnv::reveal_all(); let instance = Instance::new(*def_id, substs.subst(bx.tcx(), self.instance.substs)); debug!("instance: {:?}", instance); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 128e30be79929..2add8bf918398 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -924,7 +924,8 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn maybe_get_promoted_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Option>> { + pub fn maybe_get_promoted_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> + Option>> { match self.is_proc_macro(id) { true => None, false => self.entry(id).promoted_mir.map(|promoted| promoted.decode((self, tcx)),) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index f3863fd788ae0..0b8d2438752fa 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1060,7 +1060,8 @@ impl EncodeContext<'tcx> { } } - fn encode_promoted_mir(&mut self, def_id: DefId) -> Option>>> { + fn encode_promoted_mir(&mut self, def_id: DefId) -> + Option>>> { debug!("EncodeContext::encode_promoted_mir({:?})", def_id); if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { let promoted = self.tcx.promoted_mir(def_id); diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 33cec78f3dfd5..8ded539e7205a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -151,7 +151,8 @@ fn do_mir_borrowck<'a, 'tcx>( // will have a lifetime tied to the inference context. let mut body: Body<'tcx> = input_body.clone(); let mut promoted: IndexVec> = input_promoted.clone(); - let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted); + let free_regions = + nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted); let body = &body; // no further changes let location_table = &LocationTable::new(body); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 4e3ffb7af1601..c6a5c6fdfd0f2 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -7,7 +7,11 @@ use rustc_data_structures::indexed_vec::IndexVec; /// Replaces all free regions appearing in the MIR with fresh /// inference variables, returning the number of variables created. -pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, 'tcx>, body: &mut Body<'tcx>, promoted: &mut IndexVec>) { +pub fn renumber_mir<'tcx>( + infcx: &InferCtxt<'_, 'tcx>, + body: &mut Body<'tcx>, + promoted: &mut IndexVec>, +) { debug!("renumber_mir()"); debug!("renumber_mir: body.arg_count={:?}", body.arg_count); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 35dd5b5d7eb19..da1f64b05151b 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -384,7 +384,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { - fn new(cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, promoted: &'b IndexVec>) -> Self { + fn new( + cx: &'a mut TypeChecker<'b, 'tcx>, + body: &'b Body<'tcx>, + promoted: &'b IndexVec>, + ) -> Self { TypeVerifier { body, promoted, diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 512ace1a4728c..11f9df625285f 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -670,15 +670,16 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.output.push(MonoItem::Static(*def_id)); } } - PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted, substs), def_id, .. }) => { - debug!("collecting promoted(def_id: {:?}, promoted: {:?}, substs: {:?})", def_id, promoted, substs); - debug!("param_substs: {:?}", self.param_substs); + PlaceBase::Static(box Static { + kind: StaticKind::Promoted(promoted, substs), + def_id, + .. + }) => { let param_env = ty::ParamEnv::reveal_all(); let cid = GlobalId { instance: Instance::new(*def_id, substs.subst(self.tcx, self.param_substs)), promoted: Some(*promoted), }; - debug!("cid: {:?}", cid); match self.tcx.const_eval(param_env.and(cid)) { Ok(val) => collect_const(self.tcx, val, substs, self.output), Err(ErrorHandled::Reported) => {}, diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index a78e78331ee3f..f59ad6bae0298 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -200,7 +200,10 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { tcx.alloc_steal_mir(body) } -fn mir_validated(tcx: TyCtxt<'tcx>, def_id: DefId) -> (&'tcx Steal>, &'tcx Steal>>) { +fn mir_validated( + tcx: TyCtxt<'tcx>, + def_id: DefId, +) -> (&'tcx Steal>, &'tcx Steal>>) { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); if let hir::BodyOwnerKind::Const = tcx.hir().body_owner_kind(hir_id) { // Ensure that we compute the `mir_const_qualif` for constants at @@ -215,8 +218,9 @@ fn mir_validated(tcx: TyCtxt<'tcx>, def_id: DefId) -> (&'tcx Steal>, &qualify_and_promote_pass, &simplify::SimplifyCfg::new("qualify-consts"), ]); - let promoted = qualify_and_promote_pass.promoted.into_inner(); - (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted.unwrap_or_else(|| IndexVec::new()))) + let promoted = + qualify_and_promote_pass.promoted.into_inner().unwrap_or_else(|| IndexVec::new()); + (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) } fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index cb0ce77d5c014..fd5b6c2a32825 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -295,7 +295,12 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { new_temp } - fn promote_candidate(mut self, def_id: DefId, candidate: Candidate, next_promoted_id: usize) -> Option> { + fn promote_candidate( + mut self, + def_id: DefId, + candidate: Candidate, + next_promoted_id: usize, + ) -> Option> { let mut operand = { let promoted = &mut self.promoted; let promoted_id = Promoted::new(next_promoted_id); From 9fdf5b555181ee6438a9cb01bb38ae5a52049475 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Wed, 14 Aug 2019 08:16:06 -0400 Subject: [PATCH 120/618] Remove unnecessary Option --- src/librustc_mir/transform/mod.rs | 3 +-- src/librustc_mir/transform/qualify_consts.rs | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index f59ad6bae0298..c9bcdbe1bef50 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -218,8 +218,7 @@ fn mir_validated( &qualify_and_promote_pass, &simplify::SimplifyCfg::new("qualify-consts"), ]); - let promoted = - qualify_and_promote_pass.promoted.into_inner().unwrap_or_else(|| IndexVec::new()); + let promoted = qualify_and_promote_pass.promoted.into_inner(); (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 70a394ad98330..7f8ae88342934 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1572,13 +1572,13 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> (u8, &BitSet) { } pub struct QualifyAndPromoteConstants<'tcx> { - pub promoted: Cell>>>, + pub promoted: Cell>>, } impl<'tcx> Default for QualifyAndPromoteConstants<'tcx> { fn default() -> Self { QualifyAndPromoteConstants { - promoted: Cell::new(None), + promoted: Cell::new(IndexVec::new()), } } } @@ -1661,7 +1661,7 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { // Do the actual promotion, now that we know what's viable. self.promoted.set( - Some(promote_consts::promote_candidates(def_id, body, tcx, temps, candidates)) + promote_consts::promote_candidates(def_id, body, tcx, temps, candidates) ); } else { if !body.control_flow_destroyed.is_empty() { From e63b9920302e860b4f50968eb332f534d62b8055 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 15 Aug 2019 06:39:31 -0400 Subject: [PATCH 121/618] Resolve PR comments --- src/librustc_metadata/decoder.rs | 7 +- src/librustc_metadata/encoder.rs | 6 +- src/librustc_mir/borrow_check/nll/renumber.rs | 13 +- src/librustc_mir/shim.rs | 2 +- src/librustc_mir/transform/mod.rs | 153 +++++++----------- src/librustc_mir/transform/promote_consts.rs | 31 ++-- 6 files changed, 81 insertions(+), 131 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 2add8bf918398..5b9cb966af235 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -924,8 +924,11 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn maybe_get_promoted_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> - Option>> { + pub fn maybe_get_promoted_mir( + &self, + tcx: TyCtxt<'tcx>, + id: DefIndex, + ) -> Option>> { match self.is_proc_macro(id) { true => None, false => self.entry(id).promoted_mir.map(|promoted| promoted.decode((self, tcx)),) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0b8d2438752fa..1797d77461567 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1060,8 +1060,10 @@ impl EncodeContext<'tcx> { } } - fn encode_promoted_mir(&mut self, def_id: DefId) -> - Option>>> { + fn encode_promoted_mir( + &mut self, + def_id: DefId, + ) -> Option>>> { debug!("EncodeContext::encode_promoted_mir({:?})", def_id); if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { let promoted = self.tcx.promoted_mir(def_id); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index c6a5c6fdfd0f2..c479c38f30c7e 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -16,7 +16,11 @@ pub fn renumber_mir<'tcx>( debug!("renumber_mir: body.arg_count={:?}", body.arg_count); let mut visitor = NLLVisitor { infcx }; - visitor.visit_promoted(promoted); + + for body in promoted.iter_mut() { + visitor.visit_body(body); + } + visitor.visit_body(body); } @@ -47,13 +51,6 @@ impl<'a, 'tcx> NLLVisitor<'a, 'tcx> { { renumber_regions(self.infcx, value) } - - fn visit_promoted(&mut self, promoted: &mut IndexVec>) { - debug!("visiting promoted mir"); - for body in promoted.iter_mut() { - self.visit_body(body); - } - } } impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 9d31015f84558..aa83255bf62f4 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -112,7 +112,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx }; debug!("make_shim({:?}) = untransformed {:?}", instance, result); - run_passes(tcx, &mut result, instance, MirPhase::Const, &[ + run_passes(tcx, &mut result, instance, None, MirPhase::Const, &[ &add_moves_for_packed_drops::AddMovesForPackedDrops, &no_landing_pads::NoLandingPads, &remove_noop_landing_pads::RemoveNoopLandingPads, diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index c9bcdbe1bef50..ac291c2996d06 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -149,41 +149,38 @@ pub fn run_passes( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, instance: InstanceDef<'tcx>, + promoted: Option, mir_phase: MirPhase, passes: &[&dyn MirPass<'tcx>], ) { let phase_index = mir_phase.phase_index(); - let run_passes = |body: &mut Body<'tcx>, promoted| { - if body.phase >= mir_phase { - return; - } + if body.phase >= mir_phase { + return; + } - let source = MirSource { - instance, - promoted, - }; - let mut index = 0; - let mut run_pass = |pass: &dyn MirPass<'tcx>| { - let run_hooks = |body: &_, index, is_after| { - dump_mir::on_mir_pass(tcx, &format_args!("{:03}-{:03}", phase_index, index), - &pass.name(), source, body, is_after); - }; - run_hooks(body, index, false); - pass.run_pass(tcx, source, body); - run_hooks(body, index, true); - - index += 1; + let source = MirSource { + instance, + promoted, + }; + let mut index = 0; + let mut run_pass = |pass: &dyn MirPass<'tcx>| { + let run_hooks = |body: &_, index, is_after| { + dump_mir::on_mir_pass(tcx, &format_args!("{:03}-{:03}", phase_index, index), + &pass.name(), source, body, is_after); }; + run_hooks(body, index, false); + pass.run_pass(tcx, source, body); + run_hooks(body, index, true); - for pass in passes { - run_pass(*pass); - } - - body.phase = mir_phase; + index += 1; }; - run_passes(body, None); + for pass in passes { + run_pass(*pass); + } + + body.phase = mir_phase; } fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { @@ -191,7 +188,7 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { let _ = tcx.unsafety_check_result(def_id); let mut body = tcx.mir_built(def_id).steal(); - run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Const, &[ + run_passes(tcx, &mut body, InstanceDef::Item(def_id), None, MirPhase::Const, &[ // What we need to do constant evaluation. &simplify::SimplifyCfg::new("initial"), &rustc_peek::SanityCheck, @@ -213,7 +210,7 @@ fn mir_validated( let mut body = tcx.mir_const(def_id).steal(); let qualify_and_promote_pass = qualify_consts::QualifyAndPromoteConstants::default(); - run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Validated, &[ + run_passes(tcx, &mut body, InstanceDef::Item(def_id), None, MirPhase::Validated, &[ // What we need to run borrowck etc. &qualify_and_promote_pass, &simplify::SimplifyCfg::new("qualify-consts"), @@ -222,26 +219,13 @@ fn mir_validated( (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) } -fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { - if tcx.is_constructor(def_id) { - // There's no reason to run all of the MIR passes on constructors when - // we can just output the MIR we want directly. This also saves const - // qualification and borrow checking the trouble of special casing - // constructors. - return shim::build_adt_ctor(tcx, def_id); - } - - // (Mir-)Borrowck uses `mir_validated`, so we have to force it to - // execute before we can steal. - tcx.ensure().mir_borrowck(def_id); - - if tcx.use_ast_borrowck() { - tcx.ensure().borrowck(def_id); - } - - let (body, _) = tcx.mir_validated(def_id); - let mut body = body.steal(); - run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Optimized, &[ +fn run_optimization_passes<'tcx>( + tcx: TyCtxt<'tcx>, + body: &mut Body<'tcx>, + def_id: DefId, + promoted: Option, +) { + run_passes(tcx, body, InstanceDef::Item(def_id), promoted, MirPhase::Optimized, &[ // Remove all things only needed by analysis &no_landing_pads::NoLandingPads, &simplify_branches::SimplifyBranches::new("initial"), @@ -292,6 +276,28 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { &add_call_guards::CriticalCallEdges, &dump_mir::Marker("PreCodegen"), ]); +} + +fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { + if tcx.is_constructor(def_id) { + // There's no reason to run all of the MIR passes on constructors when + // we can just output the MIR we want directly. This also saves const + // qualification and borrow checking the trouble of special casing + // constructors. + return shim::build_adt_ctor(tcx, def_id); + } + + // (Mir-)Borrowck uses `mir_validated`, so we have to force it to + // execute before we can steal. + tcx.ensure().mir_borrowck(def_id); + + if tcx.use_ast_borrowck() { + tcx.ensure().borrowck(def_id); + } + + let (body, _) = tcx.mir_validated(def_id); + let mut body = body.steal(); + run_optimization_passes(tcx, &mut body, def_id, None); tcx.arena.alloc(body) } @@ -304,57 +310,8 @@ fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec Promoter<'a, 'tcx> { let mut operand = { let promoted = &mut self.promoted; let promoted_id = Promoted::new(next_promoted_id); - let mut promoted_place = |ty, substs, span| { + let tcx = self.tcx; + let mut promoted_place = |ty, span| { promoted.span = span; promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span); Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted_id, substs), + kind: + StaticKind::Promoted( + promoted_id, + InternalSubsts::identity_for_item(tcx, def_id), + ), ty, def_id, }), @@ -329,11 +334,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { Operand::Move(Place { base: mem::replace( &mut place.base, - promoted_place( - ty, - InternalSubsts::identity_for_item(self.tcx, def_id), - span, - ).base + promoted_place(ty, span).base ), projection: None, }) @@ -349,13 +350,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let span = statement.source_info.span; mem::replace( operand, - Operand::Copy( - promoted_place( - ty, - InternalSubsts::identity_for_item(self.tcx, def_id), - span, - ) - ) + Operand::Copy(promoted_place(ty, span)) ) } _ => bug!() @@ -367,12 +362,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { TerminatorKind::Call { ref mut args, .. } => { let ty = args[index].ty(local_decls, self.tcx); let span = terminator.source_info.span; - let operand = - Operand::Copy( - promoted_place( - ty, - InternalSubsts::identity_for_item(self.tcx, def_id), - span)); + let operand = Operand::Copy(promoted_place(ty, span)); mem::replace(&mut args[index], operand) } // We expected a `TerminatorKind::Call` for which we'd like to promote an @@ -472,6 +462,7 @@ pub fn promote_candidates<'tcx>( keep_original: false }; + //FIXME(oli-obk): having a `maybe_push()` method on `IndexVec` might be nice if let Some(promoted) = promoter.promote_candidate(def_id, candidate, promotions.len()) { promotions.push(promoted); } From 84556502e69e1741938610e4af5800fe0cee9975 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Fri, 16 Aug 2019 20:31:28 -0400 Subject: [PATCH 122/618] Handle statics in `Subst::subst()` by implementing `TypeFoldable` --- src/librustc/mir/mod.rs | 58 +++++++++++++++++++++++++-- src/librustc_codegen_ssa/mir/place.rs | 11 +---- src/librustc_mir/transform/inline.rs | 15 ------- 3 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 69e98583b191c..60efeaab97602 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1729,7 +1729,7 @@ pub enum PlaceBase<'tcx> { } /// We store the normalized type to avoid requiring normalization when reading MIR -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct Static<'tcx> { pub ty: Ty<'tcx>, pub kind: StaticKind<'tcx>, @@ -1737,7 +1737,7 @@ pub struct Static<'tcx> { } #[derive( - Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable, + Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable, )] pub enum StaticKind<'tcx> { Promoted(Promoted, SubstsRef<'tcx>), @@ -3221,13 +3221,63 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { Place { - base: self.base.clone(), + base: self.base.fold_with(folder), projection: self.projection.fold_with(folder), } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.projection.visit_with(visitor) + self.base.visit_with(visitor) || self.projection.visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable<'tcx> for PlaceBase<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + match self { + PlaceBase::Local(local) => PlaceBase::Local(local.fold_with(folder)), + PlaceBase::Static(static_) => PlaceBase::Static(static_.fold_with(folder)), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + match self { + PlaceBase::Local(local) => local.visit_with(visitor), + PlaceBase::Static(static_) => (**static_).visit_with(visitor), + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for Static<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + Static { + ty: self.ty.fold_with(folder), + kind: self.kind.fold_with(folder), + def_id: self.def_id, + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + let Static { ty, kind, def_id: _ } = self; + + ty.visit_with(visitor) || kind.visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable<'tcx> for StaticKind<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + match self { + StaticKind::Promoted(promoted, substs) => + StaticKind::Promoted(promoted.fold_with(folder), substs.fold_with(folder)), + StaticKind::Static => StaticKind::Static + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + match self { + StaticKind::Promoted(promoted, substs) => + promoted.visit_with(visitor) || substs.visit_with(visitor), + StaticKind::Static => { false } + } } } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index b08093c3a71eb..ac72928a89677 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -1,5 +1,4 @@ use rustc::ty::{self, Instance, Ty}; -use rustc::ty::subst::Subst; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::mir; use rustc::mir::tcx::PlaceTy; @@ -461,18 +460,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { projection: None, } => { let param_env = ty::ParamEnv::reveal_all(); - let instance = Instance::new(*def_id, substs.subst(bx.tcx(), self.instance.substs)); - debug!("instance: {:?}", instance); + let instance = Instance::new(*def_id, self.monomorphize(substs)); let cid = mir::interpret::GlobalId { instance: instance, promoted: Some(*promoted), }; - let mono_ty = tcx.subst_and_normalize_erasing_regions( - instance.substs, - param_env, - ty, - ); - let layout = cx.layout_of(mono_ty); + let layout = cx.layout_of(self.monomorphize(&ty)); match bx.tcx().const_eval(param_env.and(cid)) { Ok(val) => match val.val { mir::interpret::ConstValue::ByRef { alloc, offset } => { diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 533e08f5e1fd3..f31303c642faa 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -479,12 +479,10 @@ impl Inliner<'tcx> { args: &args, local_map, scope_map, - callsite, destination: dest, return_block, cleanup_block: cleanup, in_cleanup_block: false, - tcx: self.tcx, }; @@ -639,12 +637,10 @@ struct Integrator<'a, 'tcx> { args: &'a [Local], local_map: IndexVec, scope_map: IndexVec, - callsite: CallSite<'tcx>, destination: Place<'tcx>, return_block: BasicBlock, cleanup_block: Option, in_cleanup_block: bool, - tcx: TyCtxt<'tcx>, } impl<'a, 'tcx> Integrator<'a, 'tcx> { @@ -693,17 +689,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { // Return pointer; update the place itself *place = self.destination.clone(); }, - Place { - base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_, substs), - .. - }), - projection: None, - } => { - let adjusted_substs = substs.subst(self.tcx, self.callsite.substs); - debug!("replacing substs {:?} with {:?}", substs, adjusted_substs); - *substs = adjusted_substs; - }, _ => self.super_place(place, _ctxt, _location) } } From 5c45420bdad8d3bf950ff3c46e1856348a7ddc7b Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 4 Aug 2019 22:23:32 -0400 Subject: [PATCH 123/618] Changed tests --- src/test/incremental/hashes/for_loops.rs | 2 +- src/test/ui/consts/array-literal-index-oob.rs | 1 - .../ui/consts/array-literal-index-oob.stderr | 8 +---- .../ui/consts/const-eval/issue-43197.stderr | 8 ++--- .../ui/consts/const-eval/promoted_errors.rs | 6 ++-- .../consts/const-eval/promoted_errors.stderr | 30 ++++++------------- 6 files changed, 17 insertions(+), 38 deletions(-) diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs index ca45d36a6b0e4..5d0b8b867b22f 100644 --- a/src/test/incremental/hashes/for_loops.rs +++ b/src/test/incremental/hashes/for_loops.rs @@ -94,7 +94,7 @@ pub fn change_iterable() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_iterable() { let mut _x = 0; diff --git a/src/test/ui/consts/array-literal-index-oob.rs b/src/test/ui/consts/array-literal-index-oob.rs index 76013c77de0c2..492182921ba34 100644 --- a/src/test/ui/consts/array-literal-index-oob.rs +++ b/src/test/ui/consts/array-literal-index-oob.rs @@ -2,5 +2,4 @@ fn main() { &{[1, 2, 3][4]}; //~^ ERROR index out of bounds //~| ERROR reaching this expression at runtime will panic or abort - //~| ERROR this expression will panic at runtime } diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr index 18a09fdda7be4..0ddc2a0e79cd3 100644 --- a/src/test/ui/consts/array-literal-index-oob.stderr +++ b/src/test/ui/consts/array-literal-index-oob.stderr @@ -6,12 +6,6 @@ LL | &{[1, 2, 3][4]}; | = note: `#[deny(const_err)]` on by default -error: this expression will panic at runtime - --> $DIR/array-literal-index-oob.rs:2:5 - | -LL | &{[1, 2, 3][4]}; - | ^^^^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 4 - error: reaching this expression at runtime will panic or abort --> $DIR/array-literal-index-oob.rs:2:7 | @@ -20,5 +14,5 @@ LL | &{[1, 2, 3][4]}; | | | index out of bounds: the len is 3 but the index is 4 -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr index 478e453fe0834..d971d825f278c 100644 --- a/src/test/ui/consts/const-eval/issue-43197.stderr +++ b/src/test/ui/consts/const-eval/issue-43197.stderr @@ -21,16 +21,16 @@ LL | const Y: u32 = foo(0-1); | attempt to subtract with overflow error[E0080]: evaluation of constant expression failed - --> $DIR/issue-43197.rs:12:26 + --> $DIR/issue-43197.rs:12:23 | LL | println!("{} {}", X, Y); - | ^ referenced constant has errors + | ^ referenced constant has errors error[E0080]: evaluation of constant expression failed - --> $DIR/issue-43197.rs:12:23 + --> $DIR/issue-43197.rs:12:26 | LL | println!("{} {}", X, Y); - | ^ referenced constant has errors + | ^ referenced constant has errors error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index fa8859cbb3bb6..cd989731452b3 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -7,15 +7,13 @@ fn main() { let _x = 0u32 - 1; //~^ ERROR this expression will panic at runtime [const_err] println!("{}", 1/(1-1)); - //~^ ERROR this expression will panic at runtime [const_err] - //~| ERROR attempt to divide by zero [const_err] + //~^ ERROR attempt to divide by zero [const_err] //~| ERROR reaching this expression at runtime will panic or abort [const_err] let _x = 1/(1-1); //~^ ERROR const_err //~| ERROR const_err println!("{}", 1/(false as u32)); - //~^ ERROR this expression will panic at runtime [const_err] - //~| ERROR attempt to divide by zero [const_err] + //~^ ERROR attempt to divide by zero [const_err] //~| ERROR reaching this expression at runtime will panic or abort [const_err] let _x = 1/(false as u32); //~^ ERROR const_err diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr index 12407accf096f..40d5c73e86679 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.stderr @@ -16,59 +16,47 @@ error: attempt to divide by zero LL | println!("{}", 1/(1-1)); | ^^^^^^^ -error: this expression will panic at runtime +error: reaching this expression at runtime will panic or abort --> $DIR/promoted_errors.rs:9:20 | LL | println!("{}", 1/(1-1)); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:13:14 + --> $DIR/promoted_errors.rs:12:14 | LL | let _x = 1/(1-1); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:13:14 + --> $DIR/promoted_errors.rs:12:14 | LL | let _x = 1/(1-1); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:16:20 + --> $DIR/promoted_errors.rs:15:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:16:20 +error: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors.rs:15:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:20:14 + --> $DIR/promoted_errors.rs:18:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:20:14 + --> $DIR/promoted_errors.rs:18:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ attempt to divide by zero -error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:16:20 - | -LL | println!("{}", 1/(false as u32)); - | ^^^^^^^^^^^^^^^^ attempt to divide by zero - -error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:9:20 - | -LL | println!("{}", 1/(1-1)); - | ^^^^^^^ attempt to divide by zero - -error: aborting due to 11 previous errors +error: aborting due to 9 previous errors From a078a34f057a8a6a779bf8cb0c12dcbd4ba6c0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 22 Aug 2019 13:04:32 +0200 Subject: [PATCH 124/618] Fix a typo. --- src/liballoc/collections/vec_deque.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 7315963cc8b1d..6b5e48597e4dd 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1810,7 +1810,7 @@ impl VecDeque { other } - /// Moves all the elements of `other` into `Self`, leaving `other` empty. + /// Moves all the elements of `other` into `self`, leaving `other` empty. /// /// # Panics /// From 4ee6ee0daa13d53564f64932fa1e2ad37be7d879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 22 Aug 2019 13:06:39 +0200 Subject: [PATCH 125/618] Fix formatting. --- src/liballoc/collections/vec_deque.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 6b5e48597e4dd..a4a0fbb194dd4 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1847,7 +1847,7 @@ impl VecDeque { /// /// let mut buf = VecDeque::new(); /// buf.extend(1..5); - /// buf.retain(|&x| x%2 == 0); + /// buf.retain(|&x| x % 2 == 0); /// assert_eq!(buf, [2, 4]); /// ``` /// From 7e13679cdedab8e39275c3138e0bfa795541ab67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 22 Aug 2019 13:12:31 +0200 Subject: [PATCH 126/618] Remove redundant `mut`. --- src/libstd/ffi/os_str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 1f384cbada3da..fbdb577a7f060 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -191,7 +191,7 @@ impl OsString { /// ``` /// use std::ffi::OsString; /// - /// let mut os_string = OsString::with_capacity(10); + /// let os_string = OsString::with_capacity(10); /// let capacity = os_string.capacity(); /// /// // This push is done without reallocating From 49dce2935f94426d4464a82b7d2e19ea0ba79460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 22 Aug 2019 13:14:42 +0200 Subject: [PATCH 127/618] Fix punctuation. --- src/libstd/ffi/os_str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index fbdb577a7f060..d0e35cce6411b 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -616,7 +616,7 @@ impl OsStr { /// Note that this does **not** return the number of bytes in the string in /// OS string form. /// - /// The length returned is that of the underlying storage used by `OsStr`; + /// The length returned is that of the underlying storage used by `OsStr`. /// As discussed in the [`OsString`] introduction, [`OsString`] and `OsStr` /// store strings in a form best suited for cheap inter-conversion between /// native-platform and Rust string forms, which may differ significantly From 3b04e91d275e9c0983814c3b7acc79f52cff3601 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 22 Aug 2019 14:27:51 +0200 Subject: [PATCH 128/618] Change code formatting for readability. --- src/libcore/num/f32.rs | 2 +- src/libcore/num/f64.rs | 2 +- src/libstd/f32.rs | 18 +++++++++--------- src/libstd/f64.rs | 18 +++++++++--------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 8ff78166a9f2d..22e7573eca65b 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -315,7 +315,7 @@ impl f32 { /// use std::f32; /// /// let x = 2.0_f32; - /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// let abs_difference = (x.recip() - (1.0 / x)).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index d45c04f45afc2..bbe1d04078060 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -327,7 +327,7 @@ impl f64 { /// /// ``` /// let x = 2.0_f64; - /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// let abs_difference = (x.recip() - (1.0 / x)).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index f649170c40372..6c71a0428ef09 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -236,7 +236,7 @@ impl f32 { /// let b = 60.0_f32; /// /// // 100.0 - /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); + /// let abs_difference = (m.mul_add(x, b) - ((m * x) + b)).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` @@ -318,7 +318,7 @@ impl f32 { /// use std::f32; /// /// let x = 2.0_f32; - /// let abs_difference = (x.powi(2) - x*x).abs(); + /// let abs_difference = (x.powi(2) - (x * x)).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` @@ -336,7 +336,7 @@ impl f32 { /// use std::f32; /// /// let x = 2.0_f32; - /// let abs_difference = (x.powf(2.0) - x*x).abs(); + /// let abs_difference = (x.powf(2.0) - (x * x)).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` @@ -623,7 +623,7 @@ impl f32 { /// ``` /// use std::f32; /// - /// let x = 2.0*f32::consts::PI; + /// let x = 2.0 * f32::consts::PI; /// /// let abs_difference = (x.cos() - 1.0).abs(); /// @@ -745,8 +745,8 @@ impl f32 { /// let x2 = -3.0f32; /// let y2 = 3.0f32; /// - /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); - /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); + /// let abs_difference_1 = (y1.atan2(x1) - (-pi / 4.0)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * pi / 4.0)).abs(); /// /// assert!(abs_difference_1 <= f32::EPSILON); /// assert!(abs_difference_2 <= f32::EPSILON); @@ -834,7 +834,7 @@ impl f32 { /// /// let f = x.sinh(); /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` - /// let g = (e*e - 1.0)/(2.0*e); + /// let g = ((e * e) - 1.0) / (2.0 * e); /// let abs_difference = (f - g).abs(); /// /// assert!(abs_difference <= f32::EPSILON); @@ -856,7 +856,7 @@ impl f32 { /// let x = 1.0f32; /// let f = x.cosh(); /// // Solving cosh() at 1 gives this result - /// let g = (e*e + 1.0)/(2.0*e); + /// let g = ((e * e) + 1.0) / (2.0 * e); /// let abs_difference = (f - g).abs(); /// /// // Same result @@ -880,7 +880,7 @@ impl f32 { /// /// let f = x.tanh(); /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` - /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); + /// let g = (1.0 - e.powi(-2)) / (1.0 + e.powi(-2)); /// let abs_difference = (f - g).abs(); /// /// assert!(abs_difference <= f32::EPSILON); diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index f61630997dcdb..43c2debe5ee38 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -212,7 +212,7 @@ impl f64 { /// let b = 60.0_f64; /// /// // 100.0 - /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); + /// let abs_difference = (m.mul_add(x, b) - ((m * x) + b)).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -291,7 +291,7 @@ impl f64 { /// /// ``` /// let x = 2.0_f64; - /// let abs_difference = (x.powi(2) - x*x).abs(); + /// let abs_difference = (x.powi(2) - (x * x)).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -307,7 +307,7 @@ impl f64 { /// /// ``` /// let x = 2.0_f64; - /// let abs_difference = (x.powf(2.0) - x*x).abs(); + /// let abs_difference = (x.powf(2.0) - (x * x)).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -556,7 +556,7 @@ impl f64 { /// ``` /// use std::f64; /// - /// let x = 2.0*f64::consts::PI; + /// let x = 2.0 * f64::consts::PI; /// /// let abs_difference = (x.cos() - 1.0).abs(); /// @@ -672,8 +672,8 @@ impl f64 { /// let x2 = -3.0_f64; /// let y2 = 3.0_f64; /// - /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); - /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); + /// let abs_difference_1 = (y1.atan2(x1) - (-pi / 4.0)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * pi / 4.0)).abs(); /// /// assert!(abs_difference_1 < 1e-10); /// assert!(abs_difference_2 < 1e-10); @@ -759,7 +759,7 @@ impl f64 { /// /// let f = x.sinh(); /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` - /// let g = (e*e - 1.0)/(2.0*e); + /// let g = ((e * e) - 1.0) / (2.0 * e); /// let abs_difference = (f - g).abs(); /// /// assert!(abs_difference < 1e-10); @@ -781,7 +781,7 @@ impl f64 { /// let x = 1.0_f64; /// let f = x.cosh(); /// // Solving cosh() at 1 gives this result - /// let g = (e*e + 1.0)/(2.0*e); + /// let g = ((e * e) + 1.0) / (2.0 * e); /// let abs_difference = (f - g).abs(); /// /// // Same result @@ -805,7 +805,7 @@ impl f64 { /// /// let f = x.tanh(); /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` - /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); + /// let g = (1.0 - e.powi(-2)) / (1.0 + e.powi(-2)); /// let abs_difference = (f - g).abs(); /// /// assert!(abs_difference < 1.0e-10); From cdedd268d2d1f6e9fb376d368bb40564441474cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 22 Aug 2019 14:59:31 +0200 Subject: [PATCH 129/618] Make use of existing constants. f32::consts::PI / 2.0 -> f32::consts::FRAC_PI_2 f32::consts::PI / 4.0 -> f32::consts::FRAC_PI_4 f64::consts::PI / 2.0 -> f64::consts::FRAC_PI_2 f64::consts::PI / 4.0 -> f64::consts::FRAC_PI_4 --- src/libstd/f32.rs | 19 +++++++++---------- src/libstd/f64.rs | 19 +++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 6c71a0428ef09..e55afc2344f79 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -600,7 +600,7 @@ impl f32 { /// ``` /// use std::f32; /// - /// let x = f32::consts::PI/2.0; + /// let x = f32::consts::FRAC_PI_2; /// /// let abs_difference = (x.sin() - 1.0).abs(); /// @@ -646,7 +646,7 @@ impl f32 { /// ``` /// use std::f32; /// - /// let x = f32::consts::PI / 4.0; + /// let x = f32::consts::FRAC_PI_4; /// let abs_difference = (x.tan() - 1.0).abs(); /// /// assert!(abs_difference <= f32::EPSILON); @@ -666,10 +666,10 @@ impl f32 { /// ``` /// use std::f32; /// - /// let f = f32::consts::PI / 2.0; + /// let f = f32::consts::FRAC_PI_2; /// /// // asin(sin(pi/2)) - /// let abs_difference = (f.sin().asin() - f32::consts::PI / 2.0).abs(); + /// let abs_difference = (f.sin().asin() - f32::consts::FRAC_PI_2).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` @@ -688,10 +688,10 @@ impl f32 { /// ``` /// use std::f32; /// - /// let f = f32::consts::PI / 4.0; + /// let f = f32::consts::FRAC_PI_4; /// /// // acos(cos(pi/4)) - /// let abs_difference = (f.cos().acos() - f32::consts::PI / 4.0).abs(); + /// let abs_difference = (f.cos().acos() - f32::consts::FRAC_PI_4).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` @@ -734,7 +734,6 @@ impl f32 { /// ``` /// use std::f32; /// - /// let pi = f32::consts::PI; /// // Positive angles measured counter-clockwise /// // from positive x axis /// // -pi/4 radians (45 deg clockwise) @@ -745,8 +744,8 @@ impl f32 { /// let x2 = -3.0f32; /// let y2 = 3.0f32; /// - /// let abs_difference_1 = (y1.atan2(x1) - (-pi / 4.0)).abs(); - /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * pi / 4.0)).abs(); + /// let abs_difference_1 = (y1.atan2(x1) - (-f32::consts::FRAC_PI_4)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * f32::consts::FRAC_PI_4)).abs(); /// /// assert!(abs_difference_1 <= f32::EPSILON); /// assert!(abs_difference_2 <= f32::EPSILON); @@ -765,7 +764,7 @@ impl f32 { /// ``` /// use std::f32; /// - /// let x = f32::consts::PI/4.0; + /// let x = f32::consts::FRAC_PI_4; /// let f = x.sin_cos(); /// /// let abs_difference_0 = (f.0 - x.sin()).abs(); diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 43c2debe5ee38..b357102630091 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -537,7 +537,7 @@ impl f64 { /// ``` /// use std::f64; /// - /// let x = f64::consts::PI/2.0; + /// let x = f64::consts::FRAC_PI_2; /// /// let abs_difference = (x.sin() - 1.0).abs(); /// @@ -575,7 +575,7 @@ impl f64 { /// ``` /// use std::f64; /// - /// let x = f64::consts::PI/4.0; + /// let x = f64::consts::FRAC_PI_4; /// let abs_difference = (x.tan() - 1.0).abs(); /// /// assert!(abs_difference < 1e-14); @@ -595,10 +595,10 @@ impl f64 { /// ``` /// use std::f64; /// - /// let f = f64::consts::PI / 2.0; + /// let f = f64::consts::FRAC_PI_2; /// /// // asin(sin(pi/2)) - /// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs(); + /// let abs_difference = (f.sin().asin() - f64::consts::FRAC_PI_2).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -617,10 +617,10 @@ impl f64 { /// ``` /// use std::f64; /// - /// let f = f64::consts::PI / 4.0; + /// let f = f64::consts::FRAC_PI_4; /// /// // acos(cos(pi/4)) - /// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs(); + /// let abs_difference = (f.cos().acos() - f64::consts::FRAC_PI_4).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -661,7 +661,6 @@ impl f64 { /// ``` /// use std::f64; /// - /// let pi = f64::consts::PI; /// // Positive angles measured counter-clockwise /// // from positive x axis /// // -pi/4 radians (45 deg clockwise) @@ -672,8 +671,8 @@ impl f64 { /// let x2 = -3.0_f64; /// let y2 = 3.0_f64; /// - /// let abs_difference_1 = (y1.atan2(x1) - (-pi / 4.0)).abs(); - /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * pi / 4.0)).abs(); + /// let abs_difference_1 = (y1.atan2(x1) - (-f64::consts::FRAC_PI_4)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * f64::consts::FRAC_PI_4)).abs(); /// /// assert!(abs_difference_1 < 1e-10); /// assert!(abs_difference_2 < 1e-10); @@ -692,7 +691,7 @@ impl f64 { /// ``` /// use std::f64; /// - /// let x = f64::consts::PI/4.0; + /// let x = f64::consts::FRAC_PI_4; /// let f = x.sin_cos(); /// /// let abs_difference_0 = (f.0 - x.sin()).abs(); From eae5d77995488ffc316a7ff8344c4eaa81d67932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 22 Aug 2019 15:09:03 +0200 Subject: [PATCH 130/618] Change variables names to be more consistent. Changed all instances of `c_str` into `cstr` in the documentation examples. This is also consistent with the module source code. --- src/libstd/ffi/c_str.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 512839a12c0e4..65f4e0cafe09e 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -572,8 +572,8 @@ impl CString { /// use std::ffi::{CString, CStr}; /// /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); - /// let c_str = c_string.as_c_str(); - /// assert_eq!(c_str, + /// let cstr = c_string.as_c_str(); + /// assert_eq!(cstr, /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed")); /// ``` #[inline] @@ -994,8 +994,8 @@ impl CStr { /// ``` /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"hello"); - /// assert!(c_str.is_err()); + /// let cstr = CStr::from_bytes_with_nul(b"hello"); + /// assert!(cstr.is_err()); /// ``` /// /// Creating a `CStr` with an interior nul byte is an error: @@ -1003,8 +1003,8 @@ impl CStr { /// ``` /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"he\0llo\0"); - /// assert!(c_str.is_err()); + /// let cstr = CStr::from_bytes_with_nul(b"he\0llo\0"); + /// assert!(cstr.is_err()); /// ``` #[stable(feature = "cstr_from_bytes", since = "1.10.0")] pub fn from_bytes_with_nul(bytes: &[u8]) @@ -1111,8 +1111,8 @@ impl CStr { /// ``` /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); - /// assert_eq!(c_str.to_bytes(), b"foo"); + /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + /// assert_eq!(cstr.to_bytes(), b"foo"); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -1137,8 +1137,8 @@ impl CStr { /// ``` /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); - /// assert_eq!(c_str.to_bytes_with_nul(), b"foo\0"); + /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + /// assert_eq!(cstr.to_bytes_with_nul(), b"foo\0"); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -1164,8 +1164,8 @@ impl CStr { /// ``` /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); - /// assert_eq!(c_str.to_str(), Ok("foo")); + /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + /// assert_eq!(cstr.to_str(), Ok("foo")); /// ``` #[stable(feature = "cstr_to_str", since = "1.4.0")] pub fn to_str(&self) -> Result<&str, str::Utf8Error> { @@ -1205,9 +1205,9 @@ impl CStr { /// use std::borrow::Cow; /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"Hello World\0") + /// let cstr = CStr::from_bytes_with_nul(b"Hello World\0") /// .expect("CStr::from_bytes_with_nul failed"); - /// assert_eq!(c_str.to_string_lossy(), Cow::Borrowed("Hello World")); + /// assert_eq!(cstr.to_string_lossy(), Cow::Borrowed("Hello World")); /// ``` /// /// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8: @@ -1216,10 +1216,10 @@ impl CStr { /// use std::borrow::Cow; /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0") + /// let cstr = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0") /// .expect("CStr::from_bytes_with_nul failed"); /// assert_eq!( - /// c_str.to_string_lossy(), + /// cstr.to_string_lossy(), /// Cow::Owned(String::from("Hello �World")) as Cow<'_, str> /// ); /// ``` From 2f790ee5d210f79219dad4ef129285fa2bdd88a4 Mon Sep 17 00:00:00 2001 From: Jeremy Stucki Date: Thu, 22 Aug 2019 16:47:42 +0200 Subject: [PATCH 131/618] Update .mailmap --- .mailmap | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index 98902a7212099..72c76006f7cb9 100644 --- a/.mailmap +++ b/.mailmap @@ -117,7 +117,9 @@ Jason Toffaletti Jason Toffaletti Jauhien Piatlicki Jauhien Piatlicki Jay True Jeremy Letang -Jeremy Stucki +Jeremy Stucki +Jeremy Stucki +Jeremy Stucki Jethro Beekman Jihyun Yu Jihyun Yu jihyun From 2d438d6993017ae2b991cd92ea243112e2357c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 22 Aug 2019 10:15:57 -0700 Subject: [PATCH 132/618] Correctly suggest adding bounds to `impl Trait` argument --- src/librustc_typeck/check/method/suggest.rs | 14 +++++++++++-- ...ait-with-missing-trait-bounds-in-arg.fixed | 20 +++++++++++++++++++ ...-trait-with-missing-trait-bounds-in-arg.rs | 20 +++++++++++++++++++ ...it-with-missing-trait-bounds-in-arg.stderr | 15 ++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed create mode 100644 src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs create mode 100644 src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 53024d97c3b13..9f4fed23697ab 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -743,8 +743,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We do this to avoid suggesting code that ends up as `T: FooBar`, // instead we suggest `T: Foo + Bar` in that case. let mut has_bounds = false; + let mut impl_trait = false; if let Node::GenericParam(ref param) = hir.get(id) { - has_bounds = !param.bounds.is_empty(); + match param.kind { + hir::GenericParamKind::Type { synthetic: Some(_), .. } => { + impl_trait = true; // #63706 + has_bounds = param.bounds.len() > 1; + } + _ => { + has_bounds = !param.bounds.is_empty(); + } + } } let sp = hir.span(id); // `sp` only covers `T`, change it so that it covers @@ -765,8 +774,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sp, &msg[..], candidates.iter().map(|t| format!( - "{}: {}{}", + "{}{} {}{}", param, + if impl_trait { " +" } else { ":" }, self.tcx.def_path_str(t.def_id), if has_bounds { " +"} else { "" }, )), diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed new file mode 100644 index 0000000000000..5109511f95a6b --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +trait Foo {} + +trait Bar { + fn hello(&self) {} +} + +struct S; + +impl Foo for S {} +impl Bar for S {} + +fn test(foo: impl Foo + Bar) { + foo.hello(); //~ ERROR E0599 +} + +fn main() { + test(S); +} diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs new file mode 100644 index 0000000000000..cd05b77386192 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs @@ -0,0 +1,20 @@ +// run-rustfix + +trait Foo {} + +trait Bar { + fn hello(&self) {} +} + +struct S; + +impl Foo for S {} +impl Bar for S {} + +fn test(foo: impl Foo) { + foo.hello(); //~ ERROR E0599 +} + +fn main() { + test(S); +} diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr new file mode 100644 index 0000000000000..48c2503e8eb32 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `hello` found for type `impl Foo` in the current scope + --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:15:9 + | +LL | foo.hello(); + | ^^^^^ + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `hello`, perhaps you need to restrict type parameter `impl Foo` with it: + | +LL | fn test(foo: impl Foo + Bar) { + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From d9f3258186cc221b41d2d869671d47fd4b716bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 22 Aug 2019 19:27:16 +0200 Subject: [PATCH 133/618] Fix for 7e13679. --- src/libstd/ffi/os_str.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index d0e35cce6411b..6cf062d4f30c0 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -191,7 +191,7 @@ impl OsString { /// ``` /// use std::ffi::OsString; /// - /// let os_string = OsString::with_capacity(10); + /// let mut os_string = OsString::with_capacity(10); /// let capacity = os_string.capacity(); /// /// // This push is done without reallocating @@ -233,7 +233,7 @@ impl OsString { /// ``` /// use std::ffi::OsString; /// - /// let mut os_string = OsString::with_capacity(10); + /// let os_string = OsString::with_capacity(10); /// assert!(os_string.capacity() >= 10); /// ``` #[stable(feature = "osstring_simple_functions", since = "1.9.0")] From 03507a1688e4ce5c3bf99973addd75beb1bc9ec0 Mon Sep 17 00:00:00 2001 From: Sebastian Martinez <7912302+sebastinez@users.noreply.github.com> Date: Thu, 22 Aug 2019 16:16:22 -0300 Subject: [PATCH 134/618] Update occurences of as_slice Update occurences of as_slice to as_str --- src/libstd/primitive_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index d9a3da66a6786..45816ffd229f0 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -655,7 +655,7 @@ mod prim_slice { } /// [`len`]: #method.len /// /// Note: This example shows the internals of `&str`. `unsafe` should not be -/// used to get a string slice under normal circumstances. Use `as_slice` +/// used to get a string slice under normal circumstances. Use `as_str` /// instead. #[stable(feature = "rust1", since = "1.0.0")] mod prim_str { } From 1acb53753be395f6b5bd880617ddceaa4bfadcfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 22 Aug 2019 10:38:09 -0700 Subject: [PATCH 135/618] Do not suggest `.try_into()` on `i32::from(x)` --- src/librustc_typeck/check/demand.rs | 24 +++++++++++++++++++ .../mismatched-types-numeric-from.rs | 3 +++ .../mismatched-types-numeric-from.stderr | 9 +++++++ 3 files changed, 36 insertions(+) create mode 100644 src/test/ui/suggestions/mismatched-types-numeric-from.rs create mode 100644 src/test/ui/suggestions/mismatched-types-numeric-from.stderr diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index de5ba8bc8eb42..0efc433341c1f 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -587,6 +587,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } } + if let hir::ExprKind::Call(path, args) = &expr.node { + if let ( + hir::ExprKind::Path(hir::QPath::TypeRelative(base_ty, path_segment)), + 1, + ) = (&path.node, args.len()) { + // `expr` is a conversion like `u32::from(val)`, do not suggest anything (#63697). + if let ( + hir::TyKind::Path(hir::QPath::Resolved(None, base_ty_path)), + sym::from, + ) = (&base_ty.node, path_segment.ident.name) { + if let Some(ident) = &base_ty_path.segments.iter().map(|s| s.ident).next() { + match ident.name { + sym::i128 | sym::i64 | sym::i32 | sym::i16 | sym::i8 | + sym::u128 | sym::u64 | sym::u32 | sym::u16 | sym::u8 | + sym::isize | sym::usize + if base_ty_path.segments.len() == 1 => { + return false; + } + _ => {} + } + } + } + } + } let msg = format!("you can convert an `{}` to `{}`", checked_ty, expected_ty); let cast_msg = format!("you can cast an `{} to `{}`", checked_ty, expected_ty); diff --git a/src/test/ui/suggestions/mismatched-types-numeric-from.rs b/src/test/ui/suggestions/mismatched-types-numeric-from.rs new file mode 100644 index 0000000000000..56549da9c7358 --- /dev/null +++ b/src/test/ui/suggestions/mismatched-types-numeric-from.rs @@ -0,0 +1,3 @@ +fn main() { + let _: u32 = i32::from(0_u8); //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/mismatched-types-numeric-from.stderr b/src/test/ui/suggestions/mismatched-types-numeric-from.stderr new file mode 100644 index 0000000000000..223b6747322c1 --- /dev/null +++ b/src/test/ui/suggestions/mismatched-types-numeric-from.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/mismatched-types-numeric-from.rs:2:18 + | +LL | let _: u32 = i32::from(0_u8); + | ^^^^^^^^^^^^^^^ expected u32, found i32 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 98bd60c2814e5d90c9eddcd25ea571ad032a0c74 Mon Sep 17 00:00:00 2001 From: Naja Melan Date: Thu, 22 Aug 2019 22:39:21 +0000 Subject: [PATCH 136/618] Update single-use-lifetimes When using this, rustc emits a warning that the lint has been renamed (to having an 's' at the end) --- src/doc/rustc/src/lints/listing/allowed-by-default.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/lints/listing/allowed-by-default.md b/src/doc/rustc/src/lints/listing/allowed-by-default.md index a6e4e166d7bc6..d3dfc3197e2f6 100644 --- a/src/doc/rustc/src/lints/listing/allowed-by-default.md +++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md @@ -208,7 +208,7 @@ error: missing documentation for a function To fix the lint, add documentation to all items. -## single-use-lifetime +## single-use-lifetimes This lint detects lifetimes that are only used once. Some example code that triggers this lint: From 0fb01d219c7b7de142ad4097dd1e5cf708e7a27f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 21 Aug 2019 21:28:22 +0300 Subject: [PATCH 137/618] Audit uses of `apply_mark` in built-in macros Replace them with equivalents of `Span::{def_site,call_site}` from proc macro API. The new API is much less error prone and doesn't rely on macros having default transparency. --- src/libsyntax/ext/base.rs | 30 ++++++++++++++++++------ src/libsyntax/ext/expand.rs | 1 - src/libsyntax/ext/proc_macro_server.rs | 11 ++------- src/libsyntax_ext/asm.rs | 2 +- src/libsyntax_ext/assert.rs | 2 +- src/libsyntax_ext/cfg.rs | 2 +- src/libsyntax_ext/concat.rs | 2 +- src/libsyntax_ext/concat_idents.rs | 2 +- src/libsyntax_ext/deriving/clone.rs | 2 +- src/libsyntax_ext/deriving/cmp/eq.rs | 2 +- src/libsyntax_ext/deriving/debug.rs | 2 +- src/libsyntax_ext/deriving/generic/ty.rs | 2 +- src/libsyntax_ext/deriving/mod.rs | 5 +++- src/libsyntax_ext/env.rs | 2 +- src/libsyntax_ext/format.rs | 11 ++++----- src/libsyntax_ext/global_allocator.rs | 3 +-- src/libsyntax_ext/global_asm.rs | 2 +- src/libsyntax_ext/test.rs | 6 ++--- src/libsyntax_pos/lib.rs | 8 +++++++ 19 files changed, 56 insertions(+), 41 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 075e6a8001336..004ae1cf96541 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -3,7 +3,7 @@ use crate::attr::{HasAttrs, Stability, Deprecation}; use crate::source_map::SourceMap; use crate::edition::Edition; use crate::ext::expand::{self, AstFragment, Invocation}; -use crate::ext::hygiene::{ExpnId, SyntaxContext, Transparency}; +use crate::ext::hygiene::{ExpnId, Transparency}; use crate::mut_visit::{self, MutVisitor}; use crate::parse::{self, parser, DirectoryOwnership}; use crate::parse::token; @@ -760,23 +760,39 @@ impl<'a> ExtCtxt<'a> { pub fn call_site(&self) -> Span { self.current_expansion.id.expn_data().call_site } - pub fn backtrace(&self) -> SyntaxContext { - SyntaxContext::root().apply_mark(self.current_expansion.id) + + /// Equivalent of `Span::def_site` from the proc macro API, + /// except that the location is taken from the span passed as an argument. + pub fn with_def_site_ctxt(&self, span: Span) -> Span { + span.with_ctxt_from_mark(self.current_expansion.id, Transparency::Opaque) + } + + /// Equivalent of `Span::call_site` from the proc macro API, + /// except that the location is taken from the span passed as an argument. + pub fn with_call_site_ctxt(&self, span: Span) -> Span { + span.with_ctxt_from_mark(self.current_expansion.id, Transparency::Transparent) + } + + /// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items). + /// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably), + /// or with `with_call_site_ctxt` (where necessary). + pub fn with_legacy_ctxt(&self, span: Span) -> Span { + span.with_ctxt_from_mark(self.current_expansion.id, Transparency::SemiTransparent) } /// Returns span for the macro which originally caused the current expansion to happen. /// /// Stops backtracing at include! boundary. pub fn expansion_cause(&self) -> Option { - let mut ctxt = self.backtrace(); + let mut expn_id = self.current_expansion.id; let mut last_macro = None; loop { - let expn_data = ctxt.outer_expn_data(); + let expn_data = expn_id.expn_data(); // Stop going up the backtrace once include! is encountered if expn_data.is_root() || expn_data.kind.descr() == sym::include { break; } - ctxt = expn_data.call_site.ctxt(); + expn_id = expn_data.call_site.ctxt().outer_expn(); last_macro = Some(expn_data.call_site); } last_macro @@ -865,7 +881,7 @@ impl<'a> ExtCtxt<'a> { ast::Ident::from_str(st) } pub fn std_path(&self, components: &[Symbol]) -> Vec { - let def_site = DUMMY_SP.apply_mark(self.current_expansion.id); + let def_site = self.with_def_site_ctxt(DUMMY_SP); iter::once(Ident::new(kw::DollarCrate, def_site)) .chain(components.iter().map(|&s| Ident::with_dummy_span(s))) .collect() diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 72f2c1375e7a2..4965cb097dbee 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -565,7 +565,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { return fragment_kind.dummy(span); } let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span, path }; - let span = span.with_ctxt(self.cx.backtrace()); let items = expander.expand(self.cx, span, &meta, item); fragment_kind.expect_from_annotatables(items) } diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs index 1619fa6994198..b1bbd2aaac971 100644 --- a/src/libsyntax/ext/proc_macro_server.rs +++ b/src/libsyntax/ext/proc_macro_server.rs @@ -7,7 +7,6 @@ use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint} use errors::{Diagnostic, DiagnosticBuilder}; use rustc_data_structures::sync::Lrc; use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span}; -use syntax_pos::hygiene::{SyntaxContext, Transparency}; use syntax_pos::symbol::{kw, sym, Symbol}; use proc_macro::{Delimiter, Level, LineColumn, Spacing}; @@ -363,16 +362,10 @@ impl<'a> Rustc<'a> { pub fn new(cx: &'a ExtCtxt<'_>) -> Self { // No way to determine def location for a proc macro right now, so use call location. let location = cx.current_expansion.id.expn_data().call_site; - let to_span = |transparency| { - location.with_ctxt( - SyntaxContext::root() - .apply_mark_with_transparency(cx.current_expansion.id, transparency), - ) - }; Rustc { sess: cx.parse_sess, - def_site: to_span(Transparency::Opaque), - call_site: to_span(Transparency::Transparent), + def_site: cx.with_def_site_ctxt(location), + call_site: cx.with_call_site_ctxt(location), } } diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 644a44f1989db..28f907441d872 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -63,7 +63,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, MacEager::expr(P(ast::Expr { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::InlineAsm(P(inline_asm)), - span: sp.with_ctxt(cx.backtrace()), + span: cx.with_legacy_ctxt(sp), attrs: ThinVec::new(), })) } diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs index 6301283460ac7..84583d0e5eca7 100644 --- a/src/libsyntax_ext/assert.rs +++ b/src/libsyntax_ext/assert.rs @@ -23,7 +23,7 @@ pub fn expand_assert<'cx>( } }; - let sp = sp.apply_mark(cx.current_expansion.id); + let sp = cx.with_legacy_ctxt(sp); let panic_call = Mac { path: Path::from_ident(Ident::new(sym::panic, sp)), tts: custom_message.unwrap_or_else(|| { diff --git a/src/libsyntax_ext/cfg.rs b/src/libsyntax_ext/cfg.rs index 0e52c1af9086f..21cee8ae1cb9c 100644 --- a/src/libsyntax_ext/cfg.rs +++ b/src/libsyntax_ext/cfg.rs @@ -16,7 +16,7 @@ pub fn expand_cfg( sp: Span, tts: &[tokenstream::TokenTree], ) -> Box { - let sp = sp.apply_mark(cx.current_expansion.id); + let sp = cx.with_legacy_ctxt(sp); match parse_cfg(cx, sp, tts) { Ok(cfg) => { diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index 4cd17531a4500..ffa5154ca0c36 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -59,6 +59,6 @@ pub fn expand_syntax_ext( } else if has_errors { return DummyResult::any(sp); } - let sp = sp.apply_mark(cx.current_expansion.id); + let sp = cx.with_legacy_ctxt(sp); base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) } diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index 8184fc442676d..96677072d1b80 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -39,7 +39,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>, } } - let ident = ast::Ident::new(Symbol::intern(&res_str), sp.apply_mark(cx.current_expansion.id)); + let ident = ast::Ident::new(Symbol::intern(&res_str), cx.with_legacy_ctxt(sp)); struct ConcatIdentsResult { ident: ast::Ident } diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index d030ea4a56ebb..4dd0ecfebefd4 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -112,7 +112,7 @@ fn cs_clone_shallow(name: &str, ty: P, span: Span, helper_name: &str) { // Generate statement `let _: helper_name;`, // set the expn ID so we can use the unstable struct. - let span = span.with_ctxt(cx.backtrace()); + let span = cx.with_def_site_ctxt(span); let assert_path = cx.path_all(span, true, cx.std_path(&[sym::clone, Symbol::intern(helper_name)]), vec![GenericArg::Type(ty)], vec![]); diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs index 54027c600b4cd..32ab47969ada4 100644 --- a/src/libsyntax_ext/deriving/cmp/eq.rs +++ b/src/libsyntax_ext/deriving/cmp/eq.rs @@ -53,7 +53,7 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt<'_>, ty: P, span: Span, helper_name: &str) { // Generate statement `let _: helper_name;`, // set the expn ID so we can use the unstable struct. - let span = span.with_ctxt(cx.backtrace()); + let span = cx.with_def_site_ctxt(span); let assert_path = cx.path_all(span, true, cx.std_path(&[sym::cmp, Symbol::intern(helper_name)]), vec![GenericArg::Type(ty)], vec![]); diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index 441535410480b..781645a574e9a 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -60,7 +60,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> }; // We want to make sure we have the ctxt set so that we can use unstable methods - let span = span.with_ctxt(cx.backtrace()); + let span = cx.with_def_site_ctxt(span); let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked)); let builder = Ident::from_str_and_span("debug_trait_builder", span); let builder_expr = cx.expr_ident(span, builder.clone()); diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index 7fcf036fc8176..cb1c7b21fee0d 100644 --- a/src/libsyntax_ext/deriving/generic/ty.rs +++ b/src/libsyntax_ext/deriving/generic/ty.rs @@ -85,7 +85,7 @@ impl<'a> Path<'a> { PathKind::Global => cx.path_all(span, true, idents, params, Vec::new()), PathKind::Local => cx.path_all(span, false, idents, params, Vec::new()), PathKind::Std => { - let def_site = DUMMY_SP.apply_mark(cx.current_expansion.id); + let def_site = cx.with_def_site_ctxt(DUMMY_SP); idents.insert(0, Ident::new(kw::DollarCrate, def_site)); cx.path_all(span, false, idents, params, Vec::new()) } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index da68eea0c50e7..60b6eba7a4b53 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -48,6 +48,9 @@ impl MultiItemModifier for BuiltinDerive { meta_item: &MetaItem, item: Annotatable) -> Vec { + // FIXME: Built-in derives often forget to give spans contexts, + // so we are doing it here in a centralized way. + let span = ecx.with_def_site_ctxt(span); let mut items = Vec::new(); (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a)); items @@ -60,7 +63,7 @@ fn call_intrinsic(cx: &ExtCtxt<'_>, intrinsic: &str, args: Vec>) -> P { - let span = span.with_ctxt(cx.backtrace()); + let span = cx.with_def_site_ctxt(span); let path = cx.std_path(&[sym::intrinsics, Symbol::intern(intrinsic)]); let call = cx.expr_call_global(span, path, args); diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index 9834130fa23f0..6343d218de829 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -20,7 +20,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>, Some(v) => v, }; - let sp = sp.apply_mark(cx.current_expansion.id); + let sp = cx.with_legacy_ctxt(sp); let e = match env::var(&*var.as_str()) { Err(..) => { let lt = cx.lifetime(sp, Ident::with_dummy_span(kw::StaticLifetime)); diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 83764205a198e..47394c02b4186 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -12,7 +12,7 @@ use syntax::parse::token; use syntax::ptr::P; use syntax::symbol::{Symbol, sym}; use syntax::tokenstream; -use syntax_pos::{MultiSpan, Span, DUMMY_SP}; +use syntax_pos::{MultiSpan, Span}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use std::borrow::Cow; @@ -666,8 +666,7 @@ impl<'a, 'b> Context<'a, 'b> { // passed to this function. for (i, e) in self.args.into_iter().enumerate() { let name = names_pos[i]; - let span = - DUMMY_SP.with_ctxt(e.span.ctxt().apply_mark(self.ecx.current_expansion.id)); + let span = self.ecx.with_def_site_ctxt(e.span); pats.push(self.ecx.pat_ident(span, name)); for ref arg_ty in self.arg_unique_types[i].iter() { locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, name)); @@ -745,7 +744,7 @@ impl<'a, 'b> Context<'a, 'b> { ty: &ArgumentType, arg: ast::Ident, ) -> P { - sp = sp.apply_mark(ecx.current_expansion.id); + sp = ecx.with_def_site_ctxt(sp); let arg = ecx.expr_ident(sp, arg); let trait_ = match *ty { Placeholder(ref tyname) => { @@ -798,7 +797,7 @@ fn expand_format_args_impl<'cx>( tts: &[tokenstream::TokenTree], nl: bool, ) -> Box { - sp = sp.apply_mark(ecx.current_expansion.id); + sp = ecx.with_def_site_ctxt(sp); match parse_args(ecx, sp, tts) { Ok((efmt, args, names)) => { MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names, nl)) @@ -842,7 +841,7 @@ pub fn expand_preparsed_format_args( let arg_unique_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect(); let mut macsp = ecx.call_site(); - macsp = macsp.with_ctxt(ecx.backtrace()); + macsp = ecx.with_def_site_ctxt(macsp); let msg = "format argument must be a string literal"; let fmt_sp = efmt.span; diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs index d2121abe3b466..97b8087ad1581 100644 --- a/src/libsyntax_ext/global_allocator.rs +++ b/src/libsyntax_ext/global_allocator.rs @@ -3,7 +3,6 @@ use syntax::ast::{self, Arg, Attribute, Expr, FnHeader, Generics, Ident}; use syntax::attr::check_builtin_macro_attribute; use syntax::ext::allocator::{AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS}; use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::hygiene::SyntaxContext; use syntax::ptr::P; use syntax::symbol::{kw, sym, Symbol}; use syntax_pos::Span; @@ -29,7 +28,7 @@ pub fn expand( }; // Generate a bunch of new items using the AllocFnFactory - let span = item.span.with_ctxt(SyntaxContext::root().apply_mark(ecx.current_expansion.id)); + let span = ecx.with_legacy_ctxt(item.span); let f = AllocFnFactory { span, kind: AllocatorKind::Global, diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs index 73ebeaec45497..a8b61593db749 100644 --- a/src/libsyntax_ext/global_asm.rs +++ b/src/libsyntax_ext/global_asm.rs @@ -30,7 +30,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, id: ast::DUMMY_NODE_ID, node: ast::ItemKind::GlobalAsm(P(global_asm)), vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited), - span: sp.with_ctxt(cx.backtrace()), + span: cx.with_legacy_ctxt(sp), tokens: None, })]) } diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index 08582e714ccb2..5fd87d3a0e5c6 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -4,7 +4,6 @@ use syntax::ast; use syntax::attr::{self, check_builtin_macro_attribute}; use syntax::ext::base::*; -use syntax::ext::hygiene::SyntaxContext; use syntax::print::pprust; use syntax::source_map::respan; use syntax::symbol::{Symbol, sym}; @@ -29,7 +28,7 @@ pub fn expand_test_case( if !ecx.ecfg.should_test { return vec![]; } - let sp = attr_sp.with_ctxt(SyntaxContext::root().apply_mark(ecx.current_expansion.id)); + let sp = ecx.with_legacy_ctxt(attr_sp); let mut item = anno_item.expect_item(); item = item.map(|mut item| { item.vis = respan(item.vis.span, ast::VisibilityKind::Public); @@ -93,8 +92,7 @@ pub fn expand_test_or_bench( return vec![Annotatable::Item(item)]; } - let ctxt = SyntaxContext::root().apply_mark(cx.current_expansion.id); - let (sp, attr_sp) = (item.span.with_ctxt(ctxt), attr_sp.with_ctxt(ctxt)); + let (sp, attr_sp) = (cx.with_legacy_ctxt(item.span), cx.with_legacy_ctxt(attr_sp)); // Gensym "test" so we can extern crate without conflicting with any local names let test_id = cx.ident_of("test").gensym(); diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index a17cd7625fb19..6fffefd0d6cbb 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -22,6 +22,7 @@ pub mod edition; use edition::Edition; pub mod hygiene; pub use hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind, MacroKind, DesugaringKind}; +use hygiene::Transparency; mod span_encoding; pub use span_encoding::{Span, DUMMY_SP}; @@ -512,6 +513,13 @@ impl Span { span.ctxt) } + /// Produces a span with the same location as `self` and context produced by a macro with the + /// given ID and transparency, assuming that macro was defined directly and not produced by + /// some other macro (which is the case for built-in and procedural macros). + pub fn with_ctxt_from_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span { + self.with_ctxt(SyntaxContext::root().apply_mark_with_transparency(expn_id, transparency)) + } + #[inline] pub fn apply_mark(self, mark: ExpnId) -> Span { let span = self.data(); From bf345dd6e320a3f22396d4fbdd2ed078248105d4 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 22 Aug 2019 01:29:34 +0300 Subject: [PATCH 138/618] resolve: Do not rely on default transparency when detecting proc macro derives --- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/lib.rs | 12 ++++++++---- src/libsyntax_pos/hygiene.rs | 12 ------------ 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 42428456b6eec..9a794ade729c2 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -145,7 +145,7 @@ impl<'a> Resolver<'a> { } } - fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option> { + crate fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option> { if let Some(ext) = self.macro_map.get(&def_id) { return Some(ext.clone()); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2dd0ad13c526d..875ae449d94e0 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1647,10 +1647,14 @@ impl<'a> Resolver<'a> { if module.expansion != parent.expansion && module.expansion.is_descendant_of(parent.expansion) { // The macro is a proc macro derive - if module.expansion.looks_like_proc_macro_derive() { - if parent.expansion.outer_expn_is_descendant_of(span.ctxt()) { - *poisoned = Some(node_id); - return module.parent; + if let Some(&def_id) = self.macro_defs.get(&module.expansion) { + if let Some(ext) = self.get_macro_by_def_id(def_id) { + if !ext.is_builtin && ext.macro_kind() == MacroKind::Derive { + if parent.expansion.outer_expn_is_descendant_of(span.ctxt()) { + *poisoned = Some(node_id); + return module.parent; + } + } } } } diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index ebfb0764fa2b2..db739c9a8c569 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -119,18 +119,6 @@ impl ExpnId { pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool { HygieneData::with(|data| data.is_descendant_of(self, data.outer_expn(ctxt))) } - - // Used for enabling some compatibility fallback in resolve. - #[inline] - pub fn looks_like_proc_macro_derive(self) -> bool { - HygieneData::with(|data| { - let expn_data = data.expn_data(self); - if let ExpnKind::Macro(MacroKind::Derive, _) = expn_data.kind { - return expn_data.default_transparency == Transparency::Opaque; - } - false - }) - } } #[derive(Debug)] From b0c4d0f8cbb703c90b9dc3cd1b48d2d550508ef8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 23 Aug 2019 00:27:46 +0300 Subject: [PATCH 139/618] incremental: Do not rely on default transparency when decoding syntax contexts Using `ExpnId`s default transparency here instead of the mark's real transparency was actually incorrect. --- src/librustc/ty/query/on_disk_cache.rs | 20 ++++++++++---------- src/libsyntax_pos/hygiene.rs | 26 +++++++++++++++++--------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 8bf01970eb592..c21639d0dcaee 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -23,7 +23,7 @@ use std::mem; use syntax::ast::NodeId; use syntax::source_map::{SourceMap, StableSourceFileId}; use syntax_pos::{BytePos, Span, DUMMY_SP, SourceFile}; -use syntax_pos::hygiene::{ExpnId, SyntaxContext, ExpnData}; +use syntax_pos::hygiene::{ExpnId, SyntaxContext}; const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; @@ -593,8 +593,8 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { // don't seem to be used after HIR lowering, so everything should be fine // as long as incremental compilation does not kick in before that. let location = || Span::with_root_ctxt(lo, hi); - let recover_from_expn_data = |this: &Self, expn_data, pos| { - let span = location().fresh_expansion(expn_data); + let recover_from_expn_data = |this: &Self, expn_data, transparency, pos| { + let span = location().fresh_expansion_with_transparency(expn_data, transparency); this.synthetic_syntax_contexts.borrow_mut().insert(pos, span.ctxt()); span }; @@ -603,9 +603,9 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { location() } TAG_EXPN_DATA_INLINE => { - let expn_data = Decodable::decode(self)?; + let (expn_data, transparency) = Decodable::decode(self)?; recover_from_expn_data( - self, expn_data, AbsoluteBytePos::new(self.opaque.position()) + self, expn_data, transparency, AbsoluteBytePos::new(self.opaque.position()) ) } TAG_EXPN_DATA_SHORTHAND => { @@ -614,9 +614,9 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { if let Some(ctxt) = cached_ctxt { Span::new(lo, hi, ctxt) } else { - let expn_data = - self.with_position(pos.to_usize(), |this| ExpnData::decode(this))?; - recover_from_expn_data(self, expn_data, pos) + let (expn_data, transparency) = + self.with_position(pos.to_usize(), |this| Decodable::decode(this))?; + recover_from_expn_data(self, expn_data, transparency, pos) } } _ => { @@ -819,7 +819,7 @@ where if span_data.ctxt == SyntaxContext::root() { TAG_NO_EXPN_DATA.encode(self) } else { - let (expn_id, expn_data) = span_data.ctxt.outer_expn_with_data(); + let (expn_id, transparency, expn_data) = span_data.ctxt.outer_mark_with_data(); if let Some(pos) = self.expn_data_shorthands.get(&expn_id).cloned() { TAG_EXPN_DATA_SHORTHAND.encode(self)?; pos.encode(self) @@ -827,7 +827,7 @@ where TAG_EXPN_DATA_INLINE.encode(self)?; let pos = AbsoluteBytePos::new(self.position()); self.expn_data_shorthands.insert(expn_id, pos); - expn_data.encode(self) + (expn_data, transparency).encode(self) } } } diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index db739c9a8c569..c4a0e16d931f2 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -183,8 +183,9 @@ impl HygieneData { self.syntax_context_data[ctxt.0 as usize].outer_expn } - fn outer_transparency(&self, ctxt: SyntaxContext) -> Transparency { - self.syntax_context_data[ctxt.0 as usize].outer_transparency + fn outer_mark(&self, ctxt: SyntaxContext) -> (ExpnId, Transparency) { + let data = &self.syntax_context_data[ctxt.0 as usize]; + (data.outer_expn, data.outer_transparency) } fn parent_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContext { @@ -200,7 +201,7 @@ impl HygieneData { fn marks(&self, mut ctxt: SyntaxContext) -> Vec<(ExpnId, Transparency)> { let mut marks = Vec::new(); while ctxt != SyntaxContext::root() { - marks.push((self.outer_expn(ctxt), self.outer_transparency(ctxt))); + marks.push(self.outer_mark(ctxt)); ctxt = self.parent_ctxt(ctxt); } marks.reverse(); @@ -535,13 +536,11 @@ impl SyntaxContext { HygieneData::with(|data| data.expn_data(data.outer_expn(self)).clone()) } - /// `ctxt.outer_expn_with_data()` is equivalent to but faster than - /// `{ let outer = ctxt.outer_expn(); (outer, outer.expn_data()) }`. #[inline] - pub fn outer_expn_with_data(self) -> (ExpnId, ExpnData) { + pub fn outer_mark_with_data(self) -> (ExpnId, Transparency, ExpnData) { HygieneData::with(|data| { - let outer = data.outer_expn(self); - (outer, data.expn_data(outer).clone()) + let (expn_id, transparency) = data.outer_mark(self); + (expn_id, transparency, data.expn_data(expn_id).clone()) }) } @@ -563,9 +562,18 @@ impl Span { /// The returned span belongs to the created expansion and has the new properties, /// but its location is inherited from the current span. pub fn fresh_expansion(self, expn_data: ExpnData) -> Span { + let transparency = expn_data.default_transparency; + self.fresh_expansion_with_transparency(expn_data, transparency) + } + + pub fn fresh_expansion_with_transparency( + self, expn_data: ExpnData, transparency: Transparency + ) -> Span { HygieneData::with(|data| { let expn_id = data.fresh_expn(Some(expn_data)); - self.with_ctxt(data.apply_mark(SyntaxContext::root(), expn_id)) + self.with_ctxt(data.apply_mark_with_transparency( + SyntaxContext::root(), expn_id, transparency + )) }) } } From cf9db76454838988620acf6ba7db7bc8654b6f57 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 23 Aug 2019 01:31:01 +0300 Subject: [PATCH 140/618] hygiene: Require passing transparency explicitly to `apply_mark` --- src/libsyntax/ext/expand.rs | 14 --------- src/libsyntax/ext/tt/macro_rules.rs | 21 ++++++++----- src/libsyntax/ext/tt/transcribe.rs | 44 ++++++++++++++++++++------- src/libsyntax/tokenstream.rs | 9 +----- src/libsyntax_pos/hygiene.rs | 46 ++++++++++------------------- src/libsyntax_pos/lib.rs | 6 ++-- 6 files changed, 66 insertions(+), 74 deletions(-) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 4965cb097dbee..c8c0f4ce36e8e 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1388,17 +1388,3 @@ impl<'feat> ExpansionConfig<'feat> { self.features.map_or(false, |features| features.custom_inner_attributes) } } - -// A Marker adds the given mark to the syntax context. -#[derive(Debug)] -pub struct Marker(pub ExpnId); - -impl MutVisitor for Marker { - fn visit_span(&mut self, span: &mut Span) { - *span = span.apply_mark(self.0) - } - - fn visit_mac(&mut self, mac: &mut ast::Mac) { - noop_visit_mac(mac, self) - } -} diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index b057a9ad44d0b..9292ce334b819 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -19,6 +19,7 @@ use crate::{ast, attr, attr::TransparencyError}; use errors::{DiagnosticBuilder, FatalError}; use log::debug; +use syntax_pos::hygiene::Transparency; use syntax_pos::Span; use rustc_data_structures::fx::FxHashMap; @@ -128,6 +129,7 @@ impl<'a> ParserAnyMacro<'a> { struct MacroRulesMacroExpander { name: ast::Ident, span: Span, + transparency: Transparency, lhses: Vec, rhses: Vec, valid: bool, @@ -143,7 +145,9 @@ impl TTMacroExpander for MacroRulesMacroExpander { if !self.valid { return DummyResult::any(sp); } - generic_extension(cx, sp, self.span, self.name, input, &self.lhses, &self.rhses) + generic_extension( + cx, sp, self.span, self.name, self.transparency, input, &self.lhses, &self.rhses + ) } } @@ -158,6 +162,7 @@ fn generic_extension<'cx>( sp: Span, def_span: Span, name: ast::Ident, + transparency: Transparency, arg: TokenStream, lhses: &[quoted::TokenTree], rhses: &[quoted::TokenTree], @@ -187,7 +192,7 @@ fn generic_extension<'cx>( let rhs_spans = rhs.iter().map(|t| t.span()).collect::>(); // rhs has holes ( `$id` and `$(...)` that need filled) - let mut tts = transcribe(cx, &named_matches, rhs); + let mut tts = transcribe(cx, &named_matches, rhs, transparency); // Replace all the tokens for the corresponding positions in the macro, to maintain // proper positions in error reporting, while maintaining the macro_backtrace. @@ -415,11 +420,7 @@ pub fn compile( // that is not lint-checked and trigger the "failed to process buffered lint here" bug. valid &= macro_check::check_meta_variables(sess, ast::CRATE_NODE_ID, def.span, &lhses, &rhses); - let expander: Box<_> = - Box::new(MacroRulesMacroExpander { name: def.ident, span: def.span, lhses, rhses, valid }); - - let (default_transparency, transparency_error) = - attr::find_transparency(&def.attrs, body.legacy); + let (transparency, transparency_error) = attr::find_transparency(&def.attrs, body.legacy); match transparency_error { Some(TransparencyError::UnknownTransparency(value, span)) => sess.span_diagnostic.span_err( @@ -432,6 +433,10 @@ pub fn compile( None => {} } + let expander: Box<_> = Box::new(MacroRulesMacroExpander { + name: def.ident, span: def.span, transparency, lhses, rhses, valid + }); + let allow_internal_unstable = attr::find_by_name(&def.attrs, sym::allow_internal_unstable).map(|attr| { attr.meta_item_list() @@ -473,7 +478,7 @@ pub fn compile( SyntaxExtension { kind: SyntaxExtensionKind::LegacyBang(expander), span: def.span, - default_transparency, + default_transparency: transparency, allow_internal_unstable, allow_internal_unsafe: attr::contains_name(&def.attrs, sym::allow_internal_unsafe), local_inner_macros, diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 214e721fd1506..30d5df13dcedb 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -1,9 +1,8 @@ -use crate::ast::Ident; +use crate::ast::{Ident, Mac}; use crate::ext::base::ExtCtxt; -use crate::ext::expand::Marker; use crate::ext::tt::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; use crate::ext::tt::quoted; -use crate::mut_visit::noop_visit_tt; +use crate::mut_visit::{self, MutVisitor}; use crate::parse::token::{self, NtTT, Token}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; @@ -11,8 +10,31 @@ use smallvec::{smallvec, SmallVec}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; +use syntax_pos::hygiene::{ExpnId, Transparency}; +use syntax_pos::Span; + use std::mem; +// A Marker adds the given mark to the syntax context. +struct Marker(ExpnId, Transparency); + +impl MutVisitor for Marker { + fn visit_span(&mut self, span: &mut Span) { + *span = span.apply_mark(self.0, self.1) + } + + fn visit_mac(&mut self, mac: &mut Mac) { + mut_visit::noop_visit_mac(mac, self) + } +} + +impl Marker { + fn visit_delim_span(&mut self, dspan: &mut DelimSpan) { + self.visit_span(&mut dspan.open); + self.visit_span(&mut dspan.close); + } +} + /// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). enum Frame { Delimited { forest: Lrc, idx: usize, span: DelimSpan }, @@ -68,6 +90,7 @@ pub(super) fn transcribe( cx: &ExtCtxt<'_>, interp: &FxHashMap, src: Vec, + transparency: Transparency, ) -> TokenStream { // Nothing for us to transcribe... if src.is_empty() { @@ -96,6 +119,7 @@ pub(super) fn transcribe( // again, and we are done transcribing. let mut result: Vec = Vec::new(); let mut result_stack = Vec::new(); + let mut marker = Marker(cx.current_expansion.id, transparency); loop { // Look at the last frame on the stack. @@ -207,7 +231,7 @@ pub(super) fn transcribe( } // Replace the meta-var with the matched token tree from the invocation. - quoted::TokenTree::MetaVar(mut sp, ident) => { + quoted::TokenTree::MetaVar(mut sp, mut ident) => { // Find the matched nonterminal from the macro invocation, and use it to replace // the meta-var. if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { @@ -218,7 +242,7 @@ pub(super) fn transcribe( if let NtTT(ref tt) = **nt { result.push(tt.clone().into()); } else { - sp = sp.apply_mark(cx.current_expansion.id); + marker.visit_span(&mut sp); let token = TokenTree::token(token::Interpolated(nt.clone()), sp); result.push(token.into()); } @@ -232,9 +256,8 @@ pub(super) fn transcribe( } else { // If we aren't able to match the meta-var, we push it back into the result but // with modified syntax context. (I believe this supports nested macros). - let ident = - Ident::new(ident.name, ident.span.apply_mark(cx.current_expansion.id)); - sp = sp.apply_mark(cx.current_expansion.id); + marker.visit_span(&mut sp); + marker.visit_ident(&mut ident); result.push(TokenTree::token(token::Dollar, sp).into()); result.push(TokenTree::Token(Token::from_ast_ident(ident)).into()); } @@ -246,7 +269,7 @@ pub(super) fn transcribe( // jump back out of the Delimited, pop the result_stack and add the new results back to // the previous results (from outside the Delimited). quoted::TokenTree::Delimited(mut span, delimited) => { - span = span.apply_mark(cx.current_expansion.id); + marker.visit_delim_span(&mut span); stack.push(Frame::Delimited { forest: delimited, idx: 0, span }); result_stack.push(mem::take(&mut result)); } @@ -254,9 +277,8 @@ pub(super) fn transcribe( // Nothing much to do here. Just push the token to the result, being careful to // preserve syntax context. quoted::TokenTree::Token(token) => { - let mut marker = Marker(cx.current_expansion.id); let mut tt = TokenTree::Token(token); - noop_visit_tt(&mut tt, &mut marker); + marker.visit_tt(&mut tt); result.push(tt.into()); } diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 09a1b93c7bb19..0d9f3769ce904 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -19,7 +19,7 @@ use crate::parse::Directory; use crate::parse::token::{self, DelimToken, Token, TokenKind}; use crate::print::pprust; -use syntax_pos::{BytePos, ExpnId, Span, DUMMY_SP}; +use syntax_pos::{BytePos, Span, DUMMY_SP}; #[cfg(target_arch = "x86_64")] use rustc_data_structures::static_assert_size; use rustc_data_structures::sync::Lrc; @@ -547,11 +547,4 @@ impl DelimSpan { pub fn entire(self) -> Span { self.open.with_hi(self.close.hi()) } - - pub fn apply_mark(self, expn_id: ExpnId) -> Self { - DelimSpan { - open: self.open.apply_mark(expn_id), - close: self.close.apply_mark(expn_id), - } - } } diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index c4a0e16d931f2..fa84dcdb7bf89 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -192,10 +192,10 @@ impl HygieneData { self.syntax_context_data[ctxt.0 as usize].parent } - fn remove_mark(&self, ctxt: &mut SyntaxContext) -> ExpnId { - let outer_expn = self.outer_expn(*ctxt); + fn remove_mark(&self, ctxt: &mut SyntaxContext) -> (ExpnId, Transparency) { + let outer_mark = self.outer_mark(*ctxt); *ctxt = self.parent_ctxt(*ctxt); - outer_expn + outer_mark } fn marks(&self, mut ctxt: SyntaxContext) -> Vec<(ExpnId, Transparency)> { @@ -218,20 +218,14 @@ impl HygieneData { fn adjust(&self, ctxt: &mut SyntaxContext, expn_id: ExpnId) -> Option { let mut scope = None; while !self.is_descendant_of(expn_id, self.outer_expn(*ctxt)) { - scope = Some(self.remove_mark(ctxt)); + scope = Some(self.remove_mark(ctxt).0); } scope } - fn apply_mark(&mut self, ctxt: SyntaxContext, expn_id: ExpnId) -> SyntaxContext { - assert_ne!(expn_id, ExpnId::root()); - self.apply_mark_with_transparency( - ctxt, expn_id, self.expn_data(expn_id).default_transparency - ) - } - - fn apply_mark_with_transparency(&mut self, ctxt: SyntaxContext, expn_id: ExpnId, - transparency: Transparency) -> SyntaxContext { + fn apply_mark( + &mut self, ctxt: SyntaxContext, expn_id: ExpnId, transparency: Transparency + ) -> SyntaxContext { assert_ne!(expn_id, ExpnId::root()); if transparency == Transparency::Opaque { return self.apply_mark_internal(ctxt, expn_id, transparency); @@ -365,15 +359,9 @@ impl SyntaxContext { SyntaxContext(raw) } - /// Extend a syntax context with a given expansion and default transparency for that expansion. - pub fn apply_mark(self, expn_id: ExpnId) -> SyntaxContext { - HygieneData::with(|data| data.apply_mark(self, expn_id)) - } - /// Extend a syntax context with a given expansion and transparency. - pub fn apply_mark_with_transparency(self, expn_id: ExpnId, transparency: Transparency) - -> SyntaxContext { - HygieneData::with(|data| data.apply_mark_with_transparency(self, expn_id, transparency)) + pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext { + HygieneData::with(|data| data.apply_mark(self, expn_id, transparency)) } /// Pulls a single mark off of the syntax context. This effectively moves the @@ -393,7 +381,7 @@ impl SyntaxContext { /// invocation of f that created g1. /// Returns the mark that was removed. pub fn remove_mark(&mut self) -> ExpnId { - HygieneData::with(|data| data.remove_mark(self)) + HygieneData::with(|data| data.remove_mark(self).0) } pub fn marks(self) -> Vec<(ExpnId, Transparency)> { @@ -466,8 +454,8 @@ impl SyntaxContext { let mut scope = None; let mut glob_ctxt = data.modern(glob_span.ctxt()); while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) { - scope = Some(data.remove_mark(&mut glob_ctxt)); - if data.remove_mark(self) != scope.unwrap() { + scope = Some(data.remove_mark(&mut glob_ctxt).0); + if data.remove_mark(self).0 != scope.unwrap() { return None; } } @@ -498,9 +486,9 @@ impl SyntaxContext { marks.push(data.remove_mark(&mut glob_ctxt)); } - let scope = marks.last().cloned(); - while let Some(mark) = marks.pop() { - *self = data.apply_mark(*self, mark); + let scope = marks.last().map(|mark| mark.0); + while let Some((expn_id, transparency)) = marks.pop() { + *self = data.apply_mark(*self, expn_id, transparency); } Some(scope) }) @@ -571,9 +559,7 @@ impl Span { ) -> Span { HygieneData::with(|data| { let expn_id = data.fresh_expn(Some(expn_data)); - self.with_ctxt(data.apply_mark_with_transparency( - SyntaxContext::root(), expn_id, transparency - )) + self.with_ctxt(data.apply_mark(SyntaxContext::root(), expn_id, transparency)) }) } } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 6fffefd0d6cbb..3d8bfc77a8950 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -517,13 +517,13 @@ impl Span { /// given ID and transparency, assuming that macro was defined directly and not produced by /// some other macro (which is the case for built-in and procedural macros). pub fn with_ctxt_from_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span { - self.with_ctxt(SyntaxContext::root().apply_mark_with_transparency(expn_id, transparency)) + self.with_ctxt(SyntaxContext::root().apply_mark(expn_id, transparency)) } #[inline] - pub fn apply_mark(self, mark: ExpnId) -> Span { + pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span { let span = self.data(); - span.with_ctxt(span.ctxt.apply_mark(mark)) + span.with_ctxt(span.ctxt.apply_mark(expn_id, transparency)) } #[inline] From 181ed55e96e589afe565e5ad4e7f1cd6a8000894 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 23 Aug 2019 00:48:52 +0200 Subject: [PATCH 141/618] Simplify eager normalization of constants --- src/librustc/traits/project.rs | 36 +----------------- src/librustc/traits/query/normalize.rs | 38 +------------------ src/test/ui/consts/const-size_of-cycle.stderr | 10 ++--- src/test/ui/issues/issue-44415.stderr | 10 ++--- 4 files changed, 13 insertions(+), 81 deletions(-) diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 72df45df92314..87a23f655a8f3 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -15,7 +15,6 @@ use super::util; use crate::hir::def_id::DefId; use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use crate::mir::interpret::{GlobalId, ConstValue}; use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap}; use rustc_macros::HashStable; use syntax::ast::Ident; @@ -397,40 +396,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { } fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ConstValue::Unevaluated(def_id, substs) = constant.val { - let tcx = self.selcx.tcx().global_tcx(); - let param_env = self.param_env; - if !param_env.has_local_value() { - if substs.needs_infer() || substs.has_placeholders() { - let identity_substs = InternalSubsts::identity_for_item(tcx, def_id); - let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs); - if let Some(instance) = instance { - let cid = GlobalId { - instance, - promoted: None - }; - if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - let evaluated = evaluated.subst(tcx, substs); - return evaluated; - } - } - } else { - if !substs.has_local_value() { - let instance = ty::Instance::resolve(tcx, param_env, def_id, substs); - if let Some(instance) = instance { - let cid = GlobalId { - instance, - promoted: None - }; - if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - return evaluated; - } - } - } - } - } - } - constant + constant.eval(self.selcx.tcx(), self.param_env) } } diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 2ffcd0fd4d941..c31ff3ab1b55d 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -5,11 +5,10 @@ use crate::infer::at::At; use crate::infer::canonical::OriginalQueryValues; use crate::infer::{InferCtxt, InferOk}; -use crate::mir::interpret::{GlobalId, ConstValue}; use crate::traits::project::Normalized; use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; use crate::ty::fold::{TypeFoldable, TypeFolder}; -use crate::ty::subst::{Subst, InternalSubsts}; +use crate::ty::subst::Subst; use crate::ty::{self, Ty, TyCtxt}; use super::NoSolution; @@ -191,40 +190,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { } fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ConstValue::Unevaluated(def_id, substs) = constant.val { - let tcx = self.infcx.tcx.global_tcx(); - let param_env = self.param_env; - if !param_env.has_local_value() { - if substs.needs_infer() || substs.has_placeholders() { - let identity_substs = InternalSubsts::identity_for_item(tcx, def_id); - let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs); - if let Some(instance) = instance { - let cid = GlobalId { - instance, - promoted: None, - }; - if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - let evaluated = evaluated.subst(tcx, substs); - return evaluated; - } - } - } else { - if !substs.has_local_value() { - let instance = ty::Instance::resolve(tcx, param_env, def_id, substs); - if let Some(instance) = instance { - let cid = GlobalId { - instance, - promoted: None, - }; - if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - return evaluated; - } - } - } - } - } - } - constant + constant.eval(self.infcx.tcx, self.param_env) } } diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index 113ec29239616..fdba359e7464a 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -4,6 +4,11 @@ error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{con LL | bytes: [u8; std::mem::size_of::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | +note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`... + --> $DIR/const-size_of-cycle.rs:6:17 + | +LL | bytes: [u8; std::mem::size_of::()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`... --> $SRC_DIR/libcore/mem/mod.rs:LL:COL | @@ -11,11 +16,6 @@ LL | intrinsics::size_of::() | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`... -note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`... - --> $DIR/const-size_of-cycle.rs:6:17 - | -LL | bytes: [u8; std::mem::size_of::()] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle note: cycle used when processing `Foo` --> $DIR/const-size_of-cycle.rs:5:1 diff --git a/src/test/ui/issues/issue-44415.stderr b/src/test/ui/issues/issue-44415.stderr index df8e804c87a3f..8008e53f65f4d 100644 --- a/src/test/ui/issues/issue-44415.stderr +++ b/src/test/ui/issues/issue-44415.stderr @@ -4,6 +4,11 @@ error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{con LL | bytes: [u8; unsafe { intrinsics::size_of::() }], | ^^^^^^ | +note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`... + --> $DIR/issue-44415.rs:6:17 + | +LL | bytes: [u8; unsafe { intrinsics::size_of::() }], + | ^^^^^^ note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`... --> $DIR/issue-44415.rs:6:26 | @@ -11,11 +16,6 @@ LL | bytes: [u8; unsafe { intrinsics::size_of::() }], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`... -note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`... - --> $DIR/issue-44415.rs:6:17 - | -LL | bytes: [u8; unsafe { intrinsics::size_of::() }], - | ^^^^^^ = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle note: cycle used when processing `Foo` --> $DIR/issue-44415.rs:5:1 From 6548a5fa5d1f6d1794592945837111f7264ae598 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 23 Aug 2019 01:44:18 +0300 Subject: [PATCH 142/618] Remove default macro transparencies All transparancies are passed explicitly now. Also remove `#[rustc_macro_transparency]` annotations from built-in macros, they are no longer used. `#[rustc_macro_transparency]` only makes sense for declarative macros now. --- src/libcore/macros.rs | 8 -------- src/librustc/ich/impls_syntax.rs | 1 - src/libsyntax/ext/base.rs | 20 -------------------- src/libsyntax/ext/tt/macro_rules.rs | 1 - src/libsyntax_pos/hygiene.rs | 6 +----- 5 files changed, 1 insertion(+), 35 deletions(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 6c88a766a2f10..ffaca029a8a78 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -734,7 +734,6 @@ pub(crate) mod builtin { #[allow_internal_unstable(fmt_internals)] #[rustc_builtin_macro] #[macro_export] - #[rustc_macro_transparency = "opaque"] macro_rules! format_args { ($fmt:expr) => ({ /* compiler built-in */ }); ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) @@ -747,7 +746,6 @@ pub(crate) mod builtin { #[allow_internal_unstable(fmt_internals)] #[rustc_builtin_macro] #[macro_export] - #[rustc_macro_transparency = "opaque"] macro_rules! format_args_nl { ($fmt:expr) => ({ /* compiler built-in */ }); ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) @@ -1235,7 +1233,6 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] pub macro test($item:item) { /* compiler built-in */ } /// Attribute macro applied to a function to turn it into a benchmark test. @@ -1243,7 +1240,6 @@ pub(crate) mod builtin { reason = "`bench` is a part of custom test frameworks which are unstable")] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] pub macro bench($item:item) { /* compiler built-in */ } /// An implementation detail of the `#[test]` and `#[bench]` macros. @@ -1251,26 +1247,22 @@ pub(crate) mod builtin { reason = "custom test frameworks are an unstable feature")] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] pub macro test_case($item:item) { /* compiler built-in */ } /// Attribute macro applied to a static to register it as a global allocator. #[stable(feature = "global_allocator", since = "1.28.0")] #[allow_internal_unstable(rustc_attrs)] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] pub macro global_allocator($item:item) { /* compiler built-in */ } /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] - #[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(core_intrinsics, libstd_sys_internals)] pub macro RustcDecodable($item:item) { /* compiler built-in */ } /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] - #[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(core_intrinsics)] pub macro RustcEncodable($item:item) { /* compiler built-in */ } diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 7003f71c8baa0..05e2c7854b49c 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -402,7 +402,6 @@ impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnData { parent -> _, call_site, def_site, - default_transparency, allow_internal_unstable, allow_internal_unsafe, local_inner_macros, diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 004ae1cf96541..a63c4181d5e03 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -549,8 +549,6 @@ pub struct SyntaxExtension { pub kind: SyntaxExtensionKind, /// Span of the macro definition. pub span: Span, - /// Hygienic properties of spans produced by this macro by default. - pub default_transparency: Transparency, /// Whitelist of unstable features that are treated as stable inside this macro. pub allow_internal_unstable: Option>, /// Suppresses the `unsafe_code` lint for code produced by this macro. @@ -572,22 +570,6 @@ pub struct SyntaxExtension { pub is_derive_copy: bool, } -impl SyntaxExtensionKind { - /// When a syntax extension is constructed, - /// its transparency can often be inferred from its kind. - fn default_transparency(&self) -> Transparency { - match self { - SyntaxExtensionKind::Bang(..) | - SyntaxExtensionKind::Attr(..) | - SyntaxExtensionKind::Derive(..) | - SyntaxExtensionKind::NonMacroAttr { .. } => Transparency::Opaque, - SyntaxExtensionKind::LegacyBang(..) | - SyntaxExtensionKind::LegacyAttr(..) | - SyntaxExtensionKind::LegacyDerive(..) => Transparency::SemiTransparent, - } - } -} - impl SyntaxExtension { /// Returns which kind of macro calls this syntax extension. pub fn macro_kind(&self) -> MacroKind { @@ -606,7 +588,6 @@ impl SyntaxExtension { pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension { SyntaxExtension { span: DUMMY_SP, - default_transparency: kind.default_transparency(), allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, @@ -646,7 +627,6 @@ impl SyntaxExtension { parent, call_site, def_site: self.span, - default_transparency: self.default_transparency, allow_internal_unstable: self.allow_internal_unstable.clone(), allow_internal_unsafe: self.allow_internal_unsafe, local_inner_macros: self.local_inner_macros, diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 9292ce334b819..37cb8467ff5ee 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -478,7 +478,6 @@ pub fn compile( SyntaxExtension { kind: SyntaxExtensionKind::LegacyBang(expander), span: def.span, - default_transparency: transparency, allow_internal_unstable, allow_internal_unsafe: attr::contains_name(&def.attrs, sym::allow_internal_unsafe), local_inner_macros, diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index fa84dcdb7bf89..733f6f0449065 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -550,8 +550,7 @@ impl Span { /// The returned span belongs to the created expansion and has the new properties, /// but its location is inherited from the current span. pub fn fresh_expansion(self, expn_data: ExpnData) -> Span { - let transparency = expn_data.default_transparency; - self.fresh_expansion_with_transparency(expn_data, transparency) + self.fresh_expansion_with_transparency(expn_data, Transparency::SemiTransparent) } pub fn fresh_expansion_with_transparency( @@ -591,8 +590,6 @@ pub struct ExpnData { /// The span of the macro definition (possibly dummy). /// This span serves only informational purpose and is not used for resolution. pub def_site: Span, - /// Transparency used by `apply_mark` for the expansion with this expansion data by default. - pub default_transparency: Transparency, /// List of #[unstable]/feature-gated features that the macro is allowed to use /// internally without forcing the whole crate to opt-in /// to them. @@ -615,7 +612,6 @@ impl ExpnData { parent: ExpnId::root(), call_site, def_site: DUMMY_SP, - default_transparency: Transparency::SemiTransparent, allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, From 54f80a5b7c254d1df302680eac6552665b4c8945 Mon Sep 17 00:00:00 2001 From: nathanwhit Date: Thu, 22 Aug 2019 12:01:37 -0400 Subject: [PATCH 143/618] Add header flag to check run-pass test output --- src/tools/compiletest/src/header.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 076ad87c70fc4..dcd4f14f354d1 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -326,6 +326,8 @@ pub struct TestProps { pub force_host: bool, // Check stdout for error-pattern output as well as stderr pub check_stdout: bool, + // Check stdout & stderr for output of run-pass test + pub check_run_results: bool, // For UI tests, allows compiler to generate arbitrary output to stdout pub dont_check_compiler_stdout: bool, // For UI tests, allows compiler to generate arbitrary output to stderr @@ -388,6 +390,7 @@ impl TestProps { build_aux_docs: false, force_host: false, check_stdout: false, + check_run_results: false, dont_check_compiler_stdout: false, dont_check_compiler_stderr: false, no_prefer_dynamic: false, @@ -468,6 +471,10 @@ impl TestProps { self.check_stdout = config.parse_check_stdout(ln); } + if !self.check_run_results { + self.check_run_results = config.parse_check_run_results(ln); + } + if !self.dont_check_compiler_stdout { self.dont_check_compiler_stdout = config.parse_dont_check_compiler_stdout(ln); } @@ -712,6 +719,10 @@ impl Config { self.parse_name_directive(line, "check-stdout") } + fn parse_check_run_results(&self, line: &str) -> bool { + self.parse_name_directive(line, "check-run-results") + } + fn parse_dont_check_compiler_stdout(&self, line: &str) -> bool { self.parse_name_directive(line, "dont-check-compiler-stdout") } From 0c379dff2919321944440cfe7c306c2d35bffaaa Mon Sep 17 00:00:00 2001 From: Nathan Date: Thu, 22 Aug 2019 19:02:13 -0400 Subject: [PATCH 144/618] Extract loading and comparison of compiletest outputs to new fn Moved into ```fn load_compare_outputs(&self, proc_res: &ProcRes, explicit_format: bool) -> usize``` --- src/tools/compiletest/src/runtest.rs | 35 ++++++++++++++++------------ 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3da6be74129f4..86c5e4ac89dd6 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2934,33 +2934,20 @@ impl<'test> TestCx<'test> { } } - fn run_ui_test(&self) { - // if the user specified a format in the ui test - // print the output to the stderr file, otherwise extract - // the rendered error messages from json and print them - let explicit = self - .props - .compile_flags - .iter() - .any(|s| s.contains("--error-format")); - let proc_res = self.compile_test(); - self.check_if_test_should_compile(&proc_res); - + fn load_compare_outputs(&self, proc_res: &ProcRes, explicit_format: bool) -> usize { let expected_stderr = self.load_expected_output(UI_STDERR); let expected_stdout = self.load_expected_output(UI_STDOUT); - let expected_fixed = self.load_expected_output(UI_FIXED); let normalized_stdout = self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout); - let stderr = if explicit { + let stderr = if explicit_format { proc_res.stderr.clone() } else { json::extract_rendered(&proc_res.stderr) }; let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr); - let mut errors = 0; if !self.props.dont_check_compiler_stdout { errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); @@ -2968,10 +2955,28 @@ impl<'test> TestCx<'test> { if !self.props.dont_check_compiler_stderr { errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr); } + errors + } + + fn run_ui_test(&self) { + // if the user specified a format in the ui test + // print the output to the stderr file, otherwise extract + // the rendered error messages from json and print them + let explicit = self + .props + .compile_flags + .iter() + .any(|s| s.contains("--error-format")); + let proc_res = self.compile_test(); + self.check_if_test_should_compile(&proc_res); + + let expected_fixed = self.load_expected_output(UI_FIXED); let modes_to_prune = vec![CompareMode::Nll]; self.prune_duplicate_outputs(&modes_to_prune); + let mut errors = self.load_compare_outputs(&proc_res, explicit); + if self.config.compare_mode.is_some() { // don't test rustfix with nll right now } else if self.config.rustfix_coverage { From b9ba8f9596ac282b3254edbb9a7176771fb6ba24 Mon Sep 17 00:00:00 2001 From: Nathan Date: Thu, 22 Aug 2019 19:08:51 -0400 Subject: [PATCH 145/618] Compare run-pass outputs if `check-run-results` flag enabled Addresses #63751 --- src/tools/compiletest/src/runtest.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 86c5e4ac89dd6..c1f8caa474e2d 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2975,7 +2975,14 @@ impl<'test> TestCx<'test> { let modes_to_prune = vec![CompareMode::Nll]; self.prune_duplicate_outputs(&modes_to_prune); - let mut errors = self.load_compare_outputs(&proc_res, explicit); + // if the user specified to check the results of the + // run-pass test, delay loading and comparing output + // until execution of the binary + let mut errors = if !self.props.check_run_results { + self.load_compare_outputs(&proc_res, explicit) + } else { + 0 + }; if self.config.compare_mode.is_some() { // don't test rustfix with nll right now @@ -3054,7 +3061,17 @@ impl<'test> TestCx<'test> { if self.should_run_successfully() { let proc_res = self.exec_compiled_test(); - + let run_output_errors = if self.props.check_run_results { + self.load_compare_outputs(&proc_res, explicit) + } else { + 0 + }; + if run_output_errors > 0 { + self.fatal_proc_rec( + &format!("{} errors occured comparing run output.", run_output_errors), + &proc_res, + ); + } if !proc_res.status.success() { self.fatal_proc_rec("test run failed!", &proc_res); } From b873743c024d018b00e1e8c863a01d2c48bcdb1b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 20 Aug 2019 18:40:53 +0200 Subject: [PATCH 146/618] syntax: extract `accepted.rs` feature gates. --- src/libsyntax/feature_gate.rs | 234 +----------------------- src/libsyntax/feature_gate/accepted.rs | 236 +++++++++++++++++++++++++ 2 files changed, 239 insertions(+), 231 deletions(-) create mode 100644 src/libsyntax/feature_gate/accepted.rs diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index fad4f3da3de70..32fef2fc8ddb7 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -12,6 +12,9 @@ //! gate usage is added, *do not remove it again* even once the feature //! becomes stable. +mod accepted; +use accepted::ACCEPTED_FEATURES; + use AttributeType::*; use AttributeGate::*; @@ -94,13 +97,6 @@ macro_rules! declare_features { $((sym::$feature, $ver, $issue, None)),+ ]; }; - - ($((accepted, $feature: ident, $ver: expr, $issue: expr, None),)+) => { - /// Those language feature has since been Accepted (it was once Active) - const ACCEPTED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ - $((sym::$feature, $ver, $issue, None)),+ - ]; - } } // If you change this, please modify `src/doc/unstable-book` as well. @@ -638,230 +634,6 @@ declare_features! ( (stable_removed, no_stack_check, "1.0.0", None, None), ); -declare_features! ( - // ------------------------------------------------------------------------- - // feature-group-start: for testing purposes - // ------------------------------------------------------------------------- - - // A temporary feature gate used to enable parser extensions needed - // to bootstrap fix for #5723. - (accepted, issue_5723_bootstrap, "1.0.0", None, None), - // These are used to test this portion of the compiler, - // they don't actually mean anything. - (accepted, test_accepted_feature, "1.0.0", None, None), - - // ------------------------------------------------------------------------- - // feature-group-end: for testing purposes - // ------------------------------------------------------------------------- - - // ------------------------------------------------------------------------- - // feature-group-start: accepted features - // ------------------------------------------------------------------------- - - // Allows using associated `type`s in `trait`s. - (accepted, associated_types, "1.0.0", None, None), - // Allows using assigning a default type to type parameters in algebraic data type definitions. - (accepted, default_type_params, "1.0.0", None, None), - // FIXME: explain `globs`. - (accepted, globs, "1.0.0", None, None), - // Allows `macro_rules!` items. - (accepted, macro_rules, "1.0.0", None, None), - // Allows use of `&foo[a..b]` as a slicing syntax. - (accepted, slicing_syntax, "1.0.0", None, None), - // Allows struct variants `Foo { baz: u8, .. }` in enums (RFC 418). - (accepted, struct_variant, "1.0.0", None, None), - // Allows indexing tuples. - (accepted, tuple_indexing, "1.0.0", None, None), - // Allows the use of `if let` expressions. - (accepted, if_let, "1.0.0", None, None), - // Allows the use of `while let` expressions. - (accepted, while_let, "1.0.0", None, None), - // Allows using `#![no_std]`. - (accepted, no_std, "1.6.0", None, None), - // Allows overloading augmented assignment operations like `a += b`. - (accepted, augmented_assignments, "1.8.0", Some(28235), None), - // Allows empty structs and enum variants with braces. - (accepted, braced_empty_structs, "1.8.0", Some(29720), None), - // Allows `#[deprecated]` attribute. - (accepted, deprecated, "1.9.0", Some(29935), None), - // Allows macros to appear in the type position. - (accepted, type_macros, "1.13.0", Some(27245), None), - // Allows use of the postfix `?` operator in expressions. - (accepted, question_mark, "1.13.0", Some(31436), None), - // Allows `..` in tuple (struct) patterns. - (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None), - // Allows some increased flexibility in the name resolution rules, - // especially around globs and shadowing (RFC 1560). - (accepted, item_like_imports, "1.15.0", Some(35120), None), - // Allows using `Self` and associated types in struct expressions and patterns. - (accepted, more_struct_aliases, "1.16.0", Some(37544), None), - // Allows elision of `'static` lifetimes in `static`s and `const`s. - (accepted, static_in_const, "1.17.0", Some(35897), None), - // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. - (accepted, field_init_shorthand, "1.17.0", Some(37340), None), - // Allows the definition recursive static items. - (accepted, static_recursion, "1.17.0", Some(29719), None), - // Allows `pub(restricted)` visibilities (RFC 1422). - (accepted, pub_restricted, "1.18.0", Some(32409), None), - // Allows `#![windows_subsystem]`. - (accepted, windows_subsystem, "1.18.0", Some(37499), None), - // Allows `break {expr}` with a value inside `loop`s. - (accepted, loop_break_value, "1.19.0", Some(37339), None), - // Allows numeric fields in struct expressions and patterns. - (accepted, relaxed_adts, "1.19.0", Some(35626), None), - // Allows coercing non capturing closures to function pointers. - (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None), - // Allows attributes on struct literal fields. - (accepted, struct_field_attributes, "1.20.0", Some(38814), None), - // Allows the definition of associated constants in `trait` or `impl` blocks. - (accepted, associated_consts, "1.20.0", Some(29646), None), - // Allows usage of the `compile_error!` macro. - (accepted, compile_error, "1.20.0", Some(40872), None), - // Allows code like `let x: &'static u32 = &42` to work (RFC 1414). - (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), - // Allows `Drop` types in constants (RFC 1440). - (accepted, drop_types_in_const, "1.22.0", Some(33156), None), - // Allows the sysV64 ABI to be specified on all platforms - // instead of just the platforms on which it is the C ABI. - (accepted, abi_sysv64, "1.24.0", Some(36167), None), - // Allows `repr(align(16))` struct attribute (RFC 1358). - (accepted, repr_align, "1.25.0", Some(33626), None), - // Allows '|' at beginning of match arms (RFC 1925). - (accepted, match_beginning_vert, "1.25.0", Some(44101), None), - // Allows nested groups in `use` items (RFC 2128). - (accepted, use_nested_groups, "1.25.0", Some(44494), None), - // Allows indexing into constant arrays. - (accepted, const_indexing, "1.26.0", Some(29947), None), - // Allows using `a..=b` and `..=b` as inclusive range syntaxes. - (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), - // Allows `..=` in patterns (RFC 1192). - (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), - // Allows `fn main()` with return types which implements `Termination` (RFC 1937). - (accepted, termination_trait, "1.26.0", Some(43301), None), - // Allows implementing `Clone` for closures where possible (RFC 2132). - (accepted, clone_closures, "1.26.0", Some(44490), None), - // Allows implementing `Copy` for closures where possible (RFC 2132). - (accepted, copy_closures, "1.26.0", Some(44490), None), - // Allows `impl Trait` in function arguments. - (accepted, universal_impl_trait, "1.26.0", Some(34511), None), - // Allows `impl Trait` in function return types. - (accepted, conservative_impl_trait, "1.26.0", Some(34511), None), - // Allows using the `u128` and `i128` types. - (accepted, i128_type, "1.26.0", Some(35118), None), - // Allows default match binding modes (RFC 2005). - (accepted, match_default_bindings, "1.26.0", Some(42640), None), - // Allows `'_` placeholder lifetimes. - (accepted, underscore_lifetimes, "1.26.0", Some(44524), None), - // Allows attributes on lifetime/type formal parameters in generics (RFC 1327). - (accepted, generic_param_attrs, "1.27.0", Some(48848), None), - // Allows `cfg(target_feature = "...")`. - (accepted, cfg_target_feature, "1.27.0", Some(29717), None), - // Allows `#[target_feature(...)]`. - (accepted, target_feature, "1.27.0", None, None), - // Allows using `dyn Trait` as a syntax for trait objects. - (accepted, dyn_trait, "1.27.0", Some(44662), None), - // Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). - (accepted, fn_must_use, "1.27.0", Some(43302), None), - // Allows use of the `:lifetime` macro fragment specifier. - (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None), - // Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). - (accepted, termination_trait_test, "1.27.0", Some(48854), None), - // Allows the `#[global_allocator]` attribute. - (accepted, global_allocator, "1.28.0", Some(27389), None), - // Allows `#[repr(transparent)]` attribute on newtype structs. - (accepted, repr_transparent, "1.28.0", Some(43036), None), - // Allows procedural macros in `proc-macro` crates. - (accepted, proc_macro, "1.29.0", Some(38356), None), - // Allows `foo.rs` as an alternative to `foo/mod.rs`. - (accepted, non_modrs_mods, "1.30.0", Some(44660), None), - // Allows use of the `:vis` macro fragment specifier - (accepted, macro_vis_matcher, "1.30.0", Some(41022), None), - // Allows importing and reexporting macros with `use`, - // enables macro modularization in general. - (accepted, use_extern_macros, "1.30.0", Some(35896), None), - // Allows keywords to be escaped for use as identifiers. - (accepted, raw_identifiers, "1.30.0", Some(48589), None), - // Allows attributes scoped to tools. - (accepted, tool_attributes, "1.30.0", Some(44690), None), - // Allows multi-segment paths in attributes and derives. - (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None), - // Allows all literals in attribute lists and values of key-value pairs. - (accepted, attr_literals, "1.30.0", Some(34981), None), - // Allows inferring outlives requirements (RFC 2093). - (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), - // Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. - // This defines the behavior of panics. - (accepted, panic_handler, "1.30.0", Some(44489), None), - // Allows `#[used]` to preserve symbols (see llvm.used). - (accepted, used, "1.30.0", Some(40289), None), - // Allows `crate` in paths. - (accepted, crate_in_paths, "1.30.0", Some(45477), None), - // Allows resolving absolute paths as paths from other crates. - (accepted, extern_absolute_paths, "1.30.0", Some(44660), None), - // Allows access to crate names passed via `--extern` through prelude. - (accepted, extern_prelude, "1.30.0", Some(44660), None), - // Allows parentheses in patterns. - (accepted, pattern_parentheses, "1.31.0", Some(51087), None), - // Allows the definition of `const fn` functions. - (accepted, min_const_fn, "1.31.0", Some(53555), None), - // Allows scoped lints. - (accepted, tool_lints, "1.31.0", Some(44690), None), - // Allows lifetime elision in `impl` headers. For example: - // + `impl Iterator for &mut Iterator` - // + `impl Debug for Foo<'_>` - (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), - // Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. - (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), - // Allows use of the `:literal` macro fragment specifier (RFC 1576). - (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), - // Allows use of `?` as the Kleene "at most one" operator in macros. - (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), - // Allows `Self` struct constructor (RFC 2302). - (accepted, self_struct_ctor, "1.32.0", Some(51994), None), - // Allows `Self` in type definitions (RFC 2300). - (accepted, self_in_typedefs, "1.32.0", Some(49303), None), - // Allows `use x::y;` to search `x` in the current scope. - (accepted, uniform_paths, "1.32.0", Some(53130), None), - // Allows integer match exhaustiveness checking (RFC 2591). - (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), - // Allows `use path as _;` and `extern crate c as _;`. - (accepted, underscore_imports, "1.33.0", Some(48216), None), - // Allows `#[repr(packed(N))]` attribute on structs. - (accepted, repr_packed, "1.33.0", Some(33158), None), - // Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). - (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None), - // Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. - (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None), - // Allows let bindings, assignments and destructuring in `const` functions and constants. - // As long as control flow is not implemented in const eval, `&&` and `||` may not be used - // at the same time as let bindings. - (accepted, const_let, "1.33.0", Some(48821), None), - // Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. - (accepted, cfg_attr_multi, "1.33.0", Some(54881), None), - // Allows top level or-patterns (`p | q`) in `if let` and `while let`. - (accepted, if_while_or_patterns, "1.33.0", Some(48215), None), - // Allows `cfg(target_vendor = "...")`. - (accepted, cfg_target_vendor, "1.33.0", Some(29718), None), - // Allows `extern crate self as foo;`. - // This puts local crate root into extern prelude under name `foo`. - (accepted, extern_crate_self, "1.34.0", Some(56409), None), - // Allows arbitrary delimited token streams in non-macro attributes. - (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None), - // Allows paths to enum variants on type aliases including `Self`. - (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None), - // Allows using `#[repr(align(X))]` on enums with equivalent semantics - // to wrapping an enum in a wrapper struct with `#[repr(align(X))]`. - (accepted, repr_align_enum, "1.37.0", Some(57996), None), - // Allows `const _: TYPE = VALUE`. - (accepted, underscore_const_names, "1.37.0", Some(54912), None), - // Allows free and inherent `async fn`s, `async` blocks, and `.await` expressions. - (accepted, async_await, "1.39.0", Some(50547), None), - - // ------------------------------------------------------------------------- - // feature-group-end: accepted features - // ------------------------------------------------------------------------- -); - // If you change this, please modify `src/doc/unstable-book` as well. You must // move that documentation into the relevant place in the other docs, and // remove the chapter on the flag. diff --git a/src/libsyntax/feature_gate/accepted.rs b/src/libsyntax/feature_gate/accepted.rs new file mode 100644 index 0000000000000..32a0b76d5f0d8 --- /dev/null +++ b/src/libsyntax/feature_gate/accepted.rs @@ -0,0 +1,236 @@ +//! List of the accepted feature gates. + +use crate::symbol::{Symbol, sym}; + +macro_rules! declare_features { + ($((accepted, $feature: ident, $ver: expr, $issue: expr, None),)+) => { + /// Those language feature has since been Accepted (it was once Active) + pub const ACCEPTED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ + $((sym::$feature, $ver, $issue, None)),+ + ]; + } +} + +declare_features! ( + // ------------------------------------------------------------------------- + // feature-group-start: for testing purposes + // ------------------------------------------------------------------------- + + // A temporary feature gate used to enable parser extensions needed + // to bootstrap fix for #5723. + (accepted, issue_5723_bootstrap, "1.0.0", None, None), + // These are used to test this portion of the compiler, + // they don't actually mean anything. + (accepted, test_accepted_feature, "1.0.0", None, None), + + // ------------------------------------------------------------------------- + // feature-group-end: for testing purposes + // ------------------------------------------------------------------------- + + // ------------------------------------------------------------------------- + // feature-group-start: accepted features + // ------------------------------------------------------------------------- + + // Allows using associated `type`s in `trait`s. + (accepted, associated_types, "1.0.0", None, None), + // Allows using assigning a default type to type parameters in algebraic data type definitions. + (accepted, default_type_params, "1.0.0", None, None), + // FIXME: explain `globs`. + (accepted, globs, "1.0.0", None, None), + // Allows `macro_rules!` items. + (accepted, macro_rules, "1.0.0", None, None), + // Allows use of `&foo[a..b]` as a slicing syntax. + (accepted, slicing_syntax, "1.0.0", None, None), + // Allows struct variants `Foo { baz: u8, .. }` in enums (RFC 418). + (accepted, struct_variant, "1.0.0", None, None), + // Allows indexing tuples. + (accepted, tuple_indexing, "1.0.0", None, None), + // Allows the use of `if let` expressions. + (accepted, if_let, "1.0.0", None, None), + // Allows the use of `while let` expressions. + (accepted, while_let, "1.0.0", None, None), + // Allows using `#![no_std]`. + (accepted, no_std, "1.6.0", None, None), + // Allows overloading augmented assignment operations like `a += b`. + (accepted, augmented_assignments, "1.8.0", Some(28235), None), + // Allows empty structs and enum variants with braces. + (accepted, braced_empty_structs, "1.8.0", Some(29720), None), + // Allows `#[deprecated]` attribute. + (accepted, deprecated, "1.9.0", Some(29935), None), + // Allows macros to appear in the type position. + (accepted, type_macros, "1.13.0", Some(27245), None), + // Allows use of the postfix `?` operator in expressions. + (accepted, question_mark, "1.13.0", Some(31436), None), + // Allows `..` in tuple (struct) patterns. + (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None), + // Allows some increased flexibility in the name resolution rules, + // especially around globs and shadowing (RFC 1560). + (accepted, item_like_imports, "1.15.0", Some(35120), None), + // Allows using `Self` and associated types in struct expressions and patterns. + (accepted, more_struct_aliases, "1.16.0", Some(37544), None), + // Allows elision of `'static` lifetimes in `static`s and `const`s. + (accepted, static_in_const, "1.17.0", Some(35897), None), + // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. + (accepted, field_init_shorthand, "1.17.0", Some(37340), None), + // Allows the definition recursive static items. + (accepted, static_recursion, "1.17.0", Some(29719), None), + // Allows `pub(restricted)` visibilities (RFC 1422). + (accepted, pub_restricted, "1.18.0", Some(32409), None), + // Allows `#![windows_subsystem]`. + (accepted, windows_subsystem, "1.18.0", Some(37499), None), + // Allows `break {expr}` with a value inside `loop`s. + (accepted, loop_break_value, "1.19.0", Some(37339), None), + // Allows numeric fields in struct expressions and patterns. + (accepted, relaxed_adts, "1.19.0", Some(35626), None), + // Allows coercing non capturing closures to function pointers. + (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None), + // Allows attributes on struct literal fields. + (accepted, struct_field_attributes, "1.20.0", Some(38814), None), + // Allows the definition of associated constants in `trait` or `impl` blocks. + (accepted, associated_consts, "1.20.0", Some(29646), None), + // Allows usage of the `compile_error!` macro. + (accepted, compile_error, "1.20.0", Some(40872), None), + // Allows code like `let x: &'static u32 = &42` to work (RFC 1414). + (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), + // Allows `Drop` types in constants (RFC 1440). + (accepted, drop_types_in_const, "1.22.0", Some(33156), None), + // Allows the sysV64 ABI to be specified on all platforms + // instead of just the platforms on which it is the C ABI. + (accepted, abi_sysv64, "1.24.0", Some(36167), None), + // Allows `repr(align(16))` struct attribute (RFC 1358). + (accepted, repr_align, "1.25.0", Some(33626), None), + // Allows '|' at beginning of match arms (RFC 1925). + (accepted, match_beginning_vert, "1.25.0", Some(44101), None), + // Allows nested groups in `use` items (RFC 2128). + (accepted, use_nested_groups, "1.25.0", Some(44494), None), + // Allows indexing into constant arrays. + (accepted, const_indexing, "1.26.0", Some(29947), None), + // Allows using `a..=b` and `..=b` as inclusive range syntaxes. + (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), + // Allows `..=` in patterns (RFC 1192). + (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), + // Allows `fn main()` with return types which implements `Termination` (RFC 1937). + (accepted, termination_trait, "1.26.0", Some(43301), None), + // Allows implementing `Clone` for closures where possible (RFC 2132). + (accepted, clone_closures, "1.26.0", Some(44490), None), + // Allows implementing `Copy` for closures where possible (RFC 2132). + (accepted, copy_closures, "1.26.0", Some(44490), None), + // Allows `impl Trait` in function arguments. + (accepted, universal_impl_trait, "1.26.0", Some(34511), None), + // Allows `impl Trait` in function return types. + (accepted, conservative_impl_trait, "1.26.0", Some(34511), None), + // Allows using the `u128` and `i128` types. + (accepted, i128_type, "1.26.0", Some(35118), None), + // Allows default match binding modes (RFC 2005). + (accepted, match_default_bindings, "1.26.0", Some(42640), None), + // Allows `'_` placeholder lifetimes. + (accepted, underscore_lifetimes, "1.26.0", Some(44524), None), + // Allows attributes on lifetime/type formal parameters in generics (RFC 1327). + (accepted, generic_param_attrs, "1.27.0", Some(48848), None), + // Allows `cfg(target_feature = "...")`. + (accepted, cfg_target_feature, "1.27.0", Some(29717), None), + // Allows `#[target_feature(...)]`. + (accepted, target_feature, "1.27.0", None, None), + // Allows using `dyn Trait` as a syntax for trait objects. + (accepted, dyn_trait, "1.27.0", Some(44662), None), + // Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). + (accepted, fn_must_use, "1.27.0", Some(43302), None), + // Allows use of the `:lifetime` macro fragment specifier. + (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None), + // Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). + (accepted, termination_trait_test, "1.27.0", Some(48854), None), + // Allows the `#[global_allocator]` attribute. + (accepted, global_allocator, "1.28.0", Some(27389), None), + // Allows `#[repr(transparent)]` attribute on newtype structs. + (accepted, repr_transparent, "1.28.0", Some(43036), None), + // Allows procedural macros in `proc-macro` crates. + (accepted, proc_macro, "1.29.0", Some(38356), None), + // Allows `foo.rs` as an alternative to `foo/mod.rs`. + (accepted, non_modrs_mods, "1.30.0", Some(44660), None), + // Allows use of the `:vis` macro fragment specifier + (accepted, macro_vis_matcher, "1.30.0", Some(41022), None), + // Allows importing and reexporting macros with `use`, + // enables macro modularization in general. + (accepted, use_extern_macros, "1.30.0", Some(35896), None), + // Allows keywords to be escaped for use as identifiers. + (accepted, raw_identifiers, "1.30.0", Some(48589), None), + // Allows attributes scoped to tools. + (accepted, tool_attributes, "1.30.0", Some(44690), None), + // Allows multi-segment paths in attributes and derives. + (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None), + // Allows all literals in attribute lists and values of key-value pairs. + (accepted, attr_literals, "1.30.0", Some(34981), None), + // Allows inferring outlives requirements (RFC 2093). + (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), + // Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. + // This defines the behavior of panics. + (accepted, panic_handler, "1.30.0", Some(44489), None), + // Allows `#[used]` to preserve symbols (see llvm.used). + (accepted, used, "1.30.0", Some(40289), None), + // Allows `crate` in paths. + (accepted, crate_in_paths, "1.30.0", Some(45477), None), + // Allows resolving absolute paths as paths from other crates. + (accepted, extern_absolute_paths, "1.30.0", Some(44660), None), + // Allows access to crate names passed via `--extern` through prelude. + (accepted, extern_prelude, "1.30.0", Some(44660), None), + // Allows parentheses in patterns. + (accepted, pattern_parentheses, "1.31.0", Some(51087), None), + // Allows the definition of `const fn` functions. + (accepted, min_const_fn, "1.31.0", Some(53555), None), + // Allows scoped lints. + (accepted, tool_lints, "1.31.0", Some(44690), None), + // Allows lifetime elision in `impl` headers. For example: + // + `impl Iterator for &mut Iterator` + // + `impl Debug for Foo<'_>` + (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), + // Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. + (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), + // Allows use of the `:literal` macro fragment specifier (RFC 1576). + (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), + // Allows use of `?` as the Kleene "at most one" operator in macros. + (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), + // Allows `Self` struct constructor (RFC 2302). + (accepted, self_struct_ctor, "1.32.0", Some(51994), None), + // Allows `Self` in type definitions (RFC 2300). + (accepted, self_in_typedefs, "1.32.0", Some(49303), None), + // Allows `use x::y;` to search `x` in the current scope. + (accepted, uniform_paths, "1.32.0", Some(53130), None), + // Allows integer match exhaustiveness checking (RFC 2591). + (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), + // Allows `use path as _;` and `extern crate c as _;`. + (accepted, underscore_imports, "1.33.0", Some(48216), None), + // Allows `#[repr(packed(N))]` attribute on structs. + (accepted, repr_packed, "1.33.0", Some(33158), None), + // Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). + (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None), + // Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. + (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None), + // Allows let bindings, assignments and destructuring in `const` functions and constants. + // As long as control flow is not implemented in const eval, `&&` and `||` may not be used + // at the same time as let bindings. + (accepted, const_let, "1.33.0", Some(48821), None), + // Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. + (accepted, cfg_attr_multi, "1.33.0", Some(54881), None), + // Allows top level or-patterns (`p | q`) in `if let` and `while let`. + (accepted, if_while_or_patterns, "1.33.0", Some(48215), None), + // Allows `cfg(target_vendor = "...")`. + (accepted, cfg_target_vendor, "1.33.0", Some(29718), None), + // Allows `extern crate self as foo;`. + // This puts local crate root into extern prelude under name `foo`. + (accepted, extern_crate_self, "1.34.0", Some(56409), None), + // Allows arbitrary delimited token streams in non-macro attributes. + (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None), + // Allows paths to enum variants on type aliases including `Self`. + (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None), + // Allows using `#[repr(align(X))]` on enums with equivalent semantics + // to wrapping an enum in a wrapper struct with `#[repr(align(X))]`. + (accepted, repr_align_enum, "1.37.0", Some(57996), None), + // Allows `const _: TYPE = VALUE`. + (accepted, underscore_const_names, "1.37.0", Some(54912), None), + // Allows free and inherent `async fn`s, `async` blocks, and `.await` expressions. + (accepted, async_await, "1.39.0", Some(50547), None), + + // ------------------------------------------------------------------------- + // feature-group-end: accepted features + // ------------------------------------------------------------------------- +); From 975455b37dcdb6c59e47a289aa2d5f19d63a18f6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 20 Aug 2019 18:41:18 +0200 Subject: [PATCH 147/618] syntax: extract `removed.rs` feature gates. --- src/libsyntax/feature_gate.rs | 79 +------------------------- src/libsyntax/feature_gate/attr.rs | 1 + src/libsyntax/feature_gate/removed.rs | 82 +++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 77 deletions(-) create mode 100644 src/libsyntax/feature_gate/attr.rs create mode 100644 src/libsyntax/feature_gate/removed.rs diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 32fef2fc8ddb7..e2fa4b27f2833 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -14,6 +14,8 @@ mod accepted; use accepted::ACCEPTED_FEATURES; +mod removed; +use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES}; use AttributeType::*; use AttributeGate::*; @@ -83,20 +85,6 @@ macro_rules! declare_features { } } }; - - ($((removed, $feature: ident, $ver: expr, $issue: expr, None, $reason: expr),)+) => { - /// Represents unstable features which have since been removed (it was once Active) - const REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ - $((sym::$feature, $ver, $issue, $reason)),+ - ]; - }; - - ($((stable_removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => { - /// Represents stable features which have since been removed (it was once Accepted) - const STABLE_REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ - $((sym::$feature, $ver, $issue, None)),+ - ]; - }; } // If you change this, please modify `src/doc/unstable-book` as well. @@ -571,69 +559,6 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::let_chains, ]; -declare_features! ( - // ------------------------------------------------------------------------- - // feature-group-start: removed features - // ------------------------------------------------------------------------- - - (removed, import_shadowing, "1.0.0", None, None, None), - (removed, managed_boxes, "1.0.0", None, None, None), - // Allows use of unary negate on unsigned integers, e.g., -e for e: u8 - (removed, negate_unsigned, "1.0.0", Some(29645), None, None), - (removed, reflect, "1.0.0", Some(27749), None, None), - // A way to temporarily opt out of opt in copy. This will *never* be accepted. - (removed, opt_out_copy, "1.0.0", None, None, None), - (removed, quad_precision_float, "1.0.0", None, None, None), - (removed, struct_inherit, "1.0.0", None, None, None), - (removed, test_removed_feature, "1.0.0", None, None, None), - (removed, visible_private_types, "1.0.0", None, None, None), - (removed, unsafe_no_drop_flag, "1.0.0", None, None, None), - // Allows using items which are missing stability attributes - (removed, unmarked_api, "1.0.0", None, None, None), - (removed, allocator, "1.0.0", None, None, None), - (removed, simd, "1.0.0", Some(27731), None, - Some("removed in favor of `#[repr(simd)]`")), - (removed, advanced_slice_patterns, "1.0.0", Some(62254), None, - Some("merged into `#![feature(slice_patterns)]`")), - (removed, macro_reexport, "1.0.0", Some(29638), None, - Some("subsumed by `pub use`")), - (removed, pushpop_unsafe, "1.2.0", None, None, None), - (removed, needs_allocator, "1.4.0", Some(27389), None, - Some("subsumed by `#![feature(allocator_internals)]`")), - (removed, proc_macro_mod, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_expr, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_non_items, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_gen, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, panic_implementation, "1.28.0", Some(44489), None, - Some("subsumed by `#[panic_handler]`")), - // Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. - (removed, custom_derive, "1.32.0", Some(29644), None, - Some("subsumed by `#[proc_macro_derive]`")), - // Paths of the form: `extern::foo::bar` - (removed, extern_in_paths, "1.33.0", Some(55600), None, - Some("subsumed by `::foo::bar` paths")), - (removed, quote, "1.33.0", Some(29601), None, None), - // Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). - (removed, dropck_parametricity, "1.38.0", Some(28498), None, None), - (removed, await_macro, "1.38.0", Some(50547), None, - Some("subsumed by `.await` syntax")), - // Allows defining `existential type`s. - (removed, existential_type, "1.38.0", Some(63063), None, - Some("removed in favor of `#![feature(type_alias_impl_trait)]`")), - - // ------------------------------------------------------------------------- - // feature-group-end: removed features - // ------------------------------------------------------------------------- -); - -declare_features! ( - (stable_removed, no_stack_check, "1.0.0", None, None), -); - // If you change this, please modify `src/doc/unstable-book` as well. You must // move that documentation into the relevant place in the other docs, and // remove the chapter on the flag. diff --git a/src/libsyntax/feature_gate/attr.rs b/src/libsyntax/feature_gate/attr.rs new file mode 100644 index 0000000000000..46330df364852 --- /dev/null +++ b/src/libsyntax/feature_gate/attr.rs @@ -0,0 +1 @@ +//! TODO diff --git a/src/libsyntax/feature_gate/removed.rs b/src/libsyntax/feature_gate/removed.rs new file mode 100644 index 0000000000000..6ebfeb29f677b --- /dev/null +++ b/src/libsyntax/feature_gate/removed.rs @@ -0,0 +1,82 @@ +//! List of the removed feature gates. + +use crate::symbol::{Symbol, sym}; + +macro_rules! declare_features { + ($((removed, $feature: ident, $ver: expr, $issue: expr, None, $reason: expr),)+) => { + /// Represents unstable features which have since been removed (it was once Active) + pub const REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ + $((sym::$feature, $ver, $issue, $reason)),+ + ]; + }; + + ($((stable_removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => { + /// Represents stable features which have since been removed (it was once Accepted) + pub const STABLE_REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ + $((sym::$feature, $ver, $issue, None)),+ + ]; + }; +} + +declare_features! ( + // ------------------------------------------------------------------------- + // feature-group-start: removed features + // ------------------------------------------------------------------------- + + (removed, import_shadowing, "1.0.0", None, None, None), + (removed, managed_boxes, "1.0.0", None, None, None), + // Allows use of unary negate on unsigned integers, e.g., -e for e: u8 + (removed, negate_unsigned, "1.0.0", Some(29645), None, None), + (removed, reflect, "1.0.0", Some(27749), None, None), + // A way to temporarily opt out of opt in copy. This will *never* be accepted. + (removed, opt_out_copy, "1.0.0", None, None, None), + (removed, quad_precision_float, "1.0.0", None, None, None), + (removed, struct_inherit, "1.0.0", None, None, None), + (removed, test_removed_feature, "1.0.0", None, None, None), + (removed, visible_private_types, "1.0.0", None, None, None), + (removed, unsafe_no_drop_flag, "1.0.0", None, None, None), + // Allows using items which are missing stability attributes + (removed, unmarked_api, "1.0.0", None, None, None), + (removed, allocator, "1.0.0", None, None, None), + (removed, simd, "1.0.0", Some(27731), None, + Some("removed in favor of `#[repr(simd)]`")), + (removed, advanced_slice_patterns, "1.0.0", Some(62254), None, + Some("merged into `#![feature(slice_patterns)]`")), + (removed, macro_reexport, "1.0.0", Some(29638), None, + Some("subsumed by `pub use`")), + (removed, pushpop_unsafe, "1.2.0", None, None, None), + (removed, needs_allocator, "1.4.0", Some(27389), None, + Some("subsumed by `#![feature(allocator_internals)]`")), + (removed, proc_macro_mod, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, proc_macro_expr, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, proc_macro_non_items, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, proc_macro_gen, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, panic_implementation, "1.28.0", Some(44489), None, + Some("subsumed by `#[panic_handler]`")), + // Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. + (removed, custom_derive, "1.32.0", Some(29644), None, + Some("subsumed by `#[proc_macro_derive]`")), + // Paths of the form: `extern::foo::bar` + (removed, extern_in_paths, "1.33.0", Some(55600), None, + Some("subsumed by `::foo::bar` paths")), + (removed, quote, "1.33.0", Some(29601), None, None), + // Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). + (removed, dropck_parametricity, "1.38.0", Some(28498), None, None), + (removed, await_macro, "1.38.0", Some(50547), None, + Some("subsumed by `.await` syntax")), + // Allows defining `existential type`s. + (removed, existential_type, "1.38.0", Some(63063), None, + Some("removed in favor of `#![feature(type_alias_impl_trait)]`")), + + // ------------------------------------------------------------------------- + // feature-group-end: removed features + // ------------------------------------------------------------------------- +); + +declare_features! ( + (stable_removed, no_stack_check, "1.0.0", None, None), +); From 7afb2a82ecf74e69e4b581558990464301790b90 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 20 Aug 2019 18:50:33 +0200 Subject: [PATCH 148/618] syntax: extract `active.rs` feature gates. --- src/libsyntax/feature_gate.rs | 520 +------------------------- src/libsyntax/feature_gate/active.rs | 522 +++++++++++++++++++++++++++ 2 files changed, 525 insertions(+), 517 deletions(-) create mode 100644 src/libsyntax/feature_gate/active.rs diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index e2fa4b27f2833..f01b3af7af40b 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -16,6 +16,9 @@ mod accepted; use accepted::ACCEPTED_FEATURES; mod removed; use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES}; +mod active; +use active::{ACTIVE_FEATURES}; +pub use active::{Features, INCOMPLETE_FEATURES}; use AttributeType::*; use AttributeGate::*; @@ -42,523 +45,6 @@ use lazy_static::lazy_static; use std::env; -macro_rules! set { - ($field: ident) => {{ - fn f(features: &mut Features, _: Span) { - features.$field = true; - } - f as fn(&mut Features, Span) - }} -} - -macro_rules! declare_features { - ($((active, $feature: ident, $ver: expr, $issue: expr, $edition: expr),)+) => { - /// Represents active features that are currently being implemented or - /// currently being considered for addition/removal. - const ACTIVE_FEATURES: - &[(Symbol, &str, Option, Option, fn(&mut Features, Span))] = - &[$((sym::$feature, $ver, $issue, $edition, set!($feature))),+]; - - /// A set of features to be used by later passes. - #[derive(Clone)] - pub struct Features { - /// `#![feature]` attrs for language features, for error reporting - pub declared_lang_features: Vec<(Symbol, Span, Option)>, - /// `#![feature]` attrs for non-language (library) features - pub declared_lib_features: Vec<(Symbol, Span)>, - $(pub $feature: bool),+ - } - - impl Features { - pub fn new() -> Features { - Features { - declared_lang_features: Vec::new(), - declared_lib_features: Vec::new(), - $($feature: false),+ - } - } - - pub fn walk_feature_fields(&self, mut f: F) - where F: FnMut(&str, bool) - { - $(f(stringify!($feature), self.$feature);)+ - } - } - }; -} - -// If you change this, please modify `src/doc/unstable-book` as well. -// -// Don't ever remove anything from this list; set them to 'Removed'. -// -// The version numbers here correspond to the version in which the current status -// was set. This is most important for knowing when a particular feature became -// stable (active). -// -// Note that the features are grouped into internal/user-facing and then -// sorted by version inside those groups. This is inforced with tidy. -// -// N.B., `tools/tidy/src/features.rs` parses this information directly out of the -// source, so take care when modifying it. - -declare_features! ( - // ------------------------------------------------------------------------- - // feature-group-start: internal feature gates - // ------------------------------------------------------------------------- - - // no-tracking-issue-start - - // Allows using compiler's own crates. - (active, rustc_private, "1.0.0", Some(27812), None), - - // Allows using the `rust-intrinsic`'s "ABI". - (active, intrinsics, "1.0.0", None, None), - - // Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. - (active, lang_items, "1.0.0", None, None), - - // Allows using the `#[stable]` and `#[unstable]` attributes. - (active, staged_api, "1.0.0", None, None), - - // Allows using `#[allow_internal_unstable]`. This is an - // attribute on `macro_rules!` and can't use the attribute handling - // below (it has to be checked before expansion possibly makes - // macros disappear). - (active, allow_internal_unstable, "1.0.0", None, None), - - // Allows using `#[allow_internal_unsafe]`. This is an - // attribute on `macro_rules!` and can't use the attribute handling - // below (it has to be checked before expansion possibly makes - // macros disappear). - (active, allow_internal_unsafe, "1.0.0", None, None), - - // Allows using the macros: - // + `__diagnostic_used` - // + `__register_diagnostic` - // +`__build_diagnostic_array` - (active, rustc_diagnostic_macros, "1.0.0", None, None), - - // Allows using `#[rustc_const_unstable(feature = "foo", ..)]` which - // lets a function to be `const` when opted into with `#![feature(foo)]`. - (active, rustc_const_unstable, "1.0.0", None, None), - - // no-tracking-issue-end - - // Allows using `#[link_name="llvm.*"]`. - (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), - - // Allows using `rustc_*` attributes (RFC 572). - (active, rustc_attrs, "1.0.0", Some(29642), None), - - // Allows using `#[on_unimplemented(..)]` on traits. - (active, on_unimplemented, "1.0.0", Some(29628), None), - - // Allows using the `box $expr` syntax. - (active, box_syntax, "1.0.0", Some(49733), None), - - // Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. - (active, main, "1.0.0", Some(29634), None), - - // Allows using `#[start]` on a function indicating that it is the program entrypoint. - (active, start, "1.0.0", Some(29633), None), - - // Allows using the `#[fundamental]` attribute. - (active, fundamental, "1.0.0", Some(29635), None), - - // Allows using the `rust-call` ABI. - (active, unboxed_closures, "1.0.0", Some(29625), None), - - // Allows using the `#[linkage = ".."]` attribute. - (active, linkage, "1.0.0", Some(29603), None), - - // Allows features specific to OIBIT (auto traits). - (active, optin_builtin_traits, "1.0.0", Some(13231), None), - - // Allows using `box` in patterns (RFC 469). - (active, box_patterns, "1.0.0", Some(29641), None), - - // no-tracking-issue-start - - // Allows using `#[prelude_import]` on glob `use` items. - (active, prelude_import, "1.2.0", None, None), - - // no-tracking-issue-end - - // no-tracking-issue-start - - // Allows using `#[omit_gdb_pretty_printer_section]`. - (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), - - // Allows using the `vectorcall` ABI. - (active, abi_vectorcall, "1.7.0", None, None), - - // no-tracking-issue-end - - // Allows using `#[structural_match]` which indicates that a type is structurally matchable. - (active, structural_match, "1.8.0", Some(31434), None), - - // Allows using the `may_dangle` attribute (RFC 1327). - (active, dropck_eyepatch, "1.10.0", Some(34761), None), - - // Allows using the `#![panic_runtime]` attribute. - (active, panic_runtime, "1.10.0", Some(32837), None), - - // Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. - (active, needs_panic_runtime, "1.10.0", Some(32837), None), - - // no-tracking-issue-start - - // Allows identifying the `compiler_builtins` crate. - (active, compiler_builtins, "1.13.0", None, None), - - // Allows using the `unadjusted` ABI; perma-unstable. - (active, abi_unadjusted, "1.16.0", None, None), - - // Allows identifying crates that contain sanitizer runtimes. - (active, sanitizer_runtime, "1.17.0", None, None), - - // Used to identify crates that contain the profiler runtime. - (active, profiler_runtime, "1.18.0", None, None), - - // Allows using the `thiscall` ABI. - (active, abi_thiscall, "1.19.0", None, None), - - // Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. - (active, allocator_internals, "1.20.0", None, None), - - // no-tracking-issue-end - - // Added for testing E0705; perma-unstable. - (active, test_2018_feature, "1.31.0", Some(0), Some(Edition::Edition2018)), - - // ------------------------------------------------------------------------- - // feature-group-end: internal feature gates - // ------------------------------------------------------------------------- - - // ------------------------------------------------------------------------- - // feature-group-start: actual feature gates (target features) - // ------------------------------------------------------------------------- - - // FIXME: Document these and merge with the list below. - - // Unstable `#[target_feature]` directives. - (active, arm_target_feature, "1.27.0", Some(44839), None), - (active, aarch64_target_feature, "1.27.0", Some(44839), None), - (active, hexagon_target_feature, "1.27.0", Some(44839), None), - (active, powerpc_target_feature, "1.27.0", Some(44839), None), - (active, mips_target_feature, "1.27.0", Some(44839), None), - (active, avx512_target_feature, "1.27.0", Some(44839), None), - (active, mmx_target_feature, "1.27.0", Some(44839), None), - (active, sse4a_target_feature, "1.27.0", Some(44839), None), - (active, tbm_target_feature, "1.27.0", Some(44839), None), - (active, wasm_target_feature, "1.30.0", Some(44839), None), - (active, adx_target_feature, "1.32.0", Some(44839), None), - (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None), - (active, movbe_target_feature, "1.34.0", Some(44839), None), - (active, rtm_target_feature, "1.35.0", Some(44839), None), - (active, f16c_target_feature, "1.36.0", Some(44839), None), - - // ------------------------------------------------------------------------- - // feature-group-end: actual feature gates (target features) - // ------------------------------------------------------------------------- - - // ------------------------------------------------------------------------- - // feature-group-start: actual feature gates - // ------------------------------------------------------------------------- - - // Allows using the `#[link_args]` attribute. - (active, link_args, "1.0.0", Some(29596), None), - - // Allows defining identifiers beyond ASCII. - (active, non_ascii_idents, "1.0.0", Some(55467), None), - - // Allows using `#[plugin_registrar]` on functions. - (active, plugin_registrar, "1.0.0", Some(29597), None), - - // Allows using `#![plugin(myplugin)]`. - (active, plugin, "1.0.0", Some(29597), None), - - // Allows using `#[thread_local]` on `static` items. - (active, thread_local, "1.0.0", Some(29594), None), - - // Allows the use of SIMD types in functions declared in `extern` blocks. - (active, simd_ffi, "1.0.0", Some(27731), None), - - // Allows using custom attributes (RFC 572). - (active, custom_attribute, "1.0.0", Some(29642), None), - - // Allows using non lexical lifetimes (RFC 2094). - (active, nll, "1.0.0", Some(43234), None), - - // Allows using slice patterns. - (active, slice_patterns, "1.0.0", Some(62254), None), - - // Allows the definition of `const` functions with some advanced features. - (active, const_fn, "1.2.0", Some(57563), None), - - // Allows associated type defaults. - (active, associated_type_defaults, "1.2.0", Some(29661), None), - - // Allows `#![no_core]`. - (active, no_core, "1.3.0", Some(29639), None), - - // Allows default type parameters to influence type inference. - (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), - - // Allows `repr(simd)` and importing the various simd intrinsics. - (active, repr_simd, "1.4.0", Some(27731), None), - - // Allows `extern "platform-intrinsic" { ... }`. - (active, platform_intrinsics, "1.4.0", Some(27731), None), - - // Allows `#[unwind(..)]`. - // - // Permits specifying whether a function should permit unwinding or abort on unwind. - (active, unwind_attributes, "1.4.0", Some(58760), None), - - // Allows `#[no_debug]`. - (active, no_debug, "1.5.0", Some(29721), None), - - // Allows attributes on expressions and non-item statements. - (active, stmt_expr_attributes, "1.6.0", Some(15701), None), - - // Allows the use of type ascription in expressions. - (active, type_ascription, "1.6.0", Some(23416), None), - - // Allows `cfg(target_thread_local)`. - (active, cfg_target_thread_local, "1.7.0", Some(29594), None), - - // Allows specialization of implementations (RFC 1210). - (active, specialization, "1.7.0", Some(31844), None), - - // Allows using `#[naked]` on functions. - (active, naked_functions, "1.9.0", Some(32408), None), - - // Allows `cfg(target_has_atomic = "...")`. - (active, cfg_target_has_atomic, "1.9.0", Some(32976), None), - - // Allows `X..Y` patterns. - (active, exclusive_range_pattern, "1.11.0", Some(37854), None), - - // Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. - (active, never_type, "1.13.0", Some(35121), None), - - // Allows exhaustive pattern matching on types that contain uninhabited types. - (active, exhaustive_patterns, "1.13.0", Some(51085), None), - - // Allows untagged unions `union U { ... }`. - (active, untagged_unions, "1.13.0", Some(32836), None), - - // Allows `#[link(..., cfg(..))]`. - (active, link_cfg, "1.14.0", Some(37406), None), - - // Allows `extern "ptx-*" fn()`. - (active, abi_ptx, "1.15.0", Some(38788), None), - - // Allows the `#[repr(i128)]` attribute for enums. - (active, repr128, "1.16.0", Some(35118), None), - - // Allows `#[link(kind="static-nobundle"...)]`. - (active, static_nobundle, "1.16.0", Some(37403), None), - - // Allows `extern "msp430-interrupt" fn()`. - (active, abi_msp430_interrupt, "1.16.0", Some(38487), None), - - // Allows declarative macros 2.0 (`macro`). - (active, decl_macro, "1.17.0", Some(39412), None), - - // Allows `extern "x86-interrupt" fn()`. - (active, abi_x86_interrupt, "1.17.0", Some(40180), None), - - // Allows overlapping impls of marker traits. - (active, overlapping_marker_traits, "1.18.0", Some(29864), None), - - // Allows a test to fail without failing the whole suite. - (active, allow_fail, "1.19.0", Some(46488), None), - - // Allows unsized tuple coercion. - (active, unsized_tuple_coercion, "1.20.0", Some(42877), None), - - // Allows defining generators. - (active, generators, "1.21.0", Some(43122), None), - - // Allows `#[doc(cfg(...))]`. - (active, doc_cfg, "1.21.0", Some(43781), None), - - // Allows `#[doc(masked)]`. - (active, doc_masked, "1.21.0", Some(44027), None), - - // Allows `#[doc(spotlight)]`. - (active, doc_spotlight, "1.22.0", Some(45040), None), - - // Allows `#[doc(include = "some-file")]`. - (active, external_doc, "1.22.0", Some(44732), None), - - // Allows future-proofing enums/structs with the `#[non_exhaustive]` attribute (RFC 2008). - (active, non_exhaustive, "1.22.0", Some(44109), None), - - // Allows using `crate` as visibility modifier, synonymous with `pub(crate)`. - (active, crate_visibility_modifier, "1.23.0", Some(53120), None), - - // Allows defining `extern type`s. - (active, extern_types, "1.23.0", Some(43467), None), - - // Allows trait methods with arbitrary self types. - (active, arbitrary_self_types, "1.23.0", Some(44874), None), - - // Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). - (active, in_band_lifetimes, "1.23.0", Some(44524), None), - - // Allows associated types to be generic, e.g., `type Foo;` (RFC 1598). - (active, generic_associated_types, "1.23.0", Some(44265), None), - - // Allows defining `trait X = A + B;` alias items. - (active, trait_alias, "1.24.0", Some(41517), None), - - // Allows infering `'static` outlives requirements (RFC 2093). - (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None), - - // Allows macro invocations in `extern {}` blocks. - (active, macros_in_extern, "1.27.0", Some(49476), None), - - // Allows accessing fields of unions inside `const` functions. - (active, const_fn_union, "1.27.0", Some(51909), None), - - // Allows casting raw pointers to `usize` during const eval. - (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None), - - // Allows dereferencing raw pointers during const eval. - (active, const_raw_ptr_deref, "1.27.0", Some(51911), None), - - // Allows comparing raw pointers during const eval. - (active, const_compare_raw_pointers, "1.27.0", Some(53020), None), - - // Allows `#[doc(alias = "...")]`. - (active, doc_alias, "1.27.0", Some(50146), None), - - // Allows inconsistent bounds in where clauses. - (active, trivial_bounds, "1.28.0", Some(48214), None), - - // Allows `'a: { break 'a; }`. - (active, label_break_value, "1.28.0", Some(48594), None), - - // Allows using `#[doc(keyword = "...")]`. - (active, doc_keyword, "1.28.0", Some(51315), None), - - // Allows reinterpretation of the bits of a value of one type as another type during const eval. - (active, const_transmute, "1.29.0", Some(53605), None), - - // Allows using `try {...}` expressions. - (active, try_blocks, "1.29.0", Some(31436), None), - - // Allows defining an `#[alloc_error_handler]`. - (active, alloc_error_handler, "1.29.0", Some(51540), None), - - // Allows using the `amdgpu-kernel` ABI. - (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None), - - // Allows panicking during const eval (producing compile-time errors). - (active, const_panic, "1.30.0", Some(51999), None), - - // Allows `#[marker]` on certain traits allowing overlapping implementations. - (active, marker_trait_attr, "1.30.0", Some(29864), None), - - // Allows macro invocations on modules expressions and statements and - // procedural macros to expand to non-items. - (active, proc_macro_hygiene, "1.30.0", Some(54727), None), - - // Allows unsized rvalues at arguments and parameters. - (active, unsized_locals, "1.30.0", Some(48055), None), - - // Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. - (active, custom_test_frameworks, "1.30.0", Some(50297), None), - - // Allows non-builtin attributes in inner attribute position. - (active, custom_inner_attributes, "1.30.0", Some(54726), None), - - // Allows mixing bind-by-move in patterns and references to those identifiers in guards. - (active, bind_by_move_pattern_guards, "1.30.0", Some(15287), None), - - // Allows `impl Trait` in bindings (`let`, `const`, `static`). - (active, impl_trait_in_bindings, "1.30.0", Some(63065), None), - - // Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. - (active, lint_reasons, "1.31.0", Some(54503), None), - - // Allows exhaustive integer pattern matching on `usize` and `isize`. - (active, precise_pointer_size_matching, "1.32.0", Some(56354), None), - - // Allows relaxing the coherence rules such that - // `impl ForeignTrait for ForeignType is permitted. - (active, re_rebalance_coherence, "1.32.0", Some(55437), None), - - // Allows using `#[ffi_returns_twice]` on foreign functions. - (active, ffi_returns_twice, "1.34.0", Some(58314), None), - - // Allows const generic types (e.g. `struct Foo(...);`). - (active, const_generics, "1.34.0", Some(44580), None), - - // Allows using `#[optimize(X)]`. - (active, optimize_attribute, "1.34.0", Some(54882), None), - - // Allows using C-variadics. - (active, c_variadic, "1.34.0", Some(44930), None), - - // Allows the user of associated type bounds. - (active, associated_type_bounds, "1.34.0", Some(52662), None), - - // Attributes on formal function params. - (active, param_attrs, "1.36.0", Some(60406), None), - - // Allows calling constructor functions in `const fn`. - (active, const_constructor, "1.37.0", Some(61456), None), - - // Allows `if/while p && let q = r && ...` chains. - (active, let_chains, "1.37.0", Some(53667), None), - - // Allows #[repr(transparent)] on enums (RFC 2645). - (active, transparent_enums, "1.37.0", Some(60405), None), - - // Allows #[repr(transparent)] on unions (RFC 2645). - (active, transparent_unions, "1.37.0", Some(60405), None), - - // Allows explicit discriminants on non-unit enum variants. - (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), - - // Allows `impl Trait` with multiple unrelated lifetimes. - (active, member_constraints, "1.37.0", Some(61977), None), - - // Allows `async || body` closures. - (active, async_closure, "1.37.0", Some(62290), None), - - // Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests - (active, cfg_doctest, "1.37.0", Some(62210), None), - - // Allows `[x; N]` where `x` is a constant (RFC 2203). - (active, const_in_array_repeat_expressions, "1.37.0", Some(49147), None), - - // Allows `impl Trait` to be used inside type aliases (RFC 2515). - (active, type_alias_impl_trait, "1.38.0", Some(63063), None), - - // Allows the use of or-patterns, e.g. `0 | 1`. - (active, or_patterns, "1.38.0", Some(54883), None), - - // ------------------------------------------------------------------------- - // feature-group-end: actual feature gates - // ------------------------------------------------------------------------- -); - -/// Some features are known to be incomplete and using them is likely to have -/// unanticipated results, such as compiler crashes. We warn the user about these -/// to alert them. -pub const INCOMPLETE_FEATURES: &[Symbol] = &[ - sym::impl_trait_in_bindings, - sym::generic_associated_types, - sym::const_generics, - sym::or_patterns, - sym::let_chains, -]; - // If you change this, please modify `src/doc/unstable-book` as well. You must // move that documentation into the relevant place in the other docs, and // remove the chapter on the flag. diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs new file mode 100644 index 0000000000000..0bff4ed24a4ce --- /dev/null +++ b/src/libsyntax/feature_gate/active.rs @@ -0,0 +1,522 @@ +//! List of the active feature gates. + +use crate::edition::Edition; +use crate::symbol::{Symbol, sym}; +use syntax_pos::Span; + +macro_rules! set { + ($field: ident) => {{ + fn f(features: &mut Features, _: Span) { + features.$field = true; + } + f as fn(&mut Features, Span) + }} +} + +macro_rules! declare_features { + ($((active, $feature: ident, $ver: expr, $issue: expr, $edition: expr),)+) => { + /// Represents active features that are currently being implemented or + /// currently being considered for addition/removal. + pub const ACTIVE_FEATURES: + &[(Symbol, &str, Option, Option, fn(&mut Features, Span))] = + &[$((sym::$feature, $ver, $issue, $edition, set!($feature))),+]; + + /// A set of features to be used by later passes. + #[derive(Clone)] + pub struct Features { + /// `#![feature]` attrs for language features, for error reporting + pub declared_lang_features: Vec<(Symbol, Span, Option)>, + /// `#![feature]` attrs for non-language (library) features + pub declared_lib_features: Vec<(Symbol, Span)>, + $(pub $feature: bool),+ + } + + impl Features { + pub fn new() -> Features { + Features { + declared_lang_features: Vec::new(), + declared_lib_features: Vec::new(), + $($feature: false),+ + } + } + + pub fn walk_feature_fields(&self, mut f: F) + where F: FnMut(&str, bool) + { + $(f(stringify!($feature), self.$feature);)+ + } + } + }; +} + +// If you change this, please modify `src/doc/unstable-book` as well. +// +// Don't ever remove anything from this list; move them to `removed.rs`. +// +// The version numbers here correspond to the version in which the current status +// was set. This is most important for knowing when a particular feature became +// stable (active). +// +// Note that the features are grouped into internal/user-facing and then +// sorted by version inside those groups. This is inforced with tidy. +// +// N.B., `tools/tidy/src/features.rs` parses this information directly out of the +// source, so take care when modifying it. + +declare_features! ( + // ------------------------------------------------------------------------- + // feature-group-start: internal feature gates + // ------------------------------------------------------------------------- + + // no-tracking-issue-start + + // Allows using compiler's own crates. + (active, rustc_private, "1.0.0", Some(27812), None), + + // Allows using the `rust-intrinsic`'s "ABI". + (active, intrinsics, "1.0.0", None, None), + + // Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. + (active, lang_items, "1.0.0", None, None), + + // Allows using the `#[stable]` and `#[unstable]` attributes. + (active, staged_api, "1.0.0", None, None), + + // Allows using `#[allow_internal_unstable]`. This is an + // attribute on `macro_rules!` and can't use the attribute handling + // below (it has to be checked before expansion possibly makes + // macros disappear). + (active, allow_internal_unstable, "1.0.0", None, None), + + // Allows using `#[allow_internal_unsafe]`. This is an + // attribute on `macro_rules!` and can't use the attribute handling + // below (it has to be checked before expansion possibly makes + // macros disappear). + (active, allow_internal_unsafe, "1.0.0", None, None), + + // Allows using the macros: + // + `__diagnostic_used` + // + `__register_diagnostic` + // +`__build_diagnostic_array` + (active, rustc_diagnostic_macros, "1.0.0", None, None), + + // Allows using `#[rustc_const_unstable(feature = "foo", ..)]` which + // lets a function to be `const` when opted into with `#![feature(foo)]`. + (active, rustc_const_unstable, "1.0.0", None, None), + + // no-tracking-issue-end + + // Allows using `#[link_name="llvm.*"]`. + (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), + + // Allows using `rustc_*` attributes (RFC 572). + (active, rustc_attrs, "1.0.0", Some(29642), None), + + // Allows using `#[on_unimplemented(..)]` on traits. + (active, on_unimplemented, "1.0.0", Some(29628), None), + + // Allows using the `box $expr` syntax. + (active, box_syntax, "1.0.0", Some(49733), None), + + // Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. + (active, main, "1.0.0", Some(29634), None), + + // Allows using `#[start]` on a function indicating that it is the program entrypoint. + (active, start, "1.0.0", Some(29633), None), + + // Allows using the `#[fundamental]` attribute. + (active, fundamental, "1.0.0", Some(29635), None), + + // Allows using the `rust-call` ABI. + (active, unboxed_closures, "1.0.0", Some(29625), None), + + // Allows using the `#[linkage = ".."]` attribute. + (active, linkage, "1.0.0", Some(29603), None), + + // Allows features specific to OIBIT (auto traits). + (active, optin_builtin_traits, "1.0.0", Some(13231), None), + + // Allows using `box` in patterns (RFC 469). + (active, box_patterns, "1.0.0", Some(29641), None), + + // no-tracking-issue-start + + // Allows using `#[prelude_import]` on glob `use` items. + (active, prelude_import, "1.2.0", None, None), + + // no-tracking-issue-end + + // no-tracking-issue-start + + // Allows using `#[omit_gdb_pretty_printer_section]`. + (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), + + // Allows using the `vectorcall` ABI. + (active, abi_vectorcall, "1.7.0", None, None), + + // no-tracking-issue-end + + // Allows using `#[structural_match]` which indicates that a type is structurally matchable. + (active, structural_match, "1.8.0", Some(31434), None), + + // Allows using the `may_dangle` attribute (RFC 1327). + (active, dropck_eyepatch, "1.10.0", Some(34761), None), + + // Allows using the `#![panic_runtime]` attribute. + (active, panic_runtime, "1.10.0", Some(32837), None), + + // Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. + (active, needs_panic_runtime, "1.10.0", Some(32837), None), + + // no-tracking-issue-start + + // Allows identifying the `compiler_builtins` crate. + (active, compiler_builtins, "1.13.0", None, None), + + // Allows using the `unadjusted` ABI; perma-unstable. + (active, abi_unadjusted, "1.16.0", None, None), + + // Allows identifying crates that contain sanitizer runtimes. + (active, sanitizer_runtime, "1.17.0", None, None), + + // Used to identify crates that contain the profiler runtime. + (active, profiler_runtime, "1.18.0", None, None), + + // Allows using the `thiscall` ABI. + (active, abi_thiscall, "1.19.0", None, None), + + // Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. + (active, allocator_internals, "1.20.0", None, None), + + // no-tracking-issue-end + + // Added for testing E0705; perma-unstable. + (active, test_2018_feature, "1.31.0", Some(0), Some(Edition::Edition2018)), + + // ------------------------------------------------------------------------- + // feature-group-end: internal feature gates + // ------------------------------------------------------------------------- + + // ------------------------------------------------------------------------- + // feature-group-start: actual feature gates (target features) + // ------------------------------------------------------------------------- + + // FIXME: Document these and merge with the list below. + + // Unstable `#[target_feature]` directives. + (active, arm_target_feature, "1.27.0", Some(44839), None), + (active, aarch64_target_feature, "1.27.0", Some(44839), None), + (active, hexagon_target_feature, "1.27.0", Some(44839), None), + (active, powerpc_target_feature, "1.27.0", Some(44839), None), + (active, mips_target_feature, "1.27.0", Some(44839), None), + (active, avx512_target_feature, "1.27.0", Some(44839), None), + (active, mmx_target_feature, "1.27.0", Some(44839), None), + (active, sse4a_target_feature, "1.27.0", Some(44839), None), + (active, tbm_target_feature, "1.27.0", Some(44839), None), + (active, wasm_target_feature, "1.30.0", Some(44839), None), + (active, adx_target_feature, "1.32.0", Some(44839), None), + (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None), + (active, movbe_target_feature, "1.34.0", Some(44839), None), + (active, rtm_target_feature, "1.35.0", Some(44839), None), + (active, f16c_target_feature, "1.36.0", Some(44839), None), + + // ------------------------------------------------------------------------- + // feature-group-end: actual feature gates (target features) + // ------------------------------------------------------------------------- + + // ------------------------------------------------------------------------- + // feature-group-start: actual feature gates + // ------------------------------------------------------------------------- + + // Allows using the `#[link_args]` attribute. + (active, link_args, "1.0.0", Some(29596), None), + + // Allows defining identifiers beyond ASCII. + (active, non_ascii_idents, "1.0.0", Some(55467), None), + + // Allows using `#[plugin_registrar]` on functions. + (active, plugin_registrar, "1.0.0", Some(29597), None), + + // Allows using `#![plugin(myplugin)]`. + (active, plugin, "1.0.0", Some(29597), None), + + // Allows using `#[thread_local]` on `static` items. + (active, thread_local, "1.0.0", Some(29594), None), + + // Allows the use of SIMD types in functions declared in `extern` blocks. + (active, simd_ffi, "1.0.0", Some(27731), None), + + // Allows using custom attributes (RFC 572). + (active, custom_attribute, "1.0.0", Some(29642), None), + + // Allows using non lexical lifetimes (RFC 2094). + (active, nll, "1.0.0", Some(43234), None), + + // Allows using slice patterns. + (active, slice_patterns, "1.0.0", Some(62254), None), + + // Allows the definition of `const` functions with some advanced features. + (active, const_fn, "1.2.0", Some(57563), None), + + // Allows associated type defaults. + (active, associated_type_defaults, "1.2.0", Some(29661), None), + + // Allows `#![no_core]`. + (active, no_core, "1.3.0", Some(29639), None), + + // Allows default type parameters to influence type inference. + (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), + + // Allows `repr(simd)` and importing the various simd intrinsics. + (active, repr_simd, "1.4.0", Some(27731), None), + + // Allows `extern "platform-intrinsic" { ... }`. + (active, platform_intrinsics, "1.4.0", Some(27731), None), + + // Allows `#[unwind(..)]`. + // + // Permits specifying whether a function should permit unwinding or abort on unwind. + (active, unwind_attributes, "1.4.0", Some(58760), None), + + // Allows `#[no_debug]`. + (active, no_debug, "1.5.0", Some(29721), None), + + // Allows attributes on expressions and non-item statements. + (active, stmt_expr_attributes, "1.6.0", Some(15701), None), + + // Allows the use of type ascription in expressions. + (active, type_ascription, "1.6.0", Some(23416), None), + + // Allows `cfg(target_thread_local)`. + (active, cfg_target_thread_local, "1.7.0", Some(29594), None), + + // Allows specialization of implementations (RFC 1210). + (active, specialization, "1.7.0", Some(31844), None), + + // Allows using `#[naked]` on functions. + (active, naked_functions, "1.9.0", Some(32408), None), + + // Allows `cfg(target_has_atomic = "...")`. + (active, cfg_target_has_atomic, "1.9.0", Some(32976), None), + + // Allows `X..Y` patterns. + (active, exclusive_range_pattern, "1.11.0", Some(37854), None), + + // Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. + (active, never_type, "1.13.0", Some(35121), None), + + // Allows exhaustive pattern matching on types that contain uninhabited types. + (active, exhaustive_patterns, "1.13.0", Some(51085), None), + + // Allows untagged unions `union U { ... }`. + (active, untagged_unions, "1.13.0", Some(32836), None), + + // Allows `#[link(..., cfg(..))]`. + (active, link_cfg, "1.14.0", Some(37406), None), + + // Allows `extern "ptx-*" fn()`. + (active, abi_ptx, "1.15.0", Some(38788), None), + + // Allows the `#[repr(i128)]` attribute for enums. + (active, repr128, "1.16.0", Some(35118), None), + + // Allows `#[link(kind="static-nobundle"...)]`. + (active, static_nobundle, "1.16.0", Some(37403), None), + + // Allows `extern "msp430-interrupt" fn()`. + (active, abi_msp430_interrupt, "1.16.0", Some(38487), None), + + // Allows declarative macros 2.0 (`macro`). + (active, decl_macro, "1.17.0", Some(39412), None), + + // Allows `extern "x86-interrupt" fn()`. + (active, abi_x86_interrupt, "1.17.0", Some(40180), None), + + // Allows overlapping impls of marker traits. + (active, overlapping_marker_traits, "1.18.0", Some(29864), None), + + // Allows a test to fail without failing the whole suite. + (active, allow_fail, "1.19.0", Some(46488), None), + + // Allows unsized tuple coercion. + (active, unsized_tuple_coercion, "1.20.0", Some(42877), None), + + // Allows defining generators. + (active, generators, "1.21.0", Some(43122), None), + + // Allows `#[doc(cfg(...))]`. + (active, doc_cfg, "1.21.0", Some(43781), None), + + // Allows `#[doc(masked)]`. + (active, doc_masked, "1.21.0", Some(44027), None), + + // Allows `#[doc(spotlight)]`. + (active, doc_spotlight, "1.22.0", Some(45040), None), + + // Allows `#[doc(include = "some-file")]`. + (active, external_doc, "1.22.0", Some(44732), None), + + // Allows future-proofing enums/structs with the `#[non_exhaustive]` attribute (RFC 2008). + (active, non_exhaustive, "1.22.0", Some(44109), None), + + // Allows using `crate` as visibility modifier, synonymous with `pub(crate)`. + (active, crate_visibility_modifier, "1.23.0", Some(53120), None), + + // Allows defining `extern type`s. + (active, extern_types, "1.23.0", Some(43467), None), + + // Allows trait methods with arbitrary self types. + (active, arbitrary_self_types, "1.23.0", Some(44874), None), + + // Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). + (active, in_band_lifetimes, "1.23.0", Some(44524), None), + + // Allows associated types to be generic, e.g., `type Foo;` (RFC 1598). + (active, generic_associated_types, "1.23.0", Some(44265), None), + + // Allows defining `trait X = A + B;` alias items. + (active, trait_alias, "1.24.0", Some(41517), None), + + // Allows infering `'static` outlives requirements (RFC 2093). + (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None), + + // Allows macro invocations in `extern {}` blocks. + (active, macros_in_extern, "1.27.0", Some(49476), None), + + // Allows accessing fields of unions inside `const` functions. + (active, const_fn_union, "1.27.0", Some(51909), None), + + // Allows casting raw pointers to `usize` during const eval. + (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None), + + // Allows dereferencing raw pointers during const eval. + (active, const_raw_ptr_deref, "1.27.0", Some(51911), None), + + // Allows comparing raw pointers during const eval. + (active, const_compare_raw_pointers, "1.27.0", Some(53020), None), + + // Allows `#[doc(alias = "...")]`. + (active, doc_alias, "1.27.0", Some(50146), None), + + // Allows inconsistent bounds in where clauses. + (active, trivial_bounds, "1.28.0", Some(48214), None), + + // Allows `'a: { break 'a; }`. + (active, label_break_value, "1.28.0", Some(48594), None), + + // Allows using `#[doc(keyword = "...")]`. + (active, doc_keyword, "1.28.0", Some(51315), None), + + // Allows reinterpretation of the bits of a value of one type as another type during const eval. + (active, const_transmute, "1.29.0", Some(53605), None), + + // Allows using `try {...}` expressions. + (active, try_blocks, "1.29.0", Some(31436), None), + + // Allows defining an `#[alloc_error_handler]`. + (active, alloc_error_handler, "1.29.0", Some(51540), None), + + // Allows using the `amdgpu-kernel` ABI. + (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None), + + // Allows panicking during const eval (producing compile-time errors). + (active, const_panic, "1.30.0", Some(51999), None), + + // Allows `#[marker]` on certain traits allowing overlapping implementations. + (active, marker_trait_attr, "1.30.0", Some(29864), None), + + // Allows macro invocations on modules expressions and statements and + // procedural macros to expand to non-items. + (active, proc_macro_hygiene, "1.30.0", Some(54727), None), + + // Allows unsized rvalues at arguments and parameters. + (active, unsized_locals, "1.30.0", Some(48055), None), + + // Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. + (active, custom_test_frameworks, "1.30.0", Some(50297), None), + + // Allows non-builtin attributes in inner attribute position. + (active, custom_inner_attributes, "1.30.0", Some(54726), None), + + // Allows mixing bind-by-move in patterns and references to those identifiers in guards. + (active, bind_by_move_pattern_guards, "1.30.0", Some(15287), None), + + // Allows `impl Trait` in bindings (`let`, `const`, `static`). + (active, impl_trait_in_bindings, "1.30.0", Some(63065), None), + + // Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. + (active, lint_reasons, "1.31.0", Some(54503), None), + + // Allows exhaustive integer pattern matching on `usize` and `isize`. + (active, precise_pointer_size_matching, "1.32.0", Some(56354), None), + + // Allows relaxing the coherence rules such that + // `impl ForeignTrait for ForeignType is permitted. + (active, re_rebalance_coherence, "1.32.0", Some(55437), None), + + // Allows using `#[ffi_returns_twice]` on foreign functions. + (active, ffi_returns_twice, "1.34.0", Some(58314), None), + + // Allows const generic types (e.g. `struct Foo(...);`). + (active, const_generics, "1.34.0", Some(44580), None), + + // Allows using `#[optimize(X)]`. + (active, optimize_attribute, "1.34.0", Some(54882), None), + + // Allows using C-variadics. + (active, c_variadic, "1.34.0", Some(44930), None), + + // Allows the user of associated type bounds. + (active, associated_type_bounds, "1.34.0", Some(52662), None), + + // Attributes on formal function params. + (active, param_attrs, "1.36.0", Some(60406), None), + + // Allows calling constructor functions in `const fn`. + (active, const_constructor, "1.37.0", Some(61456), None), + + // Allows `if/while p && let q = r && ...` chains. + (active, let_chains, "1.37.0", Some(53667), None), + + // Allows #[repr(transparent)] on enums (RFC 2645). + (active, transparent_enums, "1.37.0", Some(60405), None), + + // Allows #[repr(transparent)] on unions (RFC 2645). + (active, transparent_unions, "1.37.0", Some(60405), None), + + // Allows explicit discriminants on non-unit enum variants. + (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), + + // Allows `impl Trait` with multiple unrelated lifetimes. + (active, member_constraints, "1.37.0", Some(61977), None), + + // Allows `async || body` closures. + (active, async_closure, "1.37.0", Some(62290), None), + + // Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests + (active, cfg_doctest, "1.37.0", Some(62210), None), + + // Allows `[x; N]` where `x` is a constant (RFC 2203). + (active, const_in_array_repeat_expressions, "1.37.0", Some(49147), None), + + // Allows `impl Trait` to be used inside type aliases (RFC 2515). + (active, type_alias_impl_trait, "1.38.0", Some(63063), None), + + // Allows the use of or-patterns, e.g. `0 | 1`. + (active, or_patterns, "1.38.0", Some(54883), None), + + // ------------------------------------------------------------------------- + // feature-group-end: actual feature gates + // ------------------------------------------------------------------------- +); + +/// Some features are known to be incomplete and using them is likely to have +/// unanticipated results, such as compiler crashes. We warn the user about these +/// to alert them. +pub const INCOMPLETE_FEATURES: &[Symbol] = &[ + sym::impl_trait_in_bindings, + sym::generic_associated_types, + sym::const_generics, + sym::or_patterns, + sym::let_chains, +]; From 332a77e6212ccb96800c70d864a20aecce789136 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 22 Aug 2019 18:32:31 +0200 Subject: [PATCH 149/618] syntax: extract `builin_attrs.rs`. --- src/libsyntax/feature_gate.rs | 722 +------------------ src/libsyntax/feature_gate/attr.rs | 1 - src/libsyntax/feature_gate/builtin_attrs.rs | 724 ++++++++++++++++++++ 3 files changed, 732 insertions(+), 715 deletions(-) delete mode 100644 src/libsyntax/feature_gate/attr.rs create mode 100644 src/libsyntax/feature_gate/builtin_attrs.rs diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index f01b3af7af40b..0e04d4c6c2309 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -19,15 +19,18 @@ use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES}; mod active; use active::{ACTIVE_FEATURES}; pub use active::{Features, INCOMPLETE_FEATURES}; - -use AttributeType::*; -use AttributeGate::*; +mod builtin_attrs; +pub use builtin_attrs::{ + AttributeGate, AttributeType, GatedCfg, + BuiltinAttribute, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP, + deprecated_attributes, is_builtin_attr, is_builtin_attr_name, +}; use crate::ast::{ self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind, PatKind, RangeEnd, }; -use crate::attr::{self, check_builtin_attribute, AttributeTemplate}; +use crate::attr::{self, check_builtin_attribute}; use crate::source_map::Spanned; use crate::edition::{ALL_EDITIONS, Edition}; use crate::visit::{self, FnKind, Visitor}; @@ -41,67 +44,9 @@ use rustc_data_structures::fx::FxHashMap; use rustc_target::spec::abi::Abi; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use log::debug; -use lazy_static::lazy_static; use std::env; -// If you change this, please modify `src/doc/unstable-book` as well. You must -// move that documentation into the relevant place in the other docs, and -// remove the chapter on the flag. - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum AttributeType { - /// Normal, builtin attribute that is consumed - /// by the compiler before the unused_attribute check - Normal, - - /// Builtin attribute that may not be consumed by the compiler - /// before the unused_attribute check. These attributes - /// will be ignored by the unused_attribute lint - Whitelisted, - - /// Builtin attribute that is only allowed at the crate level - CrateLevel, -} - -pub enum AttributeGate { - /// Is gated by a given feature gate, reason - /// and function to check if enabled - Gated(Stability, Symbol, &'static str, fn(&Features) -> bool), - - /// Ungated attribute, can be used on all release channels - Ungated, -} - -/// A convenience macro for constructing attribute templates. -/// E.g., `template!(Word, List: "description")` means that the attribute -/// supports forms `#[attr]` and `#[attr(description)]`. -macro_rules! template { - (Word) => { template!(@ true, None, None) }; - (List: $descr: expr) => { template!(@ false, Some($descr), None) }; - (NameValueStr: $descr: expr) => { template!(@ false, None, Some($descr)) }; - (Word, List: $descr: expr) => { template!(@ true, Some($descr), None) }; - (Word, NameValueStr: $descr: expr) => { template!(@ true, None, Some($descr)) }; - (List: $descr1: expr, NameValueStr: $descr2: expr) => { - template!(@ false, Some($descr1), Some($descr2)) - }; - (Word, List: $descr1: expr, NameValueStr: $descr2: expr) => { - template!(@ true, Some($descr1), Some($descr2)) - }; - (@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate { - word: $word, list: $list, name_value_str: $name_value_str - } }; -} - -impl AttributeGate { - fn is_deprecated(&self) -> bool { - match *self { - Gated(Stability::Deprecated(_, _), ..) => true, - _ => false, - } - } -} - #[derive(Copy, Clone, Debug)] pub enum Stability { Unstable, @@ -110,657 +55,6 @@ pub enum Stability { Deprecated(&'static str, Option<&'static str>), } -// fn() is not Debug -impl std::fmt::Debug for AttributeGate { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match *self { - Gated(ref stab, name, expl, _) => - write!(fmt, "Gated({:?}, {}, {})", stab, name, expl), - Ungated => write!(fmt, "Ungated") - } - } -} - -macro_rules! cfg_fn { - ($field: ident) => {{ - fn f(features: &Features) -> bool { - features.$field - } - f as fn(&Features) -> bool - }} -} - -pub fn deprecated_attributes() -> Vec<&'static (Symbol, AttributeType, - AttributeTemplate, AttributeGate)> { - BUILTIN_ATTRIBUTES.iter().filter(|(.., gate)| gate.is_deprecated()).collect() -} - -pub fn is_builtin_attr_name(name: ast::Name) -> bool { - BUILTIN_ATTRIBUTE_MAP.get(&name).is_some() -} - -pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { - attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).is_some() -} - -/// Attributes that have a special meaning to rustc or rustdoc -pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ - // Normal attributes - - ( - sym::warn, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - ( - sym::allow, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - ( - sym::forbid, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - ( - sym::deny, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - - (sym::macro_use, Normal, template!(Word, List: "name1, name2, ..."), Ungated), - (sym::macro_export, Normal, template!(Word, List: "local_inner_macros"), Ungated), - (sym::plugin_registrar, Normal, template!(Word), Ungated), - - (sym::cfg, Normal, template!(List: "predicate"), Ungated), - (sym::cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), Ungated), - (sym::main, Normal, template!(Word), Ungated), - (sym::start, Normal, template!(Word), Ungated), - (sym::repr, Normal, template!(List: "C, packed, ..."), Ungated), - (sym::path, Normal, template!(NameValueStr: "file"), Ungated), - (sym::automatically_derived, Normal, template!(Word), Ungated), - (sym::no_mangle, Whitelisted, template!(Word), Ungated), - (sym::no_link, Normal, template!(Word), Ungated), - (sym::derive, Normal, template!(List: "Trait1, Trait2, ..."), Ungated), - ( - sym::should_panic, - Normal, - template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), - Ungated - ), - (sym::ignore, Normal, template!(Word, NameValueStr: "reason"), Ungated), - (sym::no_implicit_prelude, Normal, template!(Word), Ungated), - (sym::reexport_test_harness_main, Normal, template!(NameValueStr: "name"), Ungated), - (sym::link_args, Normal, template!(NameValueStr: "args"), Gated(Stability::Unstable, - sym::link_args, - "the `link_args` attribute is experimental and not \ - portable across platforms, it is recommended to \ - use `#[link(name = \"foo\")] instead", - cfg_fn!(link_args))), - (sym::macro_escape, Normal, template!(Word), Ungated), - - // RFC #1445. - (sym::structural_match, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::structural_match, - "the semantics of constant patterns is \ - not yet settled", - cfg_fn!(structural_match))), - - // RFC #2008 - (sym::non_exhaustive, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::non_exhaustive, - "non exhaustive is an experimental feature", - cfg_fn!(non_exhaustive))), - - // RFC #1268 - (sym::marker, Normal, template!(Word), Gated(Stability::Unstable, - sym::marker_trait_attr, - "marker traits is an experimental feature", - cfg_fn!(marker_trait_attr))), - - (sym::plugin, CrateLevel, template!(List: "name|name(args)"), Gated(Stability::Unstable, - sym::plugin, - "compiler plugins are experimental \ - and possibly buggy", - cfg_fn!(plugin))), - - (sym::no_std, CrateLevel, template!(Word), Ungated), - (sym::no_core, CrateLevel, template!(Word), Gated(Stability::Unstable, - sym::no_core, - "no_core is experimental", - cfg_fn!(no_core))), - (sym::lang, Normal, template!(NameValueStr: "name"), Gated(Stability::Unstable, - sym::lang_items, - "language items are subject to change", - cfg_fn!(lang_items))), - (sym::linkage, Whitelisted, template!(NameValueStr: "external|internal|..."), - Gated(Stability::Unstable, - sym::linkage, - "the `linkage` attribute is experimental \ - and not portable across platforms", - cfg_fn!(linkage))), - (sym::thread_local, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::thread_local, - "`#[thread_local]` is an experimental feature, and does \ - not currently handle destructors", - cfg_fn!(thread_local))), - - (sym::rustc_on_unimplemented, Whitelisted, template!(List: - r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, - NameValueStr: "message"), - Gated(Stability::Unstable, - sym::on_unimplemented, - "the `#[rustc_on_unimplemented]` attribute \ - is an experimental feature", - cfg_fn!(on_unimplemented))), - (sym::rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), - Gated(Stability::Unstable, - sym::rustc_const_unstable, - "the `#[rustc_const_unstable]` attribute \ - is an internal feature", - cfg_fn!(rustc_const_unstable))), - (sym::default_lib_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::allocator_internals, - "the `#[default_lib_allocator]` \ - attribute is an experimental feature", - cfg_fn!(allocator_internals))), - (sym::needs_allocator, Normal, template!(Word), Gated(Stability::Unstable, - sym::allocator_internals, - "the `#[needs_allocator]` \ - attribute is an experimental \ - feature", - cfg_fn!(allocator_internals))), - (sym::panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::panic_runtime, - "the `#[panic_runtime]` attribute is \ - an experimental feature", - cfg_fn!(panic_runtime))), - (sym::needs_panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::needs_panic_runtime, - "the `#[needs_panic_runtime]` \ - attribute is an experimental \ - feature", - cfg_fn!(needs_panic_runtime))), - (sym::rustc_outlives, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_outlives]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_variance, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_variance]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_layout, Normal, template!(List: "field1, field2, ..."), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_layout]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_layout_scalar_valid_range_start, Whitelisted, template!(List: "value"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_layout_scalar_valid_range_start]` attribute \ - is just used to enable niche optimizations in libcore \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_layout_scalar_valid_range_end, Whitelisted, template!(List: "value"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_layout_scalar_valid_range_end]` attribute \ - is just used to enable niche optimizations in libcore \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_nonnull_optimization_guaranteed, Whitelisted, template!(Word), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_nonnull_optimization_guaranteed]` attribute \ - is just used to enable niche optimizations in libcore \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_regions, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_regions]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_error, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_error]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_dump_user_substs, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_if_this_changed]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_then_this_would_need, Whitelisted, template!(List: "DepNode"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_if_this_changed]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_dirty, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", - /*opt*/ except = "...""#), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_dirty]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_clean, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", - /*opt*/ except = "...""#), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_clean]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - ( - sym::rustc_partition_reused, - Whitelisted, - template!(List: r#"cfg = "...", module = "...""#), - Gated( - Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs) - ) - ), - ( - sym::rustc_partition_codegened, - Whitelisted, - template!(List: r#"cfg = "...", module = "...""#), - Gated( - Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs), - ) - ), - (sym::rustc_expected_cgu_reuse, Whitelisted, template!(List: r#"cfg = "...", module = "...", - kind = "...""#), - Gated(Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_synthetic, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_symbol_name, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal rustc attributes will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_def_path, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal rustc attributes will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_mir, Whitelisted, template!(List: "arg1, arg2, ..."), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_mir]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - ( - sym::rustc_inherit_overflow_checks, - Whitelisted, - template!(Word), - Gated( - Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_inherit_overflow_checks]` \ - attribute is just used to control \ - overflow checking behavior of several \ - libcore functions that are inlined \ - across crates and will never be stable", - cfg_fn!(rustc_attrs), - ) - ), - - (sym::rustc_dump_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_dump_program_clauses]` \ - attribute is just used for rustc unit \ - tests and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_dump_env_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_dump_env_program_clauses]` \ - attribute is just used for rustc unit \ - tests and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_object_lifetime_default, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_object_lifetime_default]` \ - attribute is just used for rustc unit \ - tests and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_test_marker, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_test_marker]` attribute \ - is used internally to track tests", - cfg_fn!(rustc_attrs))), - (sym::rustc_macro_transparency, Whitelisted, template!(NameValueStr: - "transparent|semitransparent|opaque"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "used internally for testing macro hygiene", - cfg_fn!(rustc_attrs))), - (sym::compiler_builtins, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::compiler_builtins, - "the `#[compiler_builtins]` attribute is used to \ - identify the `compiler_builtins` crate which \ - contains compiler-rt intrinsics and will never be \ - stable", - cfg_fn!(compiler_builtins))), - (sym::sanitizer_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::sanitizer_runtime, - "the `#[sanitizer_runtime]` attribute is used to \ - identify crates that contain the runtime of a \ - sanitizer and will never be stable", - cfg_fn!(sanitizer_runtime))), - (sym::profiler_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::profiler_runtime, - "the `#[profiler_runtime]` attribute is used to \ - identify the `profiler_builtins` crate which \ - contains the profiler runtime and will never be \ - stable", - cfg_fn!(profiler_runtime))), - - (sym::allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), - Gated(Stability::Unstable, - sym::allow_internal_unstable, - EXPLAIN_ALLOW_INTERNAL_UNSTABLE, - cfg_fn!(allow_internal_unstable))), - - (sym::allow_internal_unsafe, Normal, template!(Word), Gated(Stability::Unstable, - sym::allow_internal_unsafe, - EXPLAIN_ALLOW_INTERNAL_UNSAFE, - cfg_fn!(allow_internal_unsafe))), - - (sym::fundamental, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::fundamental, - "the `#[fundamental]` attribute \ - is an experimental feature", - cfg_fn!(fundamental))), - - (sym::proc_macro_derive, Normal, template!(List: "TraitName, \ - /*opt*/ attributes(name1, name2, ...)"), - Ungated), - - (sym::rustc_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_allocator_nounwind, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_builtin_macro, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_promotable, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_allow_const_fn_ptr, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_dummy, Normal, template!(Word /* doesn't matter*/), Gated(Stability::Unstable, - sym::rustc_attrs, - "used by the test suite", - cfg_fn!(rustc_attrs))), - - // FIXME: #14408 whitelist docs since rustdoc looks at them - ( - sym::doc, - Whitelisted, - template!(List: "hidden|inline|...", NameValueStr: "string"), - Ungated - ), - - // FIXME: #14406 these are processed in codegen, which happens after the - // lint pass - (sym::cold, Whitelisted, template!(Word), Ungated), - (sym::naked, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::naked_functions, - "the `#[naked]` attribute \ - is an experimental feature", - cfg_fn!(naked_functions))), - (sym::ffi_returns_twice, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::ffi_returns_twice, - "the `#[ffi_returns_twice]` attribute \ - is an experimental feature", - cfg_fn!(ffi_returns_twice))), - (sym::target_feature, Whitelisted, template!(List: r#"enable = "name""#), Ungated), - (sym::export_name, Whitelisted, template!(NameValueStr: "name"), Ungated), - (sym::inline, Whitelisted, template!(Word, List: "always|never"), Ungated), - (sym::link, Whitelisted, template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", - /*opt*/ cfg = "...""#), Ungated), - (sym::link_name, Whitelisted, template!(NameValueStr: "name"), Ungated), - (sym::link_section, Whitelisted, template!(NameValueStr: "name"), Ungated), - (sym::no_builtins, Whitelisted, template!(Word), Ungated), - (sym::no_debug, Whitelisted, template!(Word), Gated( - Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None), - sym::no_debug, - "the `#[no_debug]` attribute was an experimental feature that has been \ - deprecated due to lack of demand", - cfg_fn!(no_debug))), - ( - sym::omit_gdb_pretty_printer_section, - Whitelisted, - template!(Word), - Gated( - Stability::Unstable, - sym::omit_gdb_pretty_printer_section, - "the `#[omit_gdb_pretty_printer_section]` \ - attribute is just used for the Rust test \ - suite", - cfg_fn!(omit_gdb_pretty_printer_section) - ) - ), - (sym::may_dangle, - Normal, - template!(Word), - Gated(Stability::Unstable, - sym::dropck_eyepatch, - "`may_dangle` has unstable semantics and may be removed in the future", - cfg_fn!(dropck_eyepatch))), - (sym::unwind, Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable, - sym::unwind_attributes, - "`#[unwind]` is experimental", - cfg_fn!(unwind_attributes))), - (sym::used, Whitelisted, template!(Word), Ungated), - - // used in resolve - (sym::prelude_import, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::prelude_import, - "`#[prelude_import]` is for use by rustc only", - cfg_fn!(prelude_import))), - - // FIXME: #14407 these are only looked at on-demand so we can't - // guarantee they'll have already been checked - ( - sym::rustc_deprecated, - Whitelisted, - template!(List: r#"since = "version", reason = "...""#), - Ungated - ), - (sym::must_use, Whitelisted, template!(Word, NameValueStr: "reason"), Ungated), - ( - sym::stable, - Whitelisted, - template!(List: r#"feature = "name", since = "version""#), - Ungated - ), - ( - sym::unstable, - Whitelisted, - template!(List: r#"feature = "name", reason = "...", issue = "N""#), - Ungated - ), - (sym::deprecated, - Normal, - template!( - Word, - List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, - NameValueStr: "reason" - ), - Ungated - ), - - (sym::rustc_paren_sugar, Normal, template!(Word), Gated(Stability::Unstable, - sym::unboxed_closures, - "unboxed_closures are still evolving", - cfg_fn!(unboxed_closures))), - - (sym::windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console"), Ungated), - - (sym::proc_macro_attribute, Normal, template!(Word), Ungated), - (sym::proc_macro, Normal, template!(Word), Ungated), - - (sym::rustc_proc_macro_decls, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "used internally by rustc", - cfg_fn!(rustc_attrs))), - - (sym::allow_fail, Normal, template!(Word), Gated(Stability::Unstable, - sym::allow_fail, - "allow_fail attribute is currently unstable", - cfg_fn!(allow_fail))), - - (sym::rustc_std_internal_symbol, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this is an internal attribute that will \ - never be stable", - cfg_fn!(rustc_attrs))), - - // whitelists "identity-like" conversion methods to suggest on type mismatch - (sym::rustc_conversion_suggestion, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this is an internal attribute that will \ - never be stable", - cfg_fn!(rustc_attrs))), - - ( - sym::rustc_args_required_const, - Whitelisted, - template!(List: "N"), - Gated(Stability::Unstable, sym::rustc_attrs, "never will be stable", - cfg_fn!(rustc_attrs)) - ), - // RFC 2070 - (sym::panic_handler, Normal, template!(Word), Ungated), - - (sym::alloc_error_handler, Normal, template!(Word), Gated(Stability::Unstable, - sym::alloc_error_handler, - "`#[alloc_error_handler]` is an unstable feature", - cfg_fn!(alloc_error_handler))), - - // RFC 2412 - (sym::optimize, Whitelisted, template!(List: "size|speed"), Gated(Stability::Unstable, - sym::optimize_attribute, - "`#[optimize]` attribute is an unstable feature", - cfg_fn!(optimize_attribute))), - - // Crate level attributes - (sym::crate_name, CrateLevel, template!(NameValueStr: "name"), Ungated), - (sym::crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), Ungated), - (sym::crate_id, CrateLevel, template!(NameValueStr: "ignored"), Ungated), - (sym::feature, CrateLevel, template!(List: "name1, name1, ..."), Ungated), - (sym::no_start, CrateLevel, template!(Word), Ungated), - (sym::no_main, CrateLevel, template!(Word), Ungated), - (sym::recursion_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), - (sym::type_length_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), - (sym::test_runner, CrateLevel, template!(List: "path"), Gated(Stability::Unstable, - sym::custom_test_frameworks, - "custom test frameworks are an unstable feature", - cfg_fn!(custom_test_frameworks))), -]; - -pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate); - -lazy_static! { - pub static ref BUILTIN_ATTRIBUTE_MAP: FxHashMap = { - let mut map = FxHashMap::default(); - for attr in BUILTIN_ATTRIBUTES.iter() { - if map.insert(attr.0, attr).is_some() { - panic!("duplicate builtin attribute `{}`", attr.0); - } - } - map - }; -} - -// cfg(...)'s that are feature gated -const GATED_CFGS: &[(Symbol, Symbol, fn(&Features) -> bool)] = &[ - // (name in cfg, feature, function to check if the feature is enabled) - (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), - (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), - (sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)), - (sym::doctest, sym::cfg_doctest, cfg_fn!(cfg_doctest)), -]; - -#[derive(Debug)] -pub struct GatedCfg { - span: Span, - index: usize, -} - -impl GatedCfg { - pub fn gate(cfg: &ast::MetaItem) -> Option { - GATED_CFGS.iter() - .position(|info| cfg.check_name(info.0)) - .map(|idx| { - GatedCfg { - span: cfg.span, - index: idx - } - }) - } - - pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) { - let (cfg, feature, has_feature) = GATED_CFGS[self.index]; - if !has_feature(features) && !self.span.allows_unstable(feature) { - let explain = format!("`cfg({})` is experimental and subject to change", cfg); - emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain); - } - } -} - struct Context<'a> { features: &'a Features, parse_sess: &'a ParseSess, @@ -800,7 +94,7 @@ impl<'a> Context<'a> { ) { debug!("check_attribute(attr = {:?})", attr); if let Some(&(name, ty, _template, ref gateage)) = attr_info { - if let Gated(_, name, desc, ref has_feature) = *gateage { + if let AttributeGate::Gated(_, name, desc, ref has_feature) = *gateage { if !attr.span.allows_unstable(name) { gate_feature_fn!( self, has_feature, attr.span, name, desc, GateStrength::Hard diff --git a/src/libsyntax/feature_gate/attr.rs b/src/libsyntax/feature_gate/attr.rs deleted file mode 100644 index 46330df364852..0000000000000 --- a/src/libsyntax/feature_gate/attr.rs +++ /dev/null @@ -1 +0,0 @@ -//! TODO diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs new file mode 100644 index 0000000000000..17e58df89e137 --- /dev/null +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -0,0 +1,724 @@ +//! Built-in attributes and `cfg` flag gating. + +use AttributeType::*; +use AttributeGate::*; + +use super::{emit_feature_err, GateIssue}; +use super::{Stability, EXPLAIN_ALLOW_INTERNAL_UNSAFE, EXPLAIN_ALLOW_INTERNAL_UNSTABLE}; +use super::active::Features; + +use crate::ast; +use crate::attr::AttributeTemplate; +use crate::symbol::{Symbol, sym}; +use crate::parse::ParseSess; + +use syntax_pos::Span; +use rustc_data_structures::fx::FxHashMap; +use lazy_static::lazy_static; + +macro_rules! cfg_fn { + ($field: ident) => {{ + fn f(features: &Features) -> bool { + features.$field + } + f as fn(&Features) -> bool + }} +} + +// cfg(...)'s that are feature gated +const GATED_CFGS: &[(Symbol, Symbol, fn(&Features) -> bool)] = &[ + // (name in cfg, feature, function to check if the feature is enabled) + (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), + (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), + (sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)), + (sym::doctest, sym::cfg_doctest, cfg_fn!(cfg_doctest)), +]; + +#[derive(Debug)] +pub struct GatedCfg { + span: Span, + index: usize, +} + +impl GatedCfg { + pub fn gate(cfg: &ast::MetaItem) -> Option { + GATED_CFGS.iter() + .position(|info| cfg.check_name(info.0)) + .map(|idx| { + GatedCfg { + span: cfg.span, + index: idx + } + }) + } + + pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) { + let (cfg, feature, has_feature) = GATED_CFGS[self.index]; + if !has_feature(features) && !self.span.allows_unstable(feature) { + let explain = format!("`cfg({})` is experimental and subject to change", cfg); + emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain); + } + } +} + +// If you change this, please modify `src/doc/unstable-book` as well. You must +// move that documentation into the relevant place in the other docs, and +// remove the chapter on the flag. + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum AttributeType { + /// Normal, builtin attribute that is consumed + /// by the compiler before the unused_attribute check + Normal, + + /// Builtin attribute that may not be consumed by the compiler + /// before the unused_attribute check. These attributes + /// will be ignored by the unused_attribute lint + Whitelisted, + + /// Builtin attribute that is only allowed at the crate level + CrateLevel, +} + +pub enum AttributeGate { + /// Is gated by a given feature gate, reason + /// and function to check if enabled + Gated(Stability, Symbol, &'static str, fn(&Features) -> bool), + + /// Ungated attribute, can be used on all release channels + Ungated, +} + +// fn() is not Debug +impl std::fmt::Debug for AttributeGate { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self { + Self::Gated(ref stab, name, expl, _) => + write!(fmt, "Gated({:?}, {}, {})", stab, name, expl), + Self::Ungated => write!(fmt, "Ungated") + } + } +} + +impl AttributeGate { + fn is_deprecated(&self) -> bool { + match *self { + Self::Gated(Stability::Deprecated(_, _), ..) => true, + _ => false, + } + } +} + +/// A convenience macro for constructing attribute templates. +/// E.g., `template!(Word, List: "description")` means that the attribute +/// supports forms `#[attr]` and `#[attr(description)]`. +macro_rules! template { + (Word) => { template!(@ true, None, None) }; + (List: $descr: expr) => { template!(@ false, Some($descr), None) }; + (NameValueStr: $descr: expr) => { template!(@ false, None, Some($descr)) }; + (Word, List: $descr: expr) => { template!(@ true, Some($descr), None) }; + (Word, NameValueStr: $descr: expr) => { template!(@ true, None, Some($descr)) }; + (List: $descr1: expr, NameValueStr: $descr2: expr) => { + template!(@ false, Some($descr1), Some($descr2)) + }; + (Word, List: $descr1: expr, NameValueStr: $descr2: expr) => { + template!(@ true, Some($descr1), Some($descr2)) + }; + (@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate { + word: $word, list: $list, name_value_str: $name_value_str + } }; +} + +pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate); + +/// Attributes that have a special meaning to rustc or rustdoc +pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ + // Normal attributes + + ( + sym::warn, + Normal, + template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), + Ungated + ), + ( + sym::allow, + Normal, + template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), + Ungated + ), + ( + sym::forbid, + Normal, + template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), + Ungated + ), + ( + sym::deny, + Normal, + template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), + Ungated + ), + + (sym::macro_use, Normal, template!(Word, List: "name1, name2, ..."), Ungated), + (sym::macro_export, Normal, template!(Word, List: "local_inner_macros"), Ungated), + (sym::plugin_registrar, Normal, template!(Word), Ungated), + + (sym::cfg, Normal, template!(List: "predicate"), Ungated), + (sym::cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), Ungated), + (sym::main, Normal, template!(Word), Ungated), + (sym::start, Normal, template!(Word), Ungated), + (sym::repr, Normal, template!(List: "C, packed, ..."), Ungated), + (sym::path, Normal, template!(NameValueStr: "file"), Ungated), + (sym::automatically_derived, Normal, template!(Word), Ungated), + (sym::no_mangle, Whitelisted, template!(Word), Ungated), + (sym::no_link, Normal, template!(Word), Ungated), + (sym::derive, Normal, template!(List: "Trait1, Trait2, ..."), Ungated), + ( + sym::should_panic, + Normal, + template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), + Ungated + ), + (sym::ignore, Normal, template!(Word, NameValueStr: "reason"), Ungated), + (sym::no_implicit_prelude, Normal, template!(Word), Ungated), + (sym::reexport_test_harness_main, Normal, template!(NameValueStr: "name"), Ungated), + (sym::link_args, Normal, template!(NameValueStr: "args"), Gated(Stability::Unstable, + sym::link_args, + "the `link_args` attribute is experimental and not \ + portable across platforms, it is recommended to \ + use `#[link(name = \"foo\")] instead", + cfg_fn!(link_args))), + (sym::macro_escape, Normal, template!(Word), Ungated), + + // RFC #1445. + (sym::structural_match, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::structural_match, + "the semantics of constant patterns is \ + not yet settled", + cfg_fn!(structural_match))), + + // RFC #2008 + (sym::non_exhaustive, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::non_exhaustive, + "non exhaustive is an experimental feature", + cfg_fn!(non_exhaustive))), + + // RFC #1268 + (sym::marker, Normal, template!(Word), Gated(Stability::Unstable, + sym::marker_trait_attr, + "marker traits is an experimental feature", + cfg_fn!(marker_trait_attr))), + + (sym::plugin, CrateLevel, template!(List: "name|name(args)"), Gated(Stability::Unstable, + sym::plugin, + "compiler plugins are experimental \ + and possibly buggy", + cfg_fn!(plugin))), + + (sym::no_std, CrateLevel, template!(Word), Ungated), + (sym::no_core, CrateLevel, template!(Word), Gated(Stability::Unstable, + sym::no_core, + "no_core is experimental", + cfg_fn!(no_core))), + (sym::lang, Normal, template!(NameValueStr: "name"), Gated(Stability::Unstable, + sym::lang_items, + "language items are subject to change", + cfg_fn!(lang_items))), + (sym::linkage, Whitelisted, template!(NameValueStr: "external|internal|..."), + Gated(Stability::Unstable, + sym::linkage, + "the `linkage` attribute is experimental \ + and not portable across platforms", + cfg_fn!(linkage))), + (sym::thread_local, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::thread_local, + "`#[thread_local]` is an experimental feature, and does \ + not currently handle destructors", + cfg_fn!(thread_local))), + + (sym::rustc_on_unimplemented, Whitelisted, template!(List: + r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, + NameValueStr: "message"), + Gated(Stability::Unstable, + sym::on_unimplemented, + "the `#[rustc_on_unimplemented]` attribute \ + is an experimental feature", + cfg_fn!(on_unimplemented))), + (sym::rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), + Gated(Stability::Unstable, + sym::rustc_const_unstable, + "the `#[rustc_const_unstable]` attribute \ + is an internal feature", + cfg_fn!(rustc_const_unstable))), + (sym::default_lib_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::allocator_internals, + "the `#[default_lib_allocator]` \ + attribute is an experimental feature", + cfg_fn!(allocator_internals))), + (sym::needs_allocator, Normal, template!(Word), Gated(Stability::Unstable, + sym::allocator_internals, + "the `#[needs_allocator]` \ + attribute is an experimental \ + feature", + cfg_fn!(allocator_internals))), + (sym::panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::panic_runtime, + "the `#[panic_runtime]` attribute is \ + an experimental feature", + cfg_fn!(panic_runtime))), + (sym::needs_panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::needs_panic_runtime, + "the `#[needs_panic_runtime]` \ + attribute is an experimental \ + feature", + cfg_fn!(needs_panic_runtime))), + (sym::rustc_outlives, Normal, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_outlives]` attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_variance, Normal, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_variance]` attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_layout, Normal, template!(List: "field1, field2, ..."), + Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_layout]` attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_layout_scalar_valid_range_start, Whitelisted, template!(List: "value"), + Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_layout_scalar_valid_range_start]` attribute \ + is just used to enable niche optimizations in libcore \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_layout_scalar_valid_range_end, Whitelisted, template!(List: "value"), + Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_layout_scalar_valid_range_end]` attribute \ + is just used to enable niche optimizations in libcore \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_nonnull_optimization_guaranteed, Whitelisted, template!(Word), + Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_nonnull_optimization_guaranteed]` attribute \ + is just used to enable niche optimizations in libcore \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_regions, Normal, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_regions]` attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_error, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_error]` attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_dump_user_substs, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "this attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode"), + Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_if_this_changed]` attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_then_this_would_need, Whitelisted, template!(List: "DepNode"), + Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_if_this_changed]` attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_dirty, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", + /*opt*/ except = "...""#), + Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_dirty]` attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_clean, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", + /*opt*/ except = "...""#), + Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_clean]` attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), + ( + sym::rustc_partition_reused, + Whitelisted, + template!(List: r#"cfg = "...", module = "...""#), + Gated( + Stability::Unstable, + sym::rustc_attrs, + "this attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs) + ) + ), + ( + sym::rustc_partition_codegened, + Whitelisted, + template!(List: r#"cfg = "...", module = "...""#), + Gated( + Stability::Unstable, + sym::rustc_attrs, + "this attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs), + ) + ), + (sym::rustc_expected_cgu_reuse, Whitelisted, template!(List: r#"cfg = "...", module = "...", + kind = "...""#), + Gated(Stability::Unstable, + sym::rustc_attrs, + "this attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_synthetic, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "this attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_symbol_name, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "internal rustc attributes will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_def_path, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "internal rustc attributes will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_mir, Whitelisted, template!(List: "arg1, arg2, ..."), Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_mir]` attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), + ( + sym::rustc_inherit_overflow_checks, + Whitelisted, + template!(Word), + Gated( + Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_inherit_overflow_checks]` \ + attribute is just used to control \ + overflow checking behavior of several \ + libcore functions that are inlined \ + across crates and will never be stable", + cfg_fn!(rustc_attrs), + ) + ), + + (sym::rustc_dump_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_dump_program_clauses]` \ + attribute is just used for rustc unit \ + tests and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_dump_env_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_dump_env_program_clauses]` \ + attribute is just used for rustc unit \ + tests and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_object_lifetime_default, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_object_lifetime_default]` \ + attribute is just used for rustc unit \ + tests and will never be stable", + cfg_fn!(rustc_attrs))), + (sym::rustc_test_marker, Normal, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_test_marker]` attribute \ + is used internally to track tests", + cfg_fn!(rustc_attrs))), + (sym::rustc_macro_transparency, Whitelisted, template!(NameValueStr: + "transparent|semitransparent|opaque"), + Gated(Stability::Unstable, + sym::rustc_attrs, + "used internally for testing macro hygiene", + cfg_fn!(rustc_attrs))), + (sym::compiler_builtins, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::compiler_builtins, + "the `#[compiler_builtins]` attribute is used to \ + identify the `compiler_builtins` crate which \ + contains compiler-rt intrinsics and will never be \ + stable", + cfg_fn!(compiler_builtins))), + (sym::sanitizer_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::sanitizer_runtime, + "the `#[sanitizer_runtime]` attribute is used to \ + identify crates that contain the runtime of a \ + sanitizer and will never be stable", + cfg_fn!(sanitizer_runtime))), + (sym::profiler_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::profiler_runtime, + "the `#[profiler_runtime]` attribute is used to \ + identify the `profiler_builtins` crate which \ + contains the profiler runtime and will never be \ + stable", + cfg_fn!(profiler_runtime))), + + (sym::allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), + Gated(Stability::Unstable, + sym::allow_internal_unstable, + EXPLAIN_ALLOW_INTERNAL_UNSTABLE, + cfg_fn!(allow_internal_unstable))), + + (sym::allow_internal_unsafe, Normal, template!(Word), Gated(Stability::Unstable, + sym::allow_internal_unsafe, + EXPLAIN_ALLOW_INTERNAL_UNSAFE, + cfg_fn!(allow_internal_unsafe))), + + (sym::fundamental, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::fundamental, + "the `#[fundamental]` attribute \ + is an experimental feature", + cfg_fn!(fundamental))), + + (sym::proc_macro_derive, Normal, template!(List: "TraitName, \ + /*opt*/ attributes(name1, name2, ...)"), + Ungated), + + (sym::rustc_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "internal implementation detail", + cfg_fn!(rustc_attrs))), + + (sym::rustc_allocator_nounwind, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "internal implementation detail", + cfg_fn!(rustc_attrs))), + + (sym::rustc_builtin_macro, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "internal implementation detail", + cfg_fn!(rustc_attrs))), + + (sym::rustc_promotable, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "internal implementation detail", + cfg_fn!(rustc_attrs))), + + (sym::rustc_allow_const_fn_ptr, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "internal implementation detail", + cfg_fn!(rustc_attrs))), + + (sym::rustc_dummy, Normal, template!(Word /* doesn't matter*/), Gated(Stability::Unstable, + sym::rustc_attrs, + "used by the test suite", + cfg_fn!(rustc_attrs))), + + // FIXME: #14408 whitelist docs since rustdoc looks at them + ( + sym::doc, + Whitelisted, + template!(List: "hidden|inline|...", NameValueStr: "string"), + Ungated + ), + + // FIXME: #14406 these are processed in codegen, which happens after the + // lint pass + (sym::cold, Whitelisted, template!(Word), Ungated), + (sym::naked, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::naked_functions, + "the `#[naked]` attribute \ + is an experimental feature", + cfg_fn!(naked_functions))), + (sym::ffi_returns_twice, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::ffi_returns_twice, + "the `#[ffi_returns_twice]` attribute \ + is an experimental feature", + cfg_fn!(ffi_returns_twice))), + (sym::target_feature, Whitelisted, template!(List: r#"enable = "name""#), Ungated), + (sym::export_name, Whitelisted, template!(NameValueStr: "name"), Ungated), + (sym::inline, Whitelisted, template!(Word, List: "always|never"), Ungated), + (sym::link, Whitelisted, template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", + /*opt*/ cfg = "...""#), Ungated), + (sym::link_name, Whitelisted, template!(NameValueStr: "name"), Ungated), + (sym::link_section, Whitelisted, template!(NameValueStr: "name"), Ungated), + (sym::no_builtins, Whitelisted, template!(Word), Ungated), + (sym::no_debug, Whitelisted, template!(Word), Gated( + Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None), + sym::no_debug, + "the `#[no_debug]` attribute was an experimental feature that has been \ + deprecated due to lack of demand", + cfg_fn!(no_debug))), + ( + sym::omit_gdb_pretty_printer_section, + Whitelisted, + template!(Word), + Gated( + Stability::Unstable, + sym::omit_gdb_pretty_printer_section, + "the `#[omit_gdb_pretty_printer_section]` \ + attribute is just used for the Rust test \ + suite", + cfg_fn!(omit_gdb_pretty_printer_section) + ) + ), + (sym::may_dangle, + Normal, + template!(Word), + Gated(Stability::Unstable, + sym::dropck_eyepatch, + "`may_dangle` has unstable semantics and may be removed in the future", + cfg_fn!(dropck_eyepatch))), + (sym::unwind, Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable, + sym::unwind_attributes, + "`#[unwind]` is experimental", + cfg_fn!(unwind_attributes))), + (sym::used, Whitelisted, template!(Word), Ungated), + + // used in resolve + (sym::prelude_import, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::prelude_import, + "`#[prelude_import]` is for use by rustc only", + cfg_fn!(prelude_import))), + + // FIXME: #14407 these are only looked at on-demand so we can't + // guarantee they'll have already been checked + ( + sym::rustc_deprecated, + Whitelisted, + template!(List: r#"since = "version", reason = "...""#), + Ungated + ), + (sym::must_use, Whitelisted, template!(Word, NameValueStr: "reason"), Ungated), + ( + sym::stable, + Whitelisted, + template!(List: r#"feature = "name", since = "version""#), + Ungated + ), + ( + sym::unstable, + Whitelisted, + template!(List: r#"feature = "name", reason = "...", issue = "N""#), + Ungated + ), + (sym::deprecated, + Normal, + template!( + Word, + List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, + NameValueStr: "reason" + ), + Ungated + ), + + (sym::rustc_paren_sugar, Normal, template!(Word), Gated(Stability::Unstable, + sym::unboxed_closures, + "unboxed_closures are still evolving", + cfg_fn!(unboxed_closures))), + + (sym::windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console"), Ungated), + + (sym::proc_macro_attribute, Normal, template!(Word), Ungated), + (sym::proc_macro, Normal, template!(Word), Ungated), + + (sym::rustc_proc_macro_decls, Normal, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "used internally by rustc", + cfg_fn!(rustc_attrs))), + + (sym::allow_fail, Normal, template!(Word), Gated(Stability::Unstable, + sym::allow_fail, + "allow_fail attribute is currently unstable", + cfg_fn!(allow_fail))), + + (sym::rustc_std_internal_symbol, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "this is an internal attribute that will \ + never be stable", + cfg_fn!(rustc_attrs))), + + // whitelists "identity-like" conversion methods to suggest on type mismatch + (sym::rustc_conversion_suggestion, Whitelisted, template!(Word), Gated(Stability::Unstable, + sym::rustc_attrs, + "this is an internal attribute that will \ + never be stable", + cfg_fn!(rustc_attrs))), + + ( + sym::rustc_args_required_const, + Whitelisted, + template!(List: "N"), + Gated(Stability::Unstable, sym::rustc_attrs, "never will be stable", + cfg_fn!(rustc_attrs)) + ), + // RFC 2070 + (sym::panic_handler, Normal, template!(Word), Ungated), + + (sym::alloc_error_handler, Normal, template!(Word), Gated(Stability::Unstable, + sym::alloc_error_handler, + "`#[alloc_error_handler]` is an unstable feature", + cfg_fn!(alloc_error_handler))), + + // RFC 2412 + (sym::optimize, Whitelisted, template!(List: "size|speed"), Gated(Stability::Unstable, + sym::optimize_attribute, + "`#[optimize]` attribute is an unstable feature", + cfg_fn!(optimize_attribute))), + + // Crate level attributes + (sym::crate_name, CrateLevel, template!(NameValueStr: "name"), Ungated), + (sym::crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), Ungated), + (sym::crate_id, CrateLevel, template!(NameValueStr: "ignored"), Ungated), + (sym::feature, CrateLevel, template!(List: "name1, name1, ..."), Ungated), + (sym::no_start, CrateLevel, template!(Word), Ungated), + (sym::no_main, CrateLevel, template!(Word), Ungated), + (sym::recursion_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), + (sym::type_length_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), + (sym::test_runner, CrateLevel, template!(List: "path"), Gated(Stability::Unstable, + sym::custom_test_frameworks, + "custom test frameworks are an unstable feature", + cfg_fn!(custom_test_frameworks))), +]; + +pub fn deprecated_attributes() -> Vec<&'static BuiltinAttribute> { + BUILTIN_ATTRIBUTES.iter().filter(|(.., gate)| gate.is_deprecated()).collect() +} + +pub fn is_builtin_attr_name(name: ast::Name) -> bool { + BUILTIN_ATTRIBUTE_MAP.get(&name).is_some() +} + +pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { + attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).is_some() +} + +lazy_static! { + pub static ref BUILTIN_ATTRIBUTE_MAP: FxHashMap = { + let mut map = FxHashMap::default(); + for attr in BUILTIN_ATTRIBUTES.iter() { + if map.insert(attr.0, attr).is_some() { + panic!("duplicate builtin attribute `{}`", attr.0); + } + } + map + }; +} From 1c979ad55256d065a6d035a01910726a16644223 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 22 Aug 2019 18:37:28 +0200 Subject: [PATCH 150/618] builtin_attrs.rs: simplify `cfg_fn`. --- src/libsyntax/feature_gate/builtin_attrs.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index 17e58df89e137..7cd295b1b2cbf 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -16,17 +16,16 @@ use syntax_pos::Span; use rustc_data_structures::fx::FxHashMap; use lazy_static::lazy_static; +type GateFn = fn(&Features) -> bool; + macro_rules! cfg_fn { - ($field: ident) => {{ - fn f(features: &Features) -> bool { - features.$field - } - f as fn(&Features) -> bool - }} + ($field: ident) => { + (|features| { features.$field }) as GateFn + } } -// cfg(...)'s that are feature gated -const GATED_CFGS: &[(Symbol, Symbol, fn(&Features) -> bool)] = &[ +/// `cfg(...)`'s that are feature gated. +const GATED_CFGS: &[(Symbol, Symbol, GateFn)] = &[ // (name in cfg, feature, function to check if the feature is enabled) (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), From 0d19d1d7752bfed460bf7899171865441d6a2d87 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 22 Aug 2019 19:37:04 +0200 Subject: [PATCH 151/618] builtin_attrs.rs: refactor `rustc_attrs` entries. --- src/libsyntax/feature_gate/builtin_attrs.rs | 342 +++++++------------- 1 file changed, 109 insertions(+), 233 deletions(-) diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index 7cd295b1b2cbf..ad2e6a3feac6f 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -128,6 +128,21 @@ macro_rules! template { } }; } +macro_rules! rustc_attr { + (TEST, $gate:ident, $typ:expr, $tpl:expr $(,)?) => { + rustc_attr!( + $gate, $typ, $tpl, + concat!("the `#[", stringify!($gate), "]` attribute is just used for rustc unit tests \ + and will never be stable", + ), + ) + }; + ($gate:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { + (sym::$gate, $typ, $tpl, + Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs))) + }; +} + pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate); /// Attributes that have a special meaning to rustc or rustdoc @@ -272,193 +287,78 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ attribute is an experimental \ feature", cfg_fn!(needs_panic_runtime))), - (sym::rustc_outlives, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_outlives]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_variance, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_variance]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_layout, Normal, template!(List: "field1, field2, ..."), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_layout]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_layout_scalar_valid_range_start, Whitelisted, template!(List: "value"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_layout_scalar_valid_range_start]` attribute \ - is just used to enable niche optimizations in libcore \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_layout_scalar_valid_range_end, Whitelisted, template!(List: "value"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_layout_scalar_valid_range_end]` attribute \ - is just used to enable niche optimizations in libcore \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_nonnull_optimization_guaranteed, Whitelisted, template!(Word), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_nonnull_optimization_guaranteed]` attribute \ - is just used to enable niche optimizations in libcore \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_regions, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_regions]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_error, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_error]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_dump_user_substs, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_if_this_changed]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_then_this_would_need, Whitelisted, template!(List: "DepNode"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_if_this_changed]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_dirty, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", - /*opt*/ except = "...""#), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_dirty]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_clean, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", - /*opt*/ except = "...""#), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_clean]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - ( - sym::rustc_partition_reused, - Whitelisted, + + rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)), + rustc_attr!(TEST, rustc_variance, Normal, template!(Word)), + rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), + rustc_attr!( + rustc_layout_scalar_valid_range_start, Whitelisted, template!(List: "value"), + "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ + niche optimizations in libcore and will never be stable", + ), + rustc_attr!( + rustc_layout_scalar_valid_range_end, Whitelisted, template!(List: "value"), + "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ + niche optimizations in libcore and will never be stable", + ), + rustc_attr!( + rustc_nonnull_optimization_guaranteed, Whitelisted, template!(Word), + "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \ + niche optimizations in libcore and will never be stable", + ), + rustc_attr!(TEST, rustc_regions, Normal, template!(Word)), + rustc_attr!(TEST, rustc_error, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_dump_user_substs, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode")), + rustc_attr!(TEST, rustc_then_this_would_need, Whitelisted, template!(List: "DepNode")), + rustc_attr!( + TEST, rustc_dirty, Whitelisted, + template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), + ), + rustc_attr!( + TEST, rustc_clean, Whitelisted, + template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), + ), + rustc_attr!( + TEST, rustc_partition_reused, Whitelisted, template!(List: r#"cfg = "...", module = "...""#), - Gated( - Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs) - ) ), - ( - sym::rustc_partition_codegened, - Whitelisted, + rustc_attr!( + TEST, rustc_partition_codegened, Whitelisted, template!(List: r#"cfg = "...", module = "...""#), - Gated( - Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs), - ) ), - (sym::rustc_expected_cgu_reuse, Whitelisted, template!(List: r#"cfg = "...", module = "...", - kind = "...""#), - Gated(Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_synthetic, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_symbol_name, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal rustc attributes will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_def_path, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal rustc attributes will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_mir, Whitelisted, template!(List: "arg1, arg2, ..."), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_mir]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - ( - sym::rustc_inherit_overflow_checks, - Whitelisted, - template!(Word), - Gated( - Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_inherit_overflow_checks]` \ - attribute is just used to control \ - overflow checking behavior of several \ - libcore functions that are inlined \ - across crates and will never be stable", - cfg_fn!(rustc_attrs), - ) + rustc_attr!( + TEST, rustc_expected_cgu_reuse, Whitelisted, + template!(List: r#"cfg = "...", module = "...", kind = "...""#), + ), + rustc_attr!(TEST, rustc_synthetic, Whitelisted, template!(Word)), + rustc_attr!( + rustc_symbol_name, Whitelisted, template!(Word), + "internal rustc attributes will never be stable", + ), + rustc_attr!( + rustc_def_path, Whitelisted, template!(Word), + "internal rustc attributes will never be stable", + ), + rustc_attr!(TEST, rustc_mir, Whitelisted, template!(List: "arg1, arg2, ...")), + rustc_attr!( + rustc_inherit_overflow_checks, Whitelisted, template!(Word), + "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ + overflow checking behavior of several libcore functions that are inlined \ + across crates and will never be stable", + ), + rustc_attr!(TEST, rustc_dump_program_clauses, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_dump_env_program_clauses, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_object_lifetime_default, Whitelisted, template!(Word)), + rustc_attr!( + rustc_test_marker, Normal, template!(Word), + "the `#[rustc_test_marker]` attribute is used internally to track tests", + ), + rustc_attr!( + rustc_macro_transparency, Whitelisted, + template!(NameValueStr: "transparent|semitransparent|opaque"), + "used internally for testing macro hygiene", ), - - (sym::rustc_dump_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_dump_program_clauses]` \ - attribute is just used for rustc unit \ - tests and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_dump_env_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_dump_env_program_clauses]` \ - attribute is just used for rustc unit \ - tests and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_object_lifetime_default, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_object_lifetime_default]` \ - attribute is just used for rustc unit \ - tests and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_test_marker, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_test_marker]` attribute \ - is used internally to track tests", - cfg_fn!(rustc_attrs))), - (sym::rustc_macro_transparency, Whitelisted, template!(NameValueStr: - "transparent|semitransparent|opaque"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "used internally for testing macro hygiene", - cfg_fn!(rustc_attrs))), (sym::compiler_builtins, Whitelisted, template!(Word), Gated(Stability::Unstable, sym::compiler_builtins, "the `#[compiler_builtins]` attribute is used to \ @@ -501,35 +401,21 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ /*opt*/ attributes(name1, name2, ...)"), Ungated), - (sym::rustc_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_allocator_nounwind, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_builtin_macro, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_promotable, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_allow_const_fn_ptr, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_dummy, Normal, template!(Word /* doesn't matter*/), Gated(Stability::Unstable, - sym::rustc_attrs, - "used by the test suite", - cfg_fn!(rustc_attrs))), + rustc_attr!(rustc_allocator, Whitelisted, template!(Word), "internal implementation detail"), + rustc_attr!( + rustc_allocator_nounwind, Whitelisted, template!(Word), + "internal implementation detail", + ), + rustc_attr!( + rustc_builtin_macro, Whitelisted, template!(Word), + "internal implementation detail" + ), + rustc_attr!(rustc_promotable, Whitelisted, template!(Word), "internal implementation detail"), + rustc_attr!( + rustc_allow_const_fn_ptr, Whitelisted, template!(Word), + "internal implementation detail", + ), + rustc_attr!(rustc_dummy, Normal, template!(Word /* doesn't matter*/), "used by the test suite"), // FIXME: #14408 whitelist docs since rustdoc looks at them ( @@ -639,35 +525,25 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ (sym::proc_macro_attribute, Normal, template!(Word), Ungated), (sym::proc_macro, Normal, template!(Word), Ungated), - (sym::rustc_proc_macro_decls, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "used internally by rustc", - cfg_fn!(rustc_attrs))), + rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), "used internally by rustc"), (sym::allow_fail, Normal, template!(Word), Gated(Stability::Unstable, sym::allow_fail, "allow_fail attribute is currently unstable", cfg_fn!(allow_fail))), - (sym::rustc_std_internal_symbol, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this is an internal attribute that will \ - never be stable", - cfg_fn!(rustc_attrs))), - + rustc_attr!( + rustc_std_internal_symbol, Whitelisted, template!(Word), + "this is an internal attribute that will never be stable", + ), // whitelists "identity-like" conversion methods to suggest on type mismatch - (sym::rustc_conversion_suggestion, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this is an internal attribute that will \ - never be stable", - cfg_fn!(rustc_attrs))), - - ( - sym::rustc_args_required_const, - Whitelisted, - template!(List: "N"), - Gated(Stability::Unstable, sym::rustc_attrs, "never will be stable", - cfg_fn!(rustc_attrs)) + rustc_attr!( + rustc_conversion_suggestion, Whitelisted, template!(Word), + "this is an internal attribute that will never be stable", + ), + rustc_attr!( + rustc_args_required_const, Whitelisted, template!(List: "N"), + "this is an internal attribute that will never be stable", ), // RFC 2070 (sym::panic_handler, Normal, template!(Word), Ungated), From 584388c4aac430fbf41114d94b9c6debfe191e62 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 22 Aug 2019 20:40:50 +0200 Subject: [PATCH 152/618] builtin_attrs.rs: cleanup with `(un)gated!`. --- src/libsyntax/feature_gate/builtin_attrs.rs | 517 +++++++++----------- 1 file changed, 229 insertions(+), 288 deletions(-) diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index ad2e6a3feac6f..3188e92ed78d5 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -128,17 +128,32 @@ macro_rules! template { } }; } +macro_rules! ungated { + ($attr:ident, $typ:expr, $tpl:expr $(,)?) => { + (sym::$attr, $typ, $tpl, Ungated) + }; +} + +macro_rules! gated { + ($attr:ident, $typ:expr, $tpl:expr, $gate:ident, $msg:expr $(,)?) => { + (sym::$attr, $typ, $tpl, Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate))) + }; + ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { + (sym::$attr, $typ, $tpl, Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr))) + }; +} + macro_rules! rustc_attr { - (TEST, $gate:ident, $typ:expr, $tpl:expr $(,)?) => { + (TEST, $attr:ident, $typ:expr, $tpl:expr $(,)?) => { rustc_attr!( - $gate, $typ, $tpl, - concat!("the `#[", stringify!($gate), "]` attribute is just used for rustc unit tests \ + $attr, $typ, $tpl, + concat!("the `#[", stringify!($attr), "]` attribute is just used for rustc unit tests \ and will never be stable", ), ) }; - ($gate:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { - (sym::$gate, $typ, $tpl, + ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { + (sym::$attr, $typ, $tpl, Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs))) }; } @@ -149,145 +164,106 @@ pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, Attribute pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Normal attributes - ( - sym::warn, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - ( - sym::allow, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated + ungated!(warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), + ungated!(allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), + ungated!(forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), + ungated!(deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), + + ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ...")), + ungated!(macro_export, Normal, template!(Word, List: "local_inner_macros")), + ungated!(plugin_registrar, Normal, template!(Word)), + + ungated!(cfg, Normal, template!(List: "predicate")), + ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ...")), + ungated!(main, Normal, template!(Word)), + ungated!(start, Normal, template!(Word)), + ungated!(repr, Normal, template!(List: "C, packed, ...")), + ungated!(path, Normal, template!(NameValueStr: "file")), + ungated!(automatically_derived, Normal, template!(Word)), + ungated!(no_mangle, Whitelisted, template!(Word)), + ungated!(no_link, Normal, template!(Word)), + ungated!(derive, Normal, template!(List: "Trait1, Trait2, ...")), + ungated!( + should_panic, Normal, + template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), ), - ( - sym::forbid, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated + ungated!(ignore, Normal, template!(Word, NameValueStr: "reason")), + ungated!(no_implicit_prelude, Normal, template!(Word)), + ungated!(reexport_test_harness_main, Normal, template!(NameValueStr: "name")), + gated!( + link_args, Normal, template!(NameValueStr: "args"), + "the `link_args` attribute is experimental and not portable across platforms, \ + it is recommended to use `#[link(name = \"foo\")] instead", ), - ( - sym::deny, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - - (sym::macro_use, Normal, template!(Word, List: "name1, name2, ..."), Ungated), - (sym::macro_export, Normal, template!(Word, List: "local_inner_macros"), Ungated), - (sym::plugin_registrar, Normal, template!(Word), Ungated), - - (sym::cfg, Normal, template!(List: "predicate"), Ungated), - (sym::cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), Ungated), - (sym::main, Normal, template!(Word), Ungated), - (sym::start, Normal, template!(Word), Ungated), - (sym::repr, Normal, template!(List: "C, packed, ..."), Ungated), - (sym::path, Normal, template!(NameValueStr: "file"), Ungated), - (sym::automatically_derived, Normal, template!(Word), Ungated), - (sym::no_mangle, Whitelisted, template!(Word), Ungated), - (sym::no_link, Normal, template!(Word), Ungated), - (sym::derive, Normal, template!(List: "Trait1, Trait2, ..."), Ungated), - ( - sym::should_panic, - Normal, - template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), - Ungated - ), - (sym::ignore, Normal, template!(Word, NameValueStr: "reason"), Ungated), - (sym::no_implicit_prelude, Normal, template!(Word), Ungated), - (sym::reexport_test_harness_main, Normal, template!(NameValueStr: "name"), Ungated), - (sym::link_args, Normal, template!(NameValueStr: "args"), Gated(Stability::Unstable, - sym::link_args, - "the `link_args` attribute is experimental and not \ - portable across platforms, it is recommended to \ - use `#[link(name = \"foo\")] instead", - cfg_fn!(link_args))), - (sym::macro_escape, Normal, template!(Word), Ungated), + ungated!(macro_escape, Normal, template!(Word)), // RFC #1445. - (sym::structural_match, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::structural_match, - "the semantics of constant patterns is \ - not yet settled", - cfg_fn!(structural_match))), + gated!( + structural_match, Whitelisted, template!(Word), + "the semantics of constant patterns is not yet settled", + ), // RFC #2008 - (sym::non_exhaustive, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::non_exhaustive, - "non exhaustive is an experimental feature", - cfg_fn!(non_exhaustive))), + gated!( + non_exhaustive, Whitelisted, template!(Word), + "non exhaustive is an experimental feature", + ), // RFC #1268 - (sym::marker, Normal, template!(Word), Gated(Stability::Unstable, - sym::marker_trait_attr, - "marker traits is an experimental feature", - cfg_fn!(marker_trait_attr))), - - (sym::plugin, CrateLevel, template!(List: "name|name(args)"), Gated(Stability::Unstable, - sym::plugin, - "compiler plugins are experimental \ - and possibly buggy", - cfg_fn!(plugin))), - - (sym::no_std, CrateLevel, template!(Word), Ungated), - (sym::no_core, CrateLevel, template!(Word), Gated(Stability::Unstable, - sym::no_core, - "no_core is experimental", - cfg_fn!(no_core))), - (sym::lang, Normal, template!(NameValueStr: "name"), Gated(Stability::Unstable, - sym::lang_items, - "language items are subject to change", - cfg_fn!(lang_items))), - (sym::linkage, Whitelisted, template!(NameValueStr: "external|internal|..."), - Gated(Stability::Unstable, - sym::linkage, - "the `linkage` attribute is experimental \ - and not portable across platforms", - cfg_fn!(linkage))), - (sym::thread_local, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::thread_local, - "`#[thread_local]` is an experimental feature, and does \ - not currently handle destructors", - cfg_fn!(thread_local))), - - (sym::rustc_on_unimplemented, Whitelisted, template!(List: - r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, - NameValueStr: "message"), - Gated(Stability::Unstable, - sym::on_unimplemented, - "the `#[rustc_on_unimplemented]` attribute \ - is an experimental feature", - cfg_fn!(on_unimplemented))), - (sym::rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), - Gated(Stability::Unstable, - sym::rustc_const_unstable, - "the `#[rustc_const_unstable]` attribute \ - is an internal feature", - cfg_fn!(rustc_const_unstable))), - (sym::default_lib_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::allocator_internals, - "the `#[default_lib_allocator]` \ - attribute is an experimental feature", - cfg_fn!(allocator_internals))), - (sym::needs_allocator, Normal, template!(Word), Gated(Stability::Unstable, - sym::allocator_internals, - "the `#[needs_allocator]` \ - attribute is an experimental \ - feature", - cfg_fn!(allocator_internals))), - (sym::panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::panic_runtime, - "the `#[panic_runtime]` attribute is \ - an experimental feature", - cfg_fn!(panic_runtime))), - (sym::needs_panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::needs_panic_runtime, - "the `#[needs_panic_runtime]` \ - attribute is an experimental \ - feature", - cfg_fn!(needs_panic_runtime))), + gated!( + marker, Normal, template!(Word), marker_trait_attr, + "marker traits is an experimental feature", + ), + + gated!( + plugin, CrateLevel, template!(List: "name|name(args)"), + "compiler plugins are experimental and possibly buggy", + ), + + ungated!(no_std, CrateLevel, template!(Word)), + gated!(no_core, CrateLevel, template!(Word), "no_core is experimental"), + gated!( + lang, Normal, template!(NameValueStr: "name"), lang_items, + "language items are subject to change", + ), + gated!( + linkage, Whitelisted, template!(NameValueStr: "external|internal|..."), + "the `linkage` attribute is experimental and not portable across platforms", + ), + gated!( + thread_local, Whitelisted, template!(Word), + "`#[thread_local]` is an experimental feature, and does not currently handle destructors", + ), + gated!( + rustc_on_unimplemented, Whitelisted, + template!( + List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, + NameValueStr: "message" + ), + on_unimplemented, + "the `#[rustc_on_unimplemented]` attribute is an experimental feature", + ), + gated!( + rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), + "the `#[rustc_const_unstable]` attribute is an internal feature", + ), + gated!( + default_lib_allocator, Whitelisted, template!(Word), allocator_internals, + "the `#[default_lib_allocator]` attribute is an experimental feature", + ), + gated!( + needs_allocator, Normal, template!(Word), allocator_internals, + "the `#[needs_allocator]` attribute is an experimental feature", + ), + gated!( + panic_runtime, Whitelisted, template!(Word), + "the `#[panic_runtime]` attribute is an experimental feature", + ), + gated!( + needs_panic_runtime, Whitelisted, template!(Word), + "the `#[needs_panic_runtime]` attribute is an experimental feature", + ), rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)), rustc_attr!(TEST, rustc_variance, Normal, template!(Word)), rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), @@ -359,47 +335,38 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(NameValueStr: "transparent|semitransparent|opaque"), "used internally for testing macro hygiene", ), - (sym::compiler_builtins, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::compiler_builtins, - "the `#[compiler_builtins]` attribute is used to \ - identify the `compiler_builtins` crate which \ - contains compiler-rt intrinsics and will never be \ - stable", - cfg_fn!(compiler_builtins))), - (sym::sanitizer_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::sanitizer_runtime, - "the `#[sanitizer_runtime]` attribute is used to \ - identify crates that contain the runtime of a \ - sanitizer and will never be stable", - cfg_fn!(sanitizer_runtime))), - (sym::profiler_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::profiler_runtime, - "the `#[profiler_runtime]` attribute is used to \ - identify the `profiler_builtins` crate which \ - contains the profiler runtime and will never be \ - stable", - cfg_fn!(profiler_runtime))), - - (sym::allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), - Gated(Stability::Unstable, - sym::allow_internal_unstable, - EXPLAIN_ALLOW_INTERNAL_UNSTABLE, - cfg_fn!(allow_internal_unstable))), - - (sym::allow_internal_unsafe, Normal, template!(Word), Gated(Stability::Unstable, - sym::allow_internal_unsafe, - EXPLAIN_ALLOW_INTERNAL_UNSAFE, - cfg_fn!(allow_internal_unsafe))), - - (sym::fundamental, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::fundamental, - "the `#[fundamental]` attribute \ - is an experimental feature", - cfg_fn!(fundamental))), - - (sym::proc_macro_derive, Normal, template!(List: "TraitName, \ - /*opt*/ attributes(name1, name2, ...)"), - Ungated), + + gated!( + compiler_builtins, Whitelisted, template!(Word), + "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ + which contains compiler-rt intrinsics and will never be stable", + ), + gated!( + sanitizer_runtime, Whitelisted, template!(Word), + "the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime \ + of a sanitizer and will never be stable", + ), + gated!( + profiler_runtime, Whitelisted, template!(Word), + "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ + which contains the profiler runtime and will never be stable", + ), + + gated!( + allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), + EXPLAIN_ALLOW_INTERNAL_UNSTABLE, + ), + gated!(allow_internal_unsafe, Normal, template!(Word), EXPLAIN_ALLOW_INTERNAL_UNSAFE), + + gated!( + fundamental, Whitelisted, template!(Word), + "the `#[fundamental]` attribute is an experimental feature", + ), + + ungated!( + proc_macro_derive, Normal, + template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"), + ), rustc_attr!(rustc_allocator, Whitelisted, template!(Word), "internal implementation detail"), rustc_attr!( @@ -418,119 +385,93 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(rustc_dummy, Normal, template!(Word /* doesn't matter*/), "used by the test suite"), // FIXME: #14408 whitelist docs since rustdoc looks at them + ungated!(doc, Whitelisted, template!(List: "hidden|inline|...", NameValueStr: "string")), + + // FIXME: #14406 these are processed in codegen, which happens after the lint pass + + ungated!(cold, Whitelisted, template!(Word)), + gated!( + naked, Whitelisted, template!(Word), naked_functions, + "the `#[naked]` attribute is an experimental feature", + ), + gated!( + ffi_returns_twice, Whitelisted, template!(Word), + "the `#[ffi_returns_twice]` attribute is an experimental feature", + ), + ungated!(target_feature, Whitelisted, template!(List: r#"enable = "name""#)), + ungated!(export_name, Whitelisted, template!(NameValueStr: "name")), + ungated!(inline, Whitelisted, template!(Word, List: "always|never")), + ungated!( + link, Whitelisted, + template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ cfg = "...""#), + ), + ungated!(link_name, Whitelisted, template!(NameValueStr: "name")), + ungated!(link_section, Whitelisted, template!(NameValueStr: "name")), + ungated!(no_builtins, Whitelisted, template!(Word)), ( - sym::doc, - Whitelisted, - template!(List: "hidden|inline|...", NameValueStr: "string"), - Ungated - ), - - // FIXME: #14406 these are processed in codegen, which happens after the - // lint pass - (sym::cold, Whitelisted, template!(Word), Ungated), - (sym::naked, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::naked_functions, - "the `#[naked]` attribute \ - is an experimental feature", - cfg_fn!(naked_functions))), - (sym::ffi_returns_twice, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::ffi_returns_twice, - "the `#[ffi_returns_twice]` attribute \ - is an experimental feature", - cfg_fn!(ffi_returns_twice))), - (sym::target_feature, Whitelisted, template!(List: r#"enable = "name""#), Ungated), - (sym::export_name, Whitelisted, template!(NameValueStr: "name"), Ungated), - (sym::inline, Whitelisted, template!(Word, List: "always|never"), Ungated), - (sym::link, Whitelisted, template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", - /*opt*/ cfg = "...""#), Ungated), - (sym::link_name, Whitelisted, template!(NameValueStr: "name"), Ungated), - (sym::link_section, Whitelisted, template!(NameValueStr: "name"), Ungated), - (sym::no_builtins, Whitelisted, template!(Word), Ungated), - (sym::no_debug, Whitelisted, template!(Word), Gated( - Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None), - sym::no_debug, - "the `#[no_debug]` attribute was an experimental feature that has been \ - deprecated due to lack of demand", - cfg_fn!(no_debug))), - ( - sym::omit_gdb_pretty_printer_section, - Whitelisted, - template!(Word), + sym::no_debug, Whitelisted, template!(Word), Gated( - Stability::Unstable, - sym::omit_gdb_pretty_printer_section, - "the `#[omit_gdb_pretty_printer_section]` \ - attribute is just used for the Rust test \ - suite", - cfg_fn!(omit_gdb_pretty_printer_section) + Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None), + sym::no_debug, + "the `#[no_debug]` attribute was an experimental feature that has been \ + deprecated due to lack of demand", + cfg_fn!(no_debug) ) ), - (sym::may_dangle, - Normal, - template!(Word), - Gated(Stability::Unstable, - sym::dropck_eyepatch, + gated!( + omit_gdb_pretty_printer_section, Whitelisted, template!(Word), + "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite", + ), + gated!( + may_dangle, Normal, template!(Word), dropck_eyepatch, "`may_dangle` has unstable semantics and may be removed in the future", - cfg_fn!(dropck_eyepatch))), - (sym::unwind, Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable, - sym::unwind_attributes, - "`#[unwind]` is experimental", - cfg_fn!(unwind_attributes))), - (sym::used, Whitelisted, template!(Word), Ungated), - - // used in resolve - (sym::prelude_import, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::prelude_import, - "`#[prelude_import]` is for use by rustc only", - cfg_fn!(prelude_import))), + ), + gated!( + unwind, Whitelisted, template!(List: "allowed|aborts"), unwind_attributes, + "`#[unwind]` is experimental", + ), + ungated!(used, Whitelisted, template!(Word)), + + // Used in resolve: + gated!( + prelude_import, Whitelisted, template!(Word), + "`#[prelude_import]` is for use by rustc only", + ), // FIXME: #14407 these are only looked at on-demand so we can't // guarantee they'll have already been checked - ( - sym::rustc_deprecated, - Whitelisted, - template!(List: r#"since = "version", reason = "...""#), - Ungated - ), - (sym::must_use, Whitelisted, template!(Word, NameValueStr: "reason"), Ungated), - ( - sym::stable, - Whitelisted, - template!(List: r#"feature = "name", since = "version""#), - Ungated + ungated!( + rustc_deprecated, Whitelisted, + template!(List: r#"since = "version", reason = "...""#) ), - ( - sym::unstable, - Whitelisted, + ungated!(must_use, Whitelisted, template!(Word, NameValueStr: "reason")), + ungated!(stable, Whitelisted, template!(List: r#"feature = "name", since = "version""#)), + ungated!( + unstable, Whitelisted, template!(List: r#"feature = "name", reason = "...", issue = "N""#), - Ungated ), - (sym::deprecated, - Normal, + ungated!( + deprecated, Normal, template!( Word, List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, NameValueStr: "reason" ), - Ungated ), - (sym::rustc_paren_sugar, Normal, template!(Word), Gated(Stability::Unstable, - sym::unboxed_closures, - "unboxed_closures are still evolving", - cfg_fn!(unboxed_closures))), + gated!( + rustc_paren_sugar, Normal, template!(Word), unboxed_closures, + "unboxed_closures are still evolving", + ), - (sym::windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console"), Ungated), + ungated!(windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console")), - (sym::proc_macro_attribute, Normal, template!(Word), Ungated), - (sym::proc_macro, Normal, template!(Word), Ungated), + ungated!(proc_macro_attribute, Normal, template!(Word)), + ungated!(proc_macro, Normal, template!(Word)), rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), "used internally by rustc"), - (sym::allow_fail, Normal, template!(Word), Gated(Stability::Unstable, - sym::allow_fail, - "allow_fail attribute is currently unstable", - cfg_fn!(allow_fail))), + gated!(allow_fail, Normal, template!(Word), "allow_fail attribute is currently unstable"), rustc_attr!( rustc_std_internal_symbol, Whitelisted, template!(Word), @@ -545,33 +486,33 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_args_required_const, Whitelisted, template!(List: "N"), "this is an internal attribute that will never be stable", ), - // RFC 2070 - (sym::panic_handler, Normal, template!(Word), Ungated), - (sym::alloc_error_handler, Normal, template!(Word), Gated(Stability::Unstable, - sym::alloc_error_handler, - "`#[alloc_error_handler]` is an unstable feature", - cfg_fn!(alloc_error_handler))), + // RFC 2070 + ungated!(panic_handler, Normal, template!(Word)), + gated!( + alloc_error_handler, Normal, template!(Word), + "`#[alloc_error_handler]` is an unstable feature", + ), // RFC 2412 - (sym::optimize, Whitelisted, template!(List: "size|speed"), Gated(Stability::Unstable, - sym::optimize_attribute, - "`#[optimize]` attribute is an unstable feature", - cfg_fn!(optimize_attribute))), + gated!( + optimize, Whitelisted, template!(List: "size|speed"), optimize_attribute, + "`#[optimize]` attribute is an unstable feature", + ), // Crate level attributes - (sym::crate_name, CrateLevel, template!(NameValueStr: "name"), Ungated), - (sym::crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), Ungated), - (sym::crate_id, CrateLevel, template!(NameValueStr: "ignored"), Ungated), - (sym::feature, CrateLevel, template!(List: "name1, name1, ..."), Ungated), - (sym::no_start, CrateLevel, template!(Word), Ungated), - (sym::no_main, CrateLevel, template!(Word), Ungated), - (sym::recursion_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), - (sym::type_length_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), - (sym::test_runner, CrateLevel, template!(List: "path"), Gated(Stability::Unstable, - sym::custom_test_frameworks, - "custom test frameworks are an unstable feature", - cfg_fn!(custom_test_frameworks))), + ungated!(crate_name, CrateLevel, template!(NameValueStr: "name")), + ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|...")), + ungated!(crate_id, CrateLevel, template!(NameValueStr: "ignored")), + ungated!(feature, CrateLevel, template!(List: "name1, name1, ...")), + ungated!(no_start, CrateLevel, template!(Word)), + ungated!(no_main, CrateLevel, template!(Word)), + ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")), + ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N")), + gated!( + test_runner, CrateLevel, template!(List: "path"), custom_test_frameworks, + "custom test frameworks are an unstable feature", + ), ]; pub fn deprecated_attributes() -> Vec<&'static BuiltinAttribute> { From d286fe0b8d33175cf89c1bc92717bc3bff857420 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 22 Aug 2019 23:30:59 +0200 Subject: [PATCH 153/618] builtin_attrs.rs: organize! --- src/libsyntax/feature_gate/builtin_attrs.rs | 500 ++++++++++---------- 1 file changed, 259 insertions(+), 241 deletions(-) diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index 3188e92ed78d5..293e63c4c16db 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -158,184 +158,215 @@ macro_rules! rustc_attr { }; } +macro_rules! experimental { + ($attr:ident) => { + concat!("the `#[", stringify!($attr), "]` attribute is an experimental feature") + } +} + +const IMPL_DETAIL: &str = "internal implementation detail"; +const INTERAL_UNSTABLE: &str = "this is an internal attribute that will never be stable"; + pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate); /// Attributes that have a special meaning to rustc or rustdoc pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ - // Normal attributes + // ========================================================================== + // Stable attributes: + // ========================================================================== + + // Condtional compilation: + ungated!(cfg, Normal, template!(List: "predicate")), + ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ...")), + // Testing: + ungated!(ignore, Normal, template!(Word, NameValueStr: "reason")), + ungated!( + should_panic, Normal, + template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), + ), + // FIXME(Centril): This can be used on stable but shouldn't. + ungated!(reexport_test_harness_main, Normal, template!(NameValueStr: "name")), + + // Macros: + ungated!(derive, Normal, template!(List: "Trait1, Trait2, ...")), + ungated!(automatically_derived, Normal, template!(Word)), + ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ...")), + ungated!(macro_escape, Normal, template!(Word)), // Deprecated synonym for `macro_use`. + ungated!(macro_export, Normal, template!(Word, List: "local_inner_macros")), + ungated!(proc_macro, Normal, template!(Word)), + ungated!( + proc_macro_derive, Normal, + template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"), + ), + ungated!(proc_macro_attribute, Normal, template!(Word)), + + // Lints: ungated!(warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), ungated!(allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), ungated!(forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), ungated!(deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), + ungated!(must_use, Whitelisted, template!(Word, NameValueStr: "reason")), + ungated!( + deprecated, Normal, + template!( + Word, + List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, + NameValueStr: "reason" + ), + ), - ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ...")), - ungated!(macro_export, Normal, template!(Word, List: "local_inner_macros")), - ungated!(plugin_registrar, Normal, template!(Word)), + // Crate properties: + ungated!(crate_name, CrateLevel, template!(NameValueStr: "name")), + ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|...")), + ungated!(crate_id, CrateLevel, template!(NameValueStr: "ignored")), - ungated!(cfg, Normal, template!(List: "predicate")), - ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ...")), + // ABI, linking, symbols, and FFI + ungated!( + link, Whitelisted, + template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ cfg = "...""#), + ), + ungated!(link_name, Whitelisted, template!(NameValueStr: "name")), + ungated!(no_link, Normal, template!(Word)), + ungated!(repr, Normal, template!(List: "C, packed, ...")), + ungated!(export_name, Whitelisted, template!(NameValueStr: "name")), + ungated!(link_section, Whitelisted, template!(NameValueStr: "name")), + ungated!(no_mangle, Whitelisted, template!(Word)), + ungated!(used, Whitelisted, template!(Word)), + + // Limits: + ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")), + ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N")), + + // Entry point: ungated!(main, Normal, template!(Word)), ungated!(start, Normal, template!(Word)), - ungated!(repr, Normal, template!(List: "C, packed, ...")), + ungated!(no_start, CrateLevel, template!(Word)), + ungated!(no_main, CrateLevel, template!(Word)), + + // Modules, prelude, and resolution: ungated!(path, Normal, template!(NameValueStr: "file")), - ungated!(automatically_derived, Normal, template!(Word)), - ungated!(no_mangle, Whitelisted, template!(Word)), - ungated!(no_link, Normal, template!(Word)), - ungated!(derive, Normal, template!(List: "Trait1, Trait2, ...")), - ungated!( - should_panic, Normal, - template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), - ), - ungated!(ignore, Normal, template!(Word, NameValueStr: "reason")), + ungated!(no_std, CrateLevel, template!(Word)), ungated!(no_implicit_prelude, Normal, template!(Word)), - ungated!(reexport_test_harness_main, Normal, template!(NameValueStr: "name")), + + // Runtime + ungated!(windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console")), + ungated!(panic_handler, Normal, template!(Word)), // RFC 2070 + + // Code generation: + ungated!(inline, Whitelisted, template!(Word, List: "always|never")), + ungated!(cold, Whitelisted, template!(Word)), + ungated!(no_builtins, Whitelisted, template!(Word)), + ungated!(target_feature, Whitelisted, template!(List: r#"enable = "name""#)), + + // FIXME: #14408 whitelist docs since rustdoc looks at them + ungated!(doc, Whitelisted, template!(List: "hidden|inline|...", NameValueStr: "string")), + + // ========================================================================== + // Unstable attributes: + // ========================================================================== + + // Linking: + gated!(naked, Whitelisted, template!(Word), naked_functions, experimental!(naked)), gated!( link_args, Normal, template!(NameValueStr: "args"), "the `link_args` attribute is experimental and not portable across platforms, \ it is recommended to use `#[link(name = \"foo\")] instead", ), - ungated!(macro_escape, Normal, template!(Word)), - // RFC #1445. + // Plugins: + ungated!(plugin_registrar, Normal, template!(Word)), gated!( - structural_match, Whitelisted, template!(Word), - "the semantics of constant patterns is not yet settled", + plugin, CrateLevel, template!(List: "name|name(args)"), + "compiler plugins are experimental and possibly buggy", ), - // RFC #2008 + // Testing: + gated!(allow_fail, Normal, template!(Word), experimental!(allow_fail)), gated!( - non_exhaustive, Whitelisted, template!(Word), - "non exhaustive is an experimental feature", + test_runner, CrateLevel, template!(List: "path"), custom_test_frameworks, + "custom test frameworks are an unstable feature", ), + // RFC #2008 + gated!(non_exhaustive, Whitelisted, template!(Word), experimental!(non_exhaustive)), // RFC #1268 + gated!(marker, Normal, template!(Word), marker_trait_attr, experimental!(marker)), gated!( - marker, Normal, template!(Word), marker_trait_attr, - "marker traits is an experimental feature", + thread_local, Whitelisted, template!(Word), + "`#[thread_local]` is an experimental feature, and does not currently handle destructors", ), - + gated!(no_core, CrateLevel, template!(Word), experimental!(no_core)), + // RFC 2412 gated!( - plugin, CrateLevel, template!(List: "name|name(args)"), - "compiler plugins are experimental and possibly buggy", + optimize, Whitelisted, template!(List: "size|speed"), optimize_attribute, + experimental!(optimize), ), - ungated!(no_std, CrateLevel, template!(Word)), - gated!(no_core, CrateLevel, template!(Word), "no_core is experimental"), - gated!( - lang, Normal, template!(NameValueStr: "name"), lang_items, - "language items are subject to change", + gated!(ffi_returns_twice, Whitelisted, template!(Word), experimental!(ffi_returns_twice)), + + // ========================================================================== + // Internal attributes: Stability, deprecation, and unsafe: + // ========================================================================== + + ungated!(feature, CrateLevel, template!(List: "name1, name1, ...")), + // FIXME: #14407 these are only looked at on-demand so we can't + // guarantee they'll have already been checked + ungated!( + rustc_deprecated, Whitelisted, + template!(List: r#"since = "version", reason = "...""#) + ), + ungated!(stable, Whitelisted, template!(List: r#"feature = "name", since = "version""#)), + ungated!( + unstable, Whitelisted, + template!(List: r#"feature = "name", reason = "...", issue = "N""#), ), gated!( - linkage, Whitelisted, template!(NameValueStr: "external|internal|..."), - "the `linkage` attribute is experimental and not portable across platforms", + rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), + "the `#[rustc_const_unstable]` attribute is an internal feature", ), gated!( - thread_local, Whitelisted, template!(Word), - "`#[thread_local]` is an experimental feature, and does not currently handle destructors", + allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), + EXPLAIN_ALLOW_INTERNAL_UNSTABLE, ), + gated!(allow_internal_unsafe, Normal, template!(Word), EXPLAIN_ALLOW_INTERNAL_UNSAFE), + + // ========================================================================== + // Internal attributes: Type system related: + // ========================================================================== + gated!(fundamental, Whitelisted, template!(Word), experimental!(fundamental)), gated!( - rustc_on_unimplemented, Whitelisted, - template!( - List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, - NameValueStr: "message" - ), - on_unimplemented, - "the `#[rustc_on_unimplemented]` attribute is an experimental feature", + // RFC #1445. + structural_match, Whitelisted, template!(Word), + "the semantics of constant patterns is not yet settled", ), gated!( - rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), - "the `#[rustc_const_unstable]` attribute is an internal feature", + may_dangle, Normal, template!(Word), dropck_eyepatch, + "`may_dangle` has unstable semantics and may be removed in the future", ), + + // ========================================================================== + // Internal attributes: Runtime related: + // ========================================================================== + + rustc_attr!(rustc_allocator, Whitelisted, template!(Word), IMPL_DETAIL), + rustc_attr!(rustc_allocator_nounwind, Whitelisted, template!(Word), IMPL_DETAIL), + gated!(alloc_error_handler, Normal, template!(Word), experimental!(alloc_error_handler)), gated!( default_lib_allocator, Whitelisted, template!(Word), allocator_internals, - "the `#[default_lib_allocator]` attribute is an experimental feature", + experimental!(default_lib_allocator), ), gated!( needs_allocator, Normal, template!(Word), allocator_internals, - "the `#[needs_allocator]` attribute is an experimental feature", + experimental!(needs_allocator), ), + gated!(panic_runtime, Whitelisted, template!(Word), experimental!(panic_runtime)), + gated!(needs_panic_runtime, Whitelisted, template!(Word), experimental!(needs_panic_runtime)), gated!( - panic_runtime, Whitelisted, template!(Word), - "the `#[panic_runtime]` attribute is an experimental feature", - ), - gated!( - needs_panic_runtime, Whitelisted, template!(Word), - "the `#[needs_panic_runtime]` attribute is an experimental feature", - ), - rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)), - rustc_attr!(TEST, rustc_variance, Normal, template!(Word)), - rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), - rustc_attr!( - rustc_layout_scalar_valid_range_start, Whitelisted, template!(List: "value"), - "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ - niche optimizations in libcore and will never be stable", - ), - rustc_attr!( - rustc_layout_scalar_valid_range_end, Whitelisted, template!(List: "value"), - "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ - niche optimizations in libcore and will never be stable", - ), - rustc_attr!( - rustc_nonnull_optimization_guaranteed, Whitelisted, template!(Word), - "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \ - niche optimizations in libcore and will never be stable", - ), - rustc_attr!(TEST, rustc_regions, Normal, template!(Word)), - rustc_attr!(TEST, rustc_error, Whitelisted, template!(Word)), - rustc_attr!(TEST, rustc_dump_user_substs, Whitelisted, template!(Word)), - rustc_attr!(TEST, rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode")), - rustc_attr!(TEST, rustc_then_this_would_need, Whitelisted, template!(List: "DepNode")), - rustc_attr!( - TEST, rustc_dirty, Whitelisted, - template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), - ), - rustc_attr!( - TEST, rustc_clean, Whitelisted, - template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), - ), - rustc_attr!( - TEST, rustc_partition_reused, Whitelisted, - template!(List: r#"cfg = "...", module = "...""#), - ), - rustc_attr!( - TEST, rustc_partition_codegened, Whitelisted, - template!(List: r#"cfg = "...", module = "...""#), - ), - rustc_attr!( - TEST, rustc_expected_cgu_reuse, Whitelisted, - template!(List: r#"cfg = "...", module = "...", kind = "...""#), - ), - rustc_attr!(TEST, rustc_synthetic, Whitelisted, template!(Word)), - rustc_attr!( - rustc_symbol_name, Whitelisted, template!(Word), - "internal rustc attributes will never be stable", - ), - rustc_attr!( - rustc_def_path, Whitelisted, template!(Word), - "internal rustc attributes will never be stable", - ), - rustc_attr!(TEST, rustc_mir, Whitelisted, template!(List: "arg1, arg2, ...")), - rustc_attr!( - rustc_inherit_overflow_checks, Whitelisted, template!(Word), - "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ - overflow checking behavior of several libcore functions that are inlined \ - across crates and will never be stable", - ), - rustc_attr!(TEST, rustc_dump_program_clauses, Whitelisted, template!(Word)), - rustc_attr!(TEST, rustc_dump_env_program_clauses, Whitelisted, template!(Word)), - rustc_attr!(TEST, rustc_object_lifetime_default, Whitelisted, template!(Word)), - rustc_attr!( - rustc_test_marker, Normal, template!(Word), - "the `#[rustc_test_marker]` attribute is used internally to track tests", - ), - rustc_attr!( - rustc_macro_transparency, Whitelisted, - template!(NameValueStr: "transparent|semitransparent|opaque"), - "used internally for testing macro hygiene", + unwind, Whitelisted, template!(List: "allowed|aborts"), unwind_attributes, + experimental!(unwind), ), - gated!( compiler_builtins, Whitelisted, template!(Word), "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ @@ -352,62 +383,80 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ which contains the profiler runtime and will never be stable", ), + // ========================================================================== + // Internal attributes, Linkage: + // ========================================================================== + gated!( - allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), - EXPLAIN_ALLOW_INTERNAL_UNSTABLE, + linkage, Whitelisted, template!(NameValueStr: "external|internal|..."), + "the `linkage` attribute is experimental and not portable across platforms", ), - gated!(allow_internal_unsafe, Normal, template!(Word), EXPLAIN_ALLOW_INTERNAL_UNSAFE), + rustc_attr!(rustc_std_internal_symbol, Whitelisted, template!(Word), INTERAL_UNSTABLE), - gated!( - fundamental, Whitelisted, template!(Word), - "the `#[fundamental]` attribute is an experimental feature", + // ========================================================================== + // Internal attributes, Macro related: + // ========================================================================== + + rustc_attr!(rustc_builtin_macro, Whitelisted, template!(Word), IMPL_DETAIL), + rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERAL_UNSTABLE), + rustc_attr!( + rustc_macro_transparency, Whitelisted, + template!(NameValueStr: "transparent|semitransparent|opaque"), + "used internally for testing macro hygiene", ), - ungated!( - proc_macro_derive, Normal, - template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"), + // ========================================================================== + // Internal attributes, Diagnostics related: + // ========================================================================== + + gated!( + rustc_on_unimplemented, Whitelisted, + template!( + List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, + NameValueStr: "message" + ), + on_unimplemented, + experimental!(rustc_on_unimplemented), ), + // Whitelists "identity-like" conversion methods to suggest on type mismatch. + rustc_attr!(rustc_conversion_suggestion, Whitelisted, template!(Word), INTERAL_UNSTABLE), + + // ========================================================================== + // Internal attributes, Const related: + // ========================================================================== + + rustc_attr!(rustc_promotable, Whitelisted, template!(Word), IMPL_DETAIL), + rustc_attr!(rustc_allow_const_fn_ptr, Whitelisted, template!(Word), IMPL_DETAIL), + rustc_attr!(rustc_args_required_const, Whitelisted, template!(List: "N"), INTERAL_UNSTABLE), + + // ========================================================================== + // Internal attributes, Layout related: + // ========================================================================== - rustc_attr!(rustc_allocator, Whitelisted, template!(Word), "internal implementation detail"), rustc_attr!( - rustc_allocator_nounwind, Whitelisted, template!(Word), - "internal implementation detail", + rustc_layout_scalar_valid_range_start, Whitelisted, template!(List: "value"), + "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ + niche optimizations in libcore and will never be stable", ), rustc_attr!( - rustc_builtin_macro, Whitelisted, template!(Word), - "internal implementation detail" + rustc_layout_scalar_valid_range_end, Whitelisted, template!(List: "value"), + "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ + niche optimizations in libcore and will never be stable", ), - rustc_attr!(rustc_promotable, Whitelisted, template!(Word), "internal implementation detail"), rustc_attr!( - rustc_allow_const_fn_ptr, Whitelisted, template!(Word), - "internal implementation detail", + rustc_nonnull_optimization_guaranteed, Whitelisted, template!(Word), + "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \ + niche optimizations in libcore and will never be stable", ), - rustc_attr!(rustc_dummy, Normal, template!(Word /* doesn't matter*/), "used by the test suite"), - // FIXME: #14408 whitelist docs since rustdoc looks at them - ungated!(doc, Whitelisted, template!(List: "hidden|inline|...", NameValueStr: "string")), - - // FIXME: #14406 these are processed in codegen, which happens after the lint pass + // ========================================================================== + // Internal attributes, Misc: + // ========================================================================== - ungated!(cold, Whitelisted, template!(Word)), gated!( - naked, Whitelisted, template!(Word), naked_functions, - "the `#[naked]` attribute is an experimental feature", - ), - gated!( - ffi_returns_twice, Whitelisted, template!(Word), - "the `#[ffi_returns_twice]` attribute is an experimental feature", - ), - ungated!(target_feature, Whitelisted, template!(List: r#"enable = "name""#)), - ungated!(export_name, Whitelisted, template!(NameValueStr: "name")), - ungated!(inline, Whitelisted, template!(Word, List: "always|never")), - ungated!( - link, Whitelisted, - template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ cfg = "...""#), + lang, Normal, template!(NameValueStr: "name"), lang_items, + "language items are subject to change", ), - ungated!(link_name, Whitelisted, template!(NameValueStr: "name")), - ungated!(link_section, Whitelisted, template!(NameValueStr: "name")), - ungated!(no_builtins, Whitelisted, template!(Word)), ( sym::no_debug, Whitelisted, template!(Word), Gated( @@ -419,99 +468,68 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ) ), gated!( - omit_gdb_pretty_printer_section, Whitelisted, template!(Word), - "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite", - ), - gated!( - may_dangle, Normal, template!(Word), dropck_eyepatch, - "`may_dangle` has unstable semantics and may be removed in the future", - ), - gated!( - unwind, Whitelisted, template!(List: "allowed|aborts"), unwind_attributes, - "`#[unwind]` is experimental", - ), - ungated!(used, Whitelisted, template!(Word)), - - // Used in resolve: - gated!( + // Used in resolve: prelude_import, Whitelisted, template!(Word), "`#[prelude_import]` is for use by rustc only", ), - - // FIXME: #14407 these are only looked at on-demand so we can't - // guarantee they'll have already been checked - ungated!( - rustc_deprecated, Whitelisted, - template!(List: r#"since = "version", reason = "...""#) - ), - ungated!(must_use, Whitelisted, template!(Word, NameValueStr: "reason")), - ungated!(stable, Whitelisted, template!(List: r#"feature = "name", since = "version""#)), - ungated!( - unstable, Whitelisted, - template!(List: r#"feature = "name", reason = "...", issue = "N""#), - ), - ungated!( - deprecated, Normal, - template!( - Word, - List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, - NameValueStr: "reason" - ), - ), - gated!( rustc_paren_sugar, Normal, template!(Word), unboxed_closures, "unboxed_closures are still evolving", ), + rustc_attr!( + rustc_inherit_overflow_checks, Whitelisted, template!(Word), + "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ + overflow checking behavior of several libcore functions that are inlined \ + across crates and will never be stable", + ), + rustc_attr!( + rustc_test_marker, Normal, template!(Word), + "the `#[rustc_test_marker]` attribute is used internally to track tests", + ), - ungated!(windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console")), - - ungated!(proc_macro_attribute, Normal, template!(Word)), - ungated!(proc_macro, Normal, template!(Word)), - - rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), "used internally by rustc"), - - gated!(allow_fail, Normal, template!(Word), "allow_fail attribute is currently unstable"), + // ========================================================================== + // Internal attributes, Testing: + // ========================================================================== + rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)), + rustc_attr!(TEST, rustc_variance, Normal, template!(Word)), + rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), + rustc_attr!(TEST, rustc_regions, Normal, template!(Word)), + rustc_attr!(TEST, rustc_error, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_dump_user_substs, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode")), + rustc_attr!(TEST, rustc_then_this_would_need, Whitelisted, template!(List: "DepNode")), rustc_attr!( - rustc_std_internal_symbol, Whitelisted, template!(Word), - "this is an internal attribute that will never be stable", + TEST, rustc_dirty, Whitelisted, + template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), ), - // whitelists "identity-like" conversion methods to suggest on type mismatch rustc_attr!( - rustc_conversion_suggestion, Whitelisted, template!(Word), - "this is an internal attribute that will never be stable", + TEST, rustc_clean, Whitelisted, + template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), ), rustc_attr!( - rustc_args_required_const, Whitelisted, template!(List: "N"), - "this is an internal attribute that will never be stable", + TEST, rustc_partition_reused, Whitelisted, + template!(List: r#"cfg = "...", module = "...""#), ), - - // RFC 2070 - ungated!(panic_handler, Normal, template!(Word)), - gated!( - alloc_error_handler, Normal, template!(Word), - "`#[alloc_error_handler]` is an unstable feature", + rustc_attr!( + TEST, rustc_partition_codegened, Whitelisted, + template!(List: r#"cfg = "...", module = "...""#), ), - - // RFC 2412 - gated!( - optimize, Whitelisted, template!(List: "size|speed"), optimize_attribute, - "`#[optimize]` attribute is an unstable feature", + rustc_attr!( + TEST, rustc_expected_cgu_reuse, Whitelisted, + template!(List: r#"cfg = "...", module = "...", kind = "...""#), ), - - // Crate level attributes - ungated!(crate_name, CrateLevel, template!(NameValueStr: "name")), - ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|...")), - ungated!(crate_id, CrateLevel, template!(NameValueStr: "ignored")), - ungated!(feature, CrateLevel, template!(List: "name1, name1, ...")), - ungated!(no_start, CrateLevel, template!(Word)), - ungated!(no_main, CrateLevel, template!(Word)), - ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")), - ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N")), + rustc_attr!(TEST, rustc_synthetic, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_symbol_name, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_def_path, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_mir, Whitelisted, template!(List: "arg1, arg2, ...")), + rustc_attr!(TEST, rustc_dump_program_clauses, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_dump_env_program_clauses, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_object_lifetime_default, Whitelisted, template!(Word)), + rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/)), gated!( - test_runner, CrateLevel, template!(List: "path"), custom_test_frameworks, - "custom test frameworks are an unstable feature", + omit_gdb_pretty_printer_section, Whitelisted, template!(Word), + "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite", ), ]; From e5aa2dd1ff73e3fc0a17a68938ffafe2d4ed0e8c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 22 Aug 2019 23:35:03 +0200 Subject: [PATCH 154/618] builtin_attrs.rs: retain FIXMEs. --- src/libsyntax/feature_gate/builtin_attrs.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index 293e63c4c16db..9b347711fddc5 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -191,6 +191,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Macros: ungated!(derive, Normal, template!(List: "Trait1, Trait2, ...")), ungated!(automatically_derived, Normal, template!(Word)), + // FIXME(#14407) ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ...")), ungated!(macro_escape, Normal, template!(Word)), // Deprecated synonym for `macro_use`. ungated!(macro_export, Normal, template!(Word, List: "local_inner_macros")), @@ -207,6 +208,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), ungated!(deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), ungated!(must_use, Whitelisted, template!(Word, NameValueStr: "reason")), + // FIXME(#14407) ungated!( deprecated, Normal, template!( @@ -310,13 +312,15 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== ungated!(feature, CrateLevel, template!(List: "name1, name1, ...")), - // FIXME: #14407 these are only looked at on-demand so we can't - // guarantee they'll have already been checked + // FIXME(#14407) -- only looked at on-demand so we can't + // guarantee they'll have already been checked. ungated!( rustc_deprecated, Whitelisted, template!(List: r#"since = "version", reason = "...""#) ), + // FIXME(#14407) ungated!(stable, Whitelisted, template!(List: r#"feature = "name", since = "version""#)), + // FIXME(#14407) ungated!( unstable, Whitelisted, template!(List: r#"feature = "name", reason = "...", issue = "N""#), From 87eafd6c1b844f4258a2bbd7563c16609c4606e6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 22 Aug 2019 23:48:08 +0200 Subject: [PATCH 155/618] syntax: extract `check.rs`. --- src/libsyntax/feature_gate.rs | 958 +------------------- src/libsyntax/feature_gate/builtin_attrs.rs | 4 +- src/libsyntax/feature_gate/check.rs | 951 +++++++++++++++++++ 3 files changed, 960 insertions(+), 953 deletions(-) create mode 100644 src/libsyntax/feature_gate/check.rs diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 0e04d4c6c2309..97793bca1f589 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -13,963 +13,19 @@ //! becomes stable. mod accepted; -use accepted::ACCEPTED_FEATURES; mod removed; -use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES}; mod active; -use active::{ACTIVE_FEATURES}; -pub use active::{Features, INCOMPLETE_FEATURES}; mod builtin_attrs; +mod check; + +pub use active::{Features, INCOMPLETE_FEATURES}; pub use builtin_attrs::{ AttributeGate, AttributeType, GatedCfg, BuiltinAttribute, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP, deprecated_attributes, is_builtin_attr, is_builtin_attr_name, }; - -use crate::ast::{ - self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind, - PatKind, RangeEnd, +pub use check::{ + check_attribute, check_crate, get_features, feature_err, emit_feature_err, + Stability, GateIssue, UnstableFeatures, + EXPLAIN_STMT_ATTR_SYNTAX, EXPLAIN_UNSIZED_TUPLE_COERCION, }; -use crate::attr::{self, check_builtin_attribute}; -use crate::source_map::Spanned; -use crate::edition::{ALL_EDITIONS, Edition}; -use crate::visit::{self, FnKind, Visitor}; -use crate::parse::{token, ParseSess}; -use crate::parse::parser::Parser; -use crate::symbol::{Symbol, sym}; -use crate::tokenstream::TokenTree; - -use errors::{Applicability, DiagnosticBuilder, Handler}; -use rustc_data_structures::fx::FxHashMap; -use rustc_target::spec::abi::Abi; -use syntax_pos::{Span, DUMMY_SP, MultiSpan}; -use log::debug; - -use std::env; - -#[derive(Copy, Clone, Debug)] -pub enum Stability { - Unstable, - // First argument is tracking issue link; second argument is an optional - // help message, which defaults to "remove this attribute" - Deprecated(&'static str, Option<&'static str>), -} - -struct Context<'a> { - features: &'a Features, - parse_sess: &'a ParseSess, - plugin_attributes: &'a [(Symbol, AttributeType)], -} - -macro_rules! gate_feature_fn { - ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{ - let (cx, has_feature, span, - name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level); - let has_feature: bool = has_feature(&$cx.features); - debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature); - if !has_feature && !span.allows_unstable($name) { - leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level) - .emit(); - } - }} -} - -macro_rules! gate_feature { - ($cx: expr, $feature: ident, $span: expr, $explain: expr) => { - gate_feature_fn!($cx, |x:&Features| x.$feature, $span, - sym::$feature, $explain, GateStrength::Hard) - }; - ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => { - gate_feature_fn!($cx, |x:&Features| x.$feature, $span, - sym::$feature, $explain, $level) - }; -} - -impl<'a> Context<'a> { - fn check_attribute( - &self, - attr: &ast::Attribute, - attr_info: Option<&BuiltinAttribute>, - is_macro: bool - ) { - debug!("check_attribute(attr = {:?})", attr); - if let Some(&(name, ty, _template, ref gateage)) = attr_info { - if let AttributeGate::Gated(_, name, desc, ref has_feature) = *gateage { - if !attr.span.allows_unstable(name) { - gate_feature_fn!( - self, has_feature, attr.span, name, desc, GateStrength::Hard - ); - } - } else if name == sym::doc { - if let Some(content) = attr.meta_item_list() { - if content.iter().any(|c| c.check_name(sym::include)) { - gate_feature!(self, external_doc, attr.span, - "`#[doc(include = \"...\")]` is experimental" - ); - } - } - } - debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage); - return; - } else { - for segment in &attr.path.segments { - if segment.ident.as_str().starts_with("rustc") { - let msg = "attributes starting with `rustc` are \ - reserved for use by the `rustc` compiler"; - gate_feature!(self, rustc_attrs, segment.ident.span, msg); - } - } - } - for &(n, ty) in self.plugin_attributes { - if attr.path == n { - // Plugins can't gate attributes, so we don't check for it - // unlike the code above; we only use this loop to - // short-circuit to avoid the checks below. - debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty); - return; - } - } - if !is_macro && !attr::is_known(attr) { - // Only run the custom attribute lint during regular feature gate - // checking. Macro gating runs before the plugin attributes are - // registered, so we skip this in that case. - let msg = format!("the attribute `{}` is currently unknown to the compiler and \ - may have meaning added to it in the future", attr.path); - gate_feature!(self, custom_attribute, attr.span, &msg); - } - } -} - -pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) { - let cx = Context { features, parse_sess, plugin_attributes: &[] }; - cx.check_attribute( - attr, - attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name).map(|a| *a)), - true - ); -} - -fn find_lang_feature_issue(feature: Symbol) -> Option { - if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) { - let issue = info.2; - // FIXME (#28244): enforce that active features have issue numbers - // assert!(issue.is_some()) - issue - } else { - // search in Accepted, Removed, or Stable Removed features - let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES) - .find(|t| t.0 == feature); - match found { - Some(&(_, _, issue, _)) => issue, - None => panic!("Feature `{}` is not declared anywhere", feature), - } - } -} - -pub enum GateIssue { - Language, - Library(Option) -} - -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum GateStrength { - /// A hard error. (Most feature gates should use this.) - Hard, - /// Only a warning. (Use this only as backwards-compatibility demands.) - Soft, -} - -pub fn emit_feature_err( - sess: &ParseSess, - feature: Symbol, - span: Span, - issue: GateIssue, - explain: &str, -) { - feature_err(sess, feature, span, issue, explain).emit(); -} - -pub fn feature_err<'a, S: Into>( - sess: &'a ParseSess, - feature: Symbol, - span: S, - issue: GateIssue, - explain: &str, -) -> DiagnosticBuilder<'a> { - leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard) -} - -fn leveled_feature_err<'a, S: Into>( - sess: &'a ParseSess, - feature: Symbol, - span: S, - issue: GateIssue, - explain: &str, - level: GateStrength, -) -> DiagnosticBuilder<'a> { - let diag = &sess.span_diagnostic; - - let issue = match issue { - GateIssue::Language => find_lang_feature_issue(feature), - GateIssue::Library(lib) => lib, - }; - - let mut err = match level { - GateStrength::Hard => { - diag.struct_span_err_with_code(span, explain, stringify_error_code!(E0658)) - } - GateStrength::Soft => diag.struct_span_warn(span, explain), - }; - - match issue { - None | Some(0) => {} // We still accept `0` as a stand-in for backwards compatibility - Some(n) => { - err.note(&format!( - "for more information, see https://github.com/rust-lang/rust/issues/{}", - n, - )); - } - } - - // #23973: do not suggest `#![feature(...)]` if we are in beta/stable - if sess.unstable_features.is_nightly_build() { - err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature)); - } - - // If we're on stable and only emitting a "soft" warning, add a note to - // clarify that the feature isn't "on" (rather than being on but - // warning-worthy). - if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft { - err.help("a nightly build of the compiler is required to enable this feature"); - } - - err - -} - -const EXPLAIN_BOX_SYNTAX: &str = - "box expression syntax is experimental; you can call `Box::new` instead"; - -pub const EXPLAIN_STMT_ATTR_SYNTAX: &str = - "attributes on expressions are experimental"; - -pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &str = - "allow_internal_unstable side-steps feature gating and stability checks"; -pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &str = - "allow_internal_unsafe side-steps the unsafe_code lint"; - -pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &str = - "unsized tuple coercion is not stable enough for use and is subject to change"; - -struct PostExpansionVisitor<'a> { - context: &'a Context<'a>, - builtin_attributes: &'static FxHashMap, -} - -macro_rules! gate_feature_post { - ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{ - let (cx, span) = ($cx, $span); - if !span.allows_unstable(sym::$feature) { - gate_feature!(cx.context, $feature, span, $explain) - } - }}; - ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{ - let (cx, span) = ($cx, $span); - if !span.allows_unstable(sym::$feature) { - gate_feature!(cx.context, $feature, span, $explain, $level) - } - }} -} - -impl<'a> PostExpansionVisitor<'a> { - fn check_abi(&self, abi: Abi, span: Span) { - match abi { - Abi::RustIntrinsic => { - gate_feature_post!(&self, intrinsics, span, - "intrinsics are subject to change"); - }, - Abi::PlatformIntrinsic => { - gate_feature_post!(&self, platform_intrinsics, span, - "platform intrinsics are experimental and possibly buggy"); - }, - Abi::Vectorcall => { - gate_feature_post!(&self, abi_vectorcall, span, - "vectorcall is experimental and subject to change"); - }, - Abi::Thiscall => { - gate_feature_post!(&self, abi_thiscall, span, - "thiscall is experimental and subject to change"); - }, - Abi::RustCall => { - gate_feature_post!(&self, unboxed_closures, span, - "rust-call ABI is subject to change"); - }, - Abi::PtxKernel => { - gate_feature_post!(&self, abi_ptx, span, - "PTX ABIs are experimental and subject to change"); - }, - Abi::Unadjusted => { - gate_feature_post!(&self, abi_unadjusted, span, - "unadjusted ABI is an implementation detail and perma-unstable"); - }, - Abi::Msp430Interrupt => { - gate_feature_post!(&self, abi_msp430_interrupt, span, - "msp430-interrupt ABI is experimental and subject to change"); - }, - Abi::X86Interrupt => { - gate_feature_post!(&self, abi_x86_interrupt, span, - "x86-interrupt ABI is experimental and subject to change"); - }, - Abi::AmdGpuKernel => { - gate_feature_post!(&self, abi_amdgpu_kernel, span, - "amdgpu-kernel ABI is experimental and subject to change"); - }, - // Stable - Abi::Cdecl | - Abi::Stdcall | - Abi::Fastcall | - Abi::Aapcs | - Abi::Win64 | - Abi::SysV64 | - Abi::Rust | - Abi::C | - Abi::System => {} - } - } -} - -impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { - fn visit_attribute(&mut self, attr: &ast::Attribute) { - let attr_info = attr.ident().and_then(|ident| { - self.builtin_attributes.get(&ident.name).map(|a| *a) - }); - - // Check for gated attributes. - self.context.check_attribute(attr, attr_info, false); - - if attr.check_name(sym::doc) { - if let Some(content) = attr.meta_item_list() { - if content.len() == 1 && content[0].check_name(sym::cfg) { - gate_feature_post!(&self, doc_cfg, attr.span, - "`#[doc(cfg(...))]` is experimental" - ); - } else if content.iter().any(|c| c.check_name(sym::masked)) { - gate_feature_post!(&self, doc_masked, attr.span, - "`#[doc(masked)]` is experimental" - ); - } else if content.iter().any(|c| c.check_name(sym::spotlight)) { - gate_feature_post!(&self, doc_spotlight, attr.span, - "`#[doc(spotlight)]` is experimental" - ); - } else if content.iter().any(|c| c.check_name(sym::alias)) { - gate_feature_post!(&self, doc_alias, attr.span, - "`#[doc(alias = \"...\")]` is experimental" - ); - } else if content.iter().any(|c| c.check_name(sym::keyword)) { - gate_feature_post!(&self, doc_keyword, attr.span, - "`#[doc(keyword = \"...\")]` is experimental" - ); - } - } - } - - match attr_info { - // `rustc_dummy` doesn't have any restrictions specific to built-in attributes. - Some(&(name, _, template, _)) if name != sym::rustc_dummy => - check_builtin_attribute(self.context.parse_sess, attr, name, template), - _ => if let Some(TokenTree::Token(token)) = attr.tokens.trees().next() { - if token == token::Eq { - // All key-value attributes are restricted to meta-item syntax. - attr.parse_meta(self.context.parse_sess).map_err(|mut err| err.emit()).ok(); - } - } - } - } - - fn visit_name(&mut self, sp: Span, name: ast::Name) { - if !name.as_str().is_ascii() { - gate_feature_post!( - &self, - non_ascii_idents, - self.context.parse_sess.source_map().def_span(sp), - "non-ascii idents are not fully supported" - ); - } - } - - fn visit_item(&mut self, i: &'a ast::Item) { - match i.node { - ast::ItemKind::ForeignMod(ref foreign_module) => { - self.check_abi(foreign_module.abi, i.span); - } - - ast::ItemKind::Fn(..) => { - if attr::contains_name(&i.attrs[..], sym::plugin_registrar) { - gate_feature_post!(&self, plugin_registrar, i.span, - "compiler plugins are experimental and possibly buggy"); - } - if attr::contains_name(&i.attrs[..], sym::start) { - gate_feature_post!(&self, start, i.span, - "a `#[start]` function is an experimental \ - feature whose signature may change \ - over time"); - } - if attr::contains_name(&i.attrs[..], sym::main) { - gate_feature_post!(&self, main, i.span, - "declaration of a non-standard `#[main]` \ - function may change over time, for now \ - a top-level `fn main()` is required"); - } - } - - ast::ItemKind::Struct(..) => { - for attr in attr::filter_by_name(&i.attrs[..], sym::repr) { - for item in attr.meta_item_list().unwrap_or_else(Vec::new) { - if item.check_name(sym::simd) { - gate_feature_post!(&self, repr_simd, attr.span, - "SIMD types are experimental and possibly buggy"); - } - } - } - } - - ast::ItemKind::Enum(ast::EnumDef{ref variants, ..}, ..) => { - for variant in variants { - match (&variant.data, &variant.disr_expr) { - (ast::VariantData::Unit(..), _) => {}, - (_, Some(disr_expr)) => - gate_feature_post!( - &self, - arbitrary_enum_discriminant, - disr_expr.value.span, - "discriminants on non-unit variants are experimental"), - _ => {}, - } - } - - let has_feature = self.context.features.arbitrary_enum_discriminant; - if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) { - Parser::maybe_report_invalid_custom_discriminants( - self.context.parse_sess, - &variants, - ); - } - } - - ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => { - if polarity == ast::ImplPolarity::Negative { - gate_feature_post!(&self, optin_builtin_traits, - i.span, - "negative trait bounds are not yet fully implemented; \ - use marker types for now"); - } - - if let ast::Defaultness::Default = defaultness { - gate_feature_post!(&self, specialization, - i.span, - "specialization is unstable"); - } - } - - ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => { - gate_feature_post!(&self, optin_builtin_traits, - i.span, - "auto traits are experimental and possibly buggy"); - } - - ast::ItemKind::TraitAlias(..) => { - gate_feature_post!( - &self, - trait_alias, - i.span, - "trait aliases are experimental" - ); - } - - ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => { - let msg = "`macro` is experimental"; - gate_feature_post!(&self, decl_macro, i.span, msg); - } - - ast::ItemKind::OpaqueTy(..) => { - gate_feature_post!( - &self, - type_alias_impl_trait, - i.span, - "`impl Trait` in type aliases is unstable" - ); - } - - _ => {} - } - - visit::walk_item(self, i); - } - - fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) { - match i.node { - ast::ForeignItemKind::Fn(..) | - ast::ForeignItemKind::Static(..) => { - let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name); - let links_to_llvm = match link_name { - Some(val) => val.as_str().starts_with("llvm."), - _ => false - }; - if links_to_llvm { - gate_feature_post!(&self, link_llvm_intrinsics, i.span, - "linking to LLVM intrinsics is experimental"); - } - } - ast::ForeignItemKind::Ty => { - gate_feature_post!(&self, extern_types, i.span, - "extern types are experimental"); - } - ast::ForeignItemKind::Macro(..) => {} - } - - visit::walk_foreign_item(self, i) - } - - fn visit_ty(&mut self, ty: &'a ast::Ty) { - match ty.node { - ast::TyKind::BareFn(ref bare_fn_ty) => { - self.check_abi(bare_fn_ty.abi, ty.span); - } - ast::TyKind::Never => { - gate_feature_post!(&self, never_type, ty.span, - "The `!` type is experimental"); - } - _ => {} - } - visit::walk_ty(self, ty) - } - - fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) { - if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty { - if let ast::TyKind::Never = output_ty.node { - // Do nothing. - } else { - self.visit_ty(output_ty) - } - } - } - - fn visit_expr(&mut self, e: &'a ast::Expr) { - match e.node { - ast::ExprKind::Box(_) => { - gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX); - } - ast::ExprKind::Type(..) => { - // To avoid noise about type ascription in common syntax errors, only emit if it - // is the *only* error. - if self.context.parse_sess.span_diagnostic.err_count() == 0 { - gate_feature_post!(&self, type_ascription, e.span, - "type ascription is experimental"); - } - } - ast::ExprKind::TryBlock(_) => { - gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); - } - ast::ExprKind::Block(_, opt_label) => { - if let Some(label) = opt_label { - gate_feature_post!(&self, label_break_value, label.ident.span, - "labels on blocks are unstable"); - } - } - _ => {} - } - visit::walk_expr(self, e) - } - - fn visit_arm(&mut self, arm: &'a ast::Arm) { - visit::walk_arm(self, arm) - } - - fn visit_pat(&mut self, pattern: &'a ast::Pat) { - match &pattern.node { - PatKind::Slice(pats) => { - for pat in &*pats { - let span = pat.span; - let inner_pat = match &pat.node { - PatKind::Ident(.., Some(pat)) => pat, - _ => pat, - }; - if inner_pat.is_rest() { - gate_feature_post!( - &self, - slice_patterns, - span, - "subslice patterns are unstable" - ); - } - } - } - PatKind::Box(..) => { - gate_feature_post!(&self, box_patterns, - pattern.span, - "box pattern syntax is experimental"); - } - PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => { - gate_feature_post!(&self, exclusive_range_pattern, pattern.span, - "exclusive range pattern syntax is experimental"); - } - _ => {} - } - visit::walk_pat(self, pattern) - } - - fn visit_fn(&mut self, - fn_kind: FnKind<'a>, - fn_decl: &'a ast::FnDecl, - span: Span, - _node_id: NodeId) { - if let Some(header) = fn_kind.header() { - // Stability of const fn methods are covered in - // `visit_trait_item` and `visit_impl_item` below; this is - // because default methods don't pass through this point. - self.check_abi(header.abi, span); - } - - if fn_decl.c_variadic { - gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable"); - } - - visit::walk_fn(self, fn_kind, fn_decl, span) - } - - fn visit_generic_param(&mut self, param: &'a GenericParam) { - match param.kind { - GenericParamKind::Const { .. } => - gate_feature_post!(&self, const_generics, param.ident.span, - "const generics are unstable"), - _ => {} - } - visit::walk_generic_param(self, param) - } - - fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) { - match constraint.kind { - AssocTyConstraintKind::Bound { .. } => - gate_feature_post!(&self, associated_type_bounds, constraint.span, - "associated type bounds are unstable"), - _ => {} - } - visit::walk_assoc_ty_constraint(self, constraint) - } - - fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) { - match ti.node { - ast::TraitItemKind::Method(ref sig, ref block) => { - if block.is_none() { - self.check_abi(sig.header.abi, ti.span); - } - if sig.decl.c_variadic { - gate_feature_post!(&self, c_variadic, ti.span, - "C-variadic functions are unstable"); - } - if sig.header.constness.node == ast::Constness::Const { - gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable"); - } - } - ast::TraitItemKind::Type(_, ref default) => { - // We use three if statements instead of something like match guards so that all - // of these errors can be emitted if all cases apply. - if default.is_some() { - gate_feature_post!(&self, associated_type_defaults, ti.span, - "associated type defaults are unstable"); - } - if !ti.generics.params.is_empty() { - gate_feature_post!(&self, generic_associated_types, ti.span, - "generic associated types are unstable"); - } - if !ti.generics.where_clause.predicates.is_empty() { - gate_feature_post!(&self, generic_associated_types, ti.span, - "where clauses on associated types are unstable"); - } - } - _ => {} - } - visit::walk_trait_item(self, ti) - } - - fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) { - if ii.defaultness == ast::Defaultness::Default { - gate_feature_post!(&self, specialization, - ii.span, - "specialization is unstable"); - } - - match ii.node { - ast::ImplItemKind::Method(..) => {} - ast::ImplItemKind::OpaqueTy(..) => { - gate_feature_post!( - &self, - type_alias_impl_trait, - ii.span, - "`impl Trait` in type aliases is unstable" - ); - } - ast::ImplItemKind::TyAlias(_) => { - if !ii.generics.params.is_empty() { - gate_feature_post!(&self, generic_associated_types, ii.span, - "generic associated types are unstable"); - } - if !ii.generics.where_clause.predicates.is_empty() { - gate_feature_post!(&self, generic_associated_types, ii.span, - "where clauses on associated types are unstable"); - } - } - _ => {} - } - visit::walk_impl_item(self, ii) - } - - fn visit_vis(&mut self, vis: &'a ast::Visibility) { - if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node { - gate_feature_post!(&self, crate_visibility_modifier, vis.span, - "`crate` visibility modifier is experimental"); - } - visit::walk_vis(self, vis) - } -} - -pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], - crate_edition: Edition, allow_features: &Option>) -> Features { - fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) { - let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed"); - if let Some(reason) = reason { - err.span_note(span, reason); - } else { - err.span_label(span, "feature has been removed"); - } - err.emit(); - } - - let mut features = Features::new(); - let mut edition_enabled_features = FxHashMap::default(); - - for &edition in ALL_EDITIONS { - if edition <= crate_edition { - // The `crate_edition` implies its respective umbrella feature-gate - // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX). - edition_enabled_features.insert(edition.feature_name(), edition); - } - } - - for &(name, .., f_edition, set) in ACTIVE_FEATURES { - if let Some(f_edition) = f_edition { - if f_edition <= crate_edition { - set(&mut features, DUMMY_SP); - edition_enabled_features.insert(name, crate_edition); - } - } - } - - // Process the edition umbrella feature-gates first, to ensure - // `edition_enabled_features` is completed before it's queried. - for attr in krate_attrs { - if !attr.check_name(sym::feature) { - continue - } - - let list = match attr.meta_item_list() { - Some(list) => list, - None => continue, - }; - - for mi in list { - if !mi.is_word() { - continue; - } - - let name = mi.name_or_empty(); - - if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) { - if *edition <= crate_edition { - continue; - } - - for &(name, .., f_edition, set) in ACTIVE_FEATURES { - if let Some(f_edition) = f_edition { - if f_edition <= *edition { - // FIXME(Manishearth) there is currently no way to set - // lib features by edition - set(&mut features, DUMMY_SP); - edition_enabled_features.insert(name, *edition); - } - } - } - } - } - } - - for attr in krate_attrs { - if !attr.check_name(sym::feature) { - continue - } - - let list = match attr.meta_item_list() { - Some(list) => list, - None => continue, - }; - - let bad_input = |span| { - struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input") - }; - - for mi in list { - let name = match mi.ident() { - Some(ident) if mi.is_word() => ident.name, - Some(ident) => { - bad_input(mi.span()).span_suggestion( - mi.span(), - "expected just one word", - format!("{}", ident.name), - Applicability::MaybeIncorrect, - ).emit(); - continue - } - None => { - bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit(); - continue - } - }; - - if let Some(edition) = edition_enabled_features.get(&name) { - struct_span_warn!( - span_handler, - mi.span(), - E0705, - "the feature `{}` is included in the Rust {} edition", - name, - edition, - ).emit(); - continue; - } - - if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) { - // Handled in the separate loop above. - continue; - } - - let removed = REMOVED_FEATURES.iter().find(|f| name == f.0); - let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.0); - if let Some((.., reason)) = removed.or(stable_removed) { - feature_removed(span_handler, mi.span(), *reason); - continue; - } - - if let Some((_, since, ..)) = ACCEPTED_FEATURES.iter().find(|f| name == f.0) { - let since = Some(Symbol::intern(since)); - features.declared_lang_features.push((name, mi.span(), since)); - continue; - } - - if let Some(allowed) = allow_features.as_ref() { - if allowed.iter().find(|f| *f == name.as_str()).is_none() { - span_err!(span_handler, mi.span(), E0725, - "the feature `{}` is not in the list of allowed features", - name); - continue; - } - } - - if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) { - set(&mut features, mi.span()); - features.declared_lang_features.push((name, mi.span(), None)); - continue; - } - - features.declared_lib_features.push((name, mi.span())); - } - } - - features -} - -pub fn check_crate(krate: &ast::Crate, - sess: &ParseSess, - features: &Features, - plugin_attributes: &[(Symbol, AttributeType)], - unstable: UnstableFeatures) { - maybe_stage_features(&sess.span_diagnostic, krate, unstable); - let ctx = Context { - features, - parse_sess: sess, - plugin_attributes, - }; - - macro_rules! gate_all { - ($gate:ident, $msg:literal) => { gate_all!($gate, $gate, $msg); }; - ($spans:ident, $gate:ident, $msg:literal) => { - for span in &*sess.gated_spans.$spans.borrow() { - gate_feature!(&ctx, $gate, *span, $msg); - } - } - } - - gate_all!(param_attrs, "attributes on function parameters are unstable"); - gate_all!(let_chains, "`let` expressions in this position are experimental"); - gate_all!(async_closure, "async closures are unstable"); - gate_all!(yields, generators, "yield syntax is experimental"); - gate_all!(or_patterns, "or-patterns syntax is experimental"); - - let visitor = &mut PostExpansionVisitor { - context: &ctx, - builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP, - }; - visit::walk_crate(visitor, krate); -} - -#[derive(Clone, Copy, Hash)] -pub enum UnstableFeatures { - /// Hard errors for unstable features are active, as on beta/stable channels. - Disallow, - /// Allow features to be activated, as on nightly. - Allow, - /// Errors are bypassed for bootstrapping. This is required any time - /// during the build that feature-related lints are set to warn or above - /// because the build turns on warnings-as-errors and uses lots of unstable - /// features. As a result, this is always required for building Rust itself. - Cheat -} - -impl UnstableFeatures { - pub fn from_environment() -> UnstableFeatures { - // Whether this is a feature-staged build, i.e., on the beta or stable channel - let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some(); - // Whether we should enable unstable features for bootstrapping - let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok(); - match (disable_unstable_features, bootstrap) { - (_, true) => UnstableFeatures::Cheat, - (true, _) => UnstableFeatures::Disallow, - (false, _) => UnstableFeatures::Allow - } - } - - pub fn is_nightly_build(&self) -> bool { - match *self { - UnstableFeatures::Allow | UnstableFeatures::Cheat => true, - _ => false, - } - } -} - -fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, - unstable: UnstableFeatures) { - let allow_features = match unstable { - UnstableFeatures::Allow => true, - UnstableFeatures::Disallow => false, - UnstableFeatures::Cheat => true - }; - if !allow_features { - for attr in &krate.attrs { - if attr.check_name(sym::feature) { - let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"); - span_err!(span_handler, attr.span, E0554, - "`#![feature]` may not be used on the {} release channel", - release_channel); - } - } - } -} diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index 9b347711fddc5..b934f2e7f64ef 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -3,8 +3,8 @@ use AttributeType::*; use AttributeGate::*; -use super::{emit_feature_err, GateIssue}; -use super::{Stability, EXPLAIN_ALLOW_INTERNAL_UNSAFE, EXPLAIN_ALLOW_INTERNAL_UNSTABLE}; +use super::check::{emit_feature_err, GateIssue}; +use super::check::{Stability, EXPLAIN_ALLOW_INTERNAL_UNSAFE, EXPLAIN_ALLOW_INTERNAL_UNSTABLE}; use super::active::Features; use crate::ast; diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs new file mode 100644 index 0000000000000..d82b287b6fb05 --- /dev/null +++ b/src/libsyntax/feature_gate/check.rs @@ -0,0 +1,951 @@ +use super::active::{ACTIVE_FEATURES, Features}; +use super::accepted::ACCEPTED_FEATURES; +use super::removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES}; +use super::builtin_attrs::{AttributeGate, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; + +use crate::ast::{ + self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind, + PatKind, RangeEnd, +}; +use crate::attr::{self, check_builtin_attribute}; +use crate::source_map::Spanned; +use crate::edition::{ALL_EDITIONS, Edition}; +use crate::visit::{self, FnKind, Visitor}; +use crate::parse::{token, ParseSess}; +use crate::parse::parser::Parser; +use crate::symbol::{Symbol, sym}; +use crate::tokenstream::TokenTree; + +use errors::{Applicability, DiagnosticBuilder, Handler}; +use rustc_data_structures::fx::FxHashMap; +use rustc_target::spec::abi::Abi; +use syntax_pos::{Span, DUMMY_SP, MultiSpan}; +use log::debug; + +use std::env; + +#[derive(Copy, Clone, Debug)] +pub enum Stability { + Unstable, + // First argument is tracking issue link; second argument is an optional + // help message, which defaults to "remove this attribute" + Deprecated(&'static str, Option<&'static str>), +} + +struct Context<'a> { + features: &'a Features, + parse_sess: &'a ParseSess, + plugin_attributes: &'a [(Symbol, AttributeType)], +} + +macro_rules! gate_feature_fn { + ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{ + let (cx, has_feature, span, + name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level); + let has_feature: bool = has_feature(&$cx.features); + debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature); + if !has_feature && !span.allows_unstable($name) { + leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level) + .emit(); + } + }} +} + +macro_rules! gate_feature { + ($cx: expr, $feature: ident, $span: expr, $explain: expr) => { + gate_feature_fn!($cx, |x:&Features| x.$feature, $span, + sym::$feature, $explain, GateStrength::Hard) + }; + ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => { + gate_feature_fn!($cx, |x:&Features| x.$feature, $span, + sym::$feature, $explain, $level) + }; +} + +impl<'a> Context<'a> { + fn check_attribute( + &self, + attr: &ast::Attribute, + attr_info: Option<&BuiltinAttribute>, + is_macro: bool + ) { + debug!("check_attribute(attr = {:?})", attr); + if let Some(&(name, ty, _template, ref gateage)) = attr_info { + if let AttributeGate::Gated(_, name, desc, ref has_feature) = *gateage { + if !attr.span.allows_unstable(name) { + gate_feature_fn!( + self, has_feature, attr.span, name, desc, GateStrength::Hard + ); + } + } else if name == sym::doc { + if let Some(content) = attr.meta_item_list() { + if content.iter().any(|c| c.check_name(sym::include)) { + gate_feature!(self, external_doc, attr.span, + "`#[doc(include = \"...\")]` is experimental" + ); + } + } + } + debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage); + return; + } else { + for segment in &attr.path.segments { + if segment.ident.as_str().starts_with("rustc") { + let msg = "attributes starting with `rustc` are \ + reserved for use by the `rustc` compiler"; + gate_feature!(self, rustc_attrs, segment.ident.span, msg); + } + } + } + for &(n, ty) in self.plugin_attributes { + if attr.path == n { + // Plugins can't gate attributes, so we don't check for it + // unlike the code above; we only use this loop to + // short-circuit to avoid the checks below. + debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty); + return; + } + } + if !is_macro && !attr::is_known(attr) { + // Only run the custom attribute lint during regular feature gate + // checking. Macro gating runs before the plugin attributes are + // registered, so we skip this in that case. + let msg = format!("the attribute `{}` is currently unknown to the compiler and \ + may have meaning added to it in the future", attr.path); + gate_feature!(self, custom_attribute, attr.span, &msg); + } + } +} + +pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) { + let cx = Context { features, parse_sess, plugin_attributes: &[] }; + cx.check_attribute( + attr, + attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name).map(|a| *a)), + true + ); +} + +fn find_lang_feature_issue(feature: Symbol) -> Option { + if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) { + let issue = info.2; + // FIXME (#28244): enforce that active features have issue numbers + // assert!(issue.is_some()) + issue + } else { + // search in Accepted, Removed, or Stable Removed features + let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES) + .find(|t| t.0 == feature); + match found { + Some(&(_, _, issue, _)) => issue, + None => panic!("Feature `{}` is not declared anywhere", feature), + } + } +} + +pub enum GateIssue { + Language, + Library(Option) +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum GateStrength { + /// A hard error. (Most feature gates should use this.) + Hard, + /// Only a warning. (Use this only as backwards-compatibility demands.) + Soft, +} + +pub fn emit_feature_err( + sess: &ParseSess, + feature: Symbol, + span: Span, + issue: GateIssue, + explain: &str, +) { + feature_err(sess, feature, span, issue, explain).emit(); +} + +pub fn feature_err<'a, S: Into>( + sess: &'a ParseSess, + feature: Symbol, + span: S, + issue: GateIssue, + explain: &str, +) -> DiagnosticBuilder<'a> { + leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard) +} + +fn leveled_feature_err<'a, S: Into>( + sess: &'a ParseSess, + feature: Symbol, + span: S, + issue: GateIssue, + explain: &str, + level: GateStrength, +) -> DiagnosticBuilder<'a> { + let diag = &sess.span_diagnostic; + + let issue = match issue { + GateIssue::Language => find_lang_feature_issue(feature), + GateIssue::Library(lib) => lib, + }; + + let mut err = match level { + GateStrength::Hard => { + diag.struct_span_err_with_code(span, explain, stringify_error_code!(E0658)) + } + GateStrength::Soft => diag.struct_span_warn(span, explain), + }; + + match issue { + None | Some(0) => {} // We still accept `0` as a stand-in for backwards compatibility + Some(n) => { + err.note(&format!( + "for more information, see https://github.com/rust-lang/rust/issues/{}", + n, + )); + } + } + + // #23973: do not suggest `#![feature(...)]` if we are in beta/stable + if sess.unstable_features.is_nightly_build() { + err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature)); + } + + // If we're on stable and only emitting a "soft" warning, add a note to + // clarify that the feature isn't "on" (rather than being on but + // warning-worthy). + if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft { + err.help("a nightly build of the compiler is required to enable this feature"); + } + + err + +} + +const EXPLAIN_BOX_SYNTAX: &str = + "box expression syntax is experimental; you can call `Box::new` instead"; + +pub const EXPLAIN_STMT_ATTR_SYNTAX: &str = + "attributes on expressions are experimental"; + +pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &str = + "allow_internal_unstable side-steps feature gating and stability checks"; +pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &str = + "allow_internal_unsafe side-steps the unsafe_code lint"; + +pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &str = + "unsized tuple coercion is not stable enough for use and is subject to change"; + +struct PostExpansionVisitor<'a> { + context: &'a Context<'a>, + builtin_attributes: &'static FxHashMap, +} + +macro_rules! gate_feature_post { + ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{ + let (cx, span) = ($cx, $span); + if !span.allows_unstable(sym::$feature) { + gate_feature!(cx.context, $feature, span, $explain) + } + }}; + ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{ + let (cx, span) = ($cx, $span); + if !span.allows_unstable(sym::$feature) { + gate_feature!(cx.context, $feature, span, $explain, $level) + } + }} +} + +impl<'a> PostExpansionVisitor<'a> { + fn check_abi(&self, abi: Abi, span: Span) { + match abi { + Abi::RustIntrinsic => { + gate_feature_post!(&self, intrinsics, span, + "intrinsics are subject to change"); + }, + Abi::PlatformIntrinsic => { + gate_feature_post!(&self, platform_intrinsics, span, + "platform intrinsics are experimental and possibly buggy"); + }, + Abi::Vectorcall => { + gate_feature_post!(&self, abi_vectorcall, span, + "vectorcall is experimental and subject to change"); + }, + Abi::Thiscall => { + gate_feature_post!(&self, abi_thiscall, span, + "thiscall is experimental and subject to change"); + }, + Abi::RustCall => { + gate_feature_post!(&self, unboxed_closures, span, + "rust-call ABI is subject to change"); + }, + Abi::PtxKernel => { + gate_feature_post!(&self, abi_ptx, span, + "PTX ABIs are experimental and subject to change"); + }, + Abi::Unadjusted => { + gate_feature_post!(&self, abi_unadjusted, span, + "unadjusted ABI is an implementation detail and perma-unstable"); + }, + Abi::Msp430Interrupt => { + gate_feature_post!(&self, abi_msp430_interrupt, span, + "msp430-interrupt ABI is experimental and subject to change"); + }, + Abi::X86Interrupt => { + gate_feature_post!(&self, abi_x86_interrupt, span, + "x86-interrupt ABI is experimental and subject to change"); + }, + Abi::AmdGpuKernel => { + gate_feature_post!(&self, abi_amdgpu_kernel, span, + "amdgpu-kernel ABI is experimental and subject to change"); + }, + // Stable + Abi::Cdecl | + Abi::Stdcall | + Abi::Fastcall | + Abi::Aapcs | + Abi::Win64 | + Abi::SysV64 | + Abi::Rust | + Abi::C | + Abi::System => {} + } + } +} + +impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { + fn visit_attribute(&mut self, attr: &ast::Attribute) { + let attr_info = attr.ident().and_then(|ident| { + self.builtin_attributes.get(&ident.name).map(|a| *a) + }); + + // Check for gated attributes. + self.context.check_attribute(attr, attr_info, false); + + if attr.check_name(sym::doc) { + if let Some(content) = attr.meta_item_list() { + if content.len() == 1 && content[0].check_name(sym::cfg) { + gate_feature_post!(&self, doc_cfg, attr.span, + "`#[doc(cfg(...))]` is experimental" + ); + } else if content.iter().any(|c| c.check_name(sym::masked)) { + gate_feature_post!(&self, doc_masked, attr.span, + "`#[doc(masked)]` is experimental" + ); + } else if content.iter().any(|c| c.check_name(sym::spotlight)) { + gate_feature_post!(&self, doc_spotlight, attr.span, + "`#[doc(spotlight)]` is experimental" + ); + } else if content.iter().any(|c| c.check_name(sym::alias)) { + gate_feature_post!(&self, doc_alias, attr.span, + "`#[doc(alias = \"...\")]` is experimental" + ); + } else if content.iter().any(|c| c.check_name(sym::keyword)) { + gate_feature_post!(&self, doc_keyword, attr.span, + "`#[doc(keyword = \"...\")]` is experimental" + ); + } + } + } + + match attr_info { + // `rustc_dummy` doesn't have any restrictions specific to built-in attributes. + Some(&(name, _, template, _)) if name != sym::rustc_dummy => + check_builtin_attribute(self.context.parse_sess, attr, name, template), + _ => if let Some(TokenTree::Token(token)) = attr.tokens.trees().next() { + if token == token::Eq { + // All key-value attributes are restricted to meta-item syntax. + attr.parse_meta(self.context.parse_sess).map_err(|mut err| err.emit()).ok(); + } + } + } + } + + fn visit_name(&mut self, sp: Span, name: ast::Name) { + if !name.as_str().is_ascii() { + gate_feature_post!( + &self, + non_ascii_idents, + self.context.parse_sess.source_map().def_span(sp), + "non-ascii idents are not fully supported" + ); + } + } + + fn visit_item(&mut self, i: &'a ast::Item) { + match i.node { + ast::ItemKind::ForeignMod(ref foreign_module) => { + self.check_abi(foreign_module.abi, i.span); + } + + ast::ItemKind::Fn(..) => { + if attr::contains_name(&i.attrs[..], sym::plugin_registrar) { + gate_feature_post!(&self, plugin_registrar, i.span, + "compiler plugins are experimental and possibly buggy"); + } + if attr::contains_name(&i.attrs[..], sym::start) { + gate_feature_post!(&self, start, i.span, + "a `#[start]` function is an experimental \ + feature whose signature may change \ + over time"); + } + if attr::contains_name(&i.attrs[..], sym::main) { + gate_feature_post!(&self, main, i.span, + "declaration of a non-standard `#[main]` \ + function may change over time, for now \ + a top-level `fn main()` is required"); + } + } + + ast::ItemKind::Struct(..) => { + for attr in attr::filter_by_name(&i.attrs[..], sym::repr) { + for item in attr.meta_item_list().unwrap_or_else(Vec::new) { + if item.check_name(sym::simd) { + gate_feature_post!(&self, repr_simd, attr.span, + "SIMD types are experimental and possibly buggy"); + } + } + } + } + + ast::ItemKind::Enum(ast::EnumDef{ref variants, ..}, ..) => { + for variant in variants { + match (&variant.data, &variant.disr_expr) { + (ast::VariantData::Unit(..), _) => {}, + (_, Some(disr_expr)) => + gate_feature_post!( + &self, + arbitrary_enum_discriminant, + disr_expr.value.span, + "discriminants on non-unit variants are experimental"), + _ => {}, + } + } + + let has_feature = self.context.features.arbitrary_enum_discriminant; + if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) { + Parser::maybe_report_invalid_custom_discriminants( + self.context.parse_sess, + &variants, + ); + } + } + + ast::ItemKind::Impl(_, polarity, defaultness, ..) => { + if polarity == ast::ImplPolarity::Negative { + gate_feature_post!(&self, optin_builtin_traits, + i.span, + "negative trait bounds are not yet fully implemented; \ + use marker types for now"); + } + + if let ast::Defaultness::Default = defaultness { + gate_feature_post!(&self, specialization, + i.span, + "specialization is unstable"); + } + } + + ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => { + gate_feature_post!(&self, optin_builtin_traits, + i.span, + "auto traits are experimental and possibly buggy"); + } + + ast::ItemKind::TraitAlias(..) => { + gate_feature_post!( + &self, + trait_alias, + i.span, + "trait aliases are experimental" + ); + } + + ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => { + let msg = "`macro` is experimental"; + gate_feature_post!(&self, decl_macro, i.span, msg); + } + + ast::ItemKind::OpaqueTy(..) => { + gate_feature_post!( + &self, + type_alias_impl_trait, + i.span, + "`impl Trait` in type aliases is unstable" + ); + } + + _ => {} + } + + visit::walk_item(self, i); + } + + fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) { + match i.node { + ast::ForeignItemKind::Fn(..) | + ast::ForeignItemKind::Static(..) => { + let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name); + let links_to_llvm = match link_name { + Some(val) => val.as_str().starts_with("llvm."), + _ => false + }; + if links_to_llvm { + gate_feature_post!(&self, link_llvm_intrinsics, i.span, + "linking to LLVM intrinsics is experimental"); + } + } + ast::ForeignItemKind::Ty => { + gate_feature_post!(&self, extern_types, i.span, + "extern types are experimental"); + } + ast::ForeignItemKind::Macro(..) => {} + } + + visit::walk_foreign_item(self, i) + } + + fn visit_ty(&mut self, ty: &'a ast::Ty) { + match ty.node { + ast::TyKind::BareFn(ref bare_fn_ty) => { + self.check_abi(bare_fn_ty.abi, ty.span); + } + ast::TyKind::Never => { + gate_feature_post!(&self, never_type, ty.span, + "The `!` type is experimental"); + } + _ => {} + } + visit::walk_ty(self, ty) + } + + fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) { + if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty { + if let ast::TyKind::Never = output_ty.node { + // Do nothing. + } else { + self.visit_ty(output_ty) + } + } + } + + fn visit_expr(&mut self, e: &'a ast::Expr) { + match e.node { + ast::ExprKind::Box(_) => { + gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX); + } + ast::ExprKind::Type(..) => { + // To avoid noise about type ascription in common syntax errors, only emit if it + // is the *only* error. + if self.context.parse_sess.span_diagnostic.err_count() == 0 { + gate_feature_post!(&self, type_ascription, e.span, + "type ascription is experimental"); + } + } + ast::ExprKind::TryBlock(_) => { + gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); + } + ast::ExprKind::Block(_, opt_label) => { + if let Some(label) = opt_label { + gate_feature_post!(&self, label_break_value, label.ident.span, + "labels on blocks are unstable"); + } + } + _ => {} + } + visit::walk_expr(self, e) + } + + fn visit_arm(&mut self, arm: &'a ast::Arm) { + visit::walk_arm(self, arm) + } + + fn visit_pat(&mut self, pattern: &'a ast::Pat) { + match &pattern.node { + PatKind::Slice(pats) => { + for pat in &*pats { + let span = pat.span; + let inner_pat = match &pat.node { + PatKind::Ident(.., Some(pat)) => pat, + _ => pat, + }; + if inner_pat.is_rest() { + gate_feature_post!( + &self, + slice_patterns, + span, + "subslice patterns are unstable" + ); + } + } + } + PatKind::Box(..) => { + gate_feature_post!(&self, box_patterns, + pattern.span, + "box pattern syntax is experimental"); + } + PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => { + gate_feature_post!(&self, exclusive_range_pattern, pattern.span, + "exclusive range pattern syntax is experimental"); + } + _ => {} + } + visit::walk_pat(self, pattern) + } + + fn visit_fn(&mut self, + fn_kind: FnKind<'a>, + fn_decl: &'a ast::FnDecl, + span: Span, + _node_id: NodeId) { + if let Some(header) = fn_kind.header() { + // Stability of const fn methods are covered in + // `visit_trait_item` and `visit_impl_item` below; this is + // because default methods don't pass through this point. + self.check_abi(header.abi, span); + } + + if fn_decl.c_variadic { + gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable"); + } + + visit::walk_fn(self, fn_kind, fn_decl, span) + } + + fn visit_generic_param(&mut self, param: &'a GenericParam) { + match param.kind { + GenericParamKind::Const { .. } => + gate_feature_post!(&self, const_generics, param.ident.span, + "const generics are unstable"), + _ => {} + } + visit::walk_generic_param(self, param) + } + + fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) { + match constraint.kind { + AssocTyConstraintKind::Bound { .. } => + gate_feature_post!(&self, associated_type_bounds, constraint.span, + "associated type bounds are unstable"), + _ => {} + } + visit::walk_assoc_ty_constraint(self, constraint) + } + + fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) { + match ti.node { + ast::TraitItemKind::Method(ref sig, ref block) => { + if block.is_none() { + self.check_abi(sig.header.abi, ti.span); + } + if sig.decl.c_variadic { + gate_feature_post!(&self, c_variadic, ti.span, + "C-variadic functions are unstable"); + } + if sig.header.constness.node == ast::Constness::Const { + gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable"); + } + } + ast::TraitItemKind::Type(_, ref default) => { + // We use three if statements instead of something like match guards so that all + // of these errors can be emitted if all cases apply. + if default.is_some() { + gate_feature_post!(&self, associated_type_defaults, ti.span, + "associated type defaults are unstable"); + } + if !ti.generics.params.is_empty() { + gate_feature_post!(&self, generic_associated_types, ti.span, + "generic associated types are unstable"); + } + if !ti.generics.where_clause.predicates.is_empty() { + gate_feature_post!(&self, generic_associated_types, ti.span, + "where clauses on associated types are unstable"); + } + } + _ => {} + } + visit::walk_trait_item(self, ti) + } + + fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) { + if ii.defaultness == ast::Defaultness::Default { + gate_feature_post!(&self, specialization, + ii.span, + "specialization is unstable"); + } + + match ii.node { + ast::ImplItemKind::Method(..) => {} + ast::ImplItemKind::OpaqueTy(..) => { + gate_feature_post!( + &self, + type_alias_impl_trait, + ii.span, + "`impl Trait` in type aliases is unstable" + ); + } + ast::ImplItemKind::TyAlias(_) => { + if !ii.generics.params.is_empty() { + gate_feature_post!(&self, generic_associated_types, ii.span, + "generic associated types are unstable"); + } + if !ii.generics.where_clause.predicates.is_empty() { + gate_feature_post!(&self, generic_associated_types, ii.span, + "where clauses on associated types are unstable"); + } + } + _ => {} + } + visit::walk_impl_item(self, ii) + } + + fn visit_vis(&mut self, vis: &'a ast::Visibility) { + if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node { + gate_feature_post!(&self, crate_visibility_modifier, vis.span, + "`crate` visibility modifier is experimental"); + } + visit::walk_vis(self, vis) + } +} + +pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], + crate_edition: Edition, allow_features: &Option>) -> Features { + fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) { + let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed"); + if let Some(reason) = reason { + err.span_note(span, reason); + } else { + err.span_label(span, "feature has been removed"); + } + err.emit(); + } + + let mut features = Features::new(); + let mut edition_enabled_features = FxHashMap::default(); + + for &edition in ALL_EDITIONS { + if edition <= crate_edition { + // The `crate_edition` implies its respective umbrella feature-gate + // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX). + edition_enabled_features.insert(edition.feature_name(), edition); + } + } + + for &(name, .., f_edition, set) in ACTIVE_FEATURES { + if let Some(f_edition) = f_edition { + if f_edition <= crate_edition { + set(&mut features, DUMMY_SP); + edition_enabled_features.insert(name, crate_edition); + } + } + } + + // Process the edition umbrella feature-gates first, to ensure + // `edition_enabled_features` is completed before it's queried. + for attr in krate_attrs { + if !attr.check_name(sym::feature) { + continue + } + + let list = match attr.meta_item_list() { + Some(list) => list, + None => continue, + }; + + for mi in list { + if !mi.is_word() { + continue; + } + + let name = mi.name_or_empty(); + + if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) { + if *edition <= crate_edition { + continue; + } + + for &(name, .., f_edition, set) in ACTIVE_FEATURES { + if let Some(f_edition) = f_edition { + if f_edition <= *edition { + // FIXME(Manishearth) there is currently no way to set + // lib features by edition + set(&mut features, DUMMY_SP); + edition_enabled_features.insert(name, *edition); + } + } + } + } + } + } + + for attr in krate_attrs { + if !attr.check_name(sym::feature) { + continue + } + + let list = match attr.meta_item_list() { + Some(list) => list, + None => continue, + }; + + let bad_input = |span| { + struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input") + }; + + for mi in list { + let name = match mi.ident() { + Some(ident) if mi.is_word() => ident.name, + Some(ident) => { + bad_input(mi.span()).span_suggestion( + mi.span(), + "expected just one word", + format!("{}", ident.name), + Applicability::MaybeIncorrect, + ).emit(); + continue + } + None => { + bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit(); + continue + } + }; + + if let Some(edition) = edition_enabled_features.get(&name) { + struct_span_warn!( + span_handler, + mi.span(), + E0705, + "the feature `{}` is included in the Rust {} edition", + name, + edition, + ).emit(); + continue; + } + + if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) { + // Handled in the separate loop above. + continue; + } + + let removed = REMOVED_FEATURES.iter().find(|f| name == f.0); + let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.0); + if let Some((.., reason)) = removed.or(stable_removed) { + feature_removed(span_handler, mi.span(), *reason); + continue; + } + + if let Some((_, since, ..)) = ACCEPTED_FEATURES.iter().find(|f| name == f.0) { + let since = Some(Symbol::intern(since)); + features.declared_lang_features.push((name, mi.span(), since)); + continue; + } + + if let Some(allowed) = allow_features.as_ref() { + if allowed.iter().find(|f| *f == name.as_str()).is_none() { + span_err!(span_handler, mi.span(), E0725, + "the feature `{}` is not in the list of allowed features", + name); + continue; + } + } + + if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) { + set(&mut features, mi.span()); + features.declared_lang_features.push((name, mi.span(), None)); + continue; + } + + features.declared_lib_features.push((name, mi.span())); + } + } + + features +} + +pub fn check_crate(krate: &ast::Crate, + sess: &ParseSess, + features: &Features, + plugin_attributes: &[(Symbol, AttributeType)], + unstable: UnstableFeatures) { + maybe_stage_features(&sess.span_diagnostic, krate, unstable); + let ctx = Context { + features, + parse_sess: sess, + plugin_attributes, + }; + + macro_rules! gate_all { + ($gate:ident, $msg:literal) => { gate_all!($gate, $gate, $msg); }; + ($spans:ident, $gate:ident, $msg:literal) => { + for span in &*sess.gated_spans.$spans.borrow() { + gate_feature!(&ctx, $gate, *span, $msg); + } + } + } + + gate_all!(param_attrs, "attributes on function parameters are unstable"); + gate_all!(let_chains, "`let` expressions in this position are experimental"); + gate_all!(async_closure, "async closures are unstable"); + gate_all!(yields, generators, "yield syntax is experimental"); + gate_all!(or_patterns, "or-patterns syntax is experimental"); + + let visitor = &mut PostExpansionVisitor { + context: &ctx, + builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP, + }; + visit::walk_crate(visitor, krate); +} + +#[derive(Clone, Copy, Hash)] +pub enum UnstableFeatures { + /// Hard errors for unstable features are active, as on beta/stable channels. + Disallow, + /// Allow features to be activated, as on nightly. + Allow, + /// Errors are bypassed for bootstrapping. This is required any time + /// during the build that feature-related lints are set to warn or above + /// because the build turns on warnings-as-errors and uses lots of unstable + /// features. As a result, this is always required for building Rust itself. + Cheat +} + +impl UnstableFeatures { + pub fn from_environment() -> UnstableFeatures { + // Whether this is a feature-staged build, i.e., on the beta or stable channel + let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some(); + // Whether we should enable unstable features for bootstrapping + let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok(); + match (disable_unstable_features, bootstrap) { + (_, true) => UnstableFeatures::Cheat, + (true, _) => UnstableFeatures::Disallow, + (false, _) => UnstableFeatures::Allow + } + } + + pub fn is_nightly_build(&self) -> bool { + match *self { + UnstableFeatures::Allow | UnstableFeatures::Cheat => true, + _ => false, + } + } +} + +fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, unstable: UnstableFeatures) { + let allow_features = match unstable { + UnstableFeatures::Allow => true, + UnstableFeatures::Disallow => false, + UnstableFeatures::Cheat => true + }; + if !allow_features { + for attr in &krate.attrs { + if attr.check_name(sym::feature) { + let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"); + span_err!(span_handler, attr.span, E0554, + "`#![feature]` may not be used on the {} release channel", + release_channel); + } + } + } +} From 6febb75ec8e0aeade9be97a1224bd6327b531524 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 22 Aug 2019 23:49:55 +0200 Subject: [PATCH 156/618] syntax: move `feature_gate.rs`. --- src/libsyntax/{feature_gate.rs => feature_gate/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/libsyntax/{feature_gate.rs => feature_gate/mod.rs} (100%) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate/mod.rs similarity index 100% rename from src/libsyntax/feature_gate.rs rename to src/libsyntax/feature_gate/mod.rs From 3cfb6bc73a429a67f87c6542de2b8f9395cf4b94 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 23 Aug 2019 00:06:32 +0200 Subject: [PATCH 157/618] Fix `tidy` fallout due to `feature_gate.rs` refactoring. --- src/tools/tidy/src/features.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 88a469ef9550c..468e56001012f 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -221,7 +221,14 @@ fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool { } pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { - let contents = t!(fs::read_to_string(base_src_path.join("libsyntax/feature_gate.rs"))); + let mut all = collect_lang_features_in(base_src_path, "active.rs", bad); + all.extend(collect_lang_features_in(base_src_path, "accepted.rs", bad)); + all.extend(collect_lang_features_in(base_src_path, "removed.rs", bad)); + all +} + +fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features { + let contents = t!(fs::read_to_string(base.join("libsyntax/feature_gate").join(file))); // We allow rustc-internal features to omit a tracking issue. // To make tidy accept omitting a tracking issue, group the list of features From 3e061f7c495138767a0f21ac6a56d81a9faf573d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 23 Aug 2019 01:09:51 +0200 Subject: [PATCH 158/618] `--bless` some tests due to message format change. --- .../ui/conditional-compilation/cfg-attr-crate-2.rs | 2 +- .../ui/conditional-compilation/cfg-attr-crate-2.stderr | 2 +- .../cfg-attr-multi-invalid-1.rs | 3 ++- .../cfg-attr-multi-invalid-1.stderr | 2 +- .../cfg-attr-multi-invalid-2.rs | 3 ++- .../cfg-attr-multi-invalid-2.stderr | 2 +- src/test/ui/feature-gate-optimize_attribute.rs | 10 +++++----- src/test/ui/feature-gate-optimize_attribute.stderr | 10 +++++----- .../feature-gates/feature-gate-alloc-error-handler.rs | 2 +- .../feature-gate-alloc-error-handler.stderr | 2 +- src/test/ui/feature-gates/feature-gate-allow_fail.rs | 2 +- .../ui/feature-gates/feature-gate-allow_fail.stderr | 2 +- .../ui/feature-gates/feature-gate-marker_trait_attr.rs | 2 +- .../feature-gate-marker_trait_attr.stderr | 2 +- src/test/ui/feature-gates/feature-gate-no_core.rs | 2 +- src/test/ui/feature-gates/feature-gate-no_core.stderr | 2 +- .../ui/feature-gates/feature-gate-non_exhaustive.rs | 2 +- .../feature-gates/feature-gate-non_exhaustive.stderr | 2 +- src/test/ui/feature-gates/feature-gate-rustc-attrs.rs | 2 +- .../ui/feature-gates/feature-gate-rustc-attrs.stderr | 2 +- .../ui/feature-gates/feature-gate-unwind-attributes.rs | 2 +- .../feature-gate-unwind-attributes.stderr | 2 +- src/test/ui/malformed/malformed-regressions.stderr | 6 ++---- 23 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs b/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs index 0dceba28b6ec3..7dbeba53afcfe 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs @@ -3,6 +3,6 @@ // compile-flags: --cfg broken #![crate_type = "lib"] -#![cfg_attr(broken, no_core)] //~ ERROR no_core is experimental +#![cfg_attr(broken, no_core)] //~ ERROR the `#[no_core]` attribute is an experimental feature pub struct S {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr index 5a70a5efc7f2a..7b77701ee190f 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr @@ -1,4 +1,4 @@ -error[E0658]: no_core is experimental +error[E0658]: the `#[no_core]` attribute is an experimental feature --> $DIR/cfg-attr-crate-2.rs:6:21 | LL | #![cfg_attr(broken, no_core)] diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs index be762c56048d4..42ffb71e3d7b9 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs @@ -1,6 +1,7 @@ // compile-flags: --cfg broken #![crate_type = "lib"] -#![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental +#![cfg_attr(broken, no_core, no_std)] +//~^ ERROR the `#[no_core]` attribute is an experimental feature pub struct S {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr index 5e9adf1780737..ab7e1eb96032d 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr @@ -1,4 +1,4 @@ -error[E0658]: no_core is experimental +error[E0658]: the `#[no_core]` attribute is an experimental feature --> $DIR/cfg-attr-multi-invalid-1.rs:4:21 | LL | #![cfg_attr(broken, no_core, no_std)] diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs index 8a9e99d703c70..29690e2848f2d 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs @@ -1,6 +1,7 @@ // compile-flags: --cfg broken #![crate_type = "lib"] -#![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental +#![cfg_attr(broken, no_std, no_core)] +//~^ ERROR the `#[no_core]` attribute is an experimental feature pub struct S {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr index 06b67156651cc..8126affbd36cd 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr @@ -1,4 +1,4 @@ -error[E0658]: no_core is experimental +error[E0658]: the `#[no_core]` attribute is an experimental feature --> $DIR/cfg-attr-multi-invalid-2.rs:4:29 | LL | #![cfg_attr(broken, no_std, no_core)] diff --git a/src/test/ui/feature-gate-optimize_attribute.rs b/src/test/ui/feature-gate-optimize_attribute.rs index 7fc0fdde6fba8..15aa3a6af4ca9 100644 --- a/src/test/ui/feature-gate-optimize_attribute.rs +++ b/src/test/ui/feature-gate-optimize_attribute.rs @@ -1,17 +1,17 @@ #![crate_type="rlib"] -#![optimize(speed)] //~ ERROR `#[optimize]` attribute is an unstable feature +#![optimize(speed)] //~ ERROR the `#[optimize]` attribute is an experimental feature -#[optimize(size)] //~ ERROR `#[optimize]` attribute is an unstable feature +#[optimize(size)] //~ ERROR the `#[optimize]` attribute is an experimental feature mod module { -#[optimize(size)] //~ ERROR `#[optimize]` attribute is an unstable feature +#[optimize(size)] //~ ERROR the `#[optimize]` attribute is an experimental feature fn size() {} -#[optimize(speed)] //~ ERROR `#[optimize]` attribute is an unstable feature +#[optimize(speed)] //~ ERROR the `#[optimize]` attribute is an experimental feature fn speed() {} #[optimize(banana)] -//~^ ERROR `#[optimize]` attribute is an unstable feature +//~^ ERROR the `#[optimize]` attribute is an experimental feature //~| ERROR E0722 fn not_known() {} diff --git a/src/test/ui/feature-gate-optimize_attribute.stderr b/src/test/ui/feature-gate-optimize_attribute.stderr index 4ec512eaf39a4..3e3ad71c344ee 100644 --- a/src/test/ui/feature-gate-optimize_attribute.stderr +++ b/src/test/ui/feature-gate-optimize_attribute.stderr @@ -1,4 +1,4 @@ -error[E0658]: `#[optimize]` attribute is an unstable feature +error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:7:1 | LL | #[optimize(size)] @@ -7,7 +7,7 @@ LL | #[optimize(size)] = note: for more information, see https://github.com/rust-lang/rust/issues/54882 = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable -error[E0658]: `#[optimize]` attribute is an unstable feature +error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:10:1 | LL | #[optimize(speed)] @@ -16,7 +16,7 @@ LL | #[optimize(speed)] = note: for more information, see https://github.com/rust-lang/rust/issues/54882 = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable -error[E0658]: `#[optimize]` attribute is an unstable feature +error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:13:1 | LL | #[optimize(banana)] @@ -25,7 +25,7 @@ LL | #[optimize(banana)] = note: for more information, see https://github.com/rust-lang/rust/issues/54882 = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable -error[E0658]: `#[optimize]` attribute is an unstable feature +error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:4:1 | LL | #[optimize(size)] @@ -34,7 +34,7 @@ LL | #[optimize(size)] = note: for more information, see https://github.com/rust-lang/rust/issues/54882 = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable -error[E0658]: `#[optimize]` attribute is an unstable feature +error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:2:1 | LL | #![optimize(speed)] diff --git a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs index 17b4f775ad4de..ad89096183080 100644 --- a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs +++ b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs @@ -5,7 +5,7 @@ use core::alloc::Layout; -#[alloc_error_handler] //~ ERROR `#[alloc_error_handler]` is an unstable feature +#[alloc_error_handler] //~ ERROR the `#[alloc_error_handler]` attribute is an experimental feature fn oom(info: Layout) -> ! { loop {} } diff --git a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr index d18cc09ffe777..79e44bf0d8ec1 100644 --- a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr +++ b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr @@ -1,4 +1,4 @@ -error[E0658]: `#[alloc_error_handler]` is an unstable feature +error[E0658]: the `#[alloc_error_handler]` attribute is an experimental feature --> $DIR/feature-gate-alloc-error-handler.rs:8:1 | LL | #[alloc_error_handler] diff --git a/src/test/ui/feature-gates/feature-gate-allow_fail.rs b/src/test/ui/feature-gates/feature-gate-allow_fail.rs index f9ad48551410c..287d4ccf18010 100644 --- a/src/test/ui/feature-gates/feature-gate-allow_fail.rs +++ b/src/test/ui/feature-gates/feature-gate-allow_fail.rs @@ -1,6 +1,6 @@ // check that #[allow_fail] is feature-gated -#[allow_fail] //~ ERROR allow_fail attribute is currently unstable +#[allow_fail] //~ ERROR the `#[allow_fail]` attribute is an experimental feature fn ok_to_fail() { assert!(false); } diff --git a/src/test/ui/feature-gates/feature-gate-allow_fail.stderr b/src/test/ui/feature-gates/feature-gate-allow_fail.stderr index 37bf3a262aaa0..0f60a2de3a4e5 100644 --- a/src/test/ui/feature-gates/feature-gate-allow_fail.stderr +++ b/src/test/ui/feature-gates/feature-gate-allow_fail.stderr @@ -1,4 +1,4 @@ -error[E0658]: allow_fail attribute is currently unstable +error[E0658]: the `#[allow_fail]` attribute is an experimental feature --> $DIR/feature-gate-allow_fail.rs:3:1 | LL | #[allow_fail] diff --git a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs index ea06c775b1a60..5050c4792b064 100644 --- a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs +++ b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs @@ -1,7 +1,7 @@ use std::fmt::{Debug, Display}; #[marker] trait ExplicitMarker {} -//~^ ERROR marker traits is an experimental feature +//~^ ERROR the `#[marker]` attribute is an experimental feature impl ExplicitMarker for T {} impl ExplicitMarker for T {} diff --git a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr index 94dfaf9206d14..304c081c5aace 100644 --- a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr +++ b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr @@ -1,4 +1,4 @@ -error[E0658]: marker traits is an experimental feature +error[E0658]: the `#[marker]` attribute is an experimental feature --> $DIR/feature-gate-marker_trait_attr.rs:3:1 | LL | #[marker] trait ExplicitMarker {} diff --git a/src/test/ui/feature-gates/feature-gate-no_core.rs b/src/test/ui/feature-gates/feature-gate-no_core.rs index 40178edd74b8d..706efd7867211 100644 --- a/src/test/ui/feature-gates/feature-gate-no_core.rs +++ b/src/test/ui/feature-gates/feature-gate-no_core.rs @@ -1,5 +1,5 @@ #![crate_type = "rlib"] -#![no_core] //~ ERROR no_core is experimental +#![no_core] //~ ERROR the `#[no_core]` attribute is an experimental feature pub struct S {} diff --git a/src/test/ui/feature-gates/feature-gate-no_core.stderr b/src/test/ui/feature-gates/feature-gate-no_core.stderr index 4d4ca96544e56..a80b3cbba25b1 100644 --- a/src/test/ui/feature-gates/feature-gate-no_core.stderr +++ b/src/test/ui/feature-gates/feature-gate-no_core.stderr @@ -1,4 +1,4 @@ -error[E0658]: no_core is experimental +error[E0658]: the `#[no_core]` attribute is an experimental feature --> $DIR/feature-gate-no_core.rs:3:1 | LL | #![no_core] diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs b/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs index aca214d1935e2..950f170f4fd41 100644 --- a/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs @@ -1,6 +1,6 @@ //#![feature(non_exhaustive)] -#[non_exhaustive] //~ERROR non exhaustive is an experimental feature +#[non_exhaustive] //~ERROR the `#[non_exhaustive]` attribute is an experimental feature pub enum NonExhaustiveEnum { Unit, Tuple(u32), diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr b/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr index 8a01aa9eb6a9a..482332b8d706c 100644 --- a/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr @@ -1,4 +1,4 @@ -error[E0658]: non exhaustive is an experimental feature +error[E0658]: the `#[non_exhaustive]` attribute is an experimental feature --> $DIR/feature-gate-non_exhaustive.rs:3:1 | LL | #[non_exhaustive] diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs index 13983726c78de..4044fd2b895e4 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs @@ -16,7 +16,7 @@ fn f() {} fn g() {} #[rustc_dummy] -//~^ ERROR used by the test suite +//~^ ERROR the `#[rustc_dummy]` attribute is just used for rustc unit tests #[rustc_unknown] //~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler //~| ERROR cannot find attribute macro `rustc_unknown` in this scope diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr index 23cf936ee8350..c1063027fa444 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr @@ -43,7 +43,7 @@ error: cannot find attribute macro `rustc_unknown` in this scope LL | #[rustc_unknown] | ^^^^^^^^^^^^^ -error[E0658]: used by the test suite +error[E0658]: the `#[rustc_dummy]` attribute is just used for rustc unit tests and will never be stable --> $DIR/feature-gate-rustc-attrs.rs:18:1 | LL | #[rustc_dummy] diff --git a/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs b/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs index 08e8ec9a56e51..6d8ac7e8f2911 100644 --- a/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs +++ b/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs @@ -8,7 +8,7 @@ extern { fn extern_fn(); // CHECK-NOT: Function Attrs: nounwind // CHECK: declare void @unwinding_extern_fn - #[unwind(allowed)] //~ ERROR `#[unwind]` is experimental + #[unwind(allowed)] //~ ERROR the `#[unwind]` attribute is an experimental feature fn unwinding_extern_fn(); } diff --git a/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr b/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr index 639b87e016214..10cc494213507 100644 --- a/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr +++ b/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr @@ -1,4 +1,4 @@ -error[E0658]: `#[unwind]` is experimental +error[E0658]: the `#[unwind]` attribute is an experimental feature --> $DIR/feature-gate-unwind-attributes.rs:11:5 | LL | #[unwind(allowed)] diff --git a/src/test/ui/malformed/malformed-regressions.stderr b/src/test/ui/malformed/malformed-regressions.stderr index eebb6f0623fbf..164668f562ce0 100644 --- a/src/test/ui/malformed/malformed-regressions.stderr +++ b/src/test/ui/malformed/malformed-regressions.stderr @@ -26,8 +26,7 @@ LL | #[inline = ""] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 -warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", - /*opt*/ cfg = "...")]` +warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ cfg = "...")]` --> $DIR/malformed-regressions.rs:6:1 | LL | #[link] @@ -36,8 +35,7 @@ LL | #[link] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 -warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", - /*opt*/ cfg = "...")]` +warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ cfg = "...")]` --> $DIR/malformed-regressions.rs:7:1 | LL | #[link = ""] From c8838efe355df9a9834e96a0d853743d21f06ce2 Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Thu, 22 Aug 2019 14:40:21 -0300 Subject: [PATCH 159/618] Implement decode_error_kind for wasi Based on the implementation for unix targets --- src/libstd/sys/wasi/mod.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs index f842869e08ee6..57da81b41e7ca 100644 --- a/src/libstd/sys/wasi/mod.rs +++ b/src/libstd/sys/wasi/mod.rs @@ -64,8 +64,24 @@ pub fn unsupported_err() -> Error { Error::new(ErrorKind::Other, "operation not supported on wasm yet") } -pub fn decode_error_kind(_code: i32) -> ErrorKind { - ErrorKind::Other +pub fn decode_error_kind(errno: i32) -> ErrorKind { + match errno as libc::c_int { + libc::ECONNREFUSED => ErrorKind::ConnectionRefused, + libc::ECONNRESET => ErrorKind::ConnectionReset, + libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied, + libc::EPIPE => ErrorKind::BrokenPipe, + libc::ENOTCONN => ErrorKind::NotConnected, + libc::ECONNABORTED => ErrorKind::ConnectionAborted, + libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, + libc::EADDRINUSE => ErrorKind::AddrInUse, + libc::ENOENT => ErrorKind::NotFound, + libc::EINTR => ErrorKind::Interrupted, + libc::EINVAL => ErrorKind::InvalidInput, + libc::ETIMEDOUT => ErrorKind::TimedOut, + libc::EEXIST => ErrorKind::AlreadyExists, + libc::EAGAIN => ErrorKind::WouldBlock, + _ => ErrorKind::Other, + } } // This enum is used as the storage for a bunch of types which can't actually From 73e3508bb84bec2911f56e5c2463eee3688cf8ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 23 Aug 2019 11:14:11 -0700 Subject: [PATCH 160/618] Suggest calling closure with resolved return type when appropriate --- src/librustc/ty/sty.rs | 3 +- src/librustc_typeck/check/coercion.rs | 13 +- src/librustc_typeck/check/mod.rs | 130 +++++++++++------- .../fn-or-tuple-struct-without-args.rs | 2 + .../fn-or-tuple-struct-without-args.stderr | 16 ++- 5 files changed, 103 insertions(+), 61 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index da66fdf5b1b1b..7b7e2b8bfbdc8 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -385,7 +385,8 @@ impl<'tcx> ClosureSubsts<'tcx> { let ty = self.closure_sig_ty(def_id, tcx); match ty.sty { ty::FnPtr(sig) => sig, - _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty), + ty::Infer(_) | ty::Error => ty::Binder::dummy(FnSig::fake()), // ignore errors + _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.sty), } } } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 4edb6ad893113..61b9c2a15ba16 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -799,12 +799,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// adjusted type of the expression, if successful. /// Adjustments are only recorded if the coercion succeeded. /// The expressions *must not* have any pre-existing adjustments. - pub fn try_coerce(&self, - expr: &hir::Expr, - expr_ty: Ty<'tcx>, - target: Ty<'tcx>, - allow_two_phase: AllowTwoPhase) - -> RelateResult<'tcx, Ty<'tcx>> { + pub fn try_coerce( + &self, + expr: &hir::Expr, + expr_ty: Ty<'tcx>, + target: Ty<'tcx>, + allow_two_phase: AllowTwoPhase, + ) -> RelateResult<'tcx, Ty<'tcx>> { let source = self.resolve_type_vars_with_obligations(expr_ty); debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9c7ac83e82e97..d92ce29f28459 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3917,75 +3917,99 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, ) -> bool { - match found.sty { - ty::FnDef(..) | ty::FnPtr(_) => {} - _ => return false, - } let hir = self.tcx.hir(); + let (def_id, sig) = match found.sty { + ty::FnDef(def_id, _) => (def_id, found.fn_sig(self.tcx)), + ty::Closure(def_id, substs) => { + // We don't use `closure_sig` to account for malformed closures like + // `|_: [_; continue]| {}` and instead we don't suggest anything. + let closure_sig_ty = substs.closure_sig_ty(def_id, self.tcx); + (def_id, match closure_sig_ty.sty { + ty::FnPtr(sig) => sig, + _ => return false, + }) + } + _ => return false, + }; - let sig = found.fn_sig(self.tcx); let sig = self .replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, &sig) .0; let sig = self.normalize_associated_types_in(expr.span, &sig); - if let Ok(_) = self.try_coerce(expr, sig.output(), expected, AllowTwoPhase::No) { + if self.can_coerce(sig.output(), expected) { let (mut sugg_call, applicability) = if sig.inputs().is_empty() { (String::new(), Applicability::MachineApplicable) } else { ("...".to_string(), Applicability::HasPlaceholders) }; let mut msg = "call this function"; - if let ty::FnDef(def_id, ..) = found.sty { - match hir.get_if_local(def_id) { - Some(Node::Item(hir::Item { - node: ItemKind::Fn(.., body_id), - .. - })) | - Some(Node::ImplItem(hir::ImplItem { - node: hir::ImplItemKind::Method(_, body_id), - .. - })) | - Some(Node::TraitItem(hir::TraitItem { - node: hir::TraitItemKind::Method(.., hir::TraitMethod::Provided(body_id)), - .. - })) => { - let body = hir.body(*body_id); - sugg_call = body.arguments.iter() - .map(|arg| match &arg.pat.node { - hir::PatKind::Binding(_, _, ident, None) - if ident.name != kw::SelfLower => ident.to_string(), - _ => "_".to_string(), - }).collect::>().join(", "); + match hir.get_if_local(def_id) { + Some(Node::Item(hir::Item { + node: ItemKind::Fn(.., body_id), + .. + })) | + Some(Node::ImplItem(hir::ImplItem { + node: hir::ImplItemKind::Method(_, body_id), + .. + })) | + Some(Node::TraitItem(hir::TraitItem { + node: hir::TraitItemKind::Method(.., hir::TraitMethod::Provided(body_id)), + .. + })) => { + let body = hir.body(*body_id); + sugg_call = body.arguments.iter() + .map(|arg| match &arg.pat.node { + hir::PatKind::Binding(_, _, ident, None) + if ident.name != kw::SelfLower => ident.to_string(), + _ => "_".to_string(), + }).collect::>().join(", "); + } + Some(Node::Expr(hir::Expr { + node: ExprKind::Closure(_, _, body_id, closure_span, _), + span: full_closure_span, + .. + })) => { + if *full_closure_span == expr.span { + return false; } - Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => { - sugg_call = fields.iter().map(|_| "_").collect::>().join(", "); - match hir.as_local_hir_id(def_id).and_then(|hir_id| hir.def_kind(hir_id)) { - Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, _)) => { - msg = "instantiate this tuple variant"; - } - Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, _)) => { - msg = "instantiate this tuple struct"; - } - _ => {} + err.span_label(*closure_span, "closure defined here"); + msg = "call this closure"; + let body = hir.body(*body_id); + sugg_call = body.arguments.iter() + .map(|arg| match &arg.pat.node { + hir::PatKind::Binding(_, _, ident, None) + if ident.name != kw::SelfLower => ident.to_string(), + _ => "_".to_string(), + }).collect::>().join(", "); + } + Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => { + sugg_call = fields.iter().map(|_| "_").collect::>().join(", "); + match hir.as_local_hir_id(def_id).and_then(|hir_id| hir.def_kind(hir_id)) { + Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, _)) => { + msg = "instantiate this tuple variant"; } + Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, _)) => { + msg = "instantiate this tuple struct"; + } + _ => {} } - Some(Node::ForeignItem(hir::ForeignItem { - node: hir::ForeignItemKind::Fn(_, idents, _), - .. - })) | - Some(Node::TraitItem(hir::TraitItem { - node: hir::TraitItemKind::Method(.., hir::TraitMethod::Required(idents)), - .. - })) => sugg_call = idents.iter() - .map(|ident| if ident.name != kw::SelfLower { - ident.to_string() - } else { - "_".to_string() - }).collect::>() - .join(", "), - _ => {} } - }; + Some(Node::ForeignItem(hir::ForeignItem { + node: hir::ForeignItemKind::Fn(_, idents, _), + .. + })) | + Some(Node::TraitItem(hir::TraitItem { + node: hir::TraitItemKind::Method(.., hir::TraitMethod::Required(idents)), + .. + })) => sugg_call = idents.iter() + .map(|ident| if ident.name != kw::SelfLower { + ident.to_string() + } else { + "_".to_string() + }).collect::>() + .join(", "), + _ => {} + } if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) { err.span_suggestion( expr.span, diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs index 9b6b10748172b..dd5af3e344cab 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs @@ -42,4 +42,6 @@ fn main() { let _: usize = X::bal; //~ ERROR mismatched types let _: usize = X.ban; //~ ERROR attempted to take value of method let _: usize = X.bal; //~ ERROR attempted to take value of method + let closure = || 42; + let _: usize = closure; //~ ERROR mismatched types } diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index 0686b56f97ded..28b331bdbdcbc 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -214,7 +214,21 @@ error[E0615]: attempted to take value of method `bal` on type `X` LL | let _: usize = X.bal; | ^^^ help: use parentheses to call the method: `bal()` -error: aborting due to 16 previous errors +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:46:20 + | +LL | let closure = || 42; + | -- closure defined here +LL | let _: usize = closure; + | ^^^^^^^ + | | + | expected usize, found closure + | help: use parentheses to call this closure: `closure()` + | + = note: expected type `usize` + found type `[closure@$DIR/fn-or-tuple-struct-without-args.rs:45:19: 45:24]` + +error: aborting due to 17 previous errors Some errors have detailed explanations: E0308, E0423, E0615. For more information about an error, try `rustc --explain E0308`. From 055f7e2ec23f36e522e318a64eab414caba55e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 23 Aug 2019 13:45:18 -0700 Subject: [PATCH 161/618] Extend comment --- src/librustc_typeck/check/method/suggest.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 9f4fed23697ab..440e7e5d0e314 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -747,7 +747,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Node::GenericParam(ref param) = hir.get(id) { match param.kind { hir::GenericParamKind::Type { synthetic: Some(_), .. } => { - impl_trait = true; // #63706 + // We've found `fn foo(x: impl Trait)` instead of + // `fn foo(x: T)`. We want to suggest the correct + // `fn foo(x: impl Trait + TraitBound)` instead of + // `fn foo(x: T)`. (#63706) + impl_trait = true; has_bounds = param.bounds.len() > 1; } _ => { From 912feabfc282d0040f5e56bfbba752069d4f5a1f Mon Sep 17 00:00:00 2001 From: Baoshan Pang Date: Fri, 23 Aug 2019 13:25:01 -0700 Subject: [PATCH 162/618] VxWorks does not provide a way to set the task name except at creation time --- src/libstd/sys/vxworks/thread.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/vxworks/thread.rs b/src/libstd/sys/vxworks/thread.rs index 58af8cbe48e36..ef896f6a6e8cf 100644 --- a/src/libstd/sys/vxworks/thread.rs +++ b/src/libstd/sys/vxworks/thread.rs @@ -77,7 +77,7 @@ impl Thread { } pub fn set_name(_name: &CStr) { - assert!(false, "FIXME: set_name"); + // VxWorks does not provide a way to set the task name except at creation time } pub fn sleep(dur: Duration) { From b47c9690d2974ec0318f1e87bf38f8f7ee6cf202 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 16 Aug 2019 08:29:08 -0700 Subject: [PATCH 163/618] bootstrap: Merge the libtest build step with libstd Since its inception rustbuild has always worked in three stages: one for libstd, one for libtest, and one for rustc. These three stages were architected around crates.io dependencies, where rustc wants to depend on crates.io crates but said crates don't explicitly depend on libstd, requiring a sysroot assembly step in the middle. This same logic was applied for libtest where libtest wants to depend on crates.io crates (`getopts`) but `getopts` didn't say that it depended on std, so it needed `std` built ahead of time. Lots of time has passed since the inception of rustbuild, however, and we've since gotten to the point where even `std` itself is depending on crates.io crates (albeit with some wonky configuration). This commit applies the same logic to the two dependencies that the `test` crate pulls in from crates.io, `getopts` and `unicode-width`. Over the many years since rustbuild's inception `unicode-width` was the only dependency picked up by the `test` crate, so the extra configuration necessary to get crates building in this crate graph is unlikely to be too much of a burden on developers. After this patch it means that there are now only two build phasese of rustbuild, one for libstd and one for rustc. The libtest/libproc_macro build phase is all lumped into one now with `std`. This was originally motivated by rust-lang/cargo#7216 where Cargo was having to deal with synthesizing dependency edges but this commit makes them explicit in this repository. --- Cargo.lock | 34 ++++- Cargo.toml | 1 + src/bootstrap/builder.rs | 12 +- src/bootstrap/builder/tests.rs | 153 ++++++++----------- src/bootstrap/check.rs | 55 +------ src/bootstrap/compile.rs | 139 +---------------- src/bootstrap/dist.rs | 8 +- src/bootstrap/doc.rs | 128 +--------------- src/bootstrap/lib.rs | 7 +- src/bootstrap/test.rs | 36 +---- src/bootstrap/tool.rs | 39 +---- src/libproc_macro/Cargo.toml | 3 + src/libterm/Cargo.toml | 6 +- src/libtest/Cargo.toml | 16 +- src/tools/rustc-std-workspace-std/Cargo.toml | 15 ++ src/tools/rustc-std-workspace-std/README.md | 3 + src/tools/rustc-std-workspace-std/lib.rs | 1 + src/tools/tidy/src/deps.rs | 3 + 18 files changed, 162 insertions(+), 497 deletions(-) create mode 100644 src/tools/rustc-std-workspace-std/Cargo.toml create mode 100644 src/tools/rustc-std-workspace-std/README.md create mode 100644 src/tools/rustc-std-workspace-std/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d96f92505adec..8ae21c8663706 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1139,10 +1139,12 @@ dependencies = [ [[package]] name = "getopts" -version = "0.2.19" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72327b15c228bfe31f1390f93dd5e9279587f0463836393c9df719ce62a3e450" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" dependencies = [ + "rustc-std-workspace-core", + "rustc-std-workspace-std", "unicode-width", ] @@ -2375,6 +2377,9 @@ dependencies = [ [[package]] name = "proc_macro" version = "0.0.0" +dependencies = [ + "std", +] [[package]] name = "profiler_builtins" @@ -3063,6 +3068,13 @@ dependencies = [ "core", ] +[[package]] +name = "rustc-std-workspace-std" +version = "1.0.0" +dependencies = [ + "std", +] + [[package]] name = "rustc-workspace-hack" version = "1.0.0" @@ -4068,6 +4080,10 @@ dependencies = [ [[package]] name = "term" version = "0.0.0" +dependencies = [ + "core", + "std", +] [[package]] name = "term" @@ -4114,8 +4130,13 @@ dependencies = [ name = "test" version = "0.0.0" dependencies = [ + "core", "getopts", + "libc", + "panic_abort", + "panic_unwind", "proc_macro", + "std", "term 0.0.0", ] @@ -4483,9 +4504,14 @@ checksum = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" [[package]] name = "unicode-width" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +checksum = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", + "rustc-std-workspace-std", +] [[package]] name = "unicode-xid" diff --git a/Cargo.toml b/Cargo.toml index ccd7e8b7654a6..a242f090fbc07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,6 +68,7 @@ rustc-workspace-hack = { path = 'src/tools/rustc-workspace-hack' } # here rustc-std-workspace-core = { path = 'src/tools/rustc-std-workspace-core' } rustc-std-workspace-alloc = { path = 'src/tools/rustc-std-workspace-alloc' } +rustc-std-workspace-std = { path = 'src/tools/rustc-std-workspace-std' } [patch."https://github.com/rust-lang/rust-clippy"] clippy_lints = { path = "src/tools/clippy/clippy_lints" } diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 4e49aaa16eae1..4f5de1ecd2b44 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -337,7 +337,6 @@ impl<'a> Builder<'a> { match kind { Kind::Build => describe!( compile::Std, - compile::Test, compile::Rustc, compile::CodegenBackend, compile::StartupObjects, @@ -363,7 +362,6 @@ impl<'a> Builder<'a> { ), Kind::Check | Kind::Clippy | Kind::Fix => describe!( check::Std, - check::Test, check::Rustc, check::CodegenBackend, check::Rustdoc @@ -425,8 +423,6 @@ impl<'a> Builder<'a> { doc::TheBook, doc::Standalone, doc::Std, - doc::Test, - doc::WhitelistedRustc, doc::Rustc, doc::Rustdoc, doc::ErrorIndex, @@ -801,7 +797,7 @@ impl<'a> Builder<'a> { } match mode { - Mode::Std | Mode::Test | Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolTest=> {}, + Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {}, Mode::Rustc | Mode::Codegen | Mode::ToolRustc => { // Build proc macros both for the host and the target if target != compiler.host && cmd != "check" { @@ -852,7 +848,6 @@ impl<'a> Builder<'a> { // things still build right, please do! match mode { Mode::Std => metadata.push_str("std"), - Mode::Test => metadata.push_str("test"), _ => {}, } cargo.env("__CARGO_DEFAULT_LIB_METADATA", &metadata); @@ -948,9 +943,9 @@ impl<'a> Builder<'a> { let debuginfo_level = match mode { Mode::Rustc | Mode::Codegen => self.config.rust_debuginfo_level_rustc, - Mode::Std | Mode::Test => self.config.rust_debuginfo_level_std, + Mode::Std => self.config.rust_debuginfo_level_std, Mode::ToolBootstrap | Mode::ToolStd | - Mode::ToolTest | Mode::ToolRustc => self.config.rust_debuginfo_level_tools, + Mode::ToolRustc => self.config.rust_debuginfo_level_tools, }; cargo.env("RUSTC_DEBUGINFO_LEVEL", debuginfo_level.to_string()); @@ -1150,7 +1145,6 @@ impl<'a> Builder<'a> { match (mode, self.config.rust_codegen_units_std, self.config.rust_codegen_units) { (Mode::Std, Some(n), _) | - (Mode::Test, Some(n), _) | (_, _, Some(n)) => { cargo.env("RUSTC_CODEGEN_UNITS", n.to_string()); } diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs index d1542b1fca6b7..2bb90fdb04edc 100644 --- a/src/bootstrap/builder/tests.rs +++ b/src/bootstrap/builder/tests.rs @@ -365,27 +365,6 @@ fn dist_with_same_targets_and_hosts() { }, ] ); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Test { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - ] - ); assert_eq!( first(builder.cache.all::()), &[ @@ -415,7 +394,47 @@ fn build_default() { let b = INTERNER.intern_str("B"); let c = INTERNER.intern_str("C"); - assert!(!builder.cache.all::().is_empty()); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Std { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: b, stage: 2 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + compile::Std { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + compile::Std { + compiler: Compiler { host: b, stage: 2 }, + target: b, + }, + compile::Std { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + compile::Std { + compiler: Compiler { host: b, stage: 2 }, + target: c, + }, + ] + ); assert!(!builder.cache.all::().is_empty()); assert_eq!( first(builder.cache.all::()), @@ -450,63 +469,61 @@ fn build_default() { }, ] ); +} + +#[test] +fn build_with_target_flag() { + let mut config = configure(&["B"], &["C"]); + config.skip_only_host_steps = true; + let build = Build::new(config); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); assert_eq!( - first(builder.cache.all::()), + first(builder.cache.all::()), &[ - compile::Test { + compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a, }, - compile::Test { + compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a, }, - compile::Test { + compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a, }, - compile::Test { + compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a, }, - compile::Test { + compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b, }, - compile::Test { + compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b, }, - compile::Test { + compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b, }, - compile::Test { + compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c, }, - compile::Test { + compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c, }, ] ); -} - -#[test] -fn build_with_target_flag() { - let mut config = configure(&["B"], &["C"]); - config.skip_only_host_steps = true; - let build = Build::new(config); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); - - assert!(!builder.cache.all::().is_empty()); assert_eq!( first(builder.cache.all::()), &[ @@ -541,48 +558,6 @@ fn build_with_target_flag() { }, ] ); - - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Test { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: c, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: c, - }, - ] - ); } #[test] diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 6e6fea6b831a7..e9a9b7881a068 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -1,6 +1,6 @@ //! Implementation of compiling the compiler and standard library, in "check"-based modes. -use crate::compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, +use crate::compile::{run_cargo, std_cargo, rustc_cargo, rustc_cargo_env, add_to_sysroot}; use crate::builder::{RunConfig, Builder, Kind, ShouldRun, Step}; use crate::tool::{prepare_tool_cargo, SourceType}; @@ -92,7 +92,7 @@ impl Step for Rustc { let compiler = builder.compiler(0, builder.config.build); let target = self.target; - builder.ensure(Test { target }); + builder.ensure(Std { target }); let mut cargo = builder.cargo(compiler, Mode::Rustc, target, cargo_subcommand(builder.kind)); @@ -159,47 +159,6 @@ impl Step for CodegenBackend { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Test { - pub target: Interned, -} - -impl Step for Test { - type Output = (); - const DEFAULT: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("test") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Test { - target: run.target, - }); - } - - fn run(self, builder: &Builder<'_>) { - let compiler = builder.compiler(0, builder.config.build); - let target = self.target; - - builder.ensure(Std { target }); - - let mut cargo = builder.cargo(compiler, Mode::Test, target, cargo_subcommand(builder.kind)); - test_cargo(builder, &compiler, target, &mut cargo); - - builder.info(&format!("Checking test artifacts ({} -> {})", &compiler.host, target)); - run_cargo(builder, - &mut cargo, - args(builder.kind), - &libtest_stamp(builder, compiler, target), - true); - - let libdir = builder.sysroot_libdir(compiler, target); - let hostdir = builder.sysroot_libdir(compiler, compiler.host); - add_to_sysroot(builder, &libdir, &hostdir, &libtest_stamp(builder, compiler, target)); - } -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Rustdoc { pub target: Interned, @@ -258,16 +217,6 @@ pub fn libstd_stamp( builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check.stamp") } -/// Cargo's output path for libtest in a given stage, compiled by a particular -/// compiler for the specified target. -pub fn libtest_stamp( - builder: &Builder<'_>, - compiler: Compiler, - target: Interned, -) -> PathBuf { - builder.cargo_out(compiler, Mode::Test, target).join(".libtest-check.stamp") -} - /// Cargo's output path for librustc in a given stage, compiled by a particular /// compiler for the specified target. pub fn librustc_stamp( diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 96987d081594f..7dad146b48d83 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -216,7 +216,7 @@ pub fn std_cargo(builder: &Builder<'_>, cargo.arg("--features").arg(features) .arg("--manifest-path") - .arg(builder.src.join("src/libstd/Cargo.toml")); + .arg(builder.src.join("src/libtest/Cargo.toml")); if target.contains("musl") { if let Some(p) = builder.musl_root(target) { @@ -358,129 +358,6 @@ impl Step for StartupObjects { } } -#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Test { - pub target: Interned, - pub compiler: Compiler, -} - -impl Step for Test { - type Output = (); - const DEFAULT: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("test") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Test { - compiler: run.builder.compiler(run.builder.top_stage, run.host), - target: run.target, - }); - } - - /// Builds libtest. - /// - /// This will build libtest and supporting libraries for a particular stage of - /// the build using the `compiler` targeting the `target` architecture. The - /// artifacts created will also be linked into the sysroot directory. - fn run(self, builder: &Builder<'_>) { - let target = self.target; - let compiler = self.compiler; - - builder.ensure(Std { compiler, target }); - - if builder.config.keep_stage.contains(&compiler.stage) { - builder.info("Warning: Using a potentially old libtest. This may not behave well."); - builder.ensure(TestLink { - compiler, - target_compiler: compiler, - target, - }); - return; - } - - let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); - if compiler_to_use != compiler { - builder.ensure(Test { - compiler: compiler_to_use, - target, - }); - builder.info( - &format!("Uplifting stage1 test ({} -> {})", builder.config.build, target)); - builder.ensure(TestLink { - compiler: compiler_to_use, - target_compiler: compiler, - target, - }); - return; - } - - let mut cargo = builder.cargo(compiler, Mode::Test, target, "build"); - test_cargo(builder, &compiler, target, &mut cargo); - - builder.info(&format!("Building stage{} test artifacts ({} -> {})", compiler.stage, - &compiler.host, target)); - run_cargo(builder, - &mut cargo, - vec![], - &libtest_stamp(builder, compiler, target), - false); - - builder.ensure(TestLink { - compiler: builder.compiler(compiler.stage, builder.config.build), - target_compiler: compiler, - target, - }); - } -} - -/// Same as `std_cargo`, but for libtest -pub fn test_cargo(builder: &Builder<'_>, - _compiler: &Compiler, - _target: Interned, - cargo: &mut Command) { - if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { - cargo.env("MACOSX_DEPLOYMENT_TARGET", target); - } - cargo.arg("--manifest-path") - .arg(builder.src.join("src/libtest/Cargo.toml")); -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct TestLink { - pub compiler: Compiler, - pub target_compiler: Compiler, - pub target: Interned, -} - -impl Step for TestLink { - type Output = (); - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.never() - } - - /// Same as `std_link`, only for libtest - fn run(self, builder: &Builder<'_>) { - let compiler = self.compiler; - let target_compiler = self.target_compiler; - let target = self.target; - builder.info(&format!("Copying stage{} test from stage{} ({} -> {} / {})", - target_compiler.stage, - compiler.stage, - &compiler.host, - target_compiler.host, - target)); - add_to_sysroot( - builder, - &builder.sysroot_libdir(target_compiler, target), - &builder.sysroot_libdir(target_compiler, compiler.host), - &libtest_stamp(builder, compiler, target) - ); - } -} - #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] pub struct Rustc { pub target: Interned, @@ -512,7 +389,7 @@ impl Step for Rustc { let compiler = self.compiler; let target = self.target; - builder.ensure(Test { compiler, target }); + builder.ensure(Std { compiler, target }); if builder.config.keep_stage.contains(&compiler.stage) { builder.info("Warning: Using a potentially old librustc. This may not behave well."); @@ -541,7 +418,7 @@ impl Step for Rustc { } // Ensure that build scripts and proc macros have a std / libproc_macro to link against. - builder.ensure(Test { + builder.ensure(Std { compiler: builder.compiler(self.compiler.stage, builder.config.build), target: builder.config.build, }); @@ -872,16 +749,6 @@ pub fn libstd_stamp( builder.cargo_out(compiler, Mode::Std, target).join(".libstd.stamp") } -/// Cargo's output path for libtest in a given stage, compiled by a particular -/// compiler for the specified target. -pub fn libtest_stamp( - builder: &Builder<'_>, - compiler: Compiler, - target: Interned, -) -> PathBuf { - builder.cargo_out(compiler, Mode::Test, target).join(".libtest.stamp") -} - /// Cargo's output path for librustc in a given stage, compiled by a particular /// compiler for the specified target. pub fn librustc_stamp( diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 213ceb194a814..0f4ac63651ca9 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -678,12 +678,7 @@ impl Step for Std { if builder.hosts.iter().any(|t| t == target) { builder.ensure(compile::Rustc { compiler, target }); } else { - if builder.no_std(target) == Some(true) { - // the `test` doesn't compile for no-std targets - builder.ensure(compile::Std { compiler, target }); - } else { - builder.ensure(compile::Test { compiler, target }); - } + builder.ensure(compile::Std { compiler, target }); } let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); @@ -912,6 +907,7 @@ impl Step for Src { "src/libproc_macro", "src/tools/rustc-std-workspace-core", "src/tools/rustc-std-workspace-alloc", + "src/tools/rustc-std-workspace-std", "src/librustc", "src/libsyntax", ]; diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 4f96c12fc1ddd..6805474aa049f 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -478,138 +478,12 @@ impl Step for Std { builder.run(&mut cargo); builder.cp_r(&my_out, &out); }; - for krate in &["alloc", "core", "std"] { + for krate in &["alloc", "core", "std", "proc_macro", "test"] { run_cargo_rustdoc_for(krate); } } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Test { - stage: u32, - target: Interned, -} - -impl Step for Test { - type Output = (); - const DEFAULT: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.krate("test").default_condition(builder.config.docs) - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Test { - stage: run.builder.top_stage, - target: run.target, - }); - } - - /// Compile all libtest documentation. - /// - /// This will generate all documentation for libtest and its dependencies. This - /// is largely just a wrapper around `cargo doc`. - fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - let target = self.target; - builder.info(&format!("Documenting stage{} test ({})", stage, target)); - let out = builder.doc_out(target); - t!(fs::create_dir_all(&out)); - let compiler = builder.compiler_for(stage, builder.config.build, target); - - // Build libstd docs so that we generate relative links - builder.ensure(Std { stage, target }); - - builder.ensure(compile::Test { compiler, target }); - let out_dir = builder.stage_out(compiler, Mode::Test) - .join(target).join("doc"); - - // See docs in std above for why we symlink - let my_out = builder.crate_doc_out(target); - t!(symlink_dir_force(&builder.config, &my_out, &out_dir)); - - let mut cargo = builder.cargo(compiler, Mode::Test, target, "doc"); - compile::test_cargo(builder, &compiler, target, &mut cargo); - - cargo.arg("--no-deps") - .arg("-p").arg("test") - .env("RUSTDOC_RESOURCE_SUFFIX", crate::channel::CFG_RELEASE_NUM) - .env("RUSTDOC_GENERATE_REDIRECT_PAGES", "1"); - - builder.run(&mut cargo); - builder.cp_r(&my_out, &out); - } -} - -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct WhitelistedRustc { - stage: u32, - target: Interned, -} - -impl Step for WhitelistedRustc { - type Output = (); - const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.krate("rustc-main").default_condition(builder.config.docs) - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(WhitelistedRustc { - stage: run.builder.top_stage, - target: run.target, - }); - } - - /// Generates whitelisted compiler crate documentation. - /// - /// This will generate all documentation for crates that are whitelisted - /// to be included in the standard documentation. This documentation is - /// included in the standard Rust documentation, so we should always - /// document it and symlink to merge with the rest of the std and test - /// documentation. We don't build other compiler documentation - /// here as we want to be able to keep it separate from the standard - /// documentation. This is largely just a wrapper around `cargo doc`. - fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - let target = self.target; - builder.info(&format!("Documenting stage{} whitelisted compiler ({})", stage, target)); - let out = builder.doc_out(target); - t!(fs::create_dir_all(&out)); - let compiler = builder.compiler_for(stage, builder.config.build, target); - - // Build libstd docs so that we generate relative links - builder.ensure(Std { stage, target }); - - builder.ensure(compile::Rustc { compiler, target }); - let out_dir = builder.stage_out(compiler, Mode::Rustc) - .join(target).join("doc"); - - // See docs in std above for why we symlink - let my_out = builder.crate_doc_out(target); - t!(symlink_dir_force(&builder.config, &my_out, &out_dir)); - - let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc"); - compile::rustc_cargo(builder, &mut cargo); - - // We don't want to build docs for internal compiler dependencies in this - // step (there is another step for that). Therefore, we whitelist the crates - // for which docs must be built. - for krate in &["proc_macro"] { - cargo.arg("-p").arg(krate) - .env("RUSTDOC_RESOURCE_SUFFIX", crate::channel::CFG_RELEASE_NUM) - .env("RUSTDOC_GENERATE_REDIRECT_PAGES", "1"); - } - - builder.run(&mut cargo); - builder.cp_r(&my_out, &out); - } -} - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rustc { stage: u32, diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index b72aa78f3de19..c0e0ad1a857b9 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -297,9 +297,6 @@ pub enum Mode { /// Build the standard library, placing output in the "stageN-std" directory. Std, - /// Build libtest, placing output in the "stageN-test" directory. - Test, - /// Build librustc, and compiler libraries, placing output in the "stageN-rustc" directory. Rustc, @@ -315,7 +312,6 @@ pub enum Mode { /// Compile a tool which uses all libraries we compile (up to rustc). /// Doesn't use the stage0 compiler libraries like "other", and includes /// tools like rustdoc, cargo, rls, etc. - ToolTest, ToolStd, ToolRustc, } @@ -536,11 +532,10 @@ impl Build { fn stage_out(&self, compiler: Compiler, mode: Mode) -> PathBuf { let suffix = match mode { Mode::Std => "-std", - Mode::Test => "-test", Mode::Rustc => "-rustc", Mode::Codegen => "-codegen", Mode::ToolBootstrap => "-bootstrap-tools", - Mode::ToolStd | Mode::ToolTest | Mode::ToolRustc => "-tools", + Mode::ToolStd | Mode::ToolRustc => "-tools", }; self.out.join(&*compiler.host) .join(format!("stage{}{}", compiler.stage, suffix)) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 87bd5cbacfffa..2bb053cc2b002 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1040,21 +1040,10 @@ impl Step for Compiletest { builder.ensure(compile::Rustc { compiler, target }); } - if builder.no_std(target) == Some(true) { - // the `test` doesn't compile for no-std targets - builder.ensure(compile::Std { compiler, target }); - } else { - builder.ensure(compile::Test { compiler, target }); - } - - if builder.no_std(target) == Some(true) { - // for no_std run-make (e.g., thumb*), - // we need a host compiler which is called by cargo. - builder.ensure(compile::Std { compiler, target: compiler.host }); - } + builder.ensure(compile::Std { compiler, target }); + // ensure that `libproc_macro` is available on the host. + builder.ensure(compile::Std { compiler, target: compiler.host }); - // HACK(eddyb) ensure that `libproc_macro` is available on the host. - builder.ensure(compile::Test { compiler, target: compiler.host }); // Also provide `rust_test_helpers` for the host. builder.ensure(native::TestHelpers { target: compiler.host }); @@ -1399,7 +1388,7 @@ impl Step for DocTest { fn run(self, builder: &Builder<'_>) { let compiler = self.compiler; - builder.ensure(compile::Test { + builder.ensure(compile::Std { compiler, target: compiler.host, }); @@ -1709,8 +1698,7 @@ impl Step for Crate { fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run = run.krate("test"); - for krate in run.builder.in_tree_crates("std") { + for krate in run.builder.in_tree_crates("test") { if !(krate.name.starts_with("rustc_") && krate.name.ends_with("san")) { run = run.path(krate.local_path(&builder).to_str().unwrap()); } @@ -1734,14 +1722,9 @@ impl Step for Crate { }); }; - for krate in builder.in_tree_crates("std") { - if run.path.ends_with(&krate.local_path(&builder)) { - make(Mode::Std, krate); - } - } for krate in builder.in_tree_crates("test") { if run.path.ends_with(&krate.local_path(&builder)) { - make(Mode::Test, krate); + make(Mode::Std, krate); } } } @@ -1761,7 +1744,7 @@ impl Step for Crate { let test_kind = self.test_kind; let krate = self.krate; - builder.ensure(compile::Test { compiler, target }); + builder.ensure(compile::Std { compiler, target }); builder.ensure(RemoteCopyLibs { compiler, target }); // If we're not doing a full bootstrap but we're testing a stage2 @@ -1775,9 +1758,6 @@ impl Step for Crate { Mode::Std => { compile::std_cargo(builder, &compiler, target, &mut cargo); } - Mode::Test => { - compile::test_cargo(builder, &compiler, target, &mut cargo); - } Mode::Rustc => { builder.ensure(compile::Rustc { compiler, target }); compile::rustc_cargo(builder, &mut cargo); @@ -1979,7 +1959,7 @@ impl Step for RemoteCopyLibs { return; } - builder.ensure(compile::Test { compiler, target }); + builder.ensure(compile::Std { compiler, target }); builder.info(&format!("REMOTE copy libs to emulator ({})", target)); t!(fs::create_dir_all(builder.out.join("tmp"))); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index df7eb7c455d02..54fe26f18e741 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -577,12 +577,6 @@ impl Step for Cargo { } fn run(self, builder: &Builder<'_>) -> PathBuf { - // Cargo depends on procedural macros, so make sure the host - // libstd/libproc_macro is available. - builder.ensure(compile::Test { - compiler: self.compiler, - target: builder.config.build, - }); builder.ensure(ToolBuild { compiler: self.compiler, target: self.target, @@ -650,31 +644,10 @@ macro_rules! tool_extended { tool_extended!((self, builder), Cargofmt, rustfmt, "src/tools/rustfmt", "cargo-fmt", {}; - CargoClippy, clippy, "src/tools/clippy", "cargo-clippy", { - // Clippy depends on procedural macros, so make sure that's built for - // the compiler itself. - builder.ensure(compile::Test { - compiler: self.compiler, - target: builder.config.build, - }); - }; - Clippy, clippy, "src/tools/clippy", "clippy-driver", { - // Clippy depends on procedural macros, so make sure that's built for - // the compiler itself. - builder.ensure(compile::Test { - compiler: self.compiler, - target: builder.config.build, - }); - }; + CargoClippy, clippy, "src/tools/clippy", "cargo-clippy", {}; + Clippy, clippy, "src/tools/clippy", "clippy-driver", {}; Miri, miri, "src/tools/miri", "miri", {}; - CargoMiri, miri, "src/tools/miri", "cargo-miri", { - // Miri depends on procedural macros, so make sure that's built for - // the compiler itself. - builder.ensure(compile::Test { - compiler: self.compiler, - target: builder.config.build, - }); - }; + CargoMiri, miri, "src/tools/miri", "cargo-miri", {}; Rls, rls, "src/tools/rls", "rls", { let clippy = builder.ensure(Clippy { compiler: self.compiler, @@ -684,12 +657,6 @@ tool_extended!((self, builder), if clippy.is_some() { self.extra_features.push("clippy".to_owned()); } - // RLS depends on procedural macros, so make sure that's built for - // the compiler itself. - builder.ensure(compile::Test { - compiler: self.compiler, - target: builder.config.build, - }); }; Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", {}; ); diff --git a/src/libproc_macro/Cargo.toml b/src/libproc_macro/Cargo.toml index b3d0ee94f0e12..187bdac80019d 100644 --- a/src/libproc_macro/Cargo.toml +++ b/src/libproc_macro/Cargo.toml @@ -6,3 +6,6 @@ edition = "2018" [lib] path = "lib.rs" + +[dependencies] +std = { path = "../libstd" } diff --git a/src/libterm/Cargo.toml b/src/libterm/Cargo.toml index 4eba9a9d79cc4..2931e0bda9518 100644 --- a/src/libterm/Cargo.toml +++ b/src/libterm/Cargo.toml @@ -5,6 +5,8 @@ version = "0.0.0" edition = "2018" [lib] -name = "term" path = "lib.rs" -crate-type = ["dylib", "rlib"] + +[dependencies] +core = { path = "../libcore" } +std = { path = "../libstd" } diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml index a72e4c7050289..170fbb984cf9b 100644 --- a/src/libtest/Cargo.toml +++ b/src/libtest/Cargo.toml @@ -10,8 +10,22 @@ path = "lib.rs" crate-type = ["dylib", "rlib"] [dependencies] -getopts = "0.2.19" +getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] } term = { path = "../libterm" } +std = { path = "../libstd" } +core = { path = "../libcore" } +libc = { version = "0.2", default-features = false } +panic_unwind = { path = "../libpanic_unwind" } +panic_abort = { path = "../libpanic_abort" } # not actually used but needed to always have proc_macro in the sysroot proc_macro = { path = "../libproc_macro" } + +# Forward features to the `std` crate as necessary +[features] +backtrace = ["std/backtrace"] +compiler-builtins-c = ["std/compiler-builtins-c"] +llvm-libunwind = ["std/llvm-libunwind"] +panic-unwind = ["std/panic_unwind"] +panic_immediate_abort = ["std/panic_immediate_abort"] +profiler = ["std/profiler"] diff --git a/src/tools/rustc-std-workspace-std/Cargo.toml b/src/tools/rustc-std-workspace-std/Cargo.toml new file mode 100644 index 0000000000000..ce1644809dbe6 --- /dev/null +++ b/src/tools/rustc-std-workspace-std/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "rustc-std-workspace-std" +version = "1.0.0" +authors = ["Alex Crichton "] +license = 'MIT OR Apache-2.0' +description = """ +Hack for the compiler's own build system +""" +edition = "2018" + +[lib] +path = "lib.rs" + +[dependencies] +std = { path = "../../libstd" } diff --git a/src/tools/rustc-std-workspace-std/README.md b/src/tools/rustc-std-workspace-std/README.md new file mode 100644 index 0000000000000..2228907f304c4 --- /dev/null +++ b/src/tools/rustc-std-workspace-std/README.md @@ -0,0 +1,3 @@ +# The `rustc-std-workspace-std` crate + +See documentation for the `rustc-std-workspace-core` crate. diff --git a/src/tools/rustc-std-workspace-std/lib.rs b/src/tools/rustc-std-workspace-std/lib.rs new file mode 100644 index 0000000000000..f40d09cafbb47 --- /dev/null +++ b/src/tools/rustc-std-workspace-std/lib.rs @@ -0,0 +1 @@ +pub use std::*; diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index de54eb8f57312..e07a07234c71e 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -90,15 +90,18 @@ const WHITELIST: &[Crate<'_>] = &[ Crate("crossbeam-epoch"), Crate("crossbeam-utils"), Crate("datafrog"), + Crate("dlmalloc"), Crate("either"), Crate("ena"), Crate("env_logger"), Crate("filetime"), Crate("flate2"), + Crate("fortanix-sgx-abi"), Crate("fuchsia-zircon"), Crate("fuchsia-zircon-sys"), Crate("getopts"), Crate("getrandom"), + Crate("hashbrown"), Crate("humantime"), Crate("indexmap"), Crate("itertools"), From 7dff647d23103f1de29df89c0714eddec6c0a57b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 24 Aug 2019 02:23:56 +0200 Subject: [PATCH 164/618] Ensure miri can do bit ops on pointer values --- src/librustc_mir/interpret/intrinsics.rs | 13 ++++++++----- src/librustc_mir/interpret/operand.rs | 9 ++++----- src/librustc_mir/interpret/traits.rs | 6 ++++-- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 4c86c53256e9b..334f1ea1a6901 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -95,7 +95,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | "bitreverse" => { let ty = substs.type_at(0); let layout_of = self.layout_of(ty)?; - let bits = self.read_scalar(args[0])?.to_bits(layout_of.size)?; + let val = self.read_scalar(args[0])?.not_undef()?; + let bits = self.force_bits(val, layout_of.size)?; let kind = match layout_of.abi { ty::layout::Abi::Scalar(ref scalar) => scalar.value, _ => throw_unsup!(TypeNotPrimitive(ty)), @@ -149,7 +150,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // term since the sign of the second term can be inferred from this and // the fact that the operation has overflowed (if either is 0 no // overflow can occur) - let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?; + let first_term: u128 = self.force_bits(l.to_scalar()?, l.layout.size)?; let first_term_positive = first_term & (1 << (num_bits-1)) == 0; if first_term_positive { // Negative overflow not possible since the positive first term @@ -187,7 +188,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (val, overflowed, _ty) = self.overflowing_binary_op(bin_op, l, r)?; if overflowed { let layout = self.layout_of(substs.type_at(0))?; - let r_val = r.to_scalar()?.to_bits(layout.size)?; + let r_val = self.force_bits(r.to_scalar()?, layout.size)?; throw_ub_format!("Overflowing shift by {} in `{}`", r_val, intrinsic_name); } self.write_scalar(val, dest)?; @@ -196,8 +197,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW)) // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW)) let layout = self.layout_of(substs.type_at(0))?; - let val_bits = self.read_scalar(args[0])?.to_bits(layout.size)?; - let raw_shift_bits = self.read_scalar(args[1])?.to_bits(layout.size)?; + let val = self.read_scalar(args[0])?.not_undef()?; + let val_bits = self.force_bits(val, layout.size)?; + let raw_shift = self.read_scalar(args[1])?.not_undef()?; + let raw_shift_bits = self.force_bits(raw_shift, layout.size)?; let width_bits = layout.size.bits() as u128; let shift_bits = raw_shift_bits % width_bits; let inv_shift_bits = (width_bits - shift_bits) % width_bits; diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 7a545e8ad6f79..b5aab992e3adb 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -629,11 +629,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // post-process Ok(match *discr_kind { layout::DiscriminantKind::Tag => { - let bits_discr = match raw_discr.to_bits(discr_val.layout.size) { - Ok(raw_discr) => raw_discr, - Err(_) => - throw_unsup!(InvalidDiscriminant(raw_discr.erase_tag())), - }; + let bits_discr = raw_discr + .not_undef() + .and_then(|raw_discr| self.force_bits(raw_discr, discr_val.layout.size)) + .map_err(|_| err_unsup!(InvalidDiscriminant(raw_discr.erase_tag())))?; let real_discr = if discr_val.layout.ty.is_signed() { // going from layout tag type to typeck discriminant type // requires first sign extending with the layout discriminant diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index a2fc75739ffa0..34a10de7de7fc 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -144,11 +144,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let size = alloc.read_ptr_sized( self, vtable.offset(pointer_size, self)? - )?.to_bits(pointer_size)? as u64; + )?.not_undef()?; + let size = self.force_bits(size, pointer_size)? as u64; let align = alloc.read_ptr_sized( self, vtable.offset(pointer_size * 2, self)?, - )?.to_bits(pointer_size)? as u64; + )?.not_undef()?; + let align = self.force_bits(align, pointer_size)? as u64; Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap())) } } From d6bf776bc69c766aa70c39f28f6c70ab7faf32b7 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Wed, 21 Aug 2019 21:38:23 -0400 Subject: [PATCH 165/618] Fix incremental tests --- .../persist/dirty_clean.rs | 27 ++++++++++++++----- src/test/incremental/hashes/for_loops.rs | 2 +- src/test/incremental/hashes/inherent_impls.rs | 12 ++++++--- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index e569a9bc7df40..837aa9360c895 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -24,6 +24,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::intravisit; use rustc::ich::{ATTR_DIRTY, ATTR_CLEAN}; use rustc::ty::TyCtxt; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashSet; use syntax::ast::{self, Attribute, NestedMetaItem}; use syntax::symbol::{Symbol, sym}; @@ -71,6 +72,7 @@ const BASE_IMPL: &[&str] = &[ /// code, i.e., functions+methods const BASE_MIR: &[&str] = &[ label_strs::optimized_mir, + label_strs::promoted_mir, label_strs::mir_built, ]; @@ -472,11 +474,10 @@ impl DirtyCleanVisitor<'tcx> { fn assert_dirty(&self, item_span: Span, dep_node: DepNode) { debug!("assert_dirty({:?})", dep_node); - let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node); - let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index); + let current_fingerprint = self.get_fingerprint(&dep_node); let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); - if Some(current_fingerprint) == prev_fingerprint { + if current_fingerprint == prev_fingerprint { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, @@ -484,14 +485,28 @@ impl DirtyCleanVisitor<'tcx> { } } + fn get_fingerprint(&self, dep_node: &DepNode) -> Option { + if self.tcx.dep_graph.dep_node_exists(dep_node) { + let dep_node_index = self.tcx.dep_graph.dep_node_index_of(dep_node); + Some(self.tcx.dep_graph.fingerprint_of(dep_node_index)) + } else { + None + } + } + fn assert_clean(&self, item_span: Span, dep_node: DepNode) { debug!("assert_clean({:?})", dep_node); - let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node); - let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index); + let current_fingerprint = self.get_fingerprint(&dep_node); let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); - if Some(current_fingerprint) != prev_fingerprint { + // if the node wasn't previously evaluated and now is (or vice versa), + // then the node isn't actually clean or dirty. + if (current_fingerprint == None) ^ (prev_fingerprint == None) { + return; + } + + if current_fingerprint != prev_fingerprint { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs index 5d0b8b867b22f..70820dfaea4a0 100644 --- a/src/test/incremental/hashes/for_loops.rs +++ b/src/test/incremental/hashes/for_loops.rs @@ -94,7 +94,7 @@ pub fn change_iterable() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, promoted_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_iterable() { let mut _x = 0; diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 882383e841957..e98f9b67ca421 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -42,7 +42,10 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] + #[rustc_clean( + cfg="cfail2", + except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of" + )] #[rustc_clean(cfg="cfail3")] pub fn method_body() { println!("Hello, world!"); @@ -63,7 +66,10 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] + #[rustc_clean( + cfg="cfail2", + except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of" + )] #[rustc_clean(cfg="cfail3")] #[inline] pub fn method_body_inlined() { @@ -97,7 +103,7 @@ impl Foo { #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(cfg="cfail2", except="type_of,predicates_of")] + #[rustc_dirty(cfg="cfail2", except="type_of,predicates_of,promoted_mir")] #[rustc_clean(cfg="cfail3")] pub fn method_selfness(&self) { } } From a577316b0a136b5ca980032cf1dbe683103ba15f Mon Sep 17 00:00:00 2001 From: Christian Date: Sat, 24 Aug 2019 13:36:57 +0200 Subject: [PATCH 166/618] Removed the confusing FnOnce example. closes #47091 --- src/libcore/ops/function.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs index b9552eaa1a0e5..9bb1ae8572b71 100644 --- a/src/libcore/ops/function.rs +++ b/src/libcore/ops/function.rs @@ -184,15 +184,6 @@ pub trait FnMut : FnOnce { /// [nomicon]: ../../nomicon/hrtb.html /// /// # Examples -/// -/// ## Calling a by-value closure -/// -/// ``` -/// let x = 5; -/// let square_x = move || x * x; -/// assert_eq!(square_x(), 25); -/// ``` -/// /// ## Using a `FnOnce` parameter /// /// ``` From 55f8dde6c89e3af68d4c59232f3d06e6130e9f0a Mon Sep 17 00:00:00 2001 From: Christian Date: Sat, 24 Aug 2019 13:38:09 +0200 Subject: [PATCH 167/618] Added an extra line to make the formatting conform to the rest of the document. --- src/libcore/ops/function.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs index 9bb1ae8572b71..4a0a2720fe441 100644 --- a/src/libcore/ops/function.rs +++ b/src/libcore/ops/function.rs @@ -184,6 +184,7 @@ pub trait FnMut : FnOnce { /// [nomicon]: ../../nomicon/hrtb.html /// /// # Examples +/// /// ## Using a `FnOnce` parameter /// /// ``` From 8ca9c7bbe5f2be252881e1edbd2a2ce97e75244f Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Sat, 24 Aug 2019 17:45:03 +0200 Subject: [PATCH 168/618] Fix tidy feature gate error reporting Feature gate definitions were split into multiple files in #63824 but tidy kept reporting the hard-coded path. Now, it shows the full path to the correct file. --- src/tools/tidy/src/features.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 468e56001012f..50e9116c778ea 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -176,7 +176,10 @@ pub fn check(path: &Path, bad: &mut bool, verbose: bool) -> CollectedFeatures { CollectedFeatures { lib: lib_features, lang: features } } -fn format_features<'a>(features: &'a Features, family: &'a str) -> impl Iterator + 'a { +fn format_features<'a>( + features: &'a Features, + family: &'a str, +) -> impl Iterator + 'a { features.iter().map(move |(name, feature)| { format!("{:<32} {:<8} {:<12} {:<8}", name, @@ -228,7 +231,8 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { } fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features { - let contents = t!(fs::read_to_string(base.join("libsyntax/feature_gate").join(file))); + let path = base.join("libsyntax/feature_gate").join(file); + let contents = t!(fs::read_to_string(&path)); // We allow rustc-internal features to omit a tracking issue. // To make tidy accept omitting a tracking issue, group the list of features @@ -259,8 +263,9 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features if in_feature_group { tidy_error!( bad, - // ignore-tidy-linelength - "libsyntax/feature_gate.rs:{}: new feature group is started without ending the previous one", + "{}:{}: \ + new feature group is started without ending the previous one", + path.display(), line_number, ); } @@ -289,7 +294,8 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features Err(err) => { tidy_error!( bad, - "libsyntax/feature_gate.rs:{}: failed to parse since: {} ({:?})", + "{}:{}: failed to parse since: {} ({:?})", + path.display(), line_number, since_str, err, @@ -301,7 +307,8 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features if prev_since > since { tidy_error!( bad, - "libsyntax/feature_gate.rs:{}: feature {} is not sorted by since", + "{}:{}: feature {} is not sorted by since", + path.display(), line_number, name, ); @@ -315,7 +322,8 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features *bad = true; tidy_error!( bad, - "libsyntax/feature_gate.rs:{}: no tracking issue for feature {}", + "{}:{}: no tracking issue for feature {}", + path.display(), line_number, name, ); From c9619a4202bd013f1be2776c328937ddd643e7b7 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Sat, 24 Aug 2019 17:47:26 +0200 Subject: [PATCH 169/618] Use doc comments for feature gate descriptions This is just in preparation for future usage of these texts. --- src/libsyntax/feature_gate/accepted.rs | 218 +++++++++--------- src/libsyntax/feature_gate/active.rs | 305 +++++++++++++------------ src/libsyntax/feature_gate/removed.rs | 22 +- 3 files changed, 284 insertions(+), 261 deletions(-) diff --git a/src/libsyntax/feature_gate/accepted.rs b/src/libsyntax/feature_gate/accepted.rs index 32a0b76d5f0d8..28e4d2c073c7c 100644 --- a/src/libsyntax/feature_gate/accepted.rs +++ b/src/libsyntax/feature_gate/accepted.rs @@ -3,7 +3,9 @@ use crate::symbol::{Symbol, sym}; macro_rules! declare_features { - ($((accepted, $feature: ident, $ver: expr, $issue: expr, None),)+) => { + ($( + $(#[doc = $doc:tt])* (accepted, $feature:ident, $ver:expr, $issue:expr, None), + )+) => { /// Those language feature has since been Accepted (it was once Active) pub const ACCEPTED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ $((sym::$feature, $ver, $issue, None)),+ @@ -16,11 +18,11 @@ declare_features! ( // feature-group-start: for testing purposes // ------------------------------------------------------------------------- - // A temporary feature gate used to enable parser extensions needed - // to bootstrap fix for #5723. + /// A temporary feature gate used to enable parser extensions needed + /// to bootstrap fix for #5723. (accepted, issue_5723_bootstrap, "1.0.0", None, None), - // These are used to test this portion of the compiler, - // they don't actually mean anything. + /// These are used to test this portion of the compiler, + /// they don't actually mean anything. (accepted, test_accepted_feature, "1.0.0", None, None), // ------------------------------------------------------------------------- @@ -31,203 +33,203 @@ declare_features! ( // feature-group-start: accepted features // ------------------------------------------------------------------------- - // Allows using associated `type`s in `trait`s. + /// Allows using associated `type`s in `trait`s. (accepted, associated_types, "1.0.0", None, None), - // Allows using assigning a default type to type parameters in algebraic data type definitions. + /// Allows using assigning a default type to type parameters in algebraic data type definitions. (accepted, default_type_params, "1.0.0", None, None), // FIXME: explain `globs`. (accepted, globs, "1.0.0", None, None), - // Allows `macro_rules!` items. + /// Allows `macro_rules!` items. (accepted, macro_rules, "1.0.0", None, None), - // Allows use of `&foo[a..b]` as a slicing syntax. + /// Allows use of `&foo[a..b]` as a slicing syntax. (accepted, slicing_syntax, "1.0.0", None, None), - // Allows struct variants `Foo { baz: u8, .. }` in enums (RFC 418). + /// Allows struct variants `Foo { baz: u8, .. }` in enums (RFC 418). (accepted, struct_variant, "1.0.0", None, None), - // Allows indexing tuples. + /// Allows indexing tuples. (accepted, tuple_indexing, "1.0.0", None, None), - // Allows the use of `if let` expressions. + /// Allows the use of `if let` expressions. (accepted, if_let, "1.0.0", None, None), - // Allows the use of `while let` expressions. + /// Allows the use of `while let` expressions. (accepted, while_let, "1.0.0", None, None), - // Allows using `#![no_std]`. + /// Allows using `#![no_std]`. (accepted, no_std, "1.6.0", None, None), - // Allows overloading augmented assignment operations like `a += b`. + /// Allows overloading augmented assignment operations like `a += b`. (accepted, augmented_assignments, "1.8.0", Some(28235), None), - // Allows empty structs and enum variants with braces. + /// Allows empty structs and enum variants with braces. (accepted, braced_empty_structs, "1.8.0", Some(29720), None), - // Allows `#[deprecated]` attribute. + /// Allows `#[deprecated]` attribute. (accepted, deprecated, "1.9.0", Some(29935), None), - // Allows macros to appear in the type position. + /// Allows macros to appear in the type position. (accepted, type_macros, "1.13.0", Some(27245), None), - // Allows use of the postfix `?` operator in expressions. + /// Allows use of the postfix `?` operator in expressions. (accepted, question_mark, "1.13.0", Some(31436), None), - // Allows `..` in tuple (struct) patterns. + /// Allows `..` in tuple (struct) patterns. (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None), - // Allows some increased flexibility in the name resolution rules, - // especially around globs and shadowing (RFC 1560). + /// Allows some increased flexibility in the name resolution rules, + /// especially around globs and shadowing (RFC 1560). (accepted, item_like_imports, "1.15.0", Some(35120), None), - // Allows using `Self` and associated types in struct expressions and patterns. + /// Allows using `Self` and associated types in struct expressions and patterns. (accepted, more_struct_aliases, "1.16.0", Some(37544), None), - // Allows elision of `'static` lifetimes in `static`s and `const`s. + /// Allows elision of `'static` lifetimes in `static`s and `const`s. (accepted, static_in_const, "1.17.0", Some(35897), None), - // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. + /// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. (accepted, field_init_shorthand, "1.17.0", Some(37340), None), - // Allows the definition recursive static items. + /// Allows the definition recursive static items. (accepted, static_recursion, "1.17.0", Some(29719), None), - // Allows `pub(restricted)` visibilities (RFC 1422). + /// Allows `pub(restricted)` visibilities (RFC 1422). (accepted, pub_restricted, "1.18.0", Some(32409), None), - // Allows `#![windows_subsystem]`. + /// Allows `#![windows_subsystem]`. (accepted, windows_subsystem, "1.18.0", Some(37499), None), - // Allows `break {expr}` with a value inside `loop`s. + /// Allows `break {expr}` with a value inside `loop`s. (accepted, loop_break_value, "1.19.0", Some(37339), None), - // Allows numeric fields in struct expressions and patterns. + /// Allows numeric fields in struct expressions and patterns. (accepted, relaxed_adts, "1.19.0", Some(35626), None), - // Allows coercing non capturing closures to function pointers. + /// Allows coercing non capturing closures to function pointers. (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None), - // Allows attributes on struct literal fields. + /// Allows attributes on struct literal fields. (accepted, struct_field_attributes, "1.20.0", Some(38814), None), - // Allows the definition of associated constants in `trait` or `impl` blocks. + /// Allows the definition of associated constants in `trait` or `impl` blocks. (accepted, associated_consts, "1.20.0", Some(29646), None), - // Allows usage of the `compile_error!` macro. + /// Allows usage of the `compile_error!` macro. (accepted, compile_error, "1.20.0", Some(40872), None), - // Allows code like `let x: &'static u32 = &42` to work (RFC 1414). + /// Allows code like `let x: &'static u32 = &42` to work (RFC 1414). (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), - // Allows `Drop` types in constants (RFC 1440). + /// Allows `Drop` types in constants (RFC 1440). (accepted, drop_types_in_const, "1.22.0", Some(33156), None), - // Allows the sysV64 ABI to be specified on all platforms - // instead of just the platforms on which it is the C ABI. + /// Allows the sysV64 ABI to be specified on all platforms + /// instead of just the platforms on which it is the C ABI. (accepted, abi_sysv64, "1.24.0", Some(36167), None), - // Allows `repr(align(16))` struct attribute (RFC 1358). + /// Allows `repr(align(16))` struct attribute (RFC 1358). (accepted, repr_align, "1.25.0", Some(33626), None), - // Allows '|' at beginning of match arms (RFC 1925). + /// Allows '|' at beginning of match arms (RFC 1925). (accepted, match_beginning_vert, "1.25.0", Some(44101), None), - // Allows nested groups in `use` items (RFC 2128). + /// Allows nested groups in `use` items (RFC 2128). (accepted, use_nested_groups, "1.25.0", Some(44494), None), - // Allows indexing into constant arrays. + /// Allows indexing into constant arrays. (accepted, const_indexing, "1.26.0", Some(29947), None), - // Allows using `a..=b` and `..=b` as inclusive range syntaxes. + /// Allows using `a..=b` and `..=b` as inclusive range syntaxes. (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), - // Allows `..=` in patterns (RFC 1192). + /// Allows `..=` in patterns (RFC 1192). (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), - // Allows `fn main()` with return types which implements `Termination` (RFC 1937). + /// Allows `fn main()` with return types which implements `Termination` (RFC 1937). (accepted, termination_trait, "1.26.0", Some(43301), None), - // Allows implementing `Clone` for closures where possible (RFC 2132). + /// Allows implementing `Clone` for closures where possible (RFC 2132). (accepted, clone_closures, "1.26.0", Some(44490), None), - // Allows implementing `Copy` for closures where possible (RFC 2132). + /// Allows implementing `Copy` for closures where possible (RFC 2132). (accepted, copy_closures, "1.26.0", Some(44490), None), - // Allows `impl Trait` in function arguments. + /// Allows `impl Trait` in function arguments. (accepted, universal_impl_trait, "1.26.0", Some(34511), None), - // Allows `impl Trait` in function return types. + /// Allows `impl Trait` in function return types. (accepted, conservative_impl_trait, "1.26.0", Some(34511), None), - // Allows using the `u128` and `i128` types. + /// Allows using the `u128` and `i128` types. (accepted, i128_type, "1.26.0", Some(35118), None), - // Allows default match binding modes (RFC 2005). + /// Allows default match binding modes (RFC 2005). (accepted, match_default_bindings, "1.26.0", Some(42640), None), - // Allows `'_` placeholder lifetimes. + /// Allows `'_` placeholder lifetimes. (accepted, underscore_lifetimes, "1.26.0", Some(44524), None), - // Allows attributes on lifetime/type formal parameters in generics (RFC 1327). + /// Allows attributes on lifetime/type formal parameters in generics (RFC 1327). (accepted, generic_param_attrs, "1.27.0", Some(48848), None), - // Allows `cfg(target_feature = "...")`. + /// Allows `cfg(target_feature = "...")`. (accepted, cfg_target_feature, "1.27.0", Some(29717), None), - // Allows `#[target_feature(...)]`. + /// Allows `#[target_feature(...)]`. (accepted, target_feature, "1.27.0", None, None), - // Allows using `dyn Trait` as a syntax for trait objects. + /// Allows using `dyn Trait` as a syntax for trait objects. (accepted, dyn_trait, "1.27.0", Some(44662), None), - // Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). + /// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). (accepted, fn_must_use, "1.27.0", Some(43302), None), - // Allows use of the `:lifetime` macro fragment specifier. + /// Allows use of the `:lifetime` macro fragment specifier. (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None), - // Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). + /// Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). (accepted, termination_trait_test, "1.27.0", Some(48854), None), - // Allows the `#[global_allocator]` attribute. + /// Allows the `#[global_allocator]` attribute. (accepted, global_allocator, "1.28.0", Some(27389), None), - // Allows `#[repr(transparent)]` attribute on newtype structs. + /// Allows `#[repr(transparent)]` attribute on newtype structs. (accepted, repr_transparent, "1.28.0", Some(43036), None), - // Allows procedural macros in `proc-macro` crates. + /// Allows procedural macros in `proc-macro` crates. (accepted, proc_macro, "1.29.0", Some(38356), None), - // Allows `foo.rs` as an alternative to `foo/mod.rs`. + /// Allows `foo.rs` as an alternative to `foo/mod.rs`. (accepted, non_modrs_mods, "1.30.0", Some(44660), None), - // Allows use of the `:vis` macro fragment specifier + /// Allows use of the `:vis` macro fragment specifier (accepted, macro_vis_matcher, "1.30.0", Some(41022), None), - // Allows importing and reexporting macros with `use`, - // enables macro modularization in general. + /// Allows importing and reexporting macros with `use`, + /// enables macro modularization in general. (accepted, use_extern_macros, "1.30.0", Some(35896), None), - // Allows keywords to be escaped for use as identifiers. + /// Allows keywords to be escaped for use as identifiers. (accepted, raw_identifiers, "1.30.0", Some(48589), None), - // Allows attributes scoped to tools. + /// Allows attributes scoped to tools. (accepted, tool_attributes, "1.30.0", Some(44690), None), - // Allows multi-segment paths in attributes and derives. + /// Allows multi-segment paths in attributes and derives. (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None), - // Allows all literals in attribute lists and values of key-value pairs. + /// Allows all literals in attribute lists and values of key-value pairs. (accepted, attr_literals, "1.30.0", Some(34981), None), - // Allows inferring outlives requirements (RFC 2093). + /// Allows inferring outlives requirements (RFC 2093). (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), - // Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. - // This defines the behavior of panics. + /// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. + /// This defines the behavior of panics. (accepted, panic_handler, "1.30.0", Some(44489), None), - // Allows `#[used]` to preserve symbols (see llvm.used). + /// Allows `#[used]` to preserve symbols (see llvm.used). (accepted, used, "1.30.0", Some(40289), None), - // Allows `crate` in paths. + /// Allows `crate` in paths. (accepted, crate_in_paths, "1.30.0", Some(45477), None), - // Allows resolving absolute paths as paths from other crates. + /// Allows resolving absolute paths as paths from other crates. (accepted, extern_absolute_paths, "1.30.0", Some(44660), None), - // Allows access to crate names passed via `--extern` through prelude. + /// Allows access to crate names passed via `--extern` through prelude. (accepted, extern_prelude, "1.30.0", Some(44660), None), - // Allows parentheses in patterns. + /// Allows parentheses in patterns. (accepted, pattern_parentheses, "1.31.0", Some(51087), None), - // Allows the definition of `const fn` functions. + /// Allows the definition of `const fn` functions. (accepted, min_const_fn, "1.31.0", Some(53555), None), - // Allows scoped lints. + /// Allows scoped lints. (accepted, tool_lints, "1.31.0", Some(44690), None), - // Allows lifetime elision in `impl` headers. For example: - // + `impl Iterator for &mut Iterator` - // + `impl Debug for Foo<'_>` + /// Allows lifetime elision in `impl` headers. For example: + /// + `impl Iterator for &mut Iterator` + /// + `impl Debug for Foo<'_>` (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), - // Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. + /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), - // Allows use of the `:literal` macro fragment specifier (RFC 1576). + /// Allows use of the `:literal` macro fragment specifier (RFC 1576). (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), - // Allows use of `?` as the Kleene "at most one" operator in macros. + /// Allows use of `?` as the Kleene "at most one" operator in macros. (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), - // Allows `Self` struct constructor (RFC 2302). + /// Allows `Self` struct constructor (RFC 2302). (accepted, self_struct_ctor, "1.32.0", Some(51994), None), - // Allows `Self` in type definitions (RFC 2300). + /// Allows `Self` in type definitions (RFC 2300). (accepted, self_in_typedefs, "1.32.0", Some(49303), None), - // Allows `use x::y;` to search `x` in the current scope. + /// Allows `use x::y;` to search `x` in the current scope. (accepted, uniform_paths, "1.32.0", Some(53130), None), - // Allows integer match exhaustiveness checking (RFC 2591). + /// Allows integer match exhaustiveness checking (RFC 2591). (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), - // Allows `use path as _;` and `extern crate c as _;`. + /// Allows `use path as _;` and `extern crate c as _;`. (accepted, underscore_imports, "1.33.0", Some(48216), None), - // Allows `#[repr(packed(N))]` attribute on structs. + /// Allows `#[repr(packed(N))]` attribute on structs. (accepted, repr_packed, "1.33.0", Some(33158), None), - // Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). + /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None), - // Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. + /// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None), - // Allows let bindings, assignments and destructuring in `const` functions and constants. - // As long as control flow is not implemented in const eval, `&&` and `||` may not be used - // at the same time as let bindings. + /// Allows let bindings, assignments and destructuring in `const` functions and constants. + /// As long as control flow is not implemented in const eval, `&&` and `||` may not be used + /// at the same time as let bindings. (accepted, const_let, "1.33.0", Some(48821), None), - // Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. + /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. (accepted, cfg_attr_multi, "1.33.0", Some(54881), None), - // Allows top level or-patterns (`p | q`) in `if let` and `while let`. + /// Allows top level or-patterns (`p | q`) in `if let` and `while let`. (accepted, if_while_or_patterns, "1.33.0", Some(48215), None), - // Allows `cfg(target_vendor = "...")`. + /// Allows `cfg(target_vendor = "...")`. (accepted, cfg_target_vendor, "1.33.0", Some(29718), None), - // Allows `extern crate self as foo;`. - // This puts local crate root into extern prelude under name `foo`. + /// Allows `extern crate self as foo;`. + /// This puts local crate root into extern prelude under name `foo`. (accepted, extern_crate_self, "1.34.0", Some(56409), None), - // Allows arbitrary delimited token streams in non-macro attributes. + /// Allows arbitrary delimited token streams in non-macro attributes. (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None), - // Allows paths to enum variants on type aliases including `Self`. + /// Allows paths to enum variants on type aliases including `Self`. (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None), - // Allows using `#[repr(align(X))]` on enums with equivalent semantics - // to wrapping an enum in a wrapper struct with `#[repr(align(X))]`. + /// Allows using `#[repr(align(X))]` on enums with equivalent semantics + /// to wrapping an enum in a wrapper struct with `#[repr(align(X))]`. (accepted, repr_align_enum, "1.37.0", Some(57996), None), - // Allows `const _: TYPE = VALUE`. + /// Allows `const _: TYPE = VALUE`. (accepted, underscore_const_names, "1.37.0", Some(54912), None), - // Allows free and inherent `async fn`s, `async` blocks, and `.await` expressions. + /// Allows free and inherent `async fn`s, `async` blocks, and `.await` expressions. (accepted, async_await, "1.39.0", Some(50547), None), // ------------------------------------------------------------------------- diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 0bff4ed24a4ce..4008b79b141eb 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -3,6 +3,7 @@ use crate::edition::Edition; use crate::symbol::{Symbol, sym}; use syntax_pos::Span; +use super::{State, Feature}; macro_rules! set { ($field: ident) => {{ @@ -14,12 +15,24 @@ macro_rules! set { } macro_rules! declare_features { - ($((active, $feature: ident, $ver: expr, $issue: expr, $edition: expr),)+) => { + ($( + $(#[doc = $doc:tt])* (active, $feature:ident, $ver:expr, $issue:expr, $edition:expr), + )+) => { /// Represents active features that are currently being implemented or /// currently being considered for addition/removal. pub const ACTIVE_FEATURES: - &[(Symbol, &str, Option, Option, fn(&mut Features, Span))] = - &[$((sym::$feature, $ver, $issue, $edition, set!($feature))),+]; + &[Feature] = + &[$( + // (sym::$feature, $ver, $issue, $edition, set!($feature)) + Feature { + state: State::Active { set: set!($feature) }, + name: sym::$feature, + since: $ver, + issue: $issue, + edition: $edition, + description: concat!($($doc,)*), + } + ),+]; /// A set of features to be used by later passes. #[derive(Clone)] @@ -28,7 +41,10 @@ macro_rules! declare_features { pub declared_lang_features: Vec<(Symbol, Span, Option)>, /// `#![feature]` attrs for non-language (library) features pub declared_lib_features: Vec<(Symbol, Span)>, - $(pub $feature: bool),+ + $( + $(#[doc = $doc])* + pub $feature: bool + ),+ } impl Features { @@ -58,7 +74,7 @@ macro_rules! declare_features { // stable (active). // // Note that the features are grouped into internal/user-facing and then -// sorted by version inside those groups. This is inforced with tidy. +// sorted by version inside those groups. This is enforced with tidy. // // N.B., `tools/tidy/src/features.rs` parses this information directly out of the // source, so take care when modifying it. @@ -70,127 +86,127 @@ declare_features! ( // no-tracking-issue-start - // Allows using compiler's own crates. + /// Allows using compiler's own crates. (active, rustc_private, "1.0.0", Some(27812), None), - // Allows using the `rust-intrinsic`'s "ABI". + /// Allows using the `rust-intrinsic`'s "ABI". (active, intrinsics, "1.0.0", None, None), - // Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. + /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. (active, lang_items, "1.0.0", None, None), - // Allows using the `#[stable]` and `#[unstable]` attributes. + /// Allows using the `#[stable]` and `#[unstable]` attributes. (active, staged_api, "1.0.0", None, None), - // Allows using `#[allow_internal_unstable]`. This is an - // attribute on `macro_rules!` and can't use the attribute handling - // below (it has to be checked before expansion possibly makes - // macros disappear). + /// Allows using `#[allow_internal_unstable]`. This is an + /// attribute on `macro_rules!` and can't use the attribute handling + /// below (it has to be checked before expansion possibly makes + /// macros disappear). (active, allow_internal_unstable, "1.0.0", None, None), - // Allows using `#[allow_internal_unsafe]`. This is an - // attribute on `macro_rules!` and can't use the attribute handling - // below (it has to be checked before expansion possibly makes - // macros disappear). + /// Allows using `#[allow_internal_unsafe]`. This is an + /// attribute on `macro_rules!` and can't use the attribute handling + /// below (it has to be checked before expansion possibly makes + /// macros disappear). (active, allow_internal_unsafe, "1.0.0", None, None), - // Allows using the macros: - // + `__diagnostic_used` - // + `__register_diagnostic` - // +`__build_diagnostic_array` + /// Allows using the macros: + /// + `__diagnostic_used` + /// + `__register_diagnostic` + /// +`__build_diagnostic_array` (active, rustc_diagnostic_macros, "1.0.0", None, None), - // Allows using `#[rustc_const_unstable(feature = "foo", ..)]` which - // lets a function to be `const` when opted into with `#![feature(foo)]`. + /// Allows using `#[rustc_const_unstable(feature = "foo", ..)]` which + /// lets a function to be `const` when opted into with `#![feature(foo)]`. (active, rustc_const_unstable, "1.0.0", None, None), - // no-tracking-issue-end + /// no-tracking-issue-end - // Allows using `#[link_name="llvm.*"]`. + /// Allows using `#[link_name="llvm.*"]`. (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), - // Allows using `rustc_*` attributes (RFC 572). + /// Allows using `rustc_*` attributes (RFC 572). (active, rustc_attrs, "1.0.0", Some(29642), None), - // Allows using `#[on_unimplemented(..)]` on traits. + /// Allows using `#[on_unimplemented(..)]` on traits. (active, on_unimplemented, "1.0.0", Some(29628), None), - // Allows using the `box $expr` syntax. + /// Allows using the `box $expr` syntax. (active, box_syntax, "1.0.0", Some(49733), None), - // Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. + /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. (active, main, "1.0.0", Some(29634), None), - // Allows using `#[start]` on a function indicating that it is the program entrypoint. + /// Allows using `#[start]` on a function indicating that it is the program entrypoint. (active, start, "1.0.0", Some(29633), None), - // Allows using the `#[fundamental]` attribute. + /// Allows using the `#[fundamental]` attribute. (active, fundamental, "1.0.0", Some(29635), None), - // Allows using the `rust-call` ABI. + /// Allows using the `rust-call` ABI. (active, unboxed_closures, "1.0.0", Some(29625), None), - // Allows using the `#[linkage = ".."]` attribute. + /// Allows using the `#[linkage = ".."]` attribute. (active, linkage, "1.0.0", Some(29603), None), - // Allows features specific to OIBIT (auto traits). + /// Allows features specific to OIBIT (auto traits). (active, optin_builtin_traits, "1.0.0", Some(13231), None), - // Allows using `box` in patterns (RFC 469). + /// Allows using `box` in patterns (RFC 469). (active, box_patterns, "1.0.0", Some(29641), None), // no-tracking-issue-start - // Allows using `#[prelude_import]` on glob `use` items. + /// Allows using `#[prelude_import]` on glob `use` items. (active, prelude_import, "1.2.0", None, None), // no-tracking-issue-end // no-tracking-issue-start - // Allows using `#[omit_gdb_pretty_printer_section]`. + /// Allows using `#[omit_gdb_pretty_printer_section]`. (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), - // Allows using the `vectorcall` ABI. + /// Allows using the `vectorcall` ABI. (active, abi_vectorcall, "1.7.0", None, None), // no-tracking-issue-end - // Allows using `#[structural_match]` which indicates that a type is structurally matchable. + /// Allows using `#[structural_match]` which indicates that a type is structurally matchable. (active, structural_match, "1.8.0", Some(31434), None), - // Allows using the `may_dangle` attribute (RFC 1327). + /// Allows using the `may_dangle` attribute (RFC 1327). (active, dropck_eyepatch, "1.10.0", Some(34761), None), - // Allows using the `#![panic_runtime]` attribute. + /// Allows using the `#![panic_runtime]` attribute. (active, panic_runtime, "1.10.0", Some(32837), None), - // Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. + /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. (active, needs_panic_runtime, "1.10.0", Some(32837), None), // no-tracking-issue-start - // Allows identifying the `compiler_builtins` crate. + /// Allows identifying the `compiler_builtins` crate. (active, compiler_builtins, "1.13.0", None, None), - // Allows using the `unadjusted` ABI; perma-unstable. + /// Allows using the `unadjusted` ABI; perma-unstable. (active, abi_unadjusted, "1.16.0", None, None), - // Allows identifying crates that contain sanitizer runtimes. + /// Allows identifying crates that contain sanitizer runtimes. (active, sanitizer_runtime, "1.17.0", None, None), - // Used to identify crates that contain the profiler runtime. + /// Used to identify crates that contain the profiler runtime. (active, profiler_runtime, "1.18.0", None, None), - // Allows using the `thiscall` ABI. + /// Allows using the `thiscall` ABI. (active, abi_thiscall, "1.19.0", None, None), - // Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. + /// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. (active, allocator_internals, "1.20.0", None, None), // no-tracking-issue-end - // Added for testing E0705; perma-unstable. + /// Added for testing E0705; perma-unstable. (active, test_2018_feature, "1.31.0", Some(0), Some(Edition::Edition2018)), // ------------------------------------------------------------------------- @@ -228,281 +244,282 @@ declare_features! ( // feature-group-start: actual feature gates // ------------------------------------------------------------------------- - // Allows using the `#[link_args]` attribute. + /// Allows using the `#[link_args]` attribute. (active, link_args, "1.0.0", Some(29596), None), - // Allows defining identifiers beyond ASCII. + /// Allows defining identifiers beyond ASCII. (active, non_ascii_idents, "1.0.0", Some(55467), None), - // Allows using `#[plugin_registrar]` on functions. + /// Allows using `#[plugin_registrar]` on functions. (active, plugin_registrar, "1.0.0", Some(29597), None), - // Allows using `#![plugin(myplugin)]`. + /// Allows using `#![plugin(myplugin)]`. (active, plugin, "1.0.0", Some(29597), None), - // Allows using `#[thread_local]` on `static` items. + /// Allows using `#[thread_local]` on `static` items. (active, thread_local, "1.0.0", Some(29594), None), - // Allows the use of SIMD types in functions declared in `extern` blocks. + /// Allows the use of SIMD types in functions declared in `extern` blocks. (active, simd_ffi, "1.0.0", Some(27731), None), - // Allows using custom attributes (RFC 572). + /// Allows using custom attributes (RFC 572). (active, custom_attribute, "1.0.0", Some(29642), None), - // Allows using non lexical lifetimes (RFC 2094). + /// Allows using non lexical lifetimes (RFC 2094). (active, nll, "1.0.0", Some(43234), None), - // Allows using slice patterns. + /// Allows using slice patterns. (active, slice_patterns, "1.0.0", Some(62254), None), - // Allows the definition of `const` functions with some advanced features. + /// Allows the definition of `const` functions with some advanced features. (active, const_fn, "1.2.0", Some(57563), None), - // Allows associated type defaults. + /// Allows associated type defaults. (active, associated_type_defaults, "1.2.0", Some(29661), None), - // Allows `#![no_core]`. + /// Allows `#![no_core]`. (active, no_core, "1.3.0", Some(29639), None), - // Allows default type parameters to influence type inference. + /// Allows default type parameters to influence type inference. (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), - // Allows `repr(simd)` and importing the various simd intrinsics. + /// Allows `repr(simd)` and importing the various simd intrinsics. (active, repr_simd, "1.4.0", Some(27731), None), - // Allows `extern "platform-intrinsic" { ... }`. + /// Allows `extern "platform-intrinsic" { ... }`. (active, platform_intrinsics, "1.4.0", Some(27731), None), - // Allows `#[unwind(..)]`. - // - // Permits specifying whether a function should permit unwinding or abort on unwind. + /// Allows `#[unwind(..)]`. + /// + /// Permits specifying whether a function should permit unwinding or abort on unwind. (active, unwind_attributes, "1.4.0", Some(58760), None), - // Allows `#[no_debug]`. + /// Allows `#[no_debug]`. (active, no_debug, "1.5.0", Some(29721), None), - // Allows attributes on expressions and non-item statements. + /// Allows attributes on expressions and non-item statements. (active, stmt_expr_attributes, "1.6.0", Some(15701), None), - // Allows the use of type ascription in expressions. + /// Allows the use of type ascription in expressions. (active, type_ascription, "1.6.0", Some(23416), None), - // Allows `cfg(target_thread_local)`. + /// Allows `cfg(target_thread_local)`. (active, cfg_target_thread_local, "1.7.0", Some(29594), None), - // Allows specialization of implementations (RFC 1210). + /// Allows specialization of implementations (RFC 1210). (active, specialization, "1.7.0", Some(31844), None), - // Allows using `#[naked]` on functions. + /// Allows using `#[naked]` on functions. (active, naked_functions, "1.9.0", Some(32408), None), - // Allows `cfg(target_has_atomic = "...")`. + /// Allows `cfg(target_has_atomic = "...")`. (active, cfg_target_has_atomic, "1.9.0", Some(32976), None), - // Allows `X..Y` patterns. + /// Allows `X..Y` patterns. (active, exclusive_range_pattern, "1.11.0", Some(37854), None), - // Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. + /// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. (active, never_type, "1.13.0", Some(35121), None), - // Allows exhaustive pattern matching on types that contain uninhabited types. + /// Allows exhaustive pattern matching on types that contain uninhabited types. (active, exhaustive_patterns, "1.13.0", Some(51085), None), - // Allows untagged unions `union U { ... }`. + /// Allows untagged unions `union U { ... }`. (active, untagged_unions, "1.13.0", Some(32836), None), - // Allows `#[link(..., cfg(..))]`. + /// Allows `#[link(..., cfg(..))]`. (active, link_cfg, "1.14.0", Some(37406), None), - // Allows `extern "ptx-*" fn()`. + /// Allows `extern "ptx-*" fn()`. (active, abi_ptx, "1.15.0", Some(38788), None), - // Allows the `#[repr(i128)]` attribute for enums. + /// Allows the `#[repr(i128)]` attribute for enums. (active, repr128, "1.16.0", Some(35118), None), - // Allows `#[link(kind="static-nobundle"...)]`. + /// Allows `#[link(kind="static-nobundle"...)]`. (active, static_nobundle, "1.16.0", Some(37403), None), - // Allows `extern "msp430-interrupt" fn()`. + /// Allows `extern "msp430-interrupt" fn()`. (active, abi_msp430_interrupt, "1.16.0", Some(38487), None), - // Allows declarative macros 2.0 (`macro`). + /// Allows declarative macros 2.0 (`macro`). (active, decl_macro, "1.17.0", Some(39412), None), - // Allows `extern "x86-interrupt" fn()`. + /// Allows `extern "x86-interrupt" fn()`. (active, abi_x86_interrupt, "1.17.0", Some(40180), None), - // Allows overlapping impls of marker traits. + /// Allows overlapping impls of marker traits. (active, overlapping_marker_traits, "1.18.0", Some(29864), None), - // Allows a test to fail without failing the whole suite. + /// Allows a test to fail without failing the whole suite. (active, allow_fail, "1.19.0", Some(46488), None), - // Allows unsized tuple coercion. + /// Allows unsized tuple coercion. (active, unsized_tuple_coercion, "1.20.0", Some(42877), None), - // Allows defining generators. + /// Allows defining generators. (active, generators, "1.21.0", Some(43122), None), - // Allows `#[doc(cfg(...))]`. + /// Allows `#[doc(cfg(...))]`. (active, doc_cfg, "1.21.0", Some(43781), None), - // Allows `#[doc(masked)]`. + /// Allows `#[doc(masked)]`. (active, doc_masked, "1.21.0", Some(44027), None), - // Allows `#[doc(spotlight)]`. + /// Allows `#[doc(spotlight)]`. (active, doc_spotlight, "1.22.0", Some(45040), None), - // Allows `#[doc(include = "some-file")]`. + /// Allows `#[doc(include = "some-file")]`. (active, external_doc, "1.22.0", Some(44732), None), - // Allows future-proofing enums/structs with the `#[non_exhaustive]` attribute (RFC 2008). + /// Allows future-proofing enums/structs with the `#[non_exhaustive]` attribute (RFC 2008). (active, non_exhaustive, "1.22.0", Some(44109), None), - // Allows using `crate` as visibility modifier, synonymous with `pub(crate)`. + /// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`. (active, crate_visibility_modifier, "1.23.0", Some(53120), None), - // Allows defining `extern type`s. + /// Allows defining `extern type`s. (active, extern_types, "1.23.0", Some(43467), None), - // Allows trait methods with arbitrary self types. + /// Allows trait methods with arbitrary self types. (active, arbitrary_self_types, "1.23.0", Some(44874), None), - // Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). + /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). (active, in_band_lifetimes, "1.23.0", Some(44524), None), - // Allows associated types to be generic, e.g., `type Foo;` (RFC 1598). + /// Allows associated types to be generic, e.g., `type Foo;` (RFC 1598). (active, generic_associated_types, "1.23.0", Some(44265), None), - // Allows defining `trait X = A + B;` alias items. + /// Allows defining `trait X = A + B;` alias items. (active, trait_alias, "1.24.0", Some(41517), None), - // Allows infering `'static` outlives requirements (RFC 2093). + /// Allows infering `'static` outlives requirements (RFC 2093). (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None), - // Allows macro invocations in `extern {}` blocks. + /// Allows macro invocations in `extern {}` blocks. (active, macros_in_extern, "1.27.0", Some(49476), None), - // Allows accessing fields of unions inside `const` functions. + /// Allows accessing fields of unions inside `const` functions. (active, const_fn_union, "1.27.0", Some(51909), None), - // Allows casting raw pointers to `usize` during const eval. + /// Allows casting raw pointers to `usize` during const eval. (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None), - // Allows dereferencing raw pointers during const eval. + /// Allows dereferencing raw pointers during const eval. (active, const_raw_ptr_deref, "1.27.0", Some(51911), None), - // Allows comparing raw pointers during const eval. + /// Allows comparing raw pointers during const eval. (active, const_compare_raw_pointers, "1.27.0", Some(53020), None), - // Allows `#[doc(alias = "...")]`. + /// Allows `#[doc(alias = "...")]`. (active, doc_alias, "1.27.0", Some(50146), None), - // Allows inconsistent bounds in where clauses. + /// Allows inconsistent bounds in where clauses. (active, trivial_bounds, "1.28.0", Some(48214), None), - // Allows `'a: { break 'a; }`. + /// Allows `'a: { break 'a; }`. (active, label_break_value, "1.28.0", Some(48594), None), - // Allows using `#[doc(keyword = "...")]`. + /// Allows using `#[doc(keyword = "...")]`. (active, doc_keyword, "1.28.0", Some(51315), None), - // Allows reinterpretation of the bits of a value of one type as another type during const eval. + /// Allows reinterpretation of the bits of a value of one type as another + /// type during const eval. (active, const_transmute, "1.29.0", Some(53605), None), - // Allows using `try {...}` expressions. + /// Allows using `try {...}` expressions. (active, try_blocks, "1.29.0", Some(31436), None), - // Allows defining an `#[alloc_error_handler]`. + /// Allows defining an `#[alloc_error_handler]`. (active, alloc_error_handler, "1.29.0", Some(51540), None), - // Allows using the `amdgpu-kernel` ABI. + /// Allows using the `amdgpu-kernel` ABI. (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None), - // Allows panicking during const eval (producing compile-time errors). + /// Allows panicking during const eval (producing compile-time errors). (active, const_panic, "1.30.0", Some(51999), None), - // Allows `#[marker]` on certain traits allowing overlapping implementations. + /// Allows `#[marker]` on certain traits allowing overlapping implementations. (active, marker_trait_attr, "1.30.0", Some(29864), None), - // Allows macro invocations on modules expressions and statements and - // procedural macros to expand to non-items. + /// Allows macro invocations on modules expressions and statements and + /// procedural macros to expand to non-items. (active, proc_macro_hygiene, "1.30.0", Some(54727), None), - // Allows unsized rvalues at arguments and parameters. + /// Allows unsized rvalues at arguments and parameters. (active, unsized_locals, "1.30.0", Some(48055), None), - // Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. + /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. (active, custom_test_frameworks, "1.30.0", Some(50297), None), - // Allows non-builtin attributes in inner attribute position. + /// Allows non-builtin attributes in inner attribute position. (active, custom_inner_attributes, "1.30.0", Some(54726), None), - // Allows mixing bind-by-move in patterns and references to those identifiers in guards. + /// Allows mixing bind-by-move in patterns and references to those identifiers in guards. (active, bind_by_move_pattern_guards, "1.30.0", Some(15287), None), - // Allows `impl Trait` in bindings (`let`, `const`, `static`). + /// Allows `impl Trait` in bindings (`let`, `const`, `static`). (active, impl_trait_in_bindings, "1.30.0", Some(63065), None), - // Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. + /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. (active, lint_reasons, "1.31.0", Some(54503), None), - // Allows exhaustive integer pattern matching on `usize` and `isize`. + /// Allows exhaustive integer pattern matching on `usize` and `isize`. (active, precise_pointer_size_matching, "1.32.0", Some(56354), None), - // Allows relaxing the coherence rules such that - // `impl ForeignTrait for ForeignType is permitted. + /// Allows relaxing the coherence rules such that + /// `impl ForeignTrait for ForeignType is permitted. (active, re_rebalance_coherence, "1.32.0", Some(55437), None), - // Allows using `#[ffi_returns_twice]` on foreign functions. + /// Allows using `#[ffi_returns_twice]` on foreign functions. (active, ffi_returns_twice, "1.34.0", Some(58314), None), - // Allows const generic types (e.g. `struct Foo(...);`). + /// Allows const generic types (e.g. `struct Foo(...);`). (active, const_generics, "1.34.0", Some(44580), None), - // Allows using `#[optimize(X)]`. + /// Allows using `#[optimize(X)]`. (active, optimize_attribute, "1.34.0", Some(54882), None), - // Allows using C-variadics. + /// Allows using C-variadics. (active, c_variadic, "1.34.0", Some(44930), None), - // Allows the user of associated type bounds. + /// Allows the user of associated type bounds. (active, associated_type_bounds, "1.34.0", Some(52662), None), - // Attributes on formal function params. + /// Attributes on formal function params. (active, param_attrs, "1.36.0", Some(60406), None), - // Allows calling constructor functions in `const fn`. + /// Allows calling constructor functions in `const fn`. (active, const_constructor, "1.37.0", Some(61456), None), - // Allows `if/while p && let q = r && ...` chains. + /// Allows `if/while p && let q = r && ...` chains. (active, let_chains, "1.37.0", Some(53667), None), - // Allows #[repr(transparent)] on enums (RFC 2645). + /// Allows #[repr(transparent)] on enums (RFC 2645). (active, transparent_enums, "1.37.0", Some(60405), None), - // Allows #[repr(transparent)] on unions (RFC 2645). + /// Allows #[repr(transparent)] on unions (RFC 2645). (active, transparent_unions, "1.37.0", Some(60405), None), - // Allows explicit discriminants on non-unit enum variants. + /// Allows explicit discriminants on non-unit enum variants. (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), - // Allows `impl Trait` with multiple unrelated lifetimes. + /// Allows `impl Trait` with multiple unrelated lifetimes. (active, member_constraints, "1.37.0", Some(61977), None), - // Allows `async || body` closures. + /// Allows `async || body` closures. (active, async_closure, "1.37.0", Some(62290), None), - // Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests + /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests (active, cfg_doctest, "1.37.0", Some(62210), None), - // Allows `[x; N]` where `x` is a constant (RFC 2203). + /// Allows `[x; N]` where `x` is a constant (RFC 2203). (active, const_in_array_repeat_expressions, "1.37.0", Some(49147), None), - // Allows `impl Trait` to be used inside type aliases (RFC 2515). + /// Allows `impl Trait` to be used inside type aliases (RFC 2515). (active, type_alias_impl_trait, "1.38.0", Some(63063), None), - // Allows the use of or-patterns, e.g. `0 | 1`. + /// Allows the use of or-patterns, e.g. `0 | 1`. (active, or_patterns, "1.38.0", Some(54883), None), // ------------------------------------------------------------------------- diff --git a/src/libsyntax/feature_gate/removed.rs b/src/libsyntax/feature_gate/removed.rs index 6ebfeb29f677b..6494c82e1228b 100644 --- a/src/libsyntax/feature_gate/removed.rs +++ b/src/libsyntax/feature_gate/removed.rs @@ -3,14 +3,18 @@ use crate::symbol::{Symbol, sym}; macro_rules! declare_features { - ($((removed, $feature: ident, $ver: expr, $issue: expr, None, $reason: expr),)+) => { + ($( + $(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, None, $reason:expr), + )+) => { /// Represents unstable features which have since been removed (it was once Active) pub const REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ $((sym::$feature, $ver, $issue, $reason)),+ ]; }; - ($((stable_removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => { + ($( + $(#[doc = $doc:tt])* (stable_removed, $feature:ident, $ver:expr, $issue:expr, None), + )+) => { /// Represents stable features which have since been removed (it was once Accepted) pub const STABLE_REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ $((sym::$feature, $ver, $issue, None)),+ @@ -25,17 +29,17 @@ declare_features! ( (removed, import_shadowing, "1.0.0", None, None, None), (removed, managed_boxes, "1.0.0", None, None, None), - // Allows use of unary negate on unsigned integers, e.g., -e for e: u8 + /// Allows use of unary negate on unsigned integers, e.g., -e for e: u8 (removed, negate_unsigned, "1.0.0", Some(29645), None, None), (removed, reflect, "1.0.0", Some(27749), None, None), - // A way to temporarily opt out of opt in copy. This will *never* be accepted. + /// A way to temporarily opt out of opt in copy. This will *never* be accepted. (removed, opt_out_copy, "1.0.0", None, None, None), (removed, quad_precision_float, "1.0.0", None, None, None), (removed, struct_inherit, "1.0.0", None, None, None), (removed, test_removed_feature, "1.0.0", None, None, None), (removed, visible_private_types, "1.0.0", None, None, None), (removed, unsafe_no_drop_flag, "1.0.0", None, None, None), - // Allows using items which are missing stability attributes + /// Allows using items which are missing stability attributes (removed, unmarked_api, "1.0.0", None, None, None), (removed, allocator, "1.0.0", None, None, None), (removed, simd, "1.0.0", Some(27731), None, @@ -57,18 +61,18 @@ declare_features! ( Some("subsumed by `#![feature(proc_macro_hygiene)]`")), (removed, panic_implementation, "1.28.0", Some(44489), None, Some("subsumed by `#[panic_handler]`")), - // Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. + /// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. (removed, custom_derive, "1.32.0", Some(29644), None, Some("subsumed by `#[proc_macro_derive]`")), - // Paths of the form: `extern::foo::bar` + /// Paths of the form: `extern::foo::bar` (removed, extern_in_paths, "1.33.0", Some(55600), None, Some("subsumed by `::foo::bar` paths")), (removed, quote, "1.33.0", Some(29601), None, None), - // Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). + /// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). (removed, dropck_parametricity, "1.38.0", Some(28498), None, None), (removed, await_macro, "1.38.0", Some(50547), None, Some("subsumed by `.await` syntax")), - // Allows defining `existential type`s. + /// Allows defining `existential type`s. (removed, existential_type, "1.38.0", Some(63063), None, Some("removed in favor of `#![feature(type_alias_impl_trait)]`")), From 9bbe8aed4b524c0922e2414b4916e57730f20407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 24 Aug 2019 18:47:43 +0200 Subject: [PATCH 170/618] submodules: update clippy from cd3df6be to 2bcb6155 Changes: ```` Refactor some minor things Use more if-chains Refactor 'lint_or_fun_call' Refactor 'check_unwrap_or_default' Refactor 'check_impl_item' Add missing field to LitKind::Str Run update_lints for Unicode lint Re-add false positive check Add raw string regression test for useless_format lint Re-factor useless_format lint Update Unicode lint tests Add two more tests, allow 2 other lints. Fix `temporary_cstring_as_ptr` false negative Add more testcases for redundant_pattern_matching Fix suggestions for redundant_pattern_matching Add note on how to find the latest beta commit Remove feature gate for async_await Update if_chain doc link Requested test cleanup Requested changes Ignore lines starting with '#' run-rustfix for unseparated-prefix-literals Add autofixable suggestion for unseparated integer literal suffices Further text improvements Add image docs: Explain how to update the changelog ```` --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index cd3df6bee0ee0..2bcb6155948e2 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit cd3df6bee0ee07c7dbb562b29576a0b513a4331b +Subproject commit 2bcb6155948e2f8b86db08152a5f54bd5af625e5 From 6a3d51731408708cbc6a6e4e2683da8df7326007 Mon Sep 17 00:00:00 2001 From: Caio Date: Sat, 24 Aug 2019 13:54:40 -0300 Subject: [PATCH 171/618] Modifies how Arg, Arm, Field, FieldPattern and Variant are visited Part of the necessary work to accomplish #63468. --- src/librustc/hir/map/def_collector.rs | 7 +- src/librustc/lint/context.rs | 35 +++---- src/librustc/lint/mod.rs | 36 ++----- src/librustc_lint/builtin.rs | 2 +- src/librustc_lint/nonstandard_style.rs | 5 +- src/librustc_passes/ast_validation.rs | 3 +- src/librustc_passes/hir_stats.rs | 7 +- src/libsyntax/ext/expand.rs | 10 +- src/libsyntax/mut_visit.rs | 126 +++++++++++++++---------- src/libsyntax/util/node_count.rs | 7 +- src/libsyntax/visit.rs | 54 ++++++----- 11 files changed, 147 insertions(+), 145 deletions(-) diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index d725afa405212..17bcb1d085968 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -154,7 +154,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { }); } - fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) { + fn visit_variant(&mut self, v: &'a Variant) { let def = self.create_def(v.id, DefPathData::TypeNs(v.ident.as_interned_str()), v.span); @@ -162,12 +162,11 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { if let Some(ctor_hir_id) = v.data.ctor_id() { this.create_def(ctor_hir_id, DefPathData::Ctor, v.span); } - visit::walk_variant(this, v, g, item_id) + visit::walk_variant(this, v) }); } - fn visit_variant_data(&mut self, data: &'a VariantData, _: Ident, - _: &'a Generics, _: NodeId, _: Span) { + fn visit_variant_data(&mut self, data: &'a VariantData) { for (index, field) in data.fields().iter().enumerate() { let name = field.ident.map(|ident| ident.name) .unwrap_or_else(|| sym::integer(index)); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 6801fa8d8dbe5..8126db1429247 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1040,13 +1040,13 @@ for LateContextAndPass<'a, 'tcx, T> { fn visit_variant_data(&mut self, s: &'tcx hir::VariantData, - name: ast::Name, - g: &'tcx hir::Generics, - item_id: hir::HirId, + _: ast::Name, + _: &'tcx hir::Generics, + _: hir::HirId, _: Span) { - lint_callback!(self, check_struct_def, s, name, g, item_id); + lint_callback!(self, check_struct_def, s); hir_visit::walk_struct_def(self, s); - lint_callback!(self, check_struct_def_post, s, name, g, item_id); + lint_callback!(self, check_struct_def_post, s); } fn visit_struct_field(&mut self, s: &'tcx hir::StructField) { @@ -1061,9 +1061,9 @@ for LateContextAndPass<'a, 'tcx, T> { g: &'tcx hir::Generics, item_id: hir::HirId) { self.with_lint_attrs(v.id, &v.attrs, |cx| { - lint_callback!(cx, check_variant, v, g); + lint_callback!(cx, check_variant, v); hir_visit::walk_variant(cx, v, g, item_id); - lint_callback!(cx, check_variant_post, v, g); + lint_callback!(cx, check_variant_post, v); }) } @@ -1214,18 +1214,13 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> run_early_pass!(self, check_fn_post, fk, decl, span, id); } - fn visit_variant_data(&mut self, - s: &'a ast::VariantData, - ident: ast::Ident, - g: &'a ast::Generics, - item_id: ast::NodeId, - _: Span) { - run_early_pass!(self, check_struct_def, s, ident, g, item_id); + fn visit_variant_data(&mut self, s: &'a ast::VariantData) { + run_early_pass!(self, check_struct_def, s); if let Some(ctor_hir_id) = s.ctor_id() { self.check_id(ctor_hir_id); } ast_visit::walk_struct_def(self, s); - run_early_pass!(self, check_struct_def_post, s, ident, g, item_id); + run_early_pass!(self, check_struct_def_post, s); } fn visit_struct_field(&mut self, s: &'a ast::StructField) { @@ -1235,11 +1230,11 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> }) } - fn visit_variant(&mut self, v: &'a ast::Variant, g: &'a ast::Generics, item_id: ast::NodeId) { - self.with_lint_attrs(item_id, &v.attrs, |cx| { - run_early_pass!(cx, check_variant, v, g); - ast_visit::walk_variant(cx, v, g, item_id); - run_early_pass!(cx, check_variant_post, v, g); + fn visit_variant(&mut self, v: &'a ast::Variant) { + self.with_lint_attrs(v.id, &v.attrs, |cx| { + run_early_pass!(cx, check_variant, v); + ast_visit::walk_variant(cx, v); + run_early_pass!(cx, check_variant_post, v); }) } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 2b58627cdea56..7e2707b98d50a 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -248,21 +248,11 @@ macro_rules! late_lint_methods { fn check_trait_item_post(a: &$hir hir::TraitItem); fn check_impl_item(a: &$hir hir::ImplItem); fn check_impl_item_post(a: &$hir hir::ImplItem); - fn check_struct_def( - a: &$hir hir::VariantData, - b: ast::Name, - c: &$hir hir::Generics, - d: hir::HirId - ); - fn check_struct_def_post( - a: &$hir hir::VariantData, - b: ast::Name, - c: &$hir hir::Generics, - d: hir::HirId - ); + fn check_struct_def(a: &$hir hir::VariantData); + fn check_struct_def_post(a: &$hir hir::VariantData); fn check_struct_field(a: &$hir hir::StructField); - fn check_variant(a: &$hir hir::Variant, b: &$hir hir::Generics); - fn check_variant_post(a: &$hir hir::Variant, b: &$hir hir::Generics); + fn check_variant(a: &$hir hir::Variant); + fn check_variant_post(a: &$hir hir::Variant); fn check_lifetime(a: &$hir hir::Lifetime); fn check_path(a: &$hir hir::Path, b: hir::HirId); fn check_attribute(a: &$hir ast::Attribute); @@ -395,21 +385,11 @@ macro_rules! early_lint_methods { fn check_trait_item_post(a: &ast::TraitItem); fn check_impl_item(a: &ast::ImplItem); fn check_impl_item_post(a: &ast::ImplItem); - fn check_struct_def( - a: &ast::VariantData, - b: ast::Ident, - c: &ast::Generics, - d: ast::NodeId - ); - fn check_struct_def_post( - a: &ast::VariantData, - b: ast::Ident, - c: &ast::Generics, - d: ast::NodeId - ); + fn check_struct_def(a: &ast::VariantData); + fn check_struct_def_post(a: &ast::VariantData); fn check_struct_field(a: &ast::StructField); - fn check_variant(a: &ast::Variant, b: &ast::Generics); - fn check_variant_post(a: &ast::Variant, b: &ast::Generics); + fn check_variant(a: &ast::Variant); + fn check_variant_post(a: &ast::Variant); fn check_lifetime(a: &ast::Lifetime); fn check_path(a: &ast::Path, b: ast::NodeId); fn check_attribute(a: &ast::Attribute); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ce7681c974a5d..d3c94060e274a 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -482,7 +482,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } } - fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant, _: &hir::Generics) { + fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant) { self.check_missing_docs_attrs(cx, Some(v.id), &v.attrs, diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index acd17f7663234..bb6119d0ff2aa 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -146,7 +146,7 @@ impl EarlyLintPass for NonCamelCaseTypes { } } - fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant, _: &ast::Generics) { + fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant) { self.check_case(cx, "variant", &v.ident); } @@ -350,9 +350,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { &mut self, cx: &LateContext<'_, '_>, s: &hir::VariantData, - _: ast::Name, - _: &hir::Generics, - _: hir::HirId, ) { for sf in s.fields() { self.check_snake_case(cx, "structure field", &sf.ident); diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index bd46ca4779a43..5b78727fdd5ad 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -813,8 +813,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_poly_trait_ref(self, t, m); } - fn visit_variant_data(&mut self, s: &'a VariantData, _: Ident, - _: &'a Generics, _: NodeId, _: Span) { + fn visit_variant_data(&mut self, s: &'a VariantData) { self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s)) } diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index 8fba3256ec429..7e03df5b75bdc 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -334,12 +334,9 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { ast_visit::walk_struct_field(self, s) } - fn visit_variant(&mut self, - v: &'v ast::Variant, - g: &'v ast::Generics, - item_id: NodeId) { + fn visit_variant(&mut self, v: &'v ast::Variant) { self.record("Variant", Id::None, v); - ast_visit::walk_variant(self, v, g, item_id) + ast_visit::walk_variant(self, v) } fn visit_lifetime(&mut self, lifetime: &'v ast::Lifetime) { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 72f2c1375e7a2..92b48ed62cdce 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1210,9 +1210,13 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } - fn visit_generic_params(&mut self, params: &mut Vec) { - self.cfg.configure_generic_params(params); - noop_visit_generic_params(params, self); + fn flat_map_generic_param( + &mut self, + param: ast::GenericParam + ) -> SmallVec<[ast::GenericParam; 1]> + { + let param = configure!(self, param); + noop_flat_map_generic_param(param, self) } fn visit_attribute(&mut self, at: &mut ast::Attribute) { diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 9785f8e2de098..414d234e43419 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -98,8 +98,8 @@ pub trait MutVisitor: Sized { noop_visit_fn_header(header, self); } - fn visit_struct_field(&mut self, sf: &mut StructField) { - noop_visit_struct_field(sf, self); + fn flat_map_struct_field(&mut self, sf: StructField) -> SmallVec<[StructField; 1]> { + noop_flat_map_struct_field(sf, self) } fn visit_item_kind(&mut self, i: &mut ItemKind) { @@ -130,8 +130,8 @@ pub trait MutVisitor: Sized { noop_flat_map_stmt(s, self) } - fn visit_arm(&mut self, a: &mut Arm) { - noop_visit_arm(a, self); + fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> { + noop_flat_map_arm(arm, self) } fn visit_pat(&mut self, p: &mut P) { @@ -174,8 +174,8 @@ pub trait MutVisitor: Sized { noop_visit_foreign_mod(nm, self); } - fn visit_variant(&mut self, v: &mut Variant) { - noop_visit_variant(v, self); + fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> { + noop_flat_map_variant(v, self) } fn visit_ident(&mut self, i: &mut Ident) { @@ -225,8 +225,8 @@ pub trait MutVisitor: Sized { noop_visit_attribute(at, self); } - fn visit_arg(&mut self, a: &mut Arg) { - noop_visit_arg(a, self); + fn flat_map_arg(&mut self, arg: Arg) -> SmallVec<[Arg; 1]> { + noop_flat_map_arg(arg, self) } fn visit_generics(&mut self, generics: &mut Generics) { @@ -245,12 +245,8 @@ pub trait MutVisitor: Sized { noop_visit_variant_data(vdata, self); } - fn visit_generic_param(&mut self, param: &mut GenericParam) { - noop_visit_generic_param(param, self); - } - - fn visit_generic_params(&mut self, params: &mut Vec) { - noop_visit_generic_params(params, self); + fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> { + noop_flat_map_generic_param(param, self) } fn visit_tt(&mut self, tt: &mut TokenTree) { @@ -277,8 +273,8 @@ pub trait MutVisitor: Sized { noop_visit_mt(mt, self); } - fn visit_field(&mut self, field: &mut Field) { - noop_visit_field(field, self); + fn flat_map_field(&mut self, f: Field) -> SmallVec<[Field; 1]> { + noop_flat_map_field(f, self) } fn visit_where_clause(&mut self, where_clause: &mut WhereClause) { @@ -300,6 +296,10 @@ pub trait MutVisitor: Sized { fn visit_span(&mut self, _sp: &mut Span) { // Do nothing. } + + fn flat_map_field_pattern(&mut self, fp: FieldPat) -> SmallVec<[FieldPat; 1]> { + noop_flat_map_field_pattern(fp, self) + } } /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful @@ -362,6 +362,26 @@ pub fn visit_method_sig(MethodSig { header, decl }: &mut MethodSi vis.visit_fn_decl(decl); } +pub fn noop_flat_map_field_pattern( + mut fp: FieldPat, + vis: &mut T, +) -> SmallVec<[FieldPat; 1]> { + let FieldPat { + attrs, + id, + ident, + is_shorthand: _, + pat, + span, + } = &mut fp; + vis.visit_id(id); + vis.visit_ident(ident); + vis.visit_pat(pat); + vis.visit_span(span); + visit_thin_attrs(attrs, vis); + smallvec![fp] +} + pub fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) { let UseTree { prefix, kind, span } = use_tree; vis.visit_path(prefix); @@ -382,16 +402,18 @@ pub fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) { vis.visit_span(span); } -pub fn noop_visit_arm( - Arm { attrs, pats, guard, body, span, id }: &mut Arm, +pub fn noop_flat_map_arm( + mut arm: Arm, vis: &mut T, -) { +) -> SmallVec<[Arm; 1]> { + let Arm { attrs, pats, guard, body, span, id } = &mut arm; visit_attrs(attrs, vis); vis.visit_id(id); visit_vec(pats, |pat| vis.visit_pat(pat)); visit_opt(guard, |guard| vis.visit_expr(guard)); vis.visit_expr(body); vis.visit_span(span); + smallvec![arm] } pub fn noop_visit_ty_constraint( @@ -425,7 +447,7 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { } TyKind::BareFn(bft) => { let BareFnTy { unsafety: _, abi: _, generic_params, decl } = bft.deref_mut(); - vis.visit_generic_params(generic_params); + generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_fn_decl(decl); } TyKind::Tup(tys) => visit_vec(tys, |ty| vis.visit_ty(ty)), @@ -455,14 +477,17 @@ pub fn noop_visit_foreign_mod(foreign_mod: &mut ForeignMod, vis: items.flat_map_in_place(|item| vis.flat_map_foreign_item(item)); } -pub fn noop_visit_variant(variant: &mut Variant, vis: &mut T) { - let Variant { ident, attrs, id, data, disr_expr, span } = variant; +pub fn noop_flat_map_variant(mut variant: Variant, vis: &mut T) + -> SmallVec<[Variant; 1]> +{ + let Variant { ident, attrs, id, data, disr_expr, span } = &mut variant; vis.visit_ident(ident); visit_attrs(attrs, vis); vis.visit_id(id); vis.visit_variant_data(data); visit_opt(disr_expr, |disr_expr| vis.visit_anon_const(disr_expr)); vis.visit_span(span); + smallvec![variant] } pub fn noop_visit_ident(Ident { name: _, span }: &mut Ident, vis: &mut T) { @@ -562,12 +587,14 @@ pub fn noop_visit_meta_item(mi: &mut MetaItem, vis: &mut T) { vis.visit_span(span); } -pub fn noop_visit_arg(Arg { attrs, id, pat, span, ty }: &mut Arg, vis: &mut T) { +pub fn noop_flat_map_arg(mut arg: Arg, vis: &mut T) -> SmallVec<[Arg; 1]> { + let Arg { attrs, id, pat, span, ty } = &mut arg; vis.visit_id(id); visit_thin_attrs(attrs, vis); vis.visit_pat(pat); vis.visit_span(span); vis.visit_ty(ty); + smallvec![arg] } pub fn noop_visit_tt(tt: &mut TokenTree, vis: &mut T) { @@ -693,7 +720,7 @@ pub fn noop_visit_asyncness(asyncness: &mut IsAsync, vis: &mut T) pub fn noop_visit_fn_decl(decl: &mut P, vis: &mut T) { let FnDecl { inputs, output, c_variadic: _ } = decl.deref_mut(); - visit_vec(inputs, |input| vis.visit_arg(input)); + inputs.flat_map_in_place(|arg| vis.flat_map_arg(arg)); match output { FunctionRetTy::Default(span) => vis.visit_span(span), FunctionRetTy::Ty(ty) => vis.visit_ty(ty), @@ -707,8 +734,12 @@ pub fn noop_visit_param_bound(pb: &mut GenericBound, vis: &mut T) } } -pub fn noop_visit_generic_param(param: &mut GenericParam, vis: &mut T) { - let GenericParam { id, ident, attrs, bounds, kind } = param; +pub fn noop_flat_map_generic_param( + mut param: GenericParam, + vis: &mut T +) -> SmallVec<[GenericParam; 1]> +{ + let GenericParam { id, ident, attrs, bounds, kind } = &mut param; vis.visit_id(id); vis.visit_ident(ident); visit_thin_attrs(attrs, vis); @@ -722,10 +753,7 @@ pub fn noop_visit_generic_param(param: &mut GenericParam, vis: &m vis.visit_ty(ty); } } -} - -pub fn noop_visit_generic_params(params: &mut Vec, vis: &mut T){ - visit_vec(params, |param| vis.visit_generic_param(param)); + smallvec![param] } pub fn noop_visit_label(Label { ident }: &mut Label, vis: &mut T) { @@ -739,7 +767,7 @@ fn noop_visit_lifetime(Lifetime { id, ident }: &mut Lifetime, vis pub fn noop_visit_generics(generics: &mut Generics, vis: &mut T) { let Generics { params, where_clause, span } = generics; - vis.visit_generic_params(params); + params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_where_clause(where_clause); vis.visit_span(span); } @@ -755,7 +783,7 @@ pub fn noop_visit_where_predicate(pred: &mut WherePredicate, vis: WherePredicate::BoundPredicate(bp) => { let WhereBoundPredicate { span, bound_generic_params, bounded_ty, bounds } = bp; vis.visit_span(span); - vis.visit_generic_params(bound_generic_params); + bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_ty(bounded_ty); visit_vec(bounds, |bound| vis.visit_param_bound(bound)); } @@ -777,9 +805,11 @@ pub fn noop_visit_where_predicate(pred: &mut WherePredicate, vis: pub fn noop_visit_variant_data(vdata: &mut VariantData, vis: &mut T) { match vdata { - VariantData::Struct(fields, ..) => visit_vec(fields, |field| vis.visit_struct_field(field)), + VariantData::Struct(fields, ..) => { + fields.flat_map_in_place(|field| vis.flat_map_struct_field(field)); + }, VariantData::Tuple(fields, id) => { - visit_vec(fields, |field| vis.visit_struct_field(field)); + fields.flat_map_in_place(|field| vis.flat_map_struct_field(field)); vis.visit_id(id); }, VariantData::Unit(id) => vis.visit_id(id), @@ -793,28 +823,32 @@ pub fn noop_visit_trait_ref(TraitRef { path, ref_id }: &mut Trait pub fn noop_visit_poly_trait_ref(p: &mut PolyTraitRef, vis: &mut T) { let PolyTraitRef { bound_generic_params, trait_ref, span } = p; - vis.visit_generic_params(bound_generic_params); + bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_trait_ref(trait_ref); vis.visit_span(span); } -pub fn noop_visit_struct_field(f: &mut StructField, visitor: &mut T) { - let StructField { span, ident, vis, id, ty, attrs } = f; +pub fn noop_flat_map_struct_field(mut sf: StructField, visitor: &mut T) + -> SmallVec<[StructField; 1]> +{ + let StructField { span, ident, vis, id, ty, attrs } = &mut sf; visitor.visit_span(span); visit_opt(ident, |ident| visitor.visit_ident(ident)); visitor.visit_vis(vis); visitor.visit_id(id); visitor.visit_ty(ty); visit_attrs(attrs, visitor); + smallvec![sf] } -pub fn noop_visit_field(f: &mut Field, vis: &mut T) { - let Field { ident, expr, span, is_shorthand: _, attrs, id } = f; +pub fn noop_flat_map_field(mut f: Field, vis: &mut T) -> SmallVec<[Field; 1]> { + let Field { ident, expr, span, is_shorthand: _, attrs, id } = &mut f; vis.visit_ident(ident); vis.visit_expr(expr); vis.visit_id(id); vis.visit_span(span); visit_thin_attrs(attrs, vis); + smallvec![f] } pub fn noop_visit_mt(MutTy { ty, mutbl: _ }: &mut MutTy, vis: &mut T) { @@ -858,7 +892,7 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { vis.visit_generics(generics); } ItemKind::Enum(EnumDef { variants }, generics) => { - visit_vec(variants, |variant| vis.visit_variant(variant)); + variants.flat_map_in_place(|variant| vis.flat_map_variant(variant)); vis.visit_generics(generics); } ItemKind::Struct(variant_data, generics) | @@ -1042,13 +1076,7 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { } PatKind::Struct(path, fields, _etc) => { vis.visit_path(path); - for FieldPat { ident, pat, is_shorthand: _, attrs, id, span } in fields { - vis.visit_ident(ident); - vis.visit_id(id); - vis.visit_pat(pat); - visit_thin_attrs(attrs, vis); - vis.visit_span(span); - }; + fields.flat_map_in_place(|field| vis.flat_map_field_pattern(field)); } PatKind::Box(inner) => vis.visit_pat(inner), PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner), @@ -1130,7 +1158,7 @@ pub fn noop_visit_expr(Expr { node, id, span, attrs }: &mut Expr, } ExprKind::Match(expr, arms) => { vis.visit_expr(expr); - visit_vec(arms, |arm| vis.visit_arm(arm)); + arms.flat_map_in_place(|arm| vis.flat_map_arm(arm)); } ExprKind::Closure(_capture_by, asyncness, _movability, decl, body, span) => { vis.visit_asyncness(asyncness); @@ -1193,7 +1221,7 @@ pub fn noop_visit_expr(Expr { node, id, span, attrs }: &mut Expr, ExprKind::Mac(mac) => vis.visit_mac(mac), ExprKind::Struct(path, fields, expr) => { vis.visit_path(path); - visit_vec(fields, |field| vis.visit_field(field)); + fields.flat_map_in_place(|field| vis.flat_map_field(field)); visit_opt(expr, |expr| vis.visit_expr(expr)); }, ExprKind::Paren(expr) => { diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs index f17eb3b39432e..a64fec7096132 100644 --- a/src/libsyntax/util/node_count.rs +++ b/src/libsyntax/util/node_count.rs @@ -93,8 +93,7 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_poly_trait_ref(self, t, m) } - fn visit_variant_data(&mut self, s: &VariantData, _: Ident, - _: &Generics, _: NodeId, _: Span) { + fn visit_variant_data(&mut self, s: &VariantData) { self.count += 1; walk_struct_def(self, s) } @@ -107,9 +106,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_enum_def(self, enum_definition, generics, item_id) } - fn visit_variant(&mut self, v: &Variant, g: &Generics, item_id: NodeId) { + fn visit_variant(&mut self, v: &Variant) { self.count += 1; - walk_variant(self, v, g, item_id) + walk_variant(self, v) } fn visit_lifetime(&mut self, lifetime: &Lifetime) { self.count += 1; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 91b92d84a811f..86f6d36c3c6ba 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -92,8 +92,7 @@ pub trait Visitor<'ast>: Sized { fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { walk_poly_trait_ref(self, t, m) } - fn visit_variant_data(&mut self, s: &'ast VariantData, _: Ident, - _: &'ast Generics, _: NodeId, _: Span) { + fn visit_variant_data(&mut self, s: &'ast VariantData) { walk_struct_def(self, s) } fn visit_struct_field(&mut self, s: &'ast StructField) { walk_struct_field(self, s) } @@ -101,8 +100,8 @@ pub trait Visitor<'ast>: Sized { generics: &'ast Generics, item_id: NodeId, _: Span) { walk_enum_def(self, enum_definition, generics, item_id) } - fn visit_variant(&mut self, v: &'ast Variant, g: &'ast Generics, item_id: NodeId) { - walk_variant(self, v, g, item_id) + fn visit_variant(&mut self, v: &'ast Variant) { + walk_variant(self, v) } fn visit_label(&mut self, label: &'ast Label) { walk_label(self, label) @@ -163,6 +162,12 @@ pub trait Visitor<'ast>: Sized { fn visit_fn_header(&mut self, _header: &'ast FnHeader) { // Nothing to do } + fn visit_field(&mut self, f: &'ast Field) { + walk_field(self, f) + } + fn visit_field_pattern(&mut self, fp: &'ast FieldPat) { + walk_field_pattern(self, fp) + } } #[macro_export] @@ -280,8 +285,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { ItemKind::Struct(ref struct_definition, ref generics) | ItemKind::Union(ref struct_definition, ref generics) => { visitor.visit_generics(generics); - visitor.visit_variant_data(struct_definition, item.ident, - generics, item.id, item.span); + visitor.visit_variant_data(struct_definition); } ItemKind::Trait(.., ref generics, ref bounds, ref methods) => { visitor.visit_generics(generics); @@ -300,24 +304,32 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { pub fn walk_enum_def<'a, V: Visitor<'a>>(visitor: &mut V, enum_definition: &'a EnumDef, - generics: &'a Generics, - item_id: NodeId) { - walk_list!(visitor, visit_variant, &enum_definition.variants, generics, item_id); + _: &'a Generics, + _: NodeId) { + walk_list!(visitor, visit_variant, &enum_definition.variants); } -pub fn walk_variant<'a, V>(visitor: &mut V, - variant: &'a Variant, - generics: &'a Generics, - item_id: NodeId) +pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) where V: Visitor<'a>, { visitor.visit_ident(variant.ident); - visitor.visit_variant_data(&variant.data, variant.ident, - generics, item_id, variant.span); + visitor.visit_variant_data(&variant.data); walk_list!(visitor, visit_anon_const, &variant.disr_expr); walk_list!(visitor, visit_attribute, &variant.attrs); } +pub fn walk_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a Field) { + visitor.visit_expr(&f.expr); + visitor.visit_ident(f.ident); + walk_list!(visitor, visit_attribute, f.attrs.iter()); +} + +pub fn walk_field_pattern<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a FieldPat) { + visitor.visit_ident(fp.ident); + visitor.visit_pat(&fp.pat); + walk_list!(visitor, visit_attribute, fp.attrs.iter()); +} + pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { match typ.node { TyKind::Slice(ref ty) | TyKind::Paren(ref ty) => { @@ -441,11 +453,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { } PatKind::Struct(ref path, ref fields, _) => { visitor.visit_path(path, pattern.id); - for field in fields { - walk_list!(visitor, visit_attribute, field.attrs.iter()); - visitor.visit_ident(field.ident); - visitor.visit_pat(&field.pat) - } + walk_list!(visitor, visit_field_pattern, fields); } PatKind::Box(ref subpattern) | PatKind::Ref(ref subpattern, _) | @@ -686,11 +694,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { } ExprKind::Struct(ref path, ref fields, ref optional_base) => { visitor.visit_path(path, expression.id); - for field in fields { - walk_list!(visitor, visit_attribute, field.attrs.iter()); - visitor.visit_ident(field.ident); - visitor.visit_expr(&field.expr) - } + walk_list!(visitor, visit_field, fields); walk_list!(visitor, visit_expr, optional_base); } ExprKind::Tup(ref subexpressions) => { From 14986081355db0a2ae67df6a43dd9e6e360d718c Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 20 Jul 2019 16:34:41 -0400 Subject: [PATCH 172/618] Improve Rustdoc's handling of procedural macros Fixes #58700 Fixes #58696 Fixes #49553 Fixes #52210 This commit removes the special rustdoc handling for proc macros, as we can now retrieve their span and attributes just like any other item. A new command-line option is added to rustdoc: `--crate-type`. This takes the same options as rustc's `--crate-type` option. However, all values other than `proc-macro` are treated the same. This allows Rustdoc to enable 'proc macro mode' when handling a proc macro crate. In compiletest, a new 'rustdoc-flags' option is added. This allows us to pass in the '--proc-macro-crate' flag in the absence of Cargo. I've opened [an additional PR to Cargo](https://github.com/rust-lang/cargo/pull/7159) to support passing in this flag. These two PRS can be merged in any order - the Cargo changes will not take effect until the 'cargo' submodule is updated in this repository. --- src/librustc/session/config.rs | 18 +++++---- src/librustc_interface/passes.rs | 37 ++++++++----------- src/librustdoc/clean/inline.rs | 18 +++++---- src/librustdoc/config.rs | 14 +++++++ src/librustdoc/core.rs | 8 +++- src/librustdoc/lib.rs | 3 +- src/librustdoc/test.rs | 8 +++- src/test/rustdoc-ui/failed-doctest-output.rs | 1 + .../rustdoc-ui/failed-doctest-output.stdout | 14 +++---- .../inline_cross/auxiliary/proc_macro.rs | 7 ++++ src/test/rustdoc/inline_cross/proc_macro.rs | 19 +++++----- src/test/rustdoc/proc-macro.rs | 3 +- src/test/rustdoc/rustc-macro-crate.rs | 1 + 13 files changed, 95 insertions(+), 56 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 8e3b910e0da3a..9ecdff25d2649 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1719,13 +1719,7 @@ pub fn rustc_short_optgroups() -> Vec { static, framework, or dylib (the default).", "[KIND=]NAME", ), - opt::multi_s( - "", - "crate-type", - "Comma separated list of types of crates - for the compiler to emit", - "[bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]", - ), + make_crate_type_option(), opt::opt_s( "", "crate-name", @@ -2506,6 +2500,16 @@ pub fn build_session_options_and_crate_config( ) } +pub fn make_crate_type_option() -> RustcOptGroup { + opt::multi_s( + "", + "crate-type", + "Comma separated list of types of crates + for the compiler to emit", + "[bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]", + ) +} + pub fn parse_crate_types_from_list(list_list: Vec) -> Result, String> { let mut crate_types: Vec = Vec::new(); for unparsed_crate_type in &list_list { diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 8b0b5a5b7a2bd..856690903c659 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -473,27 +473,22 @@ fn configure_and_expand_inner<'a>( ast_validation::check_crate(sess, &krate) }); - // If we're in rustdoc we're always compiling as an rlib, but that'll trip a - // bunch of checks in the `modify` function below. For now just skip this - // step entirely if we're rustdoc as it's not too useful anyway. - if !sess.opts.actually_rustdoc { - krate = time(sess, "maybe creating a macro crate", || { - let crate_types = sess.crate_types.borrow(); - let num_crate_types = crate_types.len(); - let is_proc_macro_crate = crate_types.contains(&config::CrateType::ProcMacro); - let is_test_crate = sess.opts.test; - syntax_ext::proc_macro_harness::inject( - &sess.parse_sess, - &mut resolver, - krate, - is_proc_macro_crate, - has_proc_macro_decls, - is_test_crate, - num_crate_types, - sess.diagnostic(), - ) - }); - } + krate = time(sess, "maybe creating a macro crate", || { + let crate_types = sess.crate_types.borrow(); + let num_crate_types = crate_types.len(); + let is_proc_macro_crate = crate_types.contains(&config::CrateType::ProcMacro); + let is_test_crate = sess.opts.test; + syntax_ext::proc_macro_harness::inject( + &sess.parse_sess, + &mut resolver, + krate, + is_proc_macro_crate, + has_proc_macro_decls, + is_test_crate, + num_crate_types, + sess.diagnostic(), + ) + }); // Done with macro expansion! diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 6f93c95edef08..9d93e5f93c13e 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -20,6 +20,7 @@ use crate::clean::{ self, GetDefId, ToSource, + TypeKind }; use super::Clean; @@ -107,15 +108,16 @@ pub fn try_inline( record_extern_fqn(cx, did, clean::TypeKind::Const); clean::ConstantItem(build_const(cx, did)) } - // FIXME: proc-macros don't propagate attributes or spans across crates, so they look empty - Res::Def(DefKind::Macro(MacroKind::Bang), did) => { + Res::Def(DefKind::Macro(kind), did) => { let mac = build_macro(cx, did, name); - if let clean::MacroItem(..) = mac { - record_extern_fqn(cx, did, clean::TypeKind::Macro); - mac - } else { - return None; - } + + let type_kind = match kind { + MacroKind::Bang => TypeKind::Macro, + MacroKind::Attr => TypeKind::Attr, + MacroKind::Derive => TypeKind::Derive + }; + record_extern_fqn(cx, did, type_kind); + mac } _ => return None, }; diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 98ab957ecbb38..cefae2e105eda 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -6,6 +6,7 @@ use errors; use getopts; use rustc::lint::Level; use rustc::session; +use rustc::session::config::{CrateType, parse_crate_types_from_list}; use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs}; use rustc::session::config::{nightly_options, build_codegen_options, build_debugging_options, get_cmd_lint_options, ExternEntry}; @@ -32,6 +33,8 @@ pub struct Options { pub input: PathBuf, /// The name of the crate being documented. pub crate_name: Option, + /// Whether or not this is a proc-macro crate + pub proc_macro_crate: bool, /// How to format errors and warnings. pub error_format: ErrorOutputType, /// Library search paths to hand to the compiler. @@ -111,6 +114,7 @@ impl fmt::Debug for Options { f.debug_struct("Options") .field("input", &self.input) .field("crate_name", &self.crate_name) + .field("proc_macro_crate", &self.proc_macro_crate) .field("error_format", &self.error_format) .field("libs", &self.libs) .field("externs", &FmtExterns(&self.externs)) @@ -431,7 +435,16 @@ impl Options { }; let manual_passes = matches.opt_strs("passes"); + let crate_types = match parse_crate_types_from_list(matches.opt_strs("crate-type")) { + Ok(types) => types, + Err(e) =>{ + diag.struct_err(&format!("unknown crate type: {}", e)).emit(); + return Err(1); + } + }; + let crate_name = matches.opt_str("crate-name"); + let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro); let playground_url = matches.opt_str("playground-url"); let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from); let display_warnings = matches.opt_present("display-warnings"); @@ -454,6 +467,7 @@ impl Options { Ok(Options { input, crate_name, + proc_macro_crate, error_format, libs, externs, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 87381f224d0bb..003276a5e4868 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -228,6 +228,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let RustdocOptions { input, crate_name, + proc_macro_crate, error_format, libs, externs, @@ -293,11 +294,16 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt }).collect(); let host_triple = TargetTriple::from_triple(config::host_triple()); + let crate_types = if proc_macro_crate { + vec![config::CrateType::ProcMacro] + } else { + vec![config::CrateType::Rlib] + }; // plays with error output here! let sessopts = config::Options { maybe_sysroot, search_paths: libs, - crate_types: vec![config::CrateType::Rlib], + crate_types, lint_opts: if !display_warnings { lint_opts } else { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index e30b35937db9f..bb83ff64b2f18 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -46,7 +46,7 @@ use std::panic; use std::process; use rustc::session::{early_warn, early_error}; -use rustc::session::config::{ErrorOutputType, RustcOptGroup}; +use rustc::session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_option}; #[macro_use] mod externalfiles; @@ -132,6 +132,7 @@ fn opts() -> Vec { stable("crate-name", |o| { o.optopt("", "crate-name", "specify the name of this crate", "NAME") }), + make_crate_type_option(), stable("L", |o| { o.optmulti("L", "library-path", "directory to add to crate search path", "DIR") diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 83a8d3fc10999..87bc6f09e74f5 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -43,10 +43,16 @@ pub struct TestOptions { pub fn run(options: Options) -> i32 { let input = config::Input::File(options.input.clone()); + let crate_types = if options.proc_macro_crate { + vec![config::CrateType::ProcMacro] + } else { + vec![config::CrateType::Dylib] + }; + let sessopts = config::Options { maybe_sysroot: options.maybe_sysroot.clone(), search_paths: options.libs.clone(), - crate_types: vec![config::CrateType::Dylib], + crate_types, cg: options.codegen_options.clone(), externs: options.externs.clone(), unstable_features: UnstableFeatures::from_environment(), diff --git a/src/test/rustdoc-ui/failed-doctest-output.rs b/src/test/rustdoc-ui/failed-doctest-output.rs index d2cdeb8f8f50e..fcbd7cabc6900 100644 --- a/src/test/rustdoc-ui/failed-doctest-output.rs +++ b/src/test/rustdoc-ui/failed-doctest-output.rs @@ -3,6 +3,7 @@ // adapted to use that, and that normalize line can go away // compile-flags:--test +// rustc-env:RUST_BACKTRACE=0 // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" // failure-status: 101 diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout index e362ecf349e45..ef1b419f52895 100644 --- a/src/test/rustdoc-ui/failed-doctest-output.stdout +++ b/src/test/rustdoc-ui/failed-doctest-output.stdout @@ -1,13 +1,13 @@ running 2 tests -test $DIR/failed-doctest-output.rs - OtherStruct (line 20) ... FAILED -test $DIR/failed-doctest-output.rs - SomeStruct (line 10) ... FAILED +test $DIR/failed-doctest-output.rs - OtherStruct (line 21) ... FAILED +test $DIR/failed-doctest-output.rs - SomeStruct (line 11) ... FAILED failures: ----- $DIR/failed-doctest-output.rs - OtherStruct (line 20) stdout ---- +---- $DIR/failed-doctest-output.rs - OtherStruct (line 21) stdout ---- error[E0425]: cannot find value `no` in this scope - --> $DIR/failed-doctest-output.rs:21:1 + --> $DIR/failed-doctest-output.rs:22:1 | 3 | no | ^^ not found in this scope @@ -16,7 +16,7 @@ error: aborting due to previous error For more information about this error, try `rustc --explain E0425`. Couldn't compile the test. ----- $DIR/failed-doctest-output.rs - SomeStruct (line 10) stdout ---- +---- $DIR/failed-doctest-output.rs - SomeStruct (line 11) stdout ---- Test executable failed (exit code 101). stdout: @@ -32,8 +32,8 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. failures: - $DIR/failed-doctest-output.rs - OtherStruct (line 20) - $DIR/failed-doctest-output.rs - SomeStruct (line 10) + $DIR/failed-doctest-output.rs - OtherStruct (line 21) + $DIR/failed-doctest-output.rs - SomeStruct (line 11) test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out diff --git a/src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs b/src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs index c99ef74433358..37465ccf1c27e 100644 --- a/src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs +++ b/src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs @@ -1,5 +1,6 @@ // force-host // no-prefer-dynamic +// compile-flags: --crate-type proc-macro #![crate_type="proc-macro"] #![crate_name="some_macros"] @@ -25,3 +26,9 @@ pub fn some_proc_attr(_attr: TokenStream, item: TokenStream) -> TokenStream { pub fn some_derive(_item: TokenStream) -> TokenStream { TokenStream::new() } + +/// Doc comment from the original crate +#[proc_macro] +pub fn reexported_macro(_input: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/src/test/rustdoc/inline_cross/proc_macro.rs b/src/test/rustdoc/inline_cross/proc_macro.rs index e1cdcf4940244..6880e303df90b 100644 --- a/src/test/rustdoc/inline_cross/proc_macro.rs +++ b/src/test/rustdoc/inline_cross/proc_macro.rs @@ -1,16 +1,17 @@ // aux-build:proc_macro.rs // build-aux-docs -// FIXME: if/when proc-macros start exporting their doc attributes across crates, we can turn on -// cross-crate inlining for them - extern crate some_macros; // @has proc_macro/index.html -// @has - '//a/@href' '../some_macros/macro.some_proc_macro.html' -// @has - '//a/@href' '../some_macros/attr.some_proc_attr.html' -// @has - '//a/@href' '../some_macros/derive.SomeDerive.html' -// @!has proc_macro/macro.some_proc_macro.html -// @!has proc_macro/attr.some_proc_attr.html -// @!has proc_macro/derive.SomeDerive.html +// @has - '//a/@href' 'macro.some_proc_macro.html' +// @has - '//a/@href' 'attr.some_proc_attr.html' +// @has - '//a/@href' 'derive.SomeDerive.html' +// @has proc_macro/macro.some_proc_macro.html +// @has proc_macro/attr.some_proc_attr.html +// @has proc_macro/derive.SomeDerive.html pub use some_macros::{some_proc_macro, some_proc_attr, SomeDerive}; + +// @has proc_macro/macro.reexported_macro.html +// @has - 'Doc comment from the original crate' +pub use some_macros::reexported_macro; diff --git a/src/test/rustdoc/proc-macro.rs b/src/test/rustdoc/proc-macro.rs index 4bd0b092b55a7..82196e413e94b 100644 --- a/src/test/rustdoc/proc-macro.rs +++ b/src/test/rustdoc/proc-macro.rs @@ -1,5 +1,6 @@ // force-host // no-prefer-dynamic +// compile-flags: --crate-type proc-macro --document-private-items #![crate_type="proc-macro"] #![crate_name="some_macros"] @@ -58,7 +59,7 @@ pub fn some_derive(_item: TokenStream) -> TokenStream { } // @has some_macros/foo/index.html -pub mod foo { +mod foo { // @has - '//code' 'pub use some_proc_macro;' // @has - '//a/@href' '../../some_macros/macro.some_proc_macro.html' pub use some_proc_macro; diff --git a/src/test/rustdoc/rustc-macro-crate.rs b/src/test/rustdoc/rustc-macro-crate.rs index 2f6308b20c2ee..dd5edc984dafa 100644 --- a/src/test/rustdoc/rustc-macro-crate.rs +++ b/src/test/rustdoc/rustc-macro-crate.rs @@ -1,5 +1,6 @@ // force-host // no-prefer-dynamic +// compile-flags: --crate-type proc-macro #![crate_type = "proc-macro"] From 11d40910cdc501b22e503cfe1054a7f21478785e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 23 Aug 2019 15:03:21 +0200 Subject: [PATCH 173/618] typeck: move `check_pat_walk` and children to `pat.rs`. --- src/librustc_typeck/check/_match.rs | 965 +-------------------------- src/librustc_typeck/check/mod.rs | 1 + src/librustc_typeck/check/pat.rs | 968 ++++++++++++++++++++++++++++ 3 files changed, 971 insertions(+), 963 deletions(-) create mode 100644 src/librustc_typeck/check/pat.rs diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index fc25eb44cbd88..8cb365d91fa79 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -1,631 +1,12 @@ use crate::check::{FnCtxt, Expectation, Diverges, Needs}; use crate::check::coercion::CoerceMany; -use crate::util::nodemap::FxHashMap; -use errors::{Applicability, DiagnosticBuilder}; -use rustc::hir::{self, PatKind, Pat, ExprKind}; -use rustc::hir::def::{Res, DefKind, CtorKind}; -use rustc::hir::pat_util::EnumerateAndAdjustIterator; -use rustc::hir::ptr::P; -use rustc::infer; +use rustc::hir::{self, ExprKind}; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::traits::{ObligationCause, ObligationCauseCode}; -use rustc::ty::{self, Ty, TypeFoldable}; -use rustc::ty::subst::Kind; -use syntax::ast; -use syntax::util::lev_distance::find_best_match_for_name; +use rustc::ty::{self, Ty}; use syntax_pos::Span; -use syntax_pos::hygiene::DesugaringKind; - -use std::collections::hash_map::Entry::{Occupied, Vacant}; -use std::cmp; - -use super::report_unexpected_variant_res; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - /// `discrim_span` argument having a `Span` indicates that this pattern is part of a match - /// expression arm guard, and it points to the match discriminant to add context in type errors. - /// In the following example, `discrim_span` corresponds to the `a + b` expression: - /// - /// ```text - /// error[E0308]: mismatched types - /// --> src/main.rs:5:9 - /// | - /// 4 | let temp: usize = match a + b { - /// | ----- this expression has type `usize` - /// 5 | Ok(num) => num, - /// | ^^^^^^^ expected usize, found enum `std::result::Result` - /// | - /// = note: expected type `usize` - /// found type `std::result::Result<_, _>` - /// ``` - pub fn check_pat_walk( - &self, - pat: &'tcx hir::Pat, - mut expected: Ty<'tcx>, - mut def_bm: ty::BindingMode, - discrim_span: Option, - ) { - let tcx = self.tcx; - - debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm); - - let mut path_resolution = None; - let is_non_ref_pat = match pat.node { - PatKind::Struct(..) | - PatKind::TupleStruct(..) | - PatKind::Or(_) | - PatKind::Tuple(..) | - PatKind::Box(_) | - PatKind::Range(..) | - PatKind::Slice(..) => true, - PatKind::Lit(ref lt) => { - let ty = self.check_expr(lt); - match ty.sty { - ty::Ref(..) => false, - _ => true, - } - } - PatKind::Path(ref qpath) => { - let resolution = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span); - path_resolution = Some(resolution); - match resolution.0 { - Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => false, - _ => true, - } - } - PatKind::Wild | - PatKind::Binding(..) | - PatKind::Ref(..) => false, - }; - if is_non_ref_pat { - debug!("pattern is non reference pattern"); - let mut exp_ty = self.resolve_type_vars_with_obligations(&expected); - - // Peel off as many `&` or `&mut` from the discriminant as possible. For example, - // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches - // the `Some(5)` which is not of type Ref. - // - // For each ampersand peeled off, update the binding mode and push the original - // type into the adjustments vector. - // - // See the examples in `ui/match-defbm*.rs`. - let mut pat_adjustments = vec![]; - while let ty::Ref(_, inner_ty, inner_mutability) = exp_ty.sty { - debug!("inspecting {:?}", exp_ty); - - debug!("current discriminant is Ref, inserting implicit deref"); - // Preserve the reference type. We'll need it later during HAIR lowering. - pat_adjustments.push(exp_ty); - - exp_ty = inner_ty; - def_bm = match def_bm { - // If default binding mode is by value, make it `ref` or `ref mut` - // (depending on whether we observe `&` or `&mut`). - ty::BindByValue(_) => - ty::BindByReference(inner_mutability), - - // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate - // the underlying value. - ty::BindByReference(hir::Mutability::MutImmutable) => - ty::BindByReference(hir::Mutability::MutImmutable), - - // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` - // (on `&`). - ty::BindByReference(hir::Mutability::MutMutable) => - ty::BindByReference(inner_mutability), - }; - } - expected = exp_ty; - - if pat_adjustments.len() > 0 { - debug!("default binding mode is now {:?}", def_bm); - self.inh.tables.borrow_mut() - .pat_adjustments_mut() - .insert(pat.hir_id, pat_adjustments); - } - } else if let PatKind::Ref(..) = pat.node { - // When you encounter a `&pat` pattern, reset to "by - // value". This is so that `x` and `y` here are by value, - // as they appear to be: - // - // ``` - // match &(&22, &44) { - // (&x, &y) => ... - // } - // ``` - // - // See issue #46688. - def_bm = ty::BindByValue(hir::MutImmutable); - } - - // Lose mutability now that we know binding mode and discriminant type. - let def_bm = def_bm; - let expected = expected; - - let ty = match pat.node { - PatKind::Wild => { - expected - } - PatKind::Lit(ref lt) => { - // We've already computed the type above (when checking for a non-ref pat), so - // avoid computing it again. - let ty = self.node_ty(lt.hir_id); - - // Byte string patterns behave the same way as array patterns - // They can denote both statically and dynamically-sized byte arrays. - let mut pat_ty = ty; - if let hir::ExprKind::Lit(ref lt) = lt.node { - if let ast::LitKind::ByteStr(_) = lt.node { - let expected_ty = self.structurally_resolved_type(pat.span, expected); - if let ty::Ref(_, r_ty, _) = expected_ty.sty { - if let ty::Slice(_) = r_ty.sty { - pat_ty = tcx.mk_imm_ref(tcx.lifetimes.re_static, - tcx.mk_slice(tcx.types.u8)) - } - } - } - } - - // Somewhat surprising: in this case, the subtyping - // relation goes the opposite way as the other - // cases. Actually what we really want is not a subtyping - // relation at all but rather that there exists a LUB (so - // that they can be compared). However, in practice, - // constants are always scalars or strings. For scalars - // subtyping is irrelevant, and for strings `ty` is - // type is `&'static str`, so if we say that - // - // &'static str <: expected - // - // then that's equivalent to there existing a LUB. - if let Some(mut err) = self.demand_suptype_diag(pat.span, expected, pat_ty) { - err.emit_unless(discrim_span - .filter(|&s| { - // In the case of `if`- and `while`-expressions we've already checked - // that `scrutinee: bool`. We know that the pattern is `true`, - // so an error here would be a duplicate and from the wrong POV. - s.is_desugaring(DesugaringKind::CondTemporary) - }) - .is_some()); - } - - pat_ty - } - PatKind::Range(ref begin, ref end, _) => { - let lhs_ty = self.check_expr(begin); - let rhs_ty = self.check_expr(end); - - // Check that both end-points are of numeric or char type. - let numeric_or_char = |ty: Ty<'_>| { - ty.is_numeric() - || ty.is_char() - || ty.references_error() - }; - let lhs_compat = numeric_or_char(lhs_ty); - let rhs_compat = numeric_or_char(rhs_ty); - - if !lhs_compat || !rhs_compat { - let span = if !lhs_compat && !rhs_compat { - pat.span - } else if !lhs_compat { - begin.span - } else { - end.span - }; - - let mut err = struct_span_err!( - tcx.sess, - span, - E0029, - "only char and numeric types are allowed in range patterns" - ); - err.span_label(span, "ranges require char or numeric types"); - err.note(&format!("start type: {}", self.ty_to_string(lhs_ty))); - err.note(&format!("end type: {}", self.ty_to_string(rhs_ty))); - if tcx.sess.teach(&err.get_code().unwrap()) { - err.note( - "In a match expression, only numbers and characters can be matched \ - against a range. This is because the compiler checks that the range \ - is non-empty at compile-time, and is unable to evaluate arbitrary \ - comparison functions. If you want to capture values of an orderable \ - type between two end-points, you can use a guard." - ); - } - err.emit(); - return; - } - - // Now that we know the types can be unified we find the unified type and use - // it to type the entire expression. - let common_type = self.resolve_vars_if_possible(&lhs_ty); - - // Subtyping doesn't matter here, as the value is some kind of scalar. - self.demand_eqtype_pat(pat.span, expected, lhs_ty, discrim_span); - self.demand_eqtype_pat(pat.span, expected, rhs_ty, discrim_span); - common_type - } - PatKind::Binding(ba, var_id, _, ref sub) => { - let bm = if ba == hir::BindingAnnotation::Unannotated { - def_bm - } else { - ty::BindingMode::convert(ba) - }; - self.inh - .tables - .borrow_mut() - .pat_binding_modes_mut() - .insert(pat.hir_id, bm); - debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); - let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty; - match bm { - ty::BindByReference(mutbl) => { - // If the binding is like - // ref x | ref const x | ref mut x - // then `x` is assigned a value of type `&M T` where M is the mutability - // and T is the expected type. - let region_var = self.next_region_var(infer::PatternRegion(pat.span)); - let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl }; - let region_ty = tcx.mk_ref(region_var, mt); - - // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is - // required. However, we use equality, which is stronger. See (*) for - // an explanation. - self.demand_eqtype_pat(pat.span, region_ty, local_ty, discrim_span); - } - // Otherwise, the type of x is the expected type `T`. - ty::BindByValue(_) => { - // As above, `T <: typeof(x)` is required, but we - // use equality, see (*) below. - self.demand_eqtype_pat(pat.span, expected, local_ty, discrim_span); - } - } - - // If there are multiple arms, make sure they all agree on - // what the type of the binding `x` ought to be. - if var_id != pat.hir_id { - let vt = self.local_ty(pat.span, var_id).decl_ty; - self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span); - } - - if let Some(ref p) = *sub { - self.check_pat_walk(&p, expected, def_bm, discrim_span); - } - - local_ty - } - PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => { - self.check_pat_tuple_struct( - pat, - qpath, - &subpats, - ddpos, - expected, - def_bm, - discrim_span, - ) - } - PatKind::Path(ref qpath) => { - self.check_pat_path(pat, path_resolution.unwrap(), qpath, expected) - } - PatKind::Struct(ref qpath, ref fields, etc) => { - self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, discrim_span) - } - PatKind::Or(ref pats) => { - let expected_ty = self.structurally_resolved_type(pat.span, expected); - for pat in pats { - self.check_pat_walk(pat, expected, def_bm, discrim_span); - } - expected_ty - } - PatKind::Tuple(ref elements, ddpos) => { - let mut expected_len = elements.len(); - if ddpos.is_some() { - // Require known type only when `..` is present. - if let ty::Tuple(ref tys) = - self.structurally_resolved_type(pat.span, expected).sty { - expected_len = tys.len(); - } - } - let max_len = cmp::max(expected_len, elements.len()); - - let element_tys_iter = (0..max_len).map(|_| { - Kind::from(self.next_ty_var( - // FIXME: `MiscVariable` for now -- obtaining the span and name information - // from all tuple elements isn't trivial. - TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span: pat.span, - }, - )) - }); - let element_tys = tcx.mk_substs(element_tys_iter); - let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); - if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) { - err.emit(); - // Walk subpatterns with an expected type of `err` in this case to silence - // further errors being emitted when using the bindings. #50333 - let element_tys_iter = (0..max_len).map(|_| tcx.types.err); - for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat_walk(elem, &tcx.types.err, def_bm, discrim_span); - } - tcx.mk_tup(element_tys_iter) - } else { - for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat_walk( - elem, - &element_tys[i].expect_ty(), - def_bm, - discrim_span, - ); - } - pat_ty - } - } - PatKind::Box(ref inner) => { - let inner_ty = self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span: inner.span, - }); - let uniq_ty = tcx.mk_box(inner_ty); - - if self.check_dereferencable(pat.span, expected, &inner) { - // Here, `demand::subtype` is good enough, but I don't - // think any errors can be introduced by using - // `demand::eqtype`. - self.demand_eqtype_pat(pat.span, expected, uniq_ty, discrim_span); - self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); - uniq_ty - } else { - self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); - tcx.types.err - } - } - PatKind::Ref(ref inner, mutbl) => { - let expected = self.shallow_resolve(expected); - if self.check_dereferencable(pat.span, expected, &inner) { - // `demand::subtype` would be good enough, but using - // `eqtype` turns out to be equally general. See (*) - // below for details. - - // Take region, inner-type from expected type if we - // can, to avoid creating needless variables. This - // also helps with the bad interactions of the given - // hack detailed in (*) below. - debug!("check_pat_walk: expected={:?}", expected); - let (rptr_ty, inner_ty) = match expected.sty { - ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => { - (expected, r_ty) - } - _ => { - let inner_ty = self.next_ty_var( - TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span: inner.span, - } - ); - let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl }; - let region = self.next_region_var(infer::PatternRegion(pat.span)); - let rptr_ty = tcx.mk_ref(region, mt); - debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty); - let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty); - - // Look for a case like `fn foo(&foo: u32)` and suggest - // `fn foo(foo: &u32)` - if let Some(mut err) = err { - self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected); - err.emit(); - } - (rptr_ty, inner_ty) - } - }; - - self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); - rptr_ty - } else { - self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); - tcx.types.err - } - } - PatKind::Slice(ref before, ref slice, ref after) => { - let expected_ty = self.structurally_resolved_type(pat.span, expected); - let (inner_ty, slice_ty) = match expected_ty.sty { - ty::Array(inner_ty, size) => { - if let Some(size) = size.try_eval_usize(tcx, self.param_env) { - let min_len = before.len() as u64 + after.len() as u64; - if slice.is_none() { - if min_len != size { - struct_span_err!( - tcx.sess, pat.span, E0527, - "pattern requires {} elements but array has {}", - min_len, size) - .span_label(pat.span, format!("expected {} elements", size)) - .emit(); - } - (inner_ty, tcx.types.err) - } else if let Some(rest) = size.checked_sub(min_len) { - (inner_ty, tcx.mk_array(inner_ty, rest)) - } else { - struct_span_err!(tcx.sess, pat.span, E0528, - "pattern requires at least {} elements but array has {}", - min_len, size) - .span_label(pat.span, - format!("pattern cannot match array of {} elements", size)) - .emit(); - (inner_ty, tcx.types.err) - } - } else { - struct_span_err!( - tcx.sess, - pat.span, - E0730, - "cannot pattern-match on an array without a fixed length", - ).emit(); - (inner_ty, tcx.types.err) - } - } - ty::Slice(inner_ty) => (inner_ty, expected_ty), - _ => { - if !expected_ty.references_error() { - let mut err = struct_span_err!( - tcx.sess, pat.span, E0529, - "expected an array or slice, found `{}`", - expected_ty); - if let ty::Ref(_, ty, _) = expected_ty.sty { - match ty.sty { - ty::Array(..) | ty::Slice(..) => { - err.help("the semantics of slice patterns changed \ - recently; see issue #62254"); - } - _ => {} - } - } - - err.span_label( pat.span, - format!("pattern cannot match with input type `{}`", expected_ty) - ).emit(); - } - (tcx.types.err, tcx.types.err) - } - }; - - for elt in before { - self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span); - } - if let Some(ref slice) = *slice { - self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span); - } - for elt in after { - self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span); - } - expected_ty - } - }; - - self.write_ty(pat.hir_id, ty); - - // (*) In most of the cases above (literals and constants being - // the exception), we relate types using strict equality, even - // though subtyping would be sufficient. There are a few reasons - // for this, some of which are fairly subtle and which cost me - // (nmatsakis) an hour or two debugging to remember, so I thought - // I'd write them down this time. - // - // 1. There is no loss of expressiveness here, though it does - // cause some inconvenience. What we are saying is that the type - // of `x` becomes *exactly* what is expected. This can cause unnecessary - // errors in some cases, such as this one: - // - // ``` - // fn foo<'x>(x: &'x int) { - // let a = 1; - // let mut z = x; - // z = &a; - // } - // ``` - // - // The reason we might get an error is that `z` might be - // assigned a type like `&'x int`, and then we would have - // a problem when we try to assign `&a` to `z`, because - // the lifetime of `&a` (i.e., the enclosing block) is - // shorter than `'x`. - // - // HOWEVER, this code works fine. The reason is that the - // expected type here is whatever type the user wrote, not - // the initializer's type. In this case the user wrote - // nothing, so we are going to create a type variable `Z`. - // Then we will assign the type of the initializer (`&'x - // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we - // will instantiate `Z` as a type `&'0 int` where `'0` is - // a fresh region variable, with the constraint that `'x : - // '0`. So basically we're all set. - // - // Note that there are two tests to check that this remains true - // (`regions-reassign-{match,let}-bound-pointer.rs`). - // - // 2. Things go horribly wrong if we use subtype. The reason for - // THIS is a fairly subtle case involving bound regions. See the - // `givens` field in `region_constraints`, as well as the test - // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`, - // for details. Short version is that we must sometimes detect - // relationships between specific region variables and regions - // bound in a closure signature, and that detection gets thrown - // off when we substitute fresh region variables here to enable - // subtyping. - } - - fn borrow_pat_suggestion( - &self, - err: &mut DiagnosticBuilder<'_>, - pat: &Pat, - inner: &Pat, - expected: Ty<'tcx>, - ) { - let tcx = self.tcx; - if let PatKind::Binding(..) = inner.node { - let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id); - let binding_parent = tcx.hir().get(binding_parent_id); - debug!("inner {:?} pat {:?} parent {:?}", inner, pat, binding_parent); - match binding_parent { - hir::Node::Arg(hir::Arg { span, .. }) => { - if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) { - err.span_suggestion( - *span, - &format!("did you mean `{}`", snippet), - format!(" &{}", expected), - Applicability::MachineApplicable, - ); - } - } - hir::Node::Arm(_) | - hir::Node::Pat(_) => { - // rely on match ergonomics or it might be nested `&&pat` - if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) { - err.span_suggestion( - pat.span, - "you can probably remove the explicit borrow", - snippet, - Applicability::MaybeIncorrect, - ); - } - } - _ => {} // don't provide suggestions in other cases #55175 - } - } - } - - pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool { - if let PatKind::Binding(..) = inner.node { - if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) { - if let ty::Dynamic(..) = mt.ty.sty { - // This is "x = SomeTrait" being reduced from - // "let &x = &SomeTrait" or "let box x = Box", an error. - let type_str = self.ty_to_string(expected); - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0033, - "type `{}` cannot be dereferenced", - type_str - ); - err.span_label(span, format!("type `{}` cannot be dereferenced", type_str)); - if self.tcx.sess.teach(&err.get_code().unwrap()) { - err.note("\ -This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \ -pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \ -this type has no compile-time size. Therefore, all accesses to trait types must be through \ -pointers. If you encounter this error you should try to avoid dereferencing the pointer. - -You can read more about trait objects in the Trait Objects section of the Reference: \ -https://doc.rust-lang.org/reference/types.html#trait-objects"); - } - err.emit(); - return false - } - } - } - true - } - pub fn check_match( &self, expr: &'tcx hir::Expr, @@ -1038,346 +419,4 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); discrim_ty } } - - fn check_pat_struct( - &self, - pat: &'tcx hir::Pat, - qpath: &hir::QPath, - fields: &'tcx [hir::FieldPat], - etc: bool, - expected: Ty<'tcx>, - def_bm: ty::BindingMode, - discrim_span: Option, - ) -> Ty<'tcx> { - // Resolve the path and check the definition for errors. - let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id) - { - variant_ty - } else { - for field in fields { - self.check_pat_walk(&field.pat, self.tcx.types.err, def_bm, discrim_span); - } - return self.tcx.types.err; - }; - - // Type-check the path. - self.demand_eqtype_pat(pat.span, expected, pat_ty, discrim_span); - - // Type-check subpatterns. - if self.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm) - { - pat_ty - } else { - self.tcx.types.err - } - } - - fn check_pat_path( - &self, - pat: &hir::Pat, - path_resolution: (Res, Option>, &'b [hir::PathSegment]), - qpath: &hir::QPath, - expected: Ty<'tcx>, - ) -> Ty<'tcx> { - let tcx = self.tcx; - - // We have already resolved the path. - let (res, opt_ty, segments) = path_resolution; - match res { - Res::Err => { - self.set_tainted_by_errors(); - return tcx.types.err; - } - Res::Def(DefKind::Method, _) | - Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) | - Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => { - report_unexpected_variant_res(tcx, res, pat.span, qpath); - return tcx.types.err; - } - Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..) | - Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => {} // OK - _ => bug!("unexpected pattern resolution: {:?}", res) - } - - // Type-check the path. - let pat_ty = self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id).0; - self.demand_suptype(pat.span, expected, pat_ty); - pat_ty - } - - fn check_pat_tuple_struct( - &self, - pat: &hir::Pat, - qpath: &hir::QPath, - subpats: &'tcx [P], - ddpos: Option, - expected: Ty<'tcx>, - def_bm: ty::BindingMode, - match_arm_pat_span: Option, - ) -> Ty<'tcx> { - let tcx = self.tcx; - let on_error = || { - for pat in subpats { - self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span); - } - }; - let report_unexpected_res = |res: Res| { - let msg = format!("expected tuple struct/variant, found {} `{}`", - res.descr(), - hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))); - let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg); - match (res, &pat.node) { - (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::Method, _), _) => { - err.span_label(pat.span, "`fn` calls are not allowed in patterns"); - err.help("for more information, visit \ - https://doc.rust-lang.org/book/ch18-00-patterns.html"); - } - _ => { - err.span_label(pat.span, "not a tuple variant or struct"); - } - } - err.emit(); - on_error(); - }; - - // Resolve the path and check the definition for errors. - let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span); - if res == Res::Err { - self.set_tainted_by_errors(); - on_error(); - return self.tcx.types.err; - } - - // Type-check the path. - let (pat_ty, res) = self.instantiate_value_path(segments, opt_ty, res, pat.span, - pat.hir_id); - if !pat_ty.is_fn() { - report_unexpected_res(res); - return self.tcx.types.err; - } - - let variant = match res { - Res::Err => { - self.set_tainted_by_errors(); - on_error(); - return tcx.types.err; - } - Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Method, _) => { - report_unexpected_res(res); - return tcx.types.err; - } - Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => { - tcx.expect_variant_res(res) - } - _ => bug!("unexpected pattern resolution: {:?}", res) - }; - - // Replace constructor type with constructed type for tuple struct patterns. - let pat_ty = pat_ty.fn_sig(tcx).output(); - let pat_ty = pat_ty.no_bound_vars().expect("expected fn type"); - - self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span); - - // Type-check subpatterns. - if subpats.len() == variant.fields.len() || - subpats.len() < variant.fields.len() && ddpos.is_some() { - let substs = match pat_ty.sty { - ty::Adt(_, substs) => substs, - _ => bug!("unexpected pattern type {:?}", pat_ty), - }; - for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) { - let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs); - self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span); - - self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span); - } - } else { - let subpats_ending = if subpats.len() == 1 { "" } else { "s" }; - let fields_ending = if variant.fields.len() == 1 { "" } else { "s" }; - struct_span_err!(tcx.sess, pat.span, E0023, - "this pattern has {} field{}, but the corresponding {} has {} field{}", - subpats.len(), subpats_ending, res.descr(), - variant.fields.len(), fields_ending) - .span_label(pat.span, format!("expected {} field{}, found {}", - variant.fields.len(), fields_ending, subpats.len())) - .emit(); - on_error(); - return tcx.types.err; - } - pat_ty - } - - fn check_struct_pat_fields( - &self, - adt_ty: Ty<'tcx>, - pat_id: hir::HirId, - span: Span, - variant: &'tcx ty::VariantDef, - fields: &'tcx [hir::FieldPat], - etc: bool, - def_bm: ty::BindingMode, - ) -> bool { - let tcx = self.tcx; - - let (substs, adt) = match adt_ty.sty { - ty::Adt(adt, substs) => (substs, adt), - _ => span_bug!(span, "struct pattern is not an ADT") - }; - let kind_name = adt.variant_descr(); - - // Index the struct fields' types. - let field_map = variant.fields - .iter() - .enumerate() - .map(|(i, field)| (field.ident.modern(), (i, field))) - .collect::>(); - - // Keep track of which fields have already appeared in the pattern. - let mut used_fields = FxHashMap::default(); - let mut no_field_errors = true; - - let mut inexistent_fields = vec![]; - // Typecheck each field. - for field in fields { - let span = field.span; - let ident = tcx.adjust_ident(field.ident, variant.def_id); - let field_ty = match used_fields.entry(ident) { - Occupied(occupied) => { - struct_span_err!(tcx.sess, span, E0025, - "field `{}` bound multiple times \ - in the pattern", - field.ident) - .span_label(span, - format!("multiple uses of `{}` in pattern", field.ident)) - .span_label(*occupied.get(), format!("first use of `{}`", field.ident)) - .emit(); - no_field_errors = false; - tcx.types.err - } - Vacant(vacant) => { - vacant.insert(span); - field_map.get(&ident) - .map(|(i, f)| { - self.write_field_index(field.hir_id, *i); - self.tcx.check_stability(f.did, Some(pat_id), span); - self.field_ty(span, f, substs) - }) - .unwrap_or_else(|| { - inexistent_fields.push(field.ident); - no_field_errors = false; - tcx.types.err - }) - } - }; - - self.check_pat_walk(&field.pat, field_ty, def_bm, None); - } - let mut unmentioned_fields = variant.fields - .iter() - .map(|field| field.ident.modern()) - .filter(|ident| !used_fields.contains_key(&ident)) - .collect::>(); - if inexistent_fields.len() > 0 && !variant.recovered { - let (field_names, t, plural) = if inexistent_fields.len() == 1 { - (format!("a field named `{}`", inexistent_fields[0]), "this", "") - } else { - (format!("fields named {}", - inexistent_fields.iter() - .map(|ident| format!("`{}`", ident)) - .collect::>() - .join(", ")), "these", "s") - }; - let spans = inexistent_fields.iter().map(|ident| ident.span).collect::>(); - let mut err = struct_span_err!(tcx.sess, - spans, - E0026, - "{} `{}` does not have {}", - kind_name, - tcx.def_path_str(variant.def_id), - field_names); - if let Some(ident) = inexistent_fields.last() { - err.span_label(ident.span, - format!("{} `{}` does not have {} field{}", - kind_name, - tcx.def_path_str(variant.def_id), - t, - plural)); - if plural == "" { - let input = unmentioned_fields.iter().map(|field| &field.name); - let suggested_name = - find_best_match_for_name(input, &ident.as_str(), None); - if let Some(suggested_name) = suggested_name { - err.span_suggestion( - ident.span, - "a field with a similar name exists", - suggested_name.to_string(), - Applicability::MaybeIncorrect, - ); - - // we don't want to throw `E0027` in case we have thrown `E0026` for them - unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str()); - } - } - } - if tcx.sess.teach(&err.get_code().unwrap()) { - err.note( - "This error indicates that a struct pattern attempted to \ - extract a non-existent field from a struct. Struct fields \ - are identified by the name used before the colon : so struct \ - patterns should resemble the declaration of the struct type \ - being matched.\n\n\ - If you are using shorthand field patterns but want to refer \ - to the struct field by a different name, you should rename \ - it explicitly." - ); - } - err.emit(); - } - - // Require `..` if struct has non_exhaustive attribute. - if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc { - span_err!(tcx.sess, span, E0638, - "`..` required with {} marked as non-exhaustive", - kind_name); - } - - // Report an error if incorrect number of the fields were specified. - if kind_name == "union" { - if fields.len() != 1 { - tcx.sess.span_err(span, "union patterns should have exactly one field"); - } - if etc { - tcx.sess.span_err(span, "`..` cannot be used in union patterns"); - } - } else if !etc { - if unmentioned_fields.len() > 0 { - let field_names = if unmentioned_fields.len() == 1 { - format!("field `{}`", unmentioned_fields[0]) - } else { - format!("fields {}", - unmentioned_fields.iter() - .map(|name| format!("`{}`", name)) - .collect::>() - .join(", ")) - }; - let mut diag = struct_span_err!(tcx.sess, span, E0027, - "pattern does not mention {}", - field_names); - diag.span_label(span, format!("missing {}", field_names)); - if variant.ctor_kind == CtorKind::Fn { - diag.note("trying to match a tuple variant with a struct variant pattern"); - } - if tcx.sess.teach(&diag.get_code().unwrap()) { - diag.note( - "This error indicates that a pattern for a struct fails to specify a \ - sub-pattern for every one of the struct's fields. Ensure that each field \ - from the struct's definition is mentioned in the pattern, or use `..` to \ - ignore unwanted fields." - ); - } - diag.emit(); - } - } - no_field_errors - } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9c7ac83e82e97..a130d11a5e645 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -70,6 +70,7 @@ type parameter). mod autoderef; pub mod dropck; pub mod _match; +mod pat; pub mod writeback; mod regionck; pub mod coercion; diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs new file mode 100644 index 0000000000000..e2d0f485bdf01 --- /dev/null +++ b/src/librustc_typeck/check/pat.rs @@ -0,0 +1,968 @@ +use crate::check::FnCtxt; +use crate::util::nodemap::FxHashMap; +use errors::{Applicability, DiagnosticBuilder}; +use rustc::hir::{self, PatKind, Pat}; +use rustc::hir::def::{Res, DefKind, CtorKind}; +use rustc::hir::pat_util::EnumerateAndAdjustIterator; +use rustc::hir::ptr::P; +use rustc::infer; +use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc::ty::{self, Ty, TypeFoldable}; +use rustc::ty::subst::Kind; +use syntax::ast; +use syntax::util::lev_distance::find_best_match_for_name; +use syntax_pos::Span; +use syntax_pos::hygiene::DesugaringKind; + +use std::collections::hash_map::Entry::{Occupied, Vacant}; +use std::cmp; + +use super::report_unexpected_variant_res; + +impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + /// `discrim_span` argument having a `Span` indicates that this pattern is part of a match + /// expression arm guard, and it points to the match discriminant to add context in type errors. + /// In the following example, `discrim_span` corresponds to the `a + b` expression: + /// + /// ```text + /// error[E0308]: mismatched types + /// --> src/main.rs:5:9 + /// | + /// 4 | let temp: usize = match a + b { + /// | ----- this expression has type `usize` + /// 5 | Ok(num) => num, + /// | ^^^^^^^ expected usize, found enum `std::result::Result` + /// | + /// = note: expected type `usize` + /// found type `std::result::Result<_, _>` + /// ``` + pub fn check_pat_walk( + &self, + pat: &'tcx hir::Pat, + mut expected: Ty<'tcx>, + mut def_bm: ty::BindingMode, + discrim_span: Option, + ) { + let tcx = self.tcx; + + debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm); + + let mut path_resolution = None; + let is_non_ref_pat = match pat.node { + PatKind::Struct(..) | + PatKind::TupleStruct(..) | + PatKind::Or(_) | + PatKind::Tuple(..) | + PatKind::Box(_) | + PatKind::Range(..) | + PatKind::Slice(..) => true, + PatKind::Lit(ref lt) => { + let ty = self.check_expr(lt); + match ty.sty { + ty::Ref(..) => false, + _ => true, + } + } + PatKind::Path(ref qpath) => { + let resolution = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span); + path_resolution = Some(resolution); + match resolution.0 { + Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => false, + _ => true, + } + } + PatKind::Wild | + PatKind::Binding(..) | + PatKind::Ref(..) => false, + }; + if is_non_ref_pat { + debug!("pattern is non reference pattern"); + let mut exp_ty = self.resolve_type_vars_with_obligations(&expected); + + // Peel off as many `&` or `&mut` from the discriminant as possible. For example, + // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches + // the `Some(5)` which is not of type Ref. + // + // For each ampersand peeled off, update the binding mode and push the original + // type into the adjustments vector. + // + // See the examples in `ui/match-defbm*.rs`. + let mut pat_adjustments = vec![]; + while let ty::Ref(_, inner_ty, inner_mutability) = exp_ty.sty { + debug!("inspecting {:?}", exp_ty); + + debug!("current discriminant is Ref, inserting implicit deref"); + // Preserve the reference type. We'll need it later during HAIR lowering. + pat_adjustments.push(exp_ty); + + exp_ty = inner_ty; + def_bm = match def_bm { + // If default binding mode is by value, make it `ref` or `ref mut` + // (depending on whether we observe `&` or `&mut`). + ty::BindByValue(_) => + ty::BindByReference(inner_mutability), + + // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate + // the underlying value. + ty::BindByReference(hir::Mutability::MutImmutable) => + ty::BindByReference(hir::Mutability::MutImmutable), + + // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` + // (on `&`). + ty::BindByReference(hir::Mutability::MutMutable) => + ty::BindByReference(inner_mutability), + }; + } + expected = exp_ty; + + if pat_adjustments.len() > 0 { + debug!("default binding mode is now {:?}", def_bm); + self.inh.tables.borrow_mut() + .pat_adjustments_mut() + .insert(pat.hir_id, pat_adjustments); + } + } else if let PatKind::Ref(..) = pat.node { + // When you encounter a `&pat` pattern, reset to "by + // value". This is so that `x` and `y` here are by value, + // as they appear to be: + // + // ``` + // match &(&22, &44) { + // (&x, &y) => ... + // } + // ``` + // + // See issue #46688. + def_bm = ty::BindByValue(hir::MutImmutable); + } + + // Lose mutability now that we know binding mode and discriminant type. + let def_bm = def_bm; + let expected = expected; + + let ty = match pat.node { + PatKind::Wild => { + expected + } + PatKind::Lit(ref lt) => { + // We've already computed the type above (when checking for a non-ref pat), so + // avoid computing it again. + let ty = self.node_ty(lt.hir_id); + + // Byte string patterns behave the same way as array patterns + // They can denote both statically and dynamically-sized byte arrays. + let mut pat_ty = ty; + if let hir::ExprKind::Lit(ref lt) = lt.node { + if let ast::LitKind::ByteStr(_) = lt.node { + let expected_ty = self.structurally_resolved_type(pat.span, expected); + if let ty::Ref(_, r_ty, _) = expected_ty.sty { + if let ty::Slice(_) = r_ty.sty { + pat_ty = tcx.mk_imm_ref(tcx.lifetimes.re_static, + tcx.mk_slice(tcx.types.u8)) + } + } + } + } + + // Somewhat surprising: in this case, the subtyping + // relation goes the opposite way as the other + // cases. Actually what we really want is not a subtyping + // relation at all but rather that there exists a LUB (so + // that they can be compared). However, in practice, + // constants are always scalars or strings. For scalars + // subtyping is irrelevant, and for strings `ty` is + // type is `&'static str`, so if we say that + // + // &'static str <: expected + // + // then that's equivalent to there existing a LUB. + if let Some(mut err) = self.demand_suptype_diag(pat.span, expected, pat_ty) { + err.emit_unless(discrim_span + .filter(|&s| { + // In the case of `if`- and `while`-expressions we've already checked + // that `scrutinee: bool`. We know that the pattern is `true`, + // so an error here would be a duplicate and from the wrong POV. + s.is_desugaring(DesugaringKind::CondTemporary) + }) + .is_some()); + } + + pat_ty + } + PatKind::Range(ref begin, ref end, _) => { + let lhs_ty = self.check_expr(begin); + let rhs_ty = self.check_expr(end); + + // Check that both end-points are of numeric or char type. + let numeric_or_char = |ty: Ty<'_>| { + ty.is_numeric() + || ty.is_char() + || ty.references_error() + }; + let lhs_compat = numeric_or_char(lhs_ty); + let rhs_compat = numeric_or_char(rhs_ty); + + if !lhs_compat || !rhs_compat { + let span = if !lhs_compat && !rhs_compat { + pat.span + } else if !lhs_compat { + begin.span + } else { + end.span + }; + + let mut err = struct_span_err!( + tcx.sess, + span, + E0029, + "only char and numeric types are allowed in range patterns" + ); + err.span_label(span, "ranges require char or numeric types"); + err.note(&format!("start type: {}", self.ty_to_string(lhs_ty))); + err.note(&format!("end type: {}", self.ty_to_string(rhs_ty))); + if tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "In a match expression, only numbers and characters can be matched \ + against a range. This is because the compiler checks that the range \ + is non-empty at compile-time, and is unable to evaluate arbitrary \ + comparison functions. If you want to capture values of an orderable \ + type between two end-points, you can use a guard." + ); + } + err.emit(); + return; + } + + // Now that we know the types can be unified we find the unified type and use + // it to type the entire expression. + let common_type = self.resolve_vars_if_possible(&lhs_ty); + + // Subtyping doesn't matter here, as the value is some kind of scalar. + self.demand_eqtype_pat(pat.span, expected, lhs_ty, discrim_span); + self.demand_eqtype_pat(pat.span, expected, rhs_ty, discrim_span); + common_type + } + PatKind::Binding(ba, var_id, _, ref sub) => { + let bm = if ba == hir::BindingAnnotation::Unannotated { + def_bm + } else { + ty::BindingMode::convert(ba) + }; + self.inh + .tables + .borrow_mut() + .pat_binding_modes_mut() + .insert(pat.hir_id, bm); + debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); + let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty; + match bm { + ty::BindByReference(mutbl) => { + // If the binding is like + // ref x | ref const x | ref mut x + // then `x` is assigned a value of type `&M T` where M is the mutability + // and T is the expected type. + let region_var = self.next_region_var(infer::PatternRegion(pat.span)); + let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl }; + let region_ty = tcx.mk_ref(region_var, mt); + + // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is + // required. However, we use equality, which is stronger. See (*) for + // an explanation. + self.demand_eqtype_pat(pat.span, region_ty, local_ty, discrim_span); + } + // Otherwise, the type of x is the expected type `T`. + ty::BindByValue(_) => { + // As above, `T <: typeof(x)` is required, but we + // use equality, see (*) below. + self.demand_eqtype_pat(pat.span, expected, local_ty, discrim_span); + } + } + + // If there are multiple arms, make sure they all agree on + // what the type of the binding `x` ought to be. + if var_id != pat.hir_id { + let vt = self.local_ty(pat.span, var_id).decl_ty; + self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span); + } + + if let Some(ref p) = *sub { + self.check_pat_walk(&p, expected, def_bm, discrim_span); + } + + local_ty + } + PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => { + self.check_pat_tuple_struct( + pat, + qpath, + &subpats, + ddpos, + expected, + def_bm, + discrim_span, + ) + } + PatKind::Path(ref qpath) => { + self.check_pat_path(pat, path_resolution.unwrap(), qpath, expected) + } + PatKind::Struct(ref qpath, ref fields, etc) => { + self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, discrim_span) + } + PatKind::Or(ref pats) => { + let expected_ty = self.structurally_resolved_type(pat.span, expected); + for pat in pats { + self.check_pat_walk(pat, expected, def_bm, discrim_span); + } + expected_ty + } + PatKind::Tuple(ref elements, ddpos) => { + let mut expected_len = elements.len(); + if ddpos.is_some() { + // Require known type only when `..` is present. + if let ty::Tuple(ref tys) = + self.structurally_resolved_type(pat.span, expected).sty { + expected_len = tys.len(); + } + } + let max_len = cmp::max(expected_len, elements.len()); + + let element_tys_iter = (0..max_len).map(|_| { + Kind::from(self.next_ty_var( + // FIXME: `MiscVariable` for now -- obtaining the span and name information + // from all tuple elements isn't trivial. + TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: pat.span, + }, + )) + }); + let element_tys = tcx.mk_substs(element_tys_iter); + let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); + if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) { + err.emit(); + // Walk subpatterns with an expected type of `err` in this case to silence + // further errors being emitted when using the bindings. #50333 + let element_tys_iter = (0..max_len).map(|_| tcx.types.err); + for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { + self.check_pat_walk(elem, &tcx.types.err, def_bm, discrim_span); + } + tcx.mk_tup(element_tys_iter) + } else { + for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { + self.check_pat_walk( + elem, + &element_tys[i].expect_ty(), + def_bm, + discrim_span, + ); + } + pat_ty + } + } + PatKind::Box(ref inner) => { + let inner_ty = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: inner.span, + }); + let uniq_ty = tcx.mk_box(inner_ty); + + if self.check_dereferencable(pat.span, expected, &inner) { + // Here, `demand::subtype` is good enough, but I don't + // think any errors can be introduced by using + // `demand::eqtype`. + self.demand_eqtype_pat(pat.span, expected, uniq_ty, discrim_span); + self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); + uniq_ty + } else { + self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); + tcx.types.err + } + } + PatKind::Ref(ref inner, mutbl) => { + let expected = self.shallow_resolve(expected); + if self.check_dereferencable(pat.span, expected, &inner) { + // `demand::subtype` would be good enough, but using + // `eqtype` turns out to be equally general. See (*) + // below for details. + + // Take region, inner-type from expected type if we + // can, to avoid creating needless variables. This + // also helps with the bad interactions of the given + // hack detailed in (*) below. + debug!("check_pat_walk: expected={:?}", expected); + let (rptr_ty, inner_ty) = match expected.sty { + ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => { + (expected, r_ty) + } + _ => { + let inner_ty = self.next_ty_var( + TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: inner.span, + } + ); + let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl }; + let region = self.next_region_var(infer::PatternRegion(pat.span)); + let rptr_ty = tcx.mk_ref(region, mt); + debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty); + let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty); + + // Look for a case like `fn foo(&foo: u32)` and suggest + // `fn foo(foo: &u32)` + if let Some(mut err) = err { + self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected); + err.emit(); + } + (rptr_ty, inner_ty) + } + }; + + self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); + rptr_ty + } else { + self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); + tcx.types.err + } + } + PatKind::Slice(ref before, ref slice, ref after) => { + let expected_ty = self.structurally_resolved_type(pat.span, expected); + let (inner_ty, slice_ty) = match expected_ty.sty { + ty::Array(inner_ty, size) => { + if let Some(size) = size.try_eval_usize(tcx, self.param_env) { + let min_len = before.len() as u64 + after.len() as u64; + if slice.is_none() { + if min_len != size { + struct_span_err!( + tcx.sess, pat.span, E0527, + "pattern requires {} elements but array has {}", + min_len, size) + .span_label(pat.span, format!("expected {} elements", size)) + .emit(); + } + (inner_ty, tcx.types.err) + } else if let Some(rest) = size.checked_sub(min_len) { + (inner_ty, tcx.mk_array(inner_ty, rest)) + } else { + struct_span_err!(tcx.sess, pat.span, E0528, + "pattern requires at least {} elements but array has {}", + min_len, size) + .span_label(pat.span, + format!("pattern cannot match array of {} elements", size)) + .emit(); + (inner_ty, tcx.types.err) + } + } else { + struct_span_err!( + tcx.sess, + pat.span, + E0730, + "cannot pattern-match on an array without a fixed length", + ).emit(); + (inner_ty, tcx.types.err) + } + } + ty::Slice(inner_ty) => (inner_ty, expected_ty), + _ => { + if !expected_ty.references_error() { + let mut err = struct_span_err!( + tcx.sess, pat.span, E0529, + "expected an array or slice, found `{}`", + expected_ty); + if let ty::Ref(_, ty, _) = expected_ty.sty { + match ty.sty { + ty::Array(..) | ty::Slice(..) => { + err.help("the semantics of slice patterns changed \ + recently; see issue #62254"); + } + _ => {} + } + } + + err.span_label( pat.span, + format!("pattern cannot match with input type `{}`", expected_ty) + ).emit(); + } + (tcx.types.err, tcx.types.err) + } + }; + + for elt in before { + self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span); + } + if let Some(ref slice) = *slice { + self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span); + } + for elt in after { + self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span); + } + expected_ty + } + }; + + self.write_ty(pat.hir_id, ty); + + // (*) In most of the cases above (literals and constants being + // the exception), we relate types using strict equality, even + // though subtyping would be sufficient. There are a few reasons + // for this, some of which are fairly subtle and which cost me + // (nmatsakis) an hour or two debugging to remember, so I thought + // I'd write them down this time. + // + // 1. There is no loss of expressiveness here, though it does + // cause some inconvenience. What we are saying is that the type + // of `x` becomes *exactly* what is expected. This can cause unnecessary + // errors in some cases, such as this one: + // + // ``` + // fn foo<'x>(x: &'x int) { + // let a = 1; + // let mut z = x; + // z = &a; + // } + // ``` + // + // The reason we might get an error is that `z` might be + // assigned a type like `&'x int`, and then we would have + // a problem when we try to assign `&a` to `z`, because + // the lifetime of `&a` (i.e., the enclosing block) is + // shorter than `'x`. + // + // HOWEVER, this code works fine. The reason is that the + // expected type here is whatever type the user wrote, not + // the initializer's type. In this case the user wrote + // nothing, so we are going to create a type variable `Z`. + // Then we will assign the type of the initializer (`&'x + // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we + // will instantiate `Z` as a type `&'0 int` where `'0` is + // a fresh region variable, with the constraint that `'x : + // '0`. So basically we're all set. + // + // Note that there are two tests to check that this remains true + // (`regions-reassign-{match,let}-bound-pointer.rs`). + // + // 2. Things go horribly wrong if we use subtype. The reason for + // THIS is a fairly subtle case involving bound regions. See the + // `givens` field in `region_constraints`, as well as the test + // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`, + // for details. Short version is that we must sometimes detect + // relationships between specific region variables and regions + // bound in a closure signature, and that detection gets thrown + // off when we substitute fresh region variables here to enable + // subtyping. + } + + fn borrow_pat_suggestion( + &self, + err: &mut DiagnosticBuilder<'_>, + pat: &Pat, + inner: &Pat, + expected: Ty<'tcx>, + ) { + let tcx = self.tcx; + if let PatKind::Binding(..) = inner.node { + let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id); + let binding_parent = tcx.hir().get(binding_parent_id); + debug!("inner {:?} pat {:?} parent {:?}", inner, pat, binding_parent); + match binding_parent { + hir::Node::Arg(hir::Arg { span, .. }) => { + if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) { + err.span_suggestion( + *span, + &format!("did you mean `{}`", snippet), + format!(" &{}", expected), + Applicability::MachineApplicable, + ); + } + } + hir::Node::Arm(_) | + hir::Node::Pat(_) => { + // rely on match ergonomics or it might be nested `&&pat` + if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) { + err.span_suggestion( + pat.span, + "you can probably remove the explicit borrow", + snippet, + Applicability::MaybeIncorrect, + ); + } + } + _ => {} // don't provide suggestions in other cases #55175 + } + } + } + + pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool { + if let PatKind::Binding(..) = inner.node { + if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) { + if let ty::Dynamic(..) = mt.ty.sty { + // This is "x = SomeTrait" being reduced from + // "let &x = &SomeTrait" or "let box x = Box", an error. + let type_str = self.ty_to_string(expected); + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0033, + "type `{}` cannot be dereferenced", + type_str + ); + err.span_label(span, format!("type `{}` cannot be dereferenced", type_str)); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note("\ +This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \ +pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \ +this type has no compile-time size. Therefore, all accesses to trait types must be through \ +pointers. If you encounter this error you should try to avoid dereferencing the pointer. + +You can read more about trait objects in the Trait Objects section of the Reference: \ +https://doc.rust-lang.org/reference/types.html#trait-objects"); + } + err.emit(); + return false + } + } + } + true + } + + fn check_pat_struct( + &self, + pat: &'tcx hir::Pat, + qpath: &hir::QPath, + fields: &'tcx [hir::FieldPat], + etc: bool, + expected: Ty<'tcx>, + def_bm: ty::BindingMode, + discrim_span: Option, + ) -> Ty<'tcx> { + // Resolve the path and check the definition for errors. + let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id) + { + variant_ty + } else { + for field in fields { + self.check_pat_walk(&field.pat, self.tcx.types.err, def_bm, discrim_span); + } + return self.tcx.types.err; + }; + + // Type-check the path. + self.demand_eqtype_pat(pat.span, expected, pat_ty, discrim_span); + + // Type-check subpatterns. + if self.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm) + { + pat_ty + } else { + self.tcx.types.err + } + } + + fn check_pat_path( + &self, + pat: &hir::Pat, + path_resolution: (Res, Option>, &'b [hir::PathSegment]), + qpath: &hir::QPath, + expected: Ty<'tcx>, + ) -> Ty<'tcx> { + let tcx = self.tcx; + + // We have already resolved the path. + let (res, opt_ty, segments) = path_resolution; + match res { + Res::Err => { + self.set_tainted_by_errors(); + return tcx.types.err; + } + Res::Def(DefKind::Method, _) | + Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) | + Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => { + report_unexpected_variant_res(tcx, res, pat.span, qpath); + return tcx.types.err; + } + Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..) | + Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => {} // OK + _ => bug!("unexpected pattern resolution: {:?}", res) + } + + // Type-check the path. + let pat_ty = self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id).0; + self.demand_suptype(pat.span, expected, pat_ty); + pat_ty + } + + fn check_pat_tuple_struct( + &self, + pat: &hir::Pat, + qpath: &hir::QPath, + subpats: &'tcx [P], + ddpos: Option, + expected: Ty<'tcx>, + def_bm: ty::BindingMode, + match_arm_pat_span: Option, + ) -> Ty<'tcx> { + let tcx = self.tcx; + let on_error = || { + for pat in subpats { + self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span); + } + }; + let report_unexpected_res = |res: Res| { + let msg = format!("expected tuple struct/variant, found {} `{}`", + res.descr(), + hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))); + let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg); + match (res, &pat.node) { + (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::Method, _), _) => { + err.span_label(pat.span, "`fn` calls are not allowed in patterns"); + err.help("for more information, visit \ + https://doc.rust-lang.org/book/ch18-00-patterns.html"); + } + _ => { + err.span_label(pat.span, "not a tuple variant or struct"); + } + } + err.emit(); + on_error(); + }; + + // Resolve the path and check the definition for errors. + let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span); + if res == Res::Err { + self.set_tainted_by_errors(); + on_error(); + return self.tcx.types.err; + } + + // Type-check the path. + let (pat_ty, res) = self.instantiate_value_path(segments, opt_ty, res, pat.span, + pat.hir_id); + if !pat_ty.is_fn() { + report_unexpected_res(res); + return self.tcx.types.err; + } + + let variant = match res { + Res::Err => { + self.set_tainted_by_errors(); + on_error(); + return tcx.types.err; + } + Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Method, _) => { + report_unexpected_res(res); + return tcx.types.err; + } + Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => { + tcx.expect_variant_res(res) + } + _ => bug!("unexpected pattern resolution: {:?}", res) + }; + + // Replace constructor type with constructed type for tuple struct patterns. + let pat_ty = pat_ty.fn_sig(tcx).output(); + let pat_ty = pat_ty.no_bound_vars().expect("expected fn type"); + + self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span); + + // Type-check subpatterns. + if subpats.len() == variant.fields.len() || + subpats.len() < variant.fields.len() && ddpos.is_some() { + let substs = match pat_ty.sty { + ty::Adt(_, substs) => substs, + _ => bug!("unexpected pattern type {:?}", pat_ty), + }; + for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) { + let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs); + self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span); + + self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span); + } + } else { + let subpats_ending = if subpats.len() == 1 { "" } else { "s" }; + let fields_ending = if variant.fields.len() == 1 { "" } else { "s" }; + struct_span_err!(tcx.sess, pat.span, E0023, + "this pattern has {} field{}, but the corresponding {} has {} field{}", + subpats.len(), subpats_ending, res.descr(), + variant.fields.len(), fields_ending) + .span_label(pat.span, format!("expected {} field{}, found {}", + variant.fields.len(), fields_ending, subpats.len())) + .emit(); + on_error(); + return tcx.types.err; + } + pat_ty + } + + fn check_struct_pat_fields( + &self, + adt_ty: Ty<'tcx>, + pat_id: hir::HirId, + span: Span, + variant: &'tcx ty::VariantDef, + fields: &'tcx [hir::FieldPat], + etc: bool, + def_bm: ty::BindingMode, + ) -> bool { + let tcx = self.tcx; + + let (substs, adt) = match adt_ty.sty { + ty::Adt(adt, substs) => (substs, adt), + _ => span_bug!(span, "struct pattern is not an ADT") + }; + let kind_name = adt.variant_descr(); + + // Index the struct fields' types. + let field_map = variant.fields + .iter() + .enumerate() + .map(|(i, field)| (field.ident.modern(), (i, field))) + .collect::>(); + + // Keep track of which fields have already appeared in the pattern. + let mut used_fields = FxHashMap::default(); + let mut no_field_errors = true; + + let mut inexistent_fields = vec![]; + // Typecheck each field. + for field in fields { + let span = field.span; + let ident = tcx.adjust_ident(field.ident, variant.def_id); + let field_ty = match used_fields.entry(ident) { + Occupied(occupied) => { + struct_span_err!(tcx.sess, span, E0025, + "field `{}` bound multiple times \ + in the pattern", + field.ident) + .span_label(span, + format!("multiple uses of `{}` in pattern", field.ident)) + .span_label(*occupied.get(), format!("first use of `{}`", field.ident)) + .emit(); + no_field_errors = false; + tcx.types.err + } + Vacant(vacant) => { + vacant.insert(span); + field_map.get(&ident) + .map(|(i, f)| { + self.write_field_index(field.hir_id, *i); + self.tcx.check_stability(f.did, Some(pat_id), span); + self.field_ty(span, f, substs) + }) + .unwrap_or_else(|| { + inexistent_fields.push(field.ident); + no_field_errors = false; + tcx.types.err + }) + } + }; + + self.check_pat_walk(&field.pat, field_ty, def_bm, None); + } + let mut unmentioned_fields = variant.fields + .iter() + .map(|field| field.ident.modern()) + .filter(|ident| !used_fields.contains_key(&ident)) + .collect::>(); + if inexistent_fields.len() > 0 && !variant.recovered { + let (field_names, t, plural) = if inexistent_fields.len() == 1 { + (format!("a field named `{}`", inexistent_fields[0]), "this", "") + } else { + (format!("fields named {}", + inexistent_fields.iter() + .map(|ident| format!("`{}`", ident)) + .collect::>() + .join(", ")), "these", "s") + }; + let spans = inexistent_fields.iter().map(|ident| ident.span).collect::>(); + let mut err = struct_span_err!(tcx.sess, + spans, + E0026, + "{} `{}` does not have {}", + kind_name, + tcx.def_path_str(variant.def_id), + field_names); + if let Some(ident) = inexistent_fields.last() { + err.span_label(ident.span, + format!("{} `{}` does not have {} field{}", + kind_name, + tcx.def_path_str(variant.def_id), + t, + plural)); + if plural == "" { + let input = unmentioned_fields.iter().map(|field| &field.name); + let suggested_name = + find_best_match_for_name(input, &ident.as_str(), None); + if let Some(suggested_name) = suggested_name { + err.span_suggestion( + ident.span, + "a field with a similar name exists", + suggested_name.to_string(), + Applicability::MaybeIncorrect, + ); + + // we don't want to throw `E0027` in case we have thrown `E0026` for them + unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str()); + } + } + } + if tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "This error indicates that a struct pattern attempted to \ + extract a non-existent field from a struct. Struct fields \ + are identified by the name used before the colon : so struct \ + patterns should resemble the declaration of the struct type \ + being matched.\n\n\ + If you are using shorthand field patterns but want to refer \ + to the struct field by a different name, you should rename \ + it explicitly." + ); + } + err.emit(); + } + + // Require `..` if struct has non_exhaustive attribute. + if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc { + span_err!(tcx.sess, span, E0638, + "`..` required with {} marked as non-exhaustive", + kind_name); + } + + // Report an error if incorrect number of the fields were specified. + if kind_name == "union" { + if fields.len() != 1 { + tcx.sess.span_err(span, "union patterns should have exactly one field"); + } + if etc { + tcx.sess.span_err(span, "`..` cannot be used in union patterns"); + } + } else if !etc { + if unmentioned_fields.len() > 0 { + let field_names = if unmentioned_fields.len() == 1 { + format!("field `{}`", unmentioned_fields[0]) + } else { + format!("fields {}", + unmentioned_fields.iter() + .map(|name| format!("`{}`", name)) + .collect::>() + .join(", ")) + }; + let mut diag = struct_span_err!(tcx.sess, span, E0027, + "pattern does not mention {}", + field_names); + diag.span_label(span, format!("missing {}", field_names)); + if variant.ctor_kind == CtorKind::Fn { + diag.note("trying to match a tuple variant with a struct variant pattern"); + } + if tcx.sess.teach(&diag.get_code().unwrap()) { + diag.note( + "This error indicates that a pattern for a struct fails to specify a \ + sub-pattern for every one of the struct's fields. Ensure that each field \ + from the struct's definition is mentioned in the pattern, or use `..` to \ + ignore unwanted fields." + ); + } + diag.emit(); + } + } + no_field_errors + } +} From dbe6d59d6ef744ef17d5fb3e13a1e017baae9ce8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 23 Aug 2019 15:05:58 +0200 Subject: [PATCH 174/618] typeck/pat.rs: move note out of `check_dereferenceable` as it angers VSCode. --- src/librustc_typeck/check/pat.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index e2d0f485bdf01..d8c6438817413 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -19,6 +19,15 @@ use std::cmp; use super::report_unexpected_variant_res; +const CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ: &str = "\ +This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \ +pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \ +this type has no compile-time size. Therefore, all accesses to trait types must be through \ +pointers. If you encounter this error you should try to avoid dereferencing the pointer. + +You can read more about trait objects in the Trait Objects section of the Reference: \ +https://doc.rust-lang.org/reference/types.html#trait-objects"; + impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// `discrim_span` argument having a `Span` indicates that this pattern is part of a match /// expression arm guard, and it points to the match discriminant to add context in type errors. @@ -607,14 +616,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); err.span_label(span, format!("type `{}` cannot be dereferenced", type_str)); if self.tcx.sess.teach(&err.get_code().unwrap()) { - err.note("\ -This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \ -pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \ -this type has no compile-time size. Therefore, all accesses to trait types must be through \ -pointers. If you encounter this error you should try to avoid dereferencing the pointer. - -You can read more about trait objects in the Trait Objects section of the Reference: \ -https://doc.rust-lang.org/reference/types.html#trait-objects"); + err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ); } err.emit(); return false From d1580eef6565be5708b0668bd813e1b9abedbbb5 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 23 Aug 2019 15:31:38 +0200 Subject: [PATCH 175/618] typeck/pat.rs: extract `is_non_ref_pat`. --- src/librustc_typeck/check/pat.rs | 62 ++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index d8c6438817413..25eefbaa24c6f 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -56,34 +56,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm); - let mut path_resolution = None; - let is_non_ref_pat = match pat.node { - PatKind::Struct(..) | - PatKind::TupleStruct(..) | - PatKind::Or(_) | - PatKind::Tuple(..) | - PatKind::Box(_) | - PatKind::Range(..) | - PatKind::Slice(..) => true, - PatKind::Lit(ref lt) => { - let ty = self.check_expr(lt); - match ty.sty { - ty::Ref(..) => false, - _ => true, - } - } - PatKind::Path(ref qpath) => { - let resolution = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span); - path_resolution = Some(resolution); - match resolution.0 { - Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => false, - _ => true, - } - } - PatKind::Wild | - PatKind::Binding(..) | - PatKind::Ref(..) => false, + let path_resolution = match &pat.node { + PatKind::Path(qpath) => Some(self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span)), + _ => None, }; + + let is_non_ref_pat = self.is_non_ref_pat(pat, path_resolution.map(|(res, ..)| res)); if is_non_ref_pat { debug!("pattern is non reference pattern"); let mut exp_ty = self.resolve_type_vars_with_obligations(&expected); @@ -560,6 +538,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // subtyping. } + /// Is the pattern a "non reference pattern"? + /// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`. + fn is_non_ref_pat(&self, pat: &'tcx hir::Pat, opt_path_res: Option) -> bool { + match pat.node { + PatKind::Struct(..) | + PatKind::TupleStruct(..) | + PatKind::Or(_) | + PatKind::Tuple(..) | + PatKind::Box(_) | + PatKind::Range(..) | + PatKind::Slice(..) => true, + PatKind::Lit(ref lt) => { + let ty = self.check_expr(lt); + match ty.sty { + ty::Ref(..) => false, + _ => true, + } + } + PatKind::Path(_) => { + match opt_path_res.unwrap() { + Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => false, + _ => true, + } + } + PatKind::Wild | + PatKind::Binding(..) | + PatKind::Ref(..) => false, + } + } + fn borrow_pat_suggestion( &self, err: &mut DiagnosticBuilder<'_>, From 8b4114b0d4975bde6df41dd9c8a41e44033da221 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 23 Aug 2019 15:51:18 +0200 Subject: [PATCH 176/618] typeck/pat.rs: extract `peel_off_references` and define `def_bm` algorithm more declaratively. --- src/librustc_typeck/check/pat.rs | 121 +++++++++++++++++-------------- 1 file changed, 67 insertions(+), 54 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 25eefbaa24c6f..625c57356af38 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -48,8 +48,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn check_pat_walk( &self, pat: &'tcx hir::Pat, - mut expected: Ty<'tcx>, - mut def_bm: ty::BindingMode, + expected: Ty<'tcx>, + def_bm: ty::BindingMode, discrim_span: Option, ) { let tcx = self.tcx; @@ -62,53 +62,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let is_non_ref_pat = self.is_non_ref_pat(pat, path_resolution.map(|(res, ..)| res)); - if is_non_ref_pat { + let (expected, def_bm) = if is_non_ref_pat { debug!("pattern is non reference pattern"); - let mut exp_ty = self.resolve_type_vars_with_obligations(&expected); - - // Peel off as many `&` or `&mut` from the discriminant as possible. For example, - // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches - // the `Some(5)` which is not of type Ref. - // - // For each ampersand peeled off, update the binding mode and push the original - // type into the adjustments vector. - // - // See the examples in `ui/match-defbm*.rs`. - let mut pat_adjustments = vec![]; - while let ty::Ref(_, inner_ty, inner_mutability) = exp_ty.sty { - debug!("inspecting {:?}", exp_ty); - - debug!("current discriminant is Ref, inserting implicit deref"); - // Preserve the reference type. We'll need it later during HAIR lowering. - pat_adjustments.push(exp_ty); - - exp_ty = inner_ty; - def_bm = match def_bm { - // If default binding mode is by value, make it `ref` or `ref mut` - // (depending on whether we observe `&` or `&mut`). - ty::BindByValue(_) => - ty::BindByReference(inner_mutability), - - // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate - // the underlying value. - ty::BindByReference(hir::Mutability::MutImmutable) => - ty::BindByReference(hir::Mutability::MutImmutable), - - // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` - // (on `&`). - ty::BindByReference(hir::Mutability::MutMutable) => - ty::BindByReference(inner_mutability), - }; - } - expected = exp_ty; - - if pat_adjustments.len() > 0 { - debug!("default binding mode is now {:?}", def_bm); - self.inh.tables.borrow_mut() - .pat_adjustments_mut() - .insert(pat.hir_id, pat_adjustments); - } - } else if let PatKind::Ref(..) = pat.node { + self.peel_off_references(pat, expected, def_bm) + } else { // When you encounter a `&pat` pattern, reset to "by // value". This is so that `x` and `y` here are by value, // as they appear to be: @@ -120,12 +77,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // ``` // // See issue #46688. - def_bm = ty::BindByValue(hir::MutImmutable); - } - - // Lose mutability now that we know binding mode and discriminant type. - let def_bm = def_bm; - let expected = expected; + let def_bm = match pat.node { + PatKind::Ref(..) => ty::BindByValue(hir::MutImmutable), + _ => def_bm, + }; + (expected, def_bm) + }; let ty = match pat.node { PatKind::Wild => { @@ -568,6 +525,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Peel off as many immediately nested `& mut?` from the expected type as possible + /// and return the new expected type and binding default binding mode. + /// The adjustments vector, if non-empty is stored in a table. + fn peel_off_references( + &self, + pat: &'tcx hir::Pat, + expected: Ty<'tcx>, + mut def_bm: ty::BindingMode, + ) -> (Ty<'tcx>, ty::BindingMode) { + let mut expected = self.resolve_type_vars_with_obligations(&expected); + + // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example, + // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches + // the `Some(5)` which is not of type Ref. + // + // For each ampersand peeled off, update the binding mode and push the original + // type into the adjustments vector. + // + // See the examples in `ui/match-defbm*.rs`. + let mut pat_adjustments = vec![]; + while let ty::Ref(_, inner_ty, inner_mutability) = expected.sty { + debug!("inspecting {:?}", expected); + + debug!("current discriminant is Ref, inserting implicit deref"); + // Preserve the reference type. We'll need it later during HAIR lowering. + pat_adjustments.push(expected); + + expected = inner_ty; + def_bm = match def_bm { + // If default binding mode is by value, make it `ref` or `ref mut` + // (depending on whether we observe `&` or `&mut`). + ty::BindByValue(_) => + ty::BindByReference(inner_mutability), + + // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate + // the underlying value. + ty::BindByReference(hir::Mutability::MutImmutable) => + ty::BindByReference(hir::Mutability::MutImmutable), + + // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` + // (on `&`). + ty::BindByReference(hir::Mutability::MutMutable) => + ty::BindByReference(inner_mutability), + }; + } + + if pat_adjustments.len() > 0 { + debug!("default binding mode is now {:?}", def_bm); + self.inh.tables.borrow_mut() + .pat_adjustments_mut() + .insert(pat.hir_id, pat_adjustments); + } + + (expected, def_bm) + } + fn borrow_pat_suggestion( &self, err: &mut DiagnosticBuilder<'_>, From 3ec5d07b1d30124e85cd804a74f1b03198cce1f5 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 23 Aug 2019 15:55:35 +0200 Subject: [PATCH 177/618] typeck/pat.rs: simplify `peel_off_references`. --- src/librustc_typeck/check/pat.rs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 625c57356af38..ce033b85fce05 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -553,22 +553,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_adjustments.push(expected); expected = inner_ty; - def_bm = match def_bm { + def_bm = ty::BindByReference(match def_bm { // If default binding mode is by value, make it `ref` or `ref mut` // (depending on whether we observe `&` or `&mut`). - ty::BindByValue(_) => - ty::BindByReference(inner_mutability), - - // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate - // the underlying value. - ty::BindByReference(hir::Mutability::MutImmutable) => - ty::BindByReference(hir::Mutability::MutImmutable), - - // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` - // (on `&`). - ty::BindByReference(hir::Mutability::MutMutable) => - ty::BindByReference(inner_mutability), - }; + ty::BindByValue(_) | + // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`). + ty::BindByReference(hir::Mutability::MutMutable) => inner_mutability, + // Once a `ref`, always a `ref`. + // This is because a `& &mut` cannot mutate the underlying value. + ty::BindByReference(m @ hir::Mutability::MutImmutable) => m, + }); } if pat_adjustments.len() > 0 { From 23dc37d21d392b7f796a495f8616e32ca558d578 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 23 Aug 2019 16:06:33 +0200 Subject: [PATCH 178/618] typeck/pat.rs: extract `calc_default_binding_mode`. --- src/librustc_typeck/check/pat.rs | 57 +++++++++++++++++++------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index ce033b85fce05..a9e6cfb41a469 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -60,29 +60,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Path(qpath) => Some(self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span)), _ => None, }; - - let is_non_ref_pat = self.is_non_ref_pat(pat, path_resolution.map(|(res, ..)| res)); - let (expected, def_bm) = if is_non_ref_pat { - debug!("pattern is non reference pattern"); - self.peel_off_references(pat, expected, def_bm) - } else { - // When you encounter a `&pat` pattern, reset to "by - // value". This is so that `x` and `y` here are by value, - // as they appear to be: - // - // ``` - // match &(&22, &44) { - // (&x, &y) => ... - // } - // ``` - // - // See issue #46688. - let def_bm = match pat.node { - PatKind::Ref(..) => ty::BindByValue(hir::MutImmutable), - _ => def_bm, - }; - (expected, def_bm) - }; + let is_nrp = self.is_non_ref_pat(pat, path_resolution.map(|(res, ..)| res)); + let (expected, def_bm) = self.calc_default_binding_mode(pat, expected, def_bm, is_nrp); let ty = match pat.node { PatKind::Wild => { @@ -495,6 +474,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // subtyping. } + /// Compute the new expected type and default binding mode from the old ones + /// as well as the pattern form we are currently checking. + fn calc_default_binding_mode( + &self, + pat: &'tcx hir::Pat, + expected: Ty<'tcx>, + def_bm: ty::BindingMode, + is_non_ref_pat: bool, + ) -> (Ty<'tcx>, ty::BindingMode) { + if is_non_ref_pat { + debug!("pattern is non reference pattern"); + self.peel_off_references(pat, expected, def_bm) + } else { + // When you encounter a `&pat` pattern, reset to "by + // value". This is so that `x` and `y` here are by value, + // as they appear to be: + // + // ``` + // match &(&22, &44) { + // (&x, &y) => ... + // } + // ``` + // + // See issue #46688. + let def_bm = match pat.node { + PatKind::Ref(..) => ty::BindByValue(hir::MutImmutable), + _ => def_bm, + }; + (expected, def_bm) + } + } + /// Is the pattern a "non reference pattern"? /// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`. fn is_non_ref_pat(&self, pat: &'tcx hir::Pat, opt_path_res: Option) -> bool { From d891e70b6421e2ef48a64badf3e432059a5c4b96 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 03:52:09 +0200 Subject: [PATCH 179/618] typeck/pat.rs: extract `check_pat_lit`. --- src/librustc_typeck/check/pat.rs | 98 ++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index a9e6cfb41a469..95013f60cd6de 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -68,49 +68,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected } PatKind::Lit(ref lt) => { - // We've already computed the type above (when checking for a non-ref pat), so - // avoid computing it again. - let ty = self.node_ty(lt.hir_id); - - // Byte string patterns behave the same way as array patterns - // They can denote both statically and dynamically-sized byte arrays. - let mut pat_ty = ty; - if let hir::ExprKind::Lit(ref lt) = lt.node { - if let ast::LitKind::ByteStr(_) = lt.node { - let expected_ty = self.structurally_resolved_type(pat.span, expected); - if let ty::Ref(_, r_ty, _) = expected_ty.sty { - if let ty::Slice(_) = r_ty.sty { - pat_ty = tcx.mk_imm_ref(tcx.lifetimes.re_static, - tcx.mk_slice(tcx.types.u8)) - } - } - } - } - - // Somewhat surprising: in this case, the subtyping - // relation goes the opposite way as the other - // cases. Actually what we really want is not a subtyping - // relation at all but rather that there exists a LUB (so - // that they can be compared). However, in practice, - // constants are always scalars or strings. For scalars - // subtyping is irrelevant, and for strings `ty` is - // type is `&'static str`, so if we say that - // - // &'static str <: expected - // - // then that's equivalent to there existing a LUB. - if let Some(mut err) = self.demand_suptype_diag(pat.span, expected, pat_ty) { - err.emit_unless(discrim_span - .filter(|&s| { - // In the case of `if`- and `while`-expressions we've already checked - // that `scrutinee: bool`. We know that the pattern is `true`, - // so an error here would be a duplicate and from the wrong POV. - s.is_desugaring(DesugaringKind::CondTemporary) - }) - .is_some()); - } - - pat_ty + self.check_pat_lit(pat.span, lt, expected, discrim_span) } PatKind::Range(ref begin, ref end, _) => { let lhs_ty = self.check_expr(begin); @@ -586,6 +544,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (expected, def_bm) } + fn check_pat_lit( + &self, + span: Span, + lt: &hir::Expr, + expected: Ty<'tcx>, + discrim_span: Option, + ) -> Ty<'tcx> { + // We've already computed the type above (when checking for a non-ref pat), + // so avoid computing it again. + let ty = self.node_ty(lt.hir_id); + + // Byte string patterns behave the same way as array patterns + // They can denote both statically and dynamically-sized byte arrays. + let mut pat_ty = ty; + if let hir::ExprKind::Lit(ref lt) = lt.node { + if let ast::LitKind::ByteStr(_) = lt.node { + let expected_ty = self.structurally_resolved_type(span, expected); + if let ty::Ref(_, r_ty, _) = expected_ty.sty { + if let ty::Slice(_) = r_ty.sty { + let tcx = self.tcx; + pat_ty = tcx.mk_imm_ref( + tcx.lifetimes.re_static, + tcx.mk_slice(tcx.types.u8), + ); + } + } + } + } + + // Somewhat surprising: in this case, the subtyping relation goes the + // opposite way as the other cases. Actually what we really want is not + // a subtyping relation at all but rather that there exists a LUB + // (so that they can be compared). However, in practice, constants are + // always scalars or strings. For scalars subtyping is irrelevant, + // and for strings `ty` is type is `&'static str`, so if we say that + // + // &'static str <: expected + // + // then that's equivalent to there existing a LUB. + if let Some(mut err) = self.demand_suptype_diag(span, expected, pat_ty) { + err.emit_unless(discrim_span + .filter(|&s| { + // In the case of `if`- and `while`-expressions we've already checked + // that `scrutinee: bool`. We know that the pattern is `true`, + // so an error here would be a duplicate and from the wrong POV. + s.is_desugaring(DesugaringKind::CondTemporary) + }) + .is_some()); + } + + pat_ty + } + + fn borrow_pat_suggestion( &self, err: &mut DiagnosticBuilder<'_>, From d4afae943f642be2909c649997f663b384115237 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 03:59:15 +0200 Subject: [PATCH 180/618] typeck/pat.rs: extract `check_pat_range`. --- src/librustc_typeck/check/pat.rs | 113 +++++++++++++++++-------------- 1 file changed, 63 insertions(+), 50 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 95013f60cd6de..9693ab57bc7de 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -71,57 +71,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat_lit(pat.span, lt, expected, discrim_span) } PatKind::Range(ref begin, ref end, _) => { - let lhs_ty = self.check_expr(begin); - let rhs_ty = self.check_expr(end); - - // Check that both end-points are of numeric or char type. - let numeric_or_char = |ty: Ty<'_>| { - ty.is_numeric() - || ty.is_char() - || ty.references_error() - }; - let lhs_compat = numeric_or_char(lhs_ty); - let rhs_compat = numeric_or_char(rhs_ty); - - if !lhs_compat || !rhs_compat { - let span = if !lhs_compat && !rhs_compat { - pat.span - } else if !lhs_compat { - begin.span - } else { - end.span - }; - - let mut err = struct_span_err!( - tcx.sess, - span, - E0029, - "only char and numeric types are allowed in range patterns" - ); - err.span_label(span, "ranges require char or numeric types"); - err.note(&format!("start type: {}", self.ty_to_string(lhs_ty))); - err.note(&format!("end type: {}", self.ty_to_string(rhs_ty))); - if tcx.sess.teach(&err.get_code().unwrap()) { - err.note( - "In a match expression, only numbers and characters can be matched \ - against a range. This is because the compiler checks that the range \ - is non-empty at compile-time, and is unable to evaluate arbitrary \ - comparison functions. If you want to capture values of an orderable \ - type between two end-points, you can use a guard." - ); - } - err.emit(); - return; + match self.check_pat_range(pat.span, begin, end, expected, discrim_span) { + None => return, + Some(ty) => ty, } - - // Now that we know the types can be unified we find the unified type and use - // it to type the entire expression. - let common_type = self.resolve_vars_if_possible(&lhs_ty); - - // Subtyping doesn't matter here, as the value is some kind of scalar. - self.demand_eqtype_pat(pat.span, expected, lhs_ty, discrim_span); - self.demand_eqtype_pat(pat.span, expected, rhs_ty, discrim_span); - common_type } PatKind::Binding(ba, var_id, _, ref sub) => { let bm = if ba == hir::BindingAnnotation::Unannotated { @@ -597,6 +550,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_ty } + fn check_pat_range( + &self, + span: Span, + begin: &'tcx hir::Expr, + end: &'tcx hir::Expr, + expected: Ty<'tcx>, + discrim_span: Option, + ) -> Option> { + let lhs_ty = self.check_expr(begin); + let rhs_ty = self.check_expr(end); + + // Check that both end-points are of numeric or char type. + let numeric_or_char = |ty: Ty<'_>| { + ty.is_numeric() + || ty.is_char() + || ty.references_error() + }; + let lhs_compat = numeric_or_char(lhs_ty); + let rhs_compat = numeric_or_char(rhs_ty); + + if !lhs_compat || !rhs_compat { + let span = if !lhs_compat && !rhs_compat { + span + } else if !lhs_compat { + begin.span + } else { + end.span + }; + + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0029, + "only char and numeric types are allowed in range patterns" + ); + err.span_label(span, "ranges require char or numeric types"); + err.note(&format!("start type: {}", self.ty_to_string(lhs_ty))); + err.note(&format!("end type: {}", self.ty_to_string(rhs_ty))); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "In a match expression, only numbers and characters can be matched \ + against a range. This is because the compiler checks that the range \ + is non-empty at compile-time, and is unable to evaluate arbitrary \ + comparison functions. If you want to capture values of an orderable \ + type between two end-points, you can use a guard." + ); + } + err.emit(); + return None; + } + + // Now that we know the types can be unified we find the unified type and use + // it to type the entire expression. + let common_type = self.resolve_vars_if_possible(&lhs_ty); + + // Subtyping doesn't matter here, as the value is some kind of scalar. + self.demand_eqtype_pat(span, expected, lhs_ty, discrim_span); + self.demand_eqtype_pat(span, expected, rhs_ty, discrim_span); + Some(common_type) + } fn borrow_pat_suggestion( &self, From c16248d3a1893b985d7957bfed16ed119fdbfd6f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 04:19:16 +0200 Subject: [PATCH 181/618] typeck/pat.rs: extract `check_pat_ident`. --- src/librustc_typeck/check/pat.rs | 110 ++++++++++++++++++------------- 1 file changed, 63 insertions(+), 47 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 9693ab57bc7de..fda5d3a2ecd4a 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -77,53 +77,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } PatKind::Binding(ba, var_id, _, ref sub) => { - let bm = if ba == hir::BindingAnnotation::Unannotated { - def_bm - } else { - ty::BindingMode::convert(ba) - }; - self.inh - .tables - .borrow_mut() - .pat_binding_modes_mut() - .insert(pat.hir_id, bm); - debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); - let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty; - match bm { - ty::BindByReference(mutbl) => { - // If the binding is like - // ref x | ref const x | ref mut x - // then `x` is assigned a value of type `&M T` where M is the mutability - // and T is the expected type. - let region_var = self.next_region_var(infer::PatternRegion(pat.span)); - let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl }; - let region_ty = tcx.mk_ref(region_var, mt); - - // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is - // required. However, we use equality, which is stronger. See (*) for - // an explanation. - self.demand_eqtype_pat(pat.span, region_ty, local_ty, discrim_span); - } - // Otherwise, the type of x is the expected type `T`. - ty::BindByValue(_) => { - // As above, `T <: typeof(x)` is required, but we - // use equality, see (*) below. - self.demand_eqtype_pat(pat.span, expected, local_ty, discrim_span); - } - } - - // If there are multiple arms, make sure they all agree on - // what the type of the binding `x` ought to be. - if var_id != pat.hir_id { - let vt = self.local_ty(pat.span, var_id).decl_ty; - self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span); - } - - if let Some(ref p) = *sub { - self.check_pat_walk(&p, expected, def_bm, discrim_span); - } - - local_ty + let sub = sub.as_deref(); + self.check_pat_ident(pat, ba, var_id, sub, expected, def_bm, discrim_span) } PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => { self.check_pat_tuple_struct( @@ -611,6 +566,67 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(common_type) } + fn check_pat_ident( + &self, + pat: &hir::Pat, + ba: hir::BindingAnnotation, + var_id: hir::HirId, + sub: Option<&'tcx hir::Pat>, + expected: Ty<'tcx>, + def_bm: ty::BindingMode, + discrim_span: Option, + ) -> Ty<'tcx> { + // Determine the binding mode... + let bm = match ba { + hir::BindingAnnotation::Unannotated => def_bm, + _ => ty::BindingMode::convert(ba), + }; + // ...and store it in a side table: + self.inh + .tables + .borrow_mut() + .pat_binding_modes_mut() + .insert(pat.hir_id, bm); + + debug!("check_pat_ident: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); + + let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty; + let eq_ty = match bm { + ty::BindByReference(mutbl) => { + // If the binding is like `ref x | ref const x | ref mut x` + // then `x` is assigned a value of type `&M T` where M is the + // mutability and T is the expected type. + let region_var = self.next_region_var(infer::PatternRegion(pat.span)); + let mt = ty::TypeAndMut { ty: expected, mutbl }; + let region_ty = self.tcx.mk_ref(region_var, mt); + + // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` + // is required. However, we use equality, which is stronger. + // See (*) for an explanation. + region_ty + } + // Otherwise, the type of x is the expected type `T`. + ty::BindByValue(_) => { + // As above, `T <: typeof(x)` is required, but we use equality, see (*) below. + expected + } + }; + self.demand_eqtype_pat(pat.span, eq_ty, local_ty, discrim_span); + + // If there are multiple arms, make sure they all agree on + // what the type of the binding `x` ought to be. + if var_id != pat.hir_id { + let vt = self.local_ty(pat.span, var_id).decl_ty; + self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span); + } + + if let Some(p) = sub { + self.check_pat_walk(&p, expected, def_bm, discrim_span); + } + + local_ty + } + fn borrow_pat_suggestion( &self, err: &mut DiagnosticBuilder<'_>, From 3a51caa6485b7db6ce323cba47dfbe7c44026af5 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 04:30:03 +0200 Subject: [PATCH 182/618] typeck/pat.rs: extract `check_pat_tuple`. --- src/librustc_typeck/check/pat.rs | 103 +++++++++++++++++-------------- 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index fda5d3a2ecd4a..be128ea358e7e 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -105,48 +105,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty } PatKind::Tuple(ref elements, ddpos) => { - let mut expected_len = elements.len(); - if ddpos.is_some() { - // Require known type only when `..` is present. - if let ty::Tuple(ref tys) = - self.structurally_resolved_type(pat.span, expected).sty { - expected_len = tys.len(); - } - } - let max_len = cmp::max(expected_len, elements.len()); - - let element_tys_iter = (0..max_len).map(|_| { - Kind::from(self.next_ty_var( - // FIXME: `MiscVariable` for now -- obtaining the span and name information - // from all tuple elements isn't trivial. - TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span: pat.span, - }, - )) - }); - let element_tys = tcx.mk_substs(element_tys_iter); - let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); - if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) { - err.emit(); - // Walk subpatterns with an expected type of `err` in this case to silence - // further errors being emitted when using the bindings. #50333 - let element_tys_iter = (0..max_len).map(|_| tcx.types.err); - for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat_walk(elem, &tcx.types.err, def_bm, discrim_span); - } - tcx.mk_tup(element_tys_iter) - } else { - for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat_walk( - elem, - &element_tys[i].expect_ty(), - def_bm, - discrim_span, - ); - } - pat_ty - } + self.check_pat_tuple(pat.span, elements, ddpos, expected, def_bm, discrim_span) } PatKind::Box(ref inner) => { let inner_ty = self.next_ty_var(TypeVariableOrigin { @@ -807,7 +766,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat.hir_id); if !pat_ty.is_fn() { report_unexpected_res(res); - return self.tcx.types.err; + return tcx.types.err; } let variant = match res { @@ -833,8 +792,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span); // Type-check subpatterns. - if subpats.len() == variant.fields.len() || - subpats.len() < variant.fields.len() && ddpos.is_some() { + if subpats.len() == variant.fields.len() + || subpats.len() < variant.fields.len() && ddpos.is_some() + { let substs = match pat_ty.sty { ty::Adt(_, substs) => substs, _ => bug!("unexpected pattern type {:?}", pat_ty), @@ -861,6 +821,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_ty } + fn check_pat_tuple( + &self, + span: Span, + elements: &'tcx [P], + ddpos: Option, + expected: Ty<'tcx>, + def_bm: ty::BindingMode, + discrim_span: Option, + ) -> Ty<'tcx> { + let tcx = self.tcx; + let mut expected_len = elements.len(); + if ddpos.is_some() { + // Require known type only when `..` is present. + if let ty::Tuple(ref tys) = self.structurally_resolved_type(span, expected).sty { + expected_len = tys.len(); + } + } + let max_len = cmp::max(expected_len, elements.len()); + + let element_tys_iter = (0..max_len).map(|_| { + Kind::from(self.next_ty_var( + // FIXME: `MiscVariable` for now -- obtaining the span and name information + // from all tuple elements isn't trivial. + TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span, + }, + )) + }); + let element_tys = tcx.mk_substs(element_tys_iter); + let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); + if let Some(mut err) = self.demand_eqtype_diag(span, expected, pat_ty) { + err.emit(); + // Walk subpatterns with an expected type of `err` in this case to silence + // further errors being emitted when using the bindings. #50333 + let element_tys_iter = (0..max_len).map(|_| tcx.types.err); + for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { + self.check_pat_walk(elem, &tcx.types.err, def_bm, discrim_span); + } + tcx.mk_tup(element_tys_iter) + } else { + for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { + self.check_pat_walk( + elem, + &element_tys[i].expect_ty(), + def_bm, + discrim_span, + ); + } + pat_ty + } + } + fn check_struct_pat_fields( &self, adt_ty: Ty<'tcx>, From 3de221a862b064430bc8c5727e9e1346ad85c27e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 04:39:23 +0200 Subject: [PATCH 183/618] typeck/pat.rs: extract `check_pat_box`. --- src/librustc_typeck/check/pat.rs | 46 ++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index be128ea358e7e..f740dc73db540 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -108,23 +108,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat_tuple(pat.span, elements, ddpos, expected, def_bm, discrim_span) } PatKind::Box(ref inner) => { - let inner_ty = self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span: inner.span, - }); - let uniq_ty = tcx.mk_box(inner_ty); - - if self.check_dereferencable(pat.span, expected, &inner) { - // Here, `demand::subtype` is good enough, but I don't - // think any errors can be introduced by using - // `demand::eqtype`. - self.demand_eqtype_pat(pat.span, expected, uniq_ty, discrim_span); - self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); - uniq_ty - } else { - self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); - tcx.types.err - } + self.check_pat_box(pat.span, inner, expected, def_bm, discrim_span) } PatKind::Ref(ref inner, mutbl) => { let expected = self.shallow_resolve(expected); @@ -1047,4 +1031,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } no_field_errors } + + fn check_pat_box( + &self, + span: Span, + inner: &'tcx hir::Pat, + expected: Ty<'tcx>, + def_bm: ty::BindingMode, + discrim_span: Option, + ) -> Ty<'tcx> { + let tcx = self.tcx; + let inner_ty = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: inner.span, + }); + let uniq_ty = tcx.mk_box(inner_ty); + + if self.check_dereferencable(span, expected, &inner) { + // Here, `demand::subtype` is good enough, but I don't + // think any errors can be introduced by using + // `demand::eqtype`. + self.demand_eqtype_pat(span, expected, uniq_ty, discrim_span); + self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); + uniq_ty + } else { + self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); + tcx.types.err + } + } } From b4a4e718deee509408407a39b561461ece58355c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 04:45:59 +0200 Subject: [PATCH 184/618] typeck/pat.rs: extract `check_pat_ref`. --- src/librustc_typeck/check/pat.rs | 99 ++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 44 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index f740dc73db540..55a9360b83f19 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -111,50 +111,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat_box(pat.span, inner, expected, def_bm, discrim_span) } PatKind::Ref(ref inner, mutbl) => { - let expected = self.shallow_resolve(expected); - if self.check_dereferencable(pat.span, expected, &inner) { - // `demand::subtype` would be good enough, but using - // `eqtype` turns out to be equally general. See (*) - // below for details. - - // Take region, inner-type from expected type if we - // can, to avoid creating needless variables. This - // also helps with the bad interactions of the given - // hack detailed in (*) below. - debug!("check_pat_walk: expected={:?}", expected); - let (rptr_ty, inner_ty) = match expected.sty { - ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => { - (expected, r_ty) - } - _ => { - let inner_ty = self.next_ty_var( - TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span: inner.span, - } - ); - let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl }; - let region = self.next_region_var(infer::PatternRegion(pat.span)); - let rptr_ty = tcx.mk_ref(region, mt); - debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty); - let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty); - - // Look for a case like `fn foo(&foo: u32)` and suggest - // `fn foo(foo: &u32)` - if let Some(mut err) = err { - self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected); - err.emit(); - } - (rptr_ty, inner_ty) - } - }; - - self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); - rptr_ty - } else { - self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); - tcx.types.err - } + self.check_pat_ref(pat, inner, mutbl, expected, def_bm, discrim_span) } PatKind::Slice(ref before, ref slice, ref after) => { let expected_ty = self.structurally_resolved_type(pat.span, expected); @@ -1059,4 +1016,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.types.err } } + + fn check_pat_ref( + &self, + pat: &hir::Pat, + inner: &'tcx hir::Pat, + mutbl: hir::Mutability, + expected: Ty<'tcx>, + def_bm: ty::BindingMode, + discrim_span: Option, + ) -> Ty<'tcx> { + let tcx = self.tcx; + let expected = self.shallow_resolve(expected); + if self.check_dereferencable(pat.span, expected, &inner) { + // `demand::subtype` would be good enough, but using `eqtype` turns + // out to be equally general. See (*) below for details. + + // Take region, inner-type from expected type if we can, + // to avoid creating needless variables. This also helps with + // the bad interactions of the given hack detailed in (*) below. + debug!("check_pat_ref: expected={:?}", expected); + let (rptr_ty, inner_ty) = match expected.sty { + ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => { + (expected, r_ty) + } + _ => { + let inner_ty = self.next_ty_var( + TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: inner.span, + } + ); + let mt = ty::TypeAndMut { ty: inner_ty, mutbl }; + let region = self.next_region_var(infer::PatternRegion(pat.span)); + let rptr_ty = tcx.mk_ref(region, mt); + debug!("check_pat_ref: demanding {:?} = {:?}", expected, rptr_ty); + let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty); + + // Look for a case like `fn foo(&foo: u32)` and suggest + // `fn foo(foo: &u32)` + if let Some(mut err) = err { + self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected); + err.emit(); + } + (rptr_ty, inner_ty) + } + }; + + self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); + rptr_ty + } else { + self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); + tcx.types.err + } + } } From f09f1a71396c8e416f67ac16ca559dc1d62f05df Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 05:08:49 +0200 Subject: [PATCH 185/618] typeck/pat.rs: extract `check_pat_slice`. --- src/librustc_typeck/check/pat.rs | 159 +++++++++++++++++-------------- 1 file changed, 86 insertions(+), 73 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 55a9360b83f19..7b78474e79979 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -52,8 +52,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { def_bm: ty::BindingMode, discrim_span: Option, ) { - let tcx = self.tcx; - debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm); let path_resolution = match &pat.node { @@ -114,77 +112,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat_ref(pat, inner, mutbl, expected, def_bm, discrim_span) } PatKind::Slice(ref before, ref slice, ref after) => { - let expected_ty = self.structurally_resolved_type(pat.span, expected); - let (inner_ty, slice_ty) = match expected_ty.sty { - ty::Array(inner_ty, size) => { - if let Some(size) = size.try_eval_usize(tcx, self.param_env) { - let min_len = before.len() as u64 + after.len() as u64; - if slice.is_none() { - if min_len != size { - struct_span_err!( - tcx.sess, pat.span, E0527, - "pattern requires {} elements but array has {}", - min_len, size) - .span_label(pat.span, format!("expected {} elements", size)) - .emit(); - } - (inner_ty, tcx.types.err) - } else if let Some(rest) = size.checked_sub(min_len) { - (inner_ty, tcx.mk_array(inner_ty, rest)) - } else { - struct_span_err!(tcx.sess, pat.span, E0528, - "pattern requires at least {} elements but array has {}", - min_len, size) - .span_label(pat.span, - format!("pattern cannot match array of {} elements", size)) - .emit(); - (inner_ty, tcx.types.err) - } - } else { - struct_span_err!( - tcx.sess, - pat.span, - E0730, - "cannot pattern-match on an array without a fixed length", - ).emit(); - (inner_ty, tcx.types.err) - } - } - ty::Slice(inner_ty) => (inner_ty, expected_ty), - _ => { - if !expected_ty.references_error() { - let mut err = struct_span_err!( - tcx.sess, pat.span, E0529, - "expected an array or slice, found `{}`", - expected_ty); - if let ty::Ref(_, ty, _) = expected_ty.sty { - match ty.sty { - ty::Array(..) | ty::Slice(..) => { - err.help("the semantics of slice patterns changed \ - recently; see issue #62254"); - } - _ => {} - } - } - - err.span_label( pat.span, - format!("pattern cannot match with input type `{}`", expected_ty) - ).emit(); - } - (tcx.types.err, tcx.types.err) - } - }; - - for elt in before { - self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span); - } - if let Some(ref slice) = *slice { - self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span); - } - for elt in after { - self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span); - } - expected_ty + let slice = slice.as_deref(); + self.check_pat_slice(pat.span, before, slice, after, expected, def_bm, discrim_span) } }; @@ -1070,4 +999,88 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.types.err } } + + fn check_pat_slice( + &self, + span: Span, + before: &'tcx [P], + slice: Option<&'tcx hir::Pat>, + after: &'tcx [P], + expected: Ty<'tcx>, + def_bm: ty::BindingMode, + discrim_span: Option, + ) -> Ty<'tcx> { + let tcx = self.tcx; + let expected_ty = self.structurally_resolved_type(span, expected); + let (inner_ty, slice_ty) = match expected_ty.sty { + ty::Array(inner_ty, size) => { + if let Some(size) = size.try_eval_usize(tcx, self.param_env) { + let min_len = before.len() as u64 + after.len() as u64; + if slice.is_none() { + if min_len != size { + struct_span_err!( + tcx.sess, span, E0527, + "pattern requires {} elements but array has {}", + min_len, size + ) + .span_label(span, format!("expected {} elements", size)) + .emit(); + } + (inner_ty, tcx.types.err) + } else if let Some(rest) = size.checked_sub(min_len) { + (inner_ty, tcx.mk_array(inner_ty, rest)) + } else { + let msg = format!("pattern cannot match array of {} elements", size); + struct_span_err!( + tcx.sess, span, E0528, + "pattern requires at least {} elements but array has {}", + min_len, size + ) + .span_label(span, msg) + .emit(); + (inner_ty, tcx.types.err) + } + } else { + struct_span_err!( + tcx.sess, span, E0730, + "cannot pattern-match on an array without a fixed length", + ) + .emit(); + (inner_ty, tcx.types.err) + } + } + ty::Slice(inner_ty) => (inner_ty, expected_ty), + _ => { + if !expected_ty.references_error() { + let mut err = struct_span_err!( + tcx.sess, span, E0529, + "expected an array or slice, found `{}`", + expected_ty + ); + if let ty::Ref(_, ty, _) = expected_ty.sty { + if let ty::Array(..) | ty::Slice(..) = ty.sty { + err.help("the semantics of slice patterns changed \ + recently; see issue #62254"); + } + } + + let msg = format!("pattern cannot match with input type `{}`", expected_ty); + err.span_label(span, msg); + err.emit(); + } + (tcx.types.err, tcx.types.err) + } + }; + + for elt in before { + self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span); + } + if let Some(slice) = slice { + self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span); + } + for elt in after { + self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span); + } + expected_ty + } } From 862bb385d1dea925c179dfad996150ee1bd5b2ed Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 05:13:57 +0200 Subject: [PATCH 186/618] typeck/pat.rs: simplify `check_pat_walk`. --- src/librustc_typeck/check/pat.rs | 42 +++++++++++++++----------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 7b78474e79979..c08d777c34e3e 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -61,57 +61,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_nrp = self.is_non_ref_pat(pat, path_resolution.map(|(res, ..)| res)); let (expected, def_bm) = self.calc_default_binding_mode(pat, expected, def_bm, is_nrp); - let ty = match pat.node { - PatKind::Wild => { - expected - } - PatKind::Lit(ref lt) => { - self.check_pat_lit(pat.span, lt, expected, discrim_span) - } - PatKind::Range(ref begin, ref end, _) => { + let ty = match &pat.node { + PatKind::Wild => expected, + PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, discrim_span), + PatKind::Range(begin, end, _) => { match self.check_pat_range(pat.span, begin, end, expected, discrim_span) { None => return, Some(ty) => ty, } } - PatKind::Binding(ba, var_id, _, ref sub) => { + PatKind::Binding(ba, var_id, _, sub) => { let sub = sub.as_deref(); - self.check_pat_ident(pat, ba, var_id, sub, expected, def_bm, discrim_span) + self.check_pat_ident(pat, *ba, *var_id, sub, expected, def_bm, discrim_span) } - PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => { + PatKind::TupleStruct(qpath, subpats, ddpos) => { self.check_pat_tuple_struct( pat, qpath, - &subpats, - ddpos, + subpats, + *ddpos, expected, def_bm, discrim_span, ) } - PatKind::Path(ref qpath) => { + PatKind::Path(qpath) => { self.check_pat_path(pat, path_resolution.unwrap(), qpath, expected) } - PatKind::Struct(ref qpath, ref fields, etc) => { - self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, discrim_span) + PatKind::Struct(qpath, fields, etc) => { + self.check_pat_struct(pat, qpath, fields, *etc, expected, def_bm, discrim_span) } - PatKind::Or(ref pats) => { + PatKind::Or(pats) => { let expected_ty = self.structurally_resolved_type(pat.span, expected); for pat in pats { self.check_pat_walk(pat, expected, def_bm, discrim_span); } expected_ty } - PatKind::Tuple(ref elements, ddpos) => { - self.check_pat_tuple(pat.span, elements, ddpos, expected, def_bm, discrim_span) + PatKind::Tuple(elements, ddpos) => { + self.check_pat_tuple(pat.span, elements, *ddpos, expected, def_bm, discrim_span) } - PatKind::Box(ref inner) => { + PatKind::Box(inner) => { self.check_pat_box(pat.span, inner, expected, def_bm, discrim_span) } - PatKind::Ref(ref inner, mutbl) => { - self.check_pat_ref(pat, inner, mutbl, expected, def_bm, discrim_span) + PatKind::Ref(inner, mutbl) => { + self.check_pat_ref(pat, inner, *mutbl, expected, def_bm, discrim_span) } - PatKind::Slice(ref before, ref slice, ref after) => { + PatKind::Slice(before, slice, after) => { let slice = slice.as_deref(); self.check_pat_slice(pat.span, before, slice, after, expected, def_bm, discrim_span) } From 9d69783a46a9f6096b8c2f284876d6a68e2b6455 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 13:40:42 +0200 Subject: [PATCH 187/618] typeck/pat.rs: `(*)` -> `(note_1)` for clarity. --- src/librustc_typeck/check/pat.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index c08d777c34e3e..59244ec33ca33 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -115,12 +115,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.write_ty(pat.hir_id, ty); - // (*) In most of the cases above (literals and constants being - // the exception), we relate types using strict equality, even - // though subtyping would be sufficient. There are a few reasons - // for this, some of which are fairly subtle and which cost me - // (nmatsakis) an hour or two debugging to remember, so I thought - // I'd write them down this time. + // (note_1): In most of the cases where (note_1) is referenced + // (literals and constants being the exception), we relate types + // using strict equality, even though subtyping would be sufficient. + // There are a few reasons for this, some of which are fairly subtle + // and which cost me (nmatsakis) an hour or two debugging to remember, + // so I thought I'd write them down this time. // // 1. There is no loss of expressiveness here, though it does // cause some inconvenience. What we are saying is that the type @@ -427,12 +427,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` // is required. However, we use equality, which is stronger. - // See (*) for an explanation. + // See (note_1) for an explanation. region_ty } // Otherwise, the type of x is the expected type `T`. ty::BindByValue(_) => { - // As above, `T <: typeof(x)` is required, but we use equality, see (*) below. + // As above, `T <: typeof(x)` is required, but we use equality, see (note_1). expected } }; @@ -955,11 +955,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expected = self.shallow_resolve(expected); if self.check_dereferencable(pat.span, expected, &inner) { // `demand::subtype` would be good enough, but using `eqtype` turns - // out to be equally general. See (*) below for details. + // out to be equally general. See (note_1) for details. // Take region, inner-type from expected type if we can, // to avoid creating needless variables. This also helps with - // the bad interactions of the given hack detailed in (*) below. + // the bad interactions of the given hack detailed in (note_1). debug!("check_pat_ref: expected={:?}", expected); let (rptr_ty, inner_ty) = match expected.sty { ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => { From 365ff62fca0e1fb6511a47f5f50c4af4df250dfa Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 24 Aug 2019 18:25:34 +0100 Subject: [PATCH 188/618] Don't unwrap the result of `span_to_snippet` It can return `Err` due to macros being expanded across crates or files. --- src/librustc_mir/borrow_check/move_errors.rs | 84 ++++++++++--------- .../borrow_check/mutability_errors.rs | 4 +- .../ui/borrowck/move-error-snippets-ext.rs | 7 ++ src/test/ui/borrowck/move-error-snippets.rs | 23 +++++ .../ui/borrowck/move-error-snippets.stderr | 15 ++++ 5 files changed, 90 insertions(+), 43 deletions(-) create mode 100644 src/test/ui/borrowck/move-error-snippets-ext.rs create mode 100644 src/test/ui/borrowck/move-error-snippets.rs create mode 100644 src/test/ui/borrowck/move-error-snippets.stderr diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index 738a091b0dd76..f10ff71b15e68 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -415,20 +415,21 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { "{:?}", move_place.ty(self.body, self.infcx.tcx).ty, ); - let snippet = self.infcx.tcx.sess.source_map().span_to_snippet(span).unwrap(); - let is_option = move_ty.starts_with("std::option::Option"); - let is_result = move_ty.starts_with("std::result::Result"); - if is_option || is_result { - err.span_suggestion( - span, - &format!("consider borrowing the `{}`'s content", if is_option { - "Option" - } else { - "Result" - }), - format!("{}.as_ref()", snippet), - Applicability::MaybeIncorrect, - ); + if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { + let is_option = move_ty.starts_with("std::option::Option"); + let is_result = move_ty.starts_with("std::result::Result"); + if is_option || is_result { + err.span_suggestion( + span, + &format!("consider borrowing the `{}`'s content", if is_option { + "Option" + } else { + "Result" + }), + format!("{}.as_ref()", snippet), + Applicability::MaybeIncorrect, + ); + } } err } @@ -439,19 +440,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'a>, span: Span, ) { - let snippet = self.infcx.tcx.sess.source_map().span_to_snippet(span).unwrap(); match error { GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => { - err.span_suggestion( - span, - "consider borrowing here", - format!("&{}", snippet), - Applicability::Unspecified, - ); + if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { + err.span_suggestion( + span, + "consider borrowing here", + format!("&{}", snippet), + Applicability::Unspecified, + ); + } if binds_to.is_empty() { let place_ty = move_from.ty(self.body, self.infcx.tcx).ty; @@ -517,27 +519,27 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .. })) ) = bind_to.is_user_variable { - let pat_snippet = self.infcx.tcx.sess.source_map() - .span_to_snippet(pat_span) - .unwrap(); - if pat_snippet.starts_with('&') { - let pat_snippet = pat_snippet[1..].trim_start(); - let suggestion; - let to_remove; - if pat_snippet.starts_with("mut") - && pat_snippet["mut".len()..].starts_with(Pattern_White_Space) - { - suggestion = pat_snippet["mut".len()..].trim_start(); - to_remove = "&mut"; - } else { - suggestion = pat_snippet; - to_remove = "&"; + if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) + { + if pat_snippet.starts_with('&') { + let pat_snippet = pat_snippet[1..].trim_start(); + let suggestion; + let to_remove; + if pat_snippet.starts_with("mut") + && pat_snippet["mut".len()..].starts_with(Pattern_White_Space) + { + suggestion = pat_snippet["mut".len()..].trim_start(); + to_remove = "&mut"; + } else { + suggestion = pat_snippet; + to_remove = "&"; + } + suggestions.push(( + pat_span, + to_remove, + suggestion.to_owned(), + )); } - suggestions.push(( - pat_span, - to_remove, - suggestion.to_owned(), - )); } } } diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 937c6383be341..e7f37431e5009 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -711,8 +711,8 @@ fn annotate_struct_field( } /// If possible, suggest replacing `ref` with `ref mut`. -fn suggest_ref_mut(tcx: TyCtxt<'_>, binding_span: Span) -> Option<(String)> { - let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).unwrap(); +fn suggest_ref_mut(tcx: TyCtxt<'_>, binding_span: Span) -> Option { + let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).ok()?; if hi_src.starts_with("ref") && hi_src["ref".len()..].starts_with(Pattern_White_Space) { diff --git a/src/test/ui/borrowck/move-error-snippets-ext.rs b/src/test/ui/borrowck/move-error-snippets-ext.rs new file mode 100644 index 0000000000000..c77f6c8276e70 --- /dev/null +++ b/src/test/ui/borrowck/move-error-snippets-ext.rs @@ -0,0 +1,7 @@ +// ignore-test + +macro_rules! aaa { + ($c:ident) => {{ + let a = $c; + }} +} diff --git a/src/test/ui/borrowck/move-error-snippets.rs b/src/test/ui/borrowck/move-error-snippets.rs new file mode 100644 index 0000000000000..64f9565382886 --- /dev/null +++ b/src/test/ui/borrowck/move-error-snippets.rs @@ -0,0 +1,23 @@ +// Test that we don't ICE after trying to construct a cross-file snippet #63800. + +// compile-flags: --test + +#[macro_use] +#[path = "move-error-snippets-ext.rs"] +mod move_error_snippets_ext; + +struct A; + +macro_rules! sss { + () => { + #[test] + fn fff() { + static D: A = A; + aaa!(D); //~ ERROR cannot move + } + }; +} + +sss!(); + +fn main() {} diff --git a/src/test/ui/borrowck/move-error-snippets.stderr b/src/test/ui/borrowck/move-error-snippets.stderr new file mode 100644 index 0000000000000..77463c48591bc --- /dev/null +++ b/src/test/ui/borrowck/move-error-snippets.stderr @@ -0,0 +1,15 @@ +error[E0507]: cannot move out of static item `D` + --> $DIR/move-error-snippets.rs:16:18 + | +LL | | #[macro_use] + | |__________________^ move occurs because `D` has type `A`, which does not implement the `Copy` trait +... +LL | aaa!(D); + | __________________^ +... +LL | sss!(); + | ------- in this macro invocation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. From 65deeae76dfcb8d0aeb389bbe12ef9990caf2f6f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 13:47:07 +0200 Subject: [PATCH 189/618] typeck/pat.rs: `check_pat_top` is the entry point. This clarifies the fact that type checking patterns unconditionally starts with `BindByValue` as the default binding mode making the notion of a default binding mode internal to type checking patterns. --- src/librustc_typeck/check/_match.rs | 5 ++--- src/librustc_typeck/check/mod.rs | 10 ++-------- src/librustc_typeck/check/pat.rs | 12 +++++++++++- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 8cb365d91fa79..efc37cc04b212 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -3,7 +3,7 @@ use crate::check::coercion::CoerceMany; use rustc::hir::{self, ExprKind}; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::traits::{ObligationCause, ObligationCauseCode}; -use rustc::ty::{self, Ty}; +use rustc::ty::Ty; use syntax_pos::Span; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -59,8 +59,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut all_pats_diverge = Diverges::WarnedAlways; for p in &arm.pats { self.diverges.set(Diverges::Maybe); - let binding_mode = ty::BindingMode::BindByValue(hir::Mutability::MutImmutable); - self.check_pat_walk(&p, discrim_ty, binding_mode, Some(discrim.span)); + self.check_pat_top(&p, discrim_ty, Some(discrim.span)); all_pats_diverge &= self.diverges.get(); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a130d11a5e645..ee505b2487532 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1104,8 +1104,7 @@ fn check_fn<'a, 'tcx>( // Add formal parameters. for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { // Check the pattern. - let binding_mode = ty::BindingMode::BindByValue(hir::Mutability::MutImmutable); - fcx.check_pat_walk(&arg.pat, arg_ty, binding_mode, None); + fcx.check_pat_top(&arg.pat, arg_ty, None); // Check that argument is Sized. // The check for a non-trivial pattern is a hack to avoid duplicate warnings @@ -3631,12 +3630,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - self.check_pat_walk( - &local.pat, - t, - ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), - None, - ); + self.check_pat_top(&local.pat, t, None); let pat_ty = self.node_ty(local.pat.hir_id); if pat_ty.references_error() { self.write_ty(local.hir_id, pat_ty); diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 59244ec33ca33..fc52684b5a24c 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -29,6 +29,16 @@ You can read more about trait objects in the Trait Objects section of the Refere https://doc.rust-lang.org/reference/types.html#trait-objects"; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + pub fn check_pat_top( + &self, + pat: &'tcx hir::Pat, + expected: Ty<'tcx>, + discrim_span: Option, + ) { + let def_bm = ty::BindingMode::BindByValue(hir::Mutability::MutImmutable); + self.check_pat_walk(pat, expected, def_bm, discrim_span); + } + /// `discrim_span` argument having a `Span` indicates that this pattern is part of a match /// expression arm guard, and it points to the match discriminant to add context in type errors. /// In the following example, `discrim_span` corresponds to the `a + b` expression: @@ -45,7 +55,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// = note: expected type `usize` /// found type `std::result::Result<_, _>` /// ``` - pub fn check_pat_walk( + fn check_pat_walk( &self, pat: &'tcx hir::Pat, expected: Ty<'tcx>, From 41e8aed3cfeabba102b1576db43871aa5f27eabd Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 14:01:59 +0200 Subject: [PATCH 190/618] typeck/pat.rs: `check_pat_walk` -> `check_pat`. It's just shorter and we usually don't use the `_walk` suffix. --- src/librustc_typeck/check/pat.rs | 44 ++++++++++++++------------------ 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index fc52684b5a24c..083d41f0963a6 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { discrim_span: Option, ) { let def_bm = ty::BindingMode::BindByValue(hir::Mutability::MutImmutable); - self.check_pat_walk(pat, expected, def_bm, discrim_span); + self.check_pat(pat, expected, def_bm, discrim_span); } /// `discrim_span` argument having a `Span` indicates that this pattern is part of a match @@ -55,14 +55,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// = note: expected type `usize` /// found type `std::result::Result<_, _>` /// ``` - fn check_pat_walk( + fn check_pat( &self, pat: &'tcx hir::Pat, expected: Ty<'tcx>, def_bm: ty::BindingMode, discrim_span: Option, ) { - debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm); + debug!("check_pat(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm); let path_resolution = match &pat.node { PatKind::Path(qpath) => Some(self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span)), @@ -104,7 +104,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Or(pats) => { let expected_ty = self.structurally_resolved_type(pat.span, expected); for pat in pats { - self.check_pat_walk(pat, expected, def_bm, discrim_span); + self.check_pat(pat, expected, def_bm, discrim_span); } expected_ty } @@ -456,7 +456,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(p) = sub { - self.check_pat_walk(&p, expected, def_bm, discrim_span); + self.check_pat(&p, expected, def_bm, discrim_span); } local_ty @@ -544,7 +544,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variant_ty } else { for field in fields { - self.check_pat_walk(&field.pat, self.tcx.types.err, def_bm, discrim_span); + self.check_pat(&field.pat, self.tcx.types.err, def_bm, discrim_span); } return self.tcx.types.err; }; @@ -607,7 +607,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; let on_error = || { for pat in subpats { - self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span); + self.check_pat(&pat, tcx.types.err, def_bm, match_arm_pat_span); } }; let report_unexpected_res = |res: Res| { @@ -677,7 +677,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) { let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs); - self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span); + self.check_pat(&subpat, field_ty, def_bm, match_arm_pat_span); self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span); } @@ -734,17 +734,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // further errors being emitted when using the bindings. #50333 let element_tys_iter = (0..max_len).map(|_| tcx.types.err); for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat_walk(elem, &tcx.types.err, def_bm, discrim_span); + self.check_pat(elem, &tcx.types.err, def_bm, discrim_span); } tcx.mk_tup(element_tys_iter) } else { for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat_walk( - elem, - &element_tys[i].expect_ty(), - def_bm, - discrim_span, - ); + self.check_pat(elem, &element_tys[i].expect_ty(), def_bm, discrim_span); } pat_ty } @@ -813,7 +808,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - self.check_pat_walk(&field.pat, field_ty, def_bm, None); + self.check_pat(&field.pat, field_ty, def_bm, None); } let mut unmentioned_fields = variant.fields .iter() @@ -941,13 +936,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.check_dereferencable(span, expected, &inner) { // Here, `demand::subtype` is good enough, but I don't - // think any errors can be introduced by using - // `demand::eqtype`. + // think any errors can be introduced by using `demand::eqtype`. self.demand_eqtype_pat(span, expected, uniq_ty, discrim_span); - self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); + self.check_pat(&inner, inner_ty, def_bm, discrim_span); uniq_ty } else { - self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); + self.check_pat(&inner, tcx.types.err, def_bm, discrim_span); tcx.types.err } } @@ -998,10 +992,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); + self.check_pat(&inner, inner_ty, def_bm, discrim_span); rptr_ty } else { - self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); + self.check_pat(&inner, tcx.types.err, def_bm, discrim_span); tcx.types.err } } @@ -1079,13 +1073,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; for elt in before { - self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span); + self.check_pat(&elt, inner_ty, def_bm, discrim_span); } if let Some(slice) = slice { - self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span); + self.check_pat(&slice, slice_ty, def_bm, discrim_span); } for elt in after { - self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span); + self.check_pat(&elt, inner_ty, def_bm, discrim_span); } expected_ty } From 97986b57046a7af6d5ec1eeca7a19346131dec59 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 14:49:32 +0200 Subject: [PATCH 191/618] typeck/pat.rs: some common imports. --- src/librustc_typeck/check/pat.rs | 81 +++++++++++++++----------------- 1 file changed, 38 insertions(+), 43 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 083d41f0963a6..1f6f7901c9e6e 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1,13 +1,13 @@ use crate::check::FnCtxt; use crate::util::nodemap::FxHashMap; use errors::{Applicability, DiagnosticBuilder}; -use rustc::hir::{self, PatKind, Pat}; +use rustc::hir::{self, PatKind, Pat, HirId}; use rustc::hir::def::{Res, DefKind, CtorKind}; use rustc::hir::pat_util::EnumerateAndAdjustIterator; use rustc::hir::ptr::P; use rustc::infer; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc::ty::{self, Ty, TypeFoldable}; +use rustc::ty::{self, Ty, BindingMode, TypeFoldable}; use rustc::ty::subst::Kind; use syntax::ast; use syntax::util::lev_distance::find_best_match_for_name; @@ -29,13 +29,8 @@ You can read more about trait objects in the Trait Objects section of the Refere https://doc.rust-lang.org/reference/types.html#trait-objects"; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn check_pat_top( - &self, - pat: &'tcx hir::Pat, - expected: Ty<'tcx>, - discrim_span: Option, - ) { - let def_bm = ty::BindingMode::BindByValue(hir::Mutability::MutImmutable); + pub fn check_pat_top(&self, pat: &'tcx Pat, expected: Ty<'tcx>, discrim_span: Option) { + let def_bm = BindingMode::BindByValue(hir::Mutability::MutImmutable); self.check_pat(pat, expected, def_bm, discrim_span); } @@ -57,9 +52,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// ``` fn check_pat( &self, - pat: &'tcx hir::Pat, + pat: &'tcx Pat, expected: Ty<'tcx>, - def_bm: ty::BindingMode, + def_bm: BindingMode, discrim_span: Option, ) { debug!("check_pat(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm); @@ -179,11 +174,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// as well as the pattern form we are currently checking. fn calc_default_binding_mode( &self, - pat: &'tcx hir::Pat, + pat: &'tcx Pat, expected: Ty<'tcx>, - def_bm: ty::BindingMode, + def_bm: BindingMode, is_non_ref_pat: bool, - ) -> (Ty<'tcx>, ty::BindingMode) { + ) -> (Ty<'tcx>, BindingMode) { if is_non_ref_pat { debug!("pattern is non reference pattern"); self.peel_off_references(pat, expected, def_bm) @@ -209,7 +204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Is the pattern a "non reference pattern"? /// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`. - fn is_non_ref_pat(&self, pat: &'tcx hir::Pat, opt_path_res: Option) -> bool { + fn is_non_ref_pat(&self, pat: &'tcx Pat, opt_path_res: Option) -> bool { match pat.node { PatKind::Struct(..) | PatKind::TupleStruct(..) | @@ -242,10 +237,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// The adjustments vector, if non-empty is stored in a table. fn peel_off_references( &self, - pat: &'tcx hir::Pat, + pat: &'tcx Pat, expected: Ty<'tcx>, - mut def_bm: ty::BindingMode, - ) -> (Ty<'tcx>, ty::BindingMode) { + mut def_bm: BindingMode, + ) -> (Ty<'tcx>, BindingMode) { let mut expected = self.resolve_type_vars_with_obligations(&expected); // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example, @@ -403,18 +398,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_ident( &self, - pat: &hir::Pat, + pat: &Pat, ba: hir::BindingAnnotation, - var_id: hir::HirId, - sub: Option<&'tcx hir::Pat>, + var_id: HirId, + sub: Option<&'tcx Pat>, expected: Ty<'tcx>, - def_bm: ty::BindingMode, + def_bm: BindingMode, discrim_span: Option, ) -> Ty<'tcx> { // Determine the binding mode... let bm = match ba { hir::BindingAnnotation::Unannotated => def_bm, - _ => ty::BindingMode::convert(ba), + _ => BindingMode::convert(ba), }; // ...and store it in a side table: self.inh @@ -502,7 +497,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool { + pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &Pat) -> bool { if let PatKind::Binding(..) = inner.node { if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) { if let ty::Dynamic(..) = mt.ty.sty { @@ -530,12 +525,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_struct( &self, - pat: &'tcx hir::Pat, + pat: &'tcx Pat, qpath: &hir::QPath, fields: &'tcx [hir::FieldPat], etc: bool, expected: Ty<'tcx>, - def_bm: ty::BindingMode, + def_bm: BindingMode, discrim_span: Option, ) -> Ty<'tcx> { // Resolve the path and check the definition for errors. @@ -563,7 +558,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_path( &self, - pat: &hir::Pat, + pat: &Pat, path_resolution: (Res, Option>, &'b [hir::PathSegment]), qpath: &hir::QPath, expected: Ty<'tcx>, @@ -596,12 +591,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_tuple_struct( &self, - pat: &hir::Pat, + pat: &Pat, qpath: &hir::QPath, - subpats: &'tcx [P], + subpats: &'tcx [P], ddpos: Option, expected: Ty<'tcx>, - def_bm: ty::BindingMode, + def_bm: BindingMode, match_arm_pat_span: Option, ) -> Ty<'tcx> { let tcx = self.tcx; @@ -700,10 +695,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_tuple( &self, span: Span, - elements: &'tcx [P], + elements: &'tcx [P], ddpos: Option, expected: Ty<'tcx>, - def_bm: ty::BindingMode, + def_bm: BindingMode, discrim_span: Option, ) -> Ty<'tcx> { let tcx = self.tcx; @@ -748,12 +743,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_struct_pat_fields( &self, adt_ty: Ty<'tcx>, - pat_id: hir::HirId, + pat_id: HirId, span: Span, variant: &'tcx ty::VariantDef, fields: &'tcx [hir::FieldPat], etc: bool, - def_bm: ty::BindingMode, + def_bm: BindingMode, ) -> bool { let tcx = self.tcx; @@ -922,9 +917,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_box( &self, span: Span, - inner: &'tcx hir::Pat, + inner: &'tcx Pat, expected: Ty<'tcx>, - def_bm: ty::BindingMode, + def_bm: BindingMode, discrim_span: Option, ) -> Ty<'tcx> { let tcx = self.tcx; @@ -948,11 +943,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_ref( &self, - pat: &hir::Pat, - inner: &'tcx hir::Pat, + pat: &Pat, + inner: &'tcx Pat, mutbl: hir::Mutability, expected: Ty<'tcx>, - def_bm: ty::BindingMode, + def_bm: BindingMode, discrim_span: Option, ) -> Ty<'tcx> { let tcx = self.tcx; @@ -1003,11 +998,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_slice( &self, span: Span, - before: &'tcx [P], - slice: Option<&'tcx hir::Pat>, - after: &'tcx [P], + before: &'tcx [P], + slice: Option<&'tcx Pat>, + after: &'tcx [P], expected: Ty<'tcx>, - def_bm: ty::BindingMode, + def_bm: BindingMode, discrim_span: Option, ) -> Ty<'tcx> { let tcx = self.tcx; From 2ab69aef03f9744381e4a0cedb397c34d191f4f7 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 15:51:48 +0200 Subject: [PATCH 192/618] typeck/pat.rs: extract `new_ref_ty`. --- src/librustc_typeck/check/pat.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 1f6f7901c9e6e..ac025754ffbae 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -426,9 +426,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the binding is like `ref x | ref const x | ref mut x` // then `x` is assigned a value of type `&M T` where M is the // mutability and T is the expected type. - let region_var = self.next_region_var(infer::PatternRegion(pat.span)); - let mt = ty::TypeAndMut { ty: expected, mutbl }; - let region_ty = self.tcx.mk_ref(region_var, mt); + let region_ty = self.new_ref_ty(pat.span, mutbl, expected); // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` // is required. However, we use equality, which is stronger. @@ -971,9 +969,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: inner.span, } ); - let mt = ty::TypeAndMut { ty: inner_ty, mutbl }; - let region = self.next_region_var(infer::PatternRegion(pat.span)); - let rptr_ty = tcx.mk_ref(region, mt); + let rptr_ty = self.new_ref_ty(pat.span, mutbl, inner_ty); debug!("check_pat_ref: demanding {:?} = {:?}", expected, rptr_ty); let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty); @@ -995,6 +991,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Create a reference type with a fresh region variable. + fn new_ref_ty(&self, span: Span, mutbl: hir::Mutability, ty: Ty<'tcx>) -> Ty<'tcx> { + let region = self.next_region_var(infer::PatternRegion(span)); + let mt = ty::TypeAndMut { ty, mutbl }; + self.tcx.mk_ref(region, mt) + } + fn check_pat_slice( &self, span: Span, From 729fbeb70b9aabc6df58f0cc3601402b44663cf2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 16:42:15 +0200 Subject: [PATCH 193/618] typeck/pat.rs: extract diagnostics from `check_pat_slice`. --- src/librustc_typeck/check/pat.rs | 95 ++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 41 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index ac025754ffbae..ff1500e6bd877 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1012,59 +1012,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expected_ty = self.structurally_resolved_type(span, expected); let (inner_ty, slice_ty) = match expected_ty.sty { ty::Array(inner_ty, size) => { - if let Some(size) = size.try_eval_usize(tcx, self.param_env) { + let slice_ty = if let Some(size) = size.try_eval_usize(tcx, self.param_env) { let min_len = before.len() as u64 + after.len() as u64; if slice.is_none() { if min_len != size { - struct_span_err!( - tcx.sess, span, E0527, - "pattern requires {} elements but array has {}", - min_len, size - ) - .span_label(span, format!("expected {} elements", size)) - .emit(); + self.error_scrutinee_inconsistent_length(span, min_len, size) } - (inner_ty, tcx.types.err) + tcx.types.err } else if let Some(rest) = size.checked_sub(min_len) { - (inner_ty, tcx.mk_array(inner_ty, rest)) + tcx.mk_array(inner_ty, rest) } else { - let msg = format!("pattern cannot match array of {} elements", size); - struct_span_err!( - tcx.sess, span, E0528, - "pattern requires at least {} elements but array has {}", - min_len, size - ) - .span_label(span, msg) - .emit(); - (inner_ty, tcx.types.err) + self.error_scrutinee_with_rest_inconsistent_length(span, min_len, size); + tcx.types.err } } else { - struct_span_err!( - tcx.sess, span, E0730, - "cannot pattern-match on an array without a fixed length", - ) - .emit(); - (inner_ty, tcx.types.err) - } + self.error_scrutinee_unfixed_length(span); + tcx.types.err + }; + (inner_ty, slice_ty) } ty::Slice(inner_ty) => (inner_ty, expected_ty), _ => { if !expected_ty.references_error() { - let mut err = struct_span_err!( - tcx.sess, span, E0529, - "expected an array or slice, found `{}`", - expected_ty - ); - if let ty::Ref(_, ty, _) = expected_ty.sty { - if let ty::Array(..) | ty::Slice(..) = ty.sty { - err.help("the semantics of slice patterns changed \ - recently; see issue #62254"); - } - } - - let msg = format!("pattern cannot match with input type `{}`", expected_ty); - err.span_label(span, msg); - err.emit(); + self.error_expected_array_or_slice(span, expected_ty); } (tcx.types.err, tcx.types.err) } @@ -1081,4 +1051,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } expected_ty } + + fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) { + struct_span_err!( + self.tcx.sess, span, E0527, + "pattern requires {} elements but array has {}", + min_len, size + ) + .span_label(span, format!("expected {} elements", size)) + .emit(); + } + + fn error_scrutinee_with_rest_inconsistent_length(&self, span: Span, min_len: u64, size: u64) { + struct_span_err!( + self.tcx.sess, span, E0528, + "pattern requires at least {} elements but array has {}", + min_len, size + ) + .span_label(span, format!("pattern cannot match array of {} elements", size)) + .emit(); + } + + fn error_scrutinee_unfixed_length(&self, span: Span) { + struct_span_err!( + self.tcx.sess, span, E0730, + "cannot pattern-match on an array without a fixed length", + ) + .emit(); + } + + fn error_expected_array_or_slice(&self, span: Span, expected_ty: Ty<'tcx>) { + let mut err = struct_span_err!( + self.tcx.sess, span, E0529, + "expected an array or slice, found `{}`", + expected_ty + ); + if let ty::Ref(_, ty, _) = expected_ty.sty { + if let ty::Array(..) | ty::Slice(..) = ty.sty { + err.help("the semantics of slice patterns changed recently; see issue #62254"); + } + } + err.span_label(span, format!("pattern cannot match with input type `{}`", expected_ty)); + err.emit(); + } } From 25f605ae99b1ac3565fc0bb65d97083f39444d60 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 17:34:15 +0200 Subject: [PATCH 194/618] typeck/pat.rs: extract `error_field_already_bound`. --- src/librustc_typeck/check/pat.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index ff1500e6bd877..0aed814b2da9b 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -774,14 +774,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ident = tcx.adjust_ident(field.ident, variant.def_id); let field_ty = match used_fields.entry(ident) { Occupied(occupied) => { - struct_span_err!(tcx.sess, span, E0025, - "field `{}` bound multiple times \ - in the pattern", - field.ident) - .span_label(span, - format!("multiple uses of `{}` in pattern", field.ident)) - .span_label(*occupied.get(), format!("first use of `{}`", field.ident)) - .emit(); + self.error_field_already_bound(span, field.ident, *occupied.get()); no_field_errors = false; tcx.types.err } @@ -912,6 +905,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { no_field_errors } + fn error_field_already_bound(&self, span: Span, ident: ast::Ident, other_field: Span) { + struct_span_err!( + self.tcx.sess, span, E0025, + "field `{}` bound multiple times in the pattern", + ident + ) + .span_label(span, format!("multiple uses of `{}` in pattern", ident)) + .span_label(other_field, format!("first use of `{}`", ident)) + .emit(); + } + fn check_pat_box( &self, span: Span, From ba2a784c38c5e87e746457645184d4dec957941f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 17:44:43 +0200 Subject: [PATCH 195/618] typeck/pat.rs: extract `error_unmentioned_fields`. --- src/librustc_typeck/check/pat.rs | 65 ++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 0aed814b2da9b..265f032179bf6 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -873,34 +873,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if etc { tcx.sess.span_err(span, "`..` cannot be used in union patterns"); } - } else if !etc { - if unmentioned_fields.len() > 0 { - let field_names = if unmentioned_fields.len() == 1 { - format!("field `{}`", unmentioned_fields[0]) - } else { - format!("fields {}", - unmentioned_fields.iter() - .map(|name| format!("`{}`", name)) - .collect::>() - .join(", ")) - }; - let mut diag = struct_span_err!(tcx.sess, span, E0027, - "pattern does not mention {}", - field_names); - diag.span_label(span, format!("missing {}", field_names)); - if variant.ctor_kind == CtorKind::Fn { - diag.note("trying to match a tuple variant with a struct variant pattern"); - } - if tcx.sess.teach(&diag.get_code().unwrap()) { - diag.note( - "This error indicates that a pattern for a struct fails to specify a \ - sub-pattern for every one of the struct's fields. Ensure that each field \ - from the struct's definition is mentioned in the pattern, or use `..` to \ - ignore unwanted fields." - ); - } - diag.emit(); - } + } else if !etc && unmentioned_fields.len() > 0 { + self.error_unmentioned_fields(span, unmentioned_fields, variant); } no_field_errors } @@ -916,6 +890,41 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit(); } + fn error_unmentioned_fields( + &self, + span: Span, + unmentioned_fields: Vec, + variant: &ty::VariantDef, + ) { + let field_names = if unmentioned_fields.len() == 1 { + format!("field `{}`", unmentioned_fields[0]) + } else { + let fields = unmentioned_fields.iter() + .map(|name| format!("`{}`", name)) + .collect::>() + .join(", "); + format!("fields {}", fields) + }; + let mut diag = struct_span_err!( + self.tcx.sess, span, E0027, + "pattern does not mention {}", + field_names + ); + diag.span_label(span, format!("missing {}", field_names)); + if variant.ctor_kind == CtorKind::Fn { + diag.note("trying to match a tuple variant with a struct variant pattern"); + } + if self.tcx.sess.teach(&diag.get_code().unwrap()) { + diag.note( + "This error indicates that a pattern for a struct fails to specify a \ + sub-pattern for every one of the struct's fields. Ensure that each field \ + from the struct's definition is mentioned in the pattern, or use `..` to \ + ignore unwanted fields." + ); + } + diag.emit(); + } + fn check_pat_box( &self, span: Span, From 5fbfcd88728a2c2c6400868fbd19117527d81e0b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 17:54:33 +0200 Subject: [PATCH 196/618] typeck/pat.rs: extract `error_inexistent_fields`. --- src/librustc_typeck/check/pat.rs | 130 ++++++++++++++++++------------- 1 file changed, 74 insertions(+), 56 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 265f032179bf6..f0ecbd674c07d 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -796,66 +796,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat(&field.pat, field_ty, def_bm, None); } + let mut unmentioned_fields = variant.fields .iter() .map(|field| field.ident.modern()) .filter(|ident| !used_fields.contains_key(&ident)) .collect::>(); - if inexistent_fields.len() > 0 && !variant.recovered { - let (field_names, t, plural) = if inexistent_fields.len() == 1 { - (format!("a field named `{}`", inexistent_fields[0]), "this", "") - } else { - (format!("fields named {}", - inexistent_fields.iter() - .map(|ident| format!("`{}`", ident)) - .collect::>() - .join(", ")), "these", "s") - }; - let spans = inexistent_fields.iter().map(|ident| ident.span).collect::>(); - let mut err = struct_span_err!(tcx.sess, - spans, - E0026, - "{} `{}` does not have {}", - kind_name, - tcx.def_path_str(variant.def_id), - field_names); - if let Some(ident) = inexistent_fields.last() { - err.span_label(ident.span, - format!("{} `{}` does not have {} field{}", - kind_name, - tcx.def_path_str(variant.def_id), - t, - plural)); - if plural == "" { - let input = unmentioned_fields.iter().map(|field| &field.name); - let suggested_name = - find_best_match_for_name(input, &ident.as_str(), None); - if let Some(suggested_name) = suggested_name { - err.span_suggestion( - ident.span, - "a field with a similar name exists", - suggested_name.to_string(), - Applicability::MaybeIncorrect, - ); - // we don't want to throw `E0027` in case we have thrown `E0026` for them - unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str()); - } - } - } - if tcx.sess.teach(&err.get_code().unwrap()) { - err.note( - "This error indicates that a struct pattern attempted to \ - extract a non-existent field from a struct. Struct fields \ - are identified by the name used before the colon : so struct \ - patterns should resemble the declaration of the struct type \ - being matched.\n\n\ - If you are using shorthand field patterns but want to refer \ - to the struct field by a different name, you should rename \ - it explicitly." - ); - } - err.emit(); + if inexistent_fields.len() > 0 && !variant.recovered { + self.error_inexistent_fields( + kind_name, + &inexistent_fields, + &mut unmentioned_fields, + variant + ); } // Require `..` if struct has non_exhaustive attribute. @@ -874,7 +828,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.sess.span_err(span, "`..` cannot be used in union patterns"); } } else if !etc && unmentioned_fields.len() > 0 { - self.error_unmentioned_fields(span, unmentioned_fields, variant); + self.error_unmentioned_fields(span, &unmentioned_fields, variant); } no_field_errors } @@ -890,10 +844,74 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit(); } + fn error_inexistent_fields( + &self, + kind_name: &str, + inexistent_fields: &[ast::Ident], + unmentioned_fields: &mut Vec, + variant: &ty::VariantDef, + ) { + let tcx = self.tcx; + let (field_names, t, plural) = if inexistent_fields.len() == 1 { + (format!("a field named `{}`", inexistent_fields[0]), "this", "") + } else { + (format!("fields named {}", + inexistent_fields.iter() + .map(|ident| format!("`{}`", ident)) + .collect::>() + .join(", ")), "these", "s") + }; + let spans = inexistent_fields.iter().map(|ident| ident.span).collect::>(); + let mut err = struct_span_err!(tcx.sess, + spans, + E0026, + "{} `{}` does not have {}", + kind_name, + tcx.def_path_str(variant.def_id), + field_names); + if let Some(ident) = inexistent_fields.last() { + err.span_label(ident.span, + format!("{} `{}` does not have {} field{}", + kind_name, + tcx.def_path_str(variant.def_id), + t, + plural)); + if plural == "" { + let input = unmentioned_fields.iter().map(|field| &field.name); + let suggested_name = + find_best_match_for_name(input, &ident.as_str(), None); + if let Some(suggested_name) = suggested_name { + err.span_suggestion( + ident.span, + "a field with a similar name exists", + suggested_name.to_string(), + Applicability::MaybeIncorrect, + ); + + // we don't want to throw `E0027` in case we have thrown `E0026` for them + unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str()); + } + } + } + if tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "This error indicates that a struct pattern attempted to \ + extract a non-existent field from a struct. Struct fields \ + are identified by the name used before the colon : so struct \ + patterns should resemble the declaration of the struct type \ + being matched.\n\n\ + If you are using shorthand field patterns but want to refer \ + to the struct field by a different name, you should rename \ + it explicitly." + ); + } + err.emit(); + } + fn error_unmentioned_fields( &self, span: Span, - unmentioned_fields: Vec, + unmentioned_fields: &[ast::Ident], variant: &ty::VariantDef, ) { let field_names = if unmentioned_fields.len() == 1 { From a4b3dbe4c1b225b4b911438861e98e4b1aa70183 Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Tue, 23 Jul 2019 10:30:13 +0100 Subject: [PATCH 197/618] Improve the documentation for std::hint::black_box. --- src/libcore/hint.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index 519212bb6cb4e..3aba07f882d97 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -104,11 +104,19 @@ pub fn spin_loop() { } } -/// A function that is opaque to the optimizer, to allow benchmarks to -/// pretend to use outputs to assist in avoiding dead-code -/// elimination. +/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what +/// `black_box` could do. /// -/// This function is a no-op, and does not even read from `dummy`. +/// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html +/// +/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can +/// use `x` in any possible valid way that Rust code is allowed to without introducing undefined +/// behavior in the calling code. This property makes `black_box` useful for writing code in which +/// certain optimizations are not desired, such as benchmarks. +/// +/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The +/// extent to which it can block optimisations may vary depending upon the platform and code-gen +/// backend used. Programs cannot rely on `black_box` for *correctness* in any way. #[inline] #[unstable(feature = "test", issue = "27812")] #[allow(unreachable_code)] // this makes #[cfg] a bit easier below. From 5299d8a191246cf55c8ead7b8be68c8aeca78d35 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 15:28:14 +0200 Subject: [PATCH 198/618] parser: extract `ban_unexpected_or_or`. --- src/libsyntax/parse/parser/pat.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 8cfa6abbe6270..4cda14907e46c 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -31,14 +31,7 @@ impl<'a> Parser<'a> { pats.push(self.parse_top_level_pat()?); if self.token == token::OrOr { - self.struct_span_err(self.token.span, "unexpected token `||` after pattern") - .span_suggestion( - self.token.span, - "use a single `|` to specify multiple patterns", - "|".to_owned(), - Applicability::MachineApplicable - ) - .emit(); + self.ban_unexpected_or_or(); self.bump(); } else if self.eat(&token::BinOp(token::Or)) { // This is a No-op. Continue the loop to parse the next @@ -49,6 +42,17 @@ impl<'a> Parser<'a> { }; } + fn ban_unexpected_or_or(&mut self) { + self.struct_span_err(self.token.span, "unexpected token `||` after pattern") + .span_suggestion( + self.token.span, + "use a single `|` to specify multiple patterns", + "|".to_owned(), + Applicability::MachineApplicable + ) + .emit(); + } + /// A wrapper around `parse_pat` with some special error handling for the /// "top-level" patterns in a match arm, `for` loop, `let`, &c. (in contrast /// to subpatterns within such). @@ -116,9 +120,7 @@ impl<'a> Parser<'a> { let mut pats = vec![first_pat]; while self.eat(&token::BinOp(token::Or)) { - pats.push(self.parse_pat_with_range_pat( - true, expected - )?); + pats.push(self.parse_pat_with_range_pat(true, expected)?); } let or_pattern_span = lo.to(self.prev_span); From 1ba7550a8996cffc07c6af89dcd6e1cdc63b24cf Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 15:31:34 +0200 Subject: [PATCH 199/618] parser: type alias `type Expected = Option<&'static str>;`. --- src/libsyntax/parse/parser/pat.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 4cda14907e46c..36d5ed5c4aa64 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -12,12 +12,11 @@ use crate::ThinVec; use errors::{Applicability, DiagnosticBuilder}; +type Expected = Option<&'static str>; + impl<'a> Parser<'a> { /// Parses a pattern. - pub fn parse_pat( - &mut self, - expected: Option<&'static str> - ) -> PResult<'a, P> { + pub fn parse_pat(&mut self, expected: Expected) -> PResult<'a, P> { self.parse_pat_with_range_pat(true, expected) } @@ -105,7 +104,7 @@ impl<'a> Parser<'a> { } /// Parses a pattern, that may be a or-pattern (e.g. `Some(Foo | Bar)`). - fn parse_pat_with_or(&mut self, expected: Option<&'static str>) -> PResult<'a, P> { + fn parse_pat_with_or(&mut self, expected: Expected) -> PResult<'a, P> { // Parse the first pattern. let first_pat = self.parse_pat(expected)?; @@ -135,7 +134,7 @@ impl<'a> Parser<'a> { fn parse_pat_with_range_pat( &mut self, allow_range_pat: bool, - expected: Option<&'static str>, + expected: Expected, ) -> PResult<'a, P> { maybe_recover_from_interpolated_ty_qpath!(self, true); maybe_whole!(self, NtPat, |x| x); @@ -257,7 +256,7 @@ impl<'a> Parser<'a> { } /// Parse `&pat` / `&mut pat`. - fn parse_pat_deref(&mut self, expected: Option<&'static str>) -> PResult<'a, PatKind> { + fn parse_pat_deref(&mut self, expected: Expected) -> PResult<'a, PatKind> { self.expect_and()?; let mutbl = self.parse_mutability(); @@ -363,7 +362,7 @@ impl<'a> Parser<'a> { fn fatal_unexpected_non_pat( &mut self, mut err: DiagnosticBuilder<'a>, - expected: Option<&'static str>, + expected: Expected, ) -> PResult<'a, P> { self.cancel(&mut err); From 0bbea47794d28f78cf313fde475a35a83d0e9842 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 15:45:44 +0200 Subject: [PATCH 200/618] parser: refactor `parse_pat_with_or` + use it in [p0, p1, ..] pats. --- src/libsyntax/parse/parser/pat.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 36d5ed5c4aa64..ca5a9f2a5a882 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -104,12 +104,12 @@ impl<'a> Parser<'a> { } /// Parses a pattern, that may be a or-pattern (e.g. `Some(Foo | Bar)`). - fn parse_pat_with_or(&mut self, expected: Expected) -> PResult<'a, P> { + fn parse_pat_with_or(&mut self, expected: Expected, gate_or: bool) -> PResult<'a, P> { // Parse the first pattern. let first_pat = self.parse_pat(expected)?; - // If the next token is not a `|`, this is not an or-pattern and - // we should exit here. + // If the next token is not a `|`, + // this is not an or-pattern and we should exit here. if !self.check(&token::BinOp(token::Or)) { return Ok(first_pat) } @@ -124,7 +124,10 @@ impl<'a> Parser<'a> { let or_pattern_span = lo.to(self.prev_span); - self.sess.gated_spans.or_patterns.borrow_mut().push(or_pattern_span); + // Feature gate the or-pattern if instructed: + if gate_or { + self.sess.gated_spans.or_patterns.borrow_mut().push(or_pattern_span); + } Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats))) } @@ -145,7 +148,11 @@ impl<'a> Parser<'a> { token::OpenDelim(token::Paren) => self.parse_pat_tuple_or_parens()?, token::OpenDelim(token::Bracket) => { // Parse `[pat, pat,...]` as a slice pattern. - PatKind::Slice(self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat(None))?.0) + let (pats, _) = self.parse_delim_comma_seq( + token::Bracket, + |p| p.parse_pat_with_or(None, true), + )?; + PatKind::Slice(pats) } token::DotDot => { self.bump(); @@ -273,7 +280,7 @@ impl<'a> Parser<'a> { /// Parse a tuple or parenthesis pattern. fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> { let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| { - p.parse_pat_with_or(None) + p.parse_pat_with_or(None, true) })?; // Here, `(pat,)` is a tuple pattern. @@ -517,7 +524,7 @@ impl<'a> Parser<'a> { err.span_label(self.token.span, msg); return Err(err); } - let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or(None))?; + let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or(None, true))?; Ok(PatKind::TupleStruct(path, fields)) } @@ -661,7 +668,7 @@ impl<'a> Parser<'a> { // Parsing a pattern of the form "fieldname: pat" let fieldname = self.parse_field_name()?; self.bump(); - let pat = self.parse_pat_with_or(None)?; + let pat = self.parse_pat_with_or(None, true)?; hi = pat.span; (pat, fieldname, false) } else { From 30b841dce0a1c0f26588f4b5791a9eda1c1f42f4 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 16:35:19 +0200 Subject: [PATCH 201/618] parser: improve or-patterns recovery. --- src/libsyntax/parse/parser/pat.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index ca5a9f2a5a882..e52d0bc9d483b 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -110,18 +110,25 @@ impl<'a> Parser<'a> { // If the next token is not a `|`, // this is not an or-pattern and we should exit here. - if !self.check(&token::BinOp(token::Or)) { + if !self.check(&token::BinOp(token::Or)) && self.token != token::OrOr { return Ok(first_pat) } let lo = first_pat.span; - let mut pats = vec![first_pat]; + loop { + if self.token == token::OrOr { + // Found `||`; Recover and pretend we parsed `|`. + self.ban_unexpected_or_or(); + self.bump(); + } else if self.eat(&token::BinOp(token::Or)) { + // Found `|`. Working towards a proper or-pattern. + } else { + break; + } - while self.eat(&token::BinOp(token::Or)) { pats.push(self.parse_pat_with_range_pat(true, expected)?); } - let or_pattern_span = lo.to(self.prev_span); // Feature gate the or-pattern if instructed: From d34ee769b061975bf637776052179058c1f00bd7 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 16:45:08 +0200 Subject: [PATCH 202/618] parser: move `multiple-pattern-typo` -> `or-patterns` directory. --- .../ui/{did_you_mean => or-patterns}/multiple-pattern-typo.rs | 0 .../ui/{did_you_mean => or-patterns}/multiple-pattern-typo.stderr | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{did_you_mean => or-patterns}/multiple-pattern-typo.rs (100%) rename src/test/ui/{did_you_mean => or-patterns}/multiple-pattern-typo.stderr (100%) diff --git a/src/test/ui/did_you_mean/multiple-pattern-typo.rs b/src/test/ui/or-patterns/multiple-pattern-typo.rs similarity index 100% rename from src/test/ui/did_you_mean/multiple-pattern-typo.rs rename to src/test/ui/or-patterns/multiple-pattern-typo.rs diff --git a/src/test/ui/did_you_mean/multiple-pattern-typo.stderr b/src/test/ui/or-patterns/multiple-pattern-typo.stderr similarity index 100% rename from src/test/ui/did_you_mean/multiple-pattern-typo.stderr rename to src/test/ui/or-patterns/multiple-pattern-typo.stderr From 5f57feec0a3038ffc085ba897717b4ffd75445ee Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 16:52:49 +0200 Subject: [PATCH 203/618] parser: `multiple-pattern-typo`: cover more or-pattern places. --- .../ui/or-patterns/multiple-pattern-typo.rs | 33 +++++++++++++++ .../or-patterns/multiple-pattern-typo.stderr | 42 ++++++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/test/ui/or-patterns/multiple-pattern-typo.rs b/src/test/ui/or-patterns/multiple-pattern-typo.rs index 14ad33d53b08c..5d1da56674ba4 100644 --- a/src/test/ui/or-patterns/multiple-pattern-typo.rs +++ b/src/test/ui/or-patterns/multiple-pattern-typo.rs @@ -1,7 +1,40 @@ +#![feature(or_patterns)] +//~^ WARN the feature `or_patterns` is incomplete and may cause the compiler to crash + fn main() { let x = 3; + match x { 1 | 2 || 3 => (), //~ ERROR unexpected token `||` after pattern _ => (), } + + match x { + (1 | 2 || 3) => (), //~ ERROR unexpected token `||` after pattern + _ => (), + } + + match (x,) { + (1 | 2 || 3,) => (), //~ ERROR unexpected token `||` after pattern + _ => (), + } + + struct TS(u8); + + match TS(x) { + TS(1 | 2 || 3) => (), //~ ERROR unexpected token `||` after pattern + _ => (), + } + + struct NS { f: u8 } + + match (NS { f: x }) { + NS { f: 1 | 2 || 3 } => (), //~ ERROR unexpected token `||` after pattern + _ => (), + } + + match [x] { + [1 | 2 || 3] => (), //~ ERROR unexpected token `||` after pattern + _ => (), + } } diff --git a/src/test/ui/or-patterns/multiple-pattern-typo.stderr b/src/test/ui/or-patterns/multiple-pattern-typo.stderr index a29fa584b2924..97f3470a54aa2 100644 --- a/src/test/ui/or-patterns/multiple-pattern-typo.stderr +++ b/src/test/ui/or-patterns/multiple-pattern-typo.stderr @@ -1,8 +1,46 @@ error: unexpected token `||` after pattern - --> $DIR/multiple-pattern-typo.rs:4:15 + --> $DIR/multiple-pattern-typo.rs:8:15 | LL | 1 | 2 || 3 => (), | ^^ help: use a single `|` to specify multiple patterns: `|` -error: aborting due to previous error +error: unexpected token `||` after pattern + --> $DIR/multiple-pattern-typo.rs:13:16 + | +LL | (1 | 2 || 3) => (), + | ^^ help: use a single `|` to specify multiple patterns: `|` + +error: unexpected token `||` after pattern + --> $DIR/multiple-pattern-typo.rs:18:16 + | +LL | (1 | 2 || 3,) => (), + | ^^ help: use a single `|` to specify multiple patterns: `|` + +error: unexpected token `||` after pattern + --> $DIR/multiple-pattern-typo.rs:25:18 + | +LL | TS(1 | 2 || 3) => (), + | ^^ help: use a single `|` to specify multiple patterns: `|` + +error: unexpected token `||` after pattern + --> $DIR/multiple-pattern-typo.rs:32:23 + | +LL | NS { f: 1 | 2 || 3 } => (), + | ^^ help: use a single `|` to specify multiple patterns: `|` + +error: unexpected token `||` after pattern + --> $DIR/multiple-pattern-typo.rs:37:16 + | +LL | [1 | 2 || 3] => (), + | ^^ help: use a single `|` to specify multiple patterns: `|` + +warning: the feature `or_patterns` is incomplete and may cause the compiler to crash + --> $DIR/multiple-pattern-typo.rs:1:12 + | +LL | #![feature(or_patterns)] + | ^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to 6 previous errors From f852c7ce1c6f55bc816d90c6e7f8e9205bb6c6f2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 16:55:52 +0200 Subject: [PATCH 204/618] parser: simplify `parse_pat_with_or`. --- src/libsyntax/parse/parser/pat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index e52d0bc9d483b..89688a287a7f3 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -127,7 +127,7 @@ impl<'a> Parser<'a> { break; } - pats.push(self.parse_pat_with_range_pat(true, expected)?); + pats.push(self.parse_pat(expected)?); } let or_pattern_span = lo.to(self.prev_span); From 21d9b85c0da1b639f8d8b3585e08759f96d1c286 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 17:11:12 +0200 Subject: [PATCH 205/618] parser: extract `maybe_recover_unexpected_comma`. --- src/libsyntax/parse/parser/pat.rs | 67 +++++++++++++++++-------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 89688a287a7f3..588e5aef8a2f4 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -57,40 +57,45 @@ impl<'a> Parser<'a> { /// to subpatterns within such). pub(super) fn parse_top_level_pat(&mut self) -> PResult<'a, P> { let pat = self.parse_pat(None)?; - if self.token == token::Comma { - // An unexpected comma after a top-level pattern is a clue that the - // user (perhaps more accustomed to some other language) forgot the - // parentheses in what should have been a tuple pattern; return a - // suggestion-enhanced error here rather than choking on the comma - // later. - let comma_span = self.token.span; - self.bump(); - if let Err(mut err) = self.skip_pat_list() { - // We didn't expect this to work anyway; we just wanted - // to advance to the end of the comma-sequence so we know - // the span to suggest parenthesizing - err.cancel(); - } - let seq_span = pat.span.to(self.prev_span); - let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); - if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { - err.span_suggestion( - seq_span, - "try adding parentheses to match on a tuple..", - format!("({})", seq_snippet), - Applicability::MachineApplicable - ).span_suggestion( - seq_span, - "..or a vertical bar to match on multiple alternatives", - format!("{}", seq_snippet.replace(",", " |")), - Applicability::MachineApplicable - ); - } - return Err(err); - } + self.maybe_recover_unexpected_comma(pat.span)?; Ok(pat) } + fn maybe_recover_unexpected_comma(&mut self, lo: Span) -> PResult<'a, ()> { + if self.token != token::Comma { + return Ok(()); + } + + // An unexpected comma after a top-level pattern is a clue that the + // user (perhaps more accustomed to some other language) forgot the + // parentheses in what should have been a tuple pattern; return a + // suggestion-enhanced error here rather than choking on the comma later. + let comma_span = self.token.span; + self.bump(); + if let Err(mut err) = self.skip_pat_list() { + // We didn't expect this to work anyway; we just wanted to advance to the + // end of the comma-sequence so we know the span to suggest parenthesizing. + err.cancel(); + } + let seq_span = lo.to(self.prev_span); + let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); + if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { + err.span_suggestion( + seq_span, + "try adding parentheses to match on a tuple..", + format!("({})", seq_snippet), + Applicability::MachineApplicable + ) + .span_suggestion( + seq_span, + "..or a vertical bar to match on multiple alternatives", + format!("{}", seq_snippet.replace(",", " |")), + Applicability::MachineApplicable + ); + } + Err(err) + } + /// Parse and throw away a parentesized comma separated /// sequence of patterns until `)` is reached. fn skip_pat_list(&mut self) -> PResult<'a, ()> { From a4a34ab62df777e885cac71ab171225b2cd1a812 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 17:44:27 +0200 Subject: [PATCH 206/618] parser: integrate `maybe_recover_unexpected_comma` in `parse_pat_with_or`. --- src/libsyntax/parse/parser/pat.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 588e5aef8a2f4..b2a026d0071e4 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -57,12 +57,12 @@ impl<'a> Parser<'a> { /// to subpatterns within such). pub(super) fn parse_top_level_pat(&mut self) -> PResult<'a, P> { let pat = self.parse_pat(None)?; - self.maybe_recover_unexpected_comma(pat.span)?; + self.maybe_recover_unexpected_comma(pat.span, true)?; Ok(pat) } - fn maybe_recover_unexpected_comma(&mut self, lo: Span) -> PResult<'a, ()> { - if self.token != token::Comma { + fn maybe_recover_unexpected_comma(&mut self, lo: Span, top_level: bool) -> PResult<'a, ()> { + if !top_level || self.token != token::Comma { return Ok(()); } @@ -109,9 +109,15 @@ impl<'a> Parser<'a> { } /// Parses a pattern, that may be a or-pattern (e.g. `Some(Foo | Bar)`). - fn parse_pat_with_or(&mut self, expected: Expected, gate_or: bool) -> PResult<'a, P> { + fn parse_pat_with_or( + &mut self, + expected: Expected, + gate_or: bool, + top_level: bool + ) -> PResult<'a, P> { // Parse the first pattern. let first_pat = self.parse_pat(expected)?; + self.maybe_recover_unexpected_comma(first_pat.span, top_level)?; // If the next token is not a `|`, // this is not an or-pattern and we should exit here. @@ -132,7 +138,9 @@ impl<'a> Parser<'a> { break; } - pats.push(self.parse_pat(expected)?); + let pat = self.parse_pat(expected)?; + self.maybe_recover_unexpected_comma(pat.span, top_level)?; + pats.push(pat); } let or_pattern_span = lo.to(self.prev_span); @@ -162,7 +170,7 @@ impl<'a> Parser<'a> { // Parse `[pat, pat,...]` as a slice pattern. let (pats, _) = self.parse_delim_comma_seq( token::Bracket, - |p| p.parse_pat_with_or(None, true), + |p| p.parse_pat_with_or(None, true, false), )?; PatKind::Slice(pats) } @@ -292,7 +300,7 @@ impl<'a> Parser<'a> { /// Parse a tuple or parenthesis pattern. fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> { let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| { - p.parse_pat_with_or(None, true) + p.parse_pat_with_or(None, true, false) })?; // Here, `(pat,)` is a tuple pattern. @@ -536,7 +544,7 @@ impl<'a> Parser<'a> { err.span_label(self.token.span, msg); return Err(err); } - let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or(None, true))?; + let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or(None, true, false))?; Ok(PatKind::TupleStruct(path, fields)) } @@ -680,7 +688,7 @@ impl<'a> Parser<'a> { // Parsing a pattern of the form "fieldname: pat" let fieldname = self.parse_field_name()?; self.bump(); - let pat = self.parse_pat_with_or(None, true)?; + let pat = self.parse_pat_with_or(None, true, false)?; hi = pat.span; (pat, fieldname, false) } else { From 7b59b4f14dae8c859718d60794021230e1e3ac29 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 18:13:19 +0200 Subject: [PATCH 207/618] parser: extract `eat_or_separator`. --- src/libsyntax/parse/parser/pat.rs | 58 +++++++++++++++---------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index b2a026d0071e4..3af64cef74f26 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -29,27 +29,10 @@ impl<'a> Parser<'a> { loop { pats.push(self.parse_top_level_pat()?); - if self.token == token::OrOr { - self.ban_unexpected_or_or(); - self.bump(); - } else if self.eat(&token::BinOp(token::Or)) { - // This is a No-op. Continue the loop to parse the next - // pattern. - } else { + if !self.eat_or_separator() { return Ok(pats); } - }; - } - - fn ban_unexpected_or_or(&mut self) { - self.struct_span_err(self.token.span, "unexpected token `||` after pattern") - .span_suggestion( - self.token.span, - "use a single `|` to specify multiple patterns", - "|".to_owned(), - Applicability::MachineApplicable - ) - .emit(); + } } /// A wrapper around `parse_pat` with some special error handling for the @@ -127,17 +110,7 @@ impl<'a> Parser<'a> { let lo = first_pat.span; let mut pats = vec![first_pat]; - loop { - if self.token == token::OrOr { - // Found `||`; Recover and pretend we parsed `|`. - self.ban_unexpected_or_or(); - self.bump(); - } else if self.eat(&token::BinOp(token::Or)) { - // Found `|`. Working towards a proper or-pattern. - } else { - break; - } - + while self.eat_or_separator() { let pat = self.parse_pat(expected)?; self.maybe_recover_unexpected_comma(pat.span, top_level)?; pats.push(pat); @@ -152,6 +125,31 @@ impl<'a> Parser<'a> { Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats))) } + /// Eat the or-pattern `|` separator. + /// If instead a `||` token is encountered, recover and pretend we parsed `|`. + fn eat_or_separator(&mut self) -> bool { + match self.token.kind { + token::OrOr => { + // Found `||`; Recover and pretend we parsed `|`. + self.ban_unexpected_or_or(); + self.bump(); + true + } + _ => self.eat(&token::BinOp(token::Or)), + } + } + + fn ban_unexpected_or_or(&mut self) { + self.struct_span_err(self.token.span, "unexpected token `||` after pattern") + .span_suggestion( + self.token.span, + "use a single `|` to specify multiple patterns", + "|".to_owned(), + Applicability::MachineApplicable + ) + .emit(); + } + /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are /// allowed). fn parse_pat_with_range_pat( From dc5bbaf7b2df8dc2be6c0f1a9973867e5519300b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 18:15:17 +0200 Subject: [PATCH 208/618] parser: improve `parse_pat_with_or` docs. --- src/libsyntax/parse/parser/pat.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 3af64cef74f26..14ac509d6f706 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -91,7 +91,8 @@ impl<'a> Parser<'a> { Ok(()) } - /// Parses a pattern, that may be a or-pattern (e.g. `Some(Foo | Bar)`). + /// Parses a pattern, that may be a or-pattern (e.g. `Foo | Bar` in `Some(Foo | Bar)`). + /// Corresponds to `pat` in RFC 2535. fn parse_pat_with_or( &mut self, expected: Expected, From 6498959377421876040515af39b6491a2ec2a0c5 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 18:34:35 +0200 Subject: [PATCH 209/618] parser: use `eat_or_separator` for leading vert. --- src/libsyntax/parse/parser/pat.rs | 4 ++-- src/test/ui/or-patterns/multiple-pattern-typo.rs | 5 +++++ src/test/ui/or-patterns/multiple-pattern-typo.stderr | 8 +++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 14ac509d6f706..1063e34753095 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -22,8 +22,8 @@ impl<'a> Parser<'a> { /// Parses patterns, separated by '|' s. pub(super) fn parse_pats(&mut self) -> PResult<'a, Vec>> { - // Allow a '|' before the pats (RFC 1925 + RFC 2530) - self.eat(&token::BinOp(token::Or)); + // Allow a '|' before the pats (RFCs 1925, 2530, and 2535). + self.eat_or_separator(); let mut pats = Vec::new(); loop { diff --git a/src/test/ui/or-patterns/multiple-pattern-typo.rs b/src/test/ui/or-patterns/multiple-pattern-typo.rs index 5d1da56674ba4..e308c0adb4eb8 100644 --- a/src/test/ui/or-patterns/multiple-pattern-typo.rs +++ b/src/test/ui/or-patterns/multiple-pattern-typo.rs @@ -37,4 +37,9 @@ fn main() { [1 | 2 || 3] => (), //~ ERROR unexpected token `||` after pattern _ => (), } + + match x { + || 1 | 2 | 3 => (), //~ ERROR unexpected token `||` after pattern + _ => (), + } } diff --git a/src/test/ui/or-patterns/multiple-pattern-typo.stderr b/src/test/ui/or-patterns/multiple-pattern-typo.stderr index 97f3470a54aa2..765c7879b12ca 100644 --- a/src/test/ui/or-patterns/multiple-pattern-typo.stderr +++ b/src/test/ui/or-patterns/multiple-pattern-typo.stderr @@ -34,6 +34,12 @@ error: unexpected token `||` after pattern LL | [1 | 2 || 3] => (), | ^^ help: use a single `|` to specify multiple patterns: `|` +error: unexpected token `||` after pattern + --> $DIR/multiple-pattern-typo.rs:42:9 + | +LL | || 1 | 2 | 3 => (), + | ^^ help: use a single `|` to specify multiple patterns: `|` + warning: the feature `or_patterns` is incomplete and may cause the compiler to crash --> $DIR/multiple-pattern-typo.rs:1:12 | @@ -42,5 +48,5 @@ LL | #![feature(or_patterns)] | = note: `#[warn(incomplete_features)]` on by default -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors From 39f5e5bec42a4c05588db45d12ab9aafc01776aa Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 18:37:41 +0200 Subject: [PATCH 210/618] parser: move `maybe_recover_unexpected_comma` to a more appropriate place. --- src/libsyntax/parse/parser/pat.rs | 99 +++++++++++++++---------------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 1063e34753095..680a587205686 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -35,62 +35,12 @@ impl<'a> Parser<'a> { } } - /// A wrapper around `parse_pat` with some special error handling for the - /// "top-level" patterns in a match arm, `for` loop, `let`, &c. (in contrast - /// to subpatterns within such). pub(super) fn parse_top_level_pat(&mut self) -> PResult<'a, P> { let pat = self.parse_pat(None)?; self.maybe_recover_unexpected_comma(pat.span, true)?; Ok(pat) } - fn maybe_recover_unexpected_comma(&mut self, lo: Span, top_level: bool) -> PResult<'a, ()> { - if !top_level || self.token != token::Comma { - return Ok(()); - } - - // An unexpected comma after a top-level pattern is a clue that the - // user (perhaps more accustomed to some other language) forgot the - // parentheses in what should have been a tuple pattern; return a - // suggestion-enhanced error here rather than choking on the comma later. - let comma_span = self.token.span; - self.bump(); - if let Err(mut err) = self.skip_pat_list() { - // We didn't expect this to work anyway; we just wanted to advance to the - // end of the comma-sequence so we know the span to suggest parenthesizing. - err.cancel(); - } - let seq_span = lo.to(self.prev_span); - let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); - if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { - err.span_suggestion( - seq_span, - "try adding parentheses to match on a tuple..", - format!("({})", seq_snippet), - Applicability::MachineApplicable - ) - .span_suggestion( - seq_span, - "..or a vertical bar to match on multiple alternatives", - format!("{}", seq_snippet.replace(",", " |")), - Applicability::MachineApplicable - ); - } - Err(err) - } - - /// Parse and throw away a parentesized comma separated - /// sequence of patterns until `)` is reached. - fn skip_pat_list(&mut self) -> PResult<'a, ()> { - while !self.check(&token::CloseDelim(token::Paren)) { - self.parse_pat(None)?; - if !self.eat(&token::Comma) { - return Ok(()) - } - } - Ok(()) - } - /// Parses a pattern, that may be a or-pattern (e.g. `Foo | Bar` in `Some(Foo | Bar)`). /// Corresponds to `pat` in RFC 2535. fn parse_pat_with_or( @@ -151,6 +101,55 @@ impl<'a> Parser<'a> { .emit(); } + /// Some special error handling for the "top-level" patterns in a match arm, + /// `for` loop, `let`, &c. (in contrast to subpatterns within such). + fn maybe_recover_unexpected_comma(&mut self, lo: Span, top_level: bool) -> PResult<'a, ()> { + if !top_level || self.token != token::Comma { + return Ok(()); + } + + // An unexpected comma after a top-level pattern is a clue that the + // user (perhaps more accustomed to some other language) forgot the + // parentheses in what should have been a tuple pattern; return a + // suggestion-enhanced error here rather than choking on the comma later. + let comma_span = self.token.span; + self.bump(); + if let Err(mut err) = self.skip_pat_list() { + // We didn't expect this to work anyway; we just wanted to advance to the + // end of the comma-sequence so we know the span to suggest parenthesizing. + err.cancel(); + } + let seq_span = lo.to(self.prev_span); + let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); + if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { + err.span_suggestion( + seq_span, + "try adding parentheses to match on a tuple..", + format!("({})", seq_snippet), + Applicability::MachineApplicable + ) + .span_suggestion( + seq_span, + "..or a vertical bar to match on multiple alternatives", + format!("{}", seq_snippet.replace(",", " |")), + Applicability::MachineApplicable + ); + } + Err(err) + } + + /// Parse and throw away a parentesized comma separated + /// sequence of patterns until `)` is reached. + fn skip_pat_list(&mut self) -> PResult<'a, ()> { + while !self.check(&token::CloseDelim(token::Paren)) { + self.parse_pat(None)?; + if !self.eat(&token::Comma) { + return Ok(()) + } + } + Ok(()) + } + /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are /// allowed). fn parse_pat_with_range_pat( From 8f6a0cdb0fd453580bed74586c6930b1498aa26f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 18:38:36 +0200 Subject: [PATCH 211/618] parser: document `ban_unexpected_or_or`. --- src/libsyntax/parse/parser/pat.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 680a587205686..8fab8884ca018 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -90,6 +90,7 @@ impl<'a> Parser<'a> { } } + /// We have parsed `||` instead of `|`. Error and suggest `|` instead. fn ban_unexpected_or_or(&mut self) { self.struct_span_err(self.token.span, "unexpected token `||` after pattern") .span_suggestion( From b7178ef9836fe8e98ffb3f8d4d870c94e6fe816d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 22:04:28 +0200 Subject: [PATCH 212/618] parser: `parse_pats` -> `parse_top_pat{_unpack}`. --- src/libsyntax/parse/parser/expr.rs | 12 +++++++----- src/libsyntax/parse/parser/pat.rs | 28 +++++++++++++++++----------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 5da9b75d53b04..b9dd851817160 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1241,11 +1241,12 @@ impl<'a> Parser<'a> { Ok(cond) } - /// Parses a `let $pats = $expr` pseudo-expression. + /// Parses a `let $pat = $expr` pseudo-expression. /// The `let` token has already been eaten. fn parse_let_expr(&mut self, attrs: ThinVec) -> PResult<'a, P> { let lo = self.prev_span; - let pats = self.parse_pats()?; + // FIXME(or_patterns, Centril | dlrobertson): use `parse_top_pat` instead. + let pat = self.parse_top_pat_unpack(false)?; self.expect(&token::Eq)?; let expr = self.with_res( Restrictions::NO_STRUCT_LITERAL, @@ -1253,7 +1254,7 @@ impl<'a> Parser<'a> { )?; let span = lo.to(expr.span); self.sess.gated_spans.let_chains.borrow_mut().push(span); - Ok(self.mk_expr(span, ExprKind::Let(pats, expr), attrs)) + Ok(self.mk_expr(span, ExprKind::Let(pat, expr), attrs)) } /// `else` token already eaten @@ -1387,7 +1388,8 @@ impl<'a> Parser<'a> { crate fn parse_arm(&mut self) -> PResult<'a, Arm> { let attrs = self.parse_outer_attributes()?; let lo = self.token.span; - let pats = self.parse_pats()?; + // FIXME(or_patterns, Centril | dlrobertson): use `parse_top_pat` instead. + let pat = self.parse_top_pat_unpack(false)?; let guard = if self.eat_keyword(kw::If) { Some(self.parse_expr()?) } else { @@ -1448,7 +1450,7 @@ impl<'a> Parser<'a> { Ok(ast::Arm { attrs, - pats, + pats: pat, // FIXME(or_patterns, Centril | dlrobertson): this should just be `pat,`. guard, body: expr, span: lo.to(hi), diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 8fab8884ca018..e4a9dc0097752 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -20,19 +20,25 @@ impl<'a> Parser<'a> { self.parse_pat_with_range_pat(true, expected) } - /// Parses patterns, separated by '|' s. - pub(super) fn parse_pats(&mut self) -> PResult<'a, Vec>> { - // Allow a '|' before the pats (RFCs 1925, 2530, and 2535). - self.eat_or_separator(); - - let mut pats = Vec::new(); - loop { - pats.push(self.parse_top_level_pat()?); + // FIXME(or_patterns, Centril | dlrobertson): + // remove this and use `parse_top_pat` everywhere it is used instead. + pub(super) fn parse_top_pat_unpack(&mut self, gate_or: bool) -> PResult<'a, Vec>> { + self.parse_top_pat(gate_or) + .map(|pat| pat.and_then(|pat| match pat.node { + PatKind::Or(pats) => pats, + node => vec![self.mk_pat(pat.span, node)], + })) + } - if !self.eat_or_separator() { - return Ok(pats); - } + /// Entry point to the main pattern parser. + /// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level. + pub(super) fn parse_top_pat(&mut self, gate_or: bool) -> PResult<'a, P> { + // Allow a '|' before the pats (RFCs 1925, 2530, and 2535). + if self.eat_or_separator() && gate_or { + self.sess.gated_spans.or_patterns.borrow_mut().push(self.prev_span); } + + self.parse_pat_with_or(None, gate_or, true) } pub(super) fn parse_top_level_pat(&mut self) -> PResult<'a, P> { From 92d66a131711bc7817e599c81d081847f689654c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 22:35:53 +0200 Subject: [PATCH 213/618] parser: document `parse_pat`. --- src/libsyntax/parse/parser/pat.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index e4a9dc0097752..021e52798af26 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -16,6 +16,10 @@ type Expected = Option<&'static str>; impl<'a> Parser<'a> { /// Parses a pattern. + /// + /// Corresponds to `pat` in RFC 2535 and does not admit or-patterns + /// at the top level. Used when parsing the parameters of lambda expressions, + /// functions, function pointers, and `pat` macro fragments. pub fn parse_pat(&mut self, expected: Expected) -> PResult<'a, P> { self.parse_pat_with_range_pat(true, expected) } From 95792b4d5a12276068e32f54c5d1561b8528a952 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 22:54:07 +0200 Subject: [PATCH 214/618] parser: `let` stmts & `for` exprs: allow or-patterns. --- src/libsyntax/parse/parser/expr.rs | 2 +- src/libsyntax/parse/parser/pat.rs | 6 ------ src/libsyntax/parse/parser/stmt.rs | 2 +- src/test/ui/parser/bad-match.rs | 2 +- src/test/ui/parser/bad-match.stderr | 4 ++-- src/test/ui/parser/bad-name.stderr | 4 ++-- src/test/ui/parser/issue-22647.rs | 2 +- src/test/ui/parser/issue-22647.stderr | 4 ++-- src/test/ui/parser/issue-22712.rs | 2 +- src/test/ui/parser/issue-22712.stderr | 4 ++-- src/test/ui/parser/issue-24197.rs | 2 +- src/test/ui/parser/issue-24197.stderr | 4 ++-- src/test/ui/parser/mut-patterns.rs | 3 ++- src/test/ui/parser/mut-patterns.stderr | 4 ++-- src/test/ui/parser/pat-lt-bracket-5.rs | 2 +- src/test/ui/parser/pat-lt-bracket-5.stderr | 4 ++-- src/test/ui/parser/pat-ranges-1.rs | 2 +- src/test/ui/parser/pat-ranges-1.stderr | 4 ++-- src/test/ui/parser/pat-ranges-2.rs | 2 +- src/test/ui/parser/pat-ranges-2.stderr | 4 ++-- src/test/ui/parser/pat-ranges-3.rs | 2 +- src/test/ui/parser/pat-ranges-3.stderr | 4 ++-- src/test/ui/parser/pat-ranges-4.rs | 2 +- src/test/ui/parser/pat-ranges-4.stderr | 4 ++-- 24 files changed, 35 insertions(+), 40 deletions(-) diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index b9dd851817160..25a858b47353f 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1284,7 +1284,7 @@ impl<'a> Parser<'a> { _ => None, }; - let pat = self.parse_top_level_pat()?; + let pat = self.parse_top_pat(true)?; if !self.eat_keyword(kw::In) { let in_span = self.prev_span.between(self.token.span); self.struct_span_err(in_span, "missing `in` in `for` loop") diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 021e52798af26..e77d9120bce78 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -45,12 +45,6 @@ impl<'a> Parser<'a> { self.parse_pat_with_or(None, gate_or, true) } - pub(super) fn parse_top_level_pat(&mut self) -> PResult<'a, P> { - let pat = self.parse_pat(None)?; - self.maybe_recover_unexpected_comma(pat.span, true)?; - Ok(pat) - } - /// Parses a pattern, that may be a or-pattern (e.g. `Foo | Bar` in `Some(Foo | Bar)`). /// Corresponds to `pat` in RFC 2535. fn parse_pat_with_or( diff --git a/src/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs index c911caba4cd41..3c8cb4ea5a582 100644 --- a/src/libsyntax/parse/parser/stmt.rs +++ b/src/libsyntax/parse/parser/stmt.rs @@ -207,7 +207,7 @@ impl<'a> Parser<'a> { /// Parses a local variable declaration. fn parse_local(&mut self, attrs: ThinVec) -> PResult<'a, P> { let lo = self.prev_span; - let pat = self.parse_top_level_pat()?; + let pat = self.parse_top_pat(true)?; let (err, ty) = if self.eat(&token::Colon) { // Save the state of the parser before parsing type normally, in case there is a `:` diff --git a/src/test/ui/parser/bad-match.rs b/src/test/ui/parser/bad-match.rs index 79bc7eec3113e..04100d1701ddb 100644 --- a/src/test/ui/parser/bad-match.rs +++ b/src/test/ui/parser/bad-match.rs @@ -1,4 +1,4 @@ fn main() { - let isize x = 5; //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `x` + let isize x = 5; //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `x` match x; } diff --git a/src/test/ui/parser/bad-match.stderr b/src/test/ui/parser/bad-match.stderr index 2f29b978e9c91..d5baaf5e93b35 100644 --- a/src/test/ui/parser/bad-match.stderr +++ b/src/test/ui/parser/bad-match.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `x` +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `x` --> $DIR/bad-match.rs:2:13 | LL | let isize x = 5; - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^ expected one of `:`, `;`, `=`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/bad-name.stderr b/src/test/ui/parser/bad-name.stderr index 15e61cf06cae9..dce4dabedf5c8 100644 --- a/src/test/ui/parser/bad-name.stderr +++ b/src/test/ui/parser/bad-name.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `.` +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.` --> $DIR/bad-name.rs:4:8 | LL | let x.y::.z foo; - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^ expected one of `:`, `;`, `=`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/issue-22647.rs b/src/test/ui/parser/issue-22647.rs index 25cd7ffce5a97..a6861410682cb 100644 --- a/src/test/ui/parser/issue-22647.rs +++ b/src/test/ui/parser/issue-22647.rs @@ -1,5 +1,5 @@ fn main() { - let caller = |f: F| //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `<` + let caller = |f: F| //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<` where F: Fn() -> i32 { let x = f(); diff --git a/src/test/ui/parser/issue-22647.stderr b/src/test/ui/parser/issue-22647.stderr index 2dc56a5eca3a6..4b1ef4f3dfc78 100644 --- a/src/test/ui/parser/issue-22647.stderr +++ b/src/test/ui/parser/issue-22647.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `<` +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<` --> $DIR/issue-22647.rs:2:15 | LL | let caller = |f: F| - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^ expected one of `:`, `;`, `=`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/issue-22712.rs b/src/test/ui/parser/issue-22712.rs index b03d578e3d638..774de9c7e6448 100644 --- a/src/test/ui/parser/issue-22712.rs +++ b/src/test/ui/parser/issue-22712.rs @@ -3,7 +3,7 @@ struct Foo { } fn bar() { - let Foo> //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `<` + let Foo> //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<` } fn main() {} diff --git a/src/test/ui/parser/issue-22712.stderr b/src/test/ui/parser/issue-22712.stderr index 167eaf962e0f4..d9e83144b367a 100644 --- a/src/test/ui/parser/issue-22712.stderr +++ b/src/test/ui/parser/issue-22712.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `<` +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<` --> $DIR/issue-22712.rs:6:12 | LL | let Foo> - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^ expected one of `:`, `;`, `=`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/issue-24197.rs b/src/test/ui/parser/issue-24197.rs index 005ff9fa2e0ec..aaf5137461fa6 100644 --- a/src/test/ui/parser/issue-24197.rs +++ b/src/test/ui/parser/issue-24197.rs @@ -1,3 +1,3 @@ fn main() { - let buf[0] = 0; //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `[` + let buf[0] = 0; //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `[` } diff --git a/src/test/ui/parser/issue-24197.stderr b/src/test/ui/parser/issue-24197.stderr index 2dfb31432bc99..24818db622ad4 100644 --- a/src/test/ui/parser/issue-24197.stderr +++ b/src/test/ui/parser/issue-24197.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `[` +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` --> $DIR/issue-24197.rs:2:12 | LL | let buf[0] = 0; - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^ expected one of `:`, `;`, `=`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/mut-patterns.rs b/src/test/ui/parser/mut-patterns.rs index a5eb48252394f..bffeb1e2e7c40 100644 --- a/src/test/ui/parser/mut-patterns.rs +++ b/src/test/ui/parser/mut-patterns.rs @@ -2,5 +2,6 @@ pub fn main() { struct Foo { x: isize } - let mut Foo { x: x } = Foo { x: 3 }; //~ ERROR: expected one of `:`, `;`, `=`, or `@`, found `{` + let mut Foo { x: x } = Foo { x: 3 }; + //~^ ERROR: expected one of `:`, `;`, `=`, `@`, or `|`, found `{` } diff --git a/src/test/ui/parser/mut-patterns.stderr b/src/test/ui/parser/mut-patterns.stderr index 286956440ec34..b39209afd4295 100644 --- a/src/test/ui/parser/mut-patterns.stderr +++ b/src/test/ui/parser/mut-patterns.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `{` +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `{` --> $DIR/mut-patterns.rs:5:17 | LL | let mut Foo { x: x } = Foo { x: 3 }; - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^ expected one of `:`, `;`, `=`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/pat-lt-bracket-5.rs b/src/test/ui/parser/pat-lt-bracket-5.rs index c4b9dd469f54c..aaece1f6bd9cb 100644 --- a/src/test/ui/parser/pat-lt-bracket-5.rs +++ b/src/test/ui/parser/pat-lt-bracket-5.rs @@ -1,3 +1,3 @@ fn main() { - let v[0] = v[1]; //~ ERROR expected one of `:`, `;`, `=`, or `@`, found `[` + let v[0] = v[1]; //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `[` } diff --git a/src/test/ui/parser/pat-lt-bracket-5.stderr b/src/test/ui/parser/pat-lt-bracket-5.stderr index ce4cc05db19b2..167314dde0650 100644 --- a/src/test/ui/parser/pat-lt-bracket-5.stderr +++ b/src/test/ui/parser/pat-lt-bracket-5.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, or `@`, found `[` +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` --> $DIR/pat-lt-bracket-5.rs:2:10 | LL | let v[0] = v[1]; - | ^ expected one of `:`, `;`, `=`, or `@` here + | ^ expected one of `:`, `;`, `=`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/pat-ranges-1.rs b/src/test/ui/parser/pat-ranges-1.rs index ce953b2eb2299..1dafb5a07bb5a 100644 --- a/src/test/ui/parser/pat-ranges-1.rs +++ b/src/test/ui/parser/pat-ranges-1.rs @@ -1,5 +1,5 @@ // Parsing of range patterns fn main() { - let macropus!() ..= 11 = 12; //~ error: expected one of `:`, `;`, or `=`, found `..=` + let macropus!() ..= 11 = 12; //~ error: expected one of `:`, `;`, `=`, or `|`, found `..=` } diff --git a/src/test/ui/parser/pat-ranges-1.stderr b/src/test/ui/parser/pat-ranges-1.stderr index 6e0deccab8ca2..4e2c5d28381d8 100644 --- a/src/test/ui/parser/pat-ranges-1.stderr +++ b/src/test/ui/parser/pat-ranges-1.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, or `=`, found `..=` +error: expected one of `:`, `;`, `=`, or `|`, found `..=` --> $DIR/pat-ranges-1.rs:4:21 | LL | let macropus!() ..= 11 = 12; - | ^^^ expected one of `:`, `;`, or `=` here + | ^^^ expected one of `:`, `;`, `=`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/pat-ranges-2.rs b/src/test/ui/parser/pat-ranges-2.rs index 9f736ed328c5c..1593222acca1b 100644 --- a/src/test/ui/parser/pat-ranges-2.rs +++ b/src/test/ui/parser/pat-ranges-2.rs @@ -1,5 +1,5 @@ // Parsing of range patterns fn main() { - let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, or `=`, found `!` + let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, `=`, or `|`, found `!` } diff --git a/src/test/ui/parser/pat-ranges-2.stderr b/src/test/ui/parser/pat-ranges-2.stderr index d180bb429110a..64df56f5a61b1 100644 --- a/src/test/ui/parser/pat-ranges-2.stderr +++ b/src/test/ui/parser/pat-ranges-2.stderr @@ -1,8 +1,8 @@ -error: expected one of `::`, `:`, `;`, or `=`, found `!` +error: expected one of `::`, `:`, `;`, `=`, or `|`, found `!` --> $DIR/pat-ranges-2.rs:4:26 | LL | let 10 ..= makropulos!() = 12; - | ^ expected one of `::`, `:`, `;`, or `=` here + | ^ expected one of `::`, `:`, `;`, `=`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/pat-ranges-3.rs b/src/test/ui/parser/pat-ranges-3.rs index 65da55e3bda8c..8976dcf0d90f9 100644 --- a/src/test/ui/parser/pat-ranges-3.rs +++ b/src/test/ui/parser/pat-ranges-3.rs @@ -1,5 +1,5 @@ // Parsing of range patterns fn main() { - let 10 ..= 10 + 3 = 12; //~ expected one of `:`, `;`, or `=`, found `+` + let 10 ..= 10 + 3 = 12; //~ expected one of `:`, `;`, `=`, or `|`, found `+` } diff --git a/src/test/ui/parser/pat-ranges-3.stderr b/src/test/ui/parser/pat-ranges-3.stderr index aaa85e3c2ddd8..c32c18d98dce7 100644 --- a/src/test/ui/parser/pat-ranges-3.stderr +++ b/src/test/ui/parser/pat-ranges-3.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, or `=`, found `+` +error: expected one of `:`, `;`, `=`, or `|`, found `+` --> $DIR/pat-ranges-3.rs:4:19 | LL | let 10 ..= 10 + 3 = 12; - | ^ expected one of `:`, `;`, or `=` here + | ^ expected one of `:`, `;`, `=`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/pat-ranges-4.rs b/src/test/ui/parser/pat-ranges-4.rs index 7f4a5f3239e76..61188976b028c 100644 --- a/src/test/ui/parser/pat-ranges-4.rs +++ b/src/test/ui/parser/pat-ranges-4.rs @@ -2,5 +2,5 @@ fn main() { let 10 - 3 ..= 10 = 8; - //~^ error: expected one of `...`, `..=`, `..`, `:`, `;`, or `=`, found `-` + //~^ error: expected one of `...`, `..=`, `..`, `:`, `;`, `=`, or `|`, found `-` } diff --git a/src/test/ui/parser/pat-ranges-4.stderr b/src/test/ui/parser/pat-ranges-4.stderr index 0a1d7a1f6b8ab..53e38bc670beb 100644 --- a/src/test/ui/parser/pat-ranges-4.stderr +++ b/src/test/ui/parser/pat-ranges-4.stderr @@ -1,8 +1,8 @@ -error: expected one of `...`, `..=`, `..`, `:`, `;`, or `=`, found `-` +error: expected one of `...`, `..=`, `..`, `:`, `;`, `=`, or `|`, found `-` --> $DIR/pat-ranges-4.rs:4:12 | LL | let 10 - 3 ..= 10 = 8; - | ^ expected one of `...`, `..=`, `..`, `:`, `;`, or `=` here + | ^ expected one of 7 possible tokens here error: aborting due to previous error From 5f6bec8ecf5a9018bb368becc0aaea703334795a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 22:57:34 +0200 Subject: [PATCH 215/618] parser: drive-by: simplify `parse_arg_general`. --- src/libsyntax/parse/parser.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 89725d8b3395c..002e9bccec72a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -971,15 +971,12 @@ impl<'a> Parser<'a> { /// Skips unexpected attributes and doc comments in this position and emits an appropriate /// error. /// This version of parse arg doesn't necessarily require identifier names. - fn parse_arg_general( + fn parse_arg_general( &mut self, is_trait_item: bool, allow_c_variadic: bool, - is_name_required: F, - ) -> PResult<'a, Arg> - where - F: Fn(&token::Token) -> bool - { + is_name_required: impl Fn(&token::Token) -> bool, + ) -> PResult<'a, Arg> { let lo = self.token.span; let attrs = self.parse_arg_attributes()?; if let Some(mut arg) = self.parse_self_arg()? { From a9af18bed544ede37b6b817cca1d4613aad4696f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 23:07:21 +0200 Subject: [PATCH 216/618] move `ui/or-pattern-mismatch` -> `ui/or-patterns/`. --- src/test/ui/{ => or-patterns}/or-pattern-mismatch.rs | 0 src/test/ui/{ => or-patterns}/or-pattern-mismatch.stderr | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{ => or-patterns}/or-pattern-mismatch.rs (100%) rename src/test/ui/{ => or-patterns}/or-pattern-mismatch.stderr (100%) diff --git a/src/test/ui/or-pattern-mismatch.rs b/src/test/ui/or-patterns/or-pattern-mismatch.rs similarity index 100% rename from src/test/ui/or-pattern-mismatch.rs rename to src/test/ui/or-patterns/or-pattern-mismatch.rs diff --git a/src/test/ui/or-pattern-mismatch.stderr b/src/test/ui/or-patterns/or-pattern-mismatch.stderr similarity index 100% rename from src/test/ui/or-pattern-mismatch.stderr rename to src/test/ui/or-patterns/or-pattern-mismatch.stderr From f35432e1889a4361388adf514634b122aefa746b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 23:53:08 +0200 Subject: [PATCH 217/618] or-patterns: add syntactic tests. --- .../or-patterns/or-patterns-syntactic-fail.rs | 56 +++++++++++++ .../or-patterns-syntactic-fail.stderr | 75 ++++++++++++++++++ .../or-patterns/or-patterns-syntactic-pass.rs | 78 +++++++++++++++++++ .../or-patterns-syntactic-pass.stderr | 8 ++ 4 files changed, 217 insertions(+) create mode 100644 src/test/ui/or-patterns/or-patterns-syntactic-fail.rs create mode 100644 src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr create mode 100644 src/test/ui/or-patterns/or-patterns-syntactic-pass.rs create mode 100644 src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs new file mode 100644 index 0000000000000..43c9214bd98f7 --- /dev/null +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs @@ -0,0 +1,56 @@ +// Test some cases where or-patterns may ostensibly be allowed but are in fact not. +// This is not a semantic test. We only test parsing. + +#![feature(or_patterns)] +//~^ WARN the feature `or_patterns` is incomplete and may cause the compiler to crash + +fn main() {} + +// Test the `pat` macro fragment parser: +macro_rules! accept_pat { + ($p:pat) => {} +} + +accept_pat!(p | q); //~ ERROR no rules expected the token `|` +accept_pat!(| p | q); //~ ERROR no rules expected the token `|` + +// Non-macro tests: + +enum E { A, B } +use E::*; + +fn no_top_level_or_patterns() { + // We do *not* allow or-patterns at the top level of lambdas... + let _ = |A | B: E| (); //~ ERROR binary operation `|` cannot be applied to type `E` + // -------- This looks like an or-pattern but is in fact `|A| (B: E | ())`. + + // ...and for now neither do we allow or-patterns at the top level of functions. + fn fun(A | B: E) {} //~ ERROR expected one of `:` or `@`, found `|` +} + +// We also do not allow a leading `|` when not in a top level position: + +#[cfg(FALSE)] +fn no_leading_parens() { + let ( | A | B); //~ ERROR expected pattern, found `|` +} + +#[cfg(FALSE)] +fn no_leading_tuple() { + let ( | A | B,); //~ ERROR expected pattern, found `|` +} + +#[cfg(FALSE)] +fn no_leading_slice() { + let [ | A | B ]; //~ ERROR expected pattern, found `|` +} + +#[cfg(FALSE)] +fn no_leading_tuple_struct() { + let TS( | A | B ); //~ ERROR expected pattern, found `|` +} + +#[cfg(FALSE)] +fn no_leading_struct() { + let NS { f: | A | B }; //~ ERROR expected pattern, found `|` +} diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr new file mode 100644 index 0000000000000..809ff272f6204 --- /dev/null +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -0,0 +1,75 @@ +error: expected one of `:` or `@`, found `|` + --> $DIR/or-patterns-syntactic-fail.rs:28:14 + | +LL | fn fun(A | B: E) {} + | ^ expected one of `:` or `@` here + +error: expected pattern, found `|` + --> $DIR/or-patterns-syntactic-fail.rs:35:11 + | +LL | let ( | A | B); + | ^ expected pattern + +error: expected pattern, found `|` + --> $DIR/or-patterns-syntactic-fail.rs:40:11 + | +LL | let ( | A | B,); + | ^ expected pattern + +error: expected pattern, found `|` + --> $DIR/or-patterns-syntactic-fail.rs:45:11 + | +LL | let [ | A | B ]; + | ^ expected pattern + +error: expected pattern, found `|` + --> $DIR/or-patterns-syntactic-fail.rs:50:13 + | +LL | let TS( | A | B ); + | ^ expected pattern + +error: expected pattern, found `|` + --> $DIR/or-patterns-syntactic-fail.rs:55:17 + | +LL | let NS { f: | A | B }; + | ^ expected pattern + +error: no rules expected the token `|` + --> $DIR/or-patterns-syntactic-fail.rs:14:15 + | +LL | macro_rules! accept_pat { + | ----------------------- when calling this macro +... +LL | accept_pat!(p | q); + | ^ no rules expected this token in macro call + +error: no rules expected the token `|` + --> $DIR/or-patterns-syntactic-fail.rs:15:13 + | +LL | macro_rules! accept_pat { + | ----------------------- when calling this macro +... +LL | accept_pat!(| p | q); + | ^ no rules expected this token in macro call + +warning: the feature `or_patterns` is incomplete and may cause the compiler to crash + --> $DIR/or-patterns-syntactic-fail.rs:4:12 + | +LL | #![feature(or_patterns)] + | ^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0369]: binary operation `|` cannot be applied to type `E` + --> $DIR/or-patterns-syntactic-fail.rs:24:22 + | +LL | let _ = |A | B: E| (); + | ----^ -- () + | | + | E + | + = note: an implementation of `std::ops::BitOr` might be missing for `E` + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs new file mode 100644 index 0000000000000..5fe72caf9c1ff --- /dev/null +++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs @@ -0,0 +1,78 @@ +// Here we test all the places `|` is *syntactically* allowed. +// This is not a semantic test. We only test parsing. + +// check-pass + +#![feature(or_patterns)] + +fn main() {} + +// Test the `pat` macro fragment parser: +macro_rules! accept_pat { + ($p:pat) => {} +} + +accept_pat!((p | q)); +accept_pat!((p | q,)); +accept_pat!(TS(p | q)); +accept_pat!(NS { f: p | q }); +accept_pat!([p | q]); + +// Non-macro tests: + +#[cfg(FALSE)] +fn or_patterns() { + // Top level of `let`: + let | A | B; + let A | B; + let A | B: u8; + let A | B = 0; + let A | B: u8 = 0; + + // Top level of `for`: + for | A | B in 0 {} + for A | B in 0 {} + + // Top level of `while`: + while let | A | B = 0 {} + while let A | B = 0 {} + + // Top level of `if`: + if let | A | B = 0 {} + if let A | B = 0 {} + + // Top level of `match` arms: + match 0 { + | A | B => {}, + A | B => {}, + } + + // Functions: + fn fun((A | B): _) {} + + // Lambdas: + let _ = |(A | B): u8| (); + + // Parenthesis and tuple patterns: + let (A | B); + let (A | B,); + + // Tuple struct patterns: + let A(B | C); + let E::V(B | C); + + // Struct patterns: + let S { f1: B | C, f2 }; + let E::V { f1: B | C, f2 }; + + // Slice patterns: + let [A | B, .. | ..]; + + // These bind as `(prefix p) | q` as opposed to `prefix (p | q)`: + let box 0 | 1; // Unstable; we *can* the precedence if we want. + let &0 | 1; + let &mut 0 | 1; + let x @ 0 | 1; + let ref x @ 0 | 1; + let ref mut x @ 0 | 1; +} diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr new file mode 100644 index 0000000000000..3145a2e9f2a6e --- /dev/null +++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr @@ -0,0 +1,8 @@ +warning: the feature `or_patterns` is incomplete and may cause the compiler to crash + --> $DIR/or-patterns-syntactic-pass.rs:6:12 + | +LL | #![feature(or_patterns)] + | ^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + From d3b3bceffb1f0fa7727c4d63aa37ecb9444e88c5 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 18 Aug 2019 23:57:43 +0200 Subject: [PATCH 218/618] move `feature-gate-or_patterns.*` -> `ui/or-patterns/` --- .../ui/{feature-gate => or-patterns}/feature-gate-or_patterns.rs | 0 .../{feature-gate => or-patterns}/feature-gate-or_patterns.stderr | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{feature-gate => or-patterns}/feature-gate-or_patterns.rs (100%) rename src/test/ui/{feature-gate => or-patterns}/feature-gate-or_patterns.stderr (100%) diff --git a/src/test/ui/feature-gate/feature-gate-or_patterns.rs b/src/test/ui/or-patterns/feature-gate-or_patterns.rs similarity index 100% rename from src/test/ui/feature-gate/feature-gate-or_patterns.rs rename to src/test/ui/or-patterns/feature-gate-or_patterns.rs diff --git a/src/test/ui/feature-gate/feature-gate-or_patterns.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns.stderr similarity index 100% rename from src/test/ui/feature-gate/feature-gate-or_patterns.stderr rename to src/test/ui/or-patterns/feature-gate-or_patterns.stderr From 1ffea18ddbe9ebaba4ff301a3c42e44a55741355 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 19 Aug 2019 00:19:40 +0200 Subject: [PATCH 219/618] or-patterns: harden feature gating tests. --- .../or-patterns/feature-gate-or_patterns.rs | 47 ++++- .../feature-gate-or_patterns.stderr | 182 +++++++++++++++++- 2 files changed, 227 insertions(+), 2 deletions(-) diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns.rs b/src/test/ui/or-patterns/feature-gate-or_patterns.rs index 036a6095965bd..560db20e66862 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns.rs +++ b/src/test/ui/or-patterns/feature-gate-or_patterns.rs @@ -1,4 +1,4 @@ -#![crate_type="lib"] +fn main() {} pub fn example(x: Option) { match x { @@ -7,3 +7,48 @@ pub fn example(x: Option) { _ => {} } } + +// Test the `pat` macro fragment parser: +macro_rules! accept_pat { + ($p:pat) => {} +} + +accept_pat!((p | q)); //~ ERROR or-patterns syntax is experimental +accept_pat!((p | q,)); //~ ERROR or-patterns syntax is experimental +accept_pat!(TS(p | q)); //~ ERROR or-patterns syntax is experimental +accept_pat!(NS { f: p | q }); //~ ERROR or-patterns syntax is experimental +accept_pat!([p | q]); //~ ERROR or-patterns syntax is experimental + +// Non-macro tests: + +#[cfg(FALSE)] +fn or_patterns() { + // Gated: + + let | A | B; //~ ERROR or-patterns syntax is experimental + //~^ ERROR or-patterns syntax is experimental + let A | B; //~ ERROR or-patterns syntax is experimental + for | A | B in 0 {} //~ ERROR or-patterns syntax is experimental + //~^ ERROR or-patterns syntax is experimental + for A | B in 0 {} //~ ERROR or-patterns syntax is experimental + fn fun((A | B): _) {} //~ ERROR or-patterns syntax is experimental + let _ = |(A | B): u8| (); //~ ERROR or-patterns syntax is experimental + let (A | B); //~ ERROR or-patterns syntax is experimental + let (A | B,); //~ ERROR or-patterns syntax is experimental + let A(B | C); //~ ERROR or-patterns syntax is experimental + let E::V(B | C); //~ ERROR or-patterns syntax is experimental + let S { f1: B | C, f2 }; //~ ERROR or-patterns syntax is experimental + let E::V { f1: B | C, f2 }; //~ ERROR or-patterns syntax is experimental + let [A | B]; //~ ERROR or-patterns syntax is experimental + + // Top level of `while`, `if`, and `match` arms are allowed: + + while let | A = 0 {} + while let A | B = 0 {} + if let | A = 0 {} + if let A | B = 0 {} + match 0 { + | A => {}, + A | B => {}, + } +} diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns.stderr index aaabb54c1f017..e2abfbfd5254d 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns.stderr +++ b/src/test/ui/or-patterns/feature-gate-or_patterns.stderr @@ -7,6 +7,186 @@ LL | Some(0 | 1 | 2) => {} = note: for more information, see https://github.com/rust-lang/rust/issues/54883 = help: add `#![feature(or_patterns)]` to the crate attributes to enable -error: aborting due to previous error +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:28:9 + | +LL | let | A | B; + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:28:11 + | +LL | let | A | B; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:30:9 + | +LL | let A | B; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:31:9 + | +LL | for | A | B in 0 {} + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:31:11 + | +LL | for | A | B in 0 {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:33:9 + | +LL | for A | B in 0 {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:34:13 + | +LL | fn fun((A | B): _) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:35:15 + | +LL | let _ = |(A | B): u8| (); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:36:10 + | +LL | let (A | B); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:37:10 + | +LL | let (A | B,); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:38:11 + | +LL | let A(B | C); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:39:14 + | +LL | let E::V(B | C); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:40:17 + | +LL | let S { f1: B | C, f2 }; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:41:20 + | +LL | let E::V { f1: B | C, f2 }; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:42:10 + | +LL | let [A | B]; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:16:14 + | +LL | accept_pat!((p | q)); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:17:14 + | +LL | accept_pat!((p | q,)); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:18:16 + | +LL | accept_pat!(TS(p | q)); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:19:21 + | +LL | accept_pat!(NS { f: p | q }); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:20:14 + | +LL | accept_pat!([p | q]); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error: aborting due to 21 previous errors For more information about this error, try `rustc --explain E0658`. From b205055c7bc92c0f873755996e6fac3e694c7e72 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 19 Aug 2019 02:40:24 +0200 Subject: [PATCH 220/618] parser: better recovery for || in inner pats. --- src/libsyntax/parse/parser/pat.rs | 27 ++++++- .../or-patterns/or-patterns-syntactic-fail.rs | 39 ++++------ .../or-patterns-syntactic-fail.stderr | 77 ++++++++++++++----- 3 files changed, 96 insertions(+), 47 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index e77d9120bce78..b9871be229ce5 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -155,6 +155,25 @@ impl<'a> Parser<'a> { Ok(()) } + /// Recursive possibly-or-pattern parser with recovery for an erroneous leading `|`. + /// See `parse_pat_with_or` for details on parsing or-patterns. + fn parse_pat_with_or_inner(&mut self, expected: Expected) -> PResult<'a, P> { + // Recover if `|` or `||` is here. + // The user is thinking that a leading `|` is allowed in this position. + if let token::BinOp(token::Or) | token::OrOr = self.token.kind { + let span = self.token.span; + let rm_msg = format!("remove the `{}`", pprust::token_to_string(&self.token)); + + self.struct_span_err(span, "a leading `|` is only allowed in a top-level pattern") + .span_suggestion(span, &rm_msg, String::new(), Applicability::MachineApplicable) + .emit(); + + self.bump(); + } + + self.parse_pat_with_or(expected, true, false) + } + /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are /// allowed). fn parse_pat_with_range_pat( @@ -173,7 +192,7 @@ impl<'a> Parser<'a> { // Parse `[pat, pat,...]` as a slice pattern. let (pats, _) = self.parse_delim_comma_seq( token::Bracket, - |p| p.parse_pat_with_or(None, true, false), + |p| p.parse_pat_with_or_inner(None), )?; PatKind::Slice(pats) } @@ -303,7 +322,7 @@ impl<'a> Parser<'a> { /// Parse a tuple or parenthesis pattern. fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> { let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| { - p.parse_pat_with_or(None, true, false) + p.parse_pat_with_or_inner(None) })?; // Here, `(pat,)` is a tuple pattern. @@ -547,7 +566,7 @@ impl<'a> Parser<'a> { err.span_label(self.token.span, msg); return Err(err); } - let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or(None, true, false))?; + let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner(None))?; Ok(PatKind::TupleStruct(path, fields)) } @@ -691,7 +710,7 @@ impl<'a> Parser<'a> { // Parsing a pattern of the form "fieldname: pat" let fieldname = self.parse_field_name()?; self.bump(); - let pat = self.parse_pat_with_or(None, true, false)?; + let pat = self.parse_pat_with_or_inner(None)?; hi = pat.span; (pat, fieldname, false) } else { diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs index 43c9214bd98f7..7959812f5b39c 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs @@ -30,27 +30,20 @@ fn no_top_level_or_patterns() { // We also do not allow a leading `|` when not in a top level position: -#[cfg(FALSE)] -fn no_leading_parens() { - let ( | A | B); //~ ERROR expected pattern, found `|` -} - -#[cfg(FALSE)] -fn no_leading_tuple() { - let ( | A | B,); //~ ERROR expected pattern, found `|` -} - -#[cfg(FALSE)] -fn no_leading_slice() { - let [ | A | B ]; //~ ERROR expected pattern, found `|` -} - -#[cfg(FALSE)] -fn no_leading_tuple_struct() { - let TS( | A | B ); //~ ERROR expected pattern, found `|` -} - -#[cfg(FALSE)] -fn no_leading_struct() { - let NS { f: | A | B }; //~ ERROR expected pattern, found `|` +fn no_leading_inner() { + struct TS(E); + struct NS { f: E } + + let ( | A | B) = E::A; //~ ERROR a leading `|` is only allowed in a top-level pattern + let ( | A | B,) = (E::B,); //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ | A | B ] = [E::A]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( | A | B ); //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: | A | B }; //~ ERROR a leading `|` is only allowed in a top-level pattern + + let ( || A | B) = E::A; //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ || A | B ] = [E::A]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( || A | B ); //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: || A | B }; //~ ERROR a leading `|` is only allowed in a top-level pattern + + let recovery_witness: String = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr index 809ff272f6204..dd4c309ce85a3 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -4,35 +4,59 @@ error: expected one of `:` or `@`, found `|` LL | fn fun(A | B: E) {} | ^ expected one of `:` or `@` here -error: expected pattern, found `|` - --> $DIR/or-patterns-syntactic-fail.rs:35:11 +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:37:11 | -LL | let ( | A | B); - | ^ expected pattern +LL | let ( | A | B) = E::A; + | ^ help: remove the `|` -error: expected pattern, found `|` - --> $DIR/or-patterns-syntactic-fail.rs:40:11 +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:38:11 | -LL | let ( | A | B,); - | ^ expected pattern +LL | let ( | A | B,) = (E::B,); + | ^ help: remove the `|` -error: expected pattern, found `|` - --> $DIR/or-patterns-syntactic-fail.rs:45:11 +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:39:11 | -LL | let [ | A | B ]; - | ^ expected pattern +LL | let [ | A | B ] = [E::A]; + | ^ help: remove the `|` -error: expected pattern, found `|` - --> $DIR/or-patterns-syntactic-fail.rs:50:13 +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:40:13 | LL | let TS( | A | B ); - | ^ expected pattern + | ^ help: remove the `|` -error: expected pattern, found `|` - --> $DIR/or-patterns-syntactic-fail.rs:55:17 +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:41:17 | LL | let NS { f: | A | B }; - | ^ expected pattern + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:43:11 + | +LL | let ( || A | B) = E::A; + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:44:11 + | +LL | let [ || A | B ] = [E::A]; + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:45:13 + | +LL | let TS( || A | B ); + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:46:17 + | +LL | let NS { f: || A | B }; + | ^^ help: remove the `||` error: no rules expected the token `|` --> $DIR/or-patterns-syntactic-fail.rs:14:15 @@ -70,6 +94,19 @@ LL | let _ = |A | B: E| (); | = note: an implementation of `std::ops::BitOr` might be missing for `E` -error: aborting due to 9 previous errors +error[E0308]: mismatched types + --> $DIR/or-patterns-syntactic-fail.rs:48:36 + | +LL | let recovery_witness: String = 0; + | ^ + | | + | expected struct `std::string::String`, found integer + | help: try using a conversion method: `0.to_string()` + | + = note: expected type `std::string::String` + found type `{integer}` + +error: aborting due to 14 previous errors -For more information about this error, try `rustc --explain E0369`. +Some errors have detailed explanations: E0308, E0369. +For more information about an error, try `rustc --explain E0308`. From b2966e651de3bf83ab9c712a1afaeba84162cab1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 21:43:28 +0200 Subject: [PATCH 221/618] parser: bool -> GateOr. --- src/libsyntax/parse/parser/expr.rs | 7 ++++--- src/libsyntax/parse/parser/pat.rs | 16 ++++++++++------ src/libsyntax/parse/parser/stmt.rs | 3 ++- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 25a858b47353f..83e5a84a8c6ae 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1,6 +1,7 @@ use super::{Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle}; use super::{BlockMode, SemiColonMode}; use super::{SeqSep, TokenExpectType}; +use super::pat::GateOr; use crate::maybe_recover_from_interpolated_ty_qpath; use crate::ptr::P; @@ -1246,7 +1247,7 @@ impl<'a> Parser<'a> { fn parse_let_expr(&mut self, attrs: ThinVec) -> PResult<'a, P> { let lo = self.prev_span; // FIXME(or_patterns, Centril | dlrobertson): use `parse_top_pat` instead. - let pat = self.parse_top_pat_unpack(false)?; + let pat = self.parse_top_pat_unpack(GateOr::No)?; self.expect(&token::Eq)?; let expr = self.with_res( Restrictions::NO_STRUCT_LITERAL, @@ -1284,7 +1285,7 @@ impl<'a> Parser<'a> { _ => None, }; - let pat = self.parse_top_pat(true)?; + let pat = self.parse_top_pat(GateOr::Yes)?; if !self.eat_keyword(kw::In) { let in_span = self.prev_span.between(self.token.span); self.struct_span_err(in_span, "missing `in` in `for` loop") @@ -1389,7 +1390,7 @@ impl<'a> Parser<'a> { let attrs = self.parse_outer_attributes()?; let lo = self.token.span; // FIXME(or_patterns, Centril | dlrobertson): use `parse_top_pat` instead. - let pat = self.parse_top_pat_unpack(false)?; + let pat = self.parse_top_pat_unpack(GateOr::No)?; let guard = if self.eat_keyword(kw::If) { Some(self.parse_expr()?) } else { diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index b9871be229ce5..3d89ec56ffafa 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -14,6 +14,10 @@ use errors::{Applicability, DiagnosticBuilder}; type Expected = Option<&'static str>; +/// Whether or not an or-pattern should be gated when occurring in the current context. +#[derive(PartialEq)] +pub enum GateOr { Yes, No } + impl<'a> Parser<'a> { /// Parses a pattern. /// @@ -26,7 +30,7 @@ impl<'a> Parser<'a> { // FIXME(or_patterns, Centril | dlrobertson): // remove this and use `parse_top_pat` everywhere it is used instead. - pub(super) fn parse_top_pat_unpack(&mut self, gate_or: bool) -> PResult<'a, Vec>> { + pub(super) fn parse_top_pat_unpack(&mut self, gate_or: GateOr) -> PResult<'a, Vec>> { self.parse_top_pat(gate_or) .map(|pat| pat.and_then(|pat| match pat.node { PatKind::Or(pats) => pats, @@ -36,9 +40,9 @@ impl<'a> Parser<'a> { /// Entry point to the main pattern parser. /// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level. - pub(super) fn parse_top_pat(&mut self, gate_or: bool) -> PResult<'a, P> { + pub(super) fn parse_top_pat(&mut self, gate_or: GateOr) -> PResult<'a, P> { // Allow a '|' before the pats (RFCs 1925, 2530, and 2535). - if self.eat_or_separator() && gate_or { + if self.eat_or_separator() && gate_or == GateOr::Yes { self.sess.gated_spans.or_patterns.borrow_mut().push(self.prev_span); } @@ -50,7 +54,7 @@ impl<'a> Parser<'a> { fn parse_pat_with_or( &mut self, expected: Expected, - gate_or: bool, + gate_or: GateOr, top_level: bool ) -> PResult<'a, P> { // Parse the first pattern. @@ -73,7 +77,7 @@ impl<'a> Parser<'a> { let or_pattern_span = lo.to(self.prev_span); // Feature gate the or-pattern if instructed: - if gate_or { + if gate_or == GateOr::Yes { self.sess.gated_spans.or_patterns.borrow_mut().push(or_pattern_span); } @@ -171,7 +175,7 @@ impl<'a> Parser<'a> { self.bump(); } - self.parse_pat_with_or(expected, true, false) + self.parse_pat_with_or(expected, GateOr::Yes, false) } /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are diff --git a/src/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs index 3c8cb4ea5a582..651ebf6342e71 100644 --- a/src/libsyntax/parse/parser/stmt.rs +++ b/src/libsyntax/parse/parser/stmt.rs @@ -1,6 +1,7 @@ use super::{Parser, PResult, Restrictions, PrevTokenKind, SemiColonMode, BlockMode}; use super::expr::LhsExpr; use super::path::PathStyle; +use super::pat::GateOr; use crate::ptr::P; use crate::{maybe_whole, ThinVec}; @@ -207,7 +208,7 @@ impl<'a> Parser<'a> { /// Parses a local variable declaration. fn parse_local(&mut self, attrs: ThinVec) -> PResult<'a, P> { let lo = self.prev_span; - let pat = self.parse_top_pat(true)?; + let pat = self.parse_top_pat(GateOr::Yes)?; let (err, ty) = if self.eat(&token::Colon) { // Save the state of the parser before parsing type normally, in case there is a `:` From a9ef8592e47808539ffd9237c22ce5518aa7b188 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 22:12:19 +0200 Subject: [PATCH 222/618] parser: bool -> TopLevel. --- src/libsyntax/parse/parser/pat.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 3d89ec56ffafa..c168d03378133 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -18,6 +18,10 @@ type Expected = Option<&'static str>; #[derive(PartialEq)] pub enum GateOr { Yes, No } +/// Whether or not this is the top level pattern context. +#[derive(PartialEq, Copy, Clone)] +enum TopLevel { Yes, No } + impl<'a> Parser<'a> { /// Parses a pattern. /// @@ -46,7 +50,7 @@ impl<'a> Parser<'a> { self.sess.gated_spans.or_patterns.borrow_mut().push(self.prev_span); } - self.parse_pat_with_or(None, gate_or, true) + self.parse_pat_with_or(None, gate_or, TopLevel::Yes) } /// Parses a pattern, that may be a or-pattern (e.g. `Foo | Bar` in `Some(Foo | Bar)`). @@ -55,7 +59,7 @@ impl<'a> Parser<'a> { &mut self, expected: Expected, gate_or: GateOr, - top_level: bool + top_level: TopLevel, ) -> PResult<'a, P> { // Parse the first pattern. let first_pat = self.parse_pat(expected)?; @@ -112,8 +116,8 @@ impl<'a> Parser<'a> { /// Some special error handling for the "top-level" patterns in a match arm, /// `for` loop, `let`, &c. (in contrast to subpatterns within such). - fn maybe_recover_unexpected_comma(&mut self, lo: Span, top_level: bool) -> PResult<'a, ()> { - if !top_level || self.token != token::Comma { + fn maybe_recover_unexpected_comma(&mut self, lo: Span, top_level: TopLevel) -> PResult<'a, ()> { + if top_level == TopLevel::No || self.token != token::Comma { return Ok(()); } @@ -175,7 +179,7 @@ impl<'a> Parser<'a> { self.bump(); } - self.parse_pat_with_or(expected, GateOr::Yes, false) + self.parse_pat_with_or(expected, GateOr::Yes, TopLevel::No) } /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are From 3a405421e7c1437416e225ea8d2f0fdfb501df7b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 22:46:17 +0200 Subject: [PATCH 223/618] parse_top_pat: silence leading vert gating sometimes. --- src/libsyntax/parse/parser/pat.rs | 18 ++++++-- .../feature-gate-or_patterns-leading-for.rs | 8 ++++ ...eature-gate-or_patterns-leading-for.stderr | 12 +++++ .../feature-gate-or_patterns-leading-let.rs | 8 ++++ ...eature-gate-or_patterns-leading-let.stderr | 12 +++++ .../feature-gate-or_patterns-leading.stderr | 12 +++++ .../or-patterns/feature-gate-or_patterns.rs | 2 - .../feature-gate-or_patterns.stderr | 44 ++++++------------- 8 files changed, 80 insertions(+), 36 deletions(-) create mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.rs create mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr create mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs create mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr create mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading.stderr diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index c168d03378133..724edbcfaed79 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -46,11 +46,23 @@ impl<'a> Parser<'a> { /// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level. pub(super) fn parse_top_pat(&mut self, gate_or: GateOr) -> PResult<'a, P> { // Allow a '|' before the pats (RFCs 1925, 2530, and 2535). - if self.eat_or_separator() && gate_or == GateOr::Yes { - self.sess.gated_spans.or_patterns.borrow_mut().push(self.prev_span); + let gated_leading_vert = self.eat_or_separator() && gate_or == GateOr::Yes; + + // Parse the possibly-or-pattern. + let pat = self.parse_pat_with_or(None, gate_or, TopLevel::Yes)?; + + // If we parsed a leading `|` which should be gated, + // and no other gated or-pattern has been parsed thus far, + // then we should really gate the leading `|`. + // This complicated procedure is done purely for diagnostics UX. + if gated_leading_vert { + let mut or_pattern_spans = self.sess.gated_spans.or_patterns.borrow_mut(); + if or_pattern_spans.is_empty() { + or_pattern_spans.push(self.prev_span); + } } - self.parse_pat_with_or(None, gate_or, TopLevel::Yes) + Ok(pat) } /// Parses a pattern, that may be a or-pattern (e.g. `Foo | Bar` in `Some(Foo | Bar)`). diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.rs b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.rs new file mode 100644 index 0000000000000..de8e1bba5576c --- /dev/null +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.rs @@ -0,0 +1,8 @@ +// Test feature gating for a sole leading `|` in `let`. + +fn main() {} + +#[cfg(FALSE)] +fn gated_leading_vert_in_let() { + for | A in 0 {} //~ ERROR or-patterns syntax is experimental +} diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr new file mode 100644 index 0000000000000..83804d564f3e4 --- /dev/null +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr @@ -0,0 +1,12 @@ +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns-leading-for.rs:7:11 + | +LL | for | A in 0 {} + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs new file mode 100644 index 0000000000000..a4ea4e25d861e --- /dev/null +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs @@ -0,0 +1,8 @@ +// Test feature gating for a sole leading `|` in `let`. + +fn main() {} + +#[cfg(FALSE)] +fn gated_leading_vert_in_let() { + let | A; //~ ERROR or-patterns syntax is experimental +} diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr new file mode 100644 index 0000000000000..f7954ad7a8ce1 --- /dev/null +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr @@ -0,0 +1,12 @@ +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns-leading-let.rs:7:11 + | +LL | let | A; + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns-leading.stderr new file mode 100644 index 0000000000000..8b18082fca7df --- /dev/null +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading.stderr @@ -0,0 +1,12 @@ +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns-leading.rs:7:11 + | +LL | let | A; + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns.rs b/src/test/ui/or-patterns/feature-gate-or_patterns.rs index 560db20e66862..e638838147a4d 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns.rs +++ b/src/test/ui/or-patterns/feature-gate-or_patterns.rs @@ -26,10 +26,8 @@ fn or_patterns() { // Gated: let | A | B; //~ ERROR or-patterns syntax is experimental - //~^ ERROR or-patterns syntax is experimental let A | B; //~ ERROR or-patterns syntax is experimental for | A | B in 0 {} //~ ERROR or-patterns syntax is experimental - //~^ ERROR or-patterns syntax is experimental for A | B in 0 {} //~ ERROR or-patterns syntax is experimental fn fun((A | B): _) {} //~ ERROR or-patterns syntax is experimental let _ = |(A | B): u8| (); //~ ERROR or-patterns syntax is experimental diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns.stderr index e2abfbfd5254d..aae6644dac2e0 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns.stderr +++ b/src/test/ui/or-patterns/feature-gate-or_patterns.stderr @@ -7,15 +7,6 @@ LL | Some(0 | 1 | 2) => {} = note: for more information, see https://github.com/rust-lang/rust/issues/54883 = help: add `#![feature(or_patterns)]` to the crate attributes to enable -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:28:9 - | -LL | let | A | B; - | ^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/54883 - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - error[E0658]: or-patterns syntax is experimental --> $DIR/feature-gate-or_patterns.rs:28:11 | @@ -26,7 +17,7 @@ LL | let | A | B; = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:30:9 + --> $DIR/feature-gate-or_patterns.rs:29:9 | LL | let A | B; | ^^^^^ @@ -35,16 +26,7 @@ LL | let A | B; = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:31:9 - | -LL | for | A | B in 0 {} - | ^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/54883 - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:31:11 + --> $DIR/feature-gate-or_patterns.rs:30:11 | LL | for | A | B in 0 {} | ^^^^^ @@ -53,7 +35,7 @@ LL | for | A | B in 0 {} = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:33:9 + --> $DIR/feature-gate-or_patterns.rs:31:9 | LL | for A | B in 0 {} | ^^^^^ @@ -62,7 +44,7 @@ LL | for A | B in 0 {} = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:34:13 + --> $DIR/feature-gate-or_patterns.rs:32:13 | LL | fn fun((A | B): _) {} | ^^^^^ @@ -71,7 +53,7 @@ LL | fn fun((A | B): _) {} = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:35:15 + --> $DIR/feature-gate-or_patterns.rs:33:15 | LL | let _ = |(A | B): u8| (); | ^^^^^ @@ -80,7 +62,7 @@ LL | let _ = |(A | B): u8| (); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:36:10 + --> $DIR/feature-gate-or_patterns.rs:34:10 | LL | let (A | B); | ^^^^^ @@ -89,7 +71,7 @@ LL | let (A | B); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:37:10 + --> $DIR/feature-gate-or_patterns.rs:35:10 | LL | let (A | B,); | ^^^^^ @@ -98,7 +80,7 @@ LL | let (A | B,); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:38:11 + --> $DIR/feature-gate-or_patterns.rs:36:11 | LL | let A(B | C); | ^^^^^ @@ -107,7 +89,7 @@ LL | let A(B | C); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:39:14 + --> $DIR/feature-gate-or_patterns.rs:37:14 | LL | let E::V(B | C); | ^^^^^ @@ -116,7 +98,7 @@ LL | let E::V(B | C); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:40:17 + --> $DIR/feature-gate-or_patterns.rs:38:17 | LL | let S { f1: B | C, f2 }; | ^^^^^ @@ -125,7 +107,7 @@ LL | let S { f1: B | C, f2 }; = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:41:20 + --> $DIR/feature-gate-or_patterns.rs:39:20 | LL | let E::V { f1: B | C, f2 }; | ^^^^^ @@ -134,7 +116,7 @@ LL | let E::V { f1: B | C, f2 }; = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:42:10 + --> $DIR/feature-gate-or_patterns.rs:40:10 | LL | let [A | B]; | ^^^^^ @@ -187,6 +169,6 @@ LL | accept_pat!([p | q]); = note: for more information, see https://github.com/rust-lang/rust/issues/54883 = help: add `#![feature(or_patterns)]` to the crate attributes to enable -error: aborting due to 21 previous errors +error: aborting due to 19 previous errors For more information about this error, try `rustc --explain E0658`. From e3747722fbb8a44f9053922e4c39338a3a1f9597 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 23:10:46 +0200 Subject: [PATCH 224/618] parser: extract recover_inner_leading_vert. --- src/libsyntax/parse/parser/pat.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 724edbcfaed79..dc6632cf10da9 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -178,8 +178,13 @@ impl<'a> Parser<'a> { /// Recursive possibly-or-pattern parser with recovery for an erroneous leading `|`. /// See `parse_pat_with_or` for details on parsing or-patterns. fn parse_pat_with_or_inner(&mut self, expected: Expected) -> PResult<'a, P> { - // Recover if `|` or `||` is here. - // The user is thinking that a leading `|` is allowed in this position. + self.recover_inner_leading_vert(); + self.parse_pat_with_or(expected, GateOr::Yes, TopLevel::No) + } + + /// Recover if `|` or `||` is here. + /// The user is thinking that a leading `|` is allowed in this position. + fn recover_inner_leading_vert(&mut self) { if let token::BinOp(token::Or) | token::OrOr = self.token.kind { let span = self.token.span; let rm_msg = format!("remove the `{}`", pprust::token_to_string(&self.token)); @@ -190,8 +195,6 @@ impl<'a> Parser<'a> { self.bump(); } - - self.parse_pat_with_or(expected, GateOr::Yes, TopLevel::No) } /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are From 0ab84303326fff65d5d0a168fd47448e05135c9f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 24 Aug 2019 23:44:28 +0200 Subject: [PATCH 225/618] parser: reword || recovery. --- src/libsyntax/parse/parser/pat.rs | 2 +- .../ui/or-patterns/multiple-pattern-typo.stderr | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index dc6632cf10da9..0b3de57fd6f30 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -119,7 +119,7 @@ impl<'a> Parser<'a> { self.struct_span_err(self.token.span, "unexpected token `||` after pattern") .span_suggestion( self.token.span, - "use a single `|` to specify multiple patterns", + "use a single `|` to separate multiple alternative patterns", "|".to_owned(), Applicability::MachineApplicable ) diff --git a/src/test/ui/or-patterns/multiple-pattern-typo.stderr b/src/test/ui/or-patterns/multiple-pattern-typo.stderr index 765c7879b12ca..c61b5cb208251 100644 --- a/src/test/ui/or-patterns/multiple-pattern-typo.stderr +++ b/src/test/ui/or-patterns/multiple-pattern-typo.stderr @@ -2,43 +2,43 @@ error: unexpected token `||` after pattern --> $DIR/multiple-pattern-typo.rs:8:15 | LL | 1 | 2 || 3 => (), - | ^^ help: use a single `|` to specify multiple patterns: `|` + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` error: unexpected token `||` after pattern --> $DIR/multiple-pattern-typo.rs:13:16 | LL | (1 | 2 || 3) => (), - | ^^ help: use a single `|` to specify multiple patterns: `|` + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` error: unexpected token `||` after pattern --> $DIR/multiple-pattern-typo.rs:18:16 | LL | (1 | 2 || 3,) => (), - | ^^ help: use a single `|` to specify multiple patterns: `|` + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` error: unexpected token `||` after pattern --> $DIR/multiple-pattern-typo.rs:25:18 | LL | TS(1 | 2 || 3) => (), - | ^^ help: use a single `|` to specify multiple patterns: `|` + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` error: unexpected token `||` after pattern --> $DIR/multiple-pattern-typo.rs:32:23 | LL | NS { f: 1 | 2 || 3 } => (), - | ^^ help: use a single `|` to specify multiple patterns: `|` + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` error: unexpected token `||` after pattern --> $DIR/multiple-pattern-typo.rs:37:16 | LL | [1 | 2 || 3] => (), - | ^^ help: use a single `|` to specify multiple patterns: `|` + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` error: unexpected token `||` after pattern --> $DIR/multiple-pattern-typo.rs:42:9 | LL | || 1 | 2 | 3 => (), - | ^^ help: use a single `|` to specify multiple patterns: `|` + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` warning: the feature `or_patterns` is incomplete and may cause the compiler to crash --> $DIR/multiple-pattern-typo.rs:1:12 From 3890befa8ea9def7e1c9c57a321c7b8c9f759f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 24 Aug 2019 14:54:35 -0700 Subject: [PATCH 226/618] review comment --- src/librustc/ty/sty.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 7b7e2b8bfbdc8..f41fffe507d97 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -385,7 +385,6 @@ impl<'tcx> ClosureSubsts<'tcx> { let ty = self.closure_sig_ty(def_id, tcx); match ty.sty { ty::FnPtr(sig) => sig, - ty::Infer(_) | ty::Error => ty::Binder::dummy(FnSig::fake()), // ignore errors _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.sty), } } From 4f7532765967ea174816a23c11188aa8c7865966 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 25 Aug 2019 00:08:28 +0200 Subject: [PATCH 227/618] typeck/pat.rs: dedup in `check_pat_ref`. --- src/librustc_typeck/check/pat.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index f0ecbd674c07d..7506cbdd5104a 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -981,7 +981,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let tcx = self.tcx; let expected = self.shallow_resolve(expected); - if self.check_dereferencable(pat.span, expected, &inner) { + let (rptr_ty, inner_ty) = if self.check_dereferencable(pat.span, expected, &inner) { // `demand::subtype` would be good enough, but using `eqtype` turns // out to be equally general. See (note_1) for details. @@ -989,10 +989,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // to avoid creating needless variables. This also helps with // the bad interactions of the given hack detailed in (note_1). debug!("check_pat_ref: expected={:?}", expected); - let (rptr_ty, inner_ty) = match expected.sty { - ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => { - (expected, r_ty) - } + match expected.sty { + ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty), _ => { let inner_ty = self.next_ty_var( TypeVariableOrigin { @@ -1012,14 +1010,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } (rptr_ty, inner_ty) } - }; - - self.check_pat(&inner, inner_ty, def_bm, discrim_span); - rptr_ty + } } else { - self.check_pat(&inner, tcx.types.err, def_bm, discrim_span); - tcx.types.err - } + (tcx.types.err, tcx.types.err) + }; + self.check_pat(&inner, inner_ty, def_bm, discrim_span); + rptr_ty } /// Create a reference type with a fresh region variable. From 5a7e1cb46a05fd176e5488beb58f72a05f4b1a0d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 25 Aug 2019 00:27:55 +0200 Subject: [PATCH 228/618] typeck/pat.rs: dedup in `check_pat_box`. --- src/librustc_typeck/check/pat.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 7506cbdd5104a..3f6fc95360a5e 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -952,22 +952,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { discrim_span: Option, ) -> Ty<'tcx> { let tcx = self.tcx; - let inner_ty = self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span: inner.span, - }); - let uniq_ty = tcx.mk_box(inner_ty); - - if self.check_dereferencable(span, expected, &inner) { + let (box_ty, inner_ty) = if self.check_dereferencable(span, expected, &inner) { // Here, `demand::subtype` is good enough, but I don't // think any errors can be introduced by using `demand::eqtype`. - self.demand_eqtype_pat(span, expected, uniq_ty, discrim_span); - self.check_pat(&inner, inner_ty, def_bm, discrim_span); - uniq_ty + let inner_ty = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: inner.span, + }); + let box_ty = tcx.mk_box(inner_ty); + self.demand_eqtype_pat(span, expected, box_ty, discrim_span); + (box_ty, inner_ty) } else { - self.check_pat(&inner, tcx.types.err, def_bm, discrim_span); - tcx.types.err - } + (tcx.types.err, tcx.types.err) + }; + self.check_pat(&inner, inner_ty, def_bm, discrim_span); + box_ty } fn check_pat_ref( From 1202cb0e2b168b0a913b33e3cb3c1d9339683e28 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 25 Aug 2019 01:00:19 +0200 Subject: [PATCH 229/618] parser: simplify parse_pat_with_or_{inner} --- src/libsyntax/parse/parser/pat.rs | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 0b3de57fd6f30..7c09dc4e56634 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -49,7 +49,7 @@ impl<'a> Parser<'a> { let gated_leading_vert = self.eat_or_separator() && gate_or == GateOr::Yes; // Parse the possibly-or-pattern. - let pat = self.parse_pat_with_or(None, gate_or, TopLevel::Yes)?; + let pat = self.parse_pat_with_or(gate_or, TopLevel::Yes)?; // If we parsed a leading `|` which should be gated, // and no other gated or-pattern has been parsed thus far, @@ -67,14 +67,9 @@ impl<'a> Parser<'a> { /// Parses a pattern, that may be a or-pattern (e.g. `Foo | Bar` in `Some(Foo | Bar)`). /// Corresponds to `pat` in RFC 2535. - fn parse_pat_with_or( - &mut self, - expected: Expected, - gate_or: GateOr, - top_level: TopLevel, - ) -> PResult<'a, P> { + fn parse_pat_with_or(&mut self, gate_or: GateOr, top_level: TopLevel) -> PResult<'a, P> { // Parse the first pattern. - let first_pat = self.parse_pat(expected)?; + let first_pat = self.parse_pat(None)?; self.maybe_recover_unexpected_comma(first_pat.span, top_level)?; // If the next token is not a `|`, @@ -86,7 +81,7 @@ impl<'a> Parser<'a> { let lo = first_pat.span; let mut pats = vec![first_pat]; while self.eat_or_separator() { - let pat = self.parse_pat(expected)?; + let pat = self.parse_pat(None)?; self.maybe_recover_unexpected_comma(pat.span, top_level)?; pats.push(pat); } @@ -177,9 +172,9 @@ impl<'a> Parser<'a> { /// Recursive possibly-or-pattern parser with recovery for an erroneous leading `|`. /// See `parse_pat_with_or` for details on parsing or-patterns. - fn parse_pat_with_or_inner(&mut self, expected: Expected) -> PResult<'a, P> { + fn parse_pat_with_or_inner(&mut self) -> PResult<'a, P> { self.recover_inner_leading_vert(); - self.parse_pat_with_or(expected, GateOr::Yes, TopLevel::No) + self.parse_pat_with_or(GateOr::Yes, TopLevel::No) } /// Recover if `|` or `||` is here. @@ -215,7 +210,7 @@ impl<'a> Parser<'a> { // Parse `[pat, pat,...]` as a slice pattern. let (pats, _) = self.parse_delim_comma_seq( token::Bracket, - |p| p.parse_pat_with_or_inner(None), + |p| p.parse_pat_with_or_inner(), )?; PatKind::Slice(pats) } @@ -344,9 +339,7 @@ impl<'a> Parser<'a> { /// Parse a tuple or parenthesis pattern. fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> { - let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| { - p.parse_pat_with_or_inner(None) - })?; + let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner())?; // Here, `(pat,)` is a tuple pattern. // For backward compatibility, `(..)` is a tuple pattern as well. @@ -589,7 +582,7 @@ impl<'a> Parser<'a> { err.span_label(self.token.span, msg); return Err(err); } - let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner(None))?; + let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner())?; Ok(PatKind::TupleStruct(path, fields)) } @@ -733,7 +726,7 @@ impl<'a> Parser<'a> { // Parsing a pattern of the form "fieldname: pat" let fieldname = self.parse_field_name()?; self.bump(); - let pat = self.parse_pat_with_or_inner(None)?; + let pat = self.parse_pat_with_or_inner()?; hi = pat.span; (pat, fieldname, false) } else { From 083963e58c752f1a51b67d65dc6a207bf69f1d64 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 25 Aug 2019 01:50:21 +0200 Subject: [PATCH 230/618] parser: 'while parsing this or-pattern...' --- src/libsyntax/parse/parser/pat.rs | 5 ++++- .../ui/or-patterns/while-parsing-this-or-pattern.rs | 9 +++++++++ .../or-patterns/while-parsing-this-or-pattern.stderr | 10 ++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/or-patterns/while-parsing-this-or-pattern.rs create mode 100644 src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 7c09dc4e56634..a0278fa407765 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -81,7 +81,10 @@ impl<'a> Parser<'a> { let lo = first_pat.span; let mut pats = vec![first_pat]; while self.eat_or_separator() { - let pat = self.parse_pat(None)?; + let pat = self.parse_pat(None).map_err(|mut err| { + err.span_label(lo, "while parsing this or-pattern staring here"); + err + })?; self.maybe_recover_unexpected_comma(pat.span, top_level)?; pats.push(pat); } diff --git a/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs b/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs new file mode 100644 index 0000000000000..4a9fae1406af7 --- /dev/null +++ b/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs @@ -0,0 +1,9 @@ +// Test the parser for the "while parsing this or-pattern..." label here. + +fn main() { + match Some(42) { + Some(42) | .=. => {} //~ ERROR expected pattern, found `.` + //~^ while parsing this or-pattern staring here + //~| NOTE expected pattern + } +} diff --git a/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr b/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr new file mode 100644 index 0000000000000..21fece6c64fe5 --- /dev/null +++ b/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr @@ -0,0 +1,10 @@ +error: expected pattern, found `.` + --> $DIR/while-parsing-this-or-pattern.rs:5:20 + | +LL | Some(42) | .=. => {} + | -------- ^ expected pattern + | | + | while parsing this or-pattern staring here + +error: aborting due to previous error + From 59c063302f3ce8e3020a94183c1cf4f203119ab2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 24 Aug 2019 14:16:56 -0700 Subject: [PATCH 231/618] Allow lifetime parameters to be inferred --- src/librustc/mir/mod.rs | 6 +++--- src/librustc_mir/dataflow/move_paths/mod.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 11701a6637744..654d3d780fcb2 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1555,7 +1555,7 @@ pub struct Statement<'tcx> { #[cfg(target_arch = "x86_64")] static_assert_size!(Statement<'_>, 56); -impl<'tcx> Statement<'tcx> { +impl Statement<'_> { /// Changes a statement to a nop. This is both faster than deleting instructions and avoids /// invalidating statement indices in `Location`s. pub fn make_nop(&mut self) { @@ -1677,7 +1677,7 @@ pub struct InlineAsm<'tcx> { pub inputs: Box<[(Span, Operand<'tcx>)]>, } -impl<'tcx> Debug for Statement<'tcx> { +impl Debug for Statement<'_> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { use self::StatementKind::*; match self.kind { @@ -2047,7 +2047,7 @@ impl<'p, 'tcx> Iterator for ProjectionsIter<'p, 'tcx> { impl<'p, 'tcx> FusedIterator for ProjectionsIter<'p, 'tcx> {} -impl<'tcx> Debug for Place<'tcx> { +impl Debug for Place<'_> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { self.iterate(|_place_base, place_projections| { // FIXME: remove this collect once we have migrated to slices diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 5c2255882b2c7..e5a19572170a7 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -240,7 +240,7 @@ impl MovePathLookup { // alternative will *not* create a MovePath on the fly for an // unknown place, but will rather return the nearest available // parent. - pub fn find(&self, place_ref: PlaceRef<'cx, 'tcx>) -> LookupResult { + pub fn find(&self, place_ref: PlaceRef<'_, '_>) -> LookupResult { place_ref.iterate(|place_base, place_projection| { let mut result = match place_base { PlaceBase::Local(local) => self.locals[*local], From 717e8a5219c491d0e8e865cc6abafc6fce6c4dff Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 24 Aug 2019 14:19:32 -0700 Subject: [PATCH 232/618] Join arms patterns, body is empty in all arms --- src/librustc/mir/visit.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 2d16e7bcc8371..24420cb4d7e91 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -724,10 +724,6 @@ macro_rules! make_mir_visitor { } match & $($mutability)? proj.elem { - ProjectionElem::Deref => { - } - ProjectionElem::Subslice { from: _, to: _ } => { - } ProjectionElem::Field(_field, ty) => { self.visit_ty(ty, TyContext::Location(location)); } @@ -738,11 +734,12 @@ macro_rules! make_mir_visitor { location ); } + ProjectionElem::Deref | + ProjectionElem::Subslice { from: _, to: _ } | ProjectionElem::ConstantIndex { offset: _, min_length: _, - from_end: _ } => { - } - ProjectionElem::Downcast(_name, _variant_index) => { + from_end: _ } | + ProjectionElem::Downcast(_, _) => { } } } From 53f47347941de87dff536f3875f0a62a7fda4459 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 24 Aug 2019 15:26:25 -0700 Subject: [PATCH 233/618] Add a period at the end of the sentence --- src/librustc_mir/borrow_check/prefixes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index ecafd4eb1157e..4c6be23de28be 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -136,7 +136,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { } PrefixSet::All => { // all prefixes: just blindly enqueue the base - // of the projection + // of the projection. self.next = Some(PlaceRef { base: cursor.base, projection: &proj.base, From fbe3f3e98f1cd5203b18ffacb176c70590390a63 Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Sun, 25 Aug 2019 13:01:46 +1000 Subject: [PATCH 234/618] debuginfo: give unique names to closure and generator types Closure types have been moved to the namespace where they are defined, and both closure and generator type names now include the disambiguator. This fixes an exception when lldb prints nested closures. Fixes #57822 --- .../debuginfo/metadata.rs | 10 +++- .../debuginfo/type_names.rs | 12 +++- src/test/debuginfo/issue-57822.rs | 55 +++++++++++++++++++ 3 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 src/test/debuginfo/issue-57822.rs diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 51e789b17880a..928532a1f4760 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -683,11 +683,13 @@ pub fn type_metadata( } ty::Closure(def_id, substs) => { let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx).collect(); + let containing_scope = get_namespace_for_item(cx, def_id); prepare_tuple_metadata(cx, t, &upvar_tys, unique_type_id, - usage_site_span).finalize(cx) + usage_site_span, + Some(containing_scope)).finalize(cx) } ty::Generator(def_id, substs, _) => { let upvar_tys : Vec<_> = substs.prefix_tys(def_id, cx.tcx).map(|t| { @@ -728,7 +730,8 @@ pub fn type_metadata( t, &tys, unique_type_id, - usage_site_span).finalize(cx) + usage_site_span, + NO_SCOPE_METADATA).finalize(cx) } _ => { bug!("debuginfo: unexpected type in type_metadata: {:?}", t) @@ -1205,6 +1208,7 @@ fn prepare_tuple_metadata( component_types: &[Ty<'tcx>], unique_type_id: UniqueTypeId, span: Span, + containing_scope: Option<&'ll DIScope>, ) -> RecursiveTypeDescription<'ll, 'tcx> { let tuple_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false); @@ -1212,7 +1216,7 @@ fn prepare_tuple_metadata( tuple_type, &tuple_name[..], unique_type_id, - NO_SCOPE_METADATA); + containing_scope); create_and_register_recursive_type_forward_declaration( cx, diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs index ea39913d4b91b..b7c782528de0c 100644 --- a/src/librustc_codegen_ssa/debuginfo/type_names.rs +++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs @@ -190,11 +190,19 @@ pub fn push_debuginfo_type_name<'tcx>( // processing visited.remove(t); }, - ty::Closure(..) => { + ty::Closure(def_id, ..) => { output.push_str("closure"); + let disambiguator = tcx.def_key(def_id).disambiguated_data.disambiguator; + if disambiguator != 0 { + output.push_str(&format!("-{}", disambiguator)); + } } - ty::Generator(..) => { + ty::Generator(def_id, ..) => { output.push_str("generator"); + let disambiguator = tcx.def_key(def_id).disambiguated_data.disambiguator; + if disambiguator != 0 { + output.push_str(&format!("-{}", disambiguator)); + } } ty::Error | ty::Infer(_) | diff --git a/src/test/debuginfo/issue-57822.rs b/src/test/debuginfo/issue-57822.rs new file mode 100644 index 0000000000000..ba5e8e0f2192a --- /dev/null +++ b/src/test/debuginfo/issue-57822.rs @@ -0,0 +1,55 @@ +// This test makes sure that the LLDB pretty printer does not throw an exception +// for nested closures and generators. + +// Require LLVM with DW_TAG_variant_part and a gdb that can read it. +// min-system-llvm-version: 8.0 +// min-gdb-version: 8.2 +// ignore-tidy-linelength + +// compile-flags:-g + +// === GDB TESTS =================================================================================== + +// gdb-command:run + +// gdb-command:print g +// gdb-check:$1 = issue_57822::main::closure-1 (issue_57822::main::closure (1)) + +// gdb-command:print b +// gdb-check:$2 = issue_57822::main::generator-3 {__0: issue_57822::main::generator-2 {__0: 2, <>: {[...]}}, <>: {[...]}} + +// === LLDB TESTS ================================================================================== + +// lldb-command:run + +// lldb-command:print g +// lldbg-check:(issue_57822::main::closure-1) $0 = closure-1(closure(1)) + +// lldb-command:print b +// lldbg-check:(issue_57822::main::generator-3) $1 = generator-3(generator-2(2)) + +#![feature(omit_gdb_pretty_printer_section, generators, generator_trait)] +#![omit_gdb_pretty_printer_section] + +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + let mut x = 1; + let f = move || x; + let g = move || f(); + + let mut y = 2; + let mut a = move || { + y += 1; + yield; + }; + let mut b = move || { + Pin::new(&mut a).resume(); + yield; + }; + + zzz(); // #break +} + +fn zzz() { () } From 1caaa40768fecb91b322b1e1befc91c54b56817c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 25 Aug 2019 04:39:28 +0200 Subject: [PATCH 235/618] parser: gracefully handle `fn foo(A | B: type)`. --- src/libsyntax/parse/parser.rs | 2 +- src/libsyntax/parse/parser/expr.rs | 4 +- src/libsyntax/parse/parser/pat.rs | 46 +++++++++++++++---- src/test/ui/anon-params-denied-2018.rs | 2 +- src/test/ui/anon-params-denied-2018.stderr | 16 +++---- .../feature-gate-or_patterns-leading.stderr | 12 ----- .../or-patterns/or-patterns-syntactic-fail.rs | 6 ++- .../or-patterns-syntactic-fail.stderr | 42 +++++++++++------ src/test/ui/parser/inverted-parameters.rs | 12 ++--- src/test/ui/parser/inverted-parameters.stderr | 24 +++++----- src/test/ui/parser/issue-33413.rs | 2 +- src/test/ui/parser/issue-33413.stderr | 4 +- src/test/ui/parser/issue-63135.rs | 2 +- src/test/ui/parser/issue-63135.stderr | 12 ++--- src/test/ui/parser/omitted-arg-in-item-fn.rs | 2 +- .../ui/parser/omitted-arg-in-item-fn.stderr | 4 +- src/test/ui/parser/pat-lt-bracket-2.rs | 2 +- src/test/ui/parser/pat-lt-bracket-2.stderr | 4 +- src/test/ui/parser/removed-syntax-mode.rs | 2 +- src/test/ui/parser/removed-syntax-mode.stderr | 4 +- .../rfc-2565-param-attrs/param-attrs-2018.rs | 2 +- .../param-attrs-2018.stderr | 4 +- src/test/ui/span/issue-34264.stderr | 12 ++--- 23 files changed, 125 insertions(+), 97 deletions(-) delete mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 002e9bccec72a..25ad2d4404cac 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -988,7 +988,7 @@ impl<'a> Parser<'a> { let (pat, ty) = if is_name_required || self.is_named_argument() { debug!("parse_arg_general parse_pat (is_name_required:{})", is_name_required); - let pat = self.parse_pat(Some("argument name"))?; + let pat = self.parse_fn_param_pat()?; if let Err(mut err) = self.expect(&token::Colon) { if let Some(ident) = self.argument_without_type( &mut err, diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 83e5a84a8c6ae..f7c090b5135e9 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1,7 +1,7 @@ use super::{Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle}; use super::{BlockMode, SemiColonMode}; use super::{SeqSep, TokenExpectType}; -use super::pat::GateOr; +use super::pat::{GateOr, PARAM_EXPECTED}; use crate::maybe_recover_from_interpolated_ty_qpath; use crate::ptr::P; @@ -1176,7 +1176,7 @@ impl<'a> Parser<'a> { fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> { let lo = self.token.span; let attrs = self.parse_arg_attributes()?; - let pat = self.parse_pat(Some("argument name"))?; + let pat = self.parse_pat(PARAM_EXPECTED)?; let t = if self.eat(&token::Colon) { self.parse_ty()? } else { diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index a0278fa407765..1541031ec2539 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -14,6 +14,9 @@ use errors::{Applicability, DiagnosticBuilder}; type Expected = Option<&'static str>; +/// `Expected` for function and lambda parameter patterns. +pub(super) const PARAM_EXPECTED: Expected = Some("parameter name"); + /// Whether or not an or-pattern should be gated when occurring in the current context. #[derive(PartialEq)] pub enum GateOr { Yes, No } @@ -49,7 +52,7 @@ impl<'a> Parser<'a> { let gated_leading_vert = self.eat_or_separator() && gate_or == GateOr::Yes; // Parse the possibly-or-pattern. - let pat = self.parse_pat_with_or(gate_or, TopLevel::Yes)?; + let pat = self.parse_pat_with_or(None, gate_or, TopLevel::Yes)?; // If we parsed a leading `|` which should be gated, // and no other gated or-pattern has been parsed thus far, @@ -65,11 +68,38 @@ impl<'a> Parser<'a> { Ok(pat) } + /// Parse the pattern for a function or function pointer parameter. + /// Special recovery is provided for or-patterns and leading `|`. + pub(super) fn parse_fn_param_pat(&mut self) -> PResult<'a, P> { + self.recover_leading_vert("not allowed in a parameter pattern"); + let pat = self.parse_pat_with_or(PARAM_EXPECTED, GateOr::No, TopLevel::No)?; + + if let PatKind::Or(..) = &pat.node { + self.ban_illegal_fn_param_or_pat(&pat); + } + + Ok(pat) + } + + /// Ban `A | B` immediately in a parameter pattern and suggest wrapping in parens. + fn ban_illegal_fn_param_or_pat(&self, pat: &Pat) { + let msg = "wrap the pattern in parenthesis"; + let fix = format!("({})", pprust::pat_to_string(pat)); + self.struct_span_err(pat.span, "an or-pattern parameter must be wrapped in parenthesis") + .span_suggestion(pat.span, msg, fix, Applicability::MachineApplicable) + .emit(); + } + /// Parses a pattern, that may be a or-pattern (e.g. `Foo | Bar` in `Some(Foo | Bar)`). /// Corresponds to `pat` in RFC 2535. - fn parse_pat_with_or(&mut self, gate_or: GateOr, top_level: TopLevel) -> PResult<'a, P> { + fn parse_pat_with_or( + &mut self, + expected: Expected, + gate_or: GateOr, + top_level: TopLevel, + ) -> PResult<'a, P> { // Parse the first pattern. - let first_pat = self.parse_pat(None)?; + let first_pat = self.parse_pat(expected)?; self.maybe_recover_unexpected_comma(first_pat.span, top_level)?; // If the next token is not a `|`, @@ -81,7 +111,7 @@ impl<'a> Parser<'a> { let lo = first_pat.span; let mut pats = vec![first_pat]; while self.eat_or_separator() { - let pat = self.parse_pat(None).map_err(|mut err| { + let pat = self.parse_pat(expected).map_err(|mut err| { err.span_label(lo, "while parsing this or-pattern staring here"); err })?; @@ -176,18 +206,18 @@ impl<'a> Parser<'a> { /// Recursive possibly-or-pattern parser with recovery for an erroneous leading `|`. /// See `parse_pat_with_or` for details on parsing or-patterns. fn parse_pat_with_or_inner(&mut self) -> PResult<'a, P> { - self.recover_inner_leading_vert(); - self.parse_pat_with_or(GateOr::Yes, TopLevel::No) + self.recover_leading_vert("only allowed in a top-level pattern"); + self.parse_pat_with_or(None, GateOr::Yes, TopLevel::No) } /// Recover if `|` or `||` is here. /// The user is thinking that a leading `|` is allowed in this position. - fn recover_inner_leading_vert(&mut self) { + fn recover_leading_vert(&mut self, ctx: &str) { if let token::BinOp(token::Or) | token::OrOr = self.token.kind { let span = self.token.span; let rm_msg = format!("remove the `{}`", pprust::token_to_string(&self.token)); - self.struct_span_err(span, "a leading `|` is only allowed in a top-level pattern") + self.struct_span_err(span, &format!("a leading `|` is {}", ctx)) .span_suggestion(span, &rm_msg, String::new(), Applicability::MachineApplicable) .emit(); diff --git a/src/test/ui/anon-params-denied-2018.rs b/src/test/ui/anon-params-denied-2018.rs index abff8275064e2..5721f5d235783 100644 --- a/src/test/ui/anon-params-denied-2018.rs +++ b/src/test/ui/anon-params-denied-2018.rs @@ -3,7 +3,7 @@ // edition:2018 trait T { - fn foo(i32); //~ expected one of `:` or `@`, found `)` + fn foo(i32); //~ expected one of `:`, `@`, or `|`, found `)` fn bar_with_default_impl(String, String) {} //~^ ERROR expected one of `:` diff --git a/src/test/ui/anon-params-denied-2018.stderr b/src/test/ui/anon-params-denied-2018.stderr index 438bcf4274daa..a58998e4891e0 100644 --- a/src/test/ui/anon-params-denied-2018.stderr +++ b/src/test/ui/anon-params-denied-2018.stderr @@ -1,8 +1,8 @@ -error: expected one of `:` or `@`, found `)` +error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/anon-params-denied-2018.rs:6:15 | LL | fn foo(i32); - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type @@ -14,11 +14,11 @@ help: if this is a type, explicitly ignore the parameter name LL | fn foo(_: i32); | ^^^^^^ -error: expected one of `:` or `@`, found `,` +error: expected one of `:`, `@`, or `|`, found `,` --> $DIR/anon-params-denied-2018.rs:8:36 | LL | fn bar_with_default_impl(String, String) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type @@ -30,11 +30,11 @@ help: if this is a type, explicitly ignore the parameter name LL | fn bar_with_default_impl(_: String, String) {} | ^^^^^^^^^ -error: expected one of `:` or `@`, found `)` +error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/anon-params-denied-2018.rs:8:44 | LL | fn bar_with_default_impl(String, String) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type @@ -46,11 +46,11 @@ help: if this is a type, explicitly ignore the parameter name LL | fn bar_with_default_impl(String, _: String) {} | ^^^^^^^^^ -error: expected one of `:` or `@`, found `,` +error: expected one of `:`, `@`, or `|`, found `,` --> $DIR/anon-params-denied-2018.rs:13:22 | LL | fn baz(a:usize, b, c: usize) -> usize { - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns-leading.stderr deleted file mode 100644 index 8b18082fca7df..0000000000000 --- a/src/test/ui/or-patterns/feature-gate-or_patterns-leading.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns-leading.rs:7:11 - | -LL | let | A; - | ^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/54883 - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs index 7959812f5b39c..b676ea851a3ba 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs @@ -25,7 +25,11 @@ fn no_top_level_or_patterns() { // -------- This looks like an or-pattern but is in fact `|A| (B: E | ())`. // ...and for now neither do we allow or-patterns at the top level of functions. - fn fun(A | B: E) {} //~ ERROR expected one of `:` or `@`, found `|` + fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parenthesis + + fn fun2(| A | B: E) {} + //~^ ERROR a leading `|` is not allowed in a parameter pattern + //~| ERROR an or-pattern parameter must be wrapped in parenthesis } // We also do not allow a leading `|` when not in a top level position: diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr index dd4c309ce85a3..2a3a6abfb7b62 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -1,59 +1,71 @@ -error: expected one of `:` or `@`, found `|` - --> $DIR/or-patterns-syntactic-fail.rs:28:14 +error: an or-pattern parameter must be wrapped in parenthesis + --> $DIR/or-patterns-syntactic-fail.rs:28:13 | -LL | fn fun(A | B: E) {} - | ^ expected one of `:` or `@` here +LL | fn fun1(A | B: E) {} + | ^^^^^ help: wrap the pattern in parenthesis: `(A | B)` + +error: a leading `|` is not allowed in a parameter pattern + --> $DIR/or-patterns-syntactic-fail.rs:30:13 + | +LL | fn fun2(| A | B: E) {} + | ^ help: remove the `|` + +error: an or-pattern parameter must be wrapped in parenthesis + --> $DIR/or-patterns-syntactic-fail.rs:30:15 + | +LL | fn fun2(| A | B: E) {} + | ^^^^^ help: wrap the pattern in parenthesis: `(A | B)` error: a leading `|` is only allowed in a top-level pattern - --> $DIR/or-patterns-syntactic-fail.rs:37:11 + --> $DIR/or-patterns-syntactic-fail.rs:41:11 | LL | let ( | A | B) = E::A; | ^ help: remove the `|` error: a leading `|` is only allowed in a top-level pattern - --> $DIR/or-patterns-syntactic-fail.rs:38:11 + --> $DIR/or-patterns-syntactic-fail.rs:42:11 | LL | let ( | A | B,) = (E::B,); | ^ help: remove the `|` error: a leading `|` is only allowed in a top-level pattern - --> $DIR/or-patterns-syntactic-fail.rs:39:11 + --> $DIR/or-patterns-syntactic-fail.rs:43:11 | LL | let [ | A | B ] = [E::A]; | ^ help: remove the `|` error: a leading `|` is only allowed in a top-level pattern - --> $DIR/or-patterns-syntactic-fail.rs:40:13 + --> $DIR/or-patterns-syntactic-fail.rs:44:13 | LL | let TS( | A | B ); | ^ help: remove the `|` error: a leading `|` is only allowed in a top-level pattern - --> $DIR/or-patterns-syntactic-fail.rs:41:17 + --> $DIR/or-patterns-syntactic-fail.rs:45:17 | LL | let NS { f: | A | B }; | ^ help: remove the `|` error: a leading `|` is only allowed in a top-level pattern - --> $DIR/or-patterns-syntactic-fail.rs:43:11 + --> $DIR/or-patterns-syntactic-fail.rs:47:11 | LL | let ( || A | B) = E::A; | ^^ help: remove the `||` error: a leading `|` is only allowed in a top-level pattern - --> $DIR/or-patterns-syntactic-fail.rs:44:11 + --> $DIR/or-patterns-syntactic-fail.rs:48:11 | LL | let [ || A | B ] = [E::A]; | ^^ help: remove the `||` error: a leading `|` is only allowed in a top-level pattern - --> $DIR/or-patterns-syntactic-fail.rs:45:13 + --> $DIR/or-patterns-syntactic-fail.rs:49:13 | LL | let TS( || A | B ); | ^^ help: remove the `||` error: a leading `|` is only allowed in a top-level pattern - --> $DIR/or-patterns-syntactic-fail.rs:46:17 + --> $DIR/or-patterns-syntactic-fail.rs:50:17 | LL | let NS { f: || A | B }; | ^^ help: remove the `||` @@ -95,7 +107,7 @@ LL | let _ = |A | B: E| (); = note: an implementation of `std::ops::BitOr` might be missing for `E` error[E0308]: mismatched types - --> $DIR/or-patterns-syntactic-fail.rs:48:36 + --> $DIR/or-patterns-syntactic-fail.rs:52:36 | LL | let recovery_witness: String = 0; | ^ @@ -106,7 +118,7 @@ LL | let recovery_witness: String = 0; = note: expected type `std::string::String` found type `{integer}` -error: aborting due to 14 previous errors +error: aborting due to 16 previous errors Some errors have detailed explanations: E0308, E0369. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/inverted-parameters.rs b/src/test/ui/parser/inverted-parameters.rs index f06b951041731..d6efc8be072bd 100644 --- a/src/test/ui/parser/inverted-parameters.rs +++ b/src/test/ui/parser/inverted-parameters.rs @@ -2,29 +2,29 @@ struct S; impl S { fn foo(&self, &str bar) {} - //~^ ERROR expected one of `:` or `@` + //~^ ERROR expected one of `:`, `@` //~| HELP declare the type after the parameter binding //~| SUGGESTION : } fn baz(S quux, xyzzy: i32) {} -//~^ ERROR expected one of `:` or `@` +//~^ ERROR expected one of `:`, `@` //~| HELP declare the type after the parameter binding //~| SUGGESTION : fn one(i32 a b) {} -//~^ ERROR expected one of `:` or `@` +//~^ ERROR expected one of `:`, `@` fn pattern((i32, i32) (a, b)) {} -//~^ ERROR expected `:` +//~^ ERROR expected one of `:` fn fizz(i32) {} -//~^ ERROR expected one of `:` or `@` +//~^ ERROR expected one of `:`, `@` //~| HELP if this was a parameter name, give it a type //~| HELP if this is a type, explicitly ignore the parameter name fn missing_colon(quux S) {} -//~^ ERROR expected one of `:` or `@` +//~^ ERROR expected one of `:`, `@` //~| HELP declare the type after the parameter binding //~| SUGGESTION : diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr index fb48bd1fe9383..2bda4460031a0 100644 --- a/src/test/ui/parser/inverted-parameters.stderr +++ b/src/test/ui/parser/inverted-parameters.stderr @@ -1,38 +1,38 @@ -error: expected one of `:` or `@`, found `bar` +error: expected one of `:`, `@`, or `|`, found `bar` --> $DIR/inverted-parameters.rs:4:24 | LL | fn foo(&self, &str bar) {} | -----^^^ | | | - | | expected one of `:` or `@` here + | | expected one of `:`, `@`, or `|` here | help: declare the type after the parameter binding: `: ` -error: expected one of `:` or `@`, found `quux` +error: expected one of `:`, `@`, or `|`, found `quux` --> $DIR/inverted-parameters.rs:10:10 | LL | fn baz(S quux, xyzzy: i32) {} | --^^^^ | | | - | | expected one of `:` or `@` here + | | expected one of `:`, `@`, or `|` here | help: declare the type after the parameter binding: `: ` -error: expected one of `:` or `@`, found `a` +error: expected one of `:`, `@`, or `|`, found `a` --> $DIR/inverted-parameters.rs:15:12 | LL | fn one(i32 a b) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here -error: expected `:`, found `(` +error: expected one of `:` or `|`, found `(` --> $DIR/inverted-parameters.rs:18:23 | LL | fn pattern((i32, i32) (a, b)) {} - | ^ expected `:` + | ^ expected one of `:` or `|` here -error: expected one of `:` or `@`, found `)` +error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/inverted-parameters.rs:21:12 | LL | fn fizz(i32) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type @@ -44,13 +44,13 @@ help: if this is a type, explicitly ignore the parameter name LL | fn fizz(_: i32) {} | ^^^^^^ -error: expected one of `:` or `@`, found `S` +error: expected one of `:`, `@`, or `|`, found `S` --> $DIR/inverted-parameters.rs:26:23 | LL | fn missing_colon(quux S) {} | -----^ | | | - | | expected one of `:` or `@` here + | | expected one of `:`, `@`, or `|` here | help: declare the type after the parameter binding: `: ` error: aborting due to 6 previous errors diff --git a/src/test/ui/parser/issue-33413.rs b/src/test/ui/parser/issue-33413.rs index 2ec86958174a4..22f80a8aae866 100644 --- a/src/test/ui/parser/issue-33413.rs +++ b/src/test/ui/parser/issue-33413.rs @@ -2,7 +2,7 @@ struct S; impl S { fn f(*, a: u8) -> u8 {} - //~^ ERROR expected argument name, found `*` + //~^ ERROR expected parameter name, found `*` } fn main() {} diff --git a/src/test/ui/parser/issue-33413.stderr b/src/test/ui/parser/issue-33413.stderr index f6f096b1b9a44..9e1178e8ac1f3 100644 --- a/src/test/ui/parser/issue-33413.stderr +++ b/src/test/ui/parser/issue-33413.stderr @@ -1,8 +1,8 @@ -error: expected argument name, found `*` +error: expected parameter name, found `*` --> $DIR/issue-33413.rs:4:10 | LL | fn f(*, a: u8) -> u8 {} - | ^ expected argument name + | ^ expected parameter name error: aborting due to previous error diff --git a/src/test/ui/parser/issue-63135.rs b/src/test/ui/parser/issue-63135.rs index d5f5f1469f35a..a5a8de85466bb 100644 --- a/src/test/ui/parser/issue-63135.rs +++ b/src/test/ui/parser/issue-63135.rs @@ -1,3 +1,3 @@ -// error-pattern: aborting due to 6 previous errors +// error-pattern: aborting due to 5 previous errors fn i(n{...,f # diff --git a/src/test/ui/parser/issue-63135.stderr b/src/test/ui/parser/issue-63135.stderr index c0286d90af744..a077ad454a9df 100644 --- a/src/test/ui/parser/issue-63135.stderr +++ b/src/test/ui/parser/issue-63135.stderr @@ -28,17 +28,11 @@ error: expected `[`, found `}` LL | fn i(n{...,f # | ^ expected `[` -error: expected `:`, found `)` +error: expected one of `:` or `|`, found `)` --> $DIR/issue-63135.rs:3:15 | LL | fn i(n{...,f # - | ^ expected `:` + | ^ expected one of `:` or `|` here -error: expected one of `->`, `where`, or `{`, found `` - --> $DIR/issue-63135.rs:3:15 - | -LL | fn i(n{...,f # - | ^ expected one of `->`, `where`, or `{` here - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.rs b/src/test/ui/parser/omitted-arg-in-item-fn.rs index 5ee9daf464055..49cbc4d6bf40f 100644 --- a/src/test/ui/parser/omitted-arg-in-item-fn.rs +++ b/src/test/ui/parser/omitted-arg-in-item-fn.rs @@ -1,4 +1,4 @@ -fn foo(x) { //~ ERROR expected one of `:` or `@`, found `)` +fn foo(x) { //~ ERROR expected one of `:`, `@`, or `|`, found `)` } fn main() {} diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.stderr b/src/test/ui/parser/omitted-arg-in-item-fn.stderr index e501f235d6d3b..7feb15592c54f 100644 --- a/src/test/ui/parser/omitted-arg-in-item-fn.stderr +++ b/src/test/ui/parser/omitted-arg-in-item-fn.stderr @@ -1,8 +1,8 @@ -error: expected one of `:` or `@`, found `)` +error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/omitted-arg-in-item-fn.rs:1:9 | LL | fn foo(x) { - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type diff --git a/src/test/ui/parser/pat-lt-bracket-2.rs b/src/test/ui/parser/pat-lt-bracket-2.rs index 6eb01c1c93337..3a778ed14f637 100644 --- a/src/test/ui/parser/pat-lt-bracket-2.rs +++ b/src/test/ui/parser/pat-lt-bracket-2.rs @@ -1,4 +1,4 @@ fn a(B<) {} - //~^ error: expected one of `:` or `@`, found `<` + //~^ error: expected one of `:`, `@`, or `|`, found `<` fn main() {} diff --git a/src/test/ui/parser/pat-lt-bracket-2.stderr b/src/test/ui/parser/pat-lt-bracket-2.stderr index cce1a17e9e8df..dbc8d0f5865c6 100644 --- a/src/test/ui/parser/pat-lt-bracket-2.stderr +++ b/src/test/ui/parser/pat-lt-bracket-2.stderr @@ -1,8 +1,8 @@ -error: expected one of `:` or `@`, found `<` +error: expected one of `:`, `@`, or `|`, found `<` --> $DIR/pat-lt-bracket-2.rs:1:7 | LL | fn a(B<) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here error: aborting due to previous error diff --git a/src/test/ui/parser/removed-syntax-mode.rs b/src/test/ui/parser/removed-syntax-mode.rs index 23851b5f70b37..a438db3b0c18b 100644 --- a/src/test/ui/parser/removed-syntax-mode.rs +++ b/src/test/ui/parser/removed-syntax-mode.rs @@ -1,4 +1,4 @@ fn f(+x: isize) {} -//~^ ERROR expected argument name, found `+` +//~^ ERROR expected parameter name, found `+` fn main() {} diff --git a/src/test/ui/parser/removed-syntax-mode.stderr b/src/test/ui/parser/removed-syntax-mode.stderr index 5e7139d6bfd85..d0393b379f06d 100644 --- a/src/test/ui/parser/removed-syntax-mode.stderr +++ b/src/test/ui/parser/removed-syntax-mode.stderr @@ -1,8 +1,8 @@ -error: expected argument name, found `+` +error: expected parameter name, found `+` --> $DIR/removed-syntax-mode.rs:1:6 | LL | fn f(+x: isize) {} - | ^ expected argument name + | ^ expected parameter name error: aborting due to previous error diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs index e900ccab4fd83..d71711336b06e 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs @@ -3,6 +3,6 @@ #![feature(param_attrs)] trait Trait2015 { fn foo(#[allow(C)] i32); } -//~^ ERROR expected one of `:` or `@`, found `)` +//~^ ERROR expected one of `:`, `@`, or `|`, found `)` fn main() {} diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr index d0ed65f288011..26b414e426805 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr @@ -1,8 +1,8 @@ -error: expected one of `:` or `@`, found `)` +error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/param-attrs-2018.rs:5:41 | LL | trait Trait2015 { fn foo(#[allow(C)] i32); } - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index 5dd9895c6e4f4..cc0eccd37a26f 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -1,14 +1,14 @@ -error: expected one of `:` or `@`, found `<` +error: expected one of `:`, `@`, or `|`, found `<` --> $DIR/issue-34264.rs:1:14 | LL | fn foo(Option, String) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here -error: expected one of `:` or `@`, found `)` +error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/issue-34264.rs:1:27 | LL | fn foo(Option, String) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type @@ -20,11 +20,11 @@ help: if this is a type, explicitly ignore the parameter name LL | fn foo(Option, _: String) {} | ^^^^^^^^^ -error: expected one of `:` or `@`, found `,` +error: expected one of `:`, `@`, or `|`, found `,` --> $DIR/issue-34264.rs:3:9 | LL | fn bar(x, y: usize) {} - | ^ expected one of `:` or `@` here + | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type From 6a73199da6c06c0b71ed6eeca578b00925137664 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 25 Aug 2019 05:45:51 +0200 Subject: [PATCH 236/618] or_patterns: add run-rustfix tests. --- .../ui/or-patterns/fn-param-wrap-parens.fixed | 14 ++++ .../ui/or-patterns/fn-param-wrap-parens.rs | 14 ++++ .../or-patterns/fn-param-wrap-parens.stderr | 8 +++ .../ui/or-patterns/remove-leading-vert.fixed | 23 +++++++ .../ui/or-patterns/remove-leading-vert.rs | 23 +++++++ .../ui/or-patterns/remove-leading-vert.stderr | 68 +++++++++++++++++++ 6 files changed, 150 insertions(+) create mode 100644 src/test/ui/or-patterns/fn-param-wrap-parens.fixed create mode 100644 src/test/ui/or-patterns/fn-param-wrap-parens.rs create mode 100644 src/test/ui/or-patterns/fn-param-wrap-parens.stderr create mode 100644 src/test/ui/or-patterns/remove-leading-vert.fixed create mode 100644 src/test/ui/or-patterns/remove-leading-vert.rs create mode 100644 src/test/ui/or-patterns/remove-leading-vert.stderr diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.fixed b/src/test/ui/or-patterns/fn-param-wrap-parens.fixed new file mode 100644 index 0000000000000..08730fe8b07b7 --- /dev/null +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.fixed @@ -0,0 +1,14 @@ +// Test the suggestion to wrap an or-pattern as a function parameter in parens. + +// run-rustfix + +#![feature(or_patterns)] +#![allow(warnings)] + +fn main() {} + +enum E { A, B } +use E::*; + +#[cfg(FALSE)] +fn fun1((A | B): E) {} //~ ERROR an or-pattern parameter must be wrapped in parenthesis diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.rs b/src/test/ui/or-patterns/fn-param-wrap-parens.rs new file mode 100644 index 0000000000000..ed667e0e66067 --- /dev/null +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.rs @@ -0,0 +1,14 @@ +// Test the suggestion to wrap an or-pattern as a function parameter in parens. + +// run-rustfix + +#![feature(or_patterns)] +#![allow(warnings)] + +fn main() {} + +enum E { A, B } +use E::*; + +#[cfg(FALSE)] +fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parenthesis diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.stderr b/src/test/ui/or-patterns/fn-param-wrap-parens.stderr new file mode 100644 index 0000000000000..2c6e4d9838ddc --- /dev/null +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.stderr @@ -0,0 +1,8 @@ +error: an or-pattern parameter must be wrapped in parenthesis + --> $DIR/fn-param-wrap-parens.rs:14:9 + | +LL | fn fun1(A | B: E) {} + | ^^^^^ help: wrap the pattern in parenthesis: `(A | B)` + +error: aborting due to previous error + diff --git a/src/test/ui/or-patterns/remove-leading-vert.fixed b/src/test/ui/or-patterns/remove-leading-vert.fixed new file mode 100644 index 0000000000000..e96d76061ac28 --- /dev/null +++ b/src/test/ui/or-patterns/remove-leading-vert.fixed @@ -0,0 +1,23 @@ +// Test the suggestion to remove a leading `|`. + +// run-rustfix + +#![feature(or_patterns)] +#![allow(warnings)] + +fn main() {} + +#[cfg(FALSE)] +fn leading_vert() { + fn fun1( A: E) {} //~ ERROR a leading `|` is not allowed in a parameter pattern + fn fun2( A: E) {} //~ ERROR a leading `|` is not allowed in a parameter pattern + let ( A): E; //~ ERROR a leading `|` is only allowed in a top-level pattern + let ( A): (E); //~ ERROR a leading `|` is only allowed in a top-level pattern + let ( A,): (E,); //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ A ]: [E; 1]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ A ]: [E; 1]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( A ): TS; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( A ): TS; //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: A }: NS; //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: A }: NS; //~ ERROR a leading `|` is only allowed in a top-level pattern +} diff --git a/src/test/ui/or-patterns/remove-leading-vert.rs b/src/test/ui/or-patterns/remove-leading-vert.rs new file mode 100644 index 0000000000000..3790b17553fe3 --- /dev/null +++ b/src/test/ui/or-patterns/remove-leading-vert.rs @@ -0,0 +1,23 @@ +// Test the suggestion to remove a leading `|`. + +// run-rustfix + +#![feature(or_patterns)] +#![allow(warnings)] + +fn main() {} + +#[cfg(FALSE)] +fn leading_vert() { + fn fun1( | A: E) {} //~ ERROR a leading `|` is not allowed in a parameter pattern + fn fun2( || A: E) {} //~ ERROR a leading `|` is not allowed in a parameter pattern + let ( | A): E; //~ ERROR a leading `|` is only allowed in a top-level pattern + let ( || A): (E); //~ ERROR a leading `|` is only allowed in a top-level pattern + let ( | A,): (E,); //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ | A ]: [E; 1]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ || A ]: [E; 1]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( | A ): TS; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( || A ): TS; //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: | A }: NS; //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: || A }: NS; //~ ERROR a leading `|` is only allowed in a top-level pattern +} diff --git a/src/test/ui/or-patterns/remove-leading-vert.stderr b/src/test/ui/or-patterns/remove-leading-vert.stderr new file mode 100644 index 0000000000000..cbe06f997296a --- /dev/null +++ b/src/test/ui/or-patterns/remove-leading-vert.stderr @@ -0,0 +1,68 @@ +error: a leading `|` is not allowed in a parameter pattern + --> $DIR/remove-leading-vert.rs:12:14 + | +LL | fn fun1( | A: E) {} + | ^ help: remove the `|` + +error: a leading `|` is not allowed in a parameter pattern + --> $DIR/remove-leading-vert.rs:13:14 + | +LL | fn fun2( || A: E) {} + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:14:11 + | +LL | let ( | A): E; + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:15:11 + | +LL | let ( || A): (E); + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:16:11 + | +LL | let ( | A,): (E,); + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:17:11 + | +LL | let [ | A ]: [E; 1]; + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:18:11 + | +LL | let [ || A ]: [E; 1]; + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:19:13 + | +LL | let TS( | A ): TS; + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:20:13 + | +LL | let TS( || A ): TS; + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:21:17 + | +LL | let NS { f: | A }: NS; + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/remove-leading-vert.rs:22:17 + | +LL | let NS { f: || A }: NS; + | ^^ help: remove the `||` + +error: aborting due to 11 previous errors + From acb11305e8d7298750797d45324c0ecb3cc6c256 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 25 Aug 2019 06:15:11 +0200 Subject: [PATCH 237/618] parser: TopLevel -> RecoverComma. --- src/libsyntax/parse/parser/pat.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 1541031ec2539..f2e269e03baf9 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -21,9 +21,9 @@ pub(super) const PARAM_EXPECTED: Expected = Some("parameter name"); #[derive(PartialEq)] pub enum GateOr { Yes, No } -/// Whether or not this is the top level pattern context. +/// Whether or not to recover a `,` when parsing or-patterns. #[derive(PartialEq, Copy, Clone)] -enum TopLevel { Yes, No } +enum RecoverComma { Yes, No } impl<'a> Parser<'a> { /// Parses a pattern. @@ -52,7 +52,7 @@ impl<'a> Parser<'a> { let gated_leading_vert = self.eat_or_separator() && gate_or == GateOr::Yes; // Parse the possibly-or-pattern. - let pat = self.parse_pat_with_or(None, gate_or, TopLevel::Yes)?; + let pat = self.parse_pat_with_or(None, gate_or, RecoverComma::Yes)?; // If we parsed a leading `|` which should be gated, // and no other gated or-pattern has been parsed thus far, @@ -72,7 +72,7 @@ impl<'a> Parser<'a> { /// Special recovery is provided for or-patterns and leading `|`. pub(super) fn parse_fn_param_pat(&mut self) -> PResult<'a, P> { self.recover_leading_vert("not allowed in a parameter pattern"); - let pat = self.parse_pat_with_or(PARAM_EXPECTED, GateOr::No, TopLevel::No)?; + let pat = self.parse_pat_with_or(PARAM_EXPECTED, GateOr::No, RecoverComma::No)?; if let PatKind::Or(..) = &pat.node { self.ban_illegal_fn_param_or_pat(&pat); @@ -96,11 +96,11 @@ impl<'a> Parser<'a> { &mut self, expected: Expected, gate_or: GateOr, - top_level: TopLevel, + rc: RecoverComma, ) -> PResult<'a, P> { // Parse the first pattern. let first_pat = self.parse_pat(expected)?; - self.maybe_recover_unexpected_comma(first_pat.span, top_level)?; + self.maybe_recover_unexpected_comma(first_pat.span, rc)?; // If the next token is not a `|`, // this is not an or-pattern and we should exit here. @@ -115,7 +115,7 @@ impl<'a> Parser<'a> { err.span_label(lo, "while parsing this or-pattern staring here"); err })?; - self.maybe_recover_unexpected_comma(pat.span, top_level)?; + self.maybe_recover_unexpected_comma(pat.span, rc)?; pats.push(pat); } let or_pattern_span = lo.to(self.prev_span); @@ -156,8 +156,8 @@ impl<'a> Parser<'a> { /// Some special error handling for the "top-level" patterns in a match arm, /// `for` loop, `let`, &c. (in contrast to subpatterns within such). - fn maybe_recover_unexpected_comma(&mut self, lo: Span, top_level: TopLevel) -> PResult<'a, ()> { - if top_level == TopLevel::No || self.token != token::Comma { + fn maybe_recover_unexpected_comma(&mut self, lo: Span, rc: RecoverComma) -> PResult<'a, ()> { + if rc == RecoverComma::No || self.token != token::Comma { return Ok(()); } @@ -207,7 +207,7 @@ impl<'a> Parser<'a> { /// See `parse_pat_with_or` for details on parsing or-patterns. fn parse_pat_with_or_inner(&mut self) -> PResult<'a, P> { self.recover_leading_vert("only allowed in a top-level pattern"); - self.parse_pat_with_or(None, GateOr::Yes, TopLevel::No) + self.parse_pat_with_or(None, GateOr::Yes, RecoverComma::No) } /// Recover if `|` or `||` is here. From c9d9616e825fecd4301beaf7bcd9115d5d7d393f Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Sat, 24 Aug 2019 17:50:21 +0200 Subject: [PATCH 238/618] Introduce and use `Feature` type for feature gates This replaces the ad-hoc tuples used in the different feature gate files and unifies their content into a common type, leading to more readable matches and other good stuff that comes from having named fields. It also contains the description of each feature as extracted from the doc comment. --- src/libsyntax/feature_gate/accepted.rs | 16 ++++++++++--- src/libsyntax/feature_gate/active.rs | 10 ++++++++ src/libsyntax/feature_gate/check.rs | 33 ++++++++++++++------------ src/libsyntax/feature_gate/mod.rs | 33 ++++++++++++++++++++++++++ src/libsyntax/feature_gate/removed.rs | 29 ++++++++++++++++++---- 5 files changed, 98 insertions(+), 23 deletions(-) diff --git a/src/libsyntax/feature_gate/accepted.rs b/src/libsyntax/feature_gate/accepted.rs index 28e4d2c073c7c..6c0b271c6c5e9 100644 --- a/src/libsyntax/feature_gate/accepted.rs +++ b/src/libsyntax/feature_gate/accepted.rs @@ -1,14 +1,24 @@ //! List of the accepted feature gates. -use crate::symbol::{Symbol, sym}; +use crate::symbol::sym; +use super::{State, Feature}; macro_rules! declare_features { ($( $(#[doc = $doc:tt])* (accepted, $feature:ident, $ver:expr, $issue:expr, None), )+) => { /// Those language feature has since been Accepted (it was once Active) - pub const ACCEPTED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ - $((sym::$feature, $ver, $issue, None)),+ + pub const ACCEPTED_FEATURES: &[Feature] = &[ + $( + Feature { + state: State::Accepted, + name: sym::$feature, + since: $ver, + issue: $issue, + edition: None, + description: concat!($($doc,)*), + } + ),+ ]; } } diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 4008b79b141eb..c947b09fdcb57 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -65,6 +65,16 @@ macro_rules! declare_features { }; } +impl Feature { + /// Set this feature in `Features`. Panics if called on a non-active feature. + pub fn set(&self, features: &mut Features, span: Span) { + match self.state { + State::Active { set } => set(features, span), + _ => panic!("Called `set` on feature `{}` which is not `active`", self.name) + } + } +} + // If you change this, please modify `src/doc/unstable-book` as well. // // Don't ever remove anything from this list; move them to `removed.rs`. diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index d82b287b6fb05..344e5fd6e46c2 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -1,4 +1,4 @@ -use super::active::{ACTIVE_FEATURES, Features}; +use super::{active::{ACTIVE_FEATURES, Features}, Feature, State as FeatureState}; use super::accepted::ACCEPTED_FEATURES; use super::removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES}; use super::builtin_attrs::{AttributeGate, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; @@ -127,17 +127,16 @@ pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: } fn find_lang_feature_issue(feature: Symbol) -> Option { - if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) { - let issue = info.2; + if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.name == feature) { // FIXME (#28244): enforce that active features have issue numbers - // assert!(issue.is_some()) - issue + // assert!(info.issue.is_some()) + info.issue } else { // search in Accepted, Removed, or Stable Removed features let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES) - .find(|t| t.0 == feature); + .find(|t| t.name == feature); match found { - Some(&(_, _, issue, _)) => issue, + Some(&Feature { issue, .. }) => issue, None => panic!("Feature `{}` is not declared anywhere", feature), } } @@ -829,14 +828,18 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], continue; } - let removed = REMOVED_FEATURES.iter().find(|f| name == f.0); - let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.0); - if let Some((.., reason)) = removed.or(stable_removed) { - feature_removed(span_handler, mi.span(), *reason); - continue; + let removed = REMOVED_FEATURES.iter().find(|f| name == f.name); + let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name); + if let Some(Feature { state, .. }) = removed.or(stable_removed) { + if let FeatureState::Removed { reason } + | FeatureState::Stabilized { reason } = state + { + feature_removed(span_handler, mi.span(), *reason); + continue; + } } - if let Some((_, since, ..)) = ACCEPTED_FEATURES.iter().find(|f| name == f.0) { + if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) { let since = Some(Symbol::intern(since)); features.declared_lang_features.push((name, mi.span(), since)); continue; @@ -851,8 +854,8 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } } - if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) { - set(&mut features, mi.span()); + if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) { + f.set(&mut features, mi.span()); features.declared_lang_features.push((name, mi.span(), None)); continue; } diff --git a/src/libsyntax/feature_gate/mod.rs b/src/libsyntax/feature_gate/mod.rs index 97793bca1f589..1e41667ea411e 100644 --- a/src/libsyntax/feature_gate/mod.rs +++ b/src/libsyntax/feature_gate/mod.rs @@ -18,6 +18,39 @@ mod active; mod builtin_attrs; mod check; +use std::fmt; +use crate::{edition::Edition, symbol::Symbol}; +use syntax_pos::Span; + +#[derive(Clone, Copy)] +pub enum State { + Accepted, + Active { set: fn(&mut Features, Span) }, + Removed { reason: Option<&'static str> }, + Stabilized { reason: Option<&'static str> }, +} + +impl fmt::Debug for State { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + State::Accepted { .. } => write!(f, "accepted"), + State::Active { .. } => write!(f, "active"), + State::Removed { .. } => write!(f, "removed"), + State::Stabilized { .. } => write!(f, "stabilized"), + } + } +} + +#[derive(Debug, Clone)] +pub struct Feature { + state: State, + name: Symbol, + since: &'static str, + issue: Option, + edition: Option, + description: &'static str, +} + pub use active::{Features, INCOMPLETE_FEATURES}; pub use builtin_attrs::{ AttributeGate, AttributeType, GatedCfg, diff --git a/src/libsyntax/feature_gate/removed.rs b/src/libsyntax/feature_gate/removed.rs index 6494c82e1228b..ad7d69b3e7372 100644 --- a/src/libsyntax/feature_gate/removed.rs +++ b/src/libsyntax/feature_gate/removed.rs @@ -1,14 +1,24 @@ //! List of the removed feature gates. -use crate::symbol::{Symbol, sym}; +use crate::symbol::sym; +use super::{State, Feature}; macro_rules! declare_features { ($( $(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, None, $reason:expr), )+) => { /// Represents unstable features which have since been removed (it was once Active) - pub const REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ - $((sym::$feature, $ver, $issue, $reason)),+ + pub const REMOVED_FEATURES: &[Feature] = &[ + $( + Feature { + state: State::Removed { reason: $reason }, + name: sym::$feature, + since: $ver, + issue: $issue, + edition: None, + description: concat!($($doc,)*), + } + ),+ ]; }; @@ -16,8 +26,17 @@ macro_rules! declare_features { $(#[doc = $doc:tt])* (stable_removed, $feature:ident, $ver:expr, $issue:expr, None), )+) => { /// Represents stable features which have since been removed (it was once Accepted) - pub const STABLE_REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ - $((sym::$feature, $ver, $issue, None)),+ + pub const STABLE_REMOVED_FEATURES: &[Feature] = &[ + $( + Feature { + state: State::Stabilized { reason: None }, + name: sym::$feature, + since: $ver, + issue: $issue, + edition: None, + description: concat!($($doc,)*), + } + ),+ ]; }; } From fcbbf8d312c01b6287f4011f27ddb953c3182501 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 24 Aug 2019 15:18:16 +0200 Subject: [PATCH 239/618] Fix system theme detection --- src/librustdoc/html/static/storage.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index c55b1e414436c..ab2cf8f796d48 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -118,7 +118,8 @@ function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) { } function getSystemValue() { - return getComputedStyle(document.documentElement).getPropertyValue('content'); + var property = getComputedStyle(document.documentElement).getPropertyValue('content'); + return property.replace(/\"\'/g, ""); } switchTheme(currentTheme, mainTheme, From 4f30d2ae5a4bae7ab5ce661f4b98efd76e0b1615 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 25 Aug 2019 12:54:31 +0200 Subject: [PATCH 240/618] submodules: update clippy from 2bcb6155948e2f8b86db08152a5f54bd5af625e5 to 05f603e6cec63d0b2681a84d4a64a51bccac1624 --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index 2bcb6155948e2..05f603e6cec63 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 2bcb6155948e2f8b86db08152a5f54bd5af625e5 +Subproject commit 05f603e6cec63d0b2681a84d4a64a51bccac1624 From 92e75c0f88a5cc09642285fe61a4c1be14fe314d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Aug 2019 13:57:46 +0200 Subject: [PATCH 241/618] factor wide ptr metadata checking into separate method also fat -> wide --- src/librustc_mir/interpret/validity.rs | 75 +++++++++++-------- .../consts/const-eval/union-ub-fat-ptr.stderr | 12 +-- 2 files changed, 48 insertions(+), 39 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 82d6d7db01c8d..f358a21f4af76 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -11,7 +11,7 @@ use std::hash::Hash; use super::{ GlobalAlloc, InterpResult, - OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy, + Scalar, OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy, }; macro_rules! throw_validation_failure { @@ -250,6 +250,44 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M self.path.truncate(path_len); Ok(()) } + + fn check_wide_ptr_meta( + &mut self, + meta: Option>, + pointee: TyLayout<'tcx>, + ) -> InterpResult<'tcx> { + let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env); + match tail.sty { + ty::Dynamic(..) => { + let vtable = meta.unwrap(); + try_validation!( + self.ecx.memory.check_ptr_access( + vtable, + 3*self.ecx.tcx.data_layout.pointer_size, // drop, size, align + self.ecx.tcx.data_layout.pointer_align.abi, + ), + "dangling or unaligned vtable pointer in wide pointer or too small vtable", + self.path + ); + try_validation!(self.ecx.read_drop_type_from_vtable(vtable), + "invalid drop fn in vtable", self.path); + try_validation!(self.ecx.read_size_and_align_from_vtable(vtable), + "invalid size or align in vtable", self.path); + // FIXME: More checks for the vtable. + } + ty::Slice(..) | ty::Str => { + try_validation!(meta.unwrap().to_usize(self.ecx), + "non-integer slice length in wide pointer", self.path); + } + ty::Foreign(..) => { + // Unsized, but not wide. + } + _ => + bug!("Unexpected unsized type tail: {:?}", tail), + } + + Ok(()) + } } impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> @@ -353,44 +391,15 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } } _ if ty.is_box() || ty.is_region_ptr() => { - // Handle fat pointers. + // Handle wide pointers. // Check metadata early, for better diagnostics let ptr = try_validation!(value.to_scalar_ptr(), "undefined address in pointer", self.path); let meta = try_validation!(value.to_meta(), - "uninitialized data in fat pointer metadata", self.path); + "uninitialized data in wide pointer metadata", self.path); let layout = self.ecx.layout_of(value.layout.ty.builtin_deref(true).unwrap().ty)?; if layout.is_unsized() { - let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(layout.ty, - self.ecx.param_env); - match tail.sty { - ty::Dynamic(..) => { - let vtable = meta.unwrap(); - try_validation!( - self.ecx.memory.check_ptr_access( - vtable, - 3*self.ecx.tcx.data_layout.pointer_size, // drop, size, align - self.ecx.tcx.data_layout.pointer_align.abi, - ), - "dangling or unaligned vtable pointer or too small vtable", - self.path - ); - try_validation!(self.ecx.read_drop_type_from_vtable(vtable), - "invalid drop fn in vtable", self.path); - try_validation!(self.ecx.read_size_and_align_from_vtable(vtable), - "invalid size or align in vtable", self.path); - // FIXME: More checks for the vtable. - } - ty::Slice(..) | ty::Str => { - try_validation!(meta.unwrap().to_usize(self.ecx), - "non-integer slice length in fat pointer", self.path); - } - ty::Foreign(..) => { - // Unsized, but not fat. - } - _ => - bug!("Unexpected unsized type tail: {:?}", tail), - } + self.check_wide_ptr_meta(meta, layout)?; } // Make sure this is dereferencable and all. let (size, align) = self.ecx.size_and_align_of(meta, layout)? diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr b/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr index aac32ecc5b747..54c33006d2b15 100644 --- a/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr +++ b/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub-fat-ptr.rs:81:1 | LL | const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub-fat-ptr.rs:84:1 | LL | const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -34,7 +34,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub-fat-ptr.rs:93:1 | LL | const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -42,7 +42,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub-fat-ptr.rs:97:1 | LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -50,7 +50,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub-fat-ptr.rs:100:1 | LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -58,7 +58,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub-fat-ptr.rs:103:1 | LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior From 96baf1c54e4049b7fe2fe699ede58bde1dcb2232 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Aug 2019 14:26:56 +0200 Subject: [PATCH 242/618] validate raw wide pointers --- src/librustc_mir/interpret/validity.rs | 11 +- .../{union-ub-fat-ptr.rs => ub-wide-ptr.rs} | 72 +++++++---- ...n-ub-fat-ptr.stderr => ub-wide-ptr.stderr} | 116 +++++++++++------- 3 files changed, 131 insertions(+), 68 deletions(-) rename src/test/ui/consts/const-eval/{union-ub-fat-ptr.rs => ub-wide-ptr.rs} (61%) rename src/test/ui/consts/const-eval/{union-ub-fat-ptr.stderr => ub-wide-ptr.stderr} (62%) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index f358a21f4af76..f3ce7df8d0677 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -379,16 +379,23 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } } ty::RawPtr(..) => { + // Check pointer part. if self.ref_tracking_for_consts.is_some() { // Integers/floats in CTFE: For consistency with integers, we do not // accept undef. let _ptr = try_validation!(value.to_scalar_ptr(), "undefined address in raw pointer", self.path); - let _meta = try_validation!(value.to_meta(), - "uninitialized data in raw fat pointer metadata", self.path); } else { // Remain consistent with `usize`: Accept anything. } + + // Check metadata. + let meta = try_validation!(value.to_meta(), + "uninitialized data in wide pointer metadata", self.path); + let layout = self.ecx.layout_of(value.layout.ty.builtin_deref(true).unwrap().ty)?; + if layout.is_unsized() { + self.check_wide_ptr_meta(meta, layout)?; + } } _ if ty.is_box() || ty.is_region_ptr() => { // Handle wide pointers. diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs similarity index 61% rename from src/test/ui/consts/const-eval/union-ub-fat-ptr.rs rename to src/test/ui/consts/const-eval/ub-wide-ptr.rs index d5405f3441fec..23a82bb10ea17 100644 --- a/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -1,3 +1,4 @@ +// ignore-tidy-linelength #![allow(unused)] #![allow(const_err)] // make sure we cannot allow away the errors tested here @@ -28,7 +29,9 @@ struct BadSliceRepr { union SliceTransmute { repr: SliceRepr, bad: BadSliceRepr, + addr: usize, slice: &'static [u8], + raw_slice: *const [u8], str: &'static str, my_str: &'static MyStr, my_slice: &'static MySliceBool, @@ -59,7 +62,9 @@ union DynTransmute { repr: DynRepr, repr2: DynRepr2, bad: BadDynRepr, + addr: usize, rust: &'static dyn Trait, + raw_rust: *const dyn Trait, } trait Trait {} @@ -72,39 +77,37 @@ struct MyStr(str); struct MySlice(bool, T); type MySliceBool = MySlice<[bool]>; +// # str // OK -const A: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str}; +const STR_VALID: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str}; // bad str -const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; +const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; //~^ ERROR it is undefined behavior to use this value // bad str -const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; +const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; //~^ ERROR it is undefined behavior to use this value // bad str in user-defined unsized type -const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; +const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; //~^ ERROR it is undefined behavior to use this value -// OK -const A2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice}; -// bad slice -const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; +// invalid UTF-8 +const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; //~^ ERROR it is undefined behavior to use this value -// bad slice -const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; +// invalid UTF-8 in user-defined str-like +const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; //~^ ERROR it is undefined behavior to use this value -// bad trait object -const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; -//~^ ERROR it is undefined behavior to use this value -// bad trait object -const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; +// # slice +// OK +const SLICE_VALID: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice}; +// bad slice: length uninit +const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; //~^ ERROR it is undefined behavior to use this value -// bad trait object -const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; +// bad slice: length too big +const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; //~^ ERROR it is undefined behavior to use this value - -// bad data *inside* the trait object -const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; +// bad slice: length not an int +const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; //~^ ERROR it is undefined behavior to use this value // bad data *inside* the slice @@ -120,12 +123,33 @@ const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); //~^ ERROR it is undefined behavior to use this value -// invalid UTF-8 -const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; +// # raw slice +const RAW_SLICE_VALID: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.raw_slice}; // ok +const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.raw_slice}; // ok because raw +const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; //~^ ERROR it is undefined behavior to use this value -// invalid UTF-8 in user-defined str-like -const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; + +// # trait object +// bad trait object +const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; +//~^ ERROR it is undefined behavior to use this value +// bad trait object +const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; +//~^ ERROR it is undefined behavior to use this value +// bad trait object +const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; +//~^ ERROR it is undefined behavior to use this value + +// bad data *inside* the trait object +const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; +//~^ ERROR it is undefined behavior to use this value + +// # raw trait object +const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; +//~^ ERROR it is undefined behavior to use this value +const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; //~^ ERROR it is undefined behavior to use this value +const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw fn main() { } diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr similarity index 62% rename from src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr rename to src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 54c33006d2b15..985df3b1c8bc5 100644 --- a/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -1,77 +1,69 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:78:1 + --> $DIR/ub-wide-ptr.rs:84:1 | -LL | const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) +LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:81:1 + --> $DIR/ub-wide-ptr.rs:87:1 | -LL | const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer +LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:84:1 + --> $DIR/ub-wide-ptr.rs:90:1 | -LL | const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer +LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:90:1 + --> $DIR/ub-wide-ptr.rs:94:1 | -LL | const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) +LL | const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:93:1 + --> $DIR/ub-wide-ptr.rs:97:1 | -LL | const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer +LL | const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:97:1 + --> $DIR/ub-wide-ptr.rs:104:1 | -LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:100:1 + --> $DIR/ub-wide-ptr.rs:107:1 | -LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:103:1 + --> $DIR/ub-wide-ptr.rs:110:1 | -LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:107:1 - | -LL | const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:111:1 + --> $DIR/ub-wide-ptr.rs:114:1 | LL | const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected something less or equal to 1 @@ -79,7 +71,7 @@ LL | const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:117:1 + --> $DIR/ub-wide-ptr.rs:120:1 | LL | const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected something less or equal to 1 @@ -87,7 +79,7 @@ LL | const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:120:1 + --> $DIR/ub-wide-ptr.rs:123:1 | LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected something less or equal to 1 @@ -95,21 +87,61 @@ LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }. = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:124:1 + --> $DIR/ub-wide-ptr.rs:129:1 | -LL | const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . +LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:127:1 + --> $DIR/ub-wide-ptr.rs:134:1 | -LL | const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 +LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:137:1 + | +LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:140:1 + | +LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:144:1 + | +LL | const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:148:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:150:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior -error: aborting due to 14 previous errors +error: aborting due to 18 previous errors For more information about this error, try `rustc --explain E0080`. From 0c1cb32b8440319d8a15d920a3d35e124ae52b43 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Aug 2019 14:47:01 +0200 Subject: [PATCH 243/618] test for too long slices --- src/librustc_mir/interpret/validity.rs | 16 ++++++++++++-- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 2 ++ .../ui/consts/const-eval/ub-wide-ptr.stderr | 22 +++++++++++++------ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index f3ce7df8d0677..7af55a2a3a376 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -3,7 +3,7 @@ use std::ops::RangeInclusive; use syntax_pos::symbol::{sym, Symbol}; use rustc::hir; -use rustc::ty::layout::{self, TyLayout, LayoutOf, VariantIdx}; +use rustc::ty::layout::{self, Size, TyLayout, LayoutOf, VariantIdx}; use rustc::ty; use rustc_data_structures::fx::FxHashSet; @@ -276,8 +276,20 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M // FIXME: More checks for the vtable. } ty::Slice(..) | ty::Str => { - try_validation!(meta.unwrap().to_usize(self.ecx), + let len = try_validation!(meta.unwrap().to_usize(self.ecx), "non-integer slice length in wide pointer", self.path); + // check max slice length + let elem_size = match tail.sty { + ty::Str => Size::from_bytes(1), + ty::Slice(ty) => self.ecx.layout_of(ty)?.size, + _ => bug!("It cannot be another type"), + }; + if elem_size.checked_mul(len, &*self.ecx.tcx).is_none() { + throw_validation_failure!( + "too large slice (longer than isize::MAX bytes)", + self.path + ); + } } ty::Foreign(..) => { // Unsized, but not wide. diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 23a82bb10ea17..20d1a5b08cdad 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -126,6 +126,8 @@ const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }] // # raw slice const RAW_SLICE_VALID: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.raw_slice}; // ok const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.raw_slice}; // ok because raw +const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: usize::max_value() } }.raw_slice}; +//~^ ERROR it is undefined behavior to use this value const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; //~^ ERROR it is undefined behavior to use this value diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 985df3b1c8bc5..264bb675506f6 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -89,13 +89,21 @@ LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:129:1 | +LL | const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: usize::max_value() } }.raw_slice}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too large slice (longer than isize::MAX bytes) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:131:1 + | LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:134:1 + --> $DIR/ub-wide-ptr.rs:136:1 | LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -103,7 +111,7 @@ LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vta = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:137:1 + --> $DIR/ub-wide-ptr.rs:139:1 | LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -111,7 +119,7 @@ LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, v = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:140:1 + --> $DIR/ub-wide-ptr.rs:142:1 | LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -119,7 +127,7 @@ LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, v = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:144:1 + --> $DIR/ub-wide-ptr.rs:146:1 | LL | const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 @@ -127,7 +135,7 @@ LL | const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:148:1 + --> $DIR/ub-wide-ptr.rs:150:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -135,13 +143,13 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:150:1 + --> $DIR/ub-wide-ptr.rs:152:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior -error: aborting due to 18 previous errors +error: aborting due to 19 previous errors For more information about this error, try `rustc --explain E0080`. From 39412ca9695dbf965c69f6f673c0e49313d3f1fb Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 27 Feb 2019 17:21:31 -0700 Subject: [PATCH 244/618] Permit unwinding through FFI by default See #58794 for context. --- src/librustc_mir/build/mod.rs | 2 +- src/test/ui/abi/abort-on-c-abi.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 4e970aee42cf4..6a3bb8b8b86a2 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -502,7 +502,7 @@ fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, abi: Abi) -> bool { // This is a special case: some functions have a C abi but are meant to // unwind anyway. Don't stop them. match unwind_attr { - None => true, + None => false, // FIXME(#58794) Some(UnwindAttr::Allowed) => false, Some(UnwindAttr::Aborts) => true, } diff --git a/src/test/ui/abi/abort-on-c-abi.rs b/src/test/ui/abi/abort-on-c-abi.rs index cd7dd1b6a452f..2f08730ec6132 100644 --- a/src/test/ui/abi/abort-on-c-abi.rs +++ b/src/test/ui/abi/abort-on-c-abi.rs @@ -1,6 +1,7 @@ // run-pass #![allow(unused_must_use)] +#![feature(unwind_attributes)] // Since we mark some ABIs as "nounwind" to LLVM, we must make sure that // we never unwind through them. @@ -13,6 +14,7 @@ use std::io::prelude::*; use std::io; use std::process::{Command, Stdio}; +#[unwind(aborts)] // FIXME(#58794) extern "C" fn panic_in_ffi() { panic!("Test"); } From d810e77f4ed7a76aaac71b6430b7bfb049b3649c Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 2 Apr 2019 14:53:57 -0700 Subject: [PATCH 245/618] Revert "Allow a dirty MirBuilt for make_extern and make_method_extern" This reverts commit b4a6f597934f16f89e27058a32a514c9572f148f. --- src/test/incremental/hashes/function_interfaces.rs | 2 +- src/test/incremental/hashes/inherent_impls.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index 84680a52ff3ce..4515e36166eb8 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -94,7 +94,7 @@ pub unsafe fn make_unsafe() {} pub fn make_extern() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, mir_built, typeck_tables_of, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub extern "C" fn make_extern() {} diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 882383e841957..538fd2c29203b 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -263,7 +263,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,mir_built,fn_sig,typeck_tables_of")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,fn_sig,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub extern fn make_method_extern(&self) { } } From 367b793790d7f362fa41313143e1015607b21700 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 10 May 2019 15:10:15 -0700 Subject: [PATCH 246/618] Force #[unwind(aborts)] in test/codegen/c-variadic.rs --- src/test/codegen/c-variadic.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/codegen/c-variadic.rs b/src/test/codegen/c-variadic.rs index 13be5ced27fa9..bb90a9653f573 100644 --- a/src/test/codegen/c-variadic.rs +++ b/src/test/codegen/c-variadic.rs @@ -2,6 +2,7 @@ #![crate_type = "lib"] #![feature(c_variadic)] +#![feature(unwind_attributes)] #![no_std] use core::ffi::VaList; @@ -10,6 +11,7 @@ extern "C" { fn foreign_c_variadic_1(_: VaList, ...); } +#[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_0() { // Ensure that we correctly call foreign C-variadic functions. // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0) @@ -24,20 +26,24 @@ pub unsafe extern "C" fn use_foreign_c_variadic_0() { // Ensure that we do not remove the `va_list` passed to the foreign function when // removing the "spoofed" `VaListImpl` that is used by Rust defined C-variadics. +#[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_1_0(ap: VaList) { // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap) foreign_c_variadic_1(ap); } +#[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_1_1(ap: VaList) { // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 42) foreign_c_variadic_1(ap, 42i32); } +#[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_1_2(ap: VaList) { // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 2, i32 42) foreign_c_variadic_1(ap, 2i32, 42i32); } +#[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_1_3(ap: VaList) { // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 2, i32 42, i32 0) foreign_c_variadic_1(ap, 2i32, 42i32, 0i32); From 5b7df0922ef15a8b105aceda8770faedc58ec67b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 25 Aug 2019 20:41:52 +0300 Subject: [PATCH 247/618] pprust: Do not print spaces before some tokens --- src/libsyntax/print/pprust.rs | 14 +++++++++++++- src/test/pretty/attr-literals.rs | 4 ++-- src/test/pretty/block-comment-wchar.pp | 5 +---- src/test/pretty/delimited-token-groups.rs | 2 +- src/test/pretty/do1.rs | 2 +- src/test/pretty/match-block-expr.rs | 2 +- src/test/ui/macros/macro-first-set.rs | 2 +- .../proc-macro/auxiliary/attr-stmt-expr-rpass.rs | 4 ++-- src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs | 4 ++-- 9 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 4dc00af486013..83a926a6217e7 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -152,6 +152,18 @@ pub fn to_string(f: F) -> String where printer.s.eof() } +// This makes comma-separated lists look slightly nicer, +// and also addresses a specific regression described in issue #63896. +fn tt_prepend_space(tt: &TokenTree) -> bool { + match tt { + TokenTree::Token(token) => match token.kind { + token::Comma => false, + _ => true, + } + _ => true, + } +} + fn binop_to_string(op: BinOpToken) -> &'static str { match op { token::Plus => "+", @@ -696,7 +708,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::DerefM fn print_tts(&mut self, tts: tokenstream::TokenStream, convert_dollar_crate: bool) { for (i, tt) in tts.into_trees().enumerate() { - if i != 0 { + if i != 0 && tt_prepend_space(&tt) { self.space(); } self.print_tt(tt, convert_dollar_crate); diff --git a/src/test/pretty/attr-literals.rs b/src/test/pretty/attr-literals.rs index bcd6ffaaf815b..9db7e27b16103 100644 --- a/src/test/pretty/attr-literals.rs +++ b/src/test/pretty/attr-literals.rs @@ -5,10 +5,10 @@ #![feature(rustc_attrs)] fn main() { - #![rustc_dummy("hi" , 1 , 2 , 1.012 , pi = 3.14 , bye , name ("John"))] + #![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name ("John"))] #[rustc_dummy = 8] fn f() { } - #[rustc_dummy(1 , 2 , 3)] + #[rustc_dummy(1, 2, 3)] fn g() { } } diff --git a/src/test/pretty/block-comment-wchar.pp b/src/test/pretty/block-comment-wchar.pp index f15d7cdc44ccd..9317b36ba497b 100644 --- a/src/test/pretty/block-comment-wchar.pp +++ b/src/test/pretty/block-comment-wchar.pp @@ -99,8 +99,5 @@ '\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}', '\u{2009}', '\u{200A}', '\u{2028}', '\u{2029}', '\u{202F}', '\u{205F}', '\u{3000}']; - for c in &chars { - let ws = c.is_whitespace(); - println!("{} {}" , c , ws); - } + for c in &chars { let ws = c.is_whitespace(); println!("{} {}", c, ws); } } diff --git a/src/test/pretty/delimited-token-groups.rs b/src/test/pretty/delimited-token-groups.rs index 768f27ad23a8e..7bbb7dc911f93 100644 --- a/src/test/pretty/delimited-token-groups.rs +++ b/src/test/pretty/delimited-token-groups.rs @@ -5,7 +5,7 @@ macro_rules! mac { ($ ($ tt : tt) *) => () } mac! { - struct S { field1 : u8 , field2 : u16 , } impl Clone for S + struct S { field1 : u8, field2 : u16, } impl Clone for S { fn clone () -> S { diff --git a/src/test/pretty/do1.rs b/src/test/pretty/do1.rs index 7be835cb22f2d..233ccdb0098b3 100644 --- a/src/test/pretty/do1.rs +++ b/src/test/pretty/do1.rs @@ -2,4 +2,4 @@ fn f(f: F) where F: Fn(isize) { f(10) } -fn main() { f(|i| { assert_eq!(i , 10) }) } +fn main() { f(|i| { assert_eq!(i, 10) }) } diff --git a/src/test/pretty/match-block-expr.rs b/src/test/pretty/match-block-expr.rs index 0db6574b0737f..10903e928cda8 100644 --- a/src/test/pretty/match-block-expr.rs +++ b/src/test/pretty/match-block-expr.rs @@ -2,5 +2,5 @@ fn main() { let x = match { 5 } { 1 => 5, 2 => 6, _ => 7, }; - assert_eq!(x , 7); + assert_eq!(x, 7); } diff --git a/src/test/ui/macros/macro-first-set.rs b/src/test/ui/macros/macro-first-set.rs index a21e4cd201a4f..34529cdaa64f1 100644 --- a/src/test/ui/macros/macro-first-set.rs +++ b/src/test/ui/macros/macro-first-set.rs @@ -25,7 +25,7 @@ macro_rules! foo_26444 { } fn test_26444() { - assert_eq!("a , b , c , d , e", foo_26444!(a, b; c; d, e)); + assert_eq!("a, b, c, d, e", foo_26444!(a, b; c; d, e)); assert_eq!("f", foo_26444!(; f ;)); } diff --git a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs index d81e16d9d2961..f1de3709b166b 100644 --- a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs +++ b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs @@ -17,7 +17,7 @@ pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "println!(\"{}\" , string);"); + assert_eq!(item.to_string(), "println!(\"{}\", string);"); item } @@ -31,7 +31,7 @@ pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "println!(\"{}\" , string)"); + assert_eq!(item.to_string(), "println!(\"{}\", string)"); item } diff --git a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs index 0a82cbedd77ce..d2180def5b760 100644 --- a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs +++ b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs @@ -17,7 +17,7 @@ pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "println!(\"{}\" , string);"); + assert_eq!(item.to_string(), "println!(\"{}\", string);"); item } @@ -31,7 +31,7 @@ pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "println!(\"{}\" , string)"); + assert_eq!(item.to_string(), "println!(\"{}\", string)"); item } From 94e8ff4f0b94c788ec9e9a28d3aa6f87062e2966 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Sat, 24 Aug 2019 17:50:21 +0200 Subject: [PATCH 248/618] Refactor feature gate checking code Tries to clarify the filtering of active features and make the code more expressive. --- src/libsyntax/feature_gate/check.rs | 40 ++++++++++++++++------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 344e5fd6e46c2..f3a9d135125ae 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -732,13 +732,9 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } } - for &(name, .., f_edition, set) in ACTIVE_FEATURES { - if let Some(f_edition) = f_edition { - if f_edition <= crate_edition { - set(&mut features, DUMMY_SP); - edition_enabled_features.insert(name, crate_edition); - } - } + for feature in active_features_up_to(crate_edition) { + feature.set(&mut features, DUMMY_SP); + edition_enabled_features.insert(feature.name, crate_edition); } // Process the edition umbrella feature-gates first, to ensure @@ -760,20 +756,17 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], let name = mi.name_or_empty(); - if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) { - if *edition <= crate_edition { + let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied(); + if let Some(edition) = edition { + if edition <= crate_edition { continue; } - for &(name, .., f_edition, set) in ACTIVE_FEATURES { - if let Some(f_edition) = f_edition { - if f_edition <= *edition { - // FIXME(Manishearth) there is currently no way to set - // lib features by edition - set(&mut features, DUMMY_SP); - edition_enabled_features.insert(name, *edition); - } - } + for feature in active_features_up_to(edition) { + // FIXME(Manishearth) there is currently no way to set + // lib features by edition + feature.set(&mut features, DUMMY_SP); + edition_enabled_features.insert(feature.name, edition); } } } @@ -867,6 +860,17 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], features } +fn active_features_up_to(edition: Edition) -> impl Iterator { + ACTIVE_FEATURES.iter() + .filter(move |feature| { + if let Some(feature_edition) = feature.edition { + feature_edition <= edition + } else { + false + } + }) +} + pub fn check_crate(krate: &ast::Crate, sess: &ParseSess, features: &Features, From 8458eba41bb1ae7848143f33c610b59e9614ec9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 25 Aug 2019 13:34:57 -0700 Subject: [PATCH 249/618] Point at method call on missing annotation error Make it clearer where the type name that couldn't be infered comes from. --- .../infer/error_reporting/need_type_info.rs | 39 +++++++++++++++---- .../error_reporting/region_name.rs | 6 +-- .../issue-42234-unknown-receiver-type.stderr | 4 +- .../ui/span/type-annotations-needed-expr.rs | 3 ++ .../span/type-annotations-needed-expr.stderr | 11 ++++++ 5 files changed, 51 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/span/type-annotations-needed-expr.rs create mode 100644 src/test/ui/span/type-annotations-needed-expr.stderr diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 3267505708b81..5e0f973fdd310 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -150,12 +150,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &self, ty: Ty<'tcx>, highlight: Option, - ) -> String { + ) -> (String, Option) { if let ty::Infer(ty::TyVar(ty_vid)) = ty.sty { let ty_vars = self.type_variables.borrow(); - if let TypeVariableOriginKind::TypeParameterDefinition(name) = - ty_vars.var_origin(ty_vid).kind { - return name.to_string(); + let var_origin = ty_vars.var_origin(ty_vid); + if let TypeVariableOriginKind::TypeParameterDefinition(name) = var_origin.kind { + return (name.to_string(), Some(var_origin.span)); } } @@ -165,7 +165,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { printer.region_highlight_mode = highlight; } let _ = ty.print(printer); - s + (s, None) } pub fn need_type_info_err( @@ -175,7 +175,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty: Ty<'tcx>, ) -> DiagnosticBuilder<'tcx> { let ty = self.resolve_vars_if_possible(&ty); - let name = self.extract_type_name(&ty, None); + let (name, name_sp) = self.extract_type_name(&ty, None); let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, &self.tcx.hir()); let ty_to_string = |ty: Ty<'tcx>| -> String { @@ -200,6 +200,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } let err_span = if let Some(pattern) = local_visitor.found_arg_pattern { pattern.span + } else if let Some(span) = name_sp { + // `span` here lets us point at `sum` instead of the entire right hand side expr: + // error[E0282]: type annotations needed + // --> file2.rs:3:15 + // | + // 3 | let _ = x.sum() as f64; + // | ^^^ cannot infer type for `S` + span } else { span }; @@ -325,6 +333,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; err.span_label(pattern.span, msg); } + // Instead of the following: + // error[E0282]: type annotations needed + // --> file2.rs:3:15 + // | + // 3 | let _ = x.sum() as f64; + // | --^^^--------- cannot infer type for `S` + // | + // = note: type must be known at this point + // We want: + // error[E0282]: type annotations needed + // --> file2.rs:3:15 + // | + // 3 | let _ = x.sum() as f64; + // | ^^^ cannot infer type for `S` + // | + // = note: type must be known at this point + let span = name_sp.unwrap_or(span); if !err.span.span_labels().iter().any(|span_label| { span_label.label.is_some() && span_label.span == span }) && local_visitor.found_arg_pattern.is_none() @@ -342,7 +367,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty: Ty<'tcx>, ) -> DiagnosticBuilder<'tcx> { let ty = self.resolve_vars_if_possible(&ty); - let name = self.extract_type_name(&ty, None); + let name = self.extract_type_name(&ty, None).0; let mut err = struct_span_err!( self.tcx.sess, span, E0698, "type inside {} must be known in this context", kind, ); diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index ca68b9e31b6b9..75a31628a54b6 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -413,7 +413,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) -> Option { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(needle_fr, *counter); - let type_name = infcx.extract_type_name(&argument_ty, Some(highlight)); + let type_name = infcx.extract_type_name(&argument_ty, Some(highlight)).0; debug!( "give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", @@ -695,7 +695,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(fr, *counter); - let type_name = infcx.extract_type_name(&return_ty, Some(highlight)); + let type_name = infcx.extract_type_name(&return_ty, Some(highlight)).0; let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir"); @@ -758,7 +758,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(fr, *counter); - let type_name = infcx.extract_type_name(&yield_ty, Some(highlight)); + let type_name = infcx.extract_type_name(&yield_ty, Some(highlight)).0; let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir"); diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr index 04c2870d83297..30c9adb1dce72 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr @@ -1,10 +1,10 @@ error[E0282]: type annotations needed for `std::option::Option<_>` - --> $DIR/issue-42234-unknown-receiver-type.rs:7:5 + --> $DIR/issue-42234-unknown-receiver-type.rs:7:7 | LL | let x: Option<_> = None; | - consider giving `x` the explicit type `std::option::Option<_>`, where the type parameter `T` is specified LL | x.unwrap().method_that_could_exist_on_some_type(); - | ^^^^^^^^^^ cannot infer type for `T` + | ^^^^^^ cannot infer type for `T` | = note: type must be known at this point diff --git a/src/test/ui/span/type-annotations-needed-expr.rs b/src/test/ui/span/type-annotations-needed-expr.rs new file mode 100644 index 0000000000000..f64dab4d7bc68 --- /dev/null +++ b/src/test/ui/span/type-annotations-needed-expr.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = (vec![1,2,3]).into_iter().sum() as f64; //~ ERROR E0282 +} diff --git a/src/test/ui/span/type-annotations-needed-expr.stderr b/src/test/ui/span/type-annotations-needed-expr.stderr new file mode 100644 index 0000000000000..e32a542bb7a8c --- /dev/null +++ b/src/test/ui/span/type-annotations-needed-expr.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/type-annotations-needed-expr.rs:2:39 + | +LL | let _ = (vec![1,2,3]).into_iter().sum() as f64; + | ^^^ cannot infer type for `S` + | + = note: type must be known at this point + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. From 0e3bc62f399b262bb56eb3de146a85729cdb882c Mon Sep 17 00:00:00 2001 From: Nathan Date: Sun, 25 Aug 2019 19:17:32 -0400 Subject: [PATCH 250/618] Allow checking of both compile & run output for run-pass tests --- src/tools/compiletest/src/common.rs | 4 ++- src/tools/compiletest/src/runtest.rs | 48 ++++++++++++++++++---------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 66e030e979355..edb9eb7d860e2 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -333,10 +333,12 @@ pub fn expected_output_path( testpaths.file.with_extension(extension) } -pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED]; +pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED, UI_RUN_STDERR, UI_RUN_STDOUT]; pub const UI_STDERR: &str = "stderr"; pub const UI_STDOUT: &str = "stdout"; pub const UI_FIXED: &str = "fixed"; +pub const UI_RUN_STDERR: &str = "run.stderr"; +pub const UI_RUN_STDOUT: &str = "run.stdout"; /// Absolute path to the directory where all output for all tests in the given /// `relative_dir` group should reside. Example: diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c1f8caa474e2d..7b5e0752b3673 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2,6 +2,7 @@ use crate::common::{CompareMode, PassMode}; use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT}; +use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT}; use crate::common::{output_base_dir, output_base_name, output_testname_unique}; use crate::common::{Codegen, CodegenUnits, Rustdoc}; use crate::common::{DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb}; @@ -288,6 +289,11 @@ enum ReadFrom { Stdin(String), } +enum TestOutput { + Compile, + Run, +} + impl<'test> TestCx<'test> { /// Code executed for each revision in turn (or, if there are no /// revisions, exactly once, with revision == None). @@ -2934,9 +2940,16 @@ impl<'test> TestCx<'test> { } } - fn load_compare_outputs(&self, proc_res: &ProcRes, explicit_format: bool) -> usize { - let expected_stderr = self.load_expected_output(UI_STDERR); - let expected_stdout = self.load_expected_output(UI_STDOUT); + fn load_compare_outputs(&self, proc_res: &ProcRes, + output_kind: TestOutput, explicit_format: bool) -> usize { + + let (stderr_kind, stdout_kind) = match output_kind { + TestOutput::Compile => (UI_STDERR, UI_STDOUT), + TestOutput::Run => (UI_RUN_STDERR, UI_RUN_STDOUT) + }; + + let expected_stderr = self.load_expected_output(stderr_kind); + let expected_stdout = self.load_expected_output(stdout_kind); let normalized_stdout = self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout); @@ -2949,11 +2962,19 @@ impl<'test> TestCx<'test> { let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr); let mut errors = 0; - if !self.props.dont_check_compiler_stdout { - errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); - } - if !self.props.dont_check_compiler_stderr { - errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr); + match output_kind { + TestOutput::Compile => { + if !self.props.dont_check_compiler_stdout { + errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); + } + if !self.props.dont_check_compiler_stderr { + errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr); + } + } + TestOutput::Run => { + errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout); + errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr); + } } errors } @@ -2975,14 +2996,7 @@ impl<'test> TestCx<'test> { let modes_to_prune = vec![CompareMode::Nll]; self.prune_duplicate_outputs(&modes_to_prune); - // if the user specified to check the results of the - // run-pass test, delay loading and comparing output - // until execution of the binary - let mut errors = if !self.props.check_run_results { - self.load_compare_outputs(&proc_res, explicit) - } else { - 0 - }; + let mut errors = self.load_compare_outputs(&proc_res, TestOutput::Compile, explicit); if self.config.compare_mode.is_some() { // don't test rustfix with nll right now @@ -3062,7 +3076,7 @@ impl<'test> TestCx<'test> { if self.should_run_successfully() { let proc_res = self.exec_compiled_test(); let run_output_errors = if self.props.check_run_results { - self.load_compare_outputs(&proc_res, explicit) + self.load_compare_outputs(&proc_res, TestOutput::Run, explicit) } else { 0 }; From c8a69e2567c714b870bbb7b2135153a3017c990c Mon Sep 17 00:00:00 2001 From: Hristo Venev Date: Mon, 26 Aug 2019 13:14:30 +0000 Subject: [PATCH 251/618] ty: use Align for ReprOptions pack and align. --- src/librustc/ty/layout.rs | 49 +++++++++++++------------------- src/librustc/ty/mod.rs | 28 +++++++++++------- src/librustc_typeck/check/mod.rs | 14 +++++---- 3 files changed, 45 insertions(+), 46 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 8febcfd0754c9..5ec4754c4535b 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -273,14 +273,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { repr: &ReprOptions, kind: StructKind) -> Result> { let dl = self.data_layout(); - let packed = repr.packed(); - if packed && repr.align > 0 { + let pack = repr.pack; + if pack.is_some() && repr.align.is_some() { bug!("struct cannot be packed and aligned"); } - let pack = Align::from_bytes(repr.pack as u64).unwrap(); - - let mut align = if packed { + let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align @@ -303,7 +301,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }; let optimizing = &mut inverse_memory_index[..end]; let field_align = |f: &TyLayout<'_>| { - if packed { f.align.abi.min(pack) } else { f.align.abi } + if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi } }; match kind { StructKind::AlwaysSized | @@ -334,7 +332,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let mut largest_niche_available = 0; if let StructKind::Prefixed(prefix_size, prefix_align) = kind { - let prefix_align = if packed { + let prefix_align = if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align @@ -355,7 +353,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } // Invariant: offset < dl.obj_size_bound() <= 1<<61 - let field_align = if packed { + let field_align = if let Some(pack) = pack { field.align.min(AbiAndPrefAlign::new(pack)) } else { field.align @@ -379,10 +377,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { .ok_or(LayoutError::SizeOverflow(ty))?; } - if repr.align > 0 { - let repr_align = repr.align as u64; - align = align.max(AbiAndPrefAlign::new(Align::from_bytes(repr_align).unwrap())); - debug!("univariant repr_align: {:?}", repr_align); + if let Some(repr_align) = repr.align { + align = align.max(AbiAndPrefAlign::new(repr_align)); } debug!("univariant min_size: {:?}", offset); @@ -730,23 +726,18 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }).collect::, _>>()?; if def.is_union() { - let packed = def.repr.packed(); - if packed && def.repr.align > 0 { - bug!("Union cannot be packed and aligned"); + if def.repr.pack.is_some() && def.repr.align.is_some() { + bug!("union cannot be packed and aligned"); } - let pack = Align::from_bytes(def.repr.pack as u64).unwrap(); - - let mut align = if packed { + let mut align = if def.repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align }; - if def.repr.align > 0 { - let repr_align = def.repr.align as u64; - align = align.max( - AbiAndPrefAlign::new(Align::from_bytes(repr_align).unwrap())); + if let Some(repr_align) = def.repr.align { + align = align.max(AbiAndPrefAlign::new(repr_align)); } let optimize = !def.repr.inhibit_union_abi_opt(); @@ -755,13 +746,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let index = VariantIdx::new(0); for field in &variants[index] { assert!(!field.is_unsized()); - - let field_align = if packed { - field.align.min(AbiAndPrefAlign::new(pack)) - } else { - field.align - }; - align = align.max(field_align); + align = align.max(field.align); // If all non-ZST fields have the same ABI, forward this ABI if optimize && !field.is_zst() { @@ -796,6 +781,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { size = cmp::max(size, field.size); } + if let Some(pack) = def.repr.pack { + align = align.min(AbiAndPrefAlign::new(pack)); + } + return Ok(tcx.intern_layout(LayoutDetails { variants: Variants::Single { index }, fields: FieldPlacement::Union(variants[index].len()), @@ -1637,7 +1626,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }; let adt_kind = adt_def.adt_kind(); - let adt_packed = adt_def.repr.packed(); + let adt_packed = adt_def.repr.pack.is_some(); let build_variant_info = |n: Option, flds: &[ast::Name], diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 0b81f193df409..bafd65673e613 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -33,6 +33,7 @@ use arena::SyncDroplessArena; use crate::session::DataTypeKind; use rustc_serialize::{self, Encodable, Encoder}; +use rustc_target::abi::Align; use std::cell::RefCell; use std::cmp::{self, Ordering}; use std::fmt; @@ -2057,8 +2058,8 @@ impl_stable_hash_for!(struct ReprFlags { #[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)] pub struct ReprOptions { pub int: Option, - pub align: u32, - pub pack: u32, + pub align: Option, + pub pack: Option, pub flags: ReprFlags, } @@ -2073,18 +2074,19 @@ impl ReprOptions { pub fn new(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { let mut flags = ReprFlags::empty(); let mut size = None; - let mut max_align = 0; - let mut min_pack = 0; + let mut max_align: Option = None; + let mut min_pack: Option = None; for attr in tcx.get_attrs(did).iter() { for r in attr::find_repr_attrs(&tcx.sess.parse_sess, attr) { flags.insert(match r { attr::ReprC => ReprFlags::IS_C, attr::ReprPacked(pack) => { - min_pack = if min_pack > 0 { - cmp::min(pack, min_pack) + let pack = Align::from_bytes(pack as u64).unwrap(); + min_pack = Some(if let Some(min_pack) = min_pack { + min_pack.min(pack) } else { pack - }; + }); ReprFlags::empty() }, attr::ReprTransparent => ReprFlags::IS_TRANSPARENT, @@ -2094,7 +2096,7 @@ impl ReprOptions { ReprFlags::empty() }, attr::ReprAlign(align) => { - max_align = cmp::max(align, max_align); + max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap())); ReprFlags::empty() }, }); @@ -2113,7 +2115,7 @@ impl ReprOptions { #[inline] pub fn c(&self) -> bool { self.flags.contains(ReprFlags::IS_C) } #[inline] - pub fn packed(&self) -> bool { self.pack > 0 } + pub fn packed(&self) -> bool { self.pack.is_some() } #[inline] pub fn transparent(&self) -> bool { self.flags.contains(ReprFlags::IS_TRANSPARENT) } #[inline] @@ -2133,8 +2135,12 @@ impl ReprOptions { /// Returns `true` if this `#[repr()]` should inhibit struct field reordering /// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr()`. pub fn inhibit_struct_field_reordering_opt(&self) -> bool { - self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.pack == 1 || - self.int.is_some() + if let Some(pack) = self.pack { + if pack.bytes() == 1 { + return true; + } + } + self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some() } /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c4dbe97a7bd96..fa5414fc22b08 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1859,14 +1859,18 @@ fn check_packed(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) { for attr in tcx.get_attrs(def_id).iter() { for r in attr::find_repr_attrs(&tcx.sess.parse_sess, attr) { if let attr::ReprPacked(pack) = r { - if pack != repr.pack { - struct_span_err!(tcx.sess, sp, E0634, - "type has conflicting packed representation hints").emit(); + if let Some(repr_pack) = repr.pack { + if pack as u64 != repr_pack.bytes() { + struct_span_err!( + tcx.sess, sp, E0634, + "type has conflicting packed representation hints" + ).emit(); + } } } } } - if repr.align > 0 { + if repr.align.is_some() { struct_span_err!(tcx.sess, sp, E0587, "type has conflicting packed and align representation hints").emit(); } @@ -1885,7 +1889,7 @@ fn check_packed_inner(tcx: TyCtxt<'_>, def_id: DefId, stack: &mut Vec) -> } if let ty::Adt(def, substs) = t.sty { if def.is_struct() || def.is_union() { - if tcx.adt_def(def.did).repr.align > 0 { + if tcx.adt_def(def.did).repr.align.is_some() { return true; } // push struct def_id before checking fields From fa7ea104b232fbc2b72f7717393181e849d39dfe Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Mon, 26 Aug 2019 17:51:52 +0000 Subject: [PATCH 252/618] Error when generator trait is not found --- src/librustc_typeck/check/closure.rs | 4 ++-- src/test/ui/lang-item-missing-generator.rs | 19 +++++++++++++++++++ .../ui/lang-item-missing-generator.stderr | 4 ++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/lang-item-missing-generator.rs create mode 100644 src/test/ui/lang-item-missing-generator.stderr diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index d2f2f89cf0b1c..06b1e7bfd4eaf 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -3,7 +3,7 @@ use super::{check_fn, Expectation, FnCtxt, GeneratorTypes}; use crate::astconv::AstConv; -use crate::middle::region; +use crate::middle::{lang_items, region}; use rustc::hir::def_id::DefId; use rustc::infer::{InferOk, InferResult}; use rustc::infer::LateBoundRegionConversionTime; @@ -266,7 +266,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_ref = projection.to_poly_trait_ref(tcx); let is_fn = tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_some(); - let gen_trait = tcx.lang_items().gen_trait().unwrap(); + let gen_trait = tcx.require_lang_item(lang_items::GeneratorTraitLangItem); let is_gen = gen_trait == trait_ref.def_id(); if !is_fn && !is_gen { debug!("deduce_sig_from_projection: not fn or generator"); diff --git a/src/test/ui/lang-item-missing-generator.rs b/src/test/ui/lang-item-missing-generator.rs new file mode 100644 index 0000000000000..0c329542928c5 --- /dev/null +++ b/src/test/ui/lang-item-missing-generator.rs @@ -0,0 +1,19 @@ +// error-pattern: requires `generator` lang_item +#![feature(no_core, lang_items, unboxed_closures)] +#![no_core] + +#[lang = "sized"] pub trait Sized { } + +#[lang = "fn_once"] +#[rustc_paren_sugar] +pub trait FnOnce { + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +pub fn abc() -> impl FnOnce(f32) { + |_| {} +} + +fn main() {} diff --git a/src/test/ui/lang-item-missing-generator.stderr b/src/test/ui/lang-item-missing-generator.stderr new file mode 100644 index 0000000000000..d0cc4b81be685 --- /dev/null +++ b/src/test/ui/lang-item-missing-generator.stderr @@ -0,0 +1,4 @@ +error: requires `generator` lang_item + +error: aborting due to previous error + From ae788620588029bef52d27d01ce66010a3c9a4b2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 26 Aug 2019 19:48:56 +0200 Subject: [PATCH 253/618] raw slices do not have to comply to the size limit --- src/librustc_mir/interpret/validity.rs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 7af55a2a3a376..c2505547c5b4f 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -3,7 +3,7 @@ use std::ops::RangeInclusive; use syntax_pos::symbol::{sym, Symbol}; use rustc::hir; -use rustc::ty::layout::{self, Size, TyLayout, LayoutOf, VariantIdx}; +use rustc::ty::layout::{self, TyLayout, LayoutOf, VariantIdx}; use rustc::ty; use rustc_data_structures::fx::FxHashSet; @@ -276,20 +276,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M // FIXME: More checks for the vtable. } ty::Slice(..) | ty::Str => { - let len = try_validation!(meta.unwrap().to_usize(self.ecx), + let _len = try_validation!(meta.unwrap().to_usize(self.ecx), "non-integer slice length in wide pointer", self.path); - // check max slice length - let elem_size = match tail.sty { - ty::Str => Size::from_bytes(1), - ty::Slice(ty) => self.ecx.layout_of(ty)?.size, - _ => bug!("It cannot be another type"), - }; - if elem_size.checked_mul(len, &*self.ecx.tcx).is_none() { - throw_validation_failure!( - "too large slice (longer than isize::MAX bytes)", - self.path - ); - } + // We do not check that `len * elem_size <= isize::MAX`: + // that is only required for references, and there it falls out of the + // "dereferencable" check performed by Stacked Borrows. } ty::Foreign(..) => { // Unsized, but not wide. From 633f67ad74179ee51aaaf913d14d3d9ab65f4a65 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 26 Aug 2019 20:40:30 +0200 Subject: [PATCH 254/618] add link to FileCheck docs --- src/test/codegen/README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/test/codegen/README.md diff --git a/src/test/codegen/README.md b/src/test/codegen/README.md new file mode 100644 index 0000000000000..00de55eeab1f4 --- /dev/null +++ b/src/test/codegen/README.md @@ -0,0 +1,2 @@ +The files here use the LLVM FileCheck framework, documented at +. From 2bd27fbdfe309f3f6abd76f72f379247d49048b7 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 26 Aug 2019 22:14:31 +0200 Subject: [PATCH 255/618] parser: fix span for leading vert. --- src/libsyntax/parse/parser/pat.rs | 3 ++- .../or-patterns/feature-gate-or_patterns-leading-for.stderr | 4 ++-- .../or-patterns/feature-gate-or_patterns-leading-let.stderr | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index f2e269e03baf9..78c9a289b3702 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -50,6 +50,7 @@ impl<'a> Parser<'a> { pub(super) fn parse_top_pat(&mut self, gate_or: GateOr) -> PResult<'a, P> { // Allow a '|' before the pats (RFCs 1925, 2530, and 2535). let gated_leading_vert = self.eat_or_separator() && gate_or == GateOr::Yes; + let leading_vert_span = self.prev_span; // Parse the possibly-or-pattern. let pat = self.parse_pat_with_or(None, gate_or, RecoverComma::Yes)?; @@ -61,7 +62,7 @@ impl<'a> Parser<'a> { if gated_leading_vert { let mut or_pattern_spans = self.sess.gated_spans.or_patterns.borrow_mut(); if or_pattern_spans.is_empty() { - or_pattern_spans.push(self.prev_span); + or_pattern_spans.push(leading_vert_span); } } diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr index 83804d564f3e4..f520409e8bad6 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr @@ -1,8 +1,8 @@ error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns-leading-for.rs:7:11 + --> $DIR/feature-gate-or_patterns-leading-for.rs:7:9 | LL | for | A in 0 {} - | ^ + | ^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54883 = help: add `#![feature(or_patterns)]` to the crate attributes to enable diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr index f7954ad7a8ce1..30fd6a1a95eff 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr @@ -1,8 +1,8 @@ error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns-leading-let.rs:7:11 + --> $DIR/feature-gate-or_patterns-leading-let.rs:7:9 | LL | let | A; - | ^ + | ^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54883 = help: add `#![feature(or_patterns)]` to the crate attributes to enable From 04580b6235188ffd6bb20387e8eeb9a102fafb50 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 26 Aug 2019 22:19:47 +0200 Subject: [PATCH 256/618] adjust tests --- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 3 +-- .../ui/consts/const-eval/ub-wide-ptr.stderr | 24 +++++++------------ 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 20d1a5b08cdad..765ed60ee9742 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -126,8 +126,7 @@ const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }] // # raw slice const RAW_SLICE_VALID: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.raw_slice}; // ok const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.raw_slice}; // ok because raw -const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: usize::max_value() } }.raw_slice}; -//~^ ERROR it is undefined behavior to use this value +const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: usize::max_value() } }.raw_slice}; // ok because raw const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; //~^ ERROR it is undefined behavior to use this value diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 264bb675506f6..88d8af8026193 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -87,15 +87,7 @@ LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }. = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:129:1 - | -LL | const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: usize::max_value() } }.raw_slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too large slice (longer than isize::MAX bytes) - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:131:1 + --> $DIR/ub-wide-ptr.rs:130:1 | LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata @@ -103,7 +95,7 @@ LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:136:1 + --> $DIR/ub-wide-ptr.rs:135:1 | LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -111,7 +103,7 @@ LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vta = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:139:1 + --> $DIR/ub-wide-ptr.rs:138:1 | LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -119,7 +111,7 @@ LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, v = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:142:1 + --> $DIR/ub-wide-ptr.rs:141:1 | LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -127,7 +119,7 @@ LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, v = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:146:1 + --> $DIR/ub-wide-ptr.rs:145:1 | LL | const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 @@ -135,7 +127,7 @@ LL | const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:150:1 + --> $DIR/ub-wide-ptr.rs:149:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -143,13 +135,13 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:152:1 + --> $DIR/ub-wide-ptr.rs:151:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior -error: aborting due to 19 previous errors +error: aborting due to 18 previous errors For more information about this error, try `rustc --explain E0080`. From 7def99af8a311139c43c961e13872ff27dd235c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 26 Aug 2019 13:25:27 -0700 Subject: [PATCH 257/618] review comment --- src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs | 2 +- src/test/ui/lint/lint-dead-code-unused-variant-pub.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs b/src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs index 2b06fcb69ceee..15b04496ba7b1 100644 --- a/src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs +++ b/src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs @@ -1,4 +1,4 @@ -// run-pass +// build-pass #![deny(unused)] pub enum E {} diff --git a/src/test/ui/lint/lint-dead-code-unused-variant-pub.rs b/src/test/ui/lint/lint-dead-code-unused-variant-pub.rs index 918300ba79354..3a9061340eb81 100644 --- a/src/test/ui/lint/lint-dead-code-unused-variant-pub.rs +++ b/src/test/ui/lint/lint-dead-code-unused-variant-pub.rs @@ -1,4 +1,4 @@ -// run-pass +// build-pass #![deny(unused)] pub struct F; From ec45b87957c4158934fc3f5a821594ad0686ea4e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 24 Aug 2019 21:12:13 +0300 Subject: [PATCH 258/618] resolve: Block expansion of a derive container until all its derives are resolved Also mark derive helpers as known as a part of the derive container's expansion instead of expansion of the derives themselves which may happen too late. --- src/librustc_metadata/decoder.rs | 4 +- src/librustc_resolve/macros.rs | 41 +++---- src/libsyntax/ext/base.rs | 20 ++- src/libsyntax/ext/expand.rs | 114 ++++++++++-------- src/libsyntax/ext/proc_macro.rs | 6 +- src/test/ui/derives/deriving-bounds.stderr | 24 ++-- .../issue-43106-gating-of-derive-2.stderr | 4 +- .../issue-43106-gating-of-derive.rs | 3 - .../issue-43106-gating-of-derive.stderr | 16 +-- src/test/ui/issues/issue-36617.rs | 1 + src/test/ui/issues/issue-36617.stderr | 10 +- .../ui/proc-macro/derive-helper-configured.rs | 18 +++ .../ui/proc-macro/derive-helper-shadowing.rs | 3 +- .../proc-macro/derive-helper-shadowing.stderr | 8 +- src/test/ui/proc-macro/resolve-error.stderr | 76 ++++++------ 15 files changed, 195 insertions(+), 153 deletions(-) create mode 100644 src/test/ui/proc-macro/derive-helper-configured.rs diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 5b9cb966af235..7d2414f9a1dfa 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -538,9 +538,7 @@ impl<'a, 'tcx> CrateMetadata { attributes.iter().cloned().map(Symbol::intern).collect::>(); ( trait_name, - SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { - client, attrs: helper_attrs.clone() - })), + SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { client })), helper_attrs, ) } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 719167eb057b2..20418633dc682 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -13,7 +13,7 @@ use rustc::{ty, lint, span_bug}; use syntax::ast::{self, NodeId, Ident}; use syntax::attr::StabilityLevel; use syntax::edition::Edition; -use syntax::ext::base::{self, Indeterminate, SpecialDerives}; +use syntax::ext::base::{self, InvocationRes, Indeterminate, SpecialDerives}; use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind}; @@ -142,7 +142,7 @@ impl<'a> base::Resolver for Resolver<'a> { fn resolve_macro_invocation( &mut self, invoc: &Invocation, eager_expansion_root: ExpnId, force: bool - ) -> Result>, Indeterminate> { + ) -> Result { let invoc_id = invoc.expansion_data.id; let parent_scope = match self.invocation_parent_scopes.get(&invoc_id) { Some(parent_scope) => *parent_scope, @@ -165,25 +165,24 @@ impl<'a> base::Resolver for Resolver<'a> { InvocationKind::Derive { ref path, .. } => (path, MacroKind::Derive, &[][..], false), InvocationKind::DeriveContainer { ref derives, .. } => { - // Block expansion of derives in the container until we know whether one of them - // is a built-in `Copy`. Skip the resolution if there's only one derive - either - // it's not a `Copy` and we don't need to do anything, or it's a `Copy` and it - // will automatically knows about itself. - let mut result = Ok(None); - if derives.len() > 1 { - for path in derives { - match self.resolve_macro_path(path, Some(MacroKind::Derive), - &parent_scope, true, force) { - Ok((Some(ref ext), _)) if ext.is_derive_copy => { - self.add_derives(invoc_id, SpecialDerives::COPY); - return Ok(None); - } - Err(Determinacy::Undetermined) => result = Err(Indeterminate), - _ => {} - } - } + // Block expansion of the container until we resolve all derives in it. + // This is required for two reasons: + // - Derive helper attributes are in scope for the item to which the `#[derive]` + // is applied, so they have to be produced by the container's expansion rather + // than by individual derives. + // - Derives in the container need to know whether one of them is a built-in `Copy`. + // FIXME: Try to avoid repeated resolutions for derives here and in expansion. + let mut exts = Vec::new(); + for path in derives { + exts.push(match self.resolve_macro_path( + path, Some(MacroKind::Derive), &parent_scope, true, force + ) { + Ok((Some(ext), _)) => ext, + Ok(_) | Err(Determinacy::Determined) => self.dummy_ext(MacroKind::Derive), + Err(Determinacy::Undetermined) => return Err(Indeterminate), + }) } - return result; + return Ok(InvocationRes::DeriveContainer(exts)); } }; @@ -203,7 +202,7 @@ impl<'a> base::Resolver for Resolver<'a> { self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id); } - Ok(Some(ext)) + Ok(InvocationRes::Single(ext)) } fn check_unused_macros(&self) { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index a63c4181d5e03..f0397558a1d60 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -11,6 +11,7 @@ use crate::ptr::P; use crate::symbol::{kw, sym, Ident, Symbol}; use crate::{ThinVec, MACRO_ARGUMENTS}; use crate::tokenstream::{self, TokenStream, TokenTree}; +use crate::visit::Visitor; use errors::{DiagnosticBuilder, DiagnosticId}; use smallvec::{smallvec, SmallVec}; @@ -72,6 +73,17 @@ impl Annotatable { } } + pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { + match self { + Annotatable::Item(item) => visitor.visit_item(item), + Annotatable::TraitItem(trait_item) => visitor.visit_trait_item(trait_item), + Annotatable::ImplItem(impl_item) => visitor.visit_impl_item(impl_item), + Annotatable::ForeignItem(foreign_item) => visitor.visit_foreign_item(foreign_item), + Annotatable::Stmt(stmt) => visitor.visit_stmt(stmt), + Annotatable::Expr(expr) => visitor.visit_expr(expr), + } + } + pub fn expect_item(self) -> P { match self { Annotatable::Item(i) => i, @@ -637,6 +649,12 @@ impl SyntaxExtension { pub type NamedSyntaxExtension = (Name, SyntaxExtension); +/// Result of resolving a macro invocation. +pub enum InvocationRes { + Single(Lrc), + DeriveContainer(Vec>), +} + /// Error type that denotes indeterminacy. pub struct Indeterminate; @@ -664,7 +682,7 @@ pub trait Resolver { fn resolve_macro_invocation( &mut self, invoc: &Invocation, eager_expansion_root: ExpnId, force: bool - ) -> Result>, Indeterminate>; + ) -> Result; fn check_unused_macros(&self); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index a6b56e4d5979f..7b4a516744642 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -4,7 +4,7 @@ use crate::attr::{self, HasAttrs}; use crate::source_map::respan; use crate::config::StripUnconfigured; use crate::ext::base::*; -use crate::ext::proc_macro::collect_derives; +use crate::ext::proc_macro::{collect_derives, MarkAttrs}; use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind}; use crate::ext::tt::macro_rules::annotate_err_with_kind; use crate::ext::placeholders::{placeholder, PlaceholderExpander}; @@ -307,10 +307,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let eager_expansion_root = if self.monotonic { invoc.expansion_data.id } else { orig_expansion_data.id }; - let ext = match self.cx.resolver.resolve_macro_invocation( + let res = match self.cx.resolver.resolve_macro_invocation( &invoc, eager_expansion_root, force ) { - Ok(ext) => ext, + Ok(res) => res, Err(Indeterminate) => { undetermined_invocations.push(invoc); continue @@ -322,54 +322,72 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.current_expansion = invoc.expansion_data.clone(); // FIXME(jseyfried): Refactor out the following logic - let (expanded_fragment, new_invocations) = if let Some(ext) = ext { - let fragment = self.expand_invoc(invoc, &ext.kind); - self.collect_invocations(fragment, &[]) - } else if let InvocationKind::DeriveContainer { derives: traits, item } = invoc.kind { - if !item.derive_allowed() { - let attr = attr::find_by_name(item.attrs(), sym::derive) - .expect("`derive` attribute should exist"); - let span = attr.span; - let mut err = self.cx.mut_span_err(span, - "`derive` may only be applied to \ - structs, enums and unions"); - if let ast::AttrStyle::Inner = attr.style { - let trait_list = traits.iter() - .map(|t| t.to_string()).collect::>(); - let suggestion = format!("#[derive({})]", trait_list.join(", ")); - err.span_suggestion( - span, "try an outer attribute", suggestion, - // We don't ð‘˜ð‘›ð‘œð‘¤ that the following item is an ADT - Applicability::MaybeIncorrect - ); - } - err.emit(); + let (expanded_fragment, new_invocations) = match res { + InvocationRes::Single(ext) => { + let fragment = self.expand_invoc(invoc, &ext.kind); + self.collect_invocations(fragment, &[]) } + InvocationRes::DeriveContainer(exts) => { + let (derives, item) = match invoc.kind { + InvocationKind::DeriveContainer { derives, item } => (derives, item), + _ => unreachable!(), + }; + if !item.derive_allowed() { + let attr = attr::find_by_name(item.attrs(), sym::derive) + .expect("`derive` attribute should exist"); + let span = attr.span; + let mut err = self.cx.mut_span_err(span, + "`derive` may only be applied to structs, enums and unions"); + if let ast::AttrStyle::Inner = attr.style { + let trait_list = derives.iter() + .map(|t| t.to_string()).collect::>(); + let suggestion = format!("#[derive({})]", trait_list.join(", ")); + err.span_suggestion( + span, "try an outer attribute", suggestion, + // We don't ð‘˜ð‘›ð‘œð‘¤ that the following item is an ADT + Applicability::MaybeIncorrect + ); + } + err.emit(); + } - let mut item = self.fully_configure(item); - item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive)); - let derive_placeholders = - all_derive_placeholders.entry(invoc.expansion_data.id).or_default(); - - derive_placeholders.reserve(traits.len()); - invocations.reserve(traits.len()); - for path in traits { - let expn_id = ExpnId::fresh(None); - derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id)); - invocations.push(Invocation { - kind: InvocationKind::Derive { path, item: item.clone() }, - fragment_kind: invoc.fragment_kind, - expansion_data: ExpansionData { - id: expn_id, - ..invoc.expansion_data.clone() - }, - }); + let mut item = self.fully_configure(item); + item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive)); + let mut helper_attrs = Vec::new(); + let mut has_copy = false; + for ext in exts { + helper_attrs.extend(&ext.helper_attrs); + has_copy |= ext.is_derive_copy; + } + // Mark derive helpers inside this item as known and used. + // FIXME: This is a hack, derive helpers should be integrated with regular name + // resolution instead. For example, helpers introduced by a derive container + // can be in scope for all code produced by that container's expansion. + item.visit_with(&mut MarkAttrs(&helper_attrs)); + if has_copy { + self.cx.resolver.add_derives(invoc.expansion_data.id, SpecialDerives::COPY); + } + + let derive_placeholders = + all_derive_placeholders.entry(invoc.expansion_data.id).or_default(); + derive_placeholders.reserve(derives.len()); + invocations.reserve(derives.len()); + for path in derives { + let expn_id = ExpnId::fresh(None); + derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id)); + invocations.push(Invocation { + kind: InvocationKind::Derive { path, item: item.clone() }, + fragment_kind: invoc.fragment_kind, + expansion_data: ExpansionData { + id: expn_id, + ..invoc.expansion_data.clone() + }, + }); + } + let fragment = invoc.fragment_kind + .expect_from_annotatables(::std::iter::once(item)); + self.collect_invocations(fragment, derive_placeholders) } - let fragment = invoc.fragment_kind - .expect_from_annotatables(::std::iter::once(item)); - self.collect_invocations(fragment, derive_placeholders) - } else { - unreachable!() }; if expanded_fragments.len() < depth { diff --git a/src/libsyntax/ext/proc_macro.rs b/src/libsyntax/ext/proc_macro.rs index c17b6f6b4248a..4a44c9a9f1f31 100644 --- a/src/libsyntax/ext/proc_macro.rs +++ b/src/libsyntax/ext/proc_macro.rs @@ -78,7 +78,6 @@ pub struct ProcMacroDerive { pub client: proc_macro::bridge::client::Client< fn(proc_macro::TokenStream) -> proc_macro::TokenStream, >, - pub attrs: Vec, } impl MultiItemModifier for ProcMacroDerive { @@ -111,9 +110,6 @@ impl MultiItemModifier for ProcMacroDerive { } } - // Mark attributes as known, and used. - MarkAttrs(&self.attrs).visit_item(&item); - let token = token::Interpolated(Lrc::new(token::NtItem(item))); let input = tokenstream::TokenTree::token(token, DUMMY_SP).into(); @@ -164,7 +160,7 @@ impl MultiItemModifier for ProcMacroDerive { } } -struct MarkAttrs<'a>(&'a [ast::Name]); +crate struct MarkAttrs<'a>(crate &'a [ast::Name]); impl<'a> Visitor<'a> for MarkAttrs<'a> { fn visit_attribute(&mut self, attr: &Attribute) { diff --git a/src/test/ui/derives/deriving-bounds.stderr b/src/test/ui/derives/deriving-bounds.stderr index 99976da72da1d..b18df3511817d 100644 --- a/src/test/ui/derives/deriving-bounds.stderr +++ b/src/test/ui/derives/deriving-bounds.stderr @@ -1,15 +1,3 @@ -error: cannot find derive macro `Send` in this scope - --> $DIR/deriving-bounds.rs:1:10 - | -LL | #[derive(Send)] - | ^^^^ - | -note: unsafe traits like `Send` should be implemented explicitly - --> $DIR/deriving-bounds.rs:1:10 - | -LL | #[derive(Send)] - | ^^^^ - error: cannot find derive macro `Sync` in this scope --> $DIR/deriving-bounds.rs:5:10 | @@ -22,5 +10,17 @@ note: unsafe traits like `Sync` should be implemented explicitly LL | #[derive(Sync)] | ^^^^ +error: cannot find derive macro `Send` in this scope + --> $DIR/deriving-bounds.rs:1:10 + | +LL | #[derive(Send)] + | ^^^^ + | +note: unsafe traits like `Send` should be implemented explicitly + --> $DIR/deriving-bounds.rs:1:10 + | +LL | #[derive(Send)] + | ^^^^ + error: aborting due to 2 previous errors diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr index be3536aa789c1..f14591c85e62e 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr @@ -1,5 +1,5 @@ error: cannot find derive macro `x3300` in this scope - --> $DIR/issue-43106-gating-of-derive-2.rs:4:14 + --> $DIR/issue-43106-gating-of-derive-2.rs:12:14 | LL | #[derive(x3300)] | ^^^^^ @@ -11,7 +11,7 @@ LL | #[derive(x3300)] | ^^^^^ error: cannot find derive macro `x3300` in this scope - --> $DIR/issue-43106-gating-of-derive-2.rs:12:14 + --> $DIR/issue-43106-gating-of-derive-2.rs:4:14 | LL | #[derive(x3300)] | ^^^^^ diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs b/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs index 1397412988491..c5d9e0db4d389 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs @@ -1,9 +1,6 @@ // `#![derive]` raises errors when it occurs at contexts other than ADT // definitions. -#![derive(Debug)] -//~^ ERROR `derive` may only be applied to structs, enums and unions - #[derive(Debug)] //~^ ERROR `derive` may only be applied to structs, enums and unions mod derive { diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr index 25f160983d3df..db29a2bddd35c 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr @@ -1,38 +1,32 @@ error: `derive` may only be applied to structs, enums and unions --> $DIR/issue-43106-gating-of-derive.rs:4:1 | -LL | #![derive(Debug)] - | ^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug)]` - -error: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43106-gating-of-derive.rs:7:1 - | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ error: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43106-gating-of-derive.rs:10:17 + --> $DIR/issue-43106-gating-of-derive.rs:7:17 | LL | mod inner { #![derive(Debug)] } | ^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug)]` error: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43106-gating-of-derive.rs:13:5 + --> $DIR/issue-43106-gating-of-derive.rs:10:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ error: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43106-gating-of-derive.rs:26:5 + --> $DIR/issue-43106-gating-of-derive.rs:23:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ error: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43106-gating-of-derive.rs:30:5 + --> $DIR/issue-43106-gating-of-derive.rs:27:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/issues/issue-36617.rs b/src/test/ui/issues/issue-36617.rs index 87092689a281d..1102f3c4640a1 100644 --- a/src/test/ui/issues/issue-36617.rs +++ b/src/test/ui/issues/issue-36617.rs @@ -1,3 +1,4 @@ #![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions + //~| ERROR cannot determine resolution for the derive macro `Copy` fn main() {} diff --git a/src/test/ui/issues/issue-36617.stderr b/src/test/ui/issues/issue-36617.stderr index 296fec46d80a6..b5db98f306bd3 100644 --- a/src/test/ui/issues/issue-36617.stderr +++ b/src/test/ui/issues/issue-36617.stderr @@ -4,5 +4,13 @@ error: `derive` may only be applied to structs, enums and unions LL | #![derive(Copy)] | ^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Copy)]` -error: aborting due to previous error +error: cannot determine resolution for the derive macro `Copy` + --> $DIR/issue-36617.rs:1:11 + | +LL | #![derive(Copy)] + | ^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to 2 previous errors diff --git a/src/test/ui/proc-macro/derive-helper-configured.rs b/src/test/ui/proc-macro/derive-helper-configured.rs new file mode 100644 index 0000000000000..243cf685e8145 --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-configured.rs @@ -0,0 +1,18 @@ +// Derive helpers are resolved successfully inside `cfg_attr`. + +// check-pass +// compile-flats:--cfg TRUE +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[cfg_attr(TRUE, empty_helper)] +#[derive(Empty)] +#[cfg_attr(TRUE, empty_helper)] +struct S { + #[cfg_attr(TRUE, empty_helper)] + field: u8, +} + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.rs b/src/test/ui/proc-macro/derive-helper-shadowing.rs index 59ba1390e1323..21af4093a037d 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.rs +++ b/src/test/ui/proc-macro/derive-helper-shadowing.rs @@ -19,7 +19,8 @@ struct S { struct U; mod inner { - #[empty_helper] //~ ERROR cannot find attribute macro `empty_helper` in this scope + // FIXME No ambiguity, attributes in non-macro positions are not resolved properly + #[empty_helper] struct V; } diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr index 149f6eef443c1..2ba517ce29ee7 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr @@ -1,9 +1,3 @@ -error: cannot find attribute macro `empty_helper` in this scope - --> $DIR/derive-helper-shadowing.rs:22:15 - | -LL | #[empty_helper] - | ^^^^^^^^^^^^ - error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) --> $DIR/derive-helper-shadowing.rs:8:3 | @@ -22,6 +16,6 @@ LL | use test_macros::empty_attr as empty_helper; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr index 3c9b2baacbd91..2a5f2b883813d 100644 --- a/src/test/ui/proc-macro/resolve-error.stderr +++ b/src/test/ui/proc-macro/resolve-error.stderr @@ -1,32 +1,26 @@ -error: cannot find derive macro `FooWithLongNan` in this scope - --> $DIR/resolve-error.rs:22:10 - | -LL | #[derive(FooWithLongNan)] - | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName` - -error: cannot find attribute macro `attr_proc_macra` in this scope - --> $DIR/resolve-error.rs:27:3 +error: cannot find macro `bang_proc_macrp!` in this scope + --> $DIR/resolve-error.rs:56:5 | -LL | #[attr_proc_macra] - | ^^^^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `attr_proc_macro` +LL | bang_proc_macrp!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro` -error: cannot find attribute macro `FooWithLongNan` in this scope - --> $DIR/resolve-error.rs:31:3 +error: cannot find macro `Dlona!` in this scope + --> $DIR/resolve-error.rs:53:5 | -LL | #[FooWithLongNan] - | ^^^^^^^^^^^^^^ +LL | Dlona!(); + | ^^^^^ -error: cannot find derive macro `Dlone` in this scope - --> $DIR/resolve-error.rs:34:10 +error: cannot find macro `attr_proc_macra!` in this scope + --> $DIR/resolve-error.rs:50:5 | -LL | #[derive(Dlone)] - | ^^^^^ help: a derive macro with a similar name exists: `Clone` +LL | attr_proc_macra!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac` -error: cannot find derive macro `Dlona` in this scope - --> $DIR/resolve-error.rs:38:10 +error: cannot find macro `FooWithLongNama!` in this scope + --> $DIR/resolve-error.rs:47:5 | -LL | #[derive(Dlona)] - | ^^^^^ help: a derive macro with a similar name exists: `Clona` +LL | FooWithLongNama!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `FooWithLongNam` error: cannot find derive macro `attr_proc_macra` in this scope --> $DIR/resolve-error.rs:42:10 @@ -34,29 +28,35 @@ error: cannot find derive macro `attr_proc_macra` in this scope LL | #[derive(attr_proc_macra)] | ^^^^^^^^^^^^^^^ -error: cannot find macro `FooWithLongNama!` in this scope - --> $DIR/resolve-error.rs:47:5 +error: cannot find derive macro `Dlona` in this scope + --> $DIR/resolve-error.rs:38:10 | -LL | FooWithLongNama!(); - | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `FooWithLongNam` +LL | #[derive(Dlona)] + | ^^^^^ help: a derive macro with a similar name exists: `Clona` -error: cannot find macro `attr_proc_macra!` in this scope - --> $DIR/resolve-error.rs:50:5 +error: cannot find derive macro `Dlone` in this scope + --> $DIR/resolve-error.rs:34:10 | -LL | attr_proc_macra!(); - | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac` +LL | #[derive(Dlone)] + | ^^^^^ help: a derive macro with a similar name exists: `Clone` -error: cannot find macro `Dlona!` in this scope - --> $DIR/resolve-error.rs:53:5 +error: cannot find attribute macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:31:3 | -LL | Dlona!(); - | ^^^^^ +LL | #[FooWithLongNan] + | ^^^^^^^^^^^^^^ -error: cannot find macro `bang_proc_macrp!` in this scope - --> $DIR/resolve-error.rs:56:5 +error: cannot find attribute macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:27:3 | -LL | bang_proc_macrp!(); - | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro` +LL | #[attr_proc_macra] + | ^^^^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `attr_proc_macro` + +error: cannot find derive macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:22:10 + | +LL | #[derive(FooWithLongNan)] + | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName` error: aborting due to 10 previous errors From 32e5acb3eba7a92029488b9684d7bb27bc716294 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 20 Aug 2019 02:26:40 +0300 Subject: [PATCH 259/618] proc_macro: Turn `quote` into a regular built-in macro Previously in was implemented using a special hack in the metadata loader --- src/libproc_macro/lib.rs | 10 ++++++---- src/libproc_macro/quote.rs | 4 ++-- src/librustc_metadata/cstore_impl.rs | 12 +----------- src/libsyntax_ext/lib.rs | 8 ++++++++ src/test/ui/auxiliary/cond_plugin.rs | 1 + src/test/ui/auxiliary/proc_macro_def.rs | 1 + 6 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index c0f7714ca211a..d408fef75153e 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -19,12 +19,15 @@ #![feature(nll)] #![feature(staged_api)] +#![feature(allow_internal_unstable)] #![feature(const_fn)] +#![feature(decl_macro)] #![feature(extern_types)] #![feature(in_band_lifetimes)] #![feature(optin_builtin_traits)] #![feature(mem_take)] #![feature(non_exhaustive)] +#![feature(rustc_attrs)] #![feature(specialization)] #![recursion_limit="256"] @@ -222,11 +225,10 @@ pub mod token_stream { /// /// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term. /// To quote `$` itself, use `$$`. -/// -/// This is a dummy macro, the actual implementation is in `quote::quote`.` #[unstable(feature = "proc_macro_quote", issue = "54722")] -#[macro_export] -macro_rules! quote { () => {} } +#[allow_internal_unstable(proc_macro_def_site)] +#[cfg_attr(not(bootstrap), rustc_builtin_macro)] +pub macro quote ($($t:tt)*) { /* compiler built-in */ } #[unstable(feature = "proc_macro_internals", issue = "27812")] #[doc(hidden)] diff --git a/src/libproc_macro/quote.rs b/src/libproc_macro/quote.rs index e3d31b78f4a09..144e2d6bac43b 100644 --- a/src/libproc_macro/quote.rs +++ b/src/libproc_macro/quote.rs @@ -57,9 +57,9 @@ macro_rules! quote { } /// Quote a `TokenStream` into a `TokenStream`. -/// This is the actual `quote!()` proc macro. +/// This is the actual implementation of the `quote!()` proc macro. /// -/// It is manually loaded in `CStore::load_macro_untracked`. +/// It is loaded by the compiler in `register_builtin_macros`. #[unstable(feature = "proc_macro_quote", issue = "54722")] pub fn quote(stream: TokenStream) -> TokenStream { if stream.is_empty() { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 7aeeef00ea934..f4c04770c1505 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -30,11 +30,9 @@ use syntax::ast; use syntax::attr; use syntax::source_map; use syntax::edition::Edition; -use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; -use syntax::ext::proc_macro::BangProcMacro; use syntax::parse::source_file_to_stream; use syntax::parse::parser::emit_unclosed_delims; -use syntax::symbol::{Symbol, sym}; +use syntax::symbol::Symbol; use syntax_pos::{Span, FileName}; use rustc_data_structures::bit_set::BitSet; @@ -437,14 +435,6 @@ impl cstore::CStore { let data = self.get_crate_data(id.krate); if data.is_proc_macro_crate() { return LoadedMacro::ProcMacro(data.get_proc_macro(id.index, sess).ext); - } else if data.name == sym::proc_macro && data.item_name(id.index) == sym::quote { - let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); - let kind = SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })); - let ext = SyntaxExtension { - allow_internal_unstable: Some([sym::proc_macro_def_site][..].into()), - ..SyntaxExtension::default(kind, data.root.edition) - }; - return LoadedMacro::ProcMacro(Lrc::new(ext)); } let def = data.get_macro(id.index); diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 4add2261c6cda..1a6176916623b 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -7,13 +7,18 @@ #![feature(decl_macro)] #![feature(mem_take)] #![feature(nll)] +#![feature(proc_macro_internals)] +#![feature(proc_macro_quote)] #![feature(rustc_diagnostic_macros)] +extern crate proc_macro; + use crate::deriving::*; use syntax::ast::Ident; use syntax::edition::Edition; use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, MacroExpanderFn}; +use syntax::ext::proc_macro::BangProcMacro; use syntax::symbol::sym; mod error_codes; @@ -100,4 +105,7 @@ pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, e RustcDecodable: decodable::expand_deriving_rustc_decodable, RustcEncodable: encodable::expand_deriving_rustc_encodable, } + + let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); + register(sym::quote, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client }))); } diff --git a/src/test/ui/auxiliary/cond_plugin.rs b/src/test/ui/auxiliary/cond_plugin.rs index 1f97b556a0767..2819541bf6966 100644 --- a/src/test/ui/auxiliary/cond_plugin.rs +++ b/src/test/ui/auxiliary/cond_plugin.rs @@ -3,6 +3,7 @@ #![crate_type = "proc-macro"] #![feature(proc_macro_hygiene)] +#![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/src/test/ui/auxiliary/proc_macro_def.rs b/src/test/ui/auxiliary/proc_macro_def.rs index dfc5a42d19c69..49cfb5518ba9c 100644 --- a/src/test/ui/auxiliary/proc_macro_def.rs +++ b/src/test/ui/auxiliary/proc_macro_def.rs @@ -3,6 +3,7 @@ #![crate_type = "proc-macro"] #![feature(proc_macro_hygiene)] +#![feature(proc_macro_quote)] extern crate proc_macro; From 52c62eaae42ebc0efe370848a142c2858ac7fffc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 20 Aug 2019 21:22:32 +0300 Subject: [PATCH 260/618] Respect attributes on proc macro definitions --- src/librustc_metadata/decoder.rs | 18 ++--- src/libsyntax/ext/base.rs | 67 +++++++++++++++++- src/libsyntax/ext/tt/macro_rules.rs | 70 ++++--------------- .../proc-macro/attributes-on-definitions.rs | 12 ++++ .../attributes-on-definitions.stderr | 8 +++ .../auxiliary/attributes-on-definitions.rs | 23 ++++++ 6 files changed, 131 insertions(+), 67 deletions(-) create mode 100644 src/test/ui/proc-macro/attributes-on-definitions.rs create mode 100644 src/test/ui/proc-macro/attributes-on-definitions.stderr create mode 100644 src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 5b9cb966af235..fffeee82d8d24 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -530,7 +530,6 @@ impl<'a, 'tcx> CrateMetadata { id: DefIndex, sess: &Session) -> FullProcMacro { - let raw_macro = self.raw_proc_macro(id); let (name, kind, helper_attrs) = match *raw_macro { ProcMacro::CustomDerive { trait_name, attributes, client } => { @@ -551,16 +550,19 @@ impl<'a, 'tcx> CrateMetadata { name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new() ) }; - - let span = self.get_span(id, sess); + let name = Symbol::intern(name); FullProcMacro { - name: Symbol::intern(name), - ext: Lrc::new(SyntaxExtension { - span, + name, + ext: Lrc::new(SyntaxExtension::new( + &sess.parse_sess, + kind, + self.get_span(id, sess), helper_attrs, - ..SyntaxExtension::default(kind, root.edition) - }) + root.edition, + name, + &self.get_attributes(&self.entry(id), sess), + )), } } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index a63c4181d5e03..10ff1b17285fe 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1,11 +1,11 @@ use crate::ast::{self, NodeId, Attribute, Name, PatKind}; -use crate::attr::{HasAttrs, Stability, Deprecation}; +use crate::attr::{self, HasAttrs, Stability, Deprecation}; use crate::source_map::SourceMap; use crate::edition::Edition; use crate::ext::expand::{self, AstFragment, Invocation}; use crate::ext::hygiene::{ExpnId, Transparency}; use crate::mut_visit::{self, MutVisitor}; -use crate::parse::{self, parser, DirectoryOwnership}; +use crate::parse::{self, parser, ParseSess, DirectoryOwnership}; use crate::parse::token; use crate::ptr::P; use crate::symbol::{kw, sym, Ident, Symbol}; @@ -601,6 +601,69 @@ impl SyntaxExtension { } } + /// Constructs a syntax extension with the given properties + /// and other properties converted from attributes. + pub fn new( + sess: &ParseSess, + kind: SyntaxExtensionKind, + span: Span, + helper_attrs: Vec, + edition: Edition, + name: Name, + attrs: &[ast::Attribute], + ) -> SyntaxExtension { + let allow_internal_unstable = + attr::find_by_name(attrs, sym::allow_internal_unstable).map(|attr| { + attr.meta_item_list() + .map(|list| { + list.iter() + .filter_map(|it| { + let name = it.ident().map(|ident| ident.name); + if name.is_none() { + sess.span_diagnostic.span_err( + it.span(), "allow internal unstable expects feature names" + ) + } + name + }) + .collect::>() + .into() + }) + .unwrap_or_else(|| { + sess.span_diagnostic.span_warn( + attr.span, + "allow_internal_unstable expects list of feature names. In the future \ + this will become a hard error. Please use `allow_internal_unstable(\ + foo, bar)` to only allow the `foo` and `bar` features", + ); + vec![sym::allow_internal_unstable_backcompat_hack].into() + }) + }); + + let mut local_inner_macros = false; + if let Some(macro_export) = attr::find_by_name(attrs, sym::macro_export) { + if let Some(l) = macro_export.meta_item_list() { + local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros); + } + } + + let is_builtin = attr::contains_name(attrs, sym::rustc_builtin_macro); + + SyntaxExtension { + kind, + span, + allow_internal_unstable, + allow_internal_unsafe: attr::contains_name(attrs, sym::allow_internal_unsafe), + local_inner_macros, + stability: attr::find_stability(&sess, attrs, span), + deprecation: attr::find_deprecation(&sess, attrs, span), + helper_attrs, + edition, + is_builtin, + is_derive_copy: is_builtin && name == sym::Copy, + } + } + pub fn dummy_bang(edition: Edition) -> SyntaxExtension { fn expander<'cx>(_: &'cx mut ExtCtxt<'_>, span: Span, _: &[TokenTree]) -> Box { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 37cb8467ff5ee..46ffa52f7f572 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -1,3 +1,5 @@ +use crate::ast; +use crate::attr::{self, TransparencyError}; use crate::edition::Edition; use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind}; @@ -15,7 +17,6 @@ use crate::parse::token::{self, NtTT, Token}; use crate::parse::{Directory, ParseSess}; use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; -use crate::{ast, attr, attr::TransparencyError}; use errors::{DiagnosticBuilder, FatalError}; use log::debug; @@ -290,6 +291,7 @@ pub fn compile( def: &ast::Item, edition: Edition, ) -> SyntaxExtension { + let diag = &sess.span_diagnostic; let lhs_nm = ast::Ident::new(sym::lhs, def.span); let rhs_nm = ast::Ident::new(sym::rhs, def.span); let tt_spec = ast::Ident::new(sym::tt, def.span); @@ -423,13 +425,9 @@ pub fn compile( let (transparency, transparency_error) = attr::find_transparency(&def.attrs, body.legacy); match transparency_error { Some(TransparencyError::UnknownTransparency(value, span)) => - sess.span_diagnostic.span_err( - span, &format!("unknown macro transparency: `{}`", value) - ), + diag.span_err(span, &format!("unknown macro transparency: `{}`", value)), Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) => - sess.span_diagnostic.span_err( - vec![old_span, new_span], "multiple macro transparency attributes" - ), + diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes"), None => {} } @@ -437,57 +435,15 @@ pub fn compile( name: def.ident, span: def.span, transparency, lhses, rhses, valid }); - let allow_internal_unstable = - attr::find_by_name(&def.attrs, sym::allow_internal_unstable).map(|attr| { - attr.meta_item_list() - .map(|list| { - list.iter() - .filter_map(|it| { - let name = it.ident().map(|ident| ident.name); - if name.is_none() { - sess.span_diagnostic.span_err( - it.span(), - "allow internal unstable expects feature names", - ) - } - name - }) - .collect::>() - .into() - }) - .unwrap_or_else(|| { - sess.span_diagnostic.span_warn( - attr.span, - "allow_internal_unstable expects list of feature names. In the \ - future this will become a hard error. Please use `allow_internal_unstable(\ - foo, bar)` to only allow the `foo` and `bar` features", - ); - vec![sym::allow_internal_unstable_backcompat_hack].into() - }) - }); - - let mut local_inner_macros = false; - if let Some(macro_export) = attr::find_by_name(&def.attrs, sym::macro_export) { - if let Some(l) = macro_export.meta_item_list() { - local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros); - } - } - - let is_builtin = attr::contains_name(&def.attrs, sym::rustc_builtin_macro); - - SyntaxExtension { - kind: SyntaxExtensionKind::LegacyBang(expander), - span: def.span, - allow_internal_unstable, - allow_internal_unsafe: attr::contains_name(&def.attrs, sym::allow_internal_unsafe), - local_inner_macros, - stability: attr::find_stability(&sess, &def.attrs, def.span), - deprecation: attr::find_deprecation(&sess, &def.attrs, def.span), - helper_attrs: Vec::new(), + SyntaxExtension::new( + sess, + SyntaxExtensionKind::LegacyBang(expander), + def.span, + Vec::new(), edition, - is_builtin, - is_derive_copy: is_builtin && def.ident.name == sym::Copy, - } + def.ident.name, + &def.attrs, + ) } fn check_lhs_nt_follows( diff --git a/src/test/ui/proc-macro/attributes-on-definitions.rs b/src/test/ui/proc-macro/attributes-on-definitions.rs new file mode 100644 index 0000000000000..055781d2c6048 --- /dev/null +++ b/src/test/ui/proc-macro/attributes-on-definitions.rs @@ -0,0 +1,12 @@ +// check-pass +// aux-build:attributes-on-definitions.rs + +#![forbid(unsafe_code)] + +extern crate attributes_on_definitions; + +attributes_on_definitions::with_attrs!(); +//~^ WARN use of deprecated item +// No errors about the use of unstable and unsafe code inside the macro. + +fn main() {} diff --git a/src/test/ui/proc-macro/attributes-on-definitions.stderr b/src/test/ui/proc-macro/attributes-on-definitions.stderr new file mode 100644 index 0000000000000..c61e043b22971 --- /dev/null +++ b/src/test/ui/proc-macro/attributes-on-definitions.stderr @@ -0,0 +1,8 @@ +warning: use of deprecated item 'attributes_on_definitions::with_attrs': test + --> $DIR/attributes-on-definitions.rs:8:1 + | +LL | attributes_on_definitions::with_attrs!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + diff --git a/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs b/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs new file mode 100644 index 0000000000000..93a339840d621 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs @@ -0,0 +1,23 @@ +// force-host +// no-prefer-dynamic + +#![feature(allow_internal_unsafe)] +#![feature(allow_internal_unstable)] + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +#[allow_internal_unstable(proc_macro_internals)] +#[allow_internal_unsafe] +#[deprecated(since = "1.0.0", note = "test")] +pub fn with_attrs(_: TokenStream) -> TokenStream { + " + extern crate proc_macro; + use ::proc_macro::bridge; + + fn contains_unsafe() { unsafe {} } + ".parse().unwrap() +} From 2065ee9accc87a461897d06414195cfa3e92fb89 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 20 Aug 2019 23:18:55 +0300 Subject: [PATCH 261/618] metadata: Eliminate `FullProcMacro` Fix caching of loaded proc macros --- src/librustc_metadata/cstore.rs | 7 +-- src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/decoder.rs | 53 +++++++-------------- src/librustc_resolve/build_reduced_graph.rs | 12 ++--- src/librustc_resolve/macros.rs | 4 +- 5 files changed, 28 insertions(+), 50 deletions(-) diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index efc77699313e0..5bf4067431f24 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -95,11 +95,6 @@ pub struct CrateMetadata { pub raw_proc_macros: Option<&'static [ProcMacro]>, } -pub struct FullProcMacro { - pub name: ast::Name, - pub ext: Lrc -} - pub struct CStore { metas: RwLock>>>, /// Map from NodeId's of local extern crate statements to crate numbers @@ -109,7 +104,7 @@ pub struct CStore { pub enum LoadedMacro { MacroDef(ast::Item), - ProcMacro(Lrc), + ProcMacro(SyntaxExtension), } impl CStore { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index f4c04770c1505..5bfb315da473f 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -434,7 +434,7 @@ impl cstore::CStore { pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro { let data = self.get_crate_data(id.krate); if data.is_proc_macro_crate() { - return LoadedMacro::ProcMacro(data.get_proc_macro(id.index, sess).ext); + return LoadedMacro::ProcMacro(data.load_proc_macro(id.index, sess)); } let def = data.get_macro(id.index); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index fffeee82d8d24..c777b5ea409a4 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1,6 +1,6 @@ // Decoding metadata from a single crate's metadata -use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule, FullProcMacro}; +use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule}; use crate::schema::*; use rustc_data_structures::indexed_vec::IndexVec; @@ -512,26 +512,8 @@ impl<'a, 'tcx> CrateMetadata { self.entry(index).span.decode((self, sess)) } - - pub fn get_proc_macro(&self, id: DefIndex, sess: &Session) -> FullProcMacro { - if sess.opts.debugging_opts.dual_proc_macros { - let host_lib = self.host_lib.as_ref().unwrap(); - self.load_proc_macro( - &host_lib.metadata.get_root(), - id, - sess - ) - } else { - self.load_proc_macro(&self.root, id, sess) - } - } - - fn load_proc_macro(&self, root: &CrateRoot<'_>, - id: DefIndex, - sess: &Session) - -> FullProcMacro { - let raw_macro = self.raw_proc_macro(id); - let (name, kind, helper_attrs) = match *raw_macro { + crate fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension { + let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) { ProcMacro::CustomDerive { trait_name, attributes, client } => { let helper_attrs = attributes.iter().cloned().map(Symbol::intern).collect::>(); @@ -550,20 +532,21 @@ impl<'a, 'tcx> CrateMetadata { name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new() ) }; - let name = Symbol::intern(name); - - FullProcMacro { - name, - ext: Lrc::new(SyntaxExtension::new( - &sess.parse_sess, - kind, - self.get_span(id, sess), - helper_attrs, - root.edition, - name, - &self.get_attributes(&self.entry(id), sess), - )), - } + let edition = if sess.opts.debugging_opts.dual_proc_macros { + self.host_lib.as_ref().unwrap().metadata.get_root().edition + } else { + self.root.edition + }; + + SyntaxExtension::new( + &sess.parse_sess, + kind, + self.get_span(id, sess), + helper_attrs, + edition, + Symbol::intern(name), + &self.get_attributes(&self.entry(id), sess), + ) } pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 9a794ade729c2..165a4c707bb6d 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -150,12 +150,12 @@ impl<'a> Resolver<'a> { return Some(ext.clone()); } - let macro_def = match self.cstore.load_macro_untracked(def_id, &self.session) { - LoadedMacro::MacroDef(macro_def) => macro_def, - LoadedMacro::ProcMacro(ext) => return Some(ext), - }; + let ext = Lrc::new(match self.cstore.load_macro_untracked(def_id, &self.session) { + LoadedMacro::MacroDef(item) => + self.compile_macro(&item, self.cstore.crate_edition_untracked(def_id.krate)), + LoadedMacro::ProcMacro(ext) => ext, + }); - let ext = self.compile_macro(¯o_def, self.cstore.crate_edition_untracked(def_id.krate)); self.macro_map.insert(def_id, ext.clone()); Some(ext) } @@ -1104,7 +1104,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let expansion = parent_scope.expansion; let (ext, ident, span, is_legacy) = match &item.node { ItemKind::MacroDef(def) => { - let ext = self.r.compile_macro(item, self.r.session.edition()); + let ext = Lrc::new(self.r.compile_macro(item, self.r.session.edition())); (ext, item.ident, item.span, def.legacy) } ItemKind::Fn(..) => match Self::proc_macro_stub(item) { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 719167eb057b2..cc78e928380a8 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -800,7 +800,7 @@ impl<'a> Resolver<'a> { /// Compile the macro into a `SyntaxExtension` and possibly replace it with a pre-defined /// extension partially or entirely for built-in macros and legacy plugin macros. - crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> Lrc { + crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> SyntaxExtension { let mut result = macro_rules::compile( &self.session.parse_sess, self.session.features_untracked(), item, edition ); @@ -822,6 +822,6 @@ impl<'a> Resolver<'a> { } } - Lrc::new(result) + result } } From c476b55e528ce854b6198de5bcfdd20b08440c9d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 20 Aug 2019 23:35:03 +0300 Subject: [PATCH 262/618] proc_macro: Update `Span::def_site` to use the proc macro definition location Which is no longer dummy and is available from metadata now. --- src/libsyntax/ext/proc_macro_server.rs | 7 +- src/libsyntax/parse/parser.rs | 9 +- .../macros/auxiliary/proc_macro_sequence.rs | 20 ++- src/test/ui/macros/same-sequence-span.stderr | 12 +- src/test/ui/proc-macro/multispan.stderr | 133 ++++++++++++++---- src/test/ui/proc-macro/three-equals.stderr | 19 ++- 6 files changed, 151 insertions(+), 49 deletions(-) diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs index b1bbd2aaac971..1a26b17dac782 100644 --- a/src/libsyntax/ext/proc_macro_server.rs +++ b/src/libsyntax/ext/proc_macro_server.rs @@ -360,12 +360,11 @@ pub(crate) struct Rustc<'a> { impl<'a> Rustc<'a> { pub fn new(cx: &'a ExtCtxt<'_>) -> Self { - // No way to determine def location for a proc macro right now, so use call location. - let location = cx.current_expansion.id.expn_data().call_site; + let expn_data = cx.current_expansion.id.expn_data(); Rustc { sess: cx.parse_sess, - def_site: cx.with_def_site_ctxt(location), - call_site: cx.with_call_site_ctxt(location), + def_site: cx.with_def_site_ctxt(expn_data.def_site), + call_site: cx.with_call_site_ctxt(expn_data.call_site), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 89725d8b3395c..47243b1ac5678 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -375,10 +375,11 @@ impl<'a> Parser<'a> { if let Some(directory) = directory { parser.directory = directory; } else if !parser.token.span.is_dummy() { - if let FileName::Real(mut path) = - sess.source_map().span_to_unmapped_path(parser.token.span) { - path.pop(); - parser.directory.path = Cow::from(path); + if let Some(FileName::Real(path)) = + &sess.source_map().lookup_char_pos(parser.token.span.lo()).file.unmapped_path { + if let Some(directory_path) = path.parent() { + parser.directory.path = Cow::from(directory_path.to_path_buf()); + } } } diff --git a/src/test/ui/macros/auxiliary/proc_macro_sequence.rs b/src/test/ui/macros/auxiliary/proc_macro_sequence.rs index b50ed7ca92ad5..c460db36f1aa3 100644 --- a/src/test/ui/macros/auxiliary/proc_macro_sequence.rs +++ b/src/test/ui/macros/auxiliary/proc_macro_sequence.rs @@ -6,7 +6,7 @@ extern crate proc_macro; -use proc_macro::{quote, Span, TokenStream}; +use proc_macro::{quote, Span, TokenStream, TokenTree}; fn assert_same_span(a: Span, b: Span) { assert_eq!(a.start(), b.start()); @@ -24,12 +24,22 @@ pub fn make_foo(_: TokenStream) -> TokenStream { }; // Check that all spans are equal. - let mut span = None; + // FIXME: `quote!` gives def-site spans to idents and literals, + // but leaves (default) call-site spans on groups and punctuation. + let mut span_call = None; + let mut span_def = None; for tt in result.clone() { - match span { - None => span = Some(tt.span()), - Some(span) => assert_same_span(tt.span(), span), + match tt { + TokenTree::Ident(..) | TokenTree::Literal(..) => match span_def { + None => span_def = Some(tt.span()), + Some(span) => assert_same_span(tt.span(), span), + } + TokenTree::Punct(..) | TokenTree::Group(..) => match span_call { + None => span_call = Some(tt.span()), + Some(span) => assert_same_span(tt.span(), span), + } } + } result diff --git a/src/test/ui/macros/same-sequence-span.stderr b/src/test/ui/macros/same-sequence-span.stderr index 250773a1853ec..0eef4a2a678b6 100644 --- a/src/test/ui/macros/same-sequence-span.stderr +++ b/src/test/ui/macros/same-sequence-span.stderr @@ -17,11 +17,15 @@ LL | $(= $z:tt)* error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments --> $DIR/same-sequence-span.rs:20:1 | -LL | proc_macro_sequence::make_foo!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | proc_macro_sequence::make_foo!(); + | ^-------------------------------- + | | + | _in this macro invocation | | - | not allowed after `expr` fragments - | in this macro invocation +LL | | +LL | | +LL | | fn main() {} +... | | = note: allowed there are: `=>`, `,` or `;` diff --git a/src/test/ui/proc-macro/multispan.stderr b/src/test/ui/proc-macro/multispan.stderr index a0c1f9cd5c05f..e7f705c7feb67 100644 --- a/src/test/ui/proc-macro/multispan.stderr +++ b/src/test/ui/proc-macro/multispan.stderr @@ -1,8 +1,19 @@ error: hello to you, too! - --> $DIR/multispan.rs:14:5 - | -LL | hello!(hi); - | ^^^^^^^^^^^ in this macro invocation + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:14:5 + | +LL | hello!(hi); + | ----------- in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:14:12 @@ -11,10 +22,21 @@ LL | hello!(hi); | ^^ error: hello to you, too! - --> $DIR/multispan.rs:17:5 - | -LL | hello!(hi hi); - | ^^^^^^^^^^^^^^ in this macro invocation + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:17:5 + | +LL | hello!(hi hi); + | -------------- in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:17:12 @@ -23,10 +45,21 @@ LL | hello!(hi hi); | ^^ ^^ error: hello to you, too! - --> $DIR/multispan.rs:20:5 - | -LL | hello!(hi hi hi); - | ^^^^^^^^^^^^^^^^^ in this macro invocation + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:20:5 + | +LL | hello!(hi hi hi); + | ----------------- in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:20:12 @@ -35,10 +68,21 @@ LL | hello!(hi hi hi); | ^^ ^^ ^^ error: hello to you, too! - --> $DIR/multispan.rs:23:5 - | -LL | hello!(hi hey hi yo hi beep beep hi hi); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:23:5 + | +LL | hello!(hi hey hi yo hi beep beep hi hi); + | ---------------------------------------- in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:23:12 @@ -47,10 +91,21 @@ LL | hello!(hi hey hi yo hi beep beep hi hi); | ^^ ^^ ^^ ^^ ^^ error: hello to you, too! - --> $DIR/multispan.rs:24:5 - | -LL | hello!(hi there, hi how are you? hi... hi.); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:24:5 + | +LL | hello!(hi there, hi how are you? hi... hi.); + | -------------------------------------------- in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:24:12 @@ -59,10 +114,21 @@ LL | hello!(hi there, hi how are you? hi... hi.); | ^^ ^^ ^^ ^^ error: hello to you, too! - --> $DIR/multispan.rs:25:5 - | -LL | hello!(whoah. hi di hi di ho); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:25:5 + | +LL | hello!(whoah. hi di hi di ho); + | ------------------------------ in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:25:19 @@ -71,10 +137,21 @@ LL | hello!(whoah. hi di hi di ho); | ^^ ^^ error: hello to you, too! - --> $DIR/multispan.rs:26:5 - | -LL | hello!(hi good hi and good bye); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + --> $DIR/auxiliary/multispan.rs:31:1 + | +LL | / pub fn hello(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | } +LL | | +LL | | TokenStream::new() +LL | | } + | |_^ + | + ::: $DIR/multispan.rs:26:5 + | +LL | hello!(hi good hi and good bye); + | -------------------------------- in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:26:12 diff --git a/src/test/ui/proc-macro/three-equals.stderr b/src/test/ui/proc-macro/three-equals.stderr index 0a6cbe13098a8..0698b0f475424 100644 --- a/src/test/ui/proc-macro/three-equals.stderr +++ b/src/test/ui/proc-macro/three-equals.stderr @@ -1,8 +1,19 @@ error: found 2 equal signs, need exactly 3 - --> $DIR/three-equals.rs:15:5 - | -LL | three_equals!(==); - | ^^^^^^^^^^^^^^^^^^ in this macro invocation + --> $DIR/auxiliary/three-equals.rs:42:1 + | +LL | / pub fn three_equals(input: TokenStream) -> TokenStream { +LL | | if let Err(diag) = parse(input) { +LL | | diag.emit(); +LL | | return TokenStream::new(); +... | +LL | | "3".parse().unwrap() +LL | | } + | |_^ + | + ::: $DIR/three-equals.rs:15:5 + | +LL | three_equals!(==); + | ------------------ in this macro invocation | = help: input must be: `===` From a77247acb1bbecff8acedefce3c6cc06d7787311 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 11 Aug 2019 16:11:53 -0400 Subject: [PATCH 263/618] Move source HTML generation to own module --- src/librustdoc/html/render.rs | 179 ++----------------------------- src/librustdoc/html/sources.rs | 187 +++++++++++++++++++++++++++++++++ src/librustdoc/lib.rs | 1 + 3 files changed, 194 insertions(+), 173 deletions(-) create mode 100644 src/librustdoc/html/sources.rs diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b64e74468e6e9..c8921a92d3382 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -72,6 +72,7 @@ use crate::html::format::fmt_impl_for_trait_page; use crate::html::item_type::ItemType; use crate::html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine, ErrorCodes, IdMap}; use crate::html::{highlight, layout, static_files}; +use crate::html::sources; use minifier; @@ -173,7 +174,7 @@ struct Context { playground: Option, } -struct SharedContext { +crate struct SharedContext { /// The path to the crate root source minus the file name. /// Used for simplifying paths to the highlighted source code files. pub src_root: PathBuf, @@ -218,7 +219,7 @@ struct SharedContext { } impl SharedContext { - fn ensure_dir(&self, dst: &Path) -> Result<(), Error> { + crate fn ensure_dir(&self, dst: &Path) -> Result<(), Error> { let mut dirs = self.created_dirs.borrow_mut(); if !dirs.contains(dst) { try_err!(self.fs.create_dir_all(dst), dst); @@ -389,18 +390,6 @@ pub struct RenderInfo { pub owned_box_did: Option, } -/// Helper struct to render all source code to HTML pages -struct SourceCollector<'a> { - scx: &'a mut SharedContext, - - /// Root destination to place all HTML output into - dst: PathBuf, -} - -/// Wrapper struct to render the source code of a file. This will do things like -/// adding line numbers to the left-hand side. -struct Source<'a>(&'a str); - // Helper structs for rendering items/sidebars and carrying along contextual // information @@ -612,7 +601,7 @@ pub fn run(mut krate: clean::Crate, } let dst = output; scx.ensure_dir(&dst)?; - krate = render_sources(&dst, &mut scx, krate)?; + krate = sources::render(&dst, &mut scx, krate)?; let mut cx = Context { current: Vec::new(), dst, @@ -1293,18 +1282,6 @@ themePicker.onblur = handleThemeButtonsBlur; Ok(()) } -fn render_sources(dst: &Path, scx: &mut SharedContext, - krate: clean::Crate) -> Result { - info!("emitting source files"); - let dst = dst.join("src").join(&krate.name); - scx.ensure_dir(&dst)?; - let mut folder = SourceCollector { - dst, - scx, - }; - Ok(folder.fold_crate(krate)) -} - fn write_minify(fs:&DocFS, dst: PathBuf, contents: &str, enable_minification: bool ) -> Result<(), Error> { if enable_minification { @@ -1384,33 +1361,6 @@ fn write_minify_replacer( } } -/// Takes a path to a source file and cleans the path to it. This canonicalizes -/// things like ".." to components which preserve the "top down" hierarchy of a -/// static HTML tree. Each component in the cleaned path will be passed as an -/// argument to `f`. The very last component of the path (ie the file name) will -/// be passed to `f` if `keep_filename` is true, and ignored otherwise. -fn clean_srcpath(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) -where - F: FnMut(&OsStr), -{ - // make it relative, if possible - let p = p.strip_prefix(src_root).unwrap_or(p); - - let mut iter = p.components().peekable(); - - while let Some(c) = iter.next() { - if !keep_filename && iter.peek().is_none() { - break; - } - - match c { - Component::ParentDir => f("up".as_ref()), - Component::Normal(c) => f(c), - _ => continue, - } - } -} - /// Attempts to find where an external crate is located, given that we're /// rendering in to the specified source destination. fn extern_location(e: &clean::ExternalCrate, extern_url: Option<&str>, dst: &Path) @@ -1444,102 +1394,6 @@ fn extern_location(e: &clean::ExternalCrate, extern_url: Option<&str>, dst: &Pat }).next().unwrap_or(Unknown) // Well, at least we tried. } -impl<'a> DocFolder for SourceCollector<'a> { - fn fold_item(&mut self, item: clean::Item) -> Option { - // If we're including source files, and we haven't seen this file yet, - // then we need to render it out to the filesystem. - if self.scx.include_sources - // skip all invalid or macro spans - && item.source.filename.is_real() - // skip non-local items - && item.def_id.is_local() { - - // If it turns out that we couldn't read this file, then we probably - // can't read any of the files (generating html output from json or - // something like that), so just don't include sources for the - // entire crate. The other option is maintaining this mapping on a - // per-file basis, but that's probably not worth it... - self.scx - .include_sources = match self.emit_source(&item.source.filename) { - Ok(()) => true, - Err(e) => { - println!("warning: source code was requested to be rendered, \ - but processing `{}` had an error: {}", - item.source.filename, e); - println!(" skipping rendering of source code"); - false - } - }; - } - self.fold_item_recur(item) - } -} - -impl<'a> SourceCollector<'a> { - /// Renders the given filename into its corresponding HTML source file. - fn emit_source(&mut self, filename: &FileName) -> Result<(), Error> { - let p = match *filename { - FileName::Real(ref file) => file, - _ => return Ok(()), - }; - if self.scx.local_sources.contains_key(&**p) { - // We've already emitted this source - return Ok(()); - } - - let contents = try_err!(fs::read_to_string(&p), &p); - - // Remove the utf-8 BOM if any - let contents = if contents.starts_with("\u{feff}") { - &contents[3..] - } else { - &contents[..] - }; - - // Create the intermediate directories - let mut cur = self.dst.clone(); - let mut root_path = String::from("../../"); - let mut href = String::new(); - clean_srcpath(&self.scx.src_root, &p, false, |component| { - cur.push(component); - root_path.push_str("../"); - href.push_str(&component.to_string_lossy()); - href.push('/'); - }); - self.scx.ensure_dir(&cur)?; - let mut fname = p.file_name() - .expect("source has no filename") - .to_os_string(); - fname.push(".html"); - cur.push(&fname); - href.push_str(&fname.to_string_lossy()); - - let mut v = Vec::new(); - let title = format!("{} -- source", cur.file_name().expect("failed to get file name") - .to_string_lossy()); - let desc = format!("Source to the Rust file `{}`.", filename); - let page = layout::Page { - title: &title, - css_class: "source", - root_path: &root_path, - static_root_path: self.scx.static_root_path.as_deref(), - description: &desc, - keywords: BASIC_KEYWORDS, - resource_suffix: &self.scx.resource_suffix, - extra_scripts: &[&format!("source-files{}", self.scx.resource_suffix)], - static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)], - }; - try_err!(layout::render(&mut v, &self.scx.layout, - &page, &(""), &Source(contents), - self.scx.css_file_extension.is_some(), - &self.scx.themes, - self.scx.generate_search_filter), &cur); - self.scx.fs.write(&cur, &v)?; - self.scx.local_sources.insert(p.clone(), href); - Ok(()) - } -} - impl DocFolder for Cache { fn fold_item(&mut self, item: clean::Item) -> Option { if item.def_id.is_local() { @@ -2399,7 +2253,7 @@ impl<'a> Item<'a> { (_, _, Unknown) => return None, }; - clean_srcpath(&src_root, file, false, |component| { + sources::clean_path(&src_root, file, false, |component| { path.push_str(&component.to_string_lossy()); path.push('/'); }); @@ -5048,27 +4902,6 @@ fn sidebar_foreign_type(fmt: &mut fmt::Formatter<'_>, it: &clean::Item) -> fmt:: Ok(()) } -impl<'a> fmt::Display for Source<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let Source(s) = *self; - let lines = s.lines().count(); - let mut cols = 0; - let mut tmp = lines; - while tmp > 0 { - cols += 1; - tmp /= 10; - } - write!(fmt, "
")?;
-        for i in 1..=lines {
-            write!(fmt, "{0:1$}\n", i, cols)?;
-        }
-        write!(fmt, "
")?; - write!(fmt, "{}", - highlight::render_with_highlighting(s, None, None, None))?; - Ok(()) - } -} - fn item_macro(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, t: &clean::Macro) -> fmt::Result { wrap_into_docblock(w, |w| { @@ -5125,7 +4958,7 @@ fn item_keyword(w: &mut fmt::Formatter<'_>, cx: &Context, document(w, cx, it) } -const BASIC_KEYWORDS: &'static str = "rust, rustlang, rust-lang"; +crate const BASIC_KEYWORDS: &'static str = "rust, rustlang, rust-lang"; fn make_item_keywords(it: &clean::Item) -> String { format!("{}, {}", BASIC_KEYWORDS, it.name.as_ref().unwrap()) diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs new file mode 100644 index 0000000000000..c1f1f59d9149a --- /dev/null +++ b/src/librustdoc/html/sources.rs @@ -0,0 +1,187 @@ +use crate::clean; +use crate::docfs::PathError; +use crate::fold::DocFolder; +use crate::html::layout; +use crate::html::render::{Error, SharedContext, BASIC_KEYWORDS}; +use crate::html::highlight; +use std::ffi::OsStr; +use std::fs; +use std::path::{Component, Path, PathBuf}; +use std::fmt; +use syntax::source_map::FileName; + +crate fn render(dst: &Path, scx: &mut SharedContext, + krate: clean::Crate) -> Result { + info!("emitting source files"); + let dst = dst.join("src").join(&krate.name); + scx.ensure_dir(&dst)?; + let mut folder = SourceCollector { + dst, + scx, + }; + Ok(folder.fold_crate(krate)) +} + +/// Helper struct to render all source code to HTML pages +struct SourceCollector<'a> { + scx: &'a mut SharedContext, + + /// Root destination to place all HTML output into + dst: PathBuf, +} + +impl<'a> DocFolder for SourceCollector<'a> { + fn fold_item(&mut self, item: clean::Item) -> Option { + // If we're including source files, and we haven't seen this file yet, + // then we need to render it out to the filesystem. + if self.scx.include_sources + // skip all invalid or macro spans + && item.source.filename.is_real() + // skip non-local items + && item.def_id.is_local() { + + // If it turns out that we couldn't read this file, then we probably + // can't read any of the files (generating html output from json or + // something like that), so just don't include sources for the + // entire crate. The other option is maintaining this mapping on a + // per-file basis, but that's probably not worth it... + self.scx + .include_sources = match self.emit_source(&item.source.filename) { + Ok(()) => true, + Err(e) => { + println!("warning: source code was requested to be rendered, \ + but processing `{}` had an error: {}", + item.source.filename, e); + println!(" skipping rendering of source code"); + false + } + }; + } + self.fold_item_recur(item) + } +} + +impl<'a> SourceCollector<'a> { + /// Renders the given filename into its corresponding HTML source file. + fn emit_source(&mut self, filename: &FileName) -> Result<(), Error> { + let p = match *filename { + FileName::Real(ref file) => file, + _ => return Ok(()), + }; + if self.scx.local_sources.contains_key(&**p) { + // We've already emitted this source + return Ok(()); + } + + let contents = match fs::read_to_string(&p) { + Ok(contents) => contents, + Err(e) => { + return Err(Error::new(e, &p)); + } + }; + + // Remove the utf-8 BOM if any + let contents = if contents.starts_with("\u{feff}") { + &contents[3..] + } else { + &contents[..] + }; + + // Create the intermediate directories + let mut cur = self.dst.clone(); + let mut root_path = String::from("../../"); + let mut href = String::new(); + clean_path(&self.scx.src_root, &p, false, |component| { + cur.push(component); + root_path.push_str("../"); + href.push_str(&component.to_string_lossy()); + href.push('/'); + }); + self.scx.ensure_dir(&cur)?; + let mut fname = p.file_name() + .expect("source has no filename") + .to_os_string(); + fname.push(".html"); + cur.push(&fname); + href.push_str(&fname.to_string_lossy()); + + let mut v = Vec::new(); + let title = format!("{} -- source", cur.file_name().expect("failed to get file name") + .to_string_lossy()); + let desc = format!("Source to the Rust file `{}`.", filename); + let page = layout::Page { + title: &title, + css_class: "source", + root_path: &root_path, + static_root_path: self.scx.static_root_path.as_deref(), + description: &desc, + keywords: BASIC_KEYWORDS, + resource_suffix: &self.scx.resource_suffix, + extra_scripts: &[&format!("source-files{}", self.scx.resource_suffix)], + static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)], + }; + let result = layout::render(&mut v, &self.scx.layout, + &page, &(""), &Source(contents), + self.scx.css_file_extension.is_some(), + &self.scx.themes, + self.scx.generate_search_filter); + if let Err(e) = result { + return Err(Error::new(e, &cur)); + } + self.scx.fs.write(&cur, &v)?; + self.scx.local_sources.insert(p.clone(), href); + Ok(()) + } +} + +/// Takes a path to a source file and cleans the path to it. This canonicalizes +/// things like ".." to components which preserve the "top down" hierarchy of a +/// static HTML tree. Each component in the cleaned path will be passed as an +/// argument to `f`. The very last component of the path (ie the file name) will +/// be passed to `f` if `keep_filename` is true, and ignored otherwise. +pub fn clean_path(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) +where + F: FnMut(&OsStr), +{ + // make it relative, if possible + let p = p.strip_prefix(src_root).unwrap_or(p); + + let mut iter = p.components().peekable(); + + while let Some(c) = iter.next() { + if !keep_filename && iter.peek().is_none() { + break; + } + + match c { + Component::ParentDir => f("up".as_ref()), + Component::Normal(c) => f(c), + _ => continue, + } + } +} + +/// Wrapper struct to render the source code of a file. This will do things like +/// adding line numbers to the left-hand side. +struct Source<'a>(&'a str); + +impl<'a> fmt::Display for Source<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let Source(s) = *self; + let lines = s.lines().count(); + let mut cols = 0; + let mut tmp = lines; + while tmp > 0 { + cols += 1; + tmp /= 10; + } + write!(fmt, "
")?;
+        for i in 1..=lines {
+            write!(fmt, "{0:1$}\n", i, cols)?;
+        }
+        write!(fmt, "
")?; + write!(fmt, "{}", + highlight::render_with_highlighting(s, None, None, None))?; + Ok(()) + } +} diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index e30b35937db9f..968578f957c5c 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -67,6 +67,7 @@ pub mod html { crate mod render; crate mod static_files; crate mod toc; + crate mod sources; } mod markdown; mod passes; From e2b6f4c662ee2b57aeb0bdcd63356721cc6c4894 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 12 Aug 2019 07:10:55 -0400 Subject: [PATCH 264/618] Move top-level Clean impl to function This allows us to pass it a `&mut DocContext` which will allow removal of RefCells, etc. in the following commits. It's also somewhat a unique Clean impl in that it previously ignored `self` (re-retriveing hir::Crate), which it no longer needs to do. --- src/librustdoc/clean/mod.rs | 164 ++++++++++++++++++------------------ src/librustdoc/core.rs | 6 +- 2 files changed, 83 insertions(+), 87 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ba792a413b3c4..19cb5ddb91e86 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -136,94 +136,90 @@ pub struct Crate { pub collapsed: bool, } -impl Clean for hir::Crate { - // note that self here is ignored in favor of `cx.tcx.hir().krate()` since - // that gets around tying self's lifetime to the '_ in cx. - fn clean(&self, cx: &DocContext<'_>) -> Crate { - use crate::visit_lib::LibEmbargoVisitor; - - let v = crate::visit_ast::RustdocVisitor::new(&cx); - let module = v.visit(cx.tcx.hir().krate()); - - { - let mut r = cx.renderinfo.borrow_mut(); - r.deref_trait_did = cx.tcx.lang_items().deref_trait(); - r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait(); - r.owned_box_did = cx.tcx.lang_items().owned_box(); - } - - let mut externs = Vec::new(); - for &cnum in cx.tcx.crates().iter() { - externs.push((cnum, cnum.clean(cx))); - // Analyze doc-reachability for extern items - LibEmbargoVisitor::new(cx).visit_lib(cnum); - } - externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); - - // Clean the crate, translating the entire libsyntax AST to one that is - // understood by rustdoc. - let mut module = module.clean(cx); - let mut masked_crates = FxHashSet::default(); - - match module.inner { - ModuleItem(ref module) => { - for it in &module.items { - // `compiler_builtins` should be masked too, but we can't apply - // `#[doc(masked)]` to the injected `extern crate` because it's unstable. - if it.is_extern_crate() - && (it.attrs.has_doc_flag(sym::masked) - || cx.tcx.is_compiler_builtins(it.def_id.krate)) - { - masked_crates.insert(it.def_id.krate); - } - } - } - _ => unreachable!(), - } +pub fn krate(cx: &mut DocContext<'a>) -> Crate { + use crate::visit_lib::LibEmbargoVisitor; - let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx); - { - let m = match module.inner { - ModuleItem(ref mut m) => m, - _ => unreachable!(), - }; - m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| { - Item { - source: Span::empty(), - name: Some(prim.to_url_str().to_string()), - attrs: attrs.clone(), - visibility: Some(Public), - stability: get_stability(cx, def_id), - deprecation: get_deprecation(cx, def_id), - def_id, - inner: PrimitiveItem(prim), - } - })); - m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| { - Item { - source: Span::empty(), - name: Some(kw.clone()), - attrs: attrs, - visibility: Some(Public), - stability: get_stability(cx, def_id), - deprecation: get_deprecation(cx, def_id), - def_id, - inner: KeywordItem(kw), + let v = crate::visit_ast::RustdocVisitor::new(&cx); + let module = v.visit(cx.tcx.hir().krate()); + + { + let mut r = cx.renderinfo.borrow_mut(); + r.deref_trait_did = cx.tcx.lang_items().deref_trait(); + r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait(); + r.owned_box_did = cx.tcx.lang_items().owned_box(); + } + + let mut externs = Vec::new(); + for &cnum in cx.tcx.crates().iter() { + externs.push((cnum, cnum.clean(cx))); + // Analyze doc-reachability for extern items + LibEmbargoVisitor::new(cx).visit_lib(cnum); + } + externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); + + // Clean the crate, translating the entire libsyntax AST to one that is + // understood by rustdoc. + let mut module = module.clean(cx); + let mut masked_crates = FxHashSet::default(); + + match module.inner { + ModuleItem(ref module) => { + for it in &module.items { + // `compiler_builtins` should be masked too, but we can't apply + // `#[doc(masked)]` to the injected `extern crate` because it's unstable. + if it.is_extern_crate() + && (it.attrs.has_doc_flag(sym::masked) + || cx.tcx.is_compiler_builtins(it.def_id.krate)) + { + masked_crates.insert(it.def_id.krate); } - })); + } } + _ => unreachable!(), + } - Crate { - name, - version: None, - src, - module: Some(module), - externs, - primitives, - external_traits: cx.external_traits.clone(), - masked_crates, - collapsed: false, - } + let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx); + { + let m = match module.inner { + ModuleItem(ref mut m) => m, + _ => unreachable!(), + }; + m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| { + Item { + source: Span::empty(), + name: Some(prim.to_url_str().to_string()), + attrs: attrs.clone(), + visibility: Some(Public), + stability: get_stability(cx, def_id), + deprecation: get_deprecation(cx, def_id), + def_id, + inner: PrimitiveItem(prim), + } + })); + m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| { + Item { + source: Span::empty(), + name: Some(kw.clone()), + attrs: attrs, + visibility: Some(Public), + stability: get_stability(cx, def_id), + deprecation: get_deprecation(cx, def_id), + def_id, + inner: KeywordItem(kw), + } + })); + } + + Crate { + name, + version: None, + src, + module: Some(module), + externs, + primitives, + external_traits: cx.external_traits.clone(), + masked_crates, + collapsed: false, } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 04e69613d4b0f..45ebaa115063a 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -30,7 +30,7 @@ use std::rc::Rc; use crate::config::{Options as RustdocOptions, RenderOptions}; use crate::clean; -use crate::clean::{Clean, MAX_DEF_ID, AttributesExt}; +use crate::clean::{MAX_DEF_ID, AttributesExt}; use crate::html::render::RenderInfo; use crate::passes; @@ -363,7 +363,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut renderinfo = RenderInfo::default(); renderinfo.access_levels = access_levels; - let ctxt = DocContext { + let mut ctxt = DocContext { tcx, resolver, cstore: compiler.cstore().clone(), @@ -383,7 +383,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt }; debug!("crate: {:?}", tcx.hir().krate()); - let mut krate = tcx.hir().krate().clean(&ctxt); + let mut krate = clean::krate(&mut ctxt); fn report_deprecated_attr(name: &str, diag: &errors::Handler) { let mut msg = diag.struct_warn(&format!("the `#![doc({})]` attribute is \ From 57d57c67843f05a40d11c7d442bd5b461da6ddee Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 12 Aug 2019 07:21:04 -0400 Subject: [PATCH 265/618] Mutate DocContext from LibEmbargoVisitor and RustdocVisitor We have &mut access, so remove the RefCell borrowing --- src/librustdoc/clean/mod.rs | 18 ++++++++---------- src/librustdoc/visit_ast.rs | 8 ++++---- src/librustdoc/visit_lib.rs | 24 +++++++++++------------- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 19cb5ddb91e86..62900fa9fb15f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -136,24 +136,22 @@ pub struct Crate { pub collapsed: bool, } -pub fn krate(cx: &mut DocContext<'a>) -> Crate { +pub fn krate(mut cx: &mut DocContext<'_>) -> Crate { use crate::visit_lib::LibEmbargoVisitor; - let v = crate::visit_ast::RustdocVisitor::new(&cx); - let module = v.visit(cx.tcx.hir().krate()); + let krate = cx.tcx.hir().krate(); + let module = crate::visit_ast::RustdocVisitor::new(&mut cx).visit(krate); - { - let mut r = cx.renderinfo.borrow_mut(); - r.deref_trait_did = cx.tcx.lang_items().deref_trait(); - r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait(); - r.owned_box_did = cx.tcx.lang_items().owned_box(); - } + let mut r = cx.renderinfo.get_mut(); + r.deref_trait_did = cx.tcx.lang_items().deref_trait(); + r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait(); + r.owned_box_did = cx.tcx.lang_items().owned_box(); let mut externs = Vec::new(); for &cnum in cx.tcx.crates().iter() { externs.push((cnum, cnum.clean(cx))); // Analyze doc-reachability for extern items - LibEmbargoVisitor::new(cx).visit_lib(cnum); + LibEmbargoVisitor::new(&mut cx).visit_lib(cnum); } externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 903ed3aae1470..ee330cb32111e 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -41,7 +41,7 @@ fn def_id_to_path( // framework from syntax?. pub struct RustdocVisitor<'a, 'tcx> { - cx: &'a core::DocContext<'tcx>, + cx: &'a mut core::DocContext<'tcx>, view_item_stack: FxHashSet, inlining: bool, /// Are the current module and all of its parents public? @@ -51,7 +51,7 @@ pub struct RustdocVisitor<'a, 'tcx> { impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { pub fn new( - cx: &'a core::DocContext<'tcx> + cx: &'a mut core::DocContext<'tcx> ) -> RustdocVisitor<'a, 'tcx> { // If the root is re-exported, terminate all recursion. let mut stack = FxHashSet::default(); @@ -84,7 +84,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { ); module.is_crate = true; - self.cx.renderinfo.borrow_mut().exact_paths = self.exact_paths; + self.cx.renderinfo.get_mut().exact_paths = self.exact_paths; module } @@ -292,7 +292,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Res::Def(DefKind::ForeignTy, did) | Res::Def(DefKind::TyAlias, did) if !self_is_hidden => { self.cx.renderinfo - .borrow_mut() + .get_mut() .access_levels.map .insert(did, AccessLevel::Public); }, diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 2547e3a06e9ef..b229b5f6884d8 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -1,12 +1,10 @@ use rustc::middle::privacy::{AccessLevels, AccessLevel}; use rustc::hir::def::{Res, DefKind}; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; -use rustc::ty::Visibility; +use rustc::ty::{TyCtxt, Visibility}; use rustc::util::nodemap::FxHashSet; use syntax::symbol::sym; -use std::cell::RefMut; - use crate::clean::{AttributesExt, NestedAttributesExt}; // FIXME: this may not be exhaustive, but is sufficient for rustdocs current uses @@ -14,9 +12,9 @@ use crate::clean::{AttributesExt, NestedAttributesExt}; /// Similar to `librustc_privacy::EmbargoVisitor`, but also takes /// specific rustdoc annotations into account (i.e., `doc(hidden)`) pub struct LibEmbargoVisitor<'a, 'tcx> { - cx: &'a crate::core::DocContext<'tcx>, + tcx: TyCtxt<'tcx>, // Accessibility levels for reachable nodes - access_levels: RefMut<'a, AccessLevels>, + access_levels: &'a mut AccessLevels, // Previous accessibility level, None means unreachable prev_level: Option, // Keeps track of already visited modules, in case a module re-exports its parent @@ -25,13 +23,13 @@ pub struct LibEmbargoVisitor<'a, 'tcx> { impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { pub fn new( - cx: &'a crate::core::DocContext<'tcx> + cx: &'a mut crate::core::DocContext<'tcx> ) -> LibEmbargoVisitor<'a, 'tcx> { LibEmbargoVisitor { - cx, - access_levels: RefMut::map(cx.renderinfo.borrow_mut(), |ri| &mut ri.access_levels), + tcx: cx.tcx, + access_levels: &mut cx.renderinfo.get_mut().access_levels, prev_level: Some(AccessLevel::Public), - visited_mods: FxHashSet::default() + visited_mods: FxHashSet::default(), } } @@ -43,7 +41,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { // Updates node level and returns the updated level fn update(&mut self, did: DefId, level: Option) -> Option { - let is_hidden = self.cx.tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden); + let is_hidden = self.tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden); let old_level = self.access_levels.map.get(&did).cloned(); // Accessibility levels can only grow @@ -60,9 +58,9 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { return; } - for item in self.cx.tcx.item_children(def_id).iter() { + for item in self.tcx.item_children(def_id).iter() { if let Some(def_id) = item.res.opt_def_id() { - if self.cx.tcx.def_key(def_id).parent.map_or(false, |d| d == def_id.index) || + if self.tcx.def_key(def_id).parent.map_or(false, |d| d == def_id.index) || item.vis == Visibility::Public { self.visit_item(item.res); } @@ -72,7 +70,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { fn visit_item(&mut self, res: Res) { let def_id = res.def_id(); - let vis = self.cx.tcx.visibility(def_id); + let vis = self.tcx.visibility(def_id); let inherited_item_level = if vis == Visibility::Public { self.prev_level } else { From 95f5698c10dbf92e444abc5334a3b1333b20cb0f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 12 Aug 2019 07:32:38 -0400 Subject: [PATCH 266/618] Remove dead tracking of external param names --- src/librustdoc/clean/mod.rs | 19 ------------------- src/librustdoc/html/render.rs | 26 -------------------------- 2 files changed, 45 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 62900fa9fb15f..ed82c522779eb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -566,23 +566,6 @@ pub enum ItemEnum { } impl ItemEnum { - pub fn generics(&self) -> Option<&Generics> { - Some(match *self { - ItemEnum::StructItem(ref s) => &s.generics, - ItemEnum::EnumItem(ref e) => &e.generics, - ItemEnum::FunctionItem(ref f) => &f.generics, - ItemEnum::TypedefItem(ref t, _) => &t.generics, - ItemEnum::OpaqueTyItem(ref t, _) => &t.generics, - ItemEnum::TraitItem(ref t) => &t.generics, - ItemEnum::ImplItem(ref i) => &i.generics, - ItemEnum::TyMethodItem(ref i) => &i.generics, - ItemEnum::MethodItem(ref i) => &i.generics, - ItemEnum::ForeignFunctionItem(ref f) => &f.generics, - ItemEnum::TraitAliasItem(ref ta) => &ta.generics, - _ => return None, - }) - } - pub fn is_associated(&self) -> bool { match *self { ItemEnum::TypedefItem(_, _) | @@ -1535,8 +1518,6 @@ impl Clean for ty::GenericParamDef { (self.name.to_string(), GenericParamDefKind::Lifetime) } ty::GenericParamDefKind::Type { has_default, synthetic, .. } => { - cx.renderinfo.borrow_mut().external_param_names - .insert(self.def_id, self.name.clean(cx)); let default = if has_default { Some(cx.tcx.type_of(self.def_id).clean(cx)) } else { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c8921a92d3382..896246126d869 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -282,11 +282,6 @@ impl Impl { /// rendering threads. #[derive(Default)] pub struct Cache { - /// Mapping of typaram ids to the name of the type parameter. This is used - /// when pretty-printing a type (so pretty-printing doesn't have to - /// painfully maintain a context like this) - pub param_names: FxHashMap, - /// Maps a type ID to all known implementations for that type. This is only /// recognized for intra-crate `ResolvedPath` types, and is used to print /// out extra documentation on the page of an enum/struct. @@ -382,7 +377,6 @@ pub struct Cache { pub struct RenderInfo { pub inlined: FxHashSet, pub external_paths: crate::core::ExternalPaths, - pub external_param_names: FxHashMap, pub exact_paths: FxHashMap>, pub access_levels: AccessLevels, pub deref_trait_did: Option, @@ -617,7 +611,6 @@ pub fn run(mut krate: clean::Crate, let RenderInfo { inlined: _, external_paths, - external_param_names, exact_paths, access_levels, deref_trait_did, @@ -651,7 +644,6 @@ pub fn run(mut krate: clean::Crate, deref_mut_trait_did, owned_box_did, masked_crates: mem::take(&mut krate.masked_crates), - param_names: external_param_names, aliases: Default::default(), }; @@ -1419,12 +1411,6 @@ impl DocFolder for Cache { } } - // Register any generics to their corresponding string. This is used - // when pretty-printing types. - if let Some(generics) = item.inner.generics() { - self.generics(generics); - } - // Propagate a trait method's documentation to all implementors of the // trait. if let clean::TraitItem(ref t) = item.inner { @@ -1657,18 +1643,6 @@ impl DocFolder for Cache { } impl Cache { - fn generics(&mut self, generics: &clean::Generics) { - for param in &generics.params { - match param.kind { - clean::GenericParamDefKind::Lifetime => {} - clean::GenericParamDefKind::Type { did, .. } | - clean::GenericParamDefKind::Const { did, .. } => { - self.param_names.insert(did, param.name.clone()); - } - } - } - } - fn add_aliases(&mut self, item: &clean::Item) { if item.def_id.index == CRATE_DEF_INDEX { return From 0e079c2c689b6252154e9df04d067783bfc13224 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 12 Aug 2019 11:18:25 -0400 Subject: [PATCH 267/618] Remove support for printing HRef in alternate mode The alternate mode merely prints out the passed in text which is largely useless (as the text can simply be directly printed). --- src/librustdoc/html/format.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 9c22837bdae87..182a72b6a4d88 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -72,8 +72,8 @@ pub struct WhereClause<'a>{ } pub struct HRef<'a> { - pub did: DefId, - pub text: &'a str, + did: DefId, + text: &'a str, } impl<'a> VisSpace<'a> { @@ -452,7 +452,7 @@ fn resolved_path(w: &mut fmt::Formatter<'_>, did: DefId, path: &clean::Path, } } if w.alternate() { - write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.args)?; + write!(w, "{}{:#}", &last.name, last.args)?; } else { let path = if use_absolute { match href(did) { @@ -538,14 +538,11 @@ impl<'a> HRef<'a> { impl<'a> fmt::Display for HRef<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match href(self.did) { - Some((url, shortty, fqp)) => if !f.alternate() { - write!(f, "{}", - shortty, url, shortty, fqp.join("::"), self.text) - } else { - write!(f, "{}", self.text) - }, - _ => write!(f, "{}", self.text), + if let Some((url, short_ty, fqp)) = href(self.did) { + write!(f, r#"{}"#, + short_ty, url, short_ty, fqp.join("::"), self.text) + } else { + write!(f, "{}", self.text) } } } From 6876f9bcdc94c5e0c8cde03040b428f24f19a051 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Mon, 26 Aug 2019 18:06:24 -0500 Subject: [PATCH 268/618] filter linkcheck spurious failure --- src/tools/rustbook/src/main.rs | 54 ++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 95530b210afd6..0915600bb3875 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -1,18 +1,18 @@ -use clap::{crate_version}; +use clap::crate_version; use std::env; use std::path::{Path, PathBuf}; -use clap::{App, ArgMatches, SubCommand, AppSettings}; +use clap::{App, AppSettings, ArgMatches, SubCommand}; +use mdbook::errors::Result as Result3; use mdbook::MDBook; -use mdbook::errors::{Result as Result3}; +use failure::Error; #[cfg(feature = "linkcheck")] use mdbook::renderer::RenderContext; #[cfg(feature = "linkcheck")] use mdbook_linkcheck::{self, errors::BrokenLinks}; -use failure::Error; fn main() { let d_message = "-d, --dest-dir=[dest-dir] @@ -21,18 +21,22 @@ fn main() { 'A directory for your book{n}(Defaults to Current Directory when omitted)'"; let matches = App::new("rustbook") - .about("Build a book with mdBook") - .author("Steve Klabnik ") - .version(&*format!("v{}", crate_version!())) - .setting(AppSettings::SubcommandRequired) - .subcommand(SubCommand::with_name("build") - .about("Build the book from the markdown files") - .arg_from_usage(d_message) - .arg_from_usage(dir_message)) - .subcommand(SubCommand::with_name("linkcheck") - .about("Run linkcheck with mdBook 3") - .arg_from_usage(dir_message)) - .get_matches(); + .about("Build a book with mdBook") + .author("Steve Klabnik ") + .version(&*format!("v{}", crate_version!())) + .setting(AppSettings::SubcommandRequired) + .subcommand( + SubCommand::with_name("build") + .about("Build the book from the markdown files") + .arg_from_usage(d_message) + .arg_from_usage(dir_message), + ) + .subcommand( + SubCommand::with_name("linkcheck") + .about("Run linkcheck with mdBook 3") + .arg_from_usage(dir_message), + ) + .get_matches(); // Check which subcomamnd the user ran... match matches.subcommand() { @@ -46,23 +50,35 @@ fn main() { ::std::process::exit(101); } - }, + } ("linkcheck", Some(sub_matches)) => { if let Err(err) = linkcheck(sub_matches) { eprintln!("Error: {}", err); + // HACK: ignore timeouts + #[allow(unused_mut)] + let mut actually_broken = false; + #[cfg(feature = "linkcheck")] { if let Ok(broken_links) = err.downcast::() { for cause in broken_links.links().iter() { eprintln!("\tCaused By: {}", cause); + + if cause.contains("timed out") { + actually_broken = true; + } } } } - ::std::process::exit(101); + if actually_broken { + std::process::exit(101); + } else { + std::process::exit(0); + } } - }, + } (_, _) => unreachable!(), }; } From 3307929a849592d8ea36b10f92192e31867f76e3 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 12 Aug 2019 12:53:45 -0400 Subject: [PATCH 269/618] Store only the current depth Previously we stored the entire current path which is a bit expensive and only ever accessed its length. This stores the length directly. --- src/librustdoc/html/format.rs | 12 ++++++------ src/librustdoc/html/render.rs | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 182a72b6a4d88..54c0120e398c3 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -15,7 +15,7 @@ use rustc::hir; use crate::clean::{self, PrimitiveType}; use crate::html::item_type::ItemType; -use crate::html::render::{self, cache, CURRENT_LOCATION_KEY}; +use crate::html::render::{self, cache, CURRENT_DEPTH}; /// Helper to render an optional visibility with a space after it (if the /// visibility is preset) @@ -407,16 +407,16 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec)> { return None } - let loc = CURRENT_LOCATION_KEY.with(|l| l.borrow().clone()); + let depth = CURRENT_DEPTH.with(|l| l.get()); let (fqp, shortty, mut url) = match cache.paths.get(&did) { Some(&(ref fqp, shortty)) => { - (fqp, shortty, "../".repeat(loc.len())) + (fqp, shortty, "../".repeat(depth)) } None => { let &(ref fqp, shortty) = cache.external_paths.get(&did)?; (fqp, shortty, match cache.extern_locations[&did.krate] { (.., render::Remote(ref s)) => s.to_string(), - (.., render::Local) => "../".repeat(loc.len()), + (.., render::Local) => "../".repeat(depth), (.., render::Unknown) => return None, }) } @@ -479,7 +479,7 @@ fn primitive_link(f: &mut fmt::Formatter<'_>, if !f.alternate() { match m.primitive_locations.get(&prim) { Some(&def_id) if def_id.is_local() => { - let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); + let len = CURRENT_DEPTH.with(|s| s.get()); let len = if len == 0 {0} else {len - 1}; write!(f, "", "../".repeat(len), @@ -492,7 +492,7 @@ fn primitive_link(f: &mut fmt::Formatter<'_>, Some((cname, s.to_string())) } (ref cname, _, render::Local) => { - let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); + let len = CURRENT_DEPTH.with(|s| s.get()); Some((cname, "../".repeat(len))) } (.., render::Unknown) => None, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 896246126d869..67084991276b8 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -28,7 +28,7 @@ pub use self::ExternalLocation::*; use std::borrow::Cow; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::cmp::Ordering; use std::collections::{BTreeMap, VecDeque}; use std::default::Default; @@ -479,7 +479,7 @@ impl ToJson for IndexItemFunctionType { } thread_local!(static CACHE_KEY: RefCell> = Default::default()); -thread_local!(pub static CURRENT_LOCATION_KEY: RefCell> = RefCell::new(Vec::new())); +thread_local!(pub static CURRENT_DEPTH: Cell = Cell::new(0)); pub fn initial_ids() -> Vec { [ @@ -695,7 +695,7 @@ pub fn run(mut krate: clean::Crate, // for future parallelization opportunities let cache = Arc::new(cache); CACHE_KEY.with(|v| *v.borrow_mut() = cache.clone()); - CURRENT_LOCATION_KEY.with(|s| s.borrow_mut().clear()); + CURRENT_DEPTH.with(|s| s.set(0)); // Write shared runs within a flock; disable thread dispatching of IO temporarily. Arc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true); @@ -2003,8 +2003,8 @@ impl Context { -> io::Result<()> { // A little unfortunate that this is done like this, but it sure // does make formatting *a lot* nicer. - CURRENT_LOCATION_KEY.with(|slot| { - *slot.borrow_mut() = self.current.clone(); + CURRENT_DEPTH.with(|slot| { + slot.set(self.current.len()); }); let mut title = if it.is_primitive() || it.is_keyword() { From dafdfee33e8e78c3f34dd5befb3581fff0041ebd Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 12 Aug 2019 12:57:48 -0400 Subject: [PATCH 270/618] Inline RawMutableSpace --- src/librustdoc/html/format.rs | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 54c0120e398c3..f232d4ca69ec8 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -36,9 +36,6 @@ pub struct AsyncSpace(pub hir::IsAsync); /// Similar to VisSpace, but used for mutability #[derive(Copy, Clone)] pub struct MutableSpace(pub clean::Mutability); -/// Similar to VisSpace, but used for mutability -#[derive(Copy, Clone)] -pub struct RawMutableSpace(pub clean::Mutability); /// Wrapper struct for emitting type parameter bounds. pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]); /// Wrapper struct for emitting a comma-separated list of items @@ -604,19 +601,22 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> clean::Never => primitive_link(f, PrimitiveType::Never, "!"), clean::CVarArgs => primitive_link(f, PrimitiveType::CVarArgs, "..."), clean::RawPointer(m, ref t) => { + let m = match m { + clean::Immutable => "const", + clean::Mutable => "mut", + }; match **t { clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => { if f.alternate() { primitive_link(f, clean::PrimitiveType::RawPointer, - &format!("*{}{:#}", RawMutableSpace(m), t)) + &format!("*{} {:#}", m, t)) } else { primitive_link(f, clean::PrimitiveType::RawPointer, - &format!("*{}{}", RawMutableSpace(m), t)) + &format!("*{} {}", m, t)) } } _ => { - primitive_link(f, clean::PrimitiveType::RawPointer, - &format!("*{}", RawMutableSpace(m)))?; + primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m))?; fmt::Display::fmt(t, f) } } @@ -1044,15 +1044,6 @@ impl fmt::Display for MutableSpace { } } -impl fmt::Display for RawMutableSpace { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - RawMutableSpace(clean::Immutable) => write!(f, "const "), - RawMutableSpace(clean::Mutable) => write!(f, "mut "), - } - } -} - impl fmt::Display for AbiSpace { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let quot = if f.alternate() { "\"" } else { """ }; From edfd5556f1ddc44a9cf5a53db417330661d47053 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 12 Aug 2019 14:36:09 -0400 Subject: [PATCH 271/618] Transition a few fmt::Display impls to functions This introduces a WithFormatter abstraction that permits one-time fmt::Display on an arbitrary closure, created via `display_fn`. This allows us to prevent allocation while still using functions instead of structs, which are a bit unwieldy to thread arguments through as they can't easily call each other (and are generally a bit opaque). The eventual goal here is likely to move us off of the formatting infrastructure entirely in favor of something more structured, but this is a good step to move us in that direction as it makes, for example, passing a context describing current state to the formatting impl much easier. --- src/librustdoc/html/format.rs | 102 ++++++++++++++++++---------------- src/librustdoc/html/render.rs | 6 +- 2 files changed, 56 insertions(+), 52 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index f232d4ca69ec8..313734e3fdd6b 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -6,6 +6,7 @@ //! them in the future to instead emit any format desired. use std::borrow::Cow; +use std::cell::Cell; use std::fmt; use rustc::hir::def_id::DefId; @@ -38,8 +39,6 @@ pub struct AsyncSpace(pub hir::IsAsync); pub struct MutableSpace(pub clean::Mutability); /// Wrapper struct for emitting type parameter bounds. pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]); -/// Wrapper struct for emitting a comma-separated list of items -pub struct CommaSep<'a, T>(pub &'a [T]); pub struct AbiSpace(pub Abi); pub struct DefaultSpace(pub bool); @@ -68,11 +67,6 @@ pub struct WhereClause<'a>{ pub end_newline: bool, } -pub struct HRef<'a> { - did: DefId, - text: &'a str, -} - impl<'a> VisSpace<'a> { pub fn get(self) -> &'a Option { let VisSpace(v) = self; v @@ -91,14 +85,14 @@ impl ConstnessSpace { } } -impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for (i, item) in self.0.iter().enumerate() { +fn comma_sep(items: &[T]) -> impl fmt::Display + '_ { + display_fn(move |f| { + for (i, item) in items.iter().enumerate() { if i != 0 { write!(f, ", ")?; } fmt::Display::fmt(item, f)?; } Ok(()) - } + }) } impl<'a> fmt::Display for GenericBounds<'a> { @@ -165,9 +159,9 @@ impl fmt::Display for clean::Generics { return Ok(()); } if f.alternate() { - write!(f, "<{:#}>", CommaSep(&real_params)) + write!(f, "<{:#}>", comma_sep(&real_params)) } else { - write!(f, "<{}>", CommaSep(&real_params)) + write!(f, "<{}>", comma_sep(&real_params)) } } } @@ -265,9 +259,9 @@ impl fmt::Display for clean::PolyTrait { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if !self.generic_params.is_empty() { if f.alternate() { - write!(f, "for<{:#}> ", CommaSep(&self.generic_params))?; + write!(f, "for<{:#}> ", comma_sep(&self.generic_params))?; } else { - write!(f, "for<{}> ", CommaSep(&self.generic_params))?; + write!(f, "for<{}> ", comma_sep(&self.generic_params))?; } } if f.alternate() { @@ -452,16 +446,15 @@ fn resolved_path(w: &mut fmt::Formatter<'_>, did: DefId, path: &clean::Path, write!(w, "{}{:#}", &last.name, last.args)?; } else { let path = if use_absolute { - match href(did) { - Some((_, _, fqp)) => { - format!("{}::{}", - fqp[..fqp.len() - 1].join("::"), - HRef::new(did, fqp.last().unwrap())) - } - None => HRef::new(did, &last.name).to_string(), + if let Some((_, _, fqp)) = href(did) { + format!("{}::{}", + fqp[..fqp.len() - 1].join("::"), + anchor(did, fqp.last().unwrap())) + } else { + last.name.to_string() } } else { - HRef::new(did, &last.name).to_string() + anchor(did, &last.name).to_string() }; write!(w, "{}{}", path, last.args)?; } @@ -513,35 +506,30 @@ fn primitive_link(f: &mut fmt::Formatter<'_>, } /// Helper to render type parameters -fn tybounds(w: &mut fmt::Formatter<'_>, - param_names: &Option>) -> fmt::Result { - match *param_names { - Some(ref params) => { - for param in params { - write!(w, " + ")?; - fmt::Display::fmt(param, w)?; +fn tybounds(param_names: &Option>) -> impl fmt::Display + '_ { + display_fn(move |f| { + match *param_names { + Some(ref params) => { + for param in params { + write!(f, " + ")?; + fmt::Display::fmt(param, f)?; + } + Ok(()) } - Ok(()) + None => Ok(()) } - None => Ok(()) - } -} - -impl<'a> HRef<'a> { - pub fn new(did: DefId, text: &'a str) -> HRef<'a> { - HRef { did: did, text: text } - } + }) } -impl<'a> fmt::Display for HRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some((url, short_ty, fqp)) = href(self.did) { +pub fn anchor(did: DefId, text: &str) -> impl fmt::Display + '_ { + display_fn(move |f| { + if let Some((url, short_ty, fqp)) = href(did) { write!(f, r#"{}"#, - short_ty, url, short_ty, fqp.join("::"), self.text) + short_ty, url, short_ty, fqp.join("::"), text) } else { - write!(f, "{}", self.text) + write!(f, "{}", text) } - } + }) } fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> fmt::Result { @@ -555,7 +543,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> } // Paths like `T::Output` and `Self::Output` should be rendered with all segments. resolved_path(f, did, path, is_generic, use_absolute)?; - tybounds(f, param_names) + fmt::Display::fmt(&tybounds(param_names), f) } clean::Infer => write!(f, "_"), clean::Primitive(prim) => primitive_link(f, prim, prim.as_str()), @@ -564,12 +552,12 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> write!(f, "{}{:#}fn{:#}{:#}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi), - CommaSep(&decl.generic_params), + comma_sep(&decl.generic_params), decl.decl) } else { write!(f, "{}{}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi))?; primitive_link(f, PrimitiveType::Fn, "fn")?; - write!(f, "{}{}", CommaSep(&decl.generic_params), decl.decl) + write!(f, "{}{}", comma_sep(&decl.generic_params), decl.decl) } } clean::Tuple(ref typs) => { @@ -583,7 +571,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> } many => { primitive_link(f, PrimitiveType::Tuple, "(")?; - fmt::Display::fmt(&CommaSep(many), f)?; + fmt::Display::fmt(&comma_sep(many), f)?; primitive_link(f, PrimitiveType::Tuple, ")") } } @@ -1063,3 +1051,19 @@ impl fmt::Display for DefaultSpace { } } } + +crate fn display_fn( + f: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, +) -> impl fmt::Display { + WithFormatter(Cell::new(Some(f))) +} + +struct WithFormatter(Cell>); + +impl fmt::Display for WithFormatter + where F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0.take()).unwrap()(f) + } +} diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 67084991276b8..c37c8ef9e6c34 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2644,19 +2644,19 @@ fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context, match myitem.inner { clean::ExternCrateItem(ref name, ref src) => { - use crate::html::format::HRef; + use crate::html::format::anchor; match *src { Some(ref src) => { write!(w, "{}extern crate {} as {};", VisSpace(&myitem.visibility), - HRef::new(myitem.def_id, src), + anchor(myitem.def_id, src), name)? } None => { write!(w, "{}extern crate {};", VisSpace(&myitem.visibility), - HRef::new(myitem.def_id, name))? + anchor(myitem.def_id, name))? } } write!(w, "")?; From b3f01753b0134af903eeeea4c177e2abf1eac26e Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 12 Aug 2019 16:43:26 -0400 Subject: [PATCH 272/618] Inline recurse into only callsite --- src/librustdoc/html/render.rs | 97 +++++++++++++++-------------------- 1 file changed, 40 insertions(+), 57 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c37c8ef9e6c34..faf4f46ca5495 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1885,31 +1885,6 @@ impl Context { "../".repeat(self.current.len()) } - /// Recurse in the directory structure and change the "root path" to make - /// sure it always points to the top (relatively). - fn recurse(&mut self, s: String, f: F) -> T where - F: FnOnce(&mut Context) -> T, - { - if s.is_empty() { - panic!("Unexpected empty destination: {:?}", self.current); - } - let prev = self.dst.clone(); - self.dst.push(&s); - self.current.push(s); - - info!("Recursing into {}", self.dst.display()); - - let ret = f(self); - - info!("Recursed; leaving {}", self.dst.display()); - - // Go back to where we were at - self.dst = prev; - self.current.pop().unwrap(); - - ret - } - /// Main method for rendering a crate. /// /// This currently isn't parallelized, but it'd be pretty easy to add @@ -2090,42 +2065,50 @@ impl Context { // modules are special because they add a namespace. We also need to // recurse into the items of the module as well. let name = item.name.as_ref().unwrap().to_string(); - let mut item = Some(item); - let scx = self.shared.clone(); - self.recurse(name, |this| { - let item = item.take().unwrap(); - - let mut buf = Vec::new(); - this.render_item(&mut buf, &item, false).unwrap(); - // buf will be empty if the module is stripped and there is no redirect for it - if !buf.is_empty() { - this.shared.ensure_dir(&this.dst)?; - let joint_dst = this.dst.join("index.html"); - scx.fs.write(&joint_dst, buf)?; - } + let scx = &self.shared; + if name.is_empty() { + panic!("Unexpected empty destination: {:?}", self.current); + } + let prev = self.dst.clone(); + self.dst.push(&name); + self.current.push(name); - let m = match item.inner { - clean::StrippedItem(box clean::ModuleItem(m)) | - clean::ModuleItem(m) => m, - _ => unreachable!() - }; + info!("Recursing into {}", self.dst.display()); - // Render sidebar-items.js used throughout this module. - if !this.render_redirect_pages { - let items = this.build_sidebar_items(&m); - let js_dst = this.dst.join("sidebar-items.js"); - let mut v = Vec::new(); - try_err!(write!(&mut v, "initSidebarItems({});", - as_json(&items)), &js_dst); - scx.fs.write(&js_dst, &v)?; - } + let mut buf = Vec::new(); + self.render_item(&mut buf, &item, false).unwrap(); + // buf will be empty if the module is stripped and there is no redirect for it + if !buf.is_empty() { + self.shared.ensure_dir(&self.dst)?; + let joint_dst = self.dst.join("index.html"); + scx.fs.write(&joint_dst, buf)?; + } - for item in m.items { - f(this, item); - } + let m = match item.inner { + clean::StrippedItem(box clean::ModuleItem(m)) | + clean::ModuleItem(m) => m, + _ => unreachable!() + }; + + // Render sidebar-items.js used throughout this module. + if !self.render_redirect_pages { + let items = self.build_sidebar_items(&m); + let js_dst = self.dst.join("sidebar-items.js"); + let mut v = Vec::new(); + try_err!(write!(&mut v, "initSidebarItems({});", + as_json(&items)), &js_dst); + scx.fs.write(&js_dst, &v)?; + } + + for item in m.items { + f(self, item); + } + + info!("Recursed; leaving {}", self.dst.display()); - Ok(()) - })?; + // Go back to where we were at + self.dst = prev; + self.current.pop().unwrap(); } else if item.name.is_some() { let mut buf = Vec::new(); self.render_item(&mut buf, &item, true).unwrap(); From b0fab966fad61cac073d1494e0539961e1c442a0 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 12 Aug 2019 16:49:22 -0400 Subject: [PATCH 273/618] Shorten line during rendering instead of in markdown --- src/librustdoc/html/markdown.rs | 20 +---------- src/librustdoc/html/render.rs | 60 +++++++++++++++++++-------------- 2 files changed, 36 insertions(+), 44 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 5a7deb651b00d..74413a7f905d4 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -785,10 +785,6 @@ impl MarkdownSummaryLine<'_> { } pub fn plain_summary_line(md: &str) -> String { - plain_summary_line_full(md, false) -} - -pub fn plain_summary_line_full(md: &str, limit_length: bool) -> String { struct ParserWrapper<'a> { inner: Parser<'a>, is_in: isize, @@ -834,21 +830,7 @@ pub fn plain_summary_line_full(md: &str, limit_length: bool) -> String { s.push_str(&t); } } - if limit_length && s.chars().count() > 60 { - let mut len = 0; - let mut ret = s.split_whitespace() - .take_while(|p| { - // + 1 for the added character after the word. - len += p.chars().count() + 1; - len < 60 - }) - .collect::>() - .join(" "); - ret.push('…'); - ret - } else { - s - } + s } pub fn markdown_links(md: &str) -> Vec<(String, Option>)> { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index faf4f46ca5495..2a4a2fcea5838 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -732,7 +732,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { ty: item.type_(), name: item.name.clone().unwrap(), path: fqp[..fqp.len() - 1].join("::"), - desc: plain_summary_line_short(item.doc_value()), + desc: shorten(plain_summary_line(item.doc_value())), parent: Some(did), parent_idx: None, search_type: get_index_search_type(&item), @@ -770,7 +770,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { } let crate_doc = krate.module.as_ref().map(|module| { - plain_summary_line_short(module.doc_value()) + shorten(plain_summary_line(module.doc_value())) }).unwrap_or(String::new()); let mut crate_data = BTreeMap::new(); @@ -1482,7 +1482,7 @@ impl DocFolder for Cache { ty: item.type_(), name: s.to_string(), path: path.join("::"), - desc: plain_summary_line_short(item.doc_value()), + desc: shorten(plain_summary_line(item.doc_value())), parent, parent_idx: None, search_type: get_index_search_type(&item), @@ -1664,7 +1664,7 @@ impl Cache { ty: item.type_(), name: item_name.to_string(), path: path.clone(), - desc: plain_summary_line_short(item.doc_value()), + desc: shorten(plain_summary_line(item.doc_value())), parent: None, parent_idx: None, search_type: get_index_search_type(&item), @@ -2360,29 +2360,39 @@ fn full_path(cx: &Context, item: &clean::Item) -> String { s } -fn shorter(s: Option<&str>) -> String { - match s { - Some(s) => s.lines() - .skip_while(|s| s.chars().all(|c| c.is_whitespace())) - .take_while(|line|{ - (*line).chars().any(|chr|{ - !chr.is_whitespace() - }) - }).collect::>().join("\n"), - None => String::new() - } -} - #[inline] fn plain_summary_line(s: Option<&str>) -> String { - let line = shorter(s).replace("\n", " "); - markdown::plain_summary_line_full(&line[..], false) -} - -#[inline] -fn plain_summary_line_short(s: Option<&str>) -> String { - let line = shorter(s).replace("\n", " "); - markdown::plain_summary_line_full(&line[..], true) + let s = s.unwrap_or(""); + // This essentially gets the first paragraph of text in one line. + let mut line = s.lines() + .skip_while(|line| line.chars().all(|c| c.is_whitespace())) + .take_while(|line| line.chars().any(|c| !c.is_whitespace())) + .fold(String::new(), |mut acc, line| { + acc.push_str(line); + acc.push(' '); + acc + }); + // remove final whitespace + line.pop(); + markdown::plain_summary_line(&line[..]) +} + +fn shorten(s: String) -> String { + if s.chars().count() > 60 { + let mut len = 0; + let mut ret = s.split_whitespace() + .take_while(|p| { + // + 1 for the added character after the word. + len += p.chars().count() + 1; + len < 60 + }) + .collect::>() + .join(" "); + ret.push('…'); + ret + } else { + s + } } fn document(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item) -> fmt::Result { From 61ff27aa1cc71042a7f3699713d38b1d1ed2b4c5 Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Tue, 27 Aug 2019 10:34:28 +1000 Subject: [PATCH 274/618] debuginfo: always include disambiguator in type names --- .../debuginfo/type_names.rs | 18 ++++++++---------- src/test/debuginfo/generator-objects.rs | 16 ++++++++-------- src/test/debuginfo/issue-57822.rs | 4 ++-- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs index b7c782528de0c..9b5ad94ecd7cb 100644 --- a/src/librustc_codegen_ssa/debuginfo/type_names.rs +++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs @@ -191,18 +191,16 @@ pub fn push_debuginfo_type_name<'tcx>( visited.remove(t); }, ty::Closure(def_id, ..) => { - output.push_str("closure"); - let disambiguator = tcx.def_key(def_id).disambiguated_data.disambiguator; - if disambiguator != 0 { - output.push_str(&format!("-{}", disambiguator)); - } + output.push_str(&format!( + "closure-{}", + tcx.def_key(def_id).disambiguated_data.disambiguator + )); } ty::Generator(def_id, ..) => { - output.push_str("generator"); - let disambiguator = tcx.def_key(def_id).disambiguated_data.disambiguator; - if disambiguator != 0 { - output.push_str(&format!("-{}", disambiguator)); - } + output.push_str(&format!( + "generator-{}", + tcx.def_key(def_id).disambiguated_data.disambiguator + )); } ty::Error | ty::Infer(_) | diff --git a/src/test/debuginfo/generator-objects.rs b/src/test/debuginfo/generator-objects.rs index c6f98e5782b1f..bfa7a05cad057 100644 --- a/src/test/debuginfo/generator-objects.rs +++ b/src/test/debuginfo/generator-objects.rs @@ -10,31 +10,31 @@ // gdb-command:run // gdb-command:print b -// gdb-check:$1 = generator_objects::main::generator {__0: 0x[...], <>: {__state: 0, 0: generator_objects::main::generator::Unresumed, 1: generator_objects::main::generator::Returned, 2: generator_objects::main::generator::Panicked, 3: generator_objects::main::generator::Suspend0 {[...]}, 4: generator_objects::main::generator::Suspend1 {[...]}}} +// gdb-check:$1 = generator_objects::main::generator-0 {__0: 0x[...], <>: {__state: 0, 0: generator_objects::main::generator-0::Unresumed, 1: generator_objects::main::generator-0::Returned, 2: generator_objects::main::generator-0::Panicked, 3: generator_objects::main::generator-0::Suspend0 {[...]}, 4: generator_objects::main::generator-0::Suspend1 {[...]}}} // gdb-command:continue // gdb-command:print b -// gdb-check:$2 = generator_objects::main::generator {__0: 0x[...], <>: {__state: 3, 0: generator_objects::main::generator::Unresumed, 1: generator_objects::main::generator::Returned, 2: generator_objects::main::generator::Panicked, 3: generator_objects::main::generator::Suspend0 {c: 6, d: 7}, 4: generator_objects::main::generator::Suspend1 {[...]}}} +// gdb-check:$2 = generator_objects::main::generator-0 {__0: 0x[...], <>: {__state: 3, 0: generator_objects::main::generator-0::Unresumed, 1: generator_objects::main::generator-0::Returned, 2: generator_objects::main::generator-0::Panicked, 3: generator_objects::main::generator-0::Suspend0 {c: 6, d: 7}, 4: generator_objects::main::generator-0::Suspend1 {[...]}}} // gdb-command:continue // gdb-command:print b -// gdb-check:$3 = generator_objects::main::generator {__0: 0x[...], <>: {__state: 4, 0: generator_objects::main::generator::Unresumed, 1: generator_objects::main::generator::Returned, 2: generator_objects::main::generator::Panicked, 3: generator_objects::main::generator::Suspend0 {[...]}, 4: generator_objects::main::generator::Suspend1 {c: 7, d: 8}}} +// gdb-check:$3 = generator_objects::main::generator-0 {__0: 0x[...], <>: {__state: 4, 0: generator_objects::main::generator-0::Unresumed, 1: generator_objects::main::generator-0::Returned, 2: generator_objects::main::generator-0::Panicked, 3: generator_objects::main::generator-0::Suspend0 {[...]}, 4: generator_objects::main::generator-0::Suspend1 {c: 7, d: 8}}} // gdb-command:continue // gdb-command:print b -// gdb-check:$4 = generator_objects::main::generator {__0: 0x[...], <>: {__state: 1, 0: generator_objects::main::generator::Unresumed, 1: generator_objects::main::generator::Returned, 2: generator_objects::main::generator::Panicked, 3: generator_objects::main::generator::Suspend0 {[...]}, 4: generator_objects::main::generator::Suspend1 {[...]}}} +// gdb-check:$4 = generator_objects::main::generator-0 {__0: 0x[...], <>: {__state: 1, 0: generator_objects::main::generator-0::Unresumed, 1: generator_objects::main::generator-0::Returned, 2: generator_objects::main::generator-0::Panicked, 3: generator_objects::main::generator-0::Suspend0 {[...]}, 4: generator_objects::main::generator-0::Suspend1 {[...]}}} // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:print b -// lldbg-check:(generator_objects::main::generator) $0 = generator(&0x[...]) +// lldbg-check:(generator_objects::main::generator-0) $0 = generator-0(&0x[...]) // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator) $1 = generator(&0x[...]) +// lldbg-check:(generator_objects::main::generator-0) $1 = generator-0(&0x[...]) // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator) $2 = generator(&0x[...]) +// lldbg-check:(generator_objects::main::generator-0) $2 = generator-0(&0x[...]) // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator) $3 = generator(&0x[...]) +// lldbg-check:(generator_objects::main::generator-0) $3 = generator-0(&0x[...]) #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)] #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/issue-57822.rs b/src/test/debuginfo/issue-57822.rs index ba5e8e0f2192a..f18e41db0e6ba 100644 --- a/src/test/debuginfo/issue-57822.rs +++ b/src/test/debuginfo/issue-57822.rs @@ -13,7 +13,7 @@ // gdb-command:run // gdb-command:print g -// gdb-check:$1 = issue_57822::main::closure-1 (issue_57822::main::closure (1)) +// gdb-check:$1 = issue_57822::main::closure-1 (issue_57822::main::closure-0 (1)) // gdb-command:print b // gdb-check:$2 = issue_57822::main::generator-3 {__0: issue_57822::main::generator-2 {__0: 2, <>: {[...]}}, <>: {[...]}} @@ -23,7 +23,7 @@ // lldb-command:run // lldb-command:print g -// lldbg-check:(issue_57822::main::closure-1) $0 = closure-1(closure(1)) +// lldbg-check:(issue_57822::main::closure-1) $0 = closure-1(closure-0(1)) // lldb-command:print b // lldbg-check:(issue_57822::main::generator-3) $1 = generator-3(generator-2(2)) From b2b9b81c9a69ba1bd35e042122b4b132dd6e1e6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 26 Aug 2019 17:46:14 -0700 Subject: [PATCH 275/618] Account for doc comments coming from proc macros without spans --- .../passes/check_code_block_syntax.rs | 2 +- .../passes/collect_intra_doc_links.rs | 4 ++-- src/librustdoc/passes/mod.rs | 21 ++++++++++--------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 357e17d2d1bc4..67aa014a788f2 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { // We couldn't calculate the span of the markdown block that had the error, so our // diagnostics are going to be a bit lacking. let mut diag = self.cx.sess().struct_span_warn( - super::span_of_attrs(&item.attrs), + super::span_of_attrs(&item.attrs).unwrap_or(item.source.span()), "doc comment contains an invalid Rust code block", ); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index c73c46472d804..2951b2ccb2af9 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -465,7 +465,7 @@ fn resolution_failure( } }; let attrs = &item.attrs; - let sp = span_of_attrs(attrs); + let sp = span_of_attrs(attrs).unwrap_or(item.source.span()); let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, @@ -517,7 +517,7 @@ fn ambiguity_error( } }; let attrs = &item.attrs; - let sp = span_of_attrs(attrs); + let sp = span_of_attrs(attrs).unwrap_or(item.source.span()); let mut msg = format!("`{}` is ", path_str); diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 641a6df221446..49a34c7e46281 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -339,7 +339,7 @@ pub fn look_for_tests<'tcx>( find_testable_code(&dox, &mut tests, ErrorCodes::No); if check_missing_code == true && tests.found_tests == 0 { - let sp = span_of_attrs(&item.attrs).substitute_dummy(item.source.span()); + let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span()); let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::MISSING_DOC_CODE_EXAMPLES, hir_id, @@ -352,20 +352,23 @@ pub fn look_for_tests<'tcx>( let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::PRIVATE_DOC_TESTS, hir_id, - span_of_attrs(&item.attrs), + span_of_attrs(&item.attrs).unwrap_or(item.source.span()), "Documentation test in private item"); diag.emit(); } } /// Returns a span encompassing all the given attributes. -crate fn span_of_attrs(attrs: &clean::Attributes) -> Span { +crate fn span_of_attrs(attrs: &clean::Attributes) -> Option { if attrs.doc_strings.is_empty() { - return DUMMY_SP; + return None; } let start = attrs.doc_strings[0].span(); + if start == DUMMY_SP { + return None; + } let end = attrs.doc_strings.last().expect("No doc strings provided").span(); - start.to(end) + Some(start.to(end)) } /// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code. @@ -391,7 +394,7 @@ crate fn source_span_for_markdown_range( let snippet = cx .sess() .source_map() - .span_to_snippet(span_of_attrs(attrs)) + .span_to_snippet(span_of_attrs(attrs)?) .ok()?; let starting_line = markdown[..md_range.start].matches('\n').count(); @@ -441,10 +444,8 @@ crate fn source_span_for_markdown_range( } } - let sp = span_of_attrs(attrs).from_inner(InnerSpan::new( + Some(span_of_attrs(attrs)?.from_inner(InnerSpan::new( md_range.start + start_bytes, md_range.end + start_bytes + end_bytes, - )); - - Some(sp) + ))) } From 7ed542da7815070b4fc7aa87d53e5b97aa2e8828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 26 Aug 2019 21:12:59 -0700 Subject: [PATCH 276/618] add regression test --- .../auxiliary/through-proc-macro-aux.rs | 20 +++++++++++++++++++ src/test/rustdoc/through-proc-macro.rs | 12 +++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/test/rustdoc/auxiliary/through-proc-macro-aux.rs create mode 100644 src/test/rustdoc/through-proc-macro.rs diff --git a/src/test/rustdoc/auxiliary/through-proc-macro-aux.rs b/src/test/rustdoc/auxiliary/through-proc-macro-aux.rs new file mode 100644 index 0000000000000..5c4a01ee3a74a --- /dev/null +++ b/src/test/rustdoc/auxiliary/through-proc-macro-aux.rs @@ -0,0 +1,20 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] +#![crate_name="some_macros"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn first(_attr: TokenStream, item: TokenStream) -> TokenStream { + item // This doesn't erase the spans. +} + +#[proc_macro_attribute] +pub fn second(_attr: TokenStream, item: TokenStream) -> TokenStream { + // Make a new `TokenStream` to erase the spans: + let mut out: TokenStream = TokenStream::new(); + out.extend(item); + out +} diff --git a/src/test/rustdoc/through-proc-macro.rs b/src/test/rustdoc/through-proc-macro.rs new file mode 100644 index 0000000000000..348c9eea2dcbf --- /dev/null +++ b/src/test/rustdoc/through-proc-macro.rs @@ -0,0 +1,12 @@ +// aux-build:through-proc-macro-aux.rs +// build-aux-docs +#![warn(intra_doc_link_resolution_failure)] +extern crate some_macros; + +#[some_macros::second] +pub enum Boom { + /// [Oooops] + Bam, +} + +fn main() {} From 5cc1559c600f34f534fa3e0328ca1c2659562229 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 27 Aug 2019 10:14:07 +0200 Subject: [PATCH 277/618] token: refactor with is_non_raw_ident_where. --- src/libsyntax/parse/token.rs | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 1865f925165bd..dfea34c331ad4 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -409,7 +409,7 @@ impl Token { crate fn expect_lit(&self) -> Lit { match self.kind { Literal(lit) => lit, - _=> panic!("`expect_lit` called on non-literal"), + _ => panic!("`expect_lit` called on non-literal"), } } @@ -457,6 +457,7 @@ impl Token { pub fn is_ident(&self) -> bool { self.ident().is_some() } + /// Returns `true` if the token is a lifetime. crate fn is_lifetime(&self) -> bool { self.lifetime().is_some() @@ -508,45 +509,38 @@ impl Token { /// Returns `true` if the token is a given keyword, `kw`. pub fn is_keyword(&self, kw: Symbol) -> bool { - self.ident().map(|(id, is_raw)| id.name == kw && !is_raw).unwrap_or(false) + self.is_non_raw_ident_where(|id| id.name == kw) } crate fn is_path_segment_keyword(&self) -> bool { - match self.ident() { - Some((id, false)) => id.is_path_segment_keyword(), - _ => false, - } + self.is_non_raw_ident_where(ast::Ident::is_path_segment_keyword) } // Returns true for reserved identifiers used internally for elided lifetimes, // unnamed method parameters, crate root module, error recovery etc. crate fn is_special_ident(&self) -> bool { - match self.ident() { - Some((id, false)) => id.is_special(), - _ => false, - } + self.is_non_raw_ident_where(ast::Ident::is_special) } /// Returns `true` if the token is a keyword used in the language. crate fn is_used_keyword(&self) -> bool { - match self.ident() { - Some((id, false)) => id.is_used_keyword(), - _ => false, - } + self.is_non_raw_ident_where(ast::Ident::is_used_keyword) } /// Returns `true` if the token is a keyword reserved for possible future use. crate fn is_unused_keyword(&self) -> bool { - match self.ident() { - Some((id, false)) => id.is_unused_keyword(), - _ => false, - } + self.is_non_raw_ident_where(ast::Ident::is_unused_keyword) } /// Returns `true` if the token is either a special identifier or a keyword. pub fn is_reserved_ident(&self) -> bool { + self.is_non_raw_ident_where(ast::Ident::is_reserved) + } + + /// Returns `true` if the token is a non-raw identifier for which `pred` holds. + fn is_non_raw_ident_where(&self, pred: impl FnOnce(ast::Ident) -> bool) -> bool { match self.ident() { - Some((id, false)) => id.is_reserved(), + Some((id, false)) => pred(id), _ => false, } } From e49b9581baba9d89519d17ac0d8400b6ae77e754 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 27 Aug 2019 10:21:41 +0200 Subject: [PATCH 278/618] Simplify with Symbol/Token::is_book_lit. --- src/libsyntax/parse/literal.rs | 4 ++-- src/libsyntax/parse/parser/path.rs | 2 +- src/libsyntax/parse/token.rs | 11 +++++++---- src/libsyntax_pos/symbol.rs | 5 +++++ 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index 6409acba573ad..36233de3cfb57 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -104,7 +104,7 @@ impl LitKind { Ok(match kind { token::Bool => { - assert!(symbol == kw::True || symbol == kw::False); + assert!(symbol.is_bool_lit()); LitKind::Bool(symbol == kw::True) } token::Byte => return unescape_byte(&symbol.as_str()) @@ -261,7 +261,7 @@ impl Lit { /// Converts arbitrary token into an AST literal. crate fn from_token(token: &Token) -> Result { let lit = match token.kind { - token::Ident(name, false) if name == kw::True || name == kw::False => + token::Ident(name, false) if name.is_bool_lit() => token::Lit::new(token::Bool, name, None), token::Literal(lit) => lit, diff --git a/src/libsyntax/parse/parser/path.rs b/src/libsyntax/parse/parser/path.rs index 3eb4d45045a9e..d4b13cc2e0121 100644 --- a/src/libsyntax/parse/parser/path.rs +++ b/src/libsyntax/parse/parser/path.rs @@ -423,7 +423,7 @@ impl<'a> Parser<'a> { // FIXME(const_generics): to distinguish between idents for types and consts, // we should introduce a GenericArg::Ident in the AST and distinguish when // lowering to the HIR. For now, idents for const args are not permitted. - if self.token.is_keyword(kw::True) || self.token.is_keyword(kw::False) { + if self.token.is_bool_lit() { self.parse_literal_maybe_minus()? } else { return Err( diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index dfea34c331ad4..fe3b51aa246b8 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -417,10 +417,8 @@ impl Token { /// for example a '-42', or one of the boolean idents). crate fn can_begin_literal_or_bool(&self) -> bool { match self.kind { - Literal(..) => true, - BinOp(Minus) => true, - Ident(name, false) if name == kw::True => true, - Ident(name, false) if name == kw::False => true, + Literal(..) | BinOp(Minus) => true, + Ident(name, false) if name.is_bool_lit() => true, Interpolated(ref nt) => match **nt { NtLiteral(..) => true, _ => false, @@ -537,6 +535,11 @@ impl Token { self.is_non_raw_ident_where(ast::Ident::is_reserved) } + /// Returns `true` if the token is the identifier `true` or `false`. + crate fn is_bool_lit(&self) -> bool { + self.is_non_raw_ident_where(|id| id.name.is_bool_lit()) + } + /// Returns `true` if the token is a non-raw identifier for which `pred` holds. fn is_non_raw_ident_where(&self, pred: impl FnOnce(ast::Ident) -> bool) -> bool { match self.ident() { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 0b8f16bbc3b99..856857f74e352 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1063,6 +1063,11 @@ impl Symbol { self == kw::DollarCrate } + /// Returns `true` if the symbol is `true` or `false`. + pub fn is_bool_lit(self) -> bool { + self == kw::True || self == kw::False + } + /// This symbol can be a raw identifier. pub fn can_be_raw(self) -> bool { self != kw::Invalid && self != kw::Underscore && !self.is_path_segment_keyword() From f908aa9e8000dd7fd2c3de54fe1d914fddf4fe92 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 27 Aug 2019 13:04:48 +0200 Subject: [PATCH 279/618] recover on 'mut ' and improve recovery for keywords. --- src/libsyntax/parse/parser/pat.rs | 136 ++++++++++++++---- .../keyword-extern-as-identifier-pat.rs | 2 +- .../keyword-extern-as-identifier-pat.stderr | 8 +- src/test/ui/parser/issue-32501.rs | 3 +- src/test/ui/parser/issue-32501.stderr | 6 +- src/test/ui/parser/keyword-abstract.rs | 2 +- src/test/ui/parser/keyword-abstract.stderr | 8 +- .../ui/parser/keyword-as-as-identifier.rs | 2 +- .../ui/parser/keyword-as-as-identifier.stderr | 8 +- .../ui/parser/keyword-break-as-identifier.rs | 2 +- .../parser/keyword-break-as-identifier.stderr | 8 +- .../ui/parser/keyword-const-as-identifier.rs | 2 +- .../parser/keyword-const-as-identifier.stderr | 8 +- .../parser/keyword-continue-as-identifier.rs | 2 +- .../keyword-continue-as-identifier.stderr | 8 +- .../ui/parser/keyword-else-as-identifier.rs | 2 +- .../parser/keyword-else-as-identifier.stderr | 8 +- .../ui/parser/keyword-enum-as-identifier.rs | 2 +- .../parser/keyword-enum-as-identifier.stderr | 8 +- src/test/ui/parser/keyword-final.rs | 2 +- src/test/ui/parser/keyword-final.stderr | 8 +- .../ui/parser/keyword-fn-as-identifier.rs | 2 +- .../ui/parser/keyword-fn-as-identifier.stderr | 8 +- .../ui/parser/keyword-for-as-identifier.rs | 2 +- .../parser/keyword-for-as-identifier.stderr | 8 +- .../ui/parser/keyword-if-as-identifier.rs | 2 +- .../ui/parser/keyword-if-as-identifier.stderr | 8 +- .../ui/parser/keyword-impl-as-identifier.rs | 2 +- .../parser/keyword-impl-as-identifier.stderr | 8 +- .../ui/parser/keyword-let-as-identifier.rs | 2 +- .../parser/keyword-let-as-identifier.stderr | 8 +- .../ui/parser/keyword-loop-as-identifier.rs | 2 +- .../parser/keyword-loop-as-identifier.stderr | 8 +- .../ui/parser/keyword-match-as-identifier.rs | 2 +- .../parser/keyword-match-as-identifier.stderr | 8 +- .../ui/parser/keyword-mod-as-identifier.rs | 2 +- .../parser/keyword-mod-as-identifier.stderr | 8 +- .../ui/parser/keyword-move-as-identifier.rs | 2 +- .../parser/keyword-move-as-identifier.stderr | 8 +- src/test/ui/parser/keyword-override.rs | 2 +- src/test/ui/parser/keyword-override.stderr | 8 +- .../ui/parser/keyword-pub-as-identifier.rs | 2 +- .../parser/keyword-pub-as-identifier.stderr | 8 +- .../ui/parser/keyword-return-as-identifier.rs | 2 +- .../keyword-return-as-identifier.stderr | 8 +- .../ui/parser/keyword-static-as-identifier.rs | 2 +- .../keyword-static-as-identifier.stderr | 8 +- .../ui/parser/keyword-struct-as-identifier.rs | 2 +- .../keyword-struct-as-identifier.stderr | 8 +- .../ui/parser/keyword-trait-as-identifier.rs | 2 +- .../parser/keyword-trait-as-identifier.stderr | 8 +- .../keyword-try-as-identifier-edition2018.rs | 2 +- ...yword-try-as-identifier-edition2018.stderr | 8 +- .../ui/parser/keyword-type-as-identifier.rs | 2 +- .../parser/keyword-type-as-identifier.stderr | 8 +- src/test/ui/parser/keyword-typeof.rs | 2 +- src/test/ui/parser/keyword-typeof.stderr | 8 +- .../ui/parser/keyword-unsafe-as-identifier.rs | 2 +- .../keyword-unsafe-as-identifier.stderr | 8 +- .../ui/parser/keyword-use-as-identifier.rs | 2 +- .../parser/keyword-use-as-identifier.stderr | 8 +- .../ui/parser/keyword-where-as-identifier.rs | 2 +- .../parser/keyword-where-as-identifier.stderr | 8 +- .../ui/parser/keyword-while-as-identifier.rs | 2 +- .../parser/keyword-while-as-identifier.stderr | 8 +- src/test/ui/parser/mut-patterns.rs | 30 +++- src/test/ui/parser/mut-patterns.stderr | 68 ++++++++- src/test/ui/reserved/reserved-become.rs | 2 +- src/test/ui/reserved/reserved-become.stderr | 8 +- src/test/ui/self/self_type_keyword.rs | 3 +- src/test/ui/self/self_type_keyword.stderr | 30 ++-- 71 files changed, 449 insertions(+), 147 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 78c9a289b3702..7b228a700a748 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -4,6 +4,7 @@ use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use crate::ptr::P; use crate::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac}; use crate::ast::{BindingMode, Ident, Mutability, Path, QSelf, Expr, ExprKind}; +use crate::mut_visit::{noop_visit_pat, MutVisitor}; use crate::parse::token::{self}; use crate::print::pprust; use crate::source_map::{respan, Span, Spanned}; @@ -273,7 +274,7 @@ impl<'a> Parser<'a> { // Parse _ PatKind::Wild } else if self.eat_keyword(kw::Mut) { - self.recover_pat_ident_mut_first()? + self.parse_pat_ident_mut()? } else if self.eat_keyword(kw::Ref) { // Parse ref ident @ pat / ref mut ident @ pat let mutbl = self.parse_mutability(); @@ -281,13 +282,12 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Box) { // Parse `box pat` PatKind::Box(self.parse_pat_with_range_pat(false, None)?) - } else if self.token.is_ident() && !self.token.is_reserved_ident() && - self.parse_as_ident() { + } else if self.can_be_ident_pat() { // Parse `ident @ pat` // This can give false positives and parse nullary enums, // they are dealt with later in resolve. self.parse_pat_ident(BindingMode::ByValue(Mutability::Immutable))? - } else if self.token.is_path_start() { + } else if self.is_start_of_pat_with_path() { // Parse pattern starting with a path let (qself, path) = if self.eat_lt() { // Parse a qualified path @@ -384,24 +384,85 @@ impl<'a> Parser<'a> { }) } + fn parse_pat_ident_mut(&mut self) -> PResult<'a, PatKind> { + let mut_span = self.prev_span; + + if self.eat_keyword(kw::Ref) { + return self.recover_mut_ref_ident(mut_span) + } + + self.recover_additional_muts(); + + let mut pat = self.parse_pat(Some("identifier"))?; + + // Add `mut` to any binding in the parsed pattern. + struct AddMut; + impl MutVisitor for AddMut { + fn visit_pat(&mut self, pat: &mut P) { + if let PatKind::Ident(BindingMode::ByValue(ref mut m), ..) = pat.node { + *m = Mutability::Mutable; + } + noop_visit_pat(pat, self); + } + } + AddMut.visit_pat(&mut pat); + + // Unwrap; If we don't have `mut $ident`, error. + let pat = pat.into_inner(); + match &pat.node { + PatKind::Ident(..) => {} + _ => self.ban_mut_general_pat(mut_span, &pat), + } + + Ok(pat.node) + } + /// Recover on `mut ref? ident @ pat` and suggest /// that the order of `mut` and `ref` is incorrect. - fn recover_pat_ident_mut_first(&mut self) -> PResult<'a, PatKind> { - let mutref_span = self.prev_span.to(self.token.span); - let binding_mode = if self.eat_keyword(kw::Ref) { - self.struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect") - .span_suggestion( - mutref_span, - "try switching the order", - "ref mut".into(), - Applicability::MachineApplicable - ) - .emit(); - BindingMode::ByRef(Mutability::Mutable) - } else { - BindingMode::ByValue(Mutability::Mutable) - }; - self.parse_pat_ident(binding_mode) + fn recover_mut_ref_ident(&mut self, lo: Span) -> PResult<'a, PatKind> { + let mutref_span = lo.to(self.prev_span); + self.struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect") + .span_suggestion( + mutref_span, + "try switching the order", + "ref mut".into(), + Applicability::MachineApplicable + ) + .emit(); + + self.parse_pat_ident(BindingMode::ByRef(Mutability::Mutable)) + } + + /// Error on `mut $pat` where `$pat` is not an ident. + fn ban_mut_general_pat(&self, lo: Span, pat: &Pat) { + let span = lo.to(pat.span); + self.struct_span_err(span, "`mut` must be attached to each individual binding") + .span_suggestion( + span, + "add `mut` to each binding", + pprust::pat_to_string(&pat), + Applicability::MachineApplicable, + ) + .emit(); + } + + /// Eat any extraneous `mut`s and error + recover if we ate any. + fn recover_additional_muts(&mut self) { + let lo = self.token.span; + while self.eat_keyword(kw::Mut) {} + if lo == self.token.span { + return; + } + + let span = lo.to(self.prev_span); + self.struct_span_err(span, "`mut` on a binding may not be repeated") + .span_suggestion( + span, + "remove the additional `mut`s", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); } /// Parse macro invocation @@ -479,17 +540,6 @@ impl<'a> Parser<'a> { Err(err) } - // Helper function to decide whether to parse as ident binding - // or to try to do something more complex like range patterns. - fn parse_as_ident(&mut self) -> bool { - self.look_ahead(1, |t| match t.kind { - token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) | - token::DotDotDot | token::DotDotEq | token::DotDot | - token::ModSep | token::Not => false, - _ => true, - }) - } - /// Is the current token suitable as the start of a range patterns end? fn is_pat_range_end_start(&self) -> bool { self.token.is_path_start() // e.g. `MY_CONST`; @@ -563,6 +613,30 @@ impl<'a> Parser<'a> { } } + /// Is this the start of a pattern beginning with a path? + fn is_start_of_pat_with_path(&mut self) -> bool { + self.check_path() + // Just for recovery (see `can_be_ident`). + || self.token.is_ident() && !self.token.is_bool_lit() && !self.token.is_keyword(kw::In) + } + + /// Would `parse_pat_ident` be appropriate here? + fn can_be_ident_pat(&mut self) -> bool { + self.check_ident() + && !self.token.is_bool_lit() // Avoid `true` or `false` as a binding as it is a literal. + && !self.token.is_path_segment_keyword() // Avoid e.g. `Self` as it is a path. + // Avoid `in`. Due to recovery in the list parser this messes with `for ( $pat in $expr )`. + && !self.token.is_keyword(kw::In) + && self.look_ahead(1, |t| match t.kind { // Try to do something more complex? + token::OpenDelim(token::Paren) // A tuple struct pattern. + | token::OpenDelim(token::Brace) // A struct pattern. + | token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern. + | token::ModSep // A tuple / struct variant pattern. + | token::Not => false, // A macro expanding to a pattern. + _ => true, + }) + } + /// Parses `ident` or `ident @ pat`. /// Used by the copy foo and ref foo patterns to give a good /// error message when parsing mistakes like `ref foo(a, b)`. diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs index f9b6bad7c2552..8a420f7203cac 100644 --- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs +++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs @@ -1,3 +1,3 @@ fn main() { - let extern = 0; //~ ERROR expected pattern, found keyword `extern` + let extern = 0; //~ ERROR expected identifier, found keyword `extern` } diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr index d7b9ad2abe97a..73ac113f1b1e0 100644 --- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr +++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `extern` +error: expected identifier, found keyword `extern` --> $DIR/keyword-extern-as-identifier-pat.rs:2:9 | LL | let extern = 0; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#extern = 0; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-32501.rs b/src/test/ui/parser/issue-32501.rs index 9c01a5c6d20e3..695baf8187276 100644 --- a/src/test/ui/parser/issue-32501.rs +++ b/src/test/ui/parser/issue-32501.rs @@ -4,5 +4,6 @@ fn main() { let _ = 0; let mut b = 0; let mut _b = 0; - let mut _ = 0; //~ ERROR expected identifier, found reserved identifier `_` + let mut _ = 0; + //~^ ERROR `mut` must be attached to each individual binding } diff --git a/src/test/ui/parser/issue-32501.stderr b/src/test/ui/parser/issue-32501.stderr index 97efb89593579..f5d3300cf9c56 100644 --- a/src/test/ui/parser/issue-32501.stderr +++ b/src/test/ui/parser/issue-32501.stderr @@ -1,8 +1,8 @@ -error: expected identifier, found reserved identifier `_` - --> $DIR/issue-32501.rs:7:13 +error: `mut` must be attached to each individual binding + --> $DIR/issue-32501.rs:7:9 | LL | let mut _ = 0; - | ^ expected identifier, found reserved identifier + | ^^^^^ help: add `mut` to each binding: `_` error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-abstract.rs b/src/test/ui/parser/keyword-abstract.rs index 890802ac134a0..570206575ab07 100644 --- a/src/test/ui/parser/keyword-abstract.rs +++ b/src/test/ui/parser/keyword-abstract.rs @@ -1,3 +1,3 @@ fn main() { - let abstract = (); //~ ERROR expected pattern, found reserved keyword `abstract` + let abstract = (); //~ ERROR expected identifier, found reserved keyword `abstract` } diff --git a/src/test/ui/parser/keyword-abstract.stderr b/src/test/ui/parser/keyword-abstract.stderr index 2c79598a81b18..eb2c810099e16 100644 --- a/src/test/ui/parser/keyword-abstract.stderr +++ b/src/test/ui/parser/keyword-abstract.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `abstract` +error: expected identifier, found reserved keyword `abstract` --> $DIR/keyword-abstract.rs:2:9 | LL | let abstract = (); - | ^^^^^^^^ expected pattern + | ^^^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#abstract = (); + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-as-as-identifier.rs b/src/test/ui/parser/keyword-as-as-identifier.rs index 23ff259db3048..cd47c8a3907d9 100644 --- a/src/test/ui/parser/keyword-as-as-identifier.rs +++ b/src/test/ui/parser/keyword-as-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py as' fn main() { - let as = "foo"; //~ error: expected pattern, found keyword `as` + let as = "foo"; //~ error: expected identifier, found keyword `as` } diff --git a/src/test/ui/parser/keyword-as-as-identifier.stderr b/src/test/ui/parser/keyword-as-as-identifier.stderr index ef466488ad061..5648652be9bca 100644 --- a/src/test/ui/parser/keyword-as-as-identifier.stderr +++ b/src/test/ui/parser/keyword-as-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `as` +error: expected identifier, found keyword `as` --> $DIR/keyword-as-as-identifier.rs:4:9 | LL | let as = "foo"; - | ^^ expected pattern + | ^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#as = "foo"; + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-break-as-identifier.rs b/src/test/ui/parser/keyword-break-as-identifier.rs index 5ee111d38c9c3..04b25a7aaf613 100644 --- a/src/test/ui/parser/keyword-break-as-identifier.rs +++ b/src/test/ui/parser/keyword-break-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py break' fn main() { - let break = "foo"; //~ error: expected pattern, found keyword `break` + let break = "foo"; //~ error: expected identifier, found keyword `break` } diff --git a/src/test/ui/parser/keyword-break-as-identifier.stderr b/src/test/ui/parser/keyword-break-as-identifier.stderr index 690bd84221a94..820193db70b0f 100644 --- a/src/test/ui/parser/keyword-break-as-identifier.stderr +++ b/src/test/ui/parser/keyword-break-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `break` +error: expected identifier, found keyword `break` --> $DIR/keyword-break-as-identifier.rs:4:9 | LL | let break = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#break = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-const-as-identifier.rs b/src/test/ui/parser/keyword-const-as-identifier.rs index 48fc142cf64b1..6a2d926bf5796 100644 --- a/src/test/ui/parser/keyword-const-as-identifier.rs +++ b/src/test/ui/parser/keyword-const-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py const' fn main() { - let const = "foo"; //~ error: expected pattern, found keyword `const` + let const = "foo"; //~ error: expected identifier, found keyword `const` } diff --git a/src/test/ui/parser/keyword-const-as-identifier.stderr b/src/test/ui/parser/keyword-const-as-identifier.stderr index 6da47f88d04e3..95b536c99c75a 100644 --- a/src/test/ui/parser/keyword-const-as-identifier.stderr +++ b/src/test/ui/parser/keyword-const-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `const` +error: expected identifier, found keyword `const` --> $DIR/keyword-const-as-identifier.rs:4:9 | LL | let const = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#const = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-continue-as-identifier.rs b/src/test/ui/parser/keyword-continue-as-identifier.rs index 06315a48349ff..cfdd62a2d1bce 100644 --- a/src/test/ui/parser/keyword-continue-as-identifier.rs +++ b/src/test/ui/parser/keyword-continue-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py continue' fn main() { - let continue = "foo"; //~ error: expected pattern, found keyword `continue` + let continue = "foo"; //~ error: expected identifier, found keyword `continue` } diff --git a/src/test/ui/parser/keyword-continue-as-identifier.stderr b/src/test/ui/parser/keyword-continue-as-identifier.stderr index 4b0a659f9ad7e..6b24422a5557e 100644 --- a/src/test/ui/parser/keyword-continue-as-identifier.stderr +++ b/src/test/ui/parser/keyword-continue-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `continue` +error: expected identifier, found keyword `continue` --> $DIR/keyword-continue-as-identifier.rs:4:9 | LL | let continue = "foo"; - | ^^^^^^^^ expected pattern + | ^^^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#continue = "foo"; + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-else-as-identifier.rs b/src/test/ui/parser/keyword-else-as-identifier.rs index 0c69105cf9457..f12dac3ff75eb 100644 --- a/src/test/ui/parser/keyword-else-as-identifier.rs +++ b/src/test/ui/parser/keyword-else-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py else' fn main() { - let else = "foo"; //~ error: expected pattern, found keyword `else` + let else = "foo"; //~ error: expected identifier, found keyword `else` } diff --git a/src/test/ui/parser/keyword-else-as-identifier.stderr b/src/test/ui/parser/keyword-else-as-identifier.stderr index bec7b7ba01e12..f28635cd08cd6 100644 --- a/src/test/ui/parser/keyword-else-as-identifier.stderr +++ b/src/test/ui/parser/keyword-else-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `else` +error: expected identifier, found keyword `else` --> $DIR/keyword-else-as-identifier.rs:4:9 | LL | let else = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#else = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-enum-as-identifier.rs b/src/test/ui/parser/keyword-enum-as-identifier.rs index d1675800a2791..fe66230d02830 100644 --- a/src/test/ui/parser/keyword-enum-as-identifier.rs +++ b/src/test/ui/parser/keyword-enum-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py enum' fn main() { - let enum = "foo"; //~ error: expected pattern, found keyword `enum` + let enum = "foo"; //~ error: expected identifier, found keyword `enum` } diff --git a/src/test/ui/parser/keyword-enum-as-identifier.stderr b/src/test/ui/parser/keyword-enum-as-identifier.stderr index 51a834f797c32..fc54dce1b68f4 100644 --- a/src/test/ui/parser/keyword-enum-as-identifier.stderr +++ b/src/test/ui/parser/keyword-enum-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `enum` +error: expected identifier, found keyword `enum` --> $DIR/keyword-enum-as-identifier.rs:4:9 | LL | let enum = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#enum = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-final.rs b/src/test/ui/parser/keyword-final.rs index e1cecd0e8e07a..a79a11032a018 100644 --- a/src/test/ui/parser/keyword-final.rs +++ b/src/test/ui/parser/keyword-final.rs @@ -1,3 +1,3 @@ fn main() { - let final = (); //~ ERROR expected pattern, found reserved keyword `final` + let final = (); //~ ERROR expected identifier, found reserved keyword `final` } diff --git a/src/test/ui/parser/keyword-final.stderr b/src/test/ui/parser/keyword-final.stderr index e8372643be6b7..291710d05cbfd 100644 --- a/src/test/ui/parser/keyword-final.stderr +++ b/src/test/ui/parser/keyword-final.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `final` +error: expected identifier, found reserved keyword `final` --> $DIR/keyword-final.rs:2:9 | LL | let final = (); - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#final = (); + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-fn-as-identifier.rs b/src/test/ui/parser/keyword-fn-as-identifier.rs index bca2d5996a54b..f30e115f7947e 100644 --- a/src/test/ui/parser/keyword-fn-as-identifier.rs +++ b/src/test/ui/parser/keyword-fn-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py fn' fn main() { - let fn = "foo"; //~ error: expected pattern, found keyword `fn` + let fn = "foo"; //~ error: expected identifier, found keyword `fn` } diff --git a/src/test/ui/parser/keyword-fn-as-identifier.stderr b/src/test/ui/parser/keyword-fn-as-identifier.stderr index a071a40a70e0d..692f195b2888d 100644 --- a/src/test/ui/parser/keyword-fn-as-identifier.stderr +++ b/src/test/ui/parser/keyword-fn-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `fn` +error: expected identifier, found keyword `fn` --> $DIR/keyword-fn-as-identifier.rs:4:9 | LL | let fn = "foo"; - | ^^ expected pattern + | ^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#fn = "foo"; + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-for-as-identifier.rs b/src/test/ui/parser/keyword-for-as-identifier.rs index ce49fd90d9101..9e8a2ad53420c 100644 --- a/src/test/ui/parser/keyword-for-as-identifier.rs +++ b/src/test/ui/parser/keyword-for-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py for' fn main() { - let for = "foo"; //~ error: expected pattern, found keyword `for` + let for = "foo"; //~ error: expected identifier, found keyword `for` } diff --git a/src/test/ui/parser/keyword-for-as-identifier.stderr b/src/test/ui/parser/keyword-for-as-identifier.stderr index 090046cebdc56..bcaf421286e76 100644 --- a/src/test/ui/parser/keyword-for-as-identifier.stderr +++ b/src/test/ui/parser/keyword-for-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `for` +error: expected identifier, found keyword `for` --> $DIR/keyword-for-as-identifier.rs:4:9 | LL | let for = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#for = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-if-as-identifier.rs b/src/test/ui/parser/keyword-if-as-identifier.rs index a1302970689c4..0bd5756afce7f 100644 --- a/src/test/ui/parser/keyword-if-as-identifier.rs +++ b/src/test/ui/parser/keyword-if-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py if' fn main() { - let if = "foo"; //~ error: expected pattern, found keyword `if` + let if = "foo"; //~ error: expected identifier, found keyword `if` } diff --git a/src/test/ui/parser/keyword-if-as-identifier.stderr b/src/test/ui/parser/keyword-if-as-identifier.stderr index 98bfdb46e9770..43fbcd7148a1d 100644 --- a/src/test/ui/parser/keyword-if-as-identifier.stderr +++ b/src/test/ui/parser/keyword-if-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `if` +error: expected identifier, found keyword `if` --> $DIR/keyword-if-as-identifier.rs:4:9 | LL | let if = "foo"; - | ^^ expected pattern + | ^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#if = "foo"; + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-impl-as-identifier.rs b/src/test/ui/parser/keyword-impl-as-identifier.rs index 95a34483ad21a..df529bae07214 100644 --- a/src/test/ui/parser/keyword-impl-as-identifier.rs +++ b/src/test/ui/parser/keyword-impl-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py impl' fn main() { - let impl = "foo"; //~ error: expected pattern, found keyword `impl` + let impl = "foo"; //~ error: expected identifier, found keyword `impl` } diff --git a/src/test/ui/parser/keyword-impl-as-identifier.stderr b/src/test/ui/parser/keyword-impl-as-identifier.stderr index 2672959b7c68e..01886eb45cb6d 100644 --- a/src/test/ui/parser/keyword-impl-as-identifier.stderr +++ b/src/test/ui/parser/keyword-impl-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `impl` +error: expected identifier, found keyword `impl` --> $DIR/keyword-impl-as-identifier.rs:4:9 | LL | let impl = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#impl = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-let-as-identifier.rs b/src/test/ui/parser/keyword-let-as-identifier.rs index 07c0ddf8ce573..9b1183501b28d 100644 --- a/src/test/ui/parser/keyword-let-as-identifier.rs +++ b/src/test/ui/parser/keyword-let-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py let' fn main() { - let let = "foo"; //~ error: expected pattern, found keyword `let` + let let = "foo"; //~ error: expected identifier, found keyword `let` } diff --git a/src/test/ui/parser/keyword-let-as-identifier.stderr b/src/test/ui/parser/keyword-let-as-identifier.stderr index 99dbc0530f3fe..f6c39077be23b 100644 --- a/src/test/ui/parser/keyword-let-as-identifier.stderr +++ b/src/test/ui/parser/keyword-let-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `let` +error: expected identifier, found keyword `let` --> $DIR/keyword-let-as-identifier.rs:4:9 | LL | let let = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#let = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-loop-as-identifier.rs b/src/test/ui/parser/keyword-loop-as-identifier.rs index 8643ffe434505..46914a19be2bd 100644 --- a/src/test/ui/parser/keyword-loop-as-identifier.rs +++ b/src/test/ui/parser/keyword-loop-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py loop' fn main() { - let loop = "foo"; //~ error: expected pattern, found keyword `loop` + let loop = "foo"; //~ error: expected identifier, found keyword `loop` } diff --git a/src/test/ui/parser/keyword-loop-as-identifier.stderr b/src/test/ui/parser/keyword-loop-as-identifier.stderr index 783507eb35cd7..f0c282faa29f1 100644 --- a/src/test/ui/parser/keyword-loop-as-identifier.stderr +++ b/src/test/ui/parser/keyword-loop-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `loop` +error: expected identifier, found keyword `loop` --> $DIR/keyword-loop-as-identifier.rs:4:9 | LL | let loop = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#loop = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-match-as-identifier.rs b/src/test/ui/parser/keyword-match-as-identifier.rs index 8ef6b6810a56b..d3cecb991b8f9 100644 --- a/src/test/ui/parser/keyword-match-as-identifier.rs +++ b/src/test/ui/parser/keyword-match-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py match' fn main() { - let match = "foo"; //~ error: expected pattern, found keyword `match` + let match = "foo"; //~ error: expected identifier, found keyword `match` } diff --git a/src/test/ui/parser/keyword-match-as-identifier.stderr b/src/test/ui/parser/keyword-match-as-identifier.stderr index e56a115c91636..f1f4397d194f0 100644 --- a/src/test/ui/parser/keyword-match-as-identifier.stderr +++ b/src/test/ui/parser/keyword-match-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `match` +error: expected identifier, found keyword `match` --> $DIR/keyword-match-as-identifier.rs:4:9 | LL | let match = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#match = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-mod-as-identifier.rs b/src/test/ui/parser/keyword-mod-as-identifier.rs index 96bcdccf0a096..b9c7b6c78ed6c 100644 --- a/src/test/ui/parser/keyword-mod-as-identifier.rs +++ b/src/test/ui/parser/keyword-mod-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py mod' fn main() { - let mod = "foo"; //~ error: expected pattern, found keyword `mod` + let mod = "foo"; //~ error: expected identifier, found keyword `mod` } diff --git a/src/test/ui/parser/keyword-mod-as-identifier.stderr b/src/test/ui/parser/keyword-mod-as-identifier.stderr index a8be2ceb037d6..65ae3baa8c21d 100644 --- a/src/test/ui/parser/keyword-mod-as-identifier.stderr +++ b/src/test/ui/parser/keyword-mod-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `mod` +error: expected identifier, found keyword `mod` --> $DIR/keyword-mod-as-identifier.rs:4:9 | LL | let mod = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#mod = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-move-as-identifier.rs b/src/test/ui/parser/keyword-move-as-identifier.rs index 2193af530bd7a..65be02e3c70cf 100644 --- a/src/test/ui/parser/keyword-move-as-identifier.rs +++ b/src/test/ui/parser/keyword-move-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py move' fn main() { - let move = "foo"; //~ error: expected pattern, found keyword `move` + let move = "foo"; //~ error: expected identifier, found keyword `move` } diff --git a/src/test/ui/parser/keyword-move-as-identifier.stderr b/src/test/ui/parser/keyword-move-as-identifier.stderr index e0687e27eb585..216f7c931eea7 100644 --- a/src/test/ui/parser/keyword-move-as-identifier.stderr +++ b/src/test/ui/parser/keyword-move-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `move` +error: expected identifier, found keyword `move` --> $DIR/keyword-move-as-identifier.rs:4:9 | LL | let move = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#move = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-override.rs b/src/test/ui/parser/keyword-override.rs index 948a20095f1ea..009bebd7ddba8 100644 --- a/src/test/ui/parser/keyword-override.rs +++ b/src/test/ui/parser/keyword-override.rs @@ -1,3 +1,3 @@ fn main() { - let override = (); //~ ERROR expected pattern, found reserved keyword `override` + let override = (); //~ ERROR expected identifier, found reserved keyword `override` } diff --git a/src/test/ui/parser/keyword-override.stderr b/src/test/ui/parser/keyword-override.stderr index 1bfc6c9b3858d..3183fa510c2d1 100644 --- a/src/test/ui/parser/keyword-override.stderr +++ b/src/test/ui/parser/keyword-override.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `override` +error: expected identifier, found reserved keyword `override` --> $DIR/keyword-override.rs:2:9 | LL | let override = (); - | ^^^^^^^^ expected pattern + | ^^^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#override = (); + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-pub-as-identifier.rs b/src/test/ui/parser/keyword-pub-as-identifier.rs index 2ed8cc6b268ca..2b2bb14118d7d 100644 --- a/src/test/ui/parser/keyword-pub-as-identifier.rs +++ b/src/test/ui/parser/keyword-pub-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py pub' fn main() { - let pub = "foo"; //~ error: expected pattern, found keyword `pub` + let pub = "foo"; //~ error: expected identifier, found keyword `pub` } diff --git a/src/test/ui/parser/keyword-pub-as-identifier.stderr b/src/test/ui/parser/keyword-pub-as-identifier.stderr index 526ddcd6ee0ff..f81078b12bd3c 100644 --- a/src/test/ui/parser/keyword-pub-as-identifier.stderr +++ b/src/test/ui/parser/keyword-pub-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `pub` +error: expected identifier, found keyword `pub` --> $DIR/keyword-pub-as-identifier.rs:4:9 | LL | let pub = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#pub = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-return-as-identifier.rs b/src/test/ui/parser/keyword-return-as-identifier.rs index 920931b00f954..e1a2db5e4d82d 100644 --- a/src/test/ui/parser/keyword-return-as-identifier.rs +++ b/src/test/ui/parser/keyword-return-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py return' fn main() { - let return = "foo"; //~ error: expected pattern, found keyword `return` + let return = "foo"; //~ error: expected identifier, found keyword `return` } diff --git a/src/test/ui/parser/keyword-return-as-identifier.stderr b/src/test/ui/parser/keyword-return-as-identifier.stderr index c0156a63fa9d1..8cc4d12fbbb9a 100644 --- a/src/test/ui/parser/keyword-return-as-identifier.stderr +++ b/src/test/ui/parser/keyword-return-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `return` +error: expected identifier, found keyword `return` --> $DIR/keyword-return-as-identifier.rs:4:9 | LL | let return = "foo"; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#return = "foo"; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-static-as-identifier.rs b/src/test/ui/parser/keyword-static-as-identifier.rs index 3ccbfccfc9394..423b9854b8aa1 100644 --- a/src/test/ui/parser/keyword-static-as-identifier.rs +++ b/src/test/ui/parser/keyword-static-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py static' fn main() { - let static = "foo"; //~ error: expected pattern, found keyword `static` + let static = "foo"; //~ error: expected identifier, found keyword `static` } diff --git a/src/test/ui/parser/keyword-static-as-identifier.stderr b/src/test/ui/parser/keyword-static-as-identifier.stderr index 00a65977732f8..7d22bc97d66ae 100644 --- a/src/test/ui/parser/keyword-static-as-identifier.stderr +++ b/src/test/ui/parser/keyword-static-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `static` +error: expected identifier, found keyword `static` --> $DIR/keyword-static-as-identifier.rs:4:9 | LL | let static = "foo"; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#static = "foo"; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-struct-as-identifier.rs b/src/test/ui/parser/keyword-struct-as-identifier.rs index 69d8f19065533..18cfe11592aed 100644 --- a/src/test/ui/parser/keyword-struct-as-identifier.rs +++ b/src/test/ui/parser/keyword-struct-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py struct' fn main() { - let struct = "foo"; //~ error: expected pattern, found keyword `struct` + let struct = "foo"; //~ error: expected identifier, found keyword `struct` } diff --git a/src/test/ui/parser/keyword-struct-as-identifier.stderr b/src/test/ui/parser/keyword-struct-as-identifier.stderr index b2d6639e72ecb..b109fa6247dcd 100644 --- a/src/test/ui/parser/keyword-struct-as-identifier.stderr +++ b/src/test/ui/parser/keyword-struct-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `struct` +error: expected identifier, found keyword `struct` --> $DIR/keyword-struct-as-identifier.rs:4:9 | LL | let struct = "foo"; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#struct = "foo"; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-trait-as-identifier.rs b/src/test/ui/parser/keyword-trait-as-identifier.rs index f62858442d252..67f81167dbdd3 100644 --- a/src/test/ui/parser/keyword-trait-as-identifier.rs +++ b/src/test/ui/parser/keyword-trait-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py trait' fn main() { - let trait = "foo"; //~ error: expected pattern, found keyword `trait` + let trait = "foo"; //~ error: expected identifier, found keyword `trait` } diff --git a/src/test/ui/parser/keyword-trait-as-identifier.stderr b/src/test/ui/parser/keyword-trait-as-identifier.stderr index b31c0df28c008..ccc675cdb3a7c 100644 --- a/src/test/ui/parser/keyword-trait-as-identifier.stderr +++ b/src/test/ui/parser/keyword-trait-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `trait` +error: expected identifier, found keyword `trait` --> $DIR/keyword-trait-as-identifier.rs:4:9 | LL | let trait = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#trait = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs b/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs index 13a938b2e0988..4fa37bdb057b7 100644 --- a/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs +++ b/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs @@ -1,5 +1,5 @@ // compile-flags: --edition 2018 fn main() { - let try = "foo"; //~ error: expected pattern, found reserved keyword `try` + let try = "foo"; //~ error: expected identifier, found reserved keyword `try` } diff --git a/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr b/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr index c342e3a76fbb4..f71b889a30db5 100644 --- a/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr +++ b/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `try` +error: expected identifier, found reserved keyword `try` --> $DIR/keyword-try-as-identifier-edition2018.rs:4:9 | LL | let try = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#try = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-type-as-identifier.rs b/src/test/ui/parser/keyword-type-as-identifier.rs index 992547e6f59c0..04adddf72c6ff 100644 --- a/src/test/ui/parser/keyword-type-as-identifier.rs +++ b/src/test/ui/parser/keyword-type-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py type' fn main() { - let type = "foo"; //~ error: expected pattern, found keyword `type` + let type = "foo"; //~ error: expected identifier, found keyword `type` } diff --git a/src/test/ui/parser/keyword-type-as-identifier.stderr b/src/test/ui/parser/keyword-type-as-identifier.stderr index b749c708d441d..88099d949a829 100644 --- a/src/test/ui/parser/keyword-type-as-identifier.stderr +++ b/src/test/ui/parser/keyword-type-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `type` +error: expected identifier, found keyword `type` --> $DIR/keyword-type-as-identifier.rs:4:9 | LL | let type = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#type = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-typeof.rs b/src/test/ui/parser/keyword-typeof.rs index 4ef102646ef1c..29dc77d276cbd 100644 --- a/src/test/ui/parser/keyword-typeof.rs +++ b/src/test/ui/parser/keyword-typeof.rs @@ -1,3 +1,3 @@ fn main() { - let typeof = (); //~ ERROR expected pattern, found reserved keyword `typeof` + let typeof = (); //~ ERROR expected identifier, found reserved keyword `typeof` } diff --git a/src/test/ui/parser/keyword-typeof.stderr b/src/test/ui/parser/keyword-typeof.stderr index e7b18023e61a9..4a1b63d5c9357 100644 --- a/src/test/ui/parser/keyword-typeof.stderr +++ b/src/test/ui/parser/keyword-typeof.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `typeof` +error: expected identifier, found reserved keyword `typeof` --> $DIR/keyword-typeof.rs:2:9 | LL | let typeof = (); - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#typeof = (); + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-unsafe-as-identifier.rs b/src/test/ui/parser/keyword-unsafe-as-identifier.rs index adb20ebe48c79..0ff6d188c6480 100644 --- a/src/test/ui/parser/keyword-unsafe-as-identifier.rs +++ b/src/test/ui/parser/keyword-unsafe-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py unsafe' fn main() { - let unsafe = "foo"; //~ error: expected pattern, found keyword `unsafe` + let unsafe = "foo"; //~ error: expected identifier, found keyword `unsafe` } diff --git a/src/test/ui/parser/keyword-unsafe-as-identifier.stderr b/src/test/ui/parser/keyword-unsafe-as-identifier.stderr index 67935ce43ba04..205bb81df405b 100644 --- a/src/test/ui/parser/keyword-unsafe-as-identifier.stderr +++ b/src/test/ui/parser/keyword-unsafe-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `unsafe` +error: expected identifier, found keyword `unsafe` --> $DIR/keyword-unsafe-as-identifier.rs:4:9 | LL | let unsafe = "foo"; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#unsafe = "foo"; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-use-as-identifier.rs b/src/test/ui/parser/keyword-use-as-identifier.rs index 198444bafc5b8..821bedee08832 100644 --- a/src/test/ui/parser/keyword-use-as-identifier.rs +++ b/src/test/ui/parser/keyword-use-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py use' fn main() { - let use = "foo"; //~ error: expected pattern, found keyword `use` + let use = "foo"; //~ error: expected identifier, found keyword `use` } diff --git a/src/test/ui/parser/keyword-use-as-identifier.stderr b/src/test/ui/parser/keyword-use-as-identifier.stderr index 2c69d0a8744a0..85a0492f5735f 100644 --- a/src/test/ui/parser/keyword-use-as-identifier.stderr +++ b/src/test/ui/parser/keyword-use-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `use` +error: expected identifier, found keyword `use` --> $DIR/keyword-use-as-identifier.rs:4:9 | LL | let use = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#use = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-where-as-identifier.rs b/src/test/ui/parser/keyword-where-as-identifier.rs index 5624a8fc46038..56301bd20adfd 100644 --- a/src/test/ui/parser/keyword-where-as-identifier.rs +++ b/src/test/ui/parser/keyword-where-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py where' fn main() { - let where = "foo"; //~ error: expected pattern, found keyword `where` + let where = "foo"; //~ error: expected identifier, found keyword `where` } diff --git a/src/test/ui/parser/keyword-where-as-identifier.stderr b/src/test/ui/parser/keyword-where-as-identifier.stderr index fc01183ca046b..b8b8506907636 100644 --- a/src/test/ui/parser/keyword-where-as-identifier.stderr +++ b/src/test/ui/parser/keyword-where-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `where` +error: expected identifier, found keyword `where` --> $DIR/keyword-where-as-identifier.rs:4:9 | LL | let where = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#where = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-while-as-identifier.rs b/src/test/ui/parser/keyword-while-as-identifier.rs index c0a539d350764..22026d15dcbfb 100644 --- a/src/test/ui/parser/keyword-while-as-identifier.rs +++ b/src/test/ui/parser/keyword-while-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py while' fn main() { - let while = "foo"; //~ error: expected pattern, found keyword `while` + let while = "foo"; //~ error: expected identifier, found keyword `while` } diff --git a/src/test/ui/parser/keyword-while-as-identifier.stderr b/src/test/ui/parser/keyword-while-as-identifier.stderr index f72ac87742099..bb0c0ac668a41 100644 --- a/src/test/ui/parser/keyword-while-as-identifier.stderr +++ b/src/test/ui/parser/keyword-while-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `while` +error: expected identifier, found keyword `while` --> $DIR/keyword-while-as-identifier.rs:4:9 | LL | let while = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#while = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/mut-patterns.rs b/src/test/ui/parser/mut-patterns.rs index bffeb1e2e7c40..87e127f9d364a 100644 --- a/src/test/ui/parser/mut-patterns.rs +++ b/src/test/ui/parser/mut-patterns.rs @@ -1,7 +1,35 @@ // Can't put mut in non-ident pattern +// edition:2018 + +#![feature(box_patterns)] +#![allow(warnings)] + pub fn main() { + let mut mut x = 0; + //~^ ERROR `mut` on a binding may not be repeated + //~| remove the additional `mut`s + struct Foo { x: isize } let mut Foo { x: x } = Foo { x: 3 }; - //~^ ERROR: expected one of `:`, `;`, `=`, `@`, or `|`, found `{` + //~^ ERROR `mut` must be attached to each individual binding + //~| add `mut` to each binding + + let mut Foo { x } = Foo { x: 3 }; + //~^ ERROR `mut` must be attached to each individual binding + //~| add `mut` to each binding + + struct r#yield(u8, u8); + let mut mut yield(become, await) = r#yield(0, 0); + //~^ ERROR `mut` on a binding may not be repeated + //~| ERROR `mut` must be attached to each individual binding + //~| ERROR expected identifier, found reserved keyword `yield` + //~| ERROR expected identifier, found reserved keyword `become` + //~| ERROR expected identifier, found reserved keyword `await` + + struct W(T, U); + struct B { f: Box } + let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) + //~^ ERROR `mut` must be attached to each individual binding + = W(0, W(1, W(2, W(3, B { f: Box::new(4u8) })))); } diff --git a/src/test/ui/parser/mut-patterns.stderr b/src/test/ui/parser/mut-patterns.stderr index b39209afd4295..a251e2908f02c 100644 --- a/src/test/ui/parser/mut-patterns.stderr +++ b/src/test/ui/parser/mut-patterns.stderr @@ -1,8 +1,68 @@ -error: expected one of `:`, `;`, `=`, `@`, or `|`, found `{` - --> $DIR/mut-patterns.rs:5:17 +error: `mut` on a binding may not be repeated + --> $DIR/mut-patterns.rs:9:13 + | +LL | let mut mut x = 0; + | ^^^ help: remove the additional `mut`s + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:14:9 | LL | let mut Foo { x: x } = Foo { x: 3 }; - | ^ expected one of `:`, `;`, `=`, `@`, or `|` here + | ^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { x: mut x }` + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:18:9 + | +LL | let mut Foo { x } = Foo { x: 3 }; + | ^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { mut x }` + +error: `mut` on a binding may not be repeated + --> $DIR/mut-patterns.rs:23:13 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^ help: remove the additional `mut`s + +error: expected identifier, found reserved keyword `yield` + --> $DIR/mut-patterns.rs:23:17 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let mut mut r#yield(become, await) = r#yield(0, 0); + | ^^^^^^^ + +error: expected identifier, found reserved keyword `become` + --> $DIR/mut-patterns.rs:23:23 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let mut mut yield(r#become, await) = r#yield(0, 0); + | ^^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/mut-patterns.rs:23:31 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let mut mut yield(become, r#await) = r#yield(0, 0); + | ^^^^^^^ + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:23:9 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `r#yield(mut r#become, mut r#await)` + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:32:9 + | +LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f }))))` -error: aborting due to previous error +error: aborting due to 9 previous errors diff --git a/src/test/ui/reserved/reserved-become.rs b/src/test/ui/reserved/reserved-become.rs index 2279a05e6b2db..56645255ee5f6 100644 --- a/src/test/ui/reserved/reserved-become.rs +++ b/src/test/ui/reserved/reserved-become.rs @@ -1,4 +1,4 @@ fn main() { let become = 0; - //~^ ERROR expected pattern, found reserved keyword `become` + //~^ ERROR expected identifier, found reserved keyword `become` } diff --git a/src/test/ui/reserved/reserved-become.stderr b/src/test/ui/reserved/reserved-become.stderr index f9fe78e18b393..3ce9fb33c289e 100644 --- a/src/test/ui/reserved/reserved-become.stderr +++ b/src/test/ui/reserved/reserved-become.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `become` +error: expected identifier, found reserved keyword `become` --> $DIR/reserved-become.rs:2:9 | LL | let become = 0; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#become = 0; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/self/self_type_keyword.rs b/src/test/ui/self/self_type_keyword.rs index 01b3309fcacb1..d479905932be0 100644 --- a/src/test/ui/self/self_type_keyword.rs +++ b/src/test/ui/self/self_type_keyword.rs @@ -14,7 +14,8 @@ pub fn main() { ref Self => (), //~^ ERROR expected identifier, found keyword `Self` mut Self => (), - //~^ ERROR expected identifier, found keyword `Self` + //~^ ERROR `mut` must be attached to each individual binding + //~| ERROR cannot find unit struct/variant or constant `Self` ref mut Self => (), //~^ ERROR expected identifier, found keyword `Self` Self!() => (), diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr index b63de98b8e702..fdae06ccdd9f5 100644 --- a/src/test/ui/self/self_type_keyword.stderr +++ b/src/test/ui/self/self_type_keyword.stderr @@ -10,38 +10,38 @@ error: expected identifier, found keyword `Self` LL | ref Self => (), | ^^^^ expected identifier, found keyword -error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:16:13 +error: `mut` must be attached to each individual binding + --> $DIR/self_type_keyword.rs:16:9 | LL | mut Self => (), - | ^^^^ expected identifier, found keyword + | ^^^^^^^^ help: add `mut` to each binding: `Self` error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:18:17 + --> $DIR/self_type_keyword.rs:19:17 | LL | ref mut Self => (), | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:22:15 + --> $DIR/self_type_keyword.rs:23:15 | LL | Foo { Self } => (), | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:28:26 + --> $DIR/self_type_keyword.rs:29:26 | LL | extern crate core as Self; | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:33:32 + --> $DIR/self_type_keyword.rs:34:32 | LL | use std::option::Option as Self; | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:38:11 + --> $DIR/self_type_keyword.rs:39:11 | LL | trait Self {} | ^^^^ expected identifier, found keyword @@ -53,11 +53,21 @@ LL | struct Bar<'Self>; | ^^^^^ error: cannot find macro `Self!` in this scope - --> $DIR/self_type_keyword.rs:20:9 + --> $DIR/self_type_keyword.rs:21:9 | LL | Self!() => (), | ^^^^ +error[E0531]: cannot find unit struct/variant or constant `Self` in this scope + --> $DIR/self_type_keyword.rs:16:13 + | +LL | mut Self => (), + | ^^^^ not found in this scope +help: possible candidate is found in another module, you can import it into scope + | +LL | use foo::Self; + | + error[E0392]: parameter `'Self` is never used --> $DIR/self_type_keyword.rs:6:12 | @@ -66,6 +76,6 @@ LL | struct Bar<'Self>; | = help: consider removing `'Self` or using a marker such as `std::marker::PhantomData` -error: aborting due to 11 previous errors +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0392`. From e0ce9f8c0a97e5949c9cadd220279d6969289daa Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Tue, 27 Aug 2019 13:24:32 +0200 Subject: [PATCH 280/618] Cleanup: Consistently use `Param` instead of `Arg` #62426 --- src/librustc/hir/intravisit.rs | 14 +-- src/librustc/hir/lowering.rs | 28 +++--- src/librustc/hir/lowering/item.rs | 80 +++++++-------- src/librustc/hir/map/collector.rs | 10 +- src/librustc/hir/map/mod.rs | 14 +-- src/librustc/hir/mod.rs | 20 ++-- src/librustc/hir/print.rs | 16 +-- src/librustc/ich/impls_hir.rs | 4 +- .../infer/error_reporting/need_type_info.rs | 6 +- .../nice_region_error/different_lifetimes.rs | 22 ++--- .../nice_region_error/named_anon_conflict.rs | 30 +++--- .../error_reporting/nice_region_error/util.rs | 44 ++++----- src/librustc/lint/context.rs | 16 +-- src/librustc/lint/mod.rs | 10 +- src/librustc/middle/expr_use_visitor.rs | 18 ++-- src/librustc/middle/liveness.rs | 22 ++--- src/librustc/middle/region.rs | 4 +- src/librustc/middle/resolve_lifetime.rs | 2 +- src/librustc/traits/error_reporting.rs | 3 +- src/librustc_ast_borrowck/dataflow.rs | 4 +- src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/decoder.rs | 10 +- src/librustc_metadata/encoder.rs | 24 ++--- src/librustc_metadata/schema.rs | 2 +- src/librustc_mir/build/mod.rs | 4 +- src/librustc_mir/hair/pattern/check_match.rs | 6 +- src/librustc_passes/hir_stats.rs | 6 +- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/librustc_save_analysis/lib.rs | 4 +- src/librustc_typeck/check/demand.rs | 14 +-- src/librustc_typeck/check/mod.rs | 18 ++-- src/librustc_typeck/check/pat.rs | 2 +- src/librustc_typeck/check/regionck.rs | 20 ++-- src/librustc_typeck/check/writeback.rs | 8 +- src/librustdoc/clean/mod.rs | 4 +- src/libsyntax/ast.rs | 22 ++--- src/libsyntax/attr/mod.rs | 2 +- src/libsyntax/ext/build.rs | 12 +-- src/libsyntax/mut_visit.rs | 12 +-- src/libsyntax/parse/attr.rs | 2 +- src/libsyntax/parse/diagnostics.rs | 34 +++---- src/libsyntax/parse/parser.rs | 98 ++++++++++--------- src/libsyntax/parse/parser/expr.rs | 12 +-- src/libsyntax/parse/parser/item.rs | 10 +- src/libsyntax/parse/parser/ty.rs | 2 +- src/libsyntax/print/pprust.rs | 18 ++-- src/libsyntax/visit.rs | 14 +-- src/libsyntax_ext/deriving/generic/mod.rs | 4 +- src/libsyntax_ext/global_allocator.rs | 12 +-- .../no-args-non-move-async-closure.rs | 2 +- .../no-args-non-move-async-closure.stderr | 2 +- .../generator/no-arguments-on-generators.rs | 2 +- .../no-arguments-on-generators.stderr | 2 +- 53 files changed, 379 insertions(+), 376 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index fa274f831b795..bbde3510e29f9 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -210,8 +210,8 @@ pub trait Visitor<'v> : Sized { } } - fn visit_arg(&mut self, arg: &'v Arg) { - walk_arg(self, arg) + fn visit_param(&mut self, param: &'v Param) { + walk_param(self, param) } /// Visits the top-level item and (optionally) nested items / impl items. See @@ -400,7 +400,7 @@ pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_hir_id } pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) { - walk_list!(visitor, visit_arg, &body.arguments); + walk_list!(visitor, visit_param, &body.params); visitor.visit_expr(&body.value); } @@ -454,10 +454,10 @@ pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef) visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id) } -pub fn walk_arg<'v, V: Visitor<'v>>(visitor: &mut V, arg: &'v Arg) { - visitor.visit_id(arg.hir_id); - visitor.visit_pat(&arg.pat); - walk_list!(visitor, visit_attribute, &arg.attrs); +pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param) { + visitor.visit_id(param.hir_id); + visitor.visit_pat(¶m.pat); + walk_list!(visitor, visit_attribute, ¶m.attrs); } pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 7ec3210613727..5e2aebfd3187b 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -510,12 +510,12 @@ impl<'a> LoweringContext<'a> { &f.generic_params ); // Mirrors visit::walk_fn_decl - for argument in &f.decl.inputs { + for parameter in &f.decl.inputs { // We don't lower the ids of argument patterns self.with_hir_id_owner(None, |this| { - this.visit_pat(&argument.pat); + this.visit_pat(¶meter.pat); }); - self.visit_ty(&argument.ty) + self.visit_ty(¶meter.ty) } self.visit_fn_ret_ty(&f.decl.output) } @@ -735,7 +735,7 @@ impl<'a> LoweringContext<'a> { /// /// Presuming that in-band lifetimes are enabled, then /// `self.anonymous_lifetime_mode` will be updated to match the - /// argument while `f` is running (and restored afterwards). + /// parameter while `f` is running (and restored afterwards). fn collect_in_band_defs( &mut self, parent_id: DefId, @@ -880,7 +880,7 @@ impl<'a> LoweringContext<'a> { /// /// Presuming that in-band lifetimes are enabled, then /// `self.anonymous_lifetime_mode` will be updated to match the - /// argument while `f` is running (and restored afterwards). + /// parameter while `f` is running (and restored afterwards). fn add_in_band_defs( &mut self, generics: &Generics, @@ -1080,7 +1080,7 @@ impl<'a> LoweringContext<'a> { ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => (true, ImplTraitContext::OpaqueTy(None)), - // We are in the argument position, but not within a dyn type: + // We are in the parameter position, but not within a dyn type: // // fn foo(x: impl Iterator) // @@ -1204,7 +1204,7 @@ impl<'a> LoweringContext<'a> { unsafety: this.lower_unsafety(f.unsafety), abi: f.abi, decl: this.lower_fn_decl(&f.decl, None, false, None), - arg_names: this.lower_fn_args_to_names(&f.decl), + param_names: this.lower_fn_params_to_names(&f.decl), })) }, ) @@ -2093,12 +2093,12 @@ impl<'a> LoweringContext<'a> { } } - fn lower_fn_args_to_names(&mut self, decl: &FnDecl) -> hir::HirVec { + fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> hir::HirVec { decl.inputs .iter() - .map(|arg| match arg.pat.node { + .map(|param| match param.pat.node { PatKind::Ident(_, ident, _) => ident, - _ => Ident::new(kw::Invalid, arg.pat.span), + _ => Ident::new(kw::Invalid, param.pat.span), }) .collect() } @@ -2136,11 +2136,11 @@ impl<'a> LoweringContext<'a> { let inputs = self.with_anonymous_lifetime_mode(lt_mode, |this| { decl.inputs .iter() - .map(|arg| { + .map(|param| { if let Some((_, ibty)) = &mut in_band_ty_params { - this.lower_ty_direct(&arg.ty, ImplTraitContext::Universal(ibty)) + this.lower_ty_direct(¶m.ty, ImplTraitContext::Universal(ibty)) } else { - this.lower_ty_direct(&arg.ty, ImplTraitContext::disallowed()) + this.lower_ty_direct(¶m.ty, ImplTraitContext::disallowed()) } }) .collect::>() @@ -2205,7 +2205,7 @@ impl<'a> LoweringContext<'a> { // // type OpaqueTy = impl Future; // - // `inputs`: lowered types of arguments to the function (used to collect lifetimes) + // `inputs`: lowered types of parameters to the function (used to collect lifetimes) // `output`: unlowered output type (`T` in `-> T`) // `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition) // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 4f9a9ed5673c7..4e432f4981d23 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -720,7 +720,7 @@ impl LoweringContext<'_> { ( // Disallow impl Trait in foreign items this.lower_fn_decl(fdec, None, false, None), - this.lower_fn_args_to_names(fdec), + this.lower_fn_params_to_names(fdec), ) }, ); @@ -827,7 +827,7 @@ impl LoweringContext<'_> { ), ), TraitItemKind::Method(ref sig, None) => { - let names = self.lower_fn_args_to_names(&sig.decl); + let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig( &i.generics, sig, @@ -1028,10 +1028,10 @@ impl LoweringContext<'_> { } } - fn record_body(&mut self, arguments: HirVec, value: hir::Expr) -> hir::BodyId { + fn record_body(&mut self, params: HirVec, value: hir::Expr) -> hir::BodyId { let body = hir::Body { generator_kind: self.generator_kind, - arguments, + params, value, }; let id = body.id(); @@ -1041,21 +1041,21 @@ impl LoweringContext<'_> { fn lower_body( &mut self, - f: impl FnOnce(&mut LoweringContext<'_>) -> (HirVec, hir::Expr), + f: impl FnOnce(&mut LoweringContext<'_>) -> (HirVec, hir::Expr), ) -> hir::BodyId { let prev_gen_kind = self.generator_kind.take(); - let (arguments, result) = f(self); - let body_id = self.record_body(arguments, result); + let (parameters, result) = f(self); + let body_id = self.record_body(parameters, result); self.generator_kind = prev_gen_kind; body_id } - fn lower_arg(&mut self, arg: &Arg) -> hir::Arg { - hir::Arg { - attrs: self.lower_attrs(&arg.attrs), - hir_id: self.lower_node_id(arg.id), - pat: self.lower_pat(&arg.pat), - span: arg.span, + fn lower_param(&mut self, param: &Param) -> hir::Param { + hir::Param { + attrs: self.lower_attrs(¶m.attrs), + hir_id: self.lower_node_id(param.id), + pat: self.lower_pat(¶m.pat), + span: param.span, } } @@ -1065,7 +1065,7 @@ impl LoweringContext<'_> { body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr, ) -> hir::BodyId { self.lower_body(|this| ( - decl.inputs.iter().map(|x| this.lower_arg(x)).collect(), + decl.inputs.iter().map(|x| this.lower_param(x)).collect(), body(this), )) } @@ -1093,10 +1093,10 @@ impl LoweringContext<'_> { }; self.lower_body(|this| { - let mut arguments: Vec = Vec::new(); + let mut parameters: Vec = Vec::new(); let mut statements: Vec = Vec::new(); - // Async function arguments are lowered into the closure body so that they are + // Async function parameters are lowered into the closure body so that they are // captured and so that the drop order matches the equivalent non-async functions. // // from: @@ -1121,13 +1121,13 @@ impl LoweringContext<'_> { // // If `` is a simple ident, then it is lowered to a single // `let = ;` statement as an optimization. - for (index, argument) in decl.inputs.iter().enumerate() { - let argument = this.lower_arg(argument); - let span = argument.pat.span; + for (index, parameter) in decl.inputs.iter().enumerate() { + let parameter = this.lower_param(parameter); + let span = parameter.pat.span; // Check if this is a binding pattern, if so, we can optimize and avoid adding a - // `let = __argN;` statement. In this case, we do not rename the argument. - let (ident, is_simple_argument) = match argument.pat.node { + // `let = __argN;` statement. In this case, we do not rename the parameter. + let (ident, is_simple_parameter) = match parameter.pat.node { hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _) => (ident, true), _ => { @@ -1142,32 +1142,32 @@ impl LoweringContext<'_> { let desugared_span = this.mark_span_with_reason(DesugaringKind::Async, span, None); - // Construct an argument representing `__argN: ` to replace the argument of the + // Construct a parameter representing `__argN: ` to replace the parameter of the // async function. // - // If this is the simple case, this argument will end up being the same as the - // original argument, but with a different pattern id. + // If this is the simple case, this parameter will end up being the same as the + // original parameter, but with a different pattern id. let mut stmt_attrs = ThinVec::new(); - stmt_attrs.extend(argument.attrs.iter().cloned()); - let (new_argument_pat, new_argument_id) = this.pat_ident(desugared_span, ident); - let new_argument = hir::Arg { - attrs: argument.attrs, - hir_id: argument.hir_id, - pat: new_argument_pat, - span: argument.span, + stmt_attrs.extend(parameter.attrs.iter().cloned()); + let (new_parameter_pat, new_parameter_id) = this.pat_ident(desugared_span, ident); + let new_parameter = hir::Param { + attrs: parameter.attrs, + hir_id: parameter.hir_id, + pat: new_parameter_pat, + span: parameter.span, }; - if is_simple_argument { + if is_simple_parameter { // If this is the simple case, then we only insert one statement that is // `let = ;`. We re-use the original argument's pattern so that // `HirId`s are densely assigned. - let expr = this.expr_ident(desugared_span, ident, new_argument_id); + let expr = this.expr_ident(desugared_span, ident, new_parameter_id); let stmt = this.stmt_let_pat( stmt_attrs, desugared_span, Some(P(expr)), - argument.pat, + parameter.pat, hir::LocalSource::AsyncFn ); statements.push(stmt); @@ -1179,7 +1179,7 @@ impl LoweringContext<'_> { // let = __argN; // ``` // - // The first statement moves the argument into the closure and thus ensures + // The first statement moves the parameter into the closure and thus ensures // that the drop order is correct. // // The second statement creates the bindings that the user wrote. @@ -1189,7 +1189,7 @@ impl LoweringContext<'_> { // statement. let (move_pat, move_id) = this.pat_ident_binding_mode( desugared_span, ident, hir::BindingAnnotation::Mutable); - let move_expr = this.expr_ident(desugared_span, ident, new_argument_id); + let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id); let move_stmt = this.stmt_let_pat( ThinVec::new(), desugared_span, @@ -1199,13 +1199,13 @@ impl LoweringContext<'_> { ); // Construct the `let = __argN;` statement. We re-use the original - // argument's pattern so that `HirId`s are densely assigned. + // parameter's pattern so that `HirId`s are densely assigned. let pattern_expr = this.expr_ident(desugared_span, ident, move_id); let pattern_stmt = this.stmt_let_pat( stmt_attrs, desugared_span, Some(P(pattern_expr)), - argument.pat, + parameter.pat, hir::LocalSource::AsyncFn ); @@ -1213,7 +1213,7 @@ impl LoweringContext<'_> { statements.push(pattern_stmt); }; - arguments.push(new_argument); + parameters.push(new_parameter); } let async_expr = this.make_async_expr( @@ -1222,7 +1222,7 @@ impl LoweringContext<'_> { let body = this.lower_block_with_stmts(body, false, statements); this.expr_block(body, ThinVec::new()) }); - (HirVec::from(arguments), this.expr(body.span, async_expr, ThinVec::new())) + (HirVec::from(parameters), this.expr(body.span, async_expr, ThinVec::new())) }) } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index effe2c0cc6a76..773bb8dde0690 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -363,11 +363,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.currently_in_body = prev_in_body; } - fn visit_arg(&mut self, arg: &'hir Arg) { - let node = Node::Arg(arg); - self.insert(arg.pat.span, arg.hir_id, node); - self.with_parent(arg.hir_id, |this| { - intravisit::walk_arg(this, arg); + fn visit_param(&mut self, param: &'hir Param) { + let node = Node::Param(param); + self.insert(param.pat.span, param.hir_id, node); + self.with_parent(param.hir_id, |this| { + intravisit::walk_param(this, param); }); } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index f80e527dfd9b7..eb8be6e6e3cbc 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -360,7 +360,7 @@ impl<'hir> Map<'hir> { Node::Pat(_) | Node::Binding(_) | Node::Local(_) | - Node::Arg(_) | + Node::Param(_) | Node::Arm(_) | Node::Lifetime(_) | Node::Visibility(_) | @@ -964,7 +964,7 @@ impl<'hir> Map<'hir> { pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] { self.read(id); // reveals attributes on the node let attrs = match self.find_entry(id).map(|entry| entry.node) { - Some(Node::Arg(a)) => Some(&a.attrs[..]), + Some(Node::Param(a)) => Some(&a.attrs[..]), Some(Node::Local(l)) => Some(&l.attrs[..]), Some(Node::Item(i)) => Some(&i.attrs[..]), Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]), @@ -1028,7 +1028,7 @@ impl<'hir> Map<'hir> { pub fn span(&self, hir_id: HirId) -> Span { self.read(hir_id); // reveals span from node match self.find_entry(hir_id).map(|entry| entry.node) { - Some(Node::Arg(arg)) => arg.span, + Some(Node::Param(param)) => param.span, Some(Node::Item(item)) => item.span, Some(Node::ForeignItem(foreign_item)) => foreign_item.span, Some(Node::TraitItem(trait_method)) => trait_method.span, @@ -1223,7 +1223,7 @@ impl<'hir> print::PpAnn for Map<'hir> { Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)), Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), Nested::Body(id) => state.print_expr(&self.body(id).value), - Nested::BodyArgPat(id, i) => state.print_pat(&self.body(id).arguments[i].pat) + Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat) } } } @@ -1231,7 +1231,7 @@ impl<'hir> print::PpAnn for Map<'hir> { impl<'a> print::State<'a> { pub fn print_node(&mut self, node: Node<'_>) { match node { - Node::Arg(a) => self.print_arg(&a), + Node::Param(a) => self.print_param(&a), Node::Item(a) => self.print_item(&a), Node::ForeignItem(a) => self.print_foreign_item(&a), Node::TraitItem(a) => self.print_trait_item(a), @@ -1373,8 +1373,8 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { Some(Node::Pat(_)) => { format!("pat {}{}", map.hir_to_pretty_string(id), id_str) } - Some(Node::Arg(_)) => { - format!("arg {}{}", map.hir_to_pretty_string(id), id_str) + Some(Node::Param(_)) => { + format!("param {}{}", map.hir_to_pretty_string(id), id_str) } Some(Node::Arm(_)) => { format!("arm {}{}", map.hir_to_pretty_string(id), id_str) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 983048188527f..d2c45a5af8598 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1030,7 +1030,7 @@ pub enum Mutability { } impl Mutability { - /// Returns `MutMutable` only if both arguments are mutable. + /// Returns `MutMutable` only if both `self` and `other` are mutable. pub fn and(self, other: Self) -> Self { match self { MutMutable => other, @@ -1324,7 +1324,7 @@ pub struct BodyId { /// /// Here, the `Body` associated with `foo()` would contain: /// -/// - an `arguments` array containing the `(x, y)` pattern +/// - an `params` array containing the `(x, y)` pattern /// - a `value` containing the `x + y` expression (maybe wrapped in a block) /// - `generator_kind` would be `None` /// @@ -1332,7 +1332,7 @@ pub struct BodyId { /// map using `body_owner_def_id()`. #[derive(RustcEncodable, RustcDecodable, Debug)] pub struct Body { - pub arguments: HirVec, + pub params: HirVec, pub value: Expr, pub generator_kind: Option, } @@ -1644,7 +1644,7 @@ pub enum LocalSource { /// A desugared `for _ in _ { .. }` loop. ForLoopDesugar, /// When lowering async functions, we create locals within the `async move` so that - /// all arguments are dropped after the future is polled. + /// all parameters are dropped after the future is polled. /// /// ```ignore (pseudo-Rust) /// async fn foo( @ x: Type) { @@ -1940,7 +1940,7 @@ pub struct BareFnTy { pub abi: Abi, pub generic_params: HirVec, pub decl: P, - pub arg_names: HirVec, + pub param_names: HirVec, } #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] @@ -2027,9 +2027,9 @@ pub struct InlineAsm { pub dialect: AsmDialect, } -/// Represents an argument in a function header. +/// Represents a parameter in a function header. #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] -pub struct Arg { +pub struct Param { pub attrs: HirVec, pub hir_id: HirId, pub pat: P, @@ -2039,9 +2039,9 @@ pub struct Arg { /// Represents the header (not the body) of a function declaration. #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct FnDecl { - /// The types of the function's arguments. + /// The types of the function's parameters. /// - /// Additional argument data is stored in the function's [body](Body::arguments). + /// Additional argument data is stored in the function's [body](Body::parameters). pub inputs: HirVec, pub output: FunctionRetTy, pub c_variadic: bool, @@ -2721,7 +2721,7 @@ impl CodegenFnAttrs { #[derive(Copy, Clone, Debug)] pub enum Node<'hir> { - Arg(&'hir Arg), + Param(&'hir Param), Item(&'hir Item), ForeignItem(&'hir ForeignItem), TraitItem(&'hir TraitItem), diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 632a13f9183b2..21cc72efee4a3 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -33,7 +33,7 @@ pub enum Nested { TraitItem(hir::TraitItemId), ImplItem(hir::ImplItemId), Body(hir::BodyId), - BodyArgPat(hir::BodyId, usize) + BodyParamPat(hir::BodyId, usize) } pub trait PpAnn { @@ -62,7 +62,7 @@ impl PpAnn for hir::Crate { Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)), Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), Nested::Body(id) => state.print_expr(&self.body(id).value), - Nested::BodyArgPat(id, i) => state.print_pat(&self.body(id).arguments[i].pat) + Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat) } } } @@ -318,7 +318,7 @@ impl<'a> State<'a> { } hir::TyKind::BareFn(ref f) => { self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &f.generic_params, - &f.arg_names[..]); + &f.param_names[..]); } hir::TyKind::Def(..) => {}, hir::TyKind::Path(ref qpath) => { @@ -1290,7 +1290,7 @@ impl<'a> State<'a> { hir::ExprKind::Closure(capture_clause, ref decl, body, _fn_decl_span, _gen) => { self.print_capture_clause(capture_clause); - self.print_closure_args(&decl, body); + self.print_closure_params(&decl, body); self.s.space(); // this is a bare expression @@ -1775,7 +1775,7 @@ impl<'a> State<'a> { self.ann.post(self, AnnNode::Pat(pat)) } - pub fn print_arg(&mut self, arg: &hir::Arg) { + pub fn print_param(&mut self, arg: &hir::Param) { self.print_outer_attributes(&arg.attrs); self.print_pat(&arg.pat); } @@ -1864,7 +1864,7 @@ impl<'a> State<'a> { s.s.word(":"); s.s.space(); } else if let Some(body_id) = body_id { - s.ann.nested(s, Nested::BodyArgPat(body_id, i)); + s.ann.nested(s, Nested::BodyParamPat(body_id, i)); s.s.word(":"); s.s.space(); } @@ -1881,13 +1881,13 @@ impl<'a> State<'a> { self.print_where_clause(&generics.where_clause) } - fn print_closure_args(&mut self, decl: &hir::FnDecl, body_id: hir::BodyId) { + fn print_closure_params(&mut self, decl: &hir::FnDecl, body_id: hir::BodyId) { self.s.word("|"); let mut i = 0; self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(INDENT_UNIT); - s.ann.nested(s, Nested::BodyArgPat(body_id, i)); + s.ann.nested(s, Nested::BodyParamPat(body_id, i)); i += 1; if let hir::TyKind::Infer = ty.node { diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 60b338010b0db..fb981d961129f 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -331,13 +331,13 @@ impl<'a> HashStable> for hir::Body { hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let hir::Body { - arguments, + params, value, generator_kind, } = self; hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| { - arguments.hash_stable(hcx, hasher); + params.hash_stable(hcx, hasher); value.hash_stable(hcx, hasher); generator_kind.hash_stable(hcx, hasher); }); diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 5e0f973fdd310..7068fe3601a62 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -78,12 +78,12 @@ impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> { } fn visit_body(&mut self, body: &'tcx Body) { - for argument in &body.arguments { + for param in &body.params { if let (None, Some(ty)) = ( self.found_arg_pattern, - self.node_matches_type(argument.hir_id), + self.node_matches_type(param.hir_id), ) { - self.found_arg_pattern = Some(&*argument.pat); + self.found_arg_pattern = Some(&*param.pat); self.found_ty = Some(ty); } } diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs index 6bd2c04d51281..979815fa7f184 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -2,7 +2,7 @@ //! where both the regions are anonymous. use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::infer::error_reporting::nice_region_error::util::AnonymousArgInfo; +use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo; use crate::util::common::ErrorReported; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { @@ -59,13 +59,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let ty_sub = self.find_anon_type(sub, &bregion_sub)?; debug!( - "try_report_anon_anon_conflict: found_arg1={:?} sup={:?} br1={:?}", + "try_report_anon_anon_conflict: found_param1={:?} sup={:?} br1={:?}", ty_sub, sup, bregion_sup ); debug!( - "try_report_anon_anon_conflict: found_arg2={:?} sub={:?} br2={:?}", + "try_report_anon_anon_conflict: found_param2={:?} sub={:?} br2={:?}", ty_sup, sub, bregion_sub @@ -74,24 +74,24 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let (ty_sup, ty_fndecl_sup) = ty_sup; let (ty_sub, ty_fndecl_sub) = ty_sub; - let AnonymousArgInfo { - arg: anon_arg_sup, .. - } = self.find_arg_with_region(sup, sup)?; - let AnonymousArgInfo { - arg: anon_arg_sub, .. - } = self.find_arg_with_region(sub, sub)?; + let AnonymousParamInfo { + param: anon_param_sup, .. + } = self.find_param_with_region(sup, sup)?; + let AnonymousParamInfo { + param: anon_param_sub, .. + } = self.find_param_with_region(sub, sub)?; let sup_is_ret_type = self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup); let sub_is_ret_type = self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub); - let span_label_var1 = match anon_arg_sup.pat.simple_ident() { + let span_label_var1 = match anon_param_sup.pat.simple_ident() { Some(simple_ident) => format!(" from `{}`", simple_ident), None => String::new(), }; - let span_label_var2 = match anon_arg_sub.pat.simple_ident() { + let span_label_var2 = match anon_param_sub.pat.simple_ident() { Some(simple_ident) => format!(" into `{}`", simple_ident), None => String::new(), }; diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 51bee49b70fc0..604115cfc3711 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -6,7 +6,7 @@ use crate::ty; use errors::{Applicability, DiagnosticBuilder}; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { - /// When given a `ConcreteFailure` for a function with arguments containing a named region and + /// When given a `ConcreteFailure` for a function with parameters containing a named region and /// an anonymous region, emit an descriptive diagnostic error. pub(super) fn try_report_named_anon_conflict(&self) -> Option> { let (span, sub, sup) = self.get_regions(); @@ -24,23 +24,23 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // only introduced anonymous regions in parameters) as well as a // version new_ty of its type where the anonymous region is replaced // with the named one.//scope_def_id - let (named, anon, anon_arg_info, region_info) = if self.is_named_region(sub) + let (named, anon, anon_param_info, region_info) = if self.is_named_region(sub) && self.tcx().is_suitable_region(sup).is_some() - && self.find_arg_with_region(sup, sub).is_some() + && self.find_param_with_region(sup, sub).is_some() { ( sub, sup, - self.find_arg_with_region(sup, sub).unwrap(), + self.find_param_with_region(sup, sub).unwrap(), self.tcx().is_suitable_region(sup).unwrap(), ) } else if self.is_named_region(sup) && self.tcx().is_suitable_region(sub).is_some() - && self.find_arg_with_region(sub, sup).is_some() + && self.find_param_with_region(sub, sup).is_some() { ( sup, sub, - self.find_arg_with_region(sub, sup).unwrap(), + self.find_param_with_region(sub, sup).unwrap(), self.tcx().is_suitable_region(sub).unwrap(), ) } else { @@ -49,20 +49,20 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { debug!("try_report_named_anon_conflict: named = {:?}", named); debug!( - "try_report_named_anon_conflict: anon_arg_info = {:?}", - anon_arg_info + "try_report_named_anon_conflict: anon_param_info = {:?}", + anon_param_info ); debug!( "try_report_named_anon_conflict: region_info = {:?}", region_info ); - let (arg, new_ty, new_ty_span, br, is_first, scope_def_id, is_impl_item) = ( - anon_arg_info.arg, - anon_arg_info.arg_ty, - anon_arg_info.arg_ty_span, - anon_arg_info.bound_region, - anon_arg_info.is_first, + let (param, new_ty, new_ty_span, br, is_first, scope_def_id, is_impl_item) = ( + anon_param_info.param, + anon_param_info.param_ty, + anon_param_info.param_ty_span, + anon_param_info.bound_region, + anon_param_info.is_first, region_info.def_id, region_info.is_impl_item, ); @@ -95,7 +95,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } } - let (error_var, span_label_var) = match arg.pat.simple_ident() { + let (error_var, span_label_var) = match param.pat.simple_ident() { Some(simple_ident) => ( format!("the type of `{}`", simple_ident), format!("the type of `{}`", simple_ident), diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs index f33f917392653..668c99da0034f 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs @@ -10,37 +10,37 @@ use syntax_pos::Span; // The struct contains the information about the anonymous region // we are searching for. #[derive(Debug)] -pub(super) struct AnonymousArgInfo<'tcx> { - // the argument corresponding to the anonymous region - pub arg: &'tcx hir::Arg, - // the type corresponding to the anonymopus region argument - pub arg_ty: Ty<'tcx>, +pub(super) struct AnonymousParamInfo<'tcx> { + // the parameter corresponding to the anonymous region + pub param: &'tcx hir::Param, + // the type corresponding to the anonymopus region parameter + pub param_ty: Ty<'tcx>, // the ty::BoundRegion corresponding to the anonymous region pub bound_region: ty::BoundRegion, - // arg_ty_span contains span of argument type - pub arg_ty_span : Span, + // param_ty_span contains span of parameter type + pub param_ty_span : Span, // corresponds to id the argument is the first parameter // in the declaration pub is_first: bool, } impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { - // This method walks the Type of the function body arguments using + // This method walks the Type of the function body parameters using // `fold_regions()` function and returns the - // &hir::Arg of the function argument corresponding to the anonymous + // &hir::Param of the function parameter corresponding to the anonymous // region and the Ty corresponding to the named region. // Currently only the case where the function declaration consists of // one named region and one anonymous region is handled. // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32` - // Here, we would return the hir::Arg for y, we return the type &'a + // Here, we would return the hir::Param for y, we return the type &'a // i32, which is the type of y but with the anonymous region replaced // with 'a, the corresponding bound region and is_first which is true if - // the hir::Arg is the first argument in the function declaration. - pub(super) fn find_arg_with_region( + // the hir::Param is the first parameter in the function declaration. + pub(super) fn find_param_with_region( &self, anon_region: Region<'tcx>, replace_region: Region<'tcx>, - ) -> Option> { + ) -> Option> { let (id, bound_region) = match *anon_region { ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region), ty::ReEarlyBound(ebr) => ( @@ -57,16 +57,16 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let owner_id = hir.body_owner(body_id); let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap(); if let Some(tables) = self.tables { - body.arguments + body.params .iter() .enumerate() - .filter_map(|(index, arg)| { + .filter_map(|(index, param)| { // May return None; sometimes the tables are not yet populated. let ty_hir_id = fn_decl.inputs[index].hir_id; - let arg_ty_span = hir.span(ty_hir_id); - let ty = tables.node_type_opt(arg.hir_id)?; + let param_ty_span = hir.span(ty_hir_id); + let ty = tables.node_type_opt(param.hir_id)?; let mut found_anon_region = false; - let new_arg_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| { + let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| { if *r == *anon_region { found_anon_region = true; replace_region @@ -76,10 +76,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }); if found_anon_region { let is_first = index == 0; - Some(AnonymousArgInfo { - arg: arg, - arg_ty: new_arg_ty, - arg_ty_span : arg_ty_span, + Some(AnonymousParamInfo { + param: param, + param_ty: new_param_ty, + param_ty_span : param_ty_span, bound_region: bound_region, is_first: is_first, }) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 8126db1429247..affda256322a4 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -966,10 +966,10 @@ for LateContextAndPass<'a, 'tcx, T> { self.context.tables = old_tables; } - fn visit_arg(&mut self, arg: &'tcx hir::Arg) { - self.with_lint_attrs(arg.hir_id, &arg.attrs, |cx| { - lint_callback!(cx, check_arg, arg); - hir_visit::walk_arg(cx, arg); + fn visit_param(&mut self, param: &'tcx hir::Param) { + self.with_lint_attrs(param.hir_id, ¶m.attrs, |cx| { + lint_callback!(cx, check_param, param); + hir_visit::walk_param(cx, param); }); } @@ -1163,10 +1163,10 @@ for LateContextAndPass<'a, 'tcx, T> { } impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> { - fn visit_arg(&mut self, arg: &'a ast::Arg) { - self.with_lint_attrs(arg.id, &arg.attrs, |cx| { - run_early_pass!(cx, check_arg, arg); - ast_visit::walk_arg(cx, arg); + fn visit_param(&mut self, param: &'a ast::Param) { + self.with_lint_attrs(param.id, ¶m.attrs, |cx| { + run_early_pass!(cx, check_param, param); + ast_visit::walk_param(cx, param); }); } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 7e2707b98d50a..a3518b2b478ad 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -206,7 +206,7 @@ macro_rules! declare_lint_pass { macro_rules! late_lint_methods { ($macro:path, $args:tt, [$hir:tt]) => ( $macro!($args, [$hir], [ - fn check_arg(a: &$hir hir::Arg); + fn check_param(a: &$hir hir::Param); fn check_body(a: &$hir hir::Body); fn check_body_post(a: &$hir hir::Body); fn check_name(a: Span, b: ast::Name); @@ -349,7 +349,7 @@ macro_rules! declare_combined_late_lint_pass { macro_rules! early_lint_methods { ($macro:path, $args:tt) => ( $macro!($args, [ - fn check_arg(a: &ast::Arg); + fn check_param(a: &ast::Param); fn check_ident(a: ast::Ident); fn check_crate(a: &ast::Crate); fn check_crate_post(a: &ast::Crate); @@ -792,9 +792,9 @@ impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> { intravisit::NestedVisitorMap::All(&self.tcx.hir()) } - fn visit_arg(&mut self, arg: &'tcx hir::Arg) { - self.with_lint_attrs(arg.hir_id, &arg.attrs, |builder| { - intravisit::walk_arg(builder, arg); + fn visit_param(&mut self, param: &'tcx hir::Param) { + self.with_lint_attrs(param.hir_id, ¶m.attrs, |builder| { + intravisit::walk_param(builder, param); }); } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index a274d7bbee5f7..222c2a405d65b 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -313,9 +313,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { pub fn consume_body(&mut self, body: &hir::Body) { debug!("consume_body(body={:?})", body); - for arg in &body.arguments { - let arg_ty = return_if_err!(self.mc.pat_ty_adjusted(&arg.pat)); - debug!("consume_body: arg_ty = {:?}", arg_ty); + for param in &body.params { + let param_ty = return_if_err!(self.mc.pat_ty_adjusted(¶m.pat)); + debug!("consume_body: param_ty = {:?}", param_ty); let fn_body_scope_r = self.tcx().mk_region(ty::ReScope( @@ -323,13 +323,13 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { id: body.value.hir_id.local_id, data: region::ScopeData::Node })); - let arg_cmt = Rc::new(self.mc.cat_rvalue( - arg.hir_id, - arg.pat.span, - fn_body_scope_r, // Args live only as long as the fn body. - arg_ty)); + let param_cmt = Rc::new(self.mc.cat_rvalue( + param.hir_id, + param.pat.span, + fn_body_scope_r, // Parameters live only as long as the fn body. + param_ty)); - self.walk_irrefutable_pat(arg_cmt, &arg.pat); + self.walk_irrefutable_pat(param_cmt, ¶m.pat); } self.consume_expr(&body.value); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 9c9e8c0bca3b8..00013bfc574f4 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -242,7 +242,7 @@ struct LocalInfo { #[derive(Copy, Clone, Debug)] enum VarKind { - Arg(HirId, ast::Name), + Param(HirId, ast::Name), Local(LocalInfo), CleanExit } @@ -298,7 +298,7 @@ impl IrMaps<'tcx> { self.num_vars += 1; match vk { - Local(LocalInfo { id: node_id, .. }) | Arg(node_id, _) => { + Local(LocalInfo { id: node_id, .. }) | Param(node_id, _) => { self.variable_map.insert(node_id, v); }, CleanExit => {} @@ -320,7 +320,7 @@ impl IrMaps<'tcx> { fn variable_name(&self, var: Variable) -> String { match self.var_kinds[var.get()] { - Local(LocalInfo { name, .. }) | Arg(_, name) => { + Local(LocalInfo { name, .. }) | Param(_, name) => { name.to_string() }, CleanExit => "".to_owned() @@ -330,7 +330,7 @@ impl IrMaps<'tcx> { fn variable_is_shorthand(&self, var: Variable) -> bool { match self.var_kinds[var.get()] { Local(LocalInfo { is_shorthand, .. }) => is_shorthand, - Arg(..) | CleanExit => false + Param(..) | CleanExit => false } } @@ -371,13 +371,13 @@ fn visit_fn<'tcx>( let body = ir.tcx.hir().body(body_id); - for arg in &body.arguments { - let is_shorthand = match arg.pat.node { + for param in &body.params { + let is_shorthand = match param.pat.node { crate::hir::PatKind::Struct(..) => true, _ => false, }; - arg.pat.each_binding(|_bm, hir_id, _x, ident| { - debug!("adding argument {:?}", hir_id); + param.pat.each_binding(|_bm, hir_id, _x, ident| { + debug!("adding parameters {:?}", hir_id); let var = if is_shorthand { Local(LocalInfo { id: hir_id, @@ -385,7 +385,7 @@ fn visit_fn<'tcx>( is_shorthand: true, }) } else { - Arg(hir_id, ident.name) + Param(hir_id, ident.name) }; fn_maps.add_variable(var); }) @@ -1525,8 +1525,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) { - for arg in &body.arguments { - arg.pat.each_binding(|_bm, hir_id, _, ident| { + for param in &body.params { + param.pat.each_binding(|_bm, hir_id, _, ident| { let sp = ident.span; let var = self.variable(hir_id, sp); // Ignore unused self. diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 3d100d2fbf833..28aa86ef9afb2 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -1383,8 +1383,8 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { // The arguments and `self` are parented to the fn. self.cx.var_parent = self.cx.parent.take(); - for argument in &body.arguments { - self.visit_pat(&argument.pat); + for param in &body.params { + self.visit_pat(¶m.pat); } // The body of the every fn is a root scope. diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index f5b0af61693be..8836a632a7ca8 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -2557,7 +2557,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } = info; let help_name = if let Some(ident) = parent.and_then(|body| { - self.tcx.hir().body(body).arguments[index].pat.simple_ident() + self.tcx.hir().body(body).params[index].pat.simple_ident() }) { format!("`{}`", ident) } else { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index ba92e851141a6..93742c83be440 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1044,7 +1044,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { node: hir::ExprKind::Closure(_, ref _decl, id, span, _), .. }) => { - (self.tcx.sess.source_map().def_span(span), self.tcx.hir().body(id).arguments.iter() + (self.tcx.sess.source_map().def_span(span), + self.tcx.hir().body(id).params.iter() .map(|arg| { if let hir::Pat { node: hir::PatKind::Tuple(ref args, _), diff --git a/src/librustc_ast_borrowck/dataflow.rs b/src/librustc_ast_borrowck/dataflow.rs index 94849728a9319..3a4c8c924764e 100644 --- a/src/librustc_ast_borrowck/dataflow.rs +++ b/src/librustc_ast_borrowck/dataflow.rs @@ -186,8 +186,8 @@ fn build_local_id_to_index(body: Option<&hir::Body>, index: &'a mut FxHashMap>, } let mut formals = Formals { entry: entry, index: index }; - for arg in &body.arguments { - formals.visit_pat(&arg.pat); + for param in &body.params { + formals.visit_pat(¶m.pat); } impl<'a, 'v> Visitor<'v> for Formals<'a> { fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 7aeeef00ea934..3fbd11bd22a7c 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -166,7 +166,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, // a `fn` when encoding, so the dep-tracking wouldn't work. // This is only used by rustdoc anyway, which shouldn't have // incremental recompilation ever enabled. - fn_arg_names => { cdata.get_fn_arg_names(def_id.index) } + fn_arg_names => { cdata.get_fn_param_names(def_id.index) } rendered_const => { cdata.get_rendered_const(def_id.index) } impl_parent => { cdata.get_parent_impl(def_id.index) } trait_of_item => { cdata.get_trait_of_item(def_id.index) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 5b9cb966af235..ede31fe69b6ff 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1150,14 +1150,14 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec { - let arg_names = match self.entry(id).kind { + pub fn get_fn_param_names(&self, id: DefIndex) -> Vec { + let param_names = match self.entry(id).kind { EntryKind::Fn(data) | - EntryKind::ForeignFn(data) => data.decode(self).arg_names, - EntryKind::Method(data) => data.decode(self).fn_data.arg_names, + EntryKind::ForeignFn(data) => data.decode(self).param_names, + EntryKind::Method(data) => data.decode(self).fn_data.param_names, _ => Lazy::empty(), }; - arg_names.decode(self).collect() + param_names.decode(self).collect() } pub fn exported_symbols( diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 1797d77461567..0eafcebefd745 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -869,18 +869,18 @@ impl EncodeContext<'tcx> { } ty::AssocKind::Method => { let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node { - let arg_names = match *m { + let param_names = match *m { hir::TraitMethod::Required(ref names) => { - self.encode_fn_arg_names(names) + self.encode_fn_param_names(names) } hir::TraitMethod::Provided(body) => { - self.encode_fn_arg_names_for_body(body) + self.encode_fn_param_names_for_body(body) } }; FnData { constness: hir::Constness::NotConst, - arg_names, - sig: self.lazy(tcx.fn_sig(def_id)), + param_names, + sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() @@ -976,8 +976,8 @@ impl EncodeContext<'tcx> { let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { FnData { constness: sig.header.constness, - arg_names: self.encode_fn_arg_names_for_body(body), - sig: self.lazy(tcx.fn_sig(def_id)), + param_names: self.encode_fn_param_names_for_body(body), + sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() @@ -1033,11 +1033,11 @@ impl EncodeContext<'tcx> { } } - fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId) + fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[ast::Name]> { self.tcx.dep_graph.with_ignore(|| { let body = self.tcx.hir().body(body_id); - self.lazy(body.arguments.iter().map(|arg| { + self.lazy(body.params.iter().map(|arg| { match arg.pat.node { PatKind::Binding(_, _, ident, _) => ident.name, _ => kw::Invalid, @@ -1046,7 +1046,7 @@ impl EncodeContext<'tcx> { }) } - fn encode_fn_arg_names(&mut self, param_names: &[ast::Ident]) -> Lazy<[ast::Name]> { + fn encode_fn_param_names(&mut self, param_names: &[ast::Ident]) -> Lazy<[ast::Name]> { self.lazy(param_names.iter().map(|ident| ident.name)) } @@ -1122,7 +1122,7 @@ impl EncodeContext<'tcx> { hir::ItemKind::Fn(_, header, .., body) => { let data = FnData { constness: header.constness, - arg_names: self.encode_fn_arg_names_for_body(body), + param_names: self.encode_fn_param_names_for_body(body), sig: self.lazy(tcx.fn_sig(def_id)), }; @@ -1663,7 +1663,7 @@ impl EncodeContext<'tcx> { hir::ForeignItemKind::Fn(_, ref names, _) => { let data = FnData { constness: hir::Constness::NotConst, - arg_names: self.encode_fn_arg_names(names), + param_names: self.encode_fn_param_names(names), sig: self.lazy(tcx.fn_sig(def_id)), }; EntryKind::ForeignFn(self.lazy(data)) diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 72a4b527c93d0..1a5887bbf4ed8 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -295,7 +295,7 @@ pub struct MacroDef { #[derive(RustcEncodable, RustcDecodable)] pub struct FnData<'tcx> { pub constness: hir::Constness, - pub arg_names: Lazy<[ast::Name]>, + pub param_names: Lazy<[ast::Name]>, pub sig: Lazy>, } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 61be17327ffda..7ab0bf7d66a64 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -94,7 +94,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { let body = tcx.hir().body(body_id); let explicit_arguments = - body.arguments + body.params .iter() .enumerate() .map(|(index, arg)| { @@ -511,7 +511,7 @@ fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, abi: Abi) -> bool { /////////////////////////////////////////////////////////////////////////// /// the main entry point for building MIR for a function -struct ArgInfo<'tcx>(Ty<'tcx>, Option, Option<&'tcx hir::Arg>, Option); +struct ArgInfo<'tcx>(Ty<'tcx>, Option, Option<&'tcx hir::Param>, Option); fn construct_fn<'a, 'tcx, A>( hir: Cx<'a, 'tcx>, diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 17fd9377a1629..5352888006c30 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -91,9 +91,9 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { fn visit_body(&mut self, body: &'tcx hir::Body) { intravisit::walk_body(self, body); - for arg in &body.arguments { - self.check_irrefutable(&arg.pat, "function argument"); - self.check_patterns(false, slice::from_ref(&arg.pat)); + for param in &body.params { + self.check_irrefutable(¶m.pat, "function argument"); + self.check_patterns(false, slice::from_ref(¶m.pat)); } } } diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index 7e03df5b75bdc..a5924efefc2af 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -94,9 +94,9 @@ impl<'k> StatCollector<'k> { } impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { - fn visit_arg(&mut self, arg: &'v hir::Arg) { - self.record("Arg", Id::Node(arg.hir_id), arg); - hir_visit::walk_arg(self, arg) + fn visit_param(&mut self, param: &'v hir::Param) { + self.record("Param", Id::Node(param.hir_id), param); + hir_visit::walk_param(self, param) } fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'v> { diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 9068605b0753c..d1fd51a97f683 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -230,7 +230,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { } } - fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) { + fn process_formals(&mut self, formals: &'l [ast::Param], qualname: &str) { for arg in formals { self.visit_pat(&arg.pat); let mut collector = PathCollector::new(); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 0bbbbb8249c20..92ccd4f49f6b9 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -32,7 +32,7 @@ use syntax::source_map::Spanned; use syntax::parse::lexer::comments::strip_doc_comment_decoration; use syntax::print::pprust; use syntax::visit::{self, Visitor}; -use syntax::print::pprust::{arg_to_string, ty_to_string}; +use syntax::print::pprust::{param_to_string, ty_to_string}; use syntax_pos::*; use dump_visitor::DumpVisitor; @@ -934,7 +934,7 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String { sig.push('('); sig.push_str(&decl.inputs .iter() - .map(arg_to_string) + .map(param_to_string) .collect::>() .join(", ")); sig.push(')'); diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 0efc433341c1f..63137bad52ff8 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -224,13 +224,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// fn takes_ref(_: &Foo) {} /// let ref opt = Some(Foo); /// - /// opt.map(|arg| takes_ref(arg)); + /// opt.map(|param| takes_ref(param)); /// ``` - /// Suggest using `opt.as_ref().map(|arg| takes_ref(arg));` instead. + /// Suggest using `opt.as_ref().map(|param| takes_ref(param));` instead. /// /// It only checks for `Option` and `Result` and won't work with /// ``` - /// opt.map(|arg| { takes_ref(arg) }); + /// opt.map(|param| { takes_ref(param) }); /// ``` fn can_use_as_ref( &self, @@ -247,13 +247,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let local_parent = self.tcx.hir().get_parent_node(local_id); - let arg_hir_id = match self.tcx.hir().find(local_parent) { - Some(Node::Arg(hir::Arg { hir_id, .. })) => hir_id, + let param_hir_id = match self.tcx.hir().find(local_parent) { + Some(Node::Param(hir::Param { hir_id, .. })) => hir_id, _ => return None }; - let arg_parent = self.tcx.hir().get_parent_node(*arg_hir_id); - let (expr_hir_id, closure_fn_decl) = match self.tcx.hir().find(arg_parent) { + let param_parent = self.tcx.hir().get_parent_node(*param_hir_id); + let (expr_hir_id, closure_fn_decl) = match self.tcx.hir().find(param_parent) { Some(Node::Expr( hir::Expr { hir_id, node: hir::ExprKind::Closure(_, decl, ..), .. } )) => (hir_id, decl), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c4dbe97a7bd96..2a3c422fe0438 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1102,19 +1102,19 @@ fn check_fn<'a, 'tcx>( GatherLocalsVisitor { fcx: &fcx, parent_id: outer_hir_id, }.visit_body(body); // Add formal parameters. - for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { + for (param_ty, param) in fn_sig.inputs().iter().zip(&body.params) { // Check the pattern. - fcx.check_pat_top(&arg.pat, arg_ty, None); + fcx.check_pat_top(¶m.pat, param_ty, None); // Check that argument is Sized. // The check for a non-trivial pattern is a hack to avoid duplicate warnings // for simple cases like `fn foo(x: Trait)`, // where we would error once on the parameter as a whole, and once on the binding `x`. - if arg.pat.simple_ident().is_none() && !fcx.tcx.features().unsized_locals { - fcx.require_type_is_sized(arg_ty, decl.output.span(), traits::SizedArgumentType); + if param.pat.simple_ident().is_none() && !fcx.tcx.features().unsized_locals { + fcx.require_type_is_sized(param_ty, decl.output.span(), traits::SizedArgumentType); } - fcx.write_ty(arg.hir_id, arg_ty); + fcx.write_ty(param.hir_id, param_ty); } inherited.tables.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig); @@ -3952,8 +3952,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .. })) => { let body = hir.body(*body_id); - sugg_call = body.arguments.iter() - .map(|arg| match &arg.pat.node { + sugg_call = body.params.iter() + .map(|param| match ¶m.pat.node { hir::PatKind::Binding(_, _, ident, None) if ident.name != kw::SelfLower => ident.to_string(), _ => "_".to_string(), @@ -3970,8 +3970,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(*closure_span, "closure defined here"); msg = "call this closure"; let body = hir.body(*body_id); - sugg_call = body.arguments.iter() - .map(|arg| match &arg.pat.node { + sugg_call = body.params.iter() + .map(|param| match ¶m.pat.node { hir::PatKind::Binding(_, _, ident, None) if ident.name != kw::SelfLower => ident.to_string(), _ => "_".to_string(), diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 3f6fc95360a5e..4cf0df308fb4c 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -468,7 +468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let binding_parent = tcx.hir().get(binding_parent_id); debug!("inner {:?} pat {:?} parent {:?}", inner, pat, binding_parent); match binding_parent { - hir::Node::Arg(hir::Arg { span, .. }) => { + hir::Node::Param(hir::Param { span, .. }) => { if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) { err.span_suggestion( *span, diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 3f9e662c6f412..fc01a820e2359 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -347,12 +347,12 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { ); self.outlives_environment .save_implied_bounds(body_id.hir_id); - self.link_fn_args( + self.link_fn_params( region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::Node, }, - &body.arguments, + &body.params, ); self.visit_body(body); self.visit_region_obligations(body_id.hir_id); @@ -1078,16 +1078,16 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { /// Computes the guarantors for any ref bindings in a match and /// then ensures that the lifetime of the resulting pointer is /// linked to the lifetime of its guarantor (if any). - fn link_fn_args(&self, body_scope: region::Scope, args: &[hir::Arg]) { - debug!("regionck::link_fn_args(body_scope={:?})", body_scope); - for arg in args { - let arg_ty = self.node_ty(arg.hir_id); + fn link_fn_params(&self, body_scope: region::Scope, params: &[hir::Param]) { + debug!("regionck::link_fn_params(body_scope={:?})", body_scope); + for param in params { + let param_ty = self.node_ty(param.hir_id); let re_scope = self.tcx.mk_region(ty::ReScope(body_scope)); - let arg_cmt = self.with_mc(|mc| { - Rc::new(mc.cat_rvalue(arg.hir_id, arg.pat.span, re_scope, arg_ty)) + let param_cmt = self.with_mc(|mc| { + Rc::new(mc.cat_rvalue(param.hir_id, param.pat.span, re_scope, param_ty)) }); - debug!("arg_ty={:?} arg_cmt={:?} arg={:?}", arg_ty, arg_cmt, arg); - self.link_pattern(arg_cmt, &arg.pat); + debug!("param_ty={:?} param_cmt={:?} param={:?}", param_ty, param_cmt, param); + self.link_pattern(param_cmt, ¶m.pat); } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index a88e32eb34dcd..487dc8ec2ae0c 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -39,8 +39,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let rustc_dump_user_substs = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_substs); let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_substs); - for arg in &body.arguments { - wbcx.visit_node_id(arg.pat.span, arg.hir_id); + for param in &body.params { + wbcx.visit_node_id(param.pat.span, param.hir_id); } // Type only exists for constants and statics, not functions. match self.tcx.hir().body_owner_kind(item_id) { @@ -245,8 +245,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { match e.node { hir::ExprKind::Closure(_, _, body, _, _) => { let body = self.fcx.tcx.hir().body(body); - for arg in &body.arguments { - self.visit_node_id(e.span, arg.hir_id); + for param in &body.params { + self.visit_node_id(e.span, param.hir_id); } self.visit_body(body); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ba792a413b3c4..629892e60727b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2120,7 +2120,7 @@ impl<'a> Clean for (&'a [hir::Ty], hir::BodyId) { Arguments { values: self.0.iter().enumerate().map(|(i, ty)| { Argument { - name: name_from_pat(&body.arguments[i].pat), + name: name_from_pat(&body.params[i].pat), type_: ty.clean(cx), } }).collect() @@ -3804,7 +3804,7 @@ pub struct BareFunctionDecl { impl Clean for hir::BareFnTy { fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl { let (generic_params, decl) = enter_impl_trait(cx, || { - (self.generic_params.clean(cx), (&*self.decl, &self.arg_names[..]).clean(cx)) + (self.generic_params.clean(cx), (&*self.decl, &self.param_names[..]).clean(cx)) }); BareFunctionDecl { unsafety: self.unsafety, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 50e428ea0cca6..6be00bcef45c0 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1789,11 +1789,11 @@ pub struct InlineAsm { pub dialect: AsmDialect, } -/// An argument in a function header. +/// A parameter in a function header. /// /// E.g., `bar: usize` as in `fn foo(bar: usize)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Arg { +pub struct Param { pub attrs: ThinVec, pub ty: P, pub pat: P, @@ -1816,7 +1816,7 @@ pub enum SelfKind { pub type ExplicitSelf = Spanned; -impl Arg { +impl Param { pub fn to_self(&self) -> Option { if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.node { if ident.name == kw::SelfLower { @@ -1843,14 +1843,14 @@ impl Arg { } } - pub fn from_self(attrs: ThinVec, eself: ExplicitSelf, eself_ident: Ident) -> Arg { + pub fn from_self(attrs: ThinVec, eself: ExplicitSelf, eself_ident: Ident) -> Param { let span = eself.span.to(eself_ident.span); let infer_ty = P(Ty { id: DUMMY_NODE_ID, node: TyKind::ImplicitSelf, span, }); - let arg = |mutbl, ty| Arg { + let param = |mutbl, ty| Param { attrs, pat: P(Pat { id: DUMMY_NODE_ID, @@ -1862,9 +1862,9 @@ impl Arg { id: DUMMY_NODE_ID, }; match eself.node { - SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty), - SelfKind::Value(mutbl) => arg(mutbl, infer_ty), - SelfKind::Region(lt, mutbl) => arg( + SelfKind::Explicit(ty, mutbl) => param(mutbl, ty), + SelfKind::Value(mutbl) => param(mutbl, infer_ty), + SelfKind::Region(lt, mutbl) => param( Mutability::Immutable, P(Ty { id: DUMMY_NODE_ID, @@ -1887,17 +1887,17 @@ impl Arg { /// E.g., `fn foo(bar: baz)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct FnDecl { - pub inputs: Vec, + pub inputs: Vec, pub output: FunctionRetTy, pub c_variadic: bool, } impl FnDecl { pub fn get_self(&self) -> Option { - self.inputs.get(0).and_then(Arg::to_self) + self.inputs.get(0).and_then(Param::to_self) } pub fn has_self(&self) -> bool { - self.inputs.get(0).map(Arg::is_self).unwrap_or(false) + self.inputs.get(0).map(Param::is_self).unwrap_or(false) } } diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index bcf03b5237a8d..0e5cfa73a9e3a 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -714,7 +714,7 @@ macro_rules! derive_has_attrs { derive_has_attrs! { Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm, - ast::Field, ast::FieldPat, ast::Variant, ast::Arg + ast::Field, ast::FieldPat, ast::Variant, ast::Param } pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index e2ac4d573a1e0..e894fd17ff587 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -655,7 +655,7 @@ impl<'a> ExtCtxt<'a> { body: P) -> P { let fn_decl = self.fn_decl( - ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(), + ids.iter().map(|id| self.param(span, *id, self.ty_infer(span))).collect(), ast::FunctionRetTy::Default(span)); // FIXME -- We are using `span` as the span of the `|...|` @@ -693,9 +693,9 @@ impl<'a> ExtCtxt<'a> { self.lambda1(span, self.expr_block(self.block(span, stmts)), ident) } - pub fn arg(&self, span: Span, ident: ast::Ident, ty: P) -> ast::Arg { + pub fn param(&self, span: Span, ident: ast::Ident, ty: P) -> ast::Param { let arg_pat = self.pat_ident(span, ident); - ast::Arg { + ast::Param { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat: arg_pat, @@ -705,7 +705,7 @@ impl<'a> ExtCtxt<'a> { } // FIXME: unused `self` - pub fn fn_decl(&self, inputs: Vec, output: ast::FunctionRetTy) -> P { + pub fn fn_decl(&self, inputs: Vec, output: ast::FunctionRetTy) -> P { P(ast::FnDecl { inputs, output, @@ -731,7 +731,7 @@ impl<'a> ExtCtxt<'a> { pub fn item_fn_poly(&self, span: Span, name: Ident, - inputs: Vec , + inputs: Vec , output: P, generics: Generics, body: P) -> P { @@ -752,7 +752,7 @@ impl<'a> ExtCtxt<'a> { pub fn item_fn(&self, span: Span, name: Ident, - inputs: Vec , + inputs: Vec , output: P, body: P ) -> P { diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 414d234e43419..e14ca4b06a09e 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -225,8 +225,8 @@ pub trait MutVisitor: Sized { noop_visit_attribute(at, self); } - fn flat_map_arg(&mut self, arg: Arg) -> SmallVec<[Arg; 1]> { - noop_flat_map_arg(arg, self) + fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> { + noop_flat_map_param(param, self) } fn visit_generics(&mut self, generics: &mut Generics) { @@ -587,14 +587,14 @@ pub fn noop_visit_meta_item(mi: &mut MetaItem, vis: &mut T) { vis.visit_span(span); } -pub fn noop_flat_map_arg(mut arg: Arg, vis: &mut T) -> SmallVec<[Arg; 1]> { - let Arg { attrs, id, pat, span, ty } = &mut arg; +pub fn noop_flat_map_param(mut param: Param, vis: &mut T) -> SmallVec<[Param; 1]> { + let Param { attrs, id, pat, span, ty } = &mut param; vis.visit_id(id); visit_thin_attrs(attrs, vis); vis.visit_pat(pat); vis.visit_span(span); vis.visit_ty(ty); - smallvec![arg] + smallvec![param] } pub fn noop_visit_tt(tt: &mut TokenTree, vis: &mut T) { @@ -720,7 +720,7 @@ pub fn noop_visit_asyncness(asyncness: &mut IsAsync, vis: &mut T) pub fn noop_visit_fn_decl(decl: &mut P, vis: &mut T) { let FnDecl { inputs, output, c_variadic: _ } = decl.deref_mut(); - inputs.flat_map_in_place(|arg| vis.flat_map_arg(arg)); + inputs.flat_map_in_place(|param| vis.flat_map_param(param)); match output { FunctionRetTy::Default(span) => vis.visit_span(span), FunctionRetTy::Ty(ty) => vis.visit_ty(ty), diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index c703058e7952d..671178223f503 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -19,7 +19,7 @@ const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ permitted in this context"; impl<'a> Parser<'a> { - crate fn parse_arg_attributes(&mut self) -> PResult<'a, Vec> { + crate fn parse_param_attributes(&mut self) -> PResult<'a, Vec> { let attrs = self.parse_outer_attributes()?; self.sess.gated_spans.param_attrs.borrow_mut() .extend(attrs.iter().map(|a| a.span)); diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 1fbf28fb83016..d4e661d1a38b7 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -1,5 +1,5 @@ use crate::ast::{ - self, Arg, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind, + self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, VariantData, }; use crate::feature_gate::{feature_err, UnstableFeatures}; @@ -18,7 +18,7 @@ use log::{debug, trace}; use std::mem; /// Creates a placeholder argument. -crate fn dummy_arg(ident: Ident) -> Arg { +crate fn dummy_arg(ident: Ident) -> Param { let pat = P(Pat { id: ast::DUMMY_NODE_ID, node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None), @@ -29,7 +29,7 @@ crate fn dummy_arg(ident: Ident) -> Arg { span: ident.span, id: ast::DUMMY_NODE_ID }; - Arg { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat, span: ident.span, ty: P(ty) } + Param { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat, span: ident.span, ty: P(ty) } } pub enum Error { @@ -1183,7 +1183,7 @@ impl<'a> Parser<'a> { Err(err) } - crate fn eat_incorrect_doc_comment_for_arg_type(&mut self) { + crate fn eat_incorrect_doc_comment_for_param_type(&mut self) { if let token::DocComment(_) = self.token.kind { self.struct_span_err( self.token.span, @@ -1211,7 +1211,7 @@ impl<'a> Parser<'a> { } } - crate fn argument_without_type( + crate fn parameter_without_type( &mut self, err: &mut DiagnosticBuilder<'_>, pat: P, @@ -1286,13 +1286,13 @@ impl<'a> Parser<'a> { Ok((pat, ty)) } - crate fn recover_bad_self_arg( + crate fn recover_bad_self_param( &mut self, - mut arg: ast::Arg, + mut param: ast::Param, is_trait_item: bool, - ) -> PResult<'a, ast::Arg> { - let sp = arg.pat.span; - arg.ty.node = TyKind::Err; + ) -> PResult<'a, ast::Param> { + let sp = param.pat.span; + param.ty.node = TyKind::Err; let mut err = self.struct_span_err(sp, "unexpected `self` parameter in function"); if is_trait_item { err.span_label(sp, "must be the first associated function parameter"); @@ -1301,7 +1301,7 @@ impl<'a> Parser<'a> { err.note("`self` is only valid as the first parameter of an associated function"); } err.emit(); - Ok(arg) + Ok(param) } crate fn consume_block(&mut self, delim: token::DelimToken) { @@ -1344,15 +1344,15 @@ impl<'a> Parser<'a> { err } - /// Replace duplicated recovered arguments with `_` pattern to avoid unecessary errors. + /// Replace duplicated recovered parameters with `_` pattern to avoid unecessary errors. /// /// This is necessary because at this point we don't know whether we parsed a function with - /// anonymous arguments or a function with names but no types. In order to minimize - /// unecessary errors, we assume the arguments are in the shape of `fn foo(a, b, c)` where - /// the arguments are *names* (so we don't emit errors about not being able to find `b` in + /// anonymous parameters or a function with names but no types. In order to minimize + /// unecessary errors, we assume the parameters are in the shape of `fn foo(a, b, c)` where + /// the parameters are *names* (so we don't emit errors about not being able to find `b` in /// the local scope), but if we find the same name multiple times, like in `fn foo(i8, i8)`, - /// we deduplicate them to not complain about duplicated argument names. - crate fn deduplicate_recovered_arg_names(&self, fn_inputs: &mut Vec) { + /// we deduplicate them to not complain about duplicated parameter names. + crate fn deduplicate_recovered_params_names(&self, fn_inputs: &mut Vec) { let mut seen_inputs = FxHashSet::default(); for input in fn_inputs.iter_mut() { let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err) = ( diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 25ad2d4404cac..bee47df942ae9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -10,7 +10,7 @@ pub use path::PathStyle; mod stmt; mod generics; -use crate::ast::{self, AttrStyle, Attribute, Arg, BindingMode, StrStyle, SelfKind}; +use crate::ast::{self, AttrStyle, Attribute, Param, BindingMode, StrStyle, SelfKind}; use crate::ast::{FnDecl, Ident, IsAsync, MacDelimiter, Mutability, TyKind}; use crate::ast::{Visibility, VisibilityKind, Unsafety, CrateSugar}; use crate::source_map::{self, respan}; @@ -970,27 +970,27 @@ impl<'a> Parser<'a> { /// Skips unexpected attributes and doc comments in this position and emits an appropriate /// error. - /// This version of parse arg doesn't necessarily require identifier names. - fn parse_arg_general( + /// This version of parse param doesn't necessarily require identifier names. + fn parse_param_general( &mut self, is_trait_item: bool, allow_c_variadic: bool, is_name_required: impl Fn(&token::Token) -> bool, - ) -> PResult<'a, Arg> { + ) -> PResult<'a, Param> { let lo = self.token.span; - let attrs = self.parse_arg_attributes()?; - if let Some(mut arg) = self.parse_self_arg()? { - arg.attrs = attrs.into(); - return self.recover_bad_self_arg(arg, is_trait_item); + let attrs = self.parse_param_attributes()?; + if let Some(mut param) = self.parse_self_param()? { + param.attrs = attrs.into(); + return self.recover_bad_self_param(param, is_trait_item); } let is_name_required = is_name_required(&self.token); let (pat, ty) = if is_name_required || self.is_named_argument() { - debug!("parse_arg_general parse_pat (is_name_required:{})", is_name_required); + debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); let pat = self.parse_fn_param_pat()?; if let Err(mut err) = self.expect(&token::Colon) { - if let Some(ident) = self.argument_without_type( + if let Some(ident) = self.parameter_without_type( &mut err, pat, is_name_required, @@ -1003,12 +1003,12 @@ impl<'a> Parser<'a> { } } - self.eat_incorrect_doc_comment_for_arg_type(); + self.eat_incorrect_doc_comment_for_param_type(); (pat, self.parse_ty_common(true, true, allow_c_variadic)?) } else { - debug!("parse_arg_general ident_to_pat"); + debug!("parse_param_general ident_to_pat"); let parser_snapshot_before_ty = self.clone(); - self.eat_incorrect_doc_comment_for_arg_type(); + self.eat_incorrect_doc_comment_for_param_type(); let mut ty = self.parse_ty_common(true, true, allow_c_variadic); if ty.is_ok() && self.token != token::Comma && self.token != token::CloseDelim(token::Paren) { @@ -1039,7 +1039,7 @@ impl<'a> Parser<'a> { let span = lo.to(self.token.span); - Ok(Arg { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, span, ty }) + Ok(Param { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, span, ty }) } /// Parses mutability (`mut` or nothing). @@ -1185,26 +1185,26 @@ impl<'a> Parser<'a> { } - fn parse_fn_args(&mut self, named_args: bool, allow_c_variadic: bool) - -> PResult<'a, (Vec , bool)> { + fn parse_fn_params(&mut self, named_params: bool, allow_c_variadic: bool) + -> PResult<'a, (Vec , bool)> { let sp = self.token.span; let mut c_variadic = false; - let (args, _): (Vec>, _) = self.parse_paren_comma_seq(|p| { + let (params, _): (Vec>, _) = self.parse_paren_comma_seq(|p| { let do_not_enforce_named_arguments_for_c_variadic = |token: &token::Token| -> bool { if token == &token::DotDotDot { false } else { - named_args + named_params } }; - match p.parse_arg_general( + match p.parse_param_general( false, allow_c_variadic, do_not_enforce_named_arguments_for_c_variadic ) { - Ok(arg) => { - if let TyKind::CVarArgs = arg.ty.node { + Ok(param) => { + if let TyKind::CVarArgs = param.ty.node { c_variadic = true; if p.token != token::CloseDelim(token::Paren) { let span = p.token.span; @@ -1212,10 +1212,10 @@ impl<'a> Parser<'a> { "`...` must be the last argument of a C-variadic function"); Ok(None) } else { - Ok(Some(arg)) + Ok(Some(param)) } } else { - Ok(Some(arg)) + Ok(Some(param)) } }, Err(mut e) => { @@ -1230,20 +1230,20 @@ impl<'a> Parser<'a> { } })?; - let args: Vec<_> = args.into_iter().filter_map(|x| x).collect(); + let params: Vec<_> = params.into_iter().filter_map(|x| x).collect(); - if c_variadic && args.len() <= 1 { + if c_variadic && params.len() <= 1 { self.span_err(sp, "C-variadic function must be declared with at least one named argument"); } - Ok((args, c_variadic)) + Ok((params, c_variadic)) } - /// Returns the parsed optional self argument and whether a self shortcut was used. + /// Returns the parsed optional self parameter and whether a self shortcut was used. /// - /// See `parse_self_arg_with_attrs` to collect attributes. - fn parse_self_arg(&mut self) -> PResult<'a, Option> { + /// See `parse_self_param_with_attrs` to collect attributes. + fn parse_self_param(&mut self) -> PResult<'a, Option> { let expect_ident = |this: &mut Self| match this.token.kind { // Preserve hygienic context. token::Ident(name, _) => @@ -1348,49 +1348,51 @@ impl<'a> Parser<'a> { }; let eself = source_map::respan(eself_lo.to(eself_hi), eself); - Ok(Some(Arg::from_self(ThinVec::default(), eself, eself_ident))) + Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident))) } - /// Returns the parsed optional self argument with attributes and whether a self + /// Returns the parsed optional self parameter with attributes and whether a self /// shortcut was used. - fn parse_self_arg_with_attrs(&mut self) -> PResult<'a, Option> { - let attrs = self.parse_arg_attributes()?; - let arg_opt = self.parse_self_arg()?; - Ok(arg_opt.map(|mut arg| { - arg.attrs = attrs.into(); - arg + fn parse_self_parameter_with_attrs(&mut self) -> PResult<'a, Option> { + let attrs = self.parse_param_attributes()?; + let param_opt = self.parse_self_param()?; + Ok(param_opt.map(|mut param| { + param.attrs = attrs.into(); + param })) } /// Parses the parameter list and result type of a function that may have a `self` parameter. - fn parse_fn_decl_with_self(&mut self, parse_arg_fn: F) -> PResult<'a, P> - where F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>, + fn parse_fn_decl_with_self(&mut self, parse_param_fn: F) -> PResult<'a, P> + where F: FnMut(&mut Parser<'a>) -> PResult<'a, Param>, { self.expect(&token::OpenDelim(token::Paren))?; // Parse optional self argument. - let self_arg = self.parse_self_arg_with_attrs()?; + let self_param = self.parse_self_parameter_with_attrs()?; // Parse the rest of the function parameter list. let sep = SeqSep::trailing_allowed(token::Comma); - let (mut fn_inputs, recovered) = if let Some(self_arg) = self_arg { + let (mut fn_inputs, recovered) = if let Some(self_param) = self_param { if self.check(&token::CloseDelim(token::Paren)) { - (vec![self_arg], false) + (vec![self_param], false) } else if self.eat(&token::Comma) { - let mut fn_inputs = vec![self_arg]; + let mut fn_inputs = vec![self_param]; let (mut input, _, recovered) = self.parse_seq_to_before_end( - &token::CloseDelim(token::Paren), sep, parse_arg_fn)?; + &token::CloseDelim(token::Paren), sep, parse_param_fn)?; fn_inputs.append(&mut input); (fn_inputs, recovered) } else { match self.expect_one_of(&[], &[]) { Err(err) => return Err(err), - Ok(recovered) => (vec![self_arg], recovered), + Ok(recovered) => (vec![self_param], recovered), } } } else { let (input, _, recovered) = - self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)?; + self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), + sep, + parse_param_fn)?; (input, recovered) }; @@ -1398,8 +1400,8 @@ impl<'a> Parser<'a> { // Parse closing paren and return type. self.expect(&token::CloseDelim(token::Paren))?; } - // Replace duplicated recovered arguments with `_` pattern to avoid unecessary errors. - self.deduplicate_recovered_arg_names(&mut fn_inputs); + // Replace duplicated recovered params with `_` pattern to avoid unecessary errors. + self.deduplicate_recovered_params_names(&mut fn_inputs); Ok(P(FnDecl { inputs: fn_inputs, diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index f7c090b5135e9..5b9f0f1df6718 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -7,7 +7,7 @@ use crate::maybe_recover_from_interpolated_ty_qpath; use crate::ptr::P; use crate::ast::{self, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode}; use crate::ast::{Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm}; -use crate::ast::{Ty, TyKind, FunctionRetTy, Arg, FnDecl}; +use crate::ast::{Ty, TyKind, FunctionRetTy, Param, FnDecl}; use crate::ast::{BinOpKind, BinOp, UnOp}; use crate::ast::{Mac, AnonConst, Field}; @@ -1157,7 +1157,7 @@ impl<'a> Parser<'a> { &[&token::BinOp(token::Or), &token::OrOr], SeqSep::trailing_allowed(token::Comma), TokenExpectType::NoExpect, - |p| p.parse_fn_block_arg() + |p| p.parse_fn_block_param() )?.0; self.expect_or()?; args @@ -1172,10 +1172,10 @@ impl<'a> Parser<'a> { })) } - /// Parses an argument in a lambda header (e.g., `|arg, arg|`). - fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> { + /// Parses a parameter in a lambda header (e.g., `|arg, arg|`). + fn parse_fn_block_param(&mut self) -> PResult<'a, Param> { let lo = self.token.span; - let attrs = self.parse_arg_attributes()?; + let attrs = self.parse_param_attributes()?; let pat = self.parse_pat(PARAM_EXPECTED)?; let t = if self.eat(&token::Colon) { self.parse_ty()? @@ -1187,7 +1187,7 @@ impl<'a> Parser<'a> { }) }; let span = lo.to(self.token.span); - Ok(Arg { + Ok(Param { attrs: attrs.into(), ty: t, pat, diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 03d7e92212382..59a3ade9c30e5 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -422,7 +422,7 @@ impl<'a> Parser<'a> { } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { let ident = self.parse_ident().unwrap(); self.bump(); // `(` - let kw_name = if let Ok(Some(_)) = self.parse_self_arg_with_attrs() + let kw_name = if let Ok(Some(_)) = self.parse_self_parameter_with_attrs() .map_err(|mut e| e.cancel()) { "method" @@ -475,7 +475,7 @@ impl<'a> Parser<'a> { self.eat_to_tokens(&[&token::Gt]); self.bump(); // `>` let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) { - if let Ok(Some(_)) = self.parse_self_arg_with_attrs() + if let Ok(Some(_)) = self.parse_self_parameter_with_attrs() .map_err(|mut e| e.cancel()) { ("fn", "method", false) @@ -861,7 +861,7 @@ impl<'a> Parser<'a> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; let decl = self.parse_fn_decl_with_self(|p| { - p.parse_arg_general(true, false, |_| true) + p.parse_param_general(true, false, |_| true) })?; generics.where_clause = self.parse_where_clause()?; *at_end = true; @@ -1040,7 +1040,7 @@ impl<'a> Parser<'a> { // We don't allow argument names to be left off in edition 2018. let is_name_required = p.token.span.rust_2018(); - p.parse_arg_general(true, false, |_| is_name_required) + p.parse_param_general(true, false, |_| is_name_required) })?; generics.where_clause = self.parse_where_clause()?; @@ -1291,7 +1291,7 @@ impl<'a> Parser<'a> { /// Parses the argument list and result type of a function declaration. fn parse_fn_decl(&mut self, allow_c_variadic: bool) -> PResult<'a, P> { - let (args, c_variadic) = self.parse_fn_args(true, allow_c_variadic)?; + let (args, c_variadic) = self.parse_fn_params(true, allow_c_variadic)?; let ret_ty = self.parse_ret_ty(true)?; Ok(P(FnDecl { diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs index 337702b8d30c5..465e31ac57e64 100644 --- a/src/libsyntax/parse/parser/ty.rs +++ b/src/libsyntax/parse/parser/ty.rs @@ -292,7 +292,7 @@ impl<'a> Parser<'a> { }; self.expect_keyword(kw::Fn)?; - let (inputs, c_variadic) = self.parse_fn_args(false, true)?; + let (inputs, c_variadic) = self.parse_fn_params(false, true)?; let ret_ty = self.parse_ret_ty(false)?; let decl = P(FnDecl { inputs, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 83a926a6217e7..bead941b20d5a 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -418,8 +418,8 @@ pub fn attribute_to_string(attr: &ast::Attribute) -> String { to_string(|s| s.print_attribute(attr)) } -pub fn arg_to_string(arg: &ast::Arg) -> String { - to_string(|s| s.print_arg(arg, false)) +pub fn param_to_string(arg: &ast::Param) -> String { + to_string(|s| s.print_param(arg, false)) } fn foreign_item_to_string(arg: &ast::ForeignItem) -> String { @@ -2101,7 +2101,7 @@ impl<'a> State<'a> { self.print_asyncness(asyncness); self.print_capture_clause(capture_clause); - self.print_fn_block_args(decl); + self.print_fn_block_params(decl); self.s.space(); self.print_expr(body); self.end(); // need to close a box @@ -2536,21 +2536,21 @@ impl<'a> State<'a> { self.print_ident(name); } self.print_generic_params(&generics.params); - self.print_fn_args_and_ret(decl); + self.print_fn_params_and_ret(decl); self.print_where_clause(&generics.where_clause) } - crate fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl) { + crate fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl) { self.popen(); - self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false)); + self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, false)); self.pclose(); self.print_fn_output(decl) } - crate fn print_fn_block_args(&mut self, decl: &ast::FnDecl) { + crate fn print_fn_block_params(&mut self, decl: &ast::FnDecl) { self.s.word("|"); - self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true)); + self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, true)); self.s.word("|"); if let ast::FunctionRetTy::Default(..) = decl.output { @@ -2759,7 +2759,7 @@ impl<'a> State<'a> { self.print_type(&mt.ty) } - crate fn print_arg(&mut self, input: &ast::Arg, is_closure: bool) { + crate fn print_param(&mut self, input: &ast::Param, is_closure: bool) { self.ibox(INDENT_UNIT); self.print_outer_attributes_inline(&input.attrs); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 86f6d36c3c6ba..ce1568316f8d4 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -66,7 +66,7 @@ pub trait Visitor<'ast>: Sized { fn visit_local(&mut self, l: &'ast Local) { walk_local(self, l) } fn visit_block(&mut self, b: &'ast Block) { walk_block(self, b) } fn visit_stmt(&mut self, s: &'ast Stmt) { walk_stmt(self, s) } - fn visit_arg(&mut self, arg: &'ast Arg) { walk_arg(self, arg) } + fn visit_param(&mut self, param: &'ast Param) { walk_param(self, param) } fn visit_arm(&mut self, a: &'ast Arm) { walk_arm(self, a) } fn visit_pat(&mut self, p: &'ast Pat) { walk_pat(self, p) } fn visit_anon_const(&mut self, c: &'ast AnonConst) { walk_anon_const(self, c) } @@ -555,8 +555,8 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionR } pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) { - for arg in &function_declaration.inputs { - visitor.visit_arg(arg); + for param in &function_declaration.inputs { + visitor.visit_param(param); } visitor.visit_fn_ret_ty(&function_declaration.output); } @@ -824,10 +824,10 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_expr_post(expression) } -pub fn walk_arg<'a, V: Visitor<'a>>(visitor: &mut V, arg: &'a Arg) { - walk_list!(visitor, visit_attribute, arg.attrs.iter()); - visitor.visit_pat(&arg.pat); - visitor.visit_ty(&arg.ty); +pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) { + walk_list!(visitor, visit_attribute, param.attrs.iter()); + visitor.visit_pat(¶m.pat); + visitor.visit_ty(¶m.ty); } pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) { diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 1475bac068846..6fd763f5a9100 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -929,10 +929,10 @@ impl<'a> MethodDef<'a> { let args = { let self_args = explicit_self.map(|explicit_self| { let ident = Ident::with_dummy_span(kw::SelfLower).with_span_pos(trait_.span); - ast::Arg::from_self(ThinVec::default(), explicit_self, ident) + ast::Param::from_self(ThinVec::default(), explicit_self, ident) }); let nonself_args = arg_types.into_iter() - .map(|(name, ty)| cx.arg(trait_.span, name, ty)); + .map(|(name, ty)| cx.param(trait_.span, name, ty)); self_args.into_iter().chain(nonself_args).collect() }; diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs index 97b8087ad1581..f4af1699cd683 100644 --- a/src/libsyntax_ext/global_allocator.rs +++ b/src/libsyntax_ext/global_allocator.rs @@ -1,5 +1,5 @@ use syntax::ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafety}; -use syntax::ast::{self, Arg, Attribute, Expr, FnHeader, Generics, Ident}; +use syntax::ast::{self, Param, Attribute, Expr, FnHeader, Generics, Ident}; use syntax::attr::check_builtin_macro_attribute; use syntax::ext::allocator::{AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS}; use syntax::ext::base::{Annotatable, ExtCtxt}; @@ -114,7 +114,7 @@ impl AllocFnFactory<'_, '_> { fn arg_ty( &self, ty: &AllocatorTy, - args: &mut Vec, + args: &mut Vec, ident: &mut dyn FnMut() -> Ident, ) -> P { match *ty { @@ -123,8 +123,8 @@ impl AllocFnFactory<'_, '_> { let ty_usize = self.cx.ty_path(usize); let size = ident(); let align = ident(); - args.push(self.cx.arg(self.span, size, ty_usize.clone())); - args.push(self.cx.arg(self.span, align, ty_usize)); + args.push(self.cx.param(self.span, size, ty_usize.clone())); + args.push(self.cx.param(self.span, align, ty_usize)); let layout_new = self.cx.std_path(&[ Symbol::intern("alloc"), @@ -140,14 +140,14 @@ impl AllocFnFactory<'_, '_> { AllocatorTy::Ptr => { let ident = ident(); - args.push(self.cx.arg(self.span, ident, self.ptr_u8())); + args.push(self.cx.param(self.span, ident, self.ptr_u8())); let arg = self.cx.expr_ident(self.span, ident); self.cx.expr_cast(self.span, arg, self.ptr_u8()) } AllocatorTy::Usize => { let ident = ident(); - args.push(self.cx.arg(self.span, ident, self.usize())); + args.push(self.cx.param(self.span, ident, self.usize())); self.cx.expr_ident(self.span, ident) } diff --git a/src/test/ui/async-await/no-args-non-move-async-closure.rs b/src/test/ui/async-await/no-args-non-move-async-closure.rs index 0ca50807f2626..3b15f35c260dc 100644 --- a/src/test/ui/async-await/no-args-non-move-async-closure.rs +++ b/src/test/ui/async-await/no-args-non-move-async-closure.rs @@ -4,5 +4,5 @@ fn main() { let _ = async |x: u8| {}; - //~^ ERROR `async` non-`move` closures with arguments are not currently supported + //~^ ERROR `async` non-`move` closures with parameters are not currently supported } diff --git a/src/test/ui/async-await/no-args-non-move-async-closure.stderr b/src/test/ui/async-await/no-args-non-move-async-closure.stderr index 1b4b86210f840..c58210b997b66 100644 --- a/src/test/ui/async-await/no-args-non-move-async-closure.stderr +++ b/src/test/ui/async-await/no-args-non-move-async-closure.stderr @@ -1,4 +1,4 @@ -error[E0708]: `async` non-`move` closures with arguments are not currently supported +error[E0708]: `async` non-`move` closures with parameters are not currently supported --> $DIR/no-args-non-move-async-closure.rs:6:13 | LL | let _ = async |x: u8| {}; diff --git a/src/test/ui/generator/no-arguments-on-generators.rs b/src/test/ui/generator/no-arguments-on-generators.rs index 344c1179be90e..a2632a4bd7d84 100644 --- a/src/test/ui/generator/no-arguments-on-generators.rs +++ b/src/test/ui/generator/no-arguments-on-generators.rs @@ -1,7 +1,7 @@ #![feature(generators)] fn main() { - let gen = |start| { //~ ERROR generators cannot have explicit arguments + let gen = |start| { //~ ERROR generators cannot have explicit parameters yield; }; } diff --git a/src/test/ui/generator/no-arguments-on-generators.stderr b/src/test/ui/generator/no-arguments-on-generators.stderr index 23ae21585fd38..8f993b27ce236 100644 --- a/src/test/ui/generator/no-arguments-on-generators.stderr +++ b/src/test/ui/generator/no-arguments-on-generators.stderr @@ -1,4 +1,4 @@ -error[E0628]: generators cannot have explicit arguments +error[E0628]: generators cannot have explicit parameters --> $DIR/no-arguments-on-generators.rs:4:15 | LL | let gen = |start| { From 98ad4ac2506e543111559ec5064cc1bd58349342 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Aug 2019 15:49:47 +0200 Subject: [PATCH 281/618] update miri --- Cargo.lock | 1 + src/tools/miri | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 8ae21c8663706..dffd496c7d9e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1992,6 +1992,7 @@ dependencies = [ "compiletest_rs", "directories", "env_logger 0.6.0", + "getrandom", "hex", "log", "num-traits", diff --git a/src/tools/miri b/src/tools/miri index d77fe6c63ca4c..69268fb75fdb4 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit d77fe6c63ca4c50b207a1161def90c9e57368d5b +Subproject commit 69268fb75fdb452296caa9bc4aaeff1674279de2 From 935c1c86070dfac3515a4296bf991cdf544bae27 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Tue, 27 Aug 2019 09:37:51 +0200 Subject: [PATCH 282/618] rustbuild: allow disabling deny(warnings) for bootstrap When deny-warnings is not specified or set to true, the behaviour is the same as before. When deny-warnings is set to false, warnings are now allowed Fixes #63911 Signed-off-by: Marc-Antoine Perennou --- src/bootstrap/bin/main.rs | 3 --- src/bootstrap/bin/rustc.rs | 8 +++----- src/bootstrap/bin/rustdoc.rs | 3 --- src/bootstrap/bootstrap.py | 2 ++ src/bootstrap/lib.rs | 3 --- src/build_helper/lib.rs | 3 --- 6 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index bd1a87c5744d3..138b7f4b26104 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -5,9 +5,6 @@ //! parent directory, and otherwise documentation can be found throughout the `build` //! directory in each respective module. -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - use std::env; use bootstrap::{Config, Build}; diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index ce92ce0269671..8cb48df14bfef 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -15,9 +15,6 @@ //! switching compilers for the bootstrap and for build scripts will probably //! never get replaced. -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - use std::env; use std::ffi::OsString; use std::io; @@ -124,8 +121,9 @@ fn main() { if env::var_os("RUSTC_DENY_WARNINGS").is_some() && env::var_os("RUSTC_EXTERNAL_TOOL").is_none() { - // When extending this list, search for `NO-RUSTC-WRAPPER` and add the new lints - // there as well, some code doesn't go through this `rustc` wrapper. + // When extending this list, add the new lints to the RUSTFLAGS of the + // build_bootstrap function of src/bootstrap/bootstrap.py as well as + // some code doesn't go through this `rustc` wrapper. cmd.arg("-Dwarnings"); cmd.arg("-Drust_2018_idioms"); cmd.arg("-Dunused_lifetimes"); diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index ff38ee8788f56..766a3463ecd8b 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -2,9 +2,6 @@ //! //! See comments in `src/bootstrap/rustc.rs` for more information. -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - use std::env; use std::process::Command; use std::path::PathBuf; diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 86901792d7974..3c56131396f29 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -631,6 +631,8 @@ def build_bootstrap(self): target_linker = self.get_toml("linker", build_section) if target_linker is not None: env["RUSTFLAGS"] += "-C linker=" + target_linker + " " + if self.get_toml("deny-warnings", "rust") != "false": + env["RUSTFLAGS"] += "-Dwarnings -Drust_2018_idioms -Dunused_lifetimes " env["PATH"] = os.path.join(self.bin_root(), "bin") + \ os.pathsep + env["PATH"] diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index c0e0ad1a857b9..575844028d562 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -103,9 +103,6 @@ //! More documentation can be found in each respective module below, and you can //! also check out the `src/bootstrap/README.md` file for more information. -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - #![feature(core_intrinsics)] #![feature(drain_filter)] diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 131d2034675e3..f035a7119188a 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -1,6 +1,3 @@ -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - use std::fs::File; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; From 97319b2b952c32ac1f0b36a834615b60b0376797 Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Tue, 27 Aug 2019 15:47:41 +0200 Subject: [PATCH 283/618] Changing error messages and renaming tests #63127 `async-await/no-args-non-move-async-closure` `generator/no-arguments-on-generators` --- src/librustc/error_codes.rs | 4 ++-- src/librustc/hir/lowering/expr.rs | 4 ++-- ...e-async-closure.rs => no-params-non-move-async-closure.rs} | 0 ...closure.stderr => no-params-non-move-async-closure.stderr} | 2 +- ...uments-on-generators.rs => no-parameters-on-generators.rs} | 0 ...n-generators.stderr => no-parameters-on-generators.stderr} | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename src/test/ui/async-await/{no-args-non-move-async-closure.rs => no-params-non-move-async-closure.rs} (100%) rename src/test/ui/async-await/{no-args-non-move-async-closure.stderr => no-params-non-move-async-closure.stderr} (86%) rename src/test/ui/generator/{no-arguments-on-generators.rs => no-parameters-on-generators.rs} (100%) rename src/test/ui/generator/{no-arguments-on-generators.stderr => no-parameters-on-generators.stderr} (77%) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index a200a058f4f99..2d09013f675a7 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2231,7 +2231,7 @@ register_diagnostics! { E0495, // cannot infer an appropriate lifetime due to conflicting requirements E0566, // conflicting representation hints E0623, // lifetime mismatch where both parameters are anonymous regions - E0628, // generators cannot have explicit arguments + E0628, // generators cannot have explicit parameters E0631, // type mismatch in closure arguments E0637, // "'_" is not a valid lifetime bound E0657, // `impl Trait` can only capture lifetimes bound at the fn level @@ -2239,7 +2239,7 @@ register_diagnostics! { E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders E0697, // closures cannot be static E0707, // multiple elided lifetimes used in arguments of `async fn` - E0708, // `async` non-`move` closures with arguments are not currently supported + E0708, // `async` non-`move` closures with parameters are not currently supported E0709, // multiple different lifetimes used in arguments of `async fn` E0710, // an unknown tool name found in scoped lint E0711, // a feature has been declared with conflicting stability attributes diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index ff0c44a23874b..bd217831faabf 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -724,7 +724,7 @@ impl LoweringContext<'_> { self.sess, fn_decl_span, E0628, - "generators cannot have explicit arguments" + "generators cannot have explicit parameters" ); self.sess.abort_if_errors(); } @@ -775,7 +775,7 @@ impl LoweringContext<'_> { this.sess, fn_decl_span, E0708, - "`async` non-`move` closures with arguments are not currently supported", + "`async` non-`move` closures with parameters are not currently supported", ) .help( "consider using `let` statements to manually capture \ diff --git a/src/test/ui/async-await/no-args-non-move-async-closure.rs b/src/test/ui/async-await/no-params-non-move-async-closure.rs similarity index 100% rename from src/test/ui/async-await/no-args-non-move-async-closure.rs rename to src/test/ui/async-await/no-params-non-move-async-closure.rs diff --git a/src/test/ui/async-await/no-args-non-move-async-closure.stderr b/src/test/ui/async-await/no-params-non-move-async-closure.stderr similarity index 86% rename from src/test/ui/async-await/no-args-non-move-async-closure.stderr rename to src/test/ui/async-await/no-params-non-move-async-closure.stderr index c58210b997b66..04c8c325fe7da 100644 --- a/src/test/ui/async-await/no-args-non-move-async-closure.stderr +++ b/src/test/ui/async-await/no-params-non-move-async-closure.stderr @@ -1,5 +1,5 @@ error[E0708]: `async` non-`move` closures with parameters are not currently supported - --> $DIR/no-args-non-move-async-closure.rs:6:13 + --> $DIR/no-params-non-move-async-closure.rs:6:13 | LL | let _ = async |x: u8| {}; | ^^^^^^^^^^^^^ diff --git a/src/test/ui/generator/no-arguments-on-generators.rs b/src/test/ui/generator/no-parameters-on-generators.rs similarity index 100% rename from src/test/ui/generator/no-arguments-on-generators.rs rename to src/test/ui/generator/no-parameters-on-generators.rs diff --git a/src/test/ui/generator/no-arguments-on-generators.stderr b/src/test/ui/generator/no-parameters-on-generators.stderr similarity index 77% rename from src/test/ui/generator/no-arguments-on-generators.stderr rename to src/test/ui/generator/no-parameters-on-generators.stderr index 8f993b27ce236..41862f2b0704b 100644 --- a/src/test/ui/generator/no-arguments-on-generators.stderr +++ b/src/test/ui/generator/no-parameters-on-generators.stderr @@ -1,5 +1,5 @@ error[E0628]: generators cannot have explicit parameters - --> $DIR/no-arguments-on-generators.rs:4:15 + --> $DIR/no-parameters-on-generators.rs:4:15 | LL | let gen = |start| { | ^^^^^^^ From 661141f8082f4ecde1e391799523ad3c566754b5 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 28 Aug 2019 00:32:21 +0900 Subject: [PATCH 284/618] Fix build src/libtest --- src/bootstrap/check.rs | 2 +- src/bootstrap/compile.rs | 2 +- src/bootstrap/doc.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index e9a9b7881a068..205a80c3a3a9e 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -34,7 +34,7 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("std") + run.all_krates("test") } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 7dad146b48d83..9d57a4f00d780 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -39,7 +39,7 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("std") + run.all_krates("test") } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 6805474aa049f..3d0a175e8206c 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -413,7 +413,7 @@ impl Step for Std { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.all_krates("std").default_condition(builder.config.docs) + run.all_krates("test").default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { From c9bf5c0bffef595136b484b0282ade18894cf5af Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Wed, 28 Aug 2019 00:45:29 +0800 Subject: [PATCH 285/618] bootstrap: allow specifying mirror for bootstrap compiler download. --- src/bootstrap/bootstrap.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 86901792d7974..c9f5d299a61c9 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -320,7 +320,7 @@ class RustBuild(object): def __init__(self): self.cargo_channel = '' self.date = '' - self._download_url = 'https://static.rust-lang.org' + self._download_url = '' self.rustc_channel = '' self.build = '' self.build_dir = os.path.join(os.getcwd(), "build") @@ -731,9 +731,19 @@ def update_submodules(self): self.update_submodule(module[0], module[1], recorded_submodules) print("Submodules updated in %.2f seconds" % (time() - start_time)) + def set_normal_environment(self): + """Set download URL for normal environment""" + if 'RUSTUP_DIST_SERVER' in os.environ: + self._download_url = os.environ['RUSTUP_DIST_SERVER'] + else: + self._download_url = 'https://static.rust-lang.org' + def set_dev_environment(self): """Set download URL for development environment""" - self._download_url = 'https://dev-static.rust-lang.org' + if 'RUSTUP_DEV_DIST_SERVER' in os.environ: + self._download_url = os.environ['RUSTUP_DEV_DIST_SERVER'] + else: + self._download_url = 'https://dev-static.rust-lang.org' def check_vendored_status(self): """Check that vendoring is configured properly""" @@ -826,6 +836,8 @@ def bootstrap(help_triggered): if 'dev' in data: build.set_dev_environment() + else: + build.set_normal_environment() build.update_submodules() From 3b2c14736d6d8fc44cf60588ed41a67eaf9459ad Mon Sep 17 00:00:00 2001 From: Baoshan Pang Date: Tue, 27 Aug 2019 10:13:59 -0700 Subject: [PATCH 286/618] remove the reference to __cxa_thread_atexit_impl --- src/libstd/sys/vxworks/fast_thread_local.rs | 27 ++------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/src/libstd/sys/vxworks/fast_thread_local.rs b/src/libstd/sys/vxworks/fast_thread_local.rs index f5a2e263d25e7..2e021980778e5 100644 --- a/src/libstd/sys/vxworks/fast_thread_local.rs +++ b/src/libstd/sys/vxworks/fast_thread_local.rs @@ -1,33 +1,10 @@ +// Copyright (c) 2019 Wind River Systems, Inc. + #![cfg(target_thread_local)] #![unstable(feature = "thread_local_internals", issue = "0")] -// Since what appears to be glibc 2.18 this symbol has been shipped which -// GCC and clang both use to invoke destructors in thread_local globals, so -// let's do the same! -// -// Note, however, that we run on lots older linuxes, as well as cross -// compiling from a newer linux to an older linux, so we also have a -// fallback implementation to use as well. -// -// Due to rust-lang/rust#18804, make sure this is not generic! pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { - use crate::mem; use crate::sys_common::thread_local::register_dtor_fallback; - - extern { - #[linkage = "extern_weak"] - static __dso_handle: *mut u8; - #[linkage = "extern_weak"] - static __cxa_thread_atexit_impl: *const libc::c_void; - } - if !__cxa_thread_atexit_impl.is_null() { - type F = unsafe extern fn(dtor: unsafe extern fn(*mut u8), - arg: *mut u8, - dso_handle: *mut u8) -> libc::c_int; - mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl) - (dtor, t, &__dso_handle as *const _ as *mut _); - return - } register_dtor_fallback(t, dtor); } From dbbe3363c94b120d1eba9cba01dadddd862716b8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 27 Aug 2019 19:51:21 +0200 Subject: [PATCH 287/618] Ensure 'let mut ;' where ':pat' is banned. --- src/libsyntax/parse/parser/pat.rs | 9 +++++++++ src/test/ui/parser/mut-patterns.rs | 8 ++++++++ src/test/ui/parser/mut-patterns.stderr | 11 ++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 7b228a700a748..08934e8533049 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -384,6 +384,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a mutable binding with the `mut` token already eaten. fn parse_pat_ident_mut(&mut self) -> PResult<'a, PatKind> { let mut_span = self.prev_span; @@ -393,6 +394,14 @@ impl<'a> Parser<'a> { self.recover_additional_muts(); + // Make sure we don't allow e.g. `let mut $p;` where `$p:pat`. + if let token::Interpolated(ref nt) = self.token.kind { + if let token::NtPat(_) = **nt { + self.expected_ident_found().emit(); + } + } + + // Parse the pattern we hope to be an identifier. let mut pat = self.parse_pat(Some("identifier"))?; // Add `mut` to any binding in the parsed pattern. diff --git a/src/test/ui/parser/mut-patterns.rs b/src/test/ui/parser/mut-patterns.rs index 87e127f9d364a..0c78ca726e003 100644 --- a/src/test/ui/parser/mut-patterns.rs +++ b/src/test/ui/parser/mut-patterns.rs @@ -32,4 +32,12 @@ pub fn main() { let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) //~^ ERROR `mut` must be attached to each individual binding = W(0, W(1, W(2, W(3, B { f: Box::new(4u8) })))); + + // Make sure we don't accidentally allow `mut $p` where `$p:pat`. + macro_rules! foo { + ($p:pat) => { + let mut $p = 0; //~ ERROR expected identifier, found `x` + } + } + foo!(x); } diff --git a/src/test/ui/parser/mut-patterns.stderr b/src/test/ui/parser/mut-patterns.stderr index a251e2908f02c..a1293129e2eaf 100644 --- a/src/test/ui/parser/mut-patterns.stderr +++ b/src/test/ui/parser/mut-patterns.stderr @@ -64,5 +64,14 @@ error: `mut` must be attached to each individual binding LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f }))))` -error: aborting due to 9 previous errors +error: expected identifier, found `x` + --> $DIR/mut-patterns.rs:39:21 + | +LL | let mut $p = 0; + | ^^ expected identifier +... +LL | foo!(x); + | -------- in this macro invocation + +error: aborting due to 10 previous errors From 7677d1f771525606af256e2972cb7116d8fde99f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Aug 2019 22:18:25 +0200 Subject: [PATCH 288/618] const_prop: only call error_to_const_error if we are actually showing something --- src/librustc_mir/const_eval.rs | 3 +++ src/librustc_mir/transform/const_prop.rs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 67d63e52b2bfa..5aa487d901663 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -519,6 +519,9 @@ pub fn const_variant_index<'tcx>( ecx.read_discriminant(op).unwrap().1 } +/// Turn an interpreter error into something to report to the user. +/// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace. +/// Should be called only if the error is actually going to to be reported! pub fn error_to_const_error<'mir, 'tcx>( ecx: &InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>, mut error: InterpErrorInfo<'tcx>, diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index b6146b6b7227d..f261fdc268b5b 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -237,9 +237,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let r = match f(self) { Ok(val) => Some(val), Err(error) => { - let diagnostic = error_to_const_error(&self.ecx, error); use rustc::mir::interpret::InterpError::*; - match diagnostic.error { + match error.kind { Exit(_) => bug!("the CTFE program cannot exit"), Unsupported(_) | UndefinedBehavior(_) @@ -248,6 +247,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // Ignore these errors. } Panic(_) => { + let diagnostic = error_to_const_error(&self.ecx, error); diagnostic.report_as_lint( self.ecx.tcx, "this expression will panic at runtime", From 1a4330d2a23f8b9912cb4ca54d259333b0133b76 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 27 Aug 2019 12:25:35 -0700 Subject: [PATCH 289/618] rustc: Handle modules in "fat" LTO more robustly When performing a "fat" LTO the compiler has a whole mess of codegen units that it links together. To do this it needs to select one module as a "base" module and then link everything else into this module. Previously LTO passes assume that there's at least one module in-memory to link into, but nowadays that's not always true! With incremental compilation modules may actually largely be cached and it may be possible that there's no in-memory modules to work with. This commit updates the logic of the LTO backend to handle modules a bit more uniformly during a fat LTO. This commit immediately splits them into two lists, one serialized and one in-memory. The in-memory list is then searched for the largest module and failing that we simply deserialize the first serialized module and link into that. This refactoring avoids juggling three lists, two of which are serialized modules and one of which is half serialized and half in-memory. Closes #63349 --- src/librustc_codegen_llvm/back/lto.rs | 86 +++++++++---------- src/librustc_codegen_llvm/lib.rs | 7 +- src/test/run-make-fulldeps/lto-empty/Makefile | 12 +++ src/test/run-make-fulldeps/lto-empty/lib.rs | 1 + src/test/ui/lto-duplicate-symbols.stderr | 2 +- 5 files changed, 59 insertions(+), 49 deletions(-) create mode 100644 src/test/run-make-fulldeps/lto-empty/Makefile create mode 100644 src/test/run-make-fulldeps/lto-empty/lib.rs diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 5ed08943fe6fd..a43fbb68dbaed 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -183,7 +183,7 @@ pub(crate) fn prepare_thin( fn fat_lto(cgcx: &CodegenContext, diag_handler: &Handler, - mut modules: Vec>, + modules: Vec>, cached_modules: Vec<(SerializedModule, WorkProduct)>, mut serialized_modules: Vec<(SerializedModule, CString)>, symbol_white_list: &[*const libc::c_char]) @@ -191,6 +191,32 @@ fn fat_lto(cgcx: &CodegenContext, { info!("going for a fat lto"); + // Sort out all our lists of incoming modules into two lists. + // + // * `serialized_modules` (also and argument to this function) contains all + // modules that are serialized in-memory. + // * `in_memory` contains modules which are already parsed and in-memory, + // such as from multi-CGU builds. + // + // All of `cached_modules` (cached from previous incremental builds) can + // immediately go onto the `serialized_modules` modules list and then we can + // split the `modules` array into these two lists. + let mut in_memory = Vec::new(); + serialized_modules.extend(cached_modules.into_iter().map(|(buffer, wp)| { + info!("pushing cached module {:?}", wp.cgu_name); + (buffer, CString::new(wp.cgu_name).unwrap()) + })); + for module in modules { + match module { + FatLTOInput::InMemory(m) => in_memory.push(m), + FatLTOInput::Serialized { name, buffer } => { + info!("pushing serialized module {:?}", name); + let buffer = SerializedModule::Local(buffer); + serialized_modules.push((buffer, CString::new(name).unwrap())); + } + } + } + // Find the "costliest" module and merge everything into that codegen unit. // All the other modules will be serialized and reparsed into the new // context, so this hopefully avoids serializing and parsing the largest @@ -200,14 +226,8 @@ fn fat_lto(cgcx: &CodegenContext, // file copy operations in the backend work correctly. The only other kind // of module here should be an allocator one, and if your crate is smaller // than the allocator module then the size doesn't really matter anyway. - let costliest_module = modules.iter() + let costliest_module = in_memory.iter() .enumerate() - .filter_map(|(i, module)| { - match module { - FatLTOInput::InMemory(m) => Some((i, m)), - FatLTOInput::Serialized { .. } => None, - } - }) .filter(|&(_, module)| module.kind == ModuleKind::Regular) .map(|(i, module)| { let cost = unsafe { @@ -223,26 +243,14 @@ fn fat_lto(cgcx: &CodegenContext, // re-executing the LTO passes. If that's the case deserialize the first // module and create a linker with it. let module: ModuleCodegen = match costliest_module { - Some((_cost, i)) => { - match modules.remove(i) { - FatLTOInput::InMemory(m) => m, - FatLTOInput::Serialized { .. } => unreachable!(), - } - } + Some((_cost, i)) => in_memory.remove(i), None => { - let pos = modules.iter().position(|m| { - match m { - FatLTOInput::InMemory(_) => false, - FatLTOInput::Serialized { .. } => true, - } - }).expect("must have at least one serialized module"); - let (name, buffer) = match modules.remove(pos) { - FatLTOInput::Serialized { name, buffer } => (name, buffer), - FatLTOInput::InMemory(_) => unreachable!(), - }; + assert!(serialized_modules.len() > 0, "must have at least one serialized module"); + let (buffer, name) = serialized_modules.remove(0); + info!("no in-memory regular modules to choose from, parsing {:?}", name); ModuleCodegen { - module_llvm: ModuleLlvm::parse(cgcx, &name, &buffer, diag_handler)?, - name, + module_llvm: ModuleLlvm::parse(cgcx, &name, buffer.data(), diag_handler)?, + name: name.into_string().unwrap(), kind: ModuleKind::Regular, } } @@ -265,25 +273,13 @@ fn fat_lto(cgcx: &CodegenContext, // and we want to move everything to the same LLVM context. Currently the // way we know of to do that is to serialize them to a string and them parse // them later. Not great but hey, that's why it's "fat" LTO, right? - let mut new_modules = modules.into_iter().map(|module| { - match module { - FatLTOInput::InMemory(module) => { - let buffer = ModuleBuffer::new(module.module_llvm.llmod()); - let llmod_id = CString::new(&module.name[..]).unwrap(); - (SerializedModule::Local(buffer), llmod_id) - } - FatLTOInput::Serialized { name, buffer } => { - let llmod_id = CString::new(name).unwrap(); - (SerializedModule::Local(buffer), llmod_id) - } - } - }).collect::>(); + for module in in_memory { + let buffer = ModuleBuffer::new(module.module_llvm.llmod()); + let llmod_id = CString::new(&module.name[..]).unwrap(); + serialized_modules.push((SerializedModule::Local(buffer), llmod_id)); + } // Sort the modules to ensure we produce deterministic results. - new_modules.sort_by(|module1, module2| module1.1.partial_cmp(&module2.1).unwrap()); - serialized_modules.extend(new_modules); - serialized_modules.extend(cached_modules.into_iter().map(|(buffer, wp)| { - (buffer, CString::new(wp.cgu_name).unwrap()) - })); + serialized_modules.sort_by(|module1, module2| module1.1.cmp(&module2.1)); // For all serialized bitcode files we parse them and link them in as we did // above, this is all mostly handled in C++. Like above, though, we don't @@ -850,7 +846,7 @@ fn module_name_to_str(c_str: &CStr) -> &str { bug!("Encountered non-utf8 LLVM module name `{}`: {}", c_str.to_string_lossy(), e)) } -fn parse_module<'a>( +pub fn parse_module<'a>( cx: &'a llvm::Context, name: &CStr, data: &[u8], diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 653dd8868f479..2fd78885bd01e 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -54,6 +54,7 @@ use syntax_pos::symbol::InternedString; pub use llvm_util::target_features; use std::any::Any; use std::sync::{mpsc, Arc}; +use std::ffi::CStr; use rustc::dep_graph::DepGraph; use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; @@ -386,13 +387,13 @@ impl ModuleLlvm { fn parse( cgcx: &CodegenContext, - name: &str, - buffer: &back::lto::ModuleBuffer, + name: &CStr, + buffer: &[u8], handler: &Handler, ) -> Result { unsafe { let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names); - let llmod_raw = buffer.parse(name, llcx, handler)?; + let llmod_raw = back::lto::parse_module(llcx, name, buffer, handler)?; let tm = match (cgcx.tm_factory.0)() { Ok(m) => m, Err(e) => { diff --git a/src/test/run-make-fulldeps/lto-empty/Makefile b/src/test/run-make-fulldeps/lto-empty/Makefile new file mode 100644 index 0000000000000..345d10bc4b9ea --- /dev/null +++ b/src/test/run-make-fulldeps/lto-empty/Makefile @@ -0,0 +1,12 @@ +-include ../tools.mk + +all: cdylib-fat cdylib-thin + +cdylib-fat: + $(RUSTC) lib.rs -C lto=fat -C opt-level=3 -C incremental=$(TMPDIR)/inc-fat + $(RUSTC) lib.rs -C lto=fat -C opt-level=3 -C incremental=$(TMPDIR)/inc-fat + +cdylib-thin: + $(RUSTC) lib.rs -C lto=thin -C opt-level=3 -C incremental=$(TMPDIR)/inc-thin + $(RUSTC) lib.rs -C lto=thin -C opt-level=3 -C incremental=$(TMPDIR)/inc-thin + diff --git a/src/test/run-make-fulldeps/lto-empty/lib.rs b/src/test/run-make-fulldeps/lto-empty/lib.rs new file mode 100644 index 0000000000000..e3663c79078f4 --- /dev/null +++ b/src/test/run-make-fulldeps/lto-empty/lib.rs @@ -0,0 +1 @@ +#![crate_type = "cdylib"] diff --git a/src/test/ui/lto-duplicate-symbols.stderr b/src/test/ui/lto-duplicate-symbols.stderr index 5760cb9a8fdb6..b7a930b61cc96 100644 --- a/src/test/ui/lto-duplicate-symbols.stderr +++ b/src/test/ui/lto-duplicate-symbols.stderr @@ -1,6 +1,6 @@ warning: Linking globals named 'foo': symbol multiply defined! -error: failed to load bc of "lto_duplicate_symbols1.3a1fbbbh-cgu.0": +error: failed to load bc of "lto_duplicate_symbols2.3a1fbbbh-cgu.0": error: aborting due to previous error From 85a4d6f522d733871c1dc94e008f4ff2ac548db0 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 27 Aug 2019 14:03:32 -0700 Subject: [PATCH 290/618] Update cargo --- Cargo.lock | 22 +++++++++++----------- src/tools/cargo | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8ae21c8663706..c758ef177d691 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -287,7 +287,7 @@ dependencies = [ "git2-curl", "glob", "hex", - "home 0.4.2", + "home 0.5.0", "ignore", "im-rc", "jobserver", @@ -1160,9 +1160,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.9.2" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb400360e8a4d61b10e648285bbfa919bbf9519d0d5d5720354456f44349226" +checksum = "327d698f86a7ebdfeb86a4238ccdb004828939d3a3555b6ead679541d14e36c0" dependencies = [ "bitflags", "libc", @@ -1175,9 +1175,9 @@ dependencies = [ [[package]] name = "git2-curl" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2293de73491c3dc4174c5949ef53d2cc037b27613f88d72032e3f5237247a7dd" +checksum = "cd6527e480187ce19aaf4fa6acfb7657b25628ce31cb8ffabdfca3bf731524c5" dependencies = [ "curl", "git2", @@ -1282,9 +1282,9 @@ dependencies = [ [[package]] name = "home" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "013e4e6e9134211bb4d6bf53dd8cfb75d9e2715cc33614b9c0827718c6fbe0b8" +checksum = "c07c315e106bd6f83f026a20ddaeef2706782e490db1dcdd37caad38a0e895b3" dependencies = [ "scopeguard 1.0.0", "winapi 0.3.6", @@ -1604,9 +1604,9 @@ dependencies = [ [[package]] name = "libgit2-sys" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c179ed6d19cd3a051e68c177fbbc214e79ac4724fac3a850ec9f3d3eb8a5578" +checksum = "8c2078aec6f4b16d1b89f6a72e4f6eb1e75ffa85312023291e89c6d3087bc8fb" dependencies = [ "cc", "libc", @@ -1668,9 +1668,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" dependencies = [ "cfg-if", ] diff --git a/src/tools/cargo b/src/tools/cargo index 3f700ec43ce72..22f7dd0495cd7 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 3f700ec43ce72305eb5315cfc710681f3469d4b4 +Subproject commit 22f7dd0495cd72ce2082d318d5a9b4dccb9c5b8c From 42e895d4d99ec7724f3efd632f52170f3f99a5aa Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 27 Aug 2019 23:44:44 +0200 Subject: [PATCH 291/618] Improve 'mut ' diagnostic. --- src/libsyntax/parse/parser/pat.rs | 54 ++++++++++++++--------- src/test/ui/parser/issue-32501.rs | 2 +- src/test/ui/parser/issue-32501.stderr | 6 ++- src/test/ui/parser/mut-patterns.rs | 3 ++ src/test/ui/parser/mut-patterns.stderr | 46 ++++++++++++++----- src/test/ui/self/self_type_keyword.rs | 2 +- src/test/ui/self/self_type_keyword.stderr | 6 ++- 7 files changed, 82 insertions(+), 37 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 08934e8533049..1ffb112a5e87e 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -405,22 +405,13 @@ impl<'a> Parser<'a> { let mut pat = self.parse_pat(Some("identifier"))?; // Add `mut` to any binding in the parsed pattern. - struct AddMut; - impl MutVisitor for AddMut { - fn visit_pat(&mut self, pat: &mut P) { - if let PatKind::Ident(BindingMode::ByValue(ref mut m), ..) = pat.node { - *m = Mutability::Mutable; - } - noop_visit_pat(pat, self); - } - } - AddMut.visit_pat(&mut pat); + let changed_any_binding = Self::make_all_value_bindings_mutable(&mut pat); // Unwrap; If we don't have `mut $ident`, error. let pat = pat.into_inner(); match &pat.node { PatKind::Ident(..) => {} - _ => self.ban_mut_general_pat(mut_span, &pat), + _ => self.ban_mut_general_pat(mut_span, &pat, changed_any_binding), } Ok(pat.node) @@ -442,17 +433,40 @@ impl<'a> Parser<'a> { self.parse_pat_ident(BindingMode::ByRef(Mutability::Mutable)) } + /// Turn all by-value immutable bindings in a pattern into mutable bindings. + /// Returns `true` if any change was made. + fn make_all_value_bindings_mutable(pat: &mut P) -> bool { + struct AddMut(bool); + impl MutVisitor for AddMut { + fn visit_pat(&mut self, pat: &mut P) { + if let PatKind::Ident(BindingMode::ByValue(ref mut m @ Mutability::Immutable), ..) + = pat.node + { + *m = Mutability::Mutable; + self.0 = true; + } + noop_visit_pat(pat, self); + } + } + + let mut add_mut = AddMut(false); + add_mut.visit_pat(pat); + add_mut.0 + } + /// Error on `mut $pat` where `$pat` is not an ident. - fn ban_mut_general_pat(&self, lo: Span, pat: &Pat) { + fn ban_mut_general_pat(&self, lo: Span, pat: &Pat, changed_any_binding: bool) { let span = lo.to(pat.span); - self.struct_span_err(span, "`mut` must be attached to each individual binding") - .span_suggestion( - span, - "add `mut` to each binding", - pprust::pat_to_string(&pat), - Applicability::MachineApplicable, - ) - .emit(); + let fix = pprust::pat_to_string(&pat); + let (problem, suggestion) = if changed_any_binding { + ("`mut` must be attached to each individual binding", "add `mut` to each binding") + } else { + ("`mut` must be followed by a named binding", "remove the `mut` prefix") + }; + self.struct_span_err(span, problem) + .span_suggestion(span, suggestion, fix, Applicability::MachineApplicable) + .note("`mut` may be followed by `variable` and `variable @ pattern`") + .emit() } /// Eat any extraneous `mut`s and error + recover if we ate any. diff --git a/src/test/ui/parser/issue-32501.rs b/src/test/ui/parser/issue-32501.rs index 695baf8187276..500242030c655 100644 --- a/src/test/ui/parser/issue-32501.rs +++ b/src/test/ui/parser/issue-32501.rs @@ -5,5 +5,5 @@ fn main() { let mut b = 0; let mut _b = 0; let mut _ = 0; - //~^ ERROR `mut` must be attached to each individual binding + //~^ ERROR `mut` must be followed by a named binding } diff --git a/src/test/ui/parser/issue-32501.stderr b/src/test/ui/parser/issue-32501.stderr index f5d3300cf9c56..d53302449a806 100644 --- a/src/test/ui/parser/issue-32501.stderr +++ b/src/test/ui/parser/issue-32501.stderr @@ -1,8 +1,10 @@ -error: `mut` must be attached to each individual binding +error: `mut` must be followed by a named binding --> $DIR/issue-32501.rs:7:9 | LL | let mut _ = 0; - | ^^^^^ help: add `mut` to each binding: `_` + | ^^^^^ help: remove the `mut` prefix: `_` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: aborting due to previous error diff --git a/src/test/ui/parser/mut-patterns.rs b/src/test/ui/parser/mut-patterns.rs index 0c78ca726e003..d46186a0fea0e 100644 --- a/src/test/ui/parser/mut-patterns.rs +++ b/src/test/ui/parser/mut-patterns.rs @@ -6,6 +6,9 @@ #![allow(warnings)] pub fn main() { + let mut _ = 0; //~ ERROR `mut` must be followed by a named binding + let mut (_, _) = (0, 0); //~ ERROR `mut` must be followed by a named binding + let mut mut x = 0; //~^ ERROR `mut` on a binding may not be repeated //~| remove the additional `mut`s diff --git a/src/test/ui/parser/mut-patterns.stderr b/src/test/ui/parser/mut-patterns.stderr index a1293129e2eaf..18ffaa5255870 100644 --- a/src/test/ui/parser/mut-patterns.stderr +++ b/src/test/ui/parser/mut-patterns.stderr @@ -1,29 +1,49 @@ +error: `mut` must be followed by a named binding + --> $DIR/mut-patterns.rs:9:9 + | +LL | let mut _ = 0; + | ^^^^^ help: remove the `mut` prefix: `_` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` must be followed by a named binding + --> $DIR/mut-patterns.rs:10:9 + | +LL | let mut (_, _) = (0, 0); + | ^^^^^^^^^^ help: remove the `mut` prefix: `(_, _)` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + error: `mut` on a binding may not be repeated - --> $DIR/mut-patterns.rs:9:13 + --> $DIR/mut-patterns.rs:12:13 | LL | let mut mut x = 0; | ^^^ help: remove the additional `mut`s error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:14:9 + --> $DIR/mut-patterns.rs:17:9 | LL | let mut Foo { x: x } = Foo { x: 3 }; | ^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { x: mut x }` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:18:9 + --> $DIR/mut-patterns.rs:21:9 | LL | let mut Foo { x } = Foo { x: 3 }; | ^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { mut x }` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: `mut` on a binding may not be repeated - --> $DIR/mut-patterns.rs:23:13 + --> $DIR/mut-patterns.rs:26:13 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^ help: remove the additional `mut`s error: expected identifier, found reserved keyword `yield` - --> $DIR/mut-patterns.rs:23:17 + --> $DIR/mut-patterns.rs:26:17 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^ expected identifier, found reserved keyword @@ -33,7 +53,7 @@ LL | let mut mut r#yield(become, await) = r#yield(0, 0); | ^^^^^^^ error: expected identifier, found reserved keyword `become` - --> $DIR/mut-patterns.rs:23:23 + --> $DIR/mut-patterns.rs:26:23 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^^ expected identifier, found reserved keyword @@ -43,7 +63,7 @@ LL | let mut mut yield(r#become, await) = r#yield(0, 0); | ^^^^^^^^ error: expected identifier, found reserved keyword `await` - --> $DIR/mut-patterns.rs:23:31 + --> $DIR/mut-patterns.rs:26:31 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^ expected identifier, found reserved keyword @@ -53,19 +73,23 @@ LL | let mut mut yield(become, r#await) = r#yield(0, 0); | ^^^^^^^ error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:23:9 + --> $DIR/mut-patterns.rs:26:9 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `r#yield(mut r#become, mut r#await)` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:32:9 + --> $DIR/mut-patterns.rs:35:9 | LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f }))))` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: expected identifier, found `x` - --> $DIR/mut-patterns.rs:39:21 + --> $DIR/mut-patterns.rs:42:21 | LL | let mut $p = 0; | ^^ expected identifier @@ -73,5 +97,5 @@ LL | let mut $p = 0; LL | foo!(x); | -------- in this macro invocation -error: aborting due to 10 previous errors +error: aborting due to 12 previous errors diff --git a/src/test/ui/self/self_type_keyword.rs b/src/test/ui/self/self_type_keyword.rs index d479905932be0..844f13c2f896a 100644 --- a/src/test/ui/self/self_type_keyword.rs +++ b/src/test/ui/self/self_type_keyword.rs @@ -14,7 +14,7 @@ pub fn main() { ref Self => (), //~^ ERROR expected identifier, found keyword `Self` mut Self => (), - //~^ ERROR `mut` must be attached to each individual binding + //~^ ERROR `mut` must be followed by a named binding //~| ERROR cannot find unit struct/variant or constant `Self` ref mut Self => (), //~^ ERROR expected identifier, found keyword `Self` diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr index fdae06ccdd9f5..bb631194bf3df 100644 --- a/src/test/ui/self/self_type_keyword.stderr +++ b/src/test/ui/self/self_type_keyword.stderr @@ -10,11 +10,13 @@ error: expected identifier, found keyword `Self` LL | ref Self => (), | ^^^^ expected identifier, found keyword -error: `mut` must be attached to each individual binding +error: `mut` must be followed by a named binding --> $DIR/self_type_keyword.rs:16:9 | LL | mut Self => (), - | ^^^^^^^^ help: add `mut` to each binding: `Self` + | ^^^^^^^^ help: remove the `mut` prefix: `Self` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: expected identifier, found keyword `Self` --> $DIR/self_type_keyword.rs:19:17 From 3d718037dcddd2aa56bd2727dee074ac9b6a6f0e Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 24 Aug 2019 16:25:55 +0100 Subject: [PATCH 292/618] Add default serialization for `Ident`s Add tests for -Zast-json and -Zast-json-noexpand, which need this impl. --- src/librustc/ty/query/on_disk_cache.rs | 25 ++++++++++++- src/libsyntax_pos/symbol.rs | 24 +++++++++++- src/test/ui/ast-json/ast-json-ice.rs | 41 +++++++++++++++++++++ src/test/ui/ast-json/ast-json-output.rs | 9 +++++ src/test/ui/ast-json/ast-json-output.stdout | 1 + 5 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/ast-json/ast-json-ice.rs create mode 100644 src/test/ui/ast-json/ast-json-output.rs create mode 100644 src/test/ui/ast-json/ast-json-output.stdout diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index c21639d0dcaee..674f8944f261a 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -20,7 +20,7 @@ use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::sync::{Lrc, Lock, HashMapExt, Once}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use std::mem; -use syntax::ast::NodeId; +use syntax::ast::{Ident, NodeId}; use syntax::source_map::{SourceMap, StableSourceFileId}; use syntax_pos::{BytePos, Span, DUMMY_SP, SourceFile}; use syntax_pos::hygiene::{ExpnId, SyntaxContext}; @@ -591,7 +591,8 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { // FIXME(mw): This method does not restore `ExpnData::parent` or // `SyntaxContextData::prev_ctxt` or `SyntaxContextData::opaque`. These things // don't seem to be used after HIR lowering, so everything should be fine - // as long as incremental compilation does not kick in before that. + // until we want incremental compilation to serialize Spans that we need + // full hygiene information for. let location = || Span::with_root_ctxt(lo, hi); let recover_from_expn_data = |this: &Self, expn_data, transparency, pos| { let span = location().fresh_expansion_with_transparency(expn_data, transparency); @@ -626,6 +627,13 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { } } +impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result { + // FIXME: Handle hygiene in incremental + bug!("Trying to decode Ident for incremental"); + } +} + // This impl makes sure that we get a runtime error when we try decode a // DefIndex that is not contained in a DefId. Such a case would be problematic // because we would not know how to transform the DefIndex to the current @@ -833,6 +841,19 @@ where } } +impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> +where + E: 'a + ty_codec::TyEncoder, +{ + fn specialized_encode(&mut self, _: &Ident) -> Result<(), Self::Error> { + // We don't currently encode enough information to ensure hygiene works + // with incremental, so panic rather than risk incremental bugs. + + // FIXME: Handle hygiene in incremental + bug!("Trying to encode Ident for incremental") + } +} + impl<'a, 'tcx, E> ty_codec::TyEncoder for CacheEncoder<'a, 'tcx, E> where E: 'a + ty_codec::TyEncoder, diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 0b8f16bbc3b99..2d8e97c1800f7 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -849,9 +849,29 @@ impl fmt::Display for Ident { } } -impl UseSpecializedEncodable for Ident {} +impl UseSpecializedEncodable for Ident { + fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { + s.emit_struct("Ident", 2, |s| { + s.emit_struct_field("name", 0, |s| { + self.name.encode(s) + })?; + s.emit_struct_field("span", 1, |s| { + self.span.encode(s) + }) + }) + } +} -impl UseSpecializedDecodable for Ident {} +impl UseSpecializedDecodable for Ident { + fn default_decode(d: &mut D) -> Result { + d.read_struct("Ident", 2, |d| { + Ok(Ident { + name: d.read_struct_field("name", 0, Decodable::decode)?, + span: d.read_struct_field("span", 1, Decodable::decode)?, + }) + }) + } +} /// A symbol is an interned or gensymed string. A gensym is a symbol that is /// never equal to any other symbol. diff --git a/src/test/ui/ast-json/ast-json-ice.rs b/src/test/ui/ast-json/ast-json-ice.rs new file mode 100644 index 0000000000000..e8a622e1b8772 --- /dev/null +++ b/src/test/ui/ast-json/ast-json-ice.rs @@ -0,0 +1,41 @@ +// Test that AST json serialization doesn't ICE (#63728). + +// revisions: expand noexpand + +//[expand] compile-flags: -Zast-json +//[noexpand] compile-flags: -Zast-json-noexpand + +// check-pass +// dont-check-compiler-stdout - don't check for any AST change. + +#![feature(asm)] + +enum V { + A(i32), + B { f: [i64; 3 + 4] } +} + +trait X { + type Output; + fn read(&self) -> Self::Output; + fn write(&mut self, _: Self::Output); +} + +macro_rules! call_println { + ($y:ident) => { println!("{}", $y) } +} + +fn main() { + #[cfg(any(target_arch = "x86", + target_arch = "x86_64", + target_arch = "arm", + target_arch = "aarch64"))] + unsafe { asm!(""::::); } + + let x: (i32) = 35; + let y = x as i64<> + 5; + + call_println!(y); + + struct A; +} diff --git a/src/test/ui/ast-json/ast-json-output.rs b/src/test/ui/ast-json/ast-json-output.rs new file mode 100644 index 0000000000000..e444a07460248 --- /dev/null +++ b/src/test/ui/ast-json/ast-json-output.rs @@ -0,0 +1,9 @@ +// Check that AST json printing works. + +// check-pass +// compile-flags: -Zast-json-noexpand +// normalize-stdout-test ":\d+" -> ":0" + +// Only include a single item to reduce how often the test output needs +// updating. +extern crate core; diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout new file mode 100644 index 0000000000000..d23cbe0240ee1 --- /dev/null +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -0,0 +1 @@ +{"module":{"inner":{"lo":0,"hi":0},"items":[{"ident":{"name":"core","span":{"lo":0,"hi":0}},"attrs":[],"id":0,"node":{"variant":"ExternCrate","fields":[null]},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"span":{"lo":0,"hi":0},"tokens":[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]}]}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}} From 82f2b376357e68cdde86d75259fed39ea4df79e3 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 28 Aug 2019 06:17:58 +0900 Subject: [PATCH 293/618] Add Option to `require_lang_item` --- src/librustc/infer/mod.rs | 2 +- src/librustc/middle/lang_items.rs | 8 ++++++-- src/librustc/traits/select.rs | 2 +- src/librustc/ty/context.rs | 4 ++-- src/librustc/ty/instance.rs | 2 +- src/librustc/ty/mod.rs | 6 +++--- src/librustc/ty/util.rs | 6 +++--- src/librustc/ty/wf.rs | 2 +- src/librustc_codegen_ssa/base.rs | 2 +- src/librustc_mir/build/matches/test.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 5 ++++- src/librustc_mir/util/elaborate_drops.rs | 2 +- src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/check/wfcheck.rs | 4 ++-- src/librustdoc/clean/auto_trait.rs | 8 ++++---- src/librustdoc/clean/mod.rs | 2 +- src/test/ui/lang-item-missing-generator.stderr | 4 ++++ 19 files changed, 39 insertions(+), 28 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index e1d77a97c1160..cc28567e2fc9e 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1460,7 +1460,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem); + let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None); // this can get called from typeck (by euv), and moves_by_default // rightly refuses to work with inference variables, but diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index c5c8639324358..334c06618bb28 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -381,9 +381,13 @@ language_item_table! { impl<'tcx> TyCtxt<'tcx> { /// Returns the `DefId` for a given `LangItem`. /// If not found, fatally abort compilation. - pub fn require_lang_item(&self, lang_item: LangItem) -> DefId { + pub fn require_lang_item(&self, lang_item: LangItem, span: Option) -> DefId { self.lang_items().require(lang_item).unwrap_or_else(|msg| { - self.sess.fatal(&msg) + if let Some(span) = span { + self.sess.span_fatal(span, &msg) + } else { + self.sess.fatal(&msg) + } }) } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index d4ae366262cbf..217c887d5254e 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3513,7 +3513,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // We can only make objects from sized types. let tr = ty::TraitRef { - def_id: tcx.require_lang_item(lang_items::SizedTraitLangItem), + def_id: tcx.require_lang_item(lang_items::SizedTraitLangItem, None), substs: tcx.mk_substs_trait(source, &[]), }; nested.push(predicate_to_obligation(tr.to_predicate())); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 9f316e93111a3..c0d86a79882ef 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2385,13 +2385,13 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem); + let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem, None); self.mk_generic_adt(def_id, ty) } #[inline] pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = self.require_lang_item(lang_items::MaybeUninitLangItem); + let def_id = self.require_lang_item(lang_items::MaybeUninitLangItem, None); self.mk_generic_adt(def_id, ty) } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index c71e1ea4e5859..a26fa72f33041 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -327,7 +327,7 @@ impl<'tcx> Instance<'tcx> { } pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> { - let def_id = tcx.require_lang_item(DropInPlaceFnLangItem); + let def_id = tcx.require_lang_item(DropInPlaceFnLangItem, None); let substs = tcx.intern_substs(&[ty.into()]); Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap() } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 0b81f193df409..90b3b7ebb0635 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2588,12 +2588,12 @@ impl<'tcx> ClosureKind { pub fn trait_did(&self, tcx: TyCtxt<'tcx>) -> DefId { match *self { - ClosureKind::Fn => tcx.require_lang_item(FnTraitLangItem), + ClosureKind::Fn => tcx.require_lang_item(FnTraitLangItem, None), ClosureKind::FnMut => { - tcx.require_lang_item(FnMutTraitLangItem) + tcx.require_lang_item(FnMutTraitLangItem, None) } ClosureKind::FnOnce => { - tcx.require_lang_item(FnOnceTraitLangItem) + tcx.require_lang_item(FnOnceTraitLangItem, None) } } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 96e16efd1300a..7a77418050cdb 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -998,7 +998,7 @@ impl<'tcx> ty::TyS<'tcx> { fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { let (param_env, ty) = query.into_parts(); - let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem); + let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem, None); tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( &infcx, @@ -1011,7 +1011,7 @@ fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { let (param_env, ty) = query.into_parts(); - let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem); + let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem, None); tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( &infcx, @@ -1024,7 +1024,7 @@ fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { let (param_env, ty) = query.into_parts(); - let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem); + let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem, None); tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( &infcx, diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index d32c32af29e0d..d6de217f79c29 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -221,7 +221,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { if !subty.has_escaping_bound_vars() { let cause = self.cause(cause); let trait_ref = ty::TraitRef { - def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None), substs: self.infcx.tcx.mk_substs_trait(subty, &[]), }; self.out.push(traits::Obligation::new(cause, self.param_env, trait_ref.to_predicate())); diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index cdc54bb179ebf..4acbe0356b47c 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -456,7 +456,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' let arg_argv = param_argv; let (start_fn, args) = if use_start_lang_item { - let start_def_id = cx.tcx().require_lang_item(StartFnLangItem); + let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None); let start_fn = callee::resolve_and_get_fn( cx, start_def_id, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index ec85daccd476e..d5890d00ea80f 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -443,7 +443,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ => bug!("non_scalar_compare called on non-reference type: {}", ty), }; - let eq_def_id = self.hir.tcx().require_lang_item(EqTraitLangItem); + let eq_def_id = self.hir.tcx().require_lang_item(EqTraitLangItem, None); let method = self.hir.trait_method(eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]); let bool_ty = self.hir.bool_ty(); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 7f8ae88342934..a59bd6677cb51 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1752,7 +1752,10 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { fulfillment_cx.register_bound(&infcx, param_env, ty, - tcx.require_lang_item(lang_items::SyncTraitLangItem), + tcx.require_lang_item( + lang_items::SyncTraitLangItem, + None + ), cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { infcx.report_fulfillment_errors(&err, None, false); diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index c5561a1ae0d15..3e9e4b7767f1e 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -897,7 +897,7 @@ where ) -> BasicBlock { let tcx = self.tcx(); let unit_temp = Place::from(self.new_temp(tcx.mk_unit())); - let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); + let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem, None); let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| { let field = Field::new(i); let field_ty = f.ty(self.tcx(), substs); diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 53101499af1dc..55e7a10f1aaa4 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -649,7 +649,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn type_is_known_to_be_sized_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); traits::type_known_to_meet_bound_modulo_regions(self, self.param_env, ty, lang_item, span) } } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 06b1e7bfd4eaf..e9370429f3f55 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -266,7 +266,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_ref = projection.to_poly_trait_ref(tcx); let is_fn = tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_some(); - let gen_trait = tcx.require_lang_item(lang_items::GeneratorTraitLangItem); + let gen_trait = tcx.require_lang_item(lang_items::GeneratorTraitLangItem, cause_span); let is_gen = gen_trait == trait_ref.def_id(); if !is_fn && !is_gen { debug!("deduce_sig_from_projection: not fn or generator"); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c4dbe97a7bd96..29fae13e6a866 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2622,7 +2622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, code: traits::ObligationCauseCode<'tcx>) { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); self.require_type_meets(ty, span, code, lang_item); } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 9c6ea7d30ccf9..f95b3e44bf0f7 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -287,7 +287,7 @@ fn check_type_defn<'tcx, F>( let last = idx == variant.fields.len() - 1; fcx.register_bound( field.ty, - fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None), traits::ObligationCause::new( field.span, fcx.body_id, @@ -375,7 +375,7 @@ fn check_item_type( if forbid_unsized { fcx.register_bound( item_ty, - fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None), traits::ObligationCause::new(ty_span, fcx.body_id, traits::MiscObligation), ); } diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 5a4dc7be326d2..516be99ed6aad 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -464,7 +464,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // it is *not* required (i.e., '?Sized') let sized_trait = self.cx .tcx - .require_lang_item(lang_items::SizedTraitLangItem); + .require_lang_item(lang_items::SizedTraitLangItem, None); let mut replacer = RegionReplacer { vid_to_region: &vid_to_region, @@ -777,9 +777,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { fn is_fn_ty(&self, tcx: TyCtxt<'_>, ty: &Type) -> bool { match &ty { &&Type::ResolvedPath { ref did, .. } => { - *did == tcx.require_lang_item(lang_items::FnTraitLangItem) - || *did == tcx.require_lang_item(lang_items::FnMutTraitLangItem) - || *did == tcx.require_lang_item(lang_items::FnOnceTraitLangItem) + *did == tcx.require_lang_item(lang_items::FnTraitLangItem, None) + || *did == tcx.require_lang_item(lang_items::FnMutTraitLangItem, None) + || *did == tcx.require_lang_item(lang_items::FnOnceTraitLangItem, None) } _ => false, } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ba792a413b3c4..ad1fa96cd3557 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1060,7 +1060,7 @@ pub enum GenericBound { impl GenericBound { fn maybe_sized(cx: &DocContext<'_>) -> GenericBound { - let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem); + let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); let empty = cx.tcx.intern_substs(&[]); let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), false, vec![], empty); diff --git a/src/test/ui/lang-item-missing-generator.stderr b/src/test/ui/lang-item-missing-generator.stderr index d0cc4b81be685..fa13bf0b12719 100644 --- a/src/test/ui/lang-item-missing-generator.stderr +++ b/src/test/ui/lang-item-missing-generator.stderr @@ -1,4 +1,8 @@ error: requires `generator` lang_item + --> $DIR/lang-item-missing-generator.rs:15:17 + | +LL | pub fn abc() -> impl FnOnce(f32) { + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error From 8c921beebbc4501f301cd1830b7c2528368e517a Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 28 Aug 2019 07:10:47 +0900 Subject: [PATCH 294/618] Apply review comments --- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_mir/util/elaborate_drops.rs | 5 ++++- src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/test/ui/lang-item-missing.stderr | 4 ++++ src/test/ui/privacy/privacy2.rs | 2 +- src/test/ui/privacy/privacy2.stderr | 4 ++++ src/test/ui/privacy/privacy3.rs | 2 +- src/test/ui/privacy/privacy3.stderr | 4 ++++ 9 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index a59bd6677cb51..a77421ce15008 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1754,7 +1754,7 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { ty, tcx.require_lang_item( lang_items::SyncTraitLangItem, - None + Some(body.span) ), cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 3e9e4b7767f1e..f3e03e7f81daa 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -897,7 +897,10 @@ where ) -> BasicBlock { let tcx = self.tcx(); let unit_temp = Place::from(self.new_temp(tcx.mk_unit())); - let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem, None); + let free_func = tcx.require_lang_item( + lang_items::BoxFreeFnLangItem, + Some(self.source_info.span) + ); let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| { let field = Field::new(i); let field_ty = f.ty(self.tcx(), substs); diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 55e7a10f1aaa4..6b88144d1fc10 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -649,7 +649,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn type_is_known_to_be_sized_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, Some(span)); traits::type_known_to_meet_bound_modulo_regions(self, self.param_env, ty, lang_item, span) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 29fae13e6a866..62e11fb421ee7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2622,7 +2622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, code: traits::ObligationCauseCode<'tcx>) { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, Some(span)); self.require_type_meets(ty, span, code, lang_item); } diff --git a/src/test/ui/lang-item-missing.stderr b/src/test/ui/lang-item-missing.stderr index f7516c7d377da..94d62023f3562 100644 --- a/src/test/ui/lang-item-missing.stderr +++ b/src/test/ui/lang-item-missing.stderr @@ -1,4 +1,8 @@ error: requires `sized` lang_item + --> $DIR/lang-item-missing.rs:10:50 + | +LL | fn start(argc: isize, argv: *const *const u8) -> isize { + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/privacy/privacy2.rs b/src/test/ui/privacy/privacy2.rs index c8fa436bd14fc..07634d9132e78 100644 --- a/src/test/ui/privacy/privacy2.rs +++ b/src/test/ui/privacy/privacy2.rs @@ -11,7 +11,7 @@ mod bar { } } -pub fn foo() {} +pub fn foo() {} //~ ERROR: requires `sized` lang_item fn test1() { use bar::foo; diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr index 9f2359657bd7c..eaa9f1ad6528e 100644 --- a/src/test/ui/privacy/privacy2.stderr +++ b/src/test/ui/privacy/privacy2.stderr @@ -11,6 +11,10 @@ LL | use bar::glob::foo; | ^^^ error: requires `sized` lang_item + --> $DIR/privacy2.rs:14:14 + | +LL | pub fn foo() {} + | ^ error: aborting due to 3 previous errors diff --git a/src/test/ui/privacy/privacy3.rs b/src/test/ui/privacy/privacy3.rs index 5a7cd76a98f6e..8853700180dbc 100644 --- a/src/test/ui/privacy/privacy3.rs +++ b/src/test/ui/privacy/privacy3.rs @@ -8,7 +8,7 @@ mod bar { pub use self::glob::*; mod glob { - fn gpriv() {} + fn gpriv() {} //~ ERROR: requires `sized` lang_item } } diff --git a/src/test/ui/privacy/privacy3.stderr b/src/test/ui/privacy/privacy3.stderr index 22c1e48b07d94..6826fbf9df290 100644 --- a/src/test/ui/privacy/privacy3.stderr +++ b/src/test/ui/privacy/privacy3.stderr @@ -5,6 +5,10 @@ LL | use bar::gpriv; | ^^^^^^^^^^ no `gpriv` in `bar` error: requires `sized` lang_item + --> $DIR/privacy3.rs:11:20 + | +LL | fn gpriv() {} + | ^ error: aborting due to 2 previous errors From ede7a777c08658ec54abea504da0e46cd0fb5e5b Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 28 Aug 2019 07:32:25 +0900 Subject: [PATCH 295/618] Remove `sized` spans --- src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/test/ui/lang-item-missing.stderr | 4 ---- src/test/ui/privacy/privacy2.rs | 2 +- src/test/ui/privacy/privacy2.stderr | 4 ---- src/test/ui/privacy/privacy3.rs | 2 +- src/test/ui/privacy/privacy3.stderr | 4 ---- 7 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 6b88144d1fc10..55e7a10f1aaa4 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -649,7 +649,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn type_is_known_to_be_sized_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, Some(span)); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); traits::type_known_to_meet_bound_modulo_regions(self, self.param_env, ty, lang_item, span) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 62e11fb421ee7..29fae13e6a866 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2622,7 +2622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, code: traits::ObligationCauseCode<'tcx>) { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, Some(span)); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); self.require_type_meets(ty, span, code, lang_item); } diff --git a/src/test/ui/lang-item-missing.stderr b/src/test/ui/lang-item-missing.stderr index 94d62023f3562..f7516c7d377da 100644 --- a/src/test/ui/lang-item-missing.stderr +++ b/src/test/ui/lang-item-missing.stderr @@ -1,8 +1,4 @@ error: requires `sized` lang_item - --> $DIR/lang-item-missing.rs:10:50 - | -LL | fn start(argc: isize, argv: *const *const u8) -> isize { - | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/privacy/privacy2.rs b/src/test/ui/privacy/privacy2.rs index 07634d9132e78..c8fa436bd14fc 100644 --- a/src/test/ui/privacy/privacy2.rs +++ b/src/test/ui/privacy/privacy2.rs @@ -11,7 +11,7 @@ mod bar { } } -pub fn foo() {} //~ ERROR: requires `sized` lang_item +pub fn foo() {} fn test1() { use bar::foo; diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr index eaa9f1ad6528e..9f2359657bd7c 100644 --- a/src/test/ui/privacy/privacy2.stderr +++ b/src/test/ui/privacy/privacy2.stderr @@ -11,10 +11,6 @@ LL | use bar::glob::foo; | ^^^ error: requires `sized` lang_item - --> $DIR/privacy2.rs:14:14 - | -LL | pub fn foo() {} - | ^ error: aborting due to 3 previous errors diff --git a/src/test/ui/privacy/privacy3.rs b/src/test/ui/privacy/privacy3.rs index 8853700180dbc..5a7cd76a98f6e 100644 --- a/src/test/ui/privacy/privacy3.rs +++ b/src/test/ui/privacy/privacy3.rs @@ -8,7 +8,7 @@ mod bar { pub use self::glob::*; mod glob { - fn gpriv() {} //~ ERROR: requires `sized` lang_item + fn gpriv() {} } } diff --git a/src/test/ui/privacy/privacy3.stderr b/src/test/ui/privacy/privacy3.stderr index 6826fbf9df290..22c1e48b07d94 100644 --- a/src/test/ui/privacy/privacy3.stderr +++ b/src/test/ui/privacy/privacy3.stderr @@ -5,10 +5,6 @@ LL | use bar::gpriv; | ^^^^^^^^^^ no `gpriv` in `bar` error: requires `sized` lang_item - --> $DIR/privacy3.rs:11:20 - | -LL | fn gpriv() {} - | ^ error: aborting due to 2 previous errors From cae6d66d9989857e321e0963142b08b1517dc723 Mon Sep 17 00:00:00 2001 From: Baoshan Pang Date: Fri, 16 Aug 2019 13:56:03 -0700 Subject: [PATCH 296/618] run test for vxWorks in 'pure' static linking mode by default; if environment variables 'RUST_TEST_DYLINK' is set to 1, then run test in 'pure' dynamic linking mode --- src/tools/compiletest/src/runtest.rs | 29 ++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3da6be74129f4..0bc77c6c502dc 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1725,6 +1725,28 @@ impl<'test> TestCx<'test> { } } + fn is_vxworks_pure_static(&self) -> bool { + if self.config.target.contains("vxworks") { + match env::var("RUST_TEST_DYLINK") { + Ok(s) => s != "1", + _ => true + } + } else { + false + } + } + + fn is_vxworks_pure_dynamic(&self) -> bool { + if self.config.target.contains("vxworks") { + match env::var("RUST_TEST_DYLINK") { + Ok(s) => s == "1", + _ => false + } + } else { + false + } + } + fn compose_and_run_compiler(&self, mut rustc: Command, input: Option) -> ProcRes { let aux_dir = self.aux_output_dir_name(); @@ -1768,6 +1790,7 @@ impl<'test> TestCx<'test> { && !self.config.host.contains("musl")) || self.config.target.contains("wasm32") || self.config.target.contains("nvptx") + || self.is_vxworks_pure_static() { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible @@ -1999,7 +2022,8 @@ impl<'test> TestCx<'test> { } if !is_rustdoc { - if self.config.target == "wasm32-unknown-unknown" { + if self.config.target == "wasm32-unknown-unknown" + || self.is_vxworks_pure_static() { // rustc.arg("-g"); // get any backtrace at all on errors } else if !self.props.no_prefer_dynamic { rustc.args(&["-C", "prefer-dynamic"]); @@ -2044,7 +2068,8 @@ impl<'test> TestCx<'test> { } // Use dynamic musl for tests because static doesn't allow creating dylibs - if self.config.host.contains("musl") { + if self.config.host.contains("musl") + || self.is_vxworks_pure_dynamic() { rustc.arg("-Ctarget-feature=-crt-static"); } From 6f67bbc445e5c2b426abc4ac0db4c1dcffd48452 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Wed, 28 Aug 2019 02:23:58 +0200 Subject: [PATCH 297/618] or-pattern: fix typo in error message --- src/libsyntax/parse/parser/pat.rs | 2 +- src/test/ui/or-patterns/while-parsing-this-or-pattern.rs | 2 +- src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 78c9a289b3702..4c6b6ce38f66b 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -113,7 +113,7 @@ impl<'a> Parser<'a> { let mut pats = vec![first_pat]; while self.eat_or_separator() { let pat = self.parse_pat(expected).map_err(|mut err| { - err.span_label(lo, "while parsing this or-pattern staring here"); + err.span_label(lo, "while parsing this or-pattern starting here"); err })?; self.maybe_recover_unexpected_comma(pat.span, rc)?; diff --git a/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs b/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs index 4a9fae1406af7..b9bfb8638b2ce 100644 --- a/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs +++ b/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs @@ -3,7 +3,7 @@ fn main() { match Some(42) { Some(42) | .=. => {} //~ ERROR expected pattern, found `.` - //~^ while parsing this or-pattern staring here + //~^ while parsing this or-pattern starting here //~| NOTE expected pattern } } diff --git a/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr b/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr index 21fece6c64fe5..7ad62ff99ee73 100644 --- a/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr +++ b/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr @@ -4,7 +4,7 @@ error: expected pattern, found `.` LL | Some(42) | .=. => {} | -------- ^ expected pattern | | - | while parsing this or-pattern staring here + | while parsing this or-pattern starting here error: aborting due to previous error From 42bd6fa22b753858bd57aec5e987247fd6a00897 Mon Sep 17 00:00:00 2001 From: Logan Wendholt Date: Tue, 27 Aug 2019 20:35:33 -0400 Subject: [PATCH 298/618] Prevent syntax error in ld linker version script --- src/librustc_codegen_ssa/back/linker.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index 26091005f25aa..de481d2262478 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -430,10 +430,13 @@ impl<'a> Linker for GccLinker<'a> { // Write an LD version script let res: io::Result<()> = try { let mut f = BufWriter::new(File::create(&path)?); - writeln!(f, "{{\n global:")?; - for sym in self.info.exports[&crate_type].iter() { - debug!(" {};", sym); - writeln!(f, " {};", sym)?; + writeln!(f, "{{")?; + if !self.info.exports[&crate_type].is_empty() { + writeln!(f, " global:")?; + for sym in self.info.exports[&crate_type].iter() { + debug!(" {};", sym); + writeln!(f, " {};", sym)?; + } } writeln!(f, "\n local:\n *;\n}};")?; }; From 85d6b7b9d3d946b35826298e3d04381f96427433 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Wed, 28 Aug 2019 03:58:42 +0200 Subject: [PATCH 299/618] Address naming and comments from reviews --- src/librustc/mir/interpret/allocation.rs | 8 ++++---- src/librustc_codegen_llvm/consts.rs | 6 +++--- src/librustc_mir/interpret/memory.rs | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index d3f87f16313d0..dcfa2e5cb4691 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -136,7 +136,7 @@ impl Allocation { self.size.bytes() as usize } - /// Look at a slice which may describe undefined bytes or describe a relocation. This differs + /// Looks at a slice which may describe undefined bytes or describe a relocation. This differs /// from `get_bytes_with_undef_and_ptr` in that it does no relocation checks (even on the /// edges) at all. It further ignores `AllocationExtra` callbacks. /// This must not be used for reads affecting the interpreter execution. @@ -144,7 +144,7 @@ impl Allocation { &self.bytes[range] } - /// View the undef mask. + /// Returns the undef mask. pub fn undef_mask(&self) -> &UndefMask { &self.undef_mask } @@ -583,7 +583,7 @@ pub struct AllocationDefinedness { /// Transferring the definedness mask to other allocations. impl Allocation { /// Creates a run-length encoding of the undef_mask. - pub fn compress_defined_range( + pub fn compress_undef_range( &self, src: Pointer, size: Size, @@ -622,7 +622,7 @@ impl Allocation { } /// Apply multiple instances of the run-length encoding to the undef_mask. - pub fn mark_compressed_range( + pub fn mark_compressed_undef_range( &mut self, defined: &AllocationDefinedness, dest: Pointer, diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 26eb870cfc0d4..8725e69b11270 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -35,9 +35,9 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll assert_eq!(offset as usize as u64, offset); let offset = offset as usize; if offset > next_offset { - // This `inspect` is okay since we have check that it is not within a relocation, it is - // within the bounds of the allocation, and it doesn't affect interpreter execution (we - // inspect the result after interpreter execution). Any undef byte is replaced with + // This `inspect` is okay since we have checked that it is not within a relocation, it + // is within the bounds of the allocation, and it doesn't affect interpreter execution + // (we inspect the result after interpreter execution). Any undef byte is replaced with // some arbitrary byte value. // // FIXME: relay undef bytes to codegen as undef const bytes diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index f7576a41e0f00..7f7729ae5e0f4 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -900,11 +900,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { assert_eq!(size.bytes() as usize as u64, size.bytes()); let src_alloc = self.get(src.alloc_id)?; - let compressed = src_alloc.compress_defined_range(src, size); + let compressed = src_alloc.compress_undef_range(src, size); // now fill in all the data let dest_allocation = self.get_mut(dest.alloc_id)?; - dest_allocation.mark_compressed_range(&compressed, dest, size, repeat); + dest_allocation.mark_compressed_undef_range(&compressed, dest, size, repeat); Ok(()) } From 0006216c9d83dabed3f13f5ed231c152561ceb6a Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 28 Aug 2019 11:23:41 +0300 Subject: [PATCH 300/618] rustc_apfloat: make the crate #![no_std] explicitly. --- src/librustc_apfloat/ieee.rs | 16 ++++++++-------- src/librustc_apfloat/lib.rs | 36 ++++++++++++++++++++---------------- src/librustc_apfloat/ppc.rs | 6 +++--- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/librustc_apfloat/ieee.rs b/src/librustc_apfloat/ieee.rs index 9f68d770b9e87..18d968fbddd9b 100644 --- a/src/librustc_apfloat/ieee.rs +++ b/src/librustc_apfloat/ieee.rs @@ -1,13 +1,13 @@ use crate::{Category, ExpInt, IEK_INF, IEK_NAN, IEK_ZERO}; use crate::{Float, FloatConvert, ParseError, Round, Status, StatusAnd}; +use core::cmp::{self, Ordering}; +use core::convert::TryFrom; +use core::fmt::{self, Write}; +use core::marker::PhantomData; +use core::mem; +use core::ops::Neg; use smallvec::{SmallVec, smallvec}; -use std::cmp::{self, Ordering}; -use std::convert::TryFrom; -use std::fmt::{self, Write}; -use std::marker::PhantomData; -use std::mem; -use std::ops::Neg; #[must_use] pub struct IeeeFloat { @@ -2287,8 +2287,8 @@ impl Loss { /// Implementation details of IeeeFloat significands, such as big integer arithmetic. /// As a rule of thumb, no functions in this module should dynamically allocate. mod sig { - use std::cmp::Ordering; - use std::mem; + use core::cmp::Ordering; + use core::mem; use super::{ExpInt, Limb, LIMB_BITS, limbs_for_bits, Loss}; pub(super) fn is_all_zeros(limbs: &[Limb]) -> bool { diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs index 9e6d5a6f62434..1190cea21acc3 100644 --- a/src/librustc_apfloat/lib.rs +++ b/src/librustc_apfloat/lib.rs @@ -31,15 +31,19 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![no_std] #![forbid(unsafe_code)] #![feature(nll)] -use std::cmp::Ordering; -use std::fmt; -use std::ops::{Neg, Add, Sub, Mul, Div, Rem}; -use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; -use std::str::FromStr; +#[macro_use] +extern crate alloc; + +use core::cmp::Ordering; +use core::fmt; +use core::ops::{Neg, Add, Sub, Mul, Div, Rem}; +use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; +use core::str::FromStr; bitflags::bitflags! { /// IEEE-754R 7: Default exception handling. @@ -587,7 +591,7 @@ macro_rules! float_common_impls { } } - impl<$t> ::std::str::FromStr for $ty<$t> where Self: Float { + impl<$t> ::core::str::FromStr for $ty<$t> where Self: Float { type Err = ParseError; fn from_str(s: &str) -> Result { Self::from_str_r(s, Round::NearestTiesToEven).map(|x| x.value) @@ -596,66 +600,66 @@ macro_rules! float_common_impls { // Rounding ties to the nearest even, by default. - impl<$t> ::std::ops::Add for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Add for $ty<$t> where Self: Float { type Output = StatusAnd; fn add(self, rhs: Self) -> StatusAnd { self.add_r(rhs, Round::NearestTiesToEven) } } - impl<$t> ::std::ops::Sub for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Sub for $ty<$t> where Self: Float { type Output = StatusAnd; fn sub(self, rhs: Self) -> StatusAnd { self.sub_r(rhs, Round::NearestTiesToEven) } } - impl<$t> ::std::ops::Mul for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Mul for $ty<$t> where Self: Float { type Output = StatusAnd; fn mul(self, rhs: Self) -> StatusAnd { self.mul_r(rhs, Round::NearestTiesToEven) } } - impl<$t> ::std::ops::Div for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Div for $ty<$t> where Self: Float { type Output = StatusAnd; fn div(self, rhs: Self) -> StatusAnd { self.div_r(rhs, Round::NearestTiesToEven) } } - impl<$t> ::std::ops::Rem for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Rem for $ty<$t> where Self: Float { type Output = StatusAnd; fn rem(self, rhs: Self) -> StatusAnd { self.c_fmod(rhs) } } - impl<$t> ::std::ops::AddAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::AddAssign for $ty<$t> where Self: Float { fn add_assign(&mut self, rhs: Self) { *self = (*self + rhs).value; } } - impl<$t> ::std::ops::SubAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::SubAssign for $ty<$t> where Self: Float { fn sub_assign(&mut self, rhs: Self) { *self = (*self - rhs).value; } } - impl<$t> ::std::ops::MulAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::MulAssign for $ty<$t> where Self: Float { fn mul_assign(&mut self, rhs: Self) { *self = (*self * rhs).value; } } - impl<$t> ::std::ops::DivAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::DivAssign for $ty<$t> where Self: Float { fn div_assign(&mut self, rhs: Self) { *self = (*self / rhs).value; } } - impl<$t> ::std::ops::RemAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::RemAssign for $ty<$t> where Self: Float { fn rem_assign(&mut self, rhs: Self) { *self = (*self % rhs).value; } diff --git a/src/librustc_apfloat/ppc.rs b/src/librustc_apfloat/ppc.rs index ddccfd6ca623b..8e2e390568e48 100644 --- a/src/librustc_apfloat/ppc.rs +++ b/src/librustc_apfloat/ppc.rs @@ -1,9 +1,9 @@ use crate::{Category, ExpInt, Float, FloatConvert, Round, ParseError, Status, StatusAnd}; use crate::ieee; -use std::cmp::Ordering; -use std::fmt; -use std::ops::Neg; +use core::cmp::Ordering; +use core::fmt; +use core::ops::Neg; #[must_use] #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] From 06228d33cac6770653d6798cf5f80d1269e5482d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 24 Jul 2019 17:50:48 +0200 Subject: [PATCH 301/618] Save crate filtering on rustdoc --- src/librustdoc/html/static/main.js | 20 ++++++++++++++++++-- src/librustdoc/html/static/storage.js | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 82d2c11b2497b..1dd8b0ad686f5 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -445,6 +445,21 @@ if (!DOMTokenList.prototype.remove) { var OUTPUT_DATA = 1; var params = getQueryStringParams(); + // Set the crate filter from saved storage, if the current page has the saved crate filter. + // + // If not, ignore the crate filter -- we want to support filtering for crates on sites like + // doc.rust-lang.org where the crates may differ from page to page while on the same domain. + var savedCrate = getCurrentValue("rustdoc-saved-filter-crate"); + if (savedCrate !== null) { + onEachLazy(document.getElementById("crate-search").getElementsByTagName("option"), + function(e) { + if (e.value === savedCrate) { + document.getElementById("crate-search").value = e.value; + return true; + } + }); + } + // Populate search bar with query string search term when provided, // but only if the input bar is empty. This avoid the obnoxious issue // where you start trying to do a search, and the index loads, and @@ -1658,9 +1673,10 @@ if (!DOMTokenList.prototype.remove) { }; search_input.onpaste = search_input.onchange; - var selectCrate = document.getElementById('crate-search'); + var selectCrate = document.getElementById("crate-search"); if (selectCrate) { selectCrate.onchange = function() { + updateLocalStorage("rustdoc-saved-filter-crate", selectCrate.value); search(undefined, true); }; } @@ -2496,7 +2512,7 @@ if (!DOMTokenList.prototype.remove) { } function addSearchOptions(crates) { - var elem = document.getElementById('crate-search'); + var elem = document.getElementById("crate-search"); if (!elem) { return; diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index e3927350d1104..dd16664395bb2 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -57,7 +57,7 @@ function onEachLazy(lazyArray, func, reversed) { function usableLocalStorage() { // Check if the browser supports localStorage at all: - if (typeof(Storage) === "undefined") { + if (typeof Storage === "undefined") { return false; } // Check if we can access it; this access will fail if the browser From cca64e73399c02b2f964e3b34f969e826d061eed Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 26 Aug 2019 21:07:58 -0400 Subject: [PATCH 302/618] Add some comments to `mir::Static` and `mir::StaticKind` --- src/librustc/mir/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 60efeaab97602..a5ef3792c6b96 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1733,6 +1733,10 @@ pub enum PlaceBase<'tcx> { pub struct Static<'tcx> { pub ty: Ty<'tcx>, pub kind: StaticKind<'tcx>, + /// The `DefId` of the item this static was declared in. For promoted values, usually, this is + /// the same as the `DefId` of the `mir::Body` containing the `Place` this promoted appears in. + /// However, after inlining, that might no longer be the case as inlined `Place`s are copied + /// into the calling frame. pub def_id: DefId, } @@ -1740,6 +1744,9 @@ pub struct Static<'tcx> { Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable, )] pub enum StaticKind<'tcx> { + /// Promoted references consist of an id (`Promoted`) and the substs necessary to monomorphize + /// it. Usually, these substs are just the identity substs for the item. However, the inliner + /// will adjust these substs when it inlines a function based on the substs at the callsite. Promoted(Promoted, SubstsRef<'tcx>), Static, } From 30b29ab0f7c54a2ca74de5117395371101fa9518 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 26 Aug 2019 21:58:16 -0400 Subject: [PATCH 303/618] Simplify `maybe_get_optimized_mir` and `maybe_get_promoted_mir` Since both functions are always unwrapped, don't wrap the return value in an `Option`. --- src/librustc_metadata/cstore_impl.rs | 20 ++--------------- src/librustc_metadata/decoder.rs | 32 ++++++++++++++++++---------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 7aeeef00ea934..81e0cd7a4c4dd 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -127,24 +127,8 @@ provide! { <'tcx> tcx, def_id, other, cdata, bug!("coerce_unsized_info: `{:?}` is missing its info", def_id); }) } - optimized_mir => { - let mir = cdata.maybe_get_optimized_mir(tcx, def_id.index).unwrap_or_else(|| { - bug!("get_optimized_mir: missing MIR for `{:?}`", def_id) - }); - - let mir = tcx.arena.alloc(mir); - - mir - } - promoted_mir => { - let promoted = cdata.maybe_get_promoted_mir(tcx, def_id.index).unwrap_or_else(|| { - bug!("get_promoted_mir: missing promoted MIR for `{:?}`", def_id) - }); - - let promoted = tcx.arena.alloc(promoted); - - promoted - } + optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) } + promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) } mir_const_qualif => { (cdata.mir_const_qualif(def_id.index), tcx.arena.alloc(BitSet::new_empty(0))) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 5b9cb966af235..10b165c906625 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -917,22 +917,32 @@ impl<'a, 'tcx> CrateMetadata { self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some() } - pub fn maybe_get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Option> { - match self.is_proc_macro(id) { - true => None, - false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))), - } + pub fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { + let mir = + match self.is_proc_macro(id) { + true => None, + false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))), + }; + + mir.unwrap_or_else(|| { + bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id)) + }) } - pub fn maybe_get_promoted_mir( + pub fn get_promoted_mir( &self, tcx: TyCtxt<'tcx>, id: DefIndex, - ) -> Option>> { - match self.is_proc_macro(id) { - true => None, - false => self.entry(id).promoted_mir.map(|promoted| promoted.decode((self, tcx)),) - } + ) -> IndexVec> { + let promoted = + match self.is_proc_macro(id) { + true => None, + false => self.entry(id).promoted_mir.map(|promoted| promoted.decode((self, tcx))) + }; + + promoted.unwrap_or_else(|| { + bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id)) + }) } pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { From 009cce88ebcbdb5825c86fd7f3ff84216a2d3fec Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 27 Aug 2019 21:24:57 -0400 Subject: [PATCH 304/618] Extract `Decoder::entry_unless_proc_macro()` --- src/librustc_metadata/decoder.rs | 42 +++++++++++++++----------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 10b165c906625..4d2f9f58226d7 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -450,11 +450,19 @@ impl<'a, 'tcx> CrateMetadata { pub fn is_proc_macro_crate(&self) -> bool { self.root.proc_macro_decls_static.is_some() } + fn is_proc_macro(&self, id: DefIndex) -> bool { self.is_proc_macro_crate() && self.root.proc_macro_data.unwrap().decode(self).find(|x| *x == id).is_some() } + fn entry_unless_proc_macro(&self, id: DefIndex) -> Option> { + match self.is_proc_macro(id) { + true => None, + false => Some(self.entry(id)), + } + } + fn maybe_entry(&self, item_id: DefIndex) -> Option>> { self.root.entries_index.lookup(self.blob.raw_bytes(), item_id) } @@ -704,10 +712,8 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_deprecation(&self, id: DefIndex) -> Option { - match self.is_proc_macro(id) { - true => None, - false => self.entry(id).deprecation.map(|depr| depr.decode(self)), - } + self.entry_unless_proc_macro(id) + .and_then(|entry| entry.deprecation.map(|depr| depr.decode(self))) } pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility { @@ -918,15 +924,11 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { - let mir = - match self.is_proc_macro(id) { - true => None, - false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))), - }; - - mir.unwrap_or_else(|| { - bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id)) - }) + self.entry_unless_proc_macro(id) + .and_then(|entry| entry.mir.map(|mir| mir.decode((self, tcx)))) + .unwrap_or_else(|| { + bug!("get_optimized_mir: missing MIR for `{:?}", self.local_def_id(id)) + }) } pub fn get_promoted_mir( @@ -934,15 +936,11 @@ impl<'a, 'tcx> CrateMetadata { tcx: TyCtxt<'tcx>, id: DefIndex, ) -> IndexVec> { - let promoted = - match self.is_proc_macro(id) { - true => None, - false => self.entry(id).promoted_mir.map(|promoted| promoted.decode((self, tcx))) - }; - - promoted.unwrap_or_else(|| { - bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id)) - }) + self.entry_unless_proc_macro(id) + .and_then(|entry| entry.promoted_mir.map(|promoted| promoted.decode((self, tcx)))) + .unwrap_or_else(|| { + bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id)) + }) } pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { From 8cf392114da9deb8bdf160b196b8fd1503fb395e Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 28 Aug 2019 13:23:00 +0200 Subject: [PATCH 305/618] Notify me (flip1995) when Clippy toolstate changes --- src/tools/publish_toolstate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 648838d26efe9..1411f4c0b05a2 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -22,7 +22,7 @@ # List of people to ping when the status of a tool or a book changed. MAINTAINERS = { 'miri': '@oli-obk @RalfJung @eddyb', - 'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk @phansch', + 'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk @phansch @flip1995', 'rls': '@Xanewok', 'rustfmt': '@topecongiro', 'book': '@carols10cents @steveklabnik', From bc91706a84bcbcf2bcbbf4b38196a219f2cf62ee Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 28 Aug 2019 13:25:04 +0200 Subject: [PATCH 306/618] Update Clippy --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index 05f603e6cec63..a939d61cf7fea 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 05f603e6cec63d0b2681a84d4a64a51bccac1624 +Subproject commit a939d61cf7feac0f328aec07f050c4ac96c51d2c From 8e10725317f9d55f41a881cfadd8cfa2e3f8c59e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 28 Aug 2019 22:36:56 +0900 Subject: [PATCH 307/618] Update rustfmt to 1.4.6 --- Cargo.lock | 2 +- src/tools/rustfmt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b294b22026ed..7749979430514 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3578,7 +3578,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.5" +version = "1.4.6" dependencies = [ "annotate-snippets", "atty", diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 9792ff05297c0..f800ce47d1da2 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 9792ff05297c0a5c40942b346c9b0341b9e7c0ee +Subproject commit f800ce47d1da2a1c02ffd260deca8b7445f7facf From 8fe65da935d7e01dbac897dcfbb4fb0f9f24e442 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 23 Jul 2019 07:25:34 -0700 Subject: [PATCH 308/618] std: Remove the `wasm_syscall` feature This commit removes the `wasm_syscall` feature from the wasm32-unknown-unknown build of the standard library. This feature was originally intended to allow an opt-in way to interact with the operating system in a posix-like way but it was never stabilized. Nowadays with the advent of the `wasm32-wasi` target that should entirely replace the intentions of the `wasm_syscall` feature. --- config.toml.example | 5 - src/bootstrap/config.rs | 3 - src/bootstrap/lib.rs | 3 - src/bootstrap/test.rs | 10 -- src/etc/wasm32-shim.js | 108 +---------------- src/libstd/Cargo.toml | 5 - src/libstd/sys/wasm/args.rs | 4 +- src/libstd/sys/wasm/mod.rs | 222 +---------------------------------- src/libstd/sys/wasm/os.rs | 18 +-- src/libstd/sys/wasm/stdio.rs | 15 +-- src/libstd/sys/wasm/time.rs | 5 +- 11 files changed, 19 insertions(+), 379 deletions(-) diff --git a/config.toml.example b/config.toml.example index a3ec4f2044cbd..30e2ee1b9babf 100644 --- a/config.toml.example +++ b/config.toml.example @@ -382,11 +382,6 @@ # This is the name of the directory in which codegen backends will get installed #codegen-backends-dir = "codegen-backends" -# Flag indicating whether `libstd` calls an imported function to handle basic IO -# when targeting WebAssembly. Enable this to debug tests for the `wasm32-unknown-unknown` -# target, as without this option the test output will not be captured. -#wasm-syscall = false - # Indicates whether LLD will be compiled and made available in the sysroot for # rustc to execute. #lld = false diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index a5bfafdfdb4dc..43d9264eaca92 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -122,7 +122,6 @@ pub struct Config { // libstd features pub backtrace: bool, // support for RUST_BACKTRACE - pub wasm_syscall: bool, // misc pub low_priority: bool, @@ -318,7 +317,6 @@ struct Rust { save_toolstates: Option, codegen_backends: Option>, codegen_backends_dir: Option, - wasm_syscall: Option, lld: Option, lldb: Option, llvm_tools: Option, @@ -558,7 +556,6 @@ impl Config { if let Some(true) = rust.incremental { config.incremental = true; } - set(&mut config.wasm_syscall, rust.wasm_syscall); set(&mut config.lld_enabled, rust.lld); set(&mut config.lldb_enabled, rust.lldb); set(&mut config.llvm_tools_enabled, rust.llvm_tools); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index c0e0ad1a857b9..0982f22473392 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -498,9 +498,6 @@ impl Build { if self.config.profiler { features.push_str(" profiler"); } - if self.config.wasm_syscall { - features.push_str(" wasm_syscall"); - } features } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 2bb053cc2b002..97b28ed9e96c8 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1811,16 +1811,6 @@ impl Step for Crate { .expect("nodejs not configured"), ); } else if target.starts_with("wasm32") { - // Warn about running tests without the `wasm_syscall` feature enabled. - // The javascript shim implements the syscall interface so that test - // output can be correctly reported. - if !builder.config.wasm_syscall { - builder.info( - "Libstd was built without `wasm_syscall` feature enabled: \ - test output may not be visible." - ); - } - // On the wasm32-unknown-unknown target we're using LTO which is // incompatible with `-C prefer-dynamic`, so disable that here cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); diff --git a/src/etc/wasm32-shim.js b/src/etc/wasm32-shim.js index 2a89c0d321d6a..262a53eabe3c7 100644 --- a/src/etc/wasm32-shim.js +++ b/src/etc/wasm32-shim.js @@ -15,113 +15,7 @@ const buffer = fs.readFileSync(process.argv[2]); Error.stackTraceLimit = 20; let m = new WebAssembly.Module(buffer); - -let memory = null; - -function viewstruct(data, fields) { - return new Uint32Array(memory.buffer).subarray(data/4, data/4 + fields); -} - -function copystr(a, b) { - let view = new Uint8Array(memory.buffer).subarray(a, a + b); - return String.fromCharCode.apply(null, view); -} - -function syscall_write([fd, ptr, len]) { - let s = copystr(ptr, len); - switch (fd) { - case 1: process.stdout.write(s); break; - case 2: process.stderr.write(s); break; - } -} - -function syscall_exit([code]) { - process.exit(code); -} - -function syscall_args(params) { - let [ptr, len] = params; - - // Calculate total required buffer size - let totalLen = -1; - for (let i = 2; i < process.argv.length; ++i) { - totalLen += Buffer.byteLength(process.argv[i]) + 1; - } - if (totalLen < 0) { totalLen = 0; } - params[2] = totalLen; - - // If buffer is large enough, copy data - if (len >= totalLen) { - let view = new Uint8Array(memory.buffer); - for (let i = 2; i < process.argv.length; ++i) { - let value = process.argv[i]; - Buffer.from(value).copy(view, ptr); - ptr += Buffer.byteLength(process.argv[i]) + 1; - } - } -} - -function syscall_getenv(params) { - let [keyPtr, keyLen, valuePtr, valueLen] = params; - - let key = copystr(keyPtr, keyLen); - let value = process.env[key]; - - if (value == null) { - params[4] = 0xFFFFFFFF; - } else { - let view = new Uint8Array(memory.buffer); - let totalLen = Buffer.byteLength(value); - params[4] = totalLen; - if (valueLen >= totalLen) { - Buffer.from(value).copy(view, valuePtr); - } - } -} - -function syscall_time(params) { - let t = Date.now(); - let secs = Math.floor(t / 1000); - let millis = t % 1000; - params[1] = Math.floor(secs / 0x100000000); - params[2] = secs % 0x100000000; - params[3] = Math.floor(millis * 1000000); -} - -let imports = {}; -imports.env = { - // These are generated by LLVM itself for various intrinsic calls. Hopefully - // one day this is not necessary and something will automatically do this. - fmod: function(x, y) { return x % y; }, - exp2: function(x) { return Math.pow(2, x); }, - exp2f: function(x) { return Math.pow(2, x); }, - ldexp: function(x, y) { return x * Math.pow(2, y); }, - ldexpf: function(x, y) { return x * Math.pow(2, y); }, - sin: Math.sin, - sinf: Math.sin, - cos: Math.cos, - cosf: Math.cos, - log: Math.log, - log2: Math.log2, - log10: Math.log10, - log10f: Math.log10, - - rust_wasm_syscall: function(index, data) { - switch (index) { - case 1: syscall_write(viewstruct(data, 3)); return true; - case 2: syscall_exit(viewstruct(data, 1)); return true; - case 3: syscall_args(viewstruct(data, 3)); return true; - case 4: syscall_getenv(viewstruct(data, 5)); return true; - case 6: syscall_time(viewstruct(data, 4)); return true; - default: - console.log("Unsupported syscall: " + index); - return false; - } - } -}; - -let instance = new WebAssembly.Instance(m, imports); -memory = instance.exports.memory; +let instance = new WebAssembly.Instance(m, {}); try { instance.exports.main(); } catch (e) { diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index bb77a5bdea493..157faa0af9bca 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -70,11 +70,6 @@ llvm-libunwind = ["unwind/llvm-libunwind"] # Make panics and failed asserts immediately abort without formatting any message panic_immediate_abort = ["core/panic_immediate_abort"] -# An off-by-default feature which enables a linux-syscall-like ABI for libstd to -# interoperate with the host environment. Currently not well documented and -# requires rebuilding the standard library to use it. -wasm_syscall = [] - # Enable std_detect default features for stdarch/crates/std_detect: # https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml std_detect_file_io = [] diff --git a/src/libstd/sys/wasm/args.rs b/src/libstd/sys/wasm/args.rs index b3c77b8699563..8279e5280e924 100644 --- a/src/libstd/sys/wasm/args.rs +++ b/src/libstd/sys/wasm/args.rs @@ -1,7 +1,6 @@ use crate::ffi::OsString; use crate::marker::PhantomData; use crate::vec; -use crate::sys::ArgsSysCall; pub unsafe fn init(_argc: isize, _argv: *const *const u8) { // On wasm these should always be null, so there's nothing for us to do here @@ -11,9 +10,8 @@ pub unsafe fn cleanup() { } pub fn args() -> Args { - let v = ArgsSysCall::perform(); Args { - iter: v.into_iter(), + iter: Vec::new().into_iter(), _dont_send_or_sync_me: PhantomData, } } diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs index 56cbafcfdb8a2..de0bb38dc319e 100644 --- a/src/libstd/sys/wasm/mod.rs +++ b/src/libstd/sys/wasm/mod.rs @@ -15,11 +15,6 @@ //! guaranteed to be a runtime error! use crate::os::raw::c_char; -use crate::ptr; -use crate::sys::os_str::Buf; -use crate::sys_common::{AsInner, FromInner}; -use crate::ffi::{OsString, OsStr}; -use crate::time::Duration; pub mod alloc; pub mod args; @@ -89,7 +84,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize { } pub unsafe fn abort_internal() -> ! { - ExitSysCall::perform(1) + crate::arch::wasm32::unreachable() } // We don't have randomness yet, but I totally used a random number generator to @@ -100,218 +95,3 @@ pub unsafe fn abort_internal() -> ! { pub fn hashmap_random_keys() -> (u64, u64) { (1, 2) } - -// Implement a minimal set of system calls to enable basic IO -pub enum SysCallIndex { - Read = 0, - Write = 1, - Exit = 2, - Args = 3, - GetEnv = 4, - SetEnv = 5, - Time = 6, -} - -#[repr(C)] -pub struct ReadSysCall { - fd: usize, - ptr: *mut u8, - len: usize, - result: usize, -} - -impl ReadSysCall { - pub fn perform(fd: usize, buffer: &mut [u8]) -> usize { - let mut call_record = ReadSysCall { - fd, - len: buffer.len(), - ptr: buffer.as_mut_ptr(), - result: 0 - }; - if unsafe { syscall(SysCallIndex::Read, &mut call_record) } { - call_record.result - } else { - 0 - } - } -} - -#[repr(C)] -pub struct WriteSysCall { - fd: usize, - ptr: *const u8, - len: usize, -} - -impl WriteSysCall { - pub fn perform(fd: usize, buffer: &[u8]) { - let mut call_record = WriteSysCall { - fd, - len: buffer.len(), - ptr: buffer.as_ptr() - }; - unsafe { syscall(SysCallIndex::Write, &mut call_record); } - } -} - -#[repr(C)] -pub struct ExitSysCall { - code: usize, -} - -impl ExitSysCall { - pub fn perform(code: usize) -> ! { - let mut call_record = ExitSysCall { - code - }; - unsafe { - syscall(SysCallIndex::Exit, &mut call_record); - crate::intrinsics::abort(); - } - } -} - -fn receive_buffer Result>(estimate: usize, mut f: F) - -> Result, E> -{ - let mut buffer = vec![0; estimate]; - loop { - let result = f(&mut buffer)?; - if result <= buffer.len() { - buffer.truncate(result); - break; - } - buffer.resize(result, 0); - } - Ok(buffer) -} - -#[repr(C)] -pub struct ArgsSysCall { - ptr: *mut u8, - len: usize, - result: usize -} - -impl ArgsSysCall { - pub fn perform() -> Vec { - receive_buffer(1024, |buffer| -> Result { - let mut call_record = ArgsSysCall { - len: buffer.len(), - ptr: buffer.as_mut_ptr(), - result: 0 - }; - if unsafe { syscall(SysCallIndex::Args, &mut call_record) } { - Ok(call_record.result) - } else { - Ok(0) - } - }) - .unwrap() - .split(|b| *b == 0) - .map(|s| FromInner::from_inner(Buf { inner: s.to_owned() })) - .collect() - } -} - -#[repr(C)] -pub struct GetEnvSysCall { - key_ptr: *const u8, - key_len: usize, - value_ptr: *mut u8, - value_len: usize, - result: usize -} - -impl GetEnvSysCall { - pub fn perform(key: &OsStr) -> Option { - let key_buf = &AsInner::as_inner(key).inner; - receive_buffer(64, |buffer| { - let mut call_record = GetEnvSysCall { - key_len: key_buf.len(), - key_ptr: key_buf.as_ptr(), - value_len: buffer.len(), - value_ptr: buffer.as_mut_ptr(), - result: !0usize - }; - if unsafe { syscall(SysCallIndex::GetEnv, &mut call_record) } { - if call_record.result == !0usize { - Err(()) - } else { - Ok(call_record.result) - } - } else { - Err(()) - } - }).ok().map(|s| { - FromInner::from_inner(Buf { inner: s }) - }) - } -} - -#[repr(C)] -pub struct SetEnvSysCall { - key_ptr: *const u8, - key_len: usize, - value_ptr: *const u8, - value_len: usize -} - -impl SetEnvSysCall { - pub fn perform(key: &OsStr, value: Option<&OsStr>) { - let key_buf = &AsInner::as_inner(key).inner; - let value_buf = value.map(|v| &AsInner::as_inner(v).inner); - let mut call_record = SetEnvSysCall { - key_len: key_buf.len(), - key_ptr: key_buf.as_ptr(), - value_len: value_buf.map(|v| v.len()).unwrap_or(!0usize), - value_ptr: value_buf.map(|v| v.as_ptr()).unwrap_or(ptr::null()) - }; - unsafe { syscall(SysCallIndex::SetEnv, &mut call_record); } - } -} - -pub enum TimeClock { - Monotonic = 0, - System = 1, -} - -#[repr(C)] -pub struct TimeSysCall { - clock: usize, - secs_hi: usize, - secs_lo: usize, - nanos: usize -} - -impl TimeSysCall { - pub fn perform(clock: TimeClock) -> Duration { - let mut call_record = TimeSysCall { - clock: clock as usize, - secs_hi: 0, - secs_lo: 0, - nanos: 0 - }; - if unsafe { syscall(SysCallIndex::Time, &mut call_record) } { - Duration::new( - ((call_record.secs_hi as u64) << 32) | (call_record.secs_lo as u64), - call_record.nanos as u32 - ) - } else { - panic!("Time system call is not implemented by WebAssembly host"); - } - } -} - -unsafe fn syscall(index: SysCallIndex, data: &mut T) -> bool { - #[cfg(feature = "wasm_syscall")] - extern { - #[no_mangle] - fn rust_wasm_syscall(index: usize, data: *mut Void) -> usize; - } - - #[cfg(not(feature = "wasm_syscall"))] - unsafe fn rust_wasm_syscall(_index: usize, _data: *mut Void) -> usize { 0 } - - rust_wasm_syscall(index as usize, data as *mut T as *mut Void) != 0 -} diff --git a/src/libstd/sys/wasm/os.rs b/src/libstd/sys/wasm/os.rs index 5d21999a991e1..890049e8bfae5 100644 --- a/src/libstd/sys/wasm/os.rs +++ b/src/libstd/sys/wasm/os.rs @@ -4,7 +4,7 @@ use crate::fmt; use crate::io; use crate::path::{self, PathBuf}; use crate::str; -use crate::sys::{unsupported, Void, ExitSysCall, GetEnvSysCall, SetEnvSysCall}; +use crate::sys::{unsupported, Void}; pub fn errno() -> i32 { 0 @@ -73,16 +73,16 @@ pub fn env() -> Env { panic!("not supported on web assembly") } -pub fn getenv(k: &OsStr) -> io::Result> { - Ok(GetEnvSysCall::perform(k)) +pub fn getenv(_: &OsStr) -> io::Result> { + Ok(None) } -pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { - Ok(SetEnvSysCall::perform(k, Some(v))) +pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::Other, "cannot set env vars on wasm32-unknown-unknown")) } -pub fn unsetenv(k: &OsStr) -> io::Result<()> { - Ok(SetEnvSysCall::perform(k, None)) +pub fn unsetenv(_: &OsStr) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::Other, "cannot unset env vars on wasm32-unknown-unknown")) } pub fn temp_dir() -> PathBuf { @@ -94,7 +94,9 @@ pub fn home_dir() -> Option { } pub fn exit(_code: i32) -> ! { - ExitSysCall::perform(_code as isize as usize) + unsafe { + crate::arch::wasm32::unreachable(); + } } pub fn getpid() -> u32 { diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs index b8899a9c84746..5a4e4505e93bd 100644 --- a/src/libstd/sys/wasm/stdio.rs +++ b/src/libstd/sys/wasm/stdio.rs @@ -1,5 +1,4 @@ use crate::io; -use crate::sys::{ReadSysCall, WriteSysCall}; pub struct Stdin; pub struct Stdout; @@ -12,8 +11,8 @@ impl Stdin { } impl io::Read for Stdin { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - Ok(ReadSysCall::perform(0, buf)) + fn read(&mut self, _buf: &mut [u8]) -> io::Result { + Ok(0) } } @@ -25,7 +24,6 @@ impl Stdout { impl io::Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { - WriteSysCall::perform(1, buf); Ok(buf.len()) } @@ -42,7 +40,6 @@ impl Stderr { impl io::Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result { - WriteSysCall::perform(2, buf); Ok(buf.len()) } @@ -57,10 +54,6 @@ pub fn is_ebadf(_err: &io::Error) -> bool { true } -pub fn panic_output() -> Option { - if cfg!(feature = "wasm_syscall") { - Stderr::new().ok() - } else { - None - } +pub fn panic_output() -> Option> { + None } diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/wasm/time.rs index 3f71461eea487..dd9ad3760b050 100644 --- a/src/libstd/sys/wasm/time.rs +++ b/src/libstd/sys/wasm/time.rs @@ -1,5 +1,4 @@ use crate::time::Duration; -use crate::sys::{TimeSysCall, TimeClock}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant(Duration); @@ -11,7 +10,7 @@ pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); impl Instant { pub fn now() -> Instant { - Instant(TimeSysCall::perform(TimeClock::Monotonic)) + panic!("time not implemented on wasm32-unknown-unknown") } pub const fn zero() -> Instant { @@ -37,7 +36,7 @@ impl Instant { impl SystemTime { pub fn now() -> SystemTime { - SystemTime(TimeSysCall::perform(TimeClock::System)) + panic!("time not implemented on wasm32-unknown-unknown") } pub fn sub_time(&self, other: &SystemTime) From 080fdb8184cea898f48818312a7645007c8b7594 Mon Sep 17 00:00:00 2001 From: Dodo Date: Wed, 28 Aug 2019 17:38:24 +0200 Subject: [PATCH 309/618] add missing `#[repr(C)]` on a union --- src/libcore/str/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index f20cb7bfbc3bd..752c372e93e3a 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2170,6 +2170,7 @@ impl str { #[inline(always)] #[rustc_const_unstable(feature="const_str_as_bytes")] pub const fn as_bytes(&self) -> &[u8] { + #[repr(C)] union Slices<'a> { str: &'a str, slice: &'a [u8], From 12e0420268a3855eea981bb8907a8bbfb1cb9d9a Mon Sep 17 00:00:00 2001 From: Nathan Date: Sun, 25 Aug 2019 21:10:33 -0400 Subject: [PATCH 310/618] Update dbg macro test to use `check-run-results` flag for run-pass test Updates the dbg-macro-expected behavior test to remove the workaround and use the `check-run-result` flag/feature in compiletest. This serves to test the feature on a real use-case (as mentioned in #63751) --- .../dbg-macro-expected-behavior.rs | 84 +------------------ .../dbg-macro-expected-behavior.run.stderr | 28 +++++++ 2 files changed, 30 insertions(+), 82 deletions(-) create mode 100644 src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs index e885263aa8084..04d924a9aed20 100644 --- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs +++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs @@ -1,7 +1,5 @@ // run-pass -// ignore-cloudabi no processes -// ignore-emscripten no processes -// ignore-sgx no processes +// check-run-results // Tests ensuring that `dbg!(expr)` has the expected run-time behavior. // as well as some compile time properties we expect. @@ -18,7 +16,7 @@ struct Point { #[derive(Debug, PartialEq)] struct NoCopy(usize); -fn test() { +fn main() { let a: Unit = dbg!(Unit); let _: Unit = dbg!(a); // We can move `a` because it's Copy. @@ -67,81 +65,3 @@ fn test() { assert_eq!((1u8, 2u32, "Yeah"), dbg!(1u8, 2u32, "Yeah",)); } - -fn validate_stderr(stderr: Vec) { - assert_eq!(stderr, &[ - ":22] Unit = Unit", - - ":23] a = Unit", - - ":29] Point{x: 42, y: 24,} = Point {", - " x: 42,", - " y: 24,", - "}", - - ":30] b = Point {", - " x: 42,", - " y: 24,", - "}", - - ":38]", - - ":42] &a = NoCopy(", - " 1337,", - ")", - - ":42] dbg!(& a) = NoCopy(", - " 1337,", - ")", - ":47] f(&42) = 42", - - "before", - ":52] { foo += 1; eprintln!(\"before\"); 7331 } = 7331", - - ":60] (\"Yeah\",) = (", - " \"Yeah\",", - ")", - - ":63] 1 = 1", - ":63] 2 = 2", - - ":67] 1u8 = 1", - ":67] 2u32 = 2", - ":67] \"Yeah\" = \"Yeah\"", - ]); -} - -fn main() { - // The following is a hack to deal with compiletest's inability - // to check the output (to stdout) of run-pass tests. - use std::env; - use std::process::Command; - - let mut args = env::args(); - let prog = args.next().unwrap(); - let child = args.next(); - if let Some("child") = child.as_ref().map(|s| &**s) { - // Only run the test if we've been spawned as 'child' - test() - } else { - // This essentially spawns as 'child' to run the tests - // and then it collects output of stderr and checks the output - // against what we expect. - let out = Command::new(&prog).arg("child").output().unwrap(); - assert!(out.status.success()); - assert!(out.stdout.is_empty()); - - let stderr = String::from_utf8(out.stderr).unwrap(); - let stderr = stderr.lines().map(|mut s| { - if s.starts_with("[") { - // Strip `[` and file path: - s = s.trim_start_matches("["); - assert!(s.starts_with(file!())); - s = s.trim_start_matches(file!()); - } - s.to_owned() - }).collect(); - - validate_stderr(stderr); - } -} diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr new file mode 100644 index 0000000000000..707b38cf37af0 --- /dev/null +++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr @@ -0,0 +1,28 @@ +[$DIR/dbg-macro-expected-behavior.rs:20] Unit = Unit +[$DIR/dbg-macro-expected-behavior.rs:21] a = Unit +[$DIR/dbg-macro-expected-behavior.rs:27] Point{x: 42, y: 24,} = Point { + x: 42, + y: 24, +} +[$DIR/dbg-macro-expected-behavior.rs:28] b = Point { + x: 42, + y: 24, +} +[$DIR/dbg-macro-expected-behavior.rs:36] +[$DIR/dbg-macro-expected-behavior.rs:40] &a = NoCopy( + 1337, +) +[$DIR/dbg-macro-expected-behavior.rs:40] dbg!(& a) = NoCopy( + 1337, +) +[$DIR/dbg-macro-expected-behavior.rs:45] f(&42) = 42 +before +[$DIR/dbg-macro-expected-behavior.rs:50] { foo += 1; eprintln!("before"); 7331 } = 7331 +[$DIR/dbg-macro-expected-behavior.rs:58] ("Yeah",) = ( + "Yeah", +) +[$DIR/dbg-macro-expected-behavior.rs:61] 1 = 1 +[$DIR/dbg-macro-expected-behavior.rs:61] 2 = 2 +[$DIR/dbg-macro-expected-behavior.rs:65] 1u8 = 1 +[$DIR/dbg-macro-expected-behavior.rs:65] 2u32 = 2 +[$DIR/dbg-macro-expected-behavior.rs:65] "Yeah" = "Yeah" From fdd8b967c180192fb74bf17f07e2fda040bb9865 Mon Sep 17 00:00:00 2001 From: Sam Radhakrishan Date: Thu, 29 Aug 2019 02:43:09 +0530 Subject: [PATCH 311/618] Fixes #63976. Incorrect error message. Fix incorrect error message when accessing private field of union --- src/librustc_typeck/check/expr.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index d139cd4264c86..4943270e193ec 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1396,8 +1396,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx().sess, expr.span, E0616, - "field `{}` of struct `{}` is private", + "field `{}` of `{}` `{}` is private", field, + if let Some(def_kind) = self.tcx().def_kind(base_did){ def_kind.descr(base_did) } + else { " " }, struct_path ); // Also check if an accessible method exists, which is often what is meant. From 35717892b9c399d7c984d7098a341db8c48d93a5 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 28 Aug 2019 14:48:02 -0700 Subject: [PATCH 312/618] Update rust-installer to limit memory use --- src/tools/rust-installer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-installer b/src/tools/rust-installer index 85958b001dbff..9f66c14c3f91a 160000 --- a/src/tools/rust-installer +++ b/src/tools/rust-installer @@ -1 +1 @@ -Subproject commit 85958b001dbff8523396809bfa844fc34a7869a8 +Subproject commit 9f66c14c3f91a48a118c7817f434167b311c3515 From 4c3e386bd7ee9020407cee4ba120eebfb6373549 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 28 Aug 2019 18:00:36 -0400 Subject: [PATCH 313/618] Allow running rustdoc on proc-macro crates without specifying '--crate-type proc-macro' Add a test to make sure that this works --- src/librustc_interface/passes.rs | 48 +++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 856690903c659..24b44964e4fd2 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -473,22 +473,38 @@ fn configure_and_expand_inner<'a>( ast_validation::check_crate(sess, &krate) }); - krate = time(sess, "maybe creating a macro crate", || { - let crate_types = sess.crate_types.borrow(); - let num_crate_types = crate_types.len(); - let is_proc_macro_crate = crate_types.contains(&config::CrateType::ProcMacro); - let is_test_crate = sess.opts.test; - syntax_ext::proc_macro_harness::inject( - &sess.parse_sess, - &mut resolver, - krate, - is_proc_macro_crate, - has_proc_macro_decls, - is_test_crate, - num_crate_types, - sess.diagnostic(), - ) - }); + + let crate_types = sess.crate_types.borrow(); + let is_proc_macro_crate = crate_types.contains(&config::CrateType::ProcMacro); + + // For backwards compatibility, we don't try to run proc macro injection + // if rustdoc is run on a proc macro crate without '--crate-type proc-macro' being + // specified. This should only affect users who manually invoke 'rustdoc', as + // 'cargo doc' will automatically pass the proper '--crate-type' flags. + // However, we do emit a warning, to let such users know that they should + // start passing '--crate-type proc-macro' + if has_proc_macro_decls && sess.opts.actually_rustdoc && !is_proc_macro_crate { + let mut msg = sess.diagnostic().struct_warn(&"Trying to document proc macro crate \ + without passing '--crate-type proc-macro to rustdoc"); + + msg.warn("The generated documentation may be incorrect"); + msg.emit() + } else { + krate = time(sess, "maybe creating a macro crate", || { + let num_crate_types = crate_types.len(); + let is_test_crate = sess.opts.test; + syntax_ext::proc_macro_harness::inject( + &sess.parse_sess, + &mut resolver, + krate, + is_proc_macro_crate, + has_proc_macro_decls, + is_test_crate, + num_crate_types, + sess.diagnostic(), + ) + }); + } // Done with macro expansion! From 820aa5b2ef9b527a67b46ef70f001151f5d66441 Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Wed, 28 Aug 2019 23:55:28 +0100 Subject: [PATCH 314/618] Stabilize pin_into_inner in 1.39.0 FCP: https://github.com/rust-lang/rust/issues/60245#issuecomment-522258129 Closes #60245 --- src/libcore/pin.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 6efeaf9ee7d2e..1080fd32a8862 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -462,7 +462,7 @@ impl> Pin

{ /// can ignore the pinning invariants when unwrapping it. /// /// [`Unpin`]: ../../std/marker/trait.Unpin.html - #[unstable(feature = "pin_into_inner", issue = "60245")] + #[stable(feature = "pin_into_inner", since = "1.39.0")] #[inline(always)] pub fn into_inner(pin: Pin

) -> P { pin.pointer @@ -569,7 +569,7 @@ impl Pin

{ /// /// [`Unpin`]: ../../std/marker/trait.Unpin.html /// [`Pin::into_inner`]: #method.into_inner - #[unstable(feature = "pin_into_inner", issue = "60245")] + #[stable(feature = "pin_into_inner", since = "1.39.0")] #[inline(always)] pub unsafe fn into_inner_unchecked(pin: Pin

) -> P { pin.pointer From ade191c70a51f6699b64423e0bc8e0f307de9ecd Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 29 Aug 2019 03:52:18 +0000 Subject: [PATCH 315/618] Small improvement for Ord implementation of integers --- src/libcore/cmp.rs | 4 ++-- src/test/codegen/integer-cmp.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 167a9dd1c3620..607427a85d67a 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -1015,8 +1015,8 @@ mod impls { // The order here is important to generate more optimal assembly. // See for more info. if *self < *other { Less } - else if *self > *other { Greater } - else { Equal } + else if *self == *other { Equal } + else { Greater } } } )*) diff --git a/src/test/codegen/integer-cmp.rs b/src/test/codegen/integer-cmp.rs index 1373b12e3721c..8ada3cf09d073 100644 --- a/src/test/codegen/integer-cmp.rs +++ b/src/test/codegen/integer-cmp.rs @@ -11,7 +11,7 @@ use std::cmp::Ordering; #[no_mangle] pub fn cmp_signed(a: i64, b: i64) -> Ordering { // CHECK: icmp slt -// CHECK: icmp sgt +// CHECK: icmp ne // CHECK: zext i1 // CHECK: select i1 a.cmp(&b) @@ -21,7 +21,7 @@ pub fn cmp_signed(a: i64, b: i64) -> Ordering { #[no_mangle] pub fn cmp_unsigned(a: u32, b: u32) -> Ordering { // CHECK: icmp ult -// CHECK: icmp ugt +// CHECK: icmp ne // CHECK: zext i1 // CHECK: select i1 a.cmp(&b) From 0e7424653e82187bd6b17bf90239247d92bb5753 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 29 Aug 2019 16:04:13 +0200 Subject: [PATCH 316/618] Add missing links on AsRef trait --- src/libcore/convert.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 641621f492baf..402a7b2c95a46 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -104,22 +104,17 @@ pub const fn identity(x: T) -> T { x } /// If you need to do a costly conversion it is better to implement [`From`] with type /// `&T` or write a custom function. /// -/// `AsRef` has the same signature as [`Borrow`], but `Borrow` is different in few aspects: +/// `AsRef` has the same signature as [`Borrow`], but [`Borrow`] is different in few aspects: /// -/// - Unlike `AsRef`, `Borrow` has a blanket impl for any `T`, and can be used to accept either +/// - Unlike `AsRef`, [`Borrow`] has a blanket impl for any `T`, and can be used to accept either /// a reference or a value. -/// - `Borrow` also requires that `Hash`, `Eq` and `Ord` for borrowed value are +/// - [`Borrow`] also requires that [`Hash`], [`Eq`] and [`Ord`] for borrowed value are /// equivalent to those of the owned value. For this reason, if you want to -/// borrow only a single field of a struct you can implement `AsRef`, but not `Borrow`. -/// -/// [`Borrow`]: ../../std/borrow/trait.Borrow.html +/// borrow only a single field of a struct you can implement `AsRef`, but not [`Borrow`]. /// /// **Note: This trait must not fail**. If the conversion can fail, use a /// dedicated method which returns an [`Option`] or a [`Result`]. /// -/// [`Option`]: ../../std/option/enum.Option.html -/// [`Result`]: ../../std/result/enum.Result.html -/// /// # Generic Implementations /// /// - `AsRef` auto-dereferences if the inner type is a reference or a mutable @@ -132,9 +127,16 @@ pub const fn identity(x: T) -> T { x } /// converted to the specified type `T`. /// /// For example: By creating a generic function that takes an `AsRef` we express that we -/// want to accept all references that can be converted to `&str` as an argument. -/// Since both [`String`] and `&str` implement `AsRef` we can accept both as input argument. +/// want to accept all references that can be converted to [`&str`] as an argument. +/// Since both [`String`] and [`&str`] implement `AsRef` we can accept both as input argument. /// +/// [`Option`]: ../../std/option/enum.Option.html +/// [`Result`]: ../../std/result/enum.Result.html +/// [`Borrow`]: ../../std/borrow/trait.Borrow.html +/// [`Hash`]: ../../std/hash/trait.Hash.html +/// [`Eq`]: ../../std/cmp/trait.Eq.html +/// [`Ord`]: ../../std/cmp/trait.Ord.html +/// [`&str`]: ../../std/primitive.str.html /// [`String`]: ../../std/string/struct.String.html /// /// ``` From 6374b8458f0796a1ff3ee2caec41321e801c35d1 Mon Sep 17 00:00:00 2001 From: newpavlov Date: Thu, 29 Aug 2019 20:13:15 +0300 Subject: [PATCH 317/618] update to wasi v0.7 --- Cargo.lock | 12 ++++ src/libstd/Cargo.toml | 2 +- src/libstd/sys/wasi/fd.rs | 104 ++++++++++++++++++---------------- src/libstd/sys/wasi/mod.rs | 13 ++++- src/libstd/sys/wasi/thread.rs | 2 +- 5 files changed, 80 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8ae21c8663706..3719b36236797 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3866,6 +3866,7 @@ dependencies = [ "rustc_msan", "rustc_tsan", "unwind", + "wasi", ] [[package]] @@ -4664,6 +4665,17 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + [[package]] name = "winapi" version = "0.2.8" diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index d801b051357a4..0d04b7a274037 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -24,7 +24,7 @@ compiler_builtins = { version = "0.1.16" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] } -wasi = { git = "https://github.com/newpavlov/rust-wasi", branch = "safe_rework", features = ['rustc-dep-of-std', 'alloc'] } +wasi = { version = "0.7.0", features = ['rustc-dep-of-std', 'alloc'] } [dependencies.backtrace] version = "0.3.35" diff --git a/src/libstd/sys/wasi/fd.rs b/src/libstd/sys/wasi/fd.rs index 275e1319be6ad..5b7a8678b66ea 100644 --- a/src/libstd/sys/wasi/fd.rs +++ b/src/libstd/sys/wasi/fd.rs @@ -53,23 +53,23 @@ impl WasiFd { } pub fn datasync(&self) -> io::Result<()> { - wasi::fd_datasync(self.fd).map_err(err2io) + unsafe { wasi::fd_datasync(self.fd).map_err(err2io) } } pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) + unsafe { wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) } } pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) + unsafe { wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) } } pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) + unsafe { wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) } } pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result { - wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) + unsafe { wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) } } pub fn seek(&self, pos: SeekFrom) -> io::Result { @@ -78,37 +78,37 @@ impl WasiFd { SeekFrom::End(pos) => (wasi::WHENCE_END, pos), SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos), }; - wasi::fd_seek(self.fd, offset, whence).map_err(err2io) + unsafe { wasi::fd_seek(self.fd, offset, whence).map_err(err2io) } } pub fn tell(&self) -> io::Result { - wasi::fd_tell(self.fd).map_err(err2io) + unsafe { wasi::fd_tell(self.fd).map_err(err2io) } } // FIXME: __wasi_fd_fdstat_get pub fn set_flags(&self, flags: wasi::FdFlags) -> io::Result<()> { - wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) + unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) } } pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> { - wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(err2io) + unsafe { wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(err2io) } } pub fn sync(&self) -> io::Result<()> { - wasi::fd_sync(self.fd).map_err(err2io) + unsafe { wasi::fd_sync(self.fd).map_err(err2io) } } pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> { - wasi::fd_advise(self.fd, offset, len, advice).map_err(err2io) + unsafe { wasi::fd_advise(self.fd, offset, len, advice).map_err(err2io) } } pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> { - wasi::fd_allocate(self.fd, offset, len).map_err(err2io) + unsafe { wasi::fd_allocate(self.fd, offset, len).map_err(err2io) } } pub fn create_directory(&self, path: &[u8]) -> io::Result<()> { - wasi::path_create_directory(self.fd, path).map_err(err2io) + unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) } } pub fn link( @@ -118,8 +118,10 @@ impl WasiFd { new_fd: &WasiFd, new_path: &[u8], ) -> io::Result<()> { - wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path) - .map_err(err2io) + unsafe { + wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path) + .map_err(err2io) + } } pub fn open( @@ -131,32 +133,35 @@ impl WasiFd { fs_rights_inheriting: wasi::Rights, fs_flags: wasi::FdFlags, ) -> io::Result { - wasi::path_open( - self.fd, - dirflags, - path, - oflags, - fs_rights_base, - fs_rights_inheriting, - fs_flags, - ).map(|fd| unsafe { WasiFd::from_raw(fd) }).map_err(err2io) + unsafe { + wasi::path_open( + self.fd, + dirflags, + path, + oflags, + fs_rights_base, + fs_rights_inheriting, + fs_flags, + ).map(|fd| WasiFd::from_raw(fd)).map_err(err2io) + } } pub fn readdir(&self, buf: &mut [u8], cookie: wasi::DirCookie) -> io::Result { - wasi::fd_readdir(self.fd, buf, cookie).map_err(err2io) + unsafe { wasi::fd_readdir(self.fd, buf, cookie).map_err(err2io) } } pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result { - wasi::path_readlink(self.fd, path, buf).map_err(err2io) + unsafe { wasi::path_readlink(self.fd, path, buf).map_err(err2io) } } pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> { - wasi::path_rename(self.fd, old_path, new_fd.fd, new_path) - .map_err(err2io) + unsafe { + wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io) + } } pub fn filestat_get(&self) -> io::Result { - wasi::fd_filestat_get(self.fd).map_err(err2io) + unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) } } pub fn filestat_set_times( @@ -165,12 +170,13 @@ impl WasiFd { mtim: wasi::Timestamp, fstflags: wasi::FstFlags, ) -> io::Result<()> { - wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags) - .map_err(err2io) + unsafe { + wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io) + } } pub fn filestat_set_size(&self, size: u64) -> io::Result<()> { - wasi::fd_filestat_set_size(self.fd, size).map_err(err2io) + unsafe { wasi::fd_filestat_set_size(self.fd, size).map_err(err2io) } } pub fn path_filestat_get( @@ -178,7 +184,7 @@ impl WasiFd { flags: wasi::LookupFlags, path: &[u8], ) -> io::Result { - wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) + unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) } } pub fn path_filestat_set_times( @@ -189,26 +195,28 @@ impl WasiFd { mtim: wasi::Timestamp, fstflags: wasi::FstFlags, ) -> io::Result<()> { - wasi::path_filestat_set_times( - self.fd, - flags, - path, - atim, - mtim, - fstflags, - ).map_err(err2io) + unsafe { + wasi::path_filestat_set_times( + self.fd, + flags, + path, + atim, + mtim, + fstflags, + ).map_err(err2io) + } } pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> { - wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) + unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) } } pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> { - wasi::path_unlink_file(self.fd, path).map_err(err2io) + unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) } } pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> { - wasi::path_remove_directory(self.fd, path).map_err(err2io) + unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) } } pub fn sock_recv( @@ -216,11 +224,11 @@ impl WasiFd { ri_data: &mut [IoSliceMut<'_>], ri_flags: wasi::RiFlags, ) -> io::Result<(usize, wasi::RoFlags)> { - wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) + unsafe { wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) } } pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::SiFlags) -> io::Result { - wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) + unsafe { wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) } } pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> { @@ -229,7 +237,7 @@ impl WasiFd { Shutdown::Write => wasi::SHUT_WR, Shutdown::Both => wasi::SHUT_WR | wasi::SHUT_RD, }; - wasi::sock_shutdown(self.fd, how).map_err(err2io) + unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) } } } @@ -237,6 +245,6 @@ impl Drop for WasiFd { fn drop(&mut self) { // FIXME: can we handle the return code here even though we can't on // unix? - let _ = wasi::fd_close(self.fd); + let _ = unsafe { wasi::fd_close(self.fd) }; } } diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs index 4007b7ac0ec5f..517e3be9cb58c 100644 --- a/src/libstd/sys/wasi/mod.rs +++ b/src/libstd/sys/wasi/mod.rs @@ -69,10 +69,17 @@ pub fn unsupported_err() -> std_io::Error { pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { use std_io::ErrorKind::*; - match errno as libc::c_int { + if errno > u16::max_value() as i32 || errno < 0 { + return Other; + } + let code = match wasi::Error::new(errno as u16) { + Some(code) => code, + None => return Other, + }; + match code { wasi::ECONNREFUSED => ConnectionRefused, wasi::ECONNRESET => ConnectionReset, - wasi::EPERM | libc::EACCES => PermissionDenied, + wasi::EPERM | wasi::EACCES => PermissionDenied, wasi::EPIPE => BrokenPipe, wasi::ENOTCONN => NotConnected, wasi::ECONNABORTED => ConnectionAborted, @@ -84,7 +91,7 @@ pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { wasi::ETIMEDOUT => TimedOut, wasi::EEXIST => AlreadyExists, wasi::EAGAIN => WouldBlock, - _ => ErrorKind::Other, + _ => Other, } } diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index dc5a72e82a354..987bf7580838b 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -47,7 +47,7 @@ impl Thread { u: wasi::raw::__wasi_subscription_u { clock: clock }, }]; let mut out: [wasi::Event; 1] = [unsafe { mem::zeroed() }]; - let n = wasi::poll_oneoff(&in_, &mut out).unwrap(); + let n = unsafe { wasi::poll_oneoff(&in_, &mut out).unwrap() }; let wasi::Event { userdata, error, type_, .. } = out[0]; match (n, userdata, error) { (1, CLOCK_ID, 0) if type_ == wasi::EVENTTYPE_CLOCK => {} From 06acfb22e03ff482275e1ffd78f691b0e5d88ffb Mon Sep 17 00:00:00 2001 From: newpavlov Date: Thu, 29 Aug 2019 20:22:24 +0300 Subject: [PATCH 318/618] add wasi license to the licenses whitelist --- src/tools/tidy/src/deps.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index e07a07234c71e..6ca912db5930d 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -15,6 +15,7 @@ const LICENSES: &[&str] = &[ "Apache-2.0 / MIT", "MIT OR Apache-2.0", "Apache-2.0 OR MIT", + "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", // wasi license "MIT", "Unlicense/MIT", "Unlicense OR MIT", From 6fe31fefd80cd1c4300b03b1e55c63de12134eed Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Thu, 29 Aug 2019 18:02:51 +0200 Subject: [PATCH 319/618] Make allocation relocation field private --- src/librustc/mir/interpret/allocation.rs | 13 +++++++++---- src/librustc_mir/interpret/intern.rs | 4 ++-- src/librustc_mir/interpret/memory.rs | 4 ++-- src/librustc_mir/monomorphize/collector.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 2 +- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index dcfa2e5cb4691..75319a6783167 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -35,7 +35,7 @@ pub struct Allocation { /// Only the first byte of a pointer is inserted into the map; i.e., /// every entry in this map applies to `pointer_size` consecutive bytes starting /// at the given offset. - pub relocations: Relocations, + relocations: Relocations, /// Denotes which part of this allocation is initialized. undef_mask: UndefMask, /// The size of the allocation. Currently, must always equal `bytes.len()`. @@ -148,6 +148,11 @@ impl Allocation { pub fn undef_mask(&self) -> &UndefMask { &self.undef_mask } + + /// Returns the relocation list. + pub fn relocations(&self) -> &Relocations { + &self.relocations + } } impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Allocation {} @@ -459,7 +464,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Relocations impl<'tcx, Tag: Copy, Extra> Allocation { /// Returns all relocations overlapping with the given ptr-offset pair. - pub fn relocations( + pub fn get_relocations( &self, cx: &impl HasDataLayout, ptr: Pointer, @@ -480,7 +485,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { ptr: Pointer, size: Size, ) -> InterpResult<'tcx> { - if self.relocations(cx, ptr, size).is_empty() { + if self.get_relocations(cx, ptr, size).is_empty() { Ok(()) } else { throw_unsup!(ReadPointerAsBytes) @@ -502,7 +507,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // Find the start and end of the given range and its outermost relocations. let (first, last) = { // Find all relocations overlapping the given range. - let relocations = self.relocations(cx, ptr, size); + let relocations = self.get_relocations(cx, ptr, size); if relocations.is_empty() { return Ok(()); } diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 32ba70a81c997..4cbbc0ffe17cc 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -94,7 +94,7 @@ impl<'rt, 'mir, 'tcx> InternVisitor<'rt, 'mir, 'tcx> { alloc.mutability = mutability; // link the alloc id to the actual allocation let alloc = tcx.intern_const_alloc(alloc); - self.leftover_relocations.extend(alloc.relocations.iter().map(|&(_, ((), reloc))| reloc)); + self.leftover_relocations.extend(alloc.relocations().iter().map(|&(_, ((), reloc))| reloc)); tcx.alloc_map.lock().set_alloc_id_memory(ptr.alloc_id, alloc); Ok(None) } @@ -316,7 +316,7 @@ pub fn intern_const_alloc_recursive( // So we hand-roll the interning logic here again let alloc = tcx.intern_const_alloc(alloc); tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc); - for &(_, ((), reloc)) in alloc.relocations.iter() { + for &(_, ((), reloc)) in alloc.relocations().iter() { if leftover_relocations.insert(reloc) { todo.push(reloc); } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 7f7729ae5e0f4..26b3f0be8c2b8 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -647,7 +647,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { for i in 0..alloc.size.bytes() { let i = Size::from_bytes(i); - if let Some(&(_, target_id)) = alloc.relocations.get(&i) { + if let Some(&(_, target_id)) = alloc.relocations().get(&i) { if allocs_seen.insert(target_id) { allocs_to_print.push_back(target_id); } @@ -809,7 +809,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // (`get_bytes_with_undef_and_ptr` below checks that there are no // relocations overlapping the edges; those would not be handled correctly). let relocations = { - let relocations = self.get(src.alloc_id)?.relocations(self, src, size); + let relocations = self.get(src.alloc_id)?.get_relocations(self, src, size); if relocations.is_empty() { // nothing to copy, ignore even the `length` loop Vec::new() diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 12d763bb7910a..a9403502f64d3 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1202,7 +1202,7 @@ fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut Vec { trace!("collecting {:?} with {:#?}", alloc_id, alloc); - for &((), inner) in alloc.relocations.values() { + for &((), inner) in alloc.relocations().values() { collect_miri(tcx, inner, output); } }, @@ -1268,7 +1268,7 @@ fn collect_const<'tcx>( collect_miri(tcx, ptr.alloc_id, output), ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => { - for &((), id) in alloc.relocations.values() { + for &((), id) in alloc.relocations().values() { collect_miri(tcx, id, output); } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 14fc0d6347e4b..e68104c6df808 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1570,7 +1570,7 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span) } else { bug!("Matching on non-ByRef static") }; - if alloc.relocations.len() != 0 { + if alloc.relocations().len() != 0 { let msg = "statics with a custom `#[link_section]` must be a \ simple list of bytes on the wasm target with no \ extra levels of indirection such as references"; From 2e59c4afd16ea7b887f3d81b5aeea8669b843afe Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 29 Aug 2019 13:03:22 -0500 Subject: [PATCH 320/618] fix bugs + review comments --- src/tools/rustbook/src/main.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 0915600bb3875..e155f3f7607f3 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -56,21 +56,22 @@ fn main() { eprintln!("Error: {}", err); // HACK: ignore timeouts - #[allow(unused_mut)] - let mut actually_broken = false; - - #[cfg(feature = "linkcheck")] - { - if let Ok(broken_links) = err.downcast::() { - for cause in broken_links.links().iter() { - eprintln!("\tCaused By: {}", cause); - - if cause.contains("timed out") { - actually_broken = true; - } - } + let actually_broken = { + #[cfg(feature = "linkcheck")] + { + err.downcast::() + .unwrap_or(false) + .links() + .iter() + .inspect(|cause| eprintln!("\tCaused By: {}", cause)) + .any(|cause| !cause.contains("timed out")); } - } + + #[cfg(not(feature = "linkcheck"))] + { + false + } + }; if actually_broken { std::process::exit(101); From 127311b75efd47a6f54aca49523c050566fc9823 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Thu, 29 Aug 2019 18:08:13 +0000 Subject: [PATCH 321/618] whitelist wasi crate --- src/tools/tidy/src/deps.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 6ca912db5930d..c31da3c6f4887 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -172,6 +172,7 @@ const WHITELIST: &[Crate<'_>] = &[ Crate("vcpkg"), Crate("version_check"), Crate("void"), + Crate("wasi"), Crate("winapi"), Crate("winapi-build"), Crate("winapi-i686-pc-windows-gnu"), From 0cc1c8d2e71f798ca28813e5dca3adb0e791684d Mon Sep 17 00:00:00 2001 From: Dante-Broggi <34220985+Dante-Broggi@users.noreply.github.com> Date: Thu, 29 Aug 2019 14:16:52 -0400 Subject: [PATCH 322/618] `new_thin_place` is only used with `align` = `layout.align.abi` and is not `pub`. --- src/librustc_codegen_ssa/mir/place.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index ac72928a89677..bd295565e67b3 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -45,14 +45,13 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { bx: &mut Bx, llval: V, layout: TyLayout<'tcx>, - align: Align, ) -> PlaceRef<'tcx, V> { assert!(!bx.cx().type_has_metadata(layout.ty)); PlaceRef { llval, llextra: None, layout, - align + align: layout.align.abi } } @@ -498,7 +497,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // with a static that is an extern_type. let layout = cx.layout_of(self.monomorphize(&ty)); let static_ = bx.get_static(*def_id); - PlaceRef::new_thin_place(bx, static_, layout, layout.align.abi) + PlaceRef::new_thin_place(bx, static_, layout) }, mir::PlaceRef { base, From 8657fb1140165f770a928b04095fc025308a4fb2 Mon Sep 17 00:00:00 2001 From: Dante-Broggi <34220985+Dante-Broggi@users.noreply.github.com> Date: Thu, 29 Aug 2019 14:24:50 -0400 Subject: [PATCH 323/618] `new_sized` is mostly used without align so rename it `new_sized_aligned`. 6/11 use `align` = `layout.align.abi`. `from_const_alloc` uses `alloc.align`, but that is `assert_eq!` to `layout.align.abi`. only 4/11 use something interesting for `align`. --- src/librustc_codegen_llvm/builder.rs | 2 +- src/librustc_codegen_llvm/common.rs | 2 +- src/librustc_codegen_llvm/intrinsic.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 4 ++-- src/librustc_codegen_ssa/mir/mod.rs | 4 ++-- src/librustc_codegen_ssa/mir/operand.rs | 1 - src/librustc_codegen_ssa/mir/place.rs | 17 +++++++++++++++-- src/librustc_codegen_ssa/mir/rvalue.rs | 2 +- 8 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 894e5c2fd3d93..1f9b3523fbd94 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -561,7 +561,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size); cg_elem.val.store(&mut body_bx, - PlaceRef::new_sized(current, cg_elem.layout, align)); + PlaceRef::new_sized_aligned(current, cg_elem.layout, align)); let next = body_bx.inbounds_gep(current, &[self.const_usize(1)]); body_bx.br(header_bx.llbb()); diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index 19f18088579b3..6ce1d4b18693c 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -348,7 +348,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { )}; self.const_bitcast(llval, llty) }; - PlaceRef::new_sized(llval, layout, alloc.align) + PlaceRef::new_sized(llval, layout) } fn const_ptrcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value { diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 9483ffca448e3..fc0b9ffd11d83 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -101,7 +101,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let name = &*tcx.item_name(def_id).as_str(); let llret_ty = self.layout_of(ret_ty).llvm_type(self); - let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout, fn_ty.ret.layout.align.abi); + let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout); let simple = get_simple_intrinsic(self, name); let llval = match name { diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index d2a7571fde1e2..30a79f9f1afba 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -989,7 +989,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Handle both by-ref and immediate tuples. if let Ref(llval, None, align) = tuple.val { - let tuple_ptr = PlaceRef::new_sized(llval, tuple.layout, align); + let tuple_ptr = PlaceRef::new_sized_aligned(llval, tuple.layout, align); for i in 0..tuple.layout.fields.count() { let field_ptr = tuple_ptr.project_field(bx, i); let field = bx.load_operand(field_ptr); @@ -1203,7 +1203,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llty = bx.backend_type(src.layout); let cast_ptr = bx.pointercast(dst.llval, bx.type_ptr_to(llty)); let align = src.layout.align.abi.min(dst.align); - src.val.store(bx, PlaceRef::new_sized(cast_ptr, src.layout, align)); + src.val.store(bx, PlaceRef::new_sized_aligned(cast_ptr, src.layout, align)); } diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 32bcdebc1c467..8acb3ba06267e 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -289,7 +289,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() { debug!("alloc: {:?} (return place) -> place", local); let llretptr = bx.get_param(0); - LocalRef::Place(PlaceRef::new_sized(llretptr, layout, layout.align.abi)) + LocalRef::Place(PlaceRef::new_sized(llretptr, layout)) } else if memory_locals.contains(local) { debug!("alloc: {:?} -> place", local); if layout.is_unsized() { @@ -548,7 +548,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let llarg = bx.get_param(llarg_idx); bx.set_value_name(llarg, &name); llarg_idx += 1; - PlaceRef::new_sized(llarg, arg.layout, arg.layout.align.abi) + PlaceRef::new_sized(llarg, arg.layout) } else if arg.is_unsized_indirect() { // As the storage for the indirect argument lives during // the whole function call, we just copy the fat pointer. diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 254b73da44261..a8ab3ea10ed16 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -485,7 +485,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.load_operand(PlaceRef::new_sized( bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout))), layout, - layout.align.abi, )) }) } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index bd295565e67b3..b8e10d3430292 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -30,6 +30,19 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { pub fn new_sized( llval: V, layout: TyLayout<'tcx>, + ) -> PlaceRef<'tcx, V> { + assert!(!layout.is_unsized()); + PlaceRef { + llval, + llextra: None, + layout, + align: layout.align.abi + } + } + + pub fn new_sized_aligned( + llval: V, + layout: TyLayout<'tcx>, align: Align, ) -> PlaceRef<'tcx, V> { assert!(!layout.is_unsized()); @@ -63,7 +76,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { debug!("alloca({:?}: {:?})", name, layout); assert!(!layout.is_unsized(), "tried to statically allocate unsized place"); let tmp = bx.alloca(bx.cx().backend_type(layout), name, layout.align.abi); - Self::new_sized(tmp, layout, layout.align.abi) + Self::new_sized(tmp, layout) } /// Returns a place for an indirect reference to an unsized place. @@ -481,7 +494,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llval = bx.cx().const_undef( bx.cx().type_ptr_to(bx.cx().backend_type(layout)) ); - PlaceRef::new_sized(llval, layout, layout.align.abi) + PlaceRef::new_sized(llval, layout) } } } diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 9da1e5024ba3a..e0ad2527229ba 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -71,7 +71,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { scratch.storage_dead(&mut bx); } OperandValue::Ref(llref, None, align) => { - let source = PlaceRef::new_sized(llref, operand.layout, align); + let source = PlaceRef::new_sized_aligned(llref, operand.layout, align); base::coerce_unsized_into(&mut bx, source, dest); } OperandValue::Ref(_, Some(_), _) => { From c71004cd218cce39501259ff3dd6e889c682dbbb Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 29 Aug 2019 21:23:52 +0200 Subject: [PATCH 324/618] Also test isize and usize in wrapping arithmetics --- src/test/ui/wrapping-int-combinations.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/ui/wrapping-int-combinations.rs b/src/test/ui/wrapping-int-combinations.rs index e09f7232bd2fb..431194ccd1dec 100644 --- a/src/test/ui/wrapping-int-combinations.rs +++ b/src/test/ui/wrapping-int-combinations.rs @@ -65,9 +65,11 @@ fn main() { wrapping_test!(i32, std::i32::MIN, std::i32::MAX); wrapping_test!(i64, std::i64::MIN, std::i64::MAX); wrapping_test!(i128, std::i128::MIN, std::i128::MAX); + wrapping_test!(isize, std::isize::MIN, std::isize::MAX); wrapping_test!(u8, std::u8::MIN, std::u8::MAX); wrapping_test!(u16, std::u16::MIN, std::u16::MAX); wrapping_test!(u32, std::u32::MIN, std::u32::MAX); wrapping_test!(u64, std::u64::MIN, std::u64::MAX); wrapping_test!(u128, std::u128::MIN, std::u128::MAX); + wrapping_test!(usize, std::usize::MIN, std::usize::MAX); } From 378c32bc90b230d1f8feffee135942d442d2a5b7 Mon Sep 17 00:00:00 2001 From: Sam Radhakrishan Date: Fri, 30 Aug 2019 00:57:20 +0530 Subject: [PATCH 325/618] Fix test. --- src/librustc_typeck/check/expr.rs | 9 ++++++--- src/test/ui/privacy/union-field-privacy-2.rs | 2 +- src/test/ui/privacy/union-field-privacy-2.stderr | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 4943270e193ec..a53fb12367d0e 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1392,14 +1392,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base_did: DefId, ) { let struct_path = self.tcx().def_path_str(base_did); + let kind_name = match self.tcx().def_kind(base_did) { + Some(def_kind) => def_kind.descr(base_did), + _ => " ", + }; let mut err = struct_span_err!( self.tcx().sess, expr.span, E0616, - "field `{}` of `{}` `{}` is private", + "field `{}` of {} `{}` is private", field, - if let Some(def_kind) = self.tcx().def_kind(base_did){ def_kind.descr(base_did) } - else { " " }, + kind_name, struct_path ); // Also check if an accessible method exists, which is often what is meant. diff --git a/src/test/ui/privacy/union-field-privacy-2.rs b/src/test/ui/privacy/union-field-privacy-2.rs index 48279630c6302..c2458f74bc8f9 100644 --- a/src/test/ui/privacy/union-field-privacy-2.rs +++ b/src/test/ui/privacy/union-field-privacy-2.rs @@ -11,5 +11,5 @@ fn main() { let a = u.a; // OK let b = u.b; // OK - let c = u.c; //~ ERROR field `c` of struct `m::U` is private + let c = u.c; //~ ERROR field `c` of union `m::U` is private } diff --git a/src/test/ui/privacy/union-field-privacy-2.stderr b/src/test/ui/privacy/union-field-privacy-2.stderr index df054b8cff8a6..8789178caac26 100644 --- a/src/test/ui/privacy/union-field-privacy-2.stderr +++ b/src/test/ui/privacy/union-field-privacy-2.stderr @@ -1,4 +1,4 @@ -error[E0616]: field `c` of struct `m::U` is private +error[E0616]: field `c` of union `m::U` is private --> $DIR/union-field-privacy-2.rs:14:13 | LL | let c = u.c; From 56ab485fbe61add87ac8febea421e2a576edca26 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Tue, 27 Aug 2019 08:07:56 +0200 Subject: [PATCH 326/618] support rustdoc test from stdin to rustc --- src/librustc_driver/lib.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index e7712ae115f54..885e2fea26a10 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -439,6 +439,15 @@ fn make_input(free_matches: &[String]) -> Option<(Input, Option, Option } else { None }; + if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") { + let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE"). + expect("when UNSTABLE_RUSTDOC_TEST_PATH is set \ + UNSTABLE_RUSTDOC_TEST_LINE also needs to be set"); + let line = isize::from_str_radix(&line, 10). + expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number"); + let file_name = FileName::doc_test_source_code(PathBuf::from(path), line); + return Some((Input::Str { name: file_name, input: src }, None, err)); + } Some((Input::Str { name: FileName::anon_source_code(&src), input: src }, None, err)) } else { From 86487329bb385f74bed67718f2358436ddca1aa4 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 29 Aug 2019 13:22:16 -0700 Subject: [PATCH 327/618] Add `Place::is_indirect` This returns whether a `Place` references the same region of memory as its base, or equivalently whether it contains a `Deref` projection. This is helpful for analyses that must track state for locals, since an assignment to `x` or `x.field` is fundamentally different than one to `*x`, which may mutate any memory region. --- src/librustc/mir/mod.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 858b77af80468..a07f12cd9c5f2 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1801,6 +1801,23 @@ pub enum ProjectionElem { Downcast(Option, VariantIdx), } +impl ProjectionElem { + /// Returns `true` if the target of this projection may refer to a different region of memory + /// than the base. + fn is_indirect(&self) -> bool { + match self { + Self::Deref => true, + + | Self::Field(_, _) + | Self::Index(_) + | Self::ConstantIndex { .. } + | Self::Subslice { .. } + | Self::Downcast(_, _) + => false + } + } +} + /// Alias for projections as they appear in places, where the base is a place /// and the index is a local. pub type PlaceElem<'tcx> = ProjectionElem>; @@ -1862,6 +1879,14 @@ impl<'tcx> Place<'tcx> { } } + /// Returns `true` if this `Place` contains a `Deref` projection. + /// + /// If `Place::is_indirect` returns false, the caller knows that the `Place` refers to the + /// same region of memory as its base. + pub fn is_indirect(&self) -> bool { + self.iterate(|_, mut projections| projections.any(|proj| proj.elem.is_indirect())) + } + /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or /// a single deref of a local. // From b304cd02c033945144404d859b8d031a46e9c8ca Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Thu, 29 Aug 2019 23:15:31 +0200 Subject: [PATCH 328/618] Run doctests via out-of-process rustc --- src/librustdoc/config.rs | 12 +++ src/librustdoc/markdown.rs | 7 +- src/librustdoc/test.rs | 214 ++++++++++++------------------------- 3 files changed, 82 insertions(+), 151 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index cefae2e105eda..30b1706f29464 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -39,12 +39,18 @@ pub struct Options { pub error_format: ErrorOutputType, /// Library search paths to hand to the compiler. pub libs: Vec, + /// Library search paths strings to hand to the compiler. + pub lib_strs: Vec, /// The list of external crates to link against. pub externs: Externs, + /// The list of external crates strings to link against. + pub extern_strs: Vec, /// List of `cfg` flags to hand to the compiler. Always includes `rustdoc`. pub cfgs: Vec, /// Codegen options to hand to the compiler. pub codegen_options: CodegenOptions, + /// Codegen options strings to hand to the compiler. + pub codegen_options_strs: Vec, /// Debugging (`-Z`) options to pass to the compiler. pub debugging_options: DebuggingOptions, /// The target used to compile the crate against. @@ -461,6 +467,9 @@ impl Options { let generate_search_filter = !matches.opt_present("disable-per-crate-search"); let persist_doctests = matches.opt_str("persist-doctests").map(PathBuf::from); let generate_redirect_pages = matches.opt_present("generate-redirect-pages"); + let codegen_options_strs = matches.opt_strs("C"); + let lib_strs = matches.opt_strs("L"); + let extern_strs = matches.opt_strs("extern"); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); @@ -470,9 +479,12 @@ impl Options { proc_macro_crate, error_format, libs, + lib_strs, externs, + extern_strs, cfgs, codegen_options, + codegen_options_strs, debugging_options, target, edition, diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index e735a9779c924..a30fc05f36acd 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -142,11 +142,8 @@ pub fn test(mut options: Options, diag: &errors::Handler) -> i32 { let mut opts = TestOptions::default(); opts.no_crate_inject = true; opts.display_warnings = options.display_warnings; - let mut collector = Collector::new(options.input.display().to_string(), options.cfgs, - options.libs, options.codegen_options, options.externs, - true, opts, options.maybe_sysroot, None, - Some(options.input), - options.linker, options.edition, options.persist_doctests); + let mut collector = Collector::new(options.input.display().to_string(), options.clone(), + true, opts, None, Some(options.input)); collector.set_position(DUMMY_SP); let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index cb6ae1c2bd24b..70511131e5302 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -2,10 +2,7 @@ use rustc_data_structures::sync::Lrc; use rustc_interface::interface; use rustc::hir; use rustc::hir::intravisit; -use rustc::hir::def_id::LOCAL_CRATE; use rustc::session::{self, config, DiagnosticOutput}; -use rustc::session::config::{OutputType, OutputTypes, Externs, CodegenOptions}; -use rustc::session::search_paths::SearchPath; use rustc::util::common::ErrorReported; use syntax::ast; use syntax::with_globals; @@ -13,13 +10,11 @@ use syntax::source_map::SourceMap; use syntax::edition::Edition; use syntax::feature_gate::UnstableFeatures; use std::env; -use std::io::prelude::*; -use std::io; -use std::panic::{self, AssertUnwindSafe}; +use std::io::{self, Write}; +use std::panic; use std::path::PathBuf; -use std::process::{self, Command}; +use std::process::{self, Command, Stdio}; use std::str; -use std::sync::{Arc, Mutex}; use syntax::symbol::sym; use syntax_pos::{BytePos, DUMMY_SP, Pos, Span, FileName}; use tempfile::Builder as TempFileBuilder; @@ -89,18 +84,11 @@ pub fn run(options: Options) -> i32 { opts.display_warnings |= options.display_warnings; let mut collector = Collector::new( compiler.crate_name()?.peek().to_string(), - options.cfgs, - options.libs, - options.codegen_options, - options.externs, + options, false, opts, - options.maybe_sysroot, Some(compiler.source_map().clone()), None, - options.linker, - options.edition, - options.persist_doctests, ); let mut global_ctxt = compiler.global_ctxt()?.take(); @@ -189,20 +177,14 @@ fn run_test( cratename: &str, filename: &FileName, line: usize, - cfgs: Vec, - libs: Vec, - cg: CodegenOptions, - externs: Externs, + options: Options, should_panic: bool, no_run: bool, as_test_harness: bool, compile_fail: bool, mut error_codes: Vec, opts: &TestOptions, - maybe_sysroot: Option, - linker: Option, edition: Edition, - persist_doctests: Option, ) -> Result<(), TestFailure> { let (test, line_offset) = match panic::catch_unwind(|| { make_test(test, Some(cratename), as_test_harness, opts, edition) @@ -223,61 +205,6 @@ fn run_test( _ => PathBuf::from(r"doctest.rs"), }; - let input = config::Input::Str { - name: FileName::DocTest(path, line as isize - line_offset as isize), - input: test, - }; - let outputs = OutputTypes::new(&[(OutputType::Exe, None)]); - - let sessopts = config::Options { - maybe_sysroot, - search_paths: libs, - crate_types: vec![config::CrateType::Executable], - output_types: outputs, - externs, - cg: config::CodegenOptions { - linker, - ..cg - }, - test: as_test_harness, - unstable_features: UnstableFeatures::from_environment(), - debugging_opts: config::DebuggingOptions { - ..config::basic_debugging_options() - }, - edition, - ..config::Options::default() - }; - - // Shuffle around a few input and output handles here. We're going to pass - // an explicit handle into rustc to collect output messages, but we also - // want to catch the error message that rustc prints when it fails. - // - // We take our thread-local stderr (likely set by the test runner) and replace - // it with a sink that is also passed to rustc itself. When this function - // returns the output of the sink is copied onto the output of our own thread. - // - // The basic idea is to not use a default Handler for rustc, and then also - // not print things by default to the actual stderr. - struct Sink(Arc>>); - impl Write for Sink { - fn write(&mut self, data: &[u8]) -> io::Result { - Write::write(&mut *self.0.lock().unwrap(), data) - } - fn flush(&mut self) -> io::Result<()> { Ok(()) } - } - struct Bomb(Arc>>, Option>); - impl Drop for Bomb { - fn drop(&mut self) { - let mut old = self.1.take().unwrap(); - let _ = old.write_all(&self.0.lock().unwrap()); - io::set_panic(Some(old)); - } - } - let data = Arc::new(Mutex::new(Vec::new())); - - let old = io::set_panic(Some(box Sink(data.clone()))); - let _bomb = Bomb(data.clone(), Some(old.unwrap_or(box io::stdout()))); - enum DirState { Temp(tempfile::TempDir), Perm(PathBuf), @@ -292,7 +219,7 @@ fn run_test( } } - let outdir = if let Some(mut path) = persist_doctests { + let outdir = if let Some(mut path) = options.persist_doctests { path.push(format!("{}_{}", filename .to_string() @@ -314,41 +241,65 @@ fn run_test( }; let output_file = outdir.path().join("rust_out"); - let config = interface::Config { - opts: sessopts, - crate_cfg: config::parse_cfgspecs(cfgs), - input, - input_path: None, - output_file: Some(output_file.clone()), - output_dir: None, - file_loader: None, - diagnostic_output: DiagnosticOutput::Raw(box Sink(data.clone())), - stderr: Some(data.clone()), - crate_name: None, - lint_caps: Default::default(), - }; + let mut compiler = Command::new(std::env::current_exe().unwrap().with_file_name("rustc")); + compiler.arg("--crate-type").arg("bin"); + for cfg in &options.cfgs { + compiler.arg("--cfg").arg(&cfg); + } + if let Some(sysroot) = options.maybe_sysroot { + compiler.arg("--sysroot").arg(sysroot); + } + compiler.arg("--edition").arg(&edition.to_string()); + compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", path); + compiler.env("UNSTABLE_RUSTDOC_TEST_LINE", + format!("{}", line as isize - line_offset as isize)); + compiler.arg("-o").arg(&output_file); + if as_test_harness { + compiler.arg("--test"); + } + for lib_str in &options.lib_strs { + compiler.arg("-L").arg(&lib_str); + } + for extern_str in &options.extern_strs { + compiler.arg("--extern").arg(&extern_str); + } + for codegen_options_str in &options.codegen_options_strs { + compiler.arg("-C").arg(&codegen_options_str); + } + if let Some(linker) = options.linker { + compiler.arg(&format!("-C linker={:?}", linker)); + } + if no_run { + compiler.arg("--emit=metadata"); + } - let compile_result = panic::catch_unwind(AssertUnwindSafe(|| { - interface::run_compiler(config, |compiler| { - if no_run { - compiler.global_ctxt().and_then(|global_ctxt| global_ctxt.take().enter(|tcx| { - tcx.analysis(LOCAL_CRATE) - })).ok(); - } else { - compiler.compile().ok(); - }; - compiler.session().compile_status() - }) - })).map_err(|_| ()).and_then(|s| s.map_err(|_| ())); + compiler.arg("-"); + compiler.stdin(Stdio::piped()); + compiler.stderr(Stdio::piped()); + + let mut child = compiler.spawn().expect("Failed to spawn rustc process"); + { + let stdin = child.stdin.as_mut().expect("Failed to open stdin"); + stdin.write_all(test.as_bytes()).expect("could write out test sources"); + } + let output = child.wait_with_output().expect("Failed to read stdout"); - match (compile_result, compile_fail) { - (Ok(()), true) => { + struct Bomb<'a>(&'a str); + impl Drop for Bomb<'_> { + fn drop(&mut self) { + eprint!("{}",self.0); + } + } + + let out = str::from_utf8(&output.stderr).unwrap(); + let _bomb = Bomb(&out); + match (output.status.success(), compile_fail) { + (true, true) => { return Err(TestFailure::UnexpectedCompilePass); } - (Ok(()), false) => {} - (Err(_), true) => { + (true, false) => {} + (false, true) => { if !error_codes.is_empty() { - let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); error_codes.retain(|err| !out.contains(err)); if !error_codes.is_empty() { @@ -356,7 +307,7 @@ fn run_test( } } } - (Err(_), false) => { + (false, false) => { return Err(TestFailure::CompileError); } } @@ -652,45 +603,28 @@ pub struct Collector { // the `names` vector of that test will be `["Title", "Subtitle"]`. names: Vec, - cfgs: Vec, - libs: Vec, - cg: CodegenOptions, - externs: Externs, + options: Options, use_headers: bool, cratename: String, opts: TestOptions, - maybe_sysroot: Option, position: Span, source_map: Option>, filename: Option, - linker: Option, - edition: Edition, - persist_doctests: Option, } impl Collector { - pub fn new(cratename: String, cfgs: Vec, libs: Vec, cg: CodegenOptions, - externs: Externs, use_headers: bool, opts: TestOptions, - maybe_sysroot: Option, source_map: Option>, - filename: Option, linker: Option, edition: Edition, - persist_doctests: Option) -> Collector { + pub fn new(cratename: String, options: Options, use_headers: bool, opts: TestOptions, + source_map: Option>, filename: Option,) -> Collector { Collector { tests: Vec::new(), names: Vec::new(), - cfgs, - libs, - cg, - externs, + options, use_headers, cratename, opts, - maybe_sysroot, position: DUMMY_SP, source_map, filename, - linker, - edition, - persist_doctests, } } @@ -725,16 +659,10 @@ impl Tester for Collector { fn add_test(&mut self, test: String, config: LangString, line: usize) { let filename = self.get_filename(); let name = self.generate_name(line, &filename); - let cfgs = self.cfgs.clone(); - let libs = self.libs.clone(); - let cg = self.cg.clone(); - let externs = self.externs.clone(); let cratename = self.cratename.to_string(); let opts = self.opts.clone(); - let maybe_sysroot = self.maybe_sysroot.clone(); - let linker = self.linker.clone(); - let edition = config.edition.unwrap_or(self.edition); - let persist_doctests = self.persist_doctests.clone(); + let edition = config.edition.unwrap_or(self.options.edition.clone()); + let options = self.options.clone(); debug!("creating test {}: {}", name, test); self.tests.push(testing::TestDescAndFn { @@ -751,20 +679,14 @@ impl Tester for Collector { &cratename, &filename, line, - cfgs, - libs, - cg, - externs, + options, config.should_panic, config.no_run, config.test_harness, config.compile_fail, config.error_codes, &opts, - maybe_sysroot, - linker, edition, - persist_doctests ); if let Err(err) = res { From c6e7f039aabe3338c400d197a689c94bde425ba6 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 15 Aug 2019 18:20:35 +0200 Subject: [PATCH 329/618] Merge oli-obk mail addresses --- .mailmap | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.mailmap b/.mailmap index c5ecfb54fca52..91b2e762d8e40 100644 --- a/.mailmap +++ b/.mailmap @@ -181,12 +181,19 @@ Neil Pankey Nick Platt Nicole Mazzuca Nif Ward -Oliver Schneider oli-obk -Oliver Schneider Oliver 'ker' Schneider -Oliver Schneider Oliver Schneider -Oliver Schneider Oliver Schneider -Oliver Schneider Oliver Schneider -Oliver Schneider Oliver Schneider +Oliver Scherer +Oliver Scherer +Oliver Scherer +Oliver Scherer +Oliver Scherer +Oliver Scherer +Oliver Scherer +Oliver Scherer +Oliver Scherer +Oliver Scherer +Oliver Scherer +Oliver Scherer +Oliver Scherer Ožbolt Menegatti gareins Paul Faria Paul Faria Peer Aramillo Irizar parir From 26e9990198d3c7262d58468f18a722920c897e35 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 19 May 2019 20:16:04 +0200 Subject: [PATCH 330/618] Add a "diagnostic item" scheme This allows lints and other diagnostics to refer to items by a unique ID instead of relying on whacky path resolution schemes that may break when items are relocated. --- src/liballoc/vec.rs | 1 + src/libcore/fmt/mod.rs | 3 +- src/librustc/arena.rs | 4 + src/librustc/lib.rs | 2 + src/librustc/lint/internal.rs | 16 +-- src/librustc/middle/diagnostic_items.rs | 123 ++++++++++++++++++ src/librustc/middle/lang_items.rs | 2 - src/librustc/query/mod.rs | 19 ++- src/librustc/ty/context.rs | 21 +++ src/librustc/ty/mod.rs | 1 + src/librustc/ty/sty.rs | 1 + src/librustc_lint/builtin.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 1 + src/librustc_metadata/decoder.rs | 18 +++ src/librustc_metadata/encoder.rs | 15 ++- src/librustc_metadata/schema.rs | 1 + src/libsyntax/feature_gate/builtin_attrs.rs | 11 ++ src/libsyntax_pos/symbol.rs | 5 +- .../ui/tool-attributes/diagnostic_item.rs | 2 + .../ui/tool-attributes/diagnostic_item.stderr | 17 +++ .../ui/tool-attributes/diagnostic_item2.rs | 6 + .../ui/tool-attributes/diagnostic_item3.rs | 7 + 22 files changed, 260 insertions(+), 18 deletions(-) create mode 100644 src/librustc/middle/diagnostic_items.rs create mode 100644 src/test/ui/tool-attributes/diagnostic_item.rs create mode 100644 src/test/ui/tool-attributes/diagnostic_item.stderr create mode 100644 src/test/ui/tool-attributes/diagnostic_item2.rs create mode 100644 src/test/ui/tool-attributes/diagnostic_item3.rs diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index d2798955c46a9..d5dc2d4b8688d 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -291,6 +291,7 @@ use crate::raw_vec::RawVec; /// [`reserve`]: ../../std/vec/struct.Vec.html#method.reserve /// [owned slice]: ../../std/boxed/struct.Box.html #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(all(not(bootstrap), not(test)), rustc_diagnostic_item = "vec_type")] pub struct Vec { buf: RawVec, len: usize, diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index bd31d25dd034b..7e35188bc1082 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -518,7 +518,8 @@ impl Display for Arguments<'_> { label="`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`", )] #[doc(alias = "{:?}")] -#[lang = "debug_trait"] +#[cfg_attr(boostrap_stdarch_ignore_this, lang = "debug_trait")] +#[cfg_attr(not(boostrap_stdarch_ignore_this), rustc_diagnostic_item = "debug_trait")] pub trait Debug { /// Formats the value using the given formatter. /// diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index a38dbbdd50c57..b3a561ef74be7 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -94,6 +94,10 @@ macro_rules! arena_types { rustc::hir::def_id::CrateNum > >, + [few] diagnostic_items: rustc_data_structures::fx::FxHashMap< + syntax::symbol::Symbol, + rustc::hir::def_id::DefId, + >, [few] resolve_lifetimes: rustc::middle::resolve_lifetime::ResolveLifetimes, [decode] generic_predicates: rustc::ty::GenericPredicates<'tcx>, [few] lint_levels: rustc::lint::LintLevelMap, diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 8d4cd51e4608c..368f5bb64fe6c 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -62,6 +62,7 @@ #![feature(log_syntax)] #![feature(mem_take)] #![feature(associated_type_bounds)] +#![feature(rustc_attrs)] #![recursion_limit="512"] @@ -109,6 +110,7 @@ pub mod middle { pub mod cstore; pub mod dead; pub mod dependency_format; + pub mod diagnostic_items; pub mod entry; pub mod exported_symbols; pub mod free_region; diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs index be73b305e2c50..13834eaf40f57 100644 --- a/src/librustc/lint/internal.rs +++ b/src/librustc/lint/internal.rs @@ -159,29 +159,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { } fn lint_ty_kind_usage(cx: &LateContext<'_, '_>, segment: &PathSegment) -> bool { - if segment.ident.name == sym::TyKind { - if let Some(res) = segment.res { - if let Some(did) = res.opt_def_id() { - return cx.match_def_path(did, TYKIND_PATH); - } + if let Some(res) = segment.res { + if let Some(did) = res.opt_def_id() { + return cx.tcx.is_diagnostic_item(sym::TyKind, did); } } false } -const TYKIND_PATH: &[Symbol] = &[sym::rustc, sym::ty, sym::sty, sym::TyKind]; -const TY_PATH: &[Symbol] = &[sym::rustc, sym::ty, sym::Ty]; -const TYCTXT_PATH: &[Symbol] = &[sym::rustc, sym::ty, sym::context, sym::TyCtxt]; - fn is_ty_or_ty_ctxt(cx: &LateContext<'_, '_>, ty: &Ty) -> Option { match &ty.node { TyKind::Path(qpath) => { if let QPath::Resolved(_, path) = qpath { let did = path.res.opt_def_id()?; - if cx.match_def_path(did, TY_PATH) { + if cx.tcx.is_diagnostic_item(sym::Ty, did) { return Some(format!("Ty{}", gen_args(path.segments.last().unwrap()))); - } else if cx.match_def_path(did, TYCTXT_PATH) { + } else if cx.tcx.is_diagnostic_item(sym::TyCtxt, did) { return Some(format!("TyCtxt{}", gen_args(path.segments.last().unwrap()))); } } diff --git a/src/librustc/middle/diagnostic_items.rs b/src/librustc/middle/diagnostic_items.rs new file mode 100644 index 0000000000000..dfae169b27824 --- /dev/null +++ b/src/librustc/middle/diagnostic_items.rs @@ -0,0 +1,123 @@ +//! Detecting diagnostic items. +//! +//! Diagnostic items are items that are not language-inherent, but can reasonably be expected to +//! exist for diagnostic purposes. This allows diagnostic authors to refer to specific items +//! directly, without having to guess module paths and crates. +//! Examples are: +//! +//! * Traits like `Debug`, that have no bearing on language semantics +//! +//! * Compiler internal types like `Ty` and `TyCtxt` + +use crate::hir::def_id::{DefId, LOCAL_CRATE}; +use crate::ty::TyCtxt; +use crate::util::nodemap::FxHashMap; + +use syntax::ast; +use syntax::symbol::{Symbol, sym}; +use crate::hir::itemlikevisit::ItemLikeVisitor; +use crate::hir; + +struct DiagnosticItemCollector<'tcx> { + // items from this crate + items: FxHashMap, + tcx: TyCtxt<'tcx>, +} + +impl<'v, 'tcx> ItemLikeVisitor<'v> for DiagnosticItemCollector<'tcx> { + fn visit_item(&mut self, item: &hir::Item) { + self.observe_item(&item.attrs, item.hir_id); + } + + fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) { + self.observe_item(&trait_item.attrs, trait_item.hir_id); + } + + fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) { + self.observe_item(&impl_item.attrs, impl_item.hir_id); + } +} + +impl<'tcx> DiagnosticItemCollector<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> DiagnosticItemCollector<'tcx> { + DiagnosticItemCollector { + tcx, + items: Default::default(), + } + } + + fn observe_item(&mut self, attrs: &[ast::Attribute], hir_id: hir::HirId) { + if let Some(name) = extract(attrs) { + let def_id = self.tcx.hir().local_def_id(hir_id); + // insert into our table + collect_item(self.tcx, &mut self.items, name, def_id); + } + } +} + +fn collect_item( + tcx: TyCtxt<'_>, + items: &mut FxHashMap, + name: Symbol, + item_def_id: DefId, +) { + // Check for duplicates. + if let Some(original_def_id) = items.insert(name, item_def_id) { + if original_def_id != item_def_id { + let mut err = match tcx.hir().span_if_local(item_def_id) { + Some(span) => tcx.sess.struct_span_err( + span, + &format!("duplicate diagnostic item found: `{}`.", name)), + None => tcx.sess.struct_err(&format!( + "duplicate diagnostic item in crate `{}`: `{}`.", + tcx.crate_name(item_def_id.krate), + name)), + }; + if let Some(span) = tcx.hir().span_if_local(original_def_id) { + span_note!(&mut err, span, "first defined here."); + } else { + err.note(&format!("first defined in crate `{}`.", + tcx.crate_name(original_def_id.krate))); + } + err.emit(); + } + } +} + +/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes. +fn extract(attrs: &[ast::Attribute]) -> Option { + attrs.iter().find_map(|attr| { + if attr.check_name(sym::rustc_diagnostic_item) { + attr.value_str() + } else { + None + } + }) +} + +/// Traverse and collect the diagnostic items in the current +pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx FxHashMap { + // Initialize the collector. + let mut collector = DiagnosticItemCollector::new(tcx); + + // Collect diagnostic items in this crate. + tcx.hir().krate().visit_all_item_likes(&mut collector); + + tcx.arena.alloc(collector.items) +} + + +/// Traverse and collect all the diagnostic items in all crates. +pub fn collect_all<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx FxHashMap { + // Initialize the collector. + let mut collector = FxHashMap::default(); + + // Collect diagnostic items in other crates. + for &cnum in tcx.crates().iter().chain(std::iter::once(&LOCAL_CRATE)) { + for (&name, &def_id) in tcx.diagnostic_items(cnum).iter() { + collect_item(tcx, &mut collector, name, def_id); + } + } + + tcx.arena.alloc(collector) +} diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 334c06618bb28..6b04600eb75f8 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -367,8 +367,6 @@ language_item_table! { MaybeUninitLangItem, "maybe_uninit", maybe_uninit, Target::Union; - DebugTraitLangItem, "debug_trait", debug_trait, Target::Trait; - // Align offset for stride != 1, must not panic. AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn; diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index c4f7ca51f4a7a..ef838114f6c36 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -804,7 +804,7 @@ rustc_queries! { } BorrowChecking { - // Lifetime resolution. See `middle::resolve_lifetimes`. + /// Lifetime resolution. See `middle::resolve_lifetimes`. query resolve_lifetimes(_: CrateNum) -> &'tcx ResolveLifetimes { desc { "resolving lifetimes" } } @@ -846,13 +846,30 @@ rustc_queries! { -> &'tcx [(Symbol, Option)] { desc { "calculating the lib features defined in a crate" } } + /// Returns the lang items defined in another crate by loading it from metadata. + // FIXME: It is illegal to pass a `CrateNum` other than `LOCAL_CRATE` here, just get rid + // of that argument? query get_lang_items(_: CrateNum) -> &'tcx LanguageItems { eval_always desc { "calculating the lang items map" } } + + /// Returns all diagnostic items defined in all crates + query all_diagnostic_items(_: CrateNum) -> &'tcx FxHashMap { + eval_always + desc { "calculating the diagnostic items map" } + } + + /// Returns the lang items defined in another crate by loading it from metadata. query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, usize)] { desc { "calculating the lang items defined in a crate" } } + + /// Returns the diagnostic items defined in a crate + query diagnostic_items(_: CrateNum) -> &'tcx FxHashMap { + desc { "calculating the diagnostic items map in a crate" } + } + query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] { desc { "calculating the missing lang items in a crate" } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c0d86a79882ef..e240e0df8b948 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -978,6 +978,7 @@ pub struct FreeRegionInfo { /// /// [rustc guide]: https://rust-lang.github.io/rustc-guide/ty.html #[derive(Copy, Clone)] +#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyCtxt")] pub struct TyCtxt<'tcx> { gcx: &'tcx GlobalCtxt<'tcx>, } @@ -1308,10 +1309,22 @@ impl<'tcx> TyCtxt<'tcx> { self.get_lib_features(LOCAL_CRATE) } + /// Obtain all lang items of this crate and all dependencies (recursively) pub fn lang_items(self) -> &'tcx middle::lang_items::LanguageItems { self.get_lang_items(LOCAL_CRATE) } + /// Obtain the given diagnostic item's `DefId`. Use `is_diagnostic_item` if you just want to + /// compare against another `DefId`, since `is_diagnostic_item` is cheaper. + pub fn get_diagnostic_item(self, name: Symbol) -> Option { + self.all_diagnostic_items(LOCAL_CRATE).get(&name).copied() + } + + /// Check whether the diagnostic item with the given `name` has the given `DefId`. + pub fn is_diagnostic_item(self, name: Symbol, did: DefId) -> bool { + self.diagnostic_items(did.krate).get(&name) == Some(&did) + } + pub fn stability(self) -> &'tcx stability::Index<'tcx> { self.stability_index(LOCAL_CRATE) } @@ -2896,6 +2909,14 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { assert_eq!(id, LOCAL_CRATE); tcx.arena.alloc(middle::lang_items::collect(tcx)) }; + providers.diagnostic_items = |tcx, id| { + assert_eq!(id, LOCAL_CRATE); + middle::diagnostic_items::collect(tcx) + }; + providers.all_diagnostic_items = |tcx, id| { + assert_eq!(id, LOCAL_CRATE); + middle::diagnostic_items::collect_all(tcx) + }; providers.maybe_unused_trait_import = |tcx, id| { tcx.maybe_unused_trait_imports.contains(&id) }; diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index eaaaf75f75dd5..56505c04f0f0c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -581,6 +581,7 @@ impl<'a, 'tcx> HashStable> for ty::TyS<'tcx> { } } +#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "Ty")] pub type Ty<'tcx> = &'tcx TyS<'tcx>; impl<'tcx> rustc_serialize::UseSpecializedEncodable for Ty<'tcx> {} diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index f41fffe507d97..d2edf6fb1ee80 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -86,6 +86,7 @@ impl BoundRegion { /// AST structure in `libsyntax/ast.rs` as well. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable, Debug)] +#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyKind")] pub enum TyKind<'tcx> { /// The primitive boolean type. Written as `bool`. Bool, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index d3c94060e274a..26e7b789f8f90 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -570,7 +570,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations { _ => return, } - let debug = match cx.tcx.lang_items().debug_trait() { + let debug = match cx.tcx.get_diagnostic_item(sym::debug_trait) { Some(debug) => debug, None => return, }; diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index ca0cf0a5a661d..d6450f00c8b6a 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -226,6 +226,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, } defined_lib_features => { cdata.get_lib_features(tcx) } defined_lang_items => { cdata.get_lang_items(tcx) } + diagnostic_items => { cdata.get_diagnostic_items(tcx) } missing_lang_items => { cdata.get_missing_lang_items(tcx) } missing_extern_crate_item => { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index cdee14d07fb4d..75d7261704722 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -12,6 +12,7 @@ use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::hir::def::{self, Res, DefKind, CtorOf, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::fx::FxHashMap; use rustc::middle::lang_items; use rustc::mir::{self, interpret}; use rustc::mir::interpret::AllocDecodingSession; @@ -757,6 +758,23 @@ impl<'a, 'tcx> CrateMetadata { } } + /// Iterates over the diagnostic items in the given crate. + pub fn get_diagnostic_items( + &self, + tcx: TyCtxt<'tcx>, + ) -> &'tcx FxHashMap { + tcx.arena.alloc(if self.is_proc_macro_crate() { + // Proc macro crates do not export any diagnostic-items to the target. + Default::default() + } else { + self.root + .diagnostic_items + .decode(self) + .map(|(name, def_index)| (name, self.local_def_id(def_index))) + .collect() + }) + } + /// Iterates over each child of the given item. pub fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Session) where F: FnMut(def::Export) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0eafcebefd745..db212408d8ebd 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -33,7 +33,7 @@ use syntax::ast; use syntax::attr; use syntax::ext::proc_macro::is_proc_macro_attr; use syntax::source_map::Spanned; -use syntax::symbol::{kw, sym, Ident}; +use syntax::symbol::{kw, sym, Ident, Symbol}; use syntax_pos::{self, FileName, SourceFile, Span}; use log::{debug, trace}; @@ -404,6 +404,11 @@ impl<'tcx> EncodeContext<'tcx> { let lang_items_missing = self.encode_lang_items_missing(); let lang_item_bytes = self.position() - i; + // Encode the diagnostic items. + i = self.position(); + let diagnostic_items = self.encode_diagnostic_items(); + let diagnostic_item_bytes = self.position() - i; + // Encode the native libraries used i = self.position(); let native_libraries = self.encode_native_libraries(); @@ -520,6 +525,7 @@ impl<'tcx> EncodeContext<'tcx> { dylib_dependency_formats, lib_features, lang_items, + diagnostic_items, lang_items_missing, native_libraries, foreign_modules, @@ -545,6 +551,7 @@ impl<'tcx> EncodeContext<'tcx> { println!(" dep bytes: {}", dep_bytes); println!(" lib feature bytes: {}", lib_feature_bytes); println!(" lang item bytes: {}", lang_item_bytes); + println!(" diagnostic item bytes: {}", diagnostic_item_bytes); println!(" native bytes: {}", native_lib_bytes); println!(" source_map bytes: {}", source_map_bytes); println!(" impl bytes: {}", impl_bytes); @@ -1555,6 +1562,12 @@ impl EncodeContext<'tcx> { self.lazy(lib_features.to_vec()) } + fn encode_diagnostic_items(&mut self) -> Lazy<[(Symbol, DefIndex)]> { + let tcx = self.tcx; + let diagnostic_items = tcx.diagnostic_items(LOCAL_CRATE); + self.lazy(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index))) + } + fn encode_lang_items(&mut self) -> Lazy<[(DefIndex, usize)]> { let tcx = self.tcx; let lang_items = tcx.lang_items(); diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 1a5887bbf4ed8..1a5f0e17ba7ce 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -176,6 +176,7 @@ pub struct CrateRoot<'tcx> { pub lib_features: Lazy<[(Symbol, Option)]>, pub lang_items: Lazy<[(DefIndex, usize)]>, pub lang_items_missing: Lazy<[lang_items::LangItem]>, + pub diagnostic_items: Lazy<[(Symbol, DefIndex)]>, pub native_libraries: Lazy<[NativeLibrary]>, pub foreign_modules: Lazy<[ForeignModule]>, pub source_map: Lazy<[syntax_pos::SourceFile]>, diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index b934f2e7f64ef..ee7ac3b15d955 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -461,6 +461,17 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ lang, Normal, template!(NameValueStr: "name"), lang_items, "language items are subject to change", ), + ( + sym::rustc_diagnostic_item, + Normal, + template!(NameValueStr: "name"), + Gated( + Stability::Unstable, + sym::rustc_attrs, + "diagnostic items compiler internal support for linting", + cfg_fn!(rustc_attrs), + ), + ), ( sym::no_debug, Whitelisted, template!(Word), Gated( diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 8833e03c72be2..f44716e013ec8 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -225,9 +225,10 @@ symbols! { custom_inner_attributes, custom_test_frameworks, c_variadic, - Debug, + debug_trait, declare_lint_pass, decl_macro, + Debug, Decodable, Default, default_lib_allocator, @@ -238,6 +239,7 @@ symbols! { deref, deref_mut, derive, + diagnostic, direct, doc, doc_alias, @@ -569,6 +571,7 @@ symbols! { rustc_conversion_suggestion, rustc_def_path, rustc_deprecated, + rustc_diagnostic_item, rustc_diagnostic_macros, rustc_dirty, rustc_dummy, diff --git a/src/test/ui/tool-attributes/diagnostic_item.rs b/src/test/ui/tool-attributes/diagnostic_item.rs new file mode 100644 index 0000000000000..88157bbbf614b --- /dev/null +++ b/src/test/ui/tool-attributes/diagnostic_item.rs @@ -0,0 +1,2 @@ +#[rustc_diagnostic_item = "foomp"] //~ ERROR will never be stabilized +struct Foomp; diff --git a/src/test/ui/tool-attributes/diagnostic_item.stderr b/src/test/ui/tool-attributes/diagnostic_item.stderr new file mode 100644 index 0000000000000..4472914118ba7 --- /dev/null +++ b/src/test/ui/tool-attributes/diagnostic_item.stderr @@ -0,0 +1,17 @@ +error[E0658]: diagnostic items compiler are internal support for linting and will never be stabilized + --> $DIR/diagnostic_item.rs:1:1 + | +LL | #[rustc_diagnostic_item = "foomp"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error[E0601]: `main` function not found in crate `diagnostic_item` + | + = note: consider adding a `main` function to `$DIR/diagnostic_item.rs` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0601, E0658. +For more information about an error, try `rustc --explain E0601`. diff --git a/src/test/ui/tool-attributes/diagnostic_item2.rs b/src/test/ui/tool-attributes/diagnostic_item2.rs new file mode 100644 index 0000000000000..b32a66b16be18 --- /dev/null +++ b/src/test/ui/tool-attributes/diagnostic_item2.rs @@ -0,0 +1,6 @@ +// check-pass + +#[clippy::diagnostic_item = "mep"] +struct Mep; + +fn main() {} diff --git a/src/test/ui/tool-attributes/diagnostic_item3.rs b/src/test/ui/tool-attributes/diagnostic_item3.rs new file mode 100644 index 0000000000000..c1a236ed1cc32 --- /dev/null +++ b/src/test/ui/tool-attributes/diagnostic_item3.rs @@ -0,0 +1,7 @@ +// check-pass +#![feature(rustc_attrs)] + +#[rustc_diagnostic_item = "foomp"] +struct Foomp; + +fn main() {} From 6978b9482b976d991dac1dc55a6effe1f697cd1f Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 30 Aug 2019 02:46:25 +0200 Subject: [PATCH 331/618] Update tests --- src/test/ui/tool-attributes/diagnostic_item.rs | 2 +- src/test/ui/tool-attributes/diagnostic_item.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/tool-attributes/diagnostic_item.rs b/src/test/ui/tool-attributes/diagnostic_item.rs index 88157bbbf614b..1d35422ed6241 100644 --- a/src/test/ui/tool-attributes/diagnostic_item.rs +++ b/src/test/ui/tool-attributes/diagnostic_item.rs @@ -1,2 +1,2 @@ -#[rustc_diagnostic_item = "foomp"] //~ ERROR will never be stabilized +#[rustc_diagnostic_item = "foomp"] //~ ERROR compiler internal support for linting struct Foomp; diff --git a/src/test/ui/tool-attributes/diagnostic_item.stderr b/src/test/ui/tool-attributes/diagnostic_item.stderr index 4472914118ba7..deff4da6b8052 100644 --- a/src/test/ui/tool-attributes/diagnostic_item.stderr +++ b/src/test/ui/tool-attributes/diagnostic_item.stderr @@ -1,4 +1,4 @@ -error[E0658]: diagnostic items compiler are internal support for linting and will never be stabilized +error[E0658]: diagnostic items compiler internal support for linting --> $DIR/diagnostic_item.rs:1:1 | LL | #[rustc_diagnostic_item = "foomp"] From 5da1123c5efbd91813fb5ba7cec5298d960ae3af Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 29 Aug 2019 17:49:46 -0700 Subject: [PATCH 332/618] Update zx_time_t to an i64 --- src/libstd/sys/unix/process/zircon.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/sys/unix/process/zircon.rs b/src/libstd/sys/unix/process/zircon.rs index ec715d5490f6f..9224bef7c4a5f 100644 --- a/src/libstd/sys/unix/process/zircon.rs +++ b/src/libstd/sys/unix/process/zircon.rs @@ -3,7 +3,7 @@ use crate::convert::TryInto; use crate::io; use crate::os::raw::c_char; -use crate::u64; +use crate::i64; use libc::{c_int, c_void, size_t}; @@ -14,8 +14,8 @@ pub type zx_status_t = i32; pub const ZX_HANDLE_INVALID: zx_handle_t = 0; -pub type zx_time_t = u64; -pub const ZX_TIME_INFINITE : zx_time_t = u64::MAX; +pub type zx_time_t = i64; +pub const ZX_TIME_INFINITE : zx_time_t = i64::MAX; pub type zx_signals_t = u32; From bee2d3748ef472e416b4a690af89543ed0edd302 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Fri, 30 Aug 2019 04:17:18 +0200 Subject: [PATCH 333/618] Move relocation range copies into allocation --- src/librustc/mir/interpret/allocation.rs | 50 ++++++++++++++++++++++++ src/librustc_mir/interpret/memory.rs | 30 ++------------ 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 75319a6783167..8f47bf9d0fd5a 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -693,6 +693,56 @@ impl DerefMut for Relocations { } } +/// A partial, owned list of relocations to transfer into another allocation. +pub struct AllocationRelocations { + relative_relocations: Vec<(Size, (Tag, AllocId))>, +} + +impl Allocation { + pub fn prepare_relocation_copy( + &self, + cx: &impl HasDataLayout, + src: Pointer, + size: Size, + dest: Pointer, + length: u64, + ) -> AllocationRelocations { + let relocations = self.get_relocations(cx, src, size); + if relocations.is_empty() { + return AllocationRelocations { relative_relocations: Vec::new() }; + } + + let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize)); + + for i in 0..length { + new_relocations.extend( + relocations + .iter() + .map(|&(offset, reloc)| { + // compute offset for current repetition + let dest_offset = dest.offset + (i * size); + ( + // shift offsets from source allocation to destination allocation + offset + dest_offset - src.offset, + reloc, + ) + }) + ); + } + + AllocationRelocations { + relative_relocations: new_relocations, + } + } + + pub fn mark_relocation_range( + &mut self, + relocations: AllocationRelocations, + ) { + self.relocations.insert_presorted(relocations.relative_relocations); + } +} + //////////////////////////////////////////////////////////////////////////////// // Undefined byte tracking //////////////////////////////////////////////////////////////////////////////// diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 26b3f0be8c2b8..6e0d77235fe2b 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -808,32 +808,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // since we don't want to keep any relocations at the target. // (`get_bytes_with_undef_and_ptr` below checks that there are no // relocations overlapping the edges; those would not be handled correctly). - let relocations = { - let relocations = self.get(src.alloc_id)?.get_relocations(self, src, size); - if relocations.is_empty() { - // nothing to copy, ignore even the `length` loop - Vec::new() - } else { - let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize)); - for i in 0..length { - new_relocations.extend( - relocations - .iter() - .map(|&(offset, reloc)| { - // compute offset for current repetition - let dest_offset = dest.offset + (i * size); - ( - // shift offsets from source allocation to destination allocation - offset + dest_offset - src.offset, - reloc, - ) - }) - ); - } - - new_relocations - } - }; + let relocations = self.get(src.alloc_id)? + .prepare_relocation_copy(self, src, size, dest, length); let tcx = self.tcx.tcx; @@ -880,7 +856,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // copy definedness to the destination self.copy_undef_mask(src, dest, size, length)?; // copy the relocations to the destination - self.get_mut(dest.alloc_id)?.relocations.insert_presorted(relocations); + self.get_mut(dest.alloc_id)?.mark_relocation_range(relocations); Ok(()) } From 7388cb4cf81523fb2709518ec8b6a16c329b72e5 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Fri, 30 Aug 2019 04:19:29 +0200 Subject: [PATCH 334/618] Fixup remaining direct relocation field references --- src/librustc_codegen_llvm/consts.rs | 8 ++++---- src/librustc_mir/interpret/snapshot.rs | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 8725e69b11270..958666cb8858a 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -25,12 +25,12 @@ use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags}; use std::ffi::{CStr, CString}; pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value { - let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1); + let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1); let dl = cx.data_layout(); let pointer_size = dl.pointer_size.bytes() as usize; let mut next_offset = 0; - for &(offset, ((), alloc_id)) in alloc.relocations.iter() { + for &(offset, ((), alloc_id)) in alloc.relocations().iter() { let offset = offset.bytes(); assert_eq!(offset as usize as u64, offset); let offset = offset as usize; @@ -455,7 +455,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { // // We could remove this hack whenever we decide to drop macOS 10.10 support. if self.tcx.sess.target.target.options.is_like_osx { - assert_eq!(alloc.relocations.len(), 0); + assert_eq!(alloc.relocations().len(), 0); let is_zeroed = { // Treats undefined bytes as if they were defined with the byte value that @@ -490,7 +490,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { section.as_str().as_ptr() as *const _, section.as_str().len() as c_uint, ); - assert!(alloc.relocations.is_empty()); + assert!(alloc.relocations().is_empty()); // The `inspect` method is okay here because we checked relocations, and // because we are doing this access to inspect the final interpreter state (not diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 0f0c422d8d3f4..2cac8bb0c517e 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -287,7 +287,6 @@ impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { let Allocation { - relocations, size, align, mutability, @@ -300,7 +299,9 @@ impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation // influence interpreter exeuction, but only to detect the error of cycles in evalution // dependencies. let bytes = self.inspect_with_undef_and_ptr_outside_interpreter(all_bytes); + let undef_mask = self.undef_mask(); + let relocations = self.relocations(); AllocationSnapshot { bytes, From 0f3e596c1d34b74c79133f3996d2c655a2cf8e66 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Aug 2019 12:54:46 +0200 Subject: [PATCH 335/618] miri: detect too large dynamically sized objects --- src/librustc_mir/interpret/eval_context.rs | 27 ++++++++++++---------- src/librustc_mir/interpret/traits.rs | 7 +++++- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index ac01d436bdc9b..054b65f0e1a9e 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -442,27 +442,30 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Issue #27023: must add any necessary padding to `size` // (to make it a multiple of `align`) before returning it. - // - // Namely, the returned size should be, in C notation: - // - // `size + ((size & (align-1)) ? align : 0)` - // - // emulated via the semi-standard fast bit trick: - // - // `(size + (align-1)) & -align` - - Ok(Some((size.align_to(align), align))) + let size = size.align_to(align); + + // Check if this brought us over the size limit. + if size.bytes() >= self.tcx.data_layout().obj_size_bound() { + throw_ub_format!("wide pointer metadata contains invalid information: \ + total size is bigger than largest supported object"); + } + Ok(Some((size, align))) } ty::Dynamic(..) => { let vtable = metadata.expect("dyn trait fat ptr must have vtable"); - // the second entry in the vtable is the dynamic size of the object. + // Read size and align from vtable (already checks size). Ok(Some(self.read_size_and_align_from_vtable(vtable)?)) } ty::Slice(_) | ty::Str => { let len = metadata.expect("slice fat ptr must have vtable").to_usize(self)?; let elem = layout.field(self, 0)?; - Ok(Some((elem.size * len, elem.align.abi))) + + // Make sure the slice is not too big. + let size = elem.size.checked_mul(len, &*self.tcx) + .ok_or_else(|| err_ub_format!("invalid slice: \ + total size is bigger than largest supported object"))?; + Ok(Some((size, elem.align.abi))) } ty::Foreign(_) => { diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 34a10de7de7fc..10b767ebba191 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -1,5 +1,5 @@ use rustc::ty::{self, Ty, Instance, TypeFoldable}; -use rustc::ty::layout::{Size, Align, LayoutOf}; +use rustc::ty::layout::{Size, Align, LayoutOf, HasDataLayout}; use rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic,}; use super::{InterpCx, Machine, MemoryKind, FnVal}; @@ -151,6 +151,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { vtable.offset(pointer_size * 2, self)?, )?.not_undef()?; let align = self.force_bits(align, pointer_size)? as u64; + + if size >= self.tcx.data_layout().obj_size_bound() { + throw_ub_format!("invalid vtable: \ + size is bigger than largest supported object"); + } Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap())) } } From 235ee34a15a272aa7eb540a632e719fbae68329b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Aug 2019 18:36:11 +0200 Subject: [PATCH 336/618] better variable names --- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 20 +++++------ .../ui/consts/const-eval/ub-wide-ptr.stderr | 36 +++++++++---------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 765ed60ee9742..c67108836fa4e 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -91,10 +91,10 @@ const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { //~^ ERROR it is undefined behavior to use this value // invalid UTF-8 -const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; +const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; //~^ ERROR it is undefined behavior to use this value // invalid UTF-8 in user-defined str-like -const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; +const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; //~^ ERROR it is undefined behavior to use this value // # slice @@ -111,16 +111,16 @@ const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { pt //~^ ERROR it is undefined behavior to use this value // bad data *inside* the slice -const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; +const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; //~^ ERROR it is undefined behavior to use this value // good MySliceBool -const I1: &MySliceBool = &MySlice(true, [false]); +const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]); // bad: sized field is not okay -const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); +const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); //~^ ERROR it is undefined behavior to use this value // bad: unsized part is not okay -const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); +const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); //~^ ERROR it is undefined behavior to use this value // # raw slice @@ -132,17 +132,17 @@ const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 // # trait object // bad trait object -const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; +const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; //~^ ERROR it is undefined behavior to use this value // bad trait object -const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; +const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; //~^ ERROR it is undefined behavior to use this value // bad trait object -const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; +const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; //~^ ERROR it is undefined behavior to use this value // bad data *inside* the trait object -const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; +const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; //~^ ERROR it is undefined behavior to use this value // # raw trait object diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 88d8af8026193..704b42e09b2ae 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -25,16 +25,16 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRe error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:94:1 | -LL | const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . +LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:97:1 | -LL | const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 +LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -65,24 +65,24 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:114:1 | -LL | const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected something less or equal to 1 +LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected something less or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:120:1 | -LL | const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected something less or equal to 1 +LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected something less or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:123:1 | -LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected something less or equal to 1 +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected something less or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -97,32 +97,32 @@ LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:135:1 | -LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:138:1 | -LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:141:1 | -LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:145:1 | -LL | const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 +LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior From d75723e9fe07b71eeaf9dad2d8a76080ea201b83 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 30 Aug 2019 08:37:02 +0200 Subject: [PATCH 337/618] mod-level doc comment for validity check --- src/librustc_mir/interpret/validity.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index c2505547c5b4f..3e14ba3efcc58 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -1,3 +1,9 @@ +//! Check the validity invariant of a given value, and tell the user +//! where in the value it got violated. +//! In const context, this goes even further and tries to approximate const safety. +//! That's useful because it means other passes (e.g. promotion) can rely on `const`s +//! to be const-safe. + use std::fmt::Write; use std::ops::RangeInclusive; From 38f6b96aae299b82d333d72828f3ea589849d907 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 30 Aug 2019 09:29:58 +0200 Subject: [PATCH 338/618] make unions repr(C) --- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 3 ++ .../ui/consts/const-eval/ub-wide-ptr.stderr | 36 +++++++++---------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index c67108836fa4e..1f810c40572c0 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -7,6 +7,7 @@ // normalize-stderr-test "allocation \d+" -> "allocation N" // normalize-stderr-test "size \d+" -> "size N" +#[repr(C)] union BoolTransmute { val: u8, bl: bool, @@ -26,6 +27,7 @@ struct BadSliceRepr { len: &'static u8, } +#[repr(C)] union SliceTransmute { repr: SliceRepr, bad: BadSliceRepr, @@ -58,6 +60,7 @@ struct BadDynRepr { vtable: usize, } +#[repr(C)] union DynTransmute { repr: DynRepr, repr2: DynRepr2, diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 704b42e09b2ae..aadabc323fbd4 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:84:1 + --> $DIR/ub-wide-ptr.rs:87:1 | LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) @@ -7,7 +7,7 @@ LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:87:1 + --> $DIR/ub-wide-ptr.rs:90:1 | LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -15,7 +15,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:90:1 + --> $DIR/ub-wide-ptr.rs:93:1 | LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -23,7 +23,7 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRe = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:94:1 + --> $DIR/ub-wide-ptr.rs:97:1 | LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . @@ -31,7 +31,7 @@ LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:97:1 + --> $DIR/ub-wide-ptr.rs:100:1 | LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 @@ -39,7 +39,7 @@ LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:104:1 + --> $DIR/ub-wide-ptr.rs:107:1 | LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata @@ -47,7 +47,7 @@ LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.sli = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:107:1 + --> $DIR/ub-wide-ptr.rs:110:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) @@ -55,7 +55,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { p = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:110:1 + --> $DIR/ub-wide-ptr.rs:113:1 | LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -63,7 +63,7 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:114:1 + --> $DIR/ub-wide-ptr.rs:117:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected something less or equal to 1 @@ -71,7 +71,7 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }. = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:120:1 + --> $DIR/ub-wide-ptr.rs:123:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected something less or equal to 1 @@ -79,7 +79,7 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:123:1 + --> $DIR/ub-wide-ptr.rs:126:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected something less or equal to 1 @@ -87,7 +87,7 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTrans = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:130:1 + --> $DIR/ub-wide-ptr.rs:133:1 | LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata @@ -95,7 +95,7 @@ LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:135:1 + --> $DIR/ub-wide-ptr.rs:138:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -103,7 +103,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:138:1 + --> $DIR/ub-wide-ptr.rs:141:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -111,7 +111,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:141:1 + --> $DIR/ub-wide-ptr.rs:144:1 | LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -119,7 +119,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDy = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:145:1 + --> $DIR/ub-wide-ptr.rs:148:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 @@ -127,7 +127,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:149:1 + --> $DIR/ub-wide-ptr.rs:152:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -135,7 +135,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:151:1 + --> $DIR/ub-wide-ptr.rs:154:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable From cf574091fb10496a72b8f105d6f8f14f3eff0db6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 30 Aug 2019 09:30:59 +0200 Subject: [PATCH 339/618] tweak const-valid test --- src/test/ui/consts/const-eval/valid-const.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/ui/consts/const-eval/valid-const.rs b/src/test/ui/consts/const-eval/valid-const.rs index 30bd47219239e..65c642d750b51 100644 --- a/src/test/ui/consts/const-eval/valid-const.rs +++ b/src/test/ui/consts/const-eval/valid-const.rs @@ -1,7 +1,8 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass // Some constants that *are* valid #![feature(const_transmute)] +#![deny(const_err)] use std::mem; use std::ptr::NonNull; From e7fed140a4db638562077afc0ec5ef174a25bcc0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 30 Aug 2019 09:31:21 +0200 Subject: [PATCH 340/618] explain why REF_AS_USIZE is important --- src/test/ui/consts/const-eval/ub-ref.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs index bbab85c2121a5..03ac12c8b1ac1 100644 --- a/src/test/ui/consts/const-eval/ub-ref.rs +++ b/src/test/ui/consts/const-eval/ub-ref.rs @@ -11,6 +11,9 @@ const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; const NULL: &u16 = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value +// It is very important that we reject this: We do promote `&(4 * REF_AS_USIZE)`, +// but that would fail to compile; so we ended up breaking user code that would +// have worked fine had we not promoted. const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; //~^ ERROR it is undefined behavior to use this value From 6d86163ffb0209aca8bf097c07304291e0f10a28 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 30 Aug 2019 09:35:02 +0200 Subject: [PATCH 341/618] const-eval tests: make all unions repr(C) --- .../const-pointer-values-in-various-types.rs | 1 + ...nst-pointer-values-in-various-types.stderr | 58 +++++++++---------- .../ui/consts/const-eval/const_transmute.rs | 1 + src/test/ui/consts/const-eval/double_check.rs | 1 + .../ui/consts/const-eval/double_check2.rs | 1 + .../ui/consts/const-eval/double_check2.stderr | 2 +- .../const-eval/feature-gate-const_fn_union.rs | 1 + .../feature-gate-const_fn_union.stderr | 2 +- src/test/ui/consts/const-eval/issue-49296.rs | 1 + .../ui/consts/const-eval/issue-49296.stderr | 2 +- .../const-eval/promoted_const_fn_fail.rs | 1 + .../const-eval/promoted_const_fn_fail.stderr | 2 +- .../promoted_const_fn_fail_deny_const_err.rs | 1 + ...omoted_const_fn_fail_deny_const_err.stderr | 2 +- .../ui/consts/const-eval/ref_to_int_match.rs | 1 + .../consts/const-eval/ref_to_int_match.stderr | 2 +- src/test/ui/consts/const-eval/ub-enum.rs | 3 + src/test/ui/consts/const-eval/ub-enum.stderr | 18 +++--- src/test/ui/consts/const-eval/ub-nonnull.rs | 1 + .../ui/consts/const-eval/ub-nonnull.stderr | 6 +- src/test/ui/consts/const-eval/ub-ref.stderr | 6 +- src/test/ui/consts/const-eval/ub-uninhabit.rs | 1 + .../ui/consts/const-eval/ub-uninhabit.stderr | 6 +- .../const-eval/union-const-eval-field.rs | 1 + .../const-eval/union-const-eval-field.stderr | 2 +- src/test/ui/consts/const-eval/union-ice.rs | 1 + .../ui/consts/const-eval/union-ice.stderr | 6 +- src/test/ui/consts/const-eval/union-ub.rs | 3 + src/test/ui/consts/const-eval/union-ub.stderr | 2 +- .../ui/consts/const-eval/union_promotion.rs | 1 + .../consts/const-eval/union_promotion.stderr | 2 +- 31 files changed, 79 insertions(+), 59 deletions(-) diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs index cc5ddb4401644..a2196db780ce0 100644 --- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs @@ -1,5 +1,6 @@ // only-x86_64 +#[repr(C)] union Nonsense { u: usize, int_32_ref: &'static i32, diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr index 73aca911531f1..3333ffac4c9b0 100644 --- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:24:5 + --> $DIR/const-pointer-values-in-various-types.rs:25:5 | LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes @@ -7,7 +7,7 @@ LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 } = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:27:43 + --> $DIR/const-pointer-values-in-various-types.rs:28:43 | LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -17,7 +17,7 @@ LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_ = note: `#[deny(const_err)]` on by default error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:30:45 + --> $DIR/const-pointer-values-in-various-types.rs:31:45 | LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -25,7 +25,7 @@ LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uin | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:33:45 + --> $DIR/const-pointer-values-in-various-types.rs:34:45 | LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -33,7 +33,7 @@ LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uin | a raw memory access tried to access part of a pointer value as raw bytes error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:36:5 + --> $DIR/const-pointer-values-in-various-types.rs:37:5 | LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes @@ -41,7 +41,7 @@ LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uin = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:39:5 + --> $DIR/const-pointer-values-in-various-types.rs:40:5 | LL | const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes @@ -49,7 +49,7 @@ LL | const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.u = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:42:43 + --> $DIR/const-pointer-values-in-various-types.rs:43:43 | LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -57,7 +57,7 @@ LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:45:45 + --> $DIR/const-pointer-values-in-various-types.rs:46:45 | LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -65,7 +65,7 @@ LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:48:45 + --> $DIR/const-pointer-values-in-various-types.rs:49:45 | LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -73,7 +73,7 @@ LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int | a raw memory access tried to access part of a pointer value as raw bytes error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:51:5 + --> $DIR/const-pointer-values-in-various-types.rs:52:5 | LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes @@ -81,7 +81,7 @@ LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:54:5 + --> $DIR/const-pointer-values-in-various-types.rs:55:5 | LL | const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes @@ -89,7 +89,7 @@ LL | const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.i = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:57:45 + --> $DIR/const-pointer-values-in-various-types.rs:58:45 | LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -97,7 +97,7 @@ LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.flo | a raw memory access tried to access part of a pointer value as raw bytes error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:60:5 + --> $DIR/const-pointer-values-in-various-types.rs:61:5 | LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes @@ -105,7 +105,7 @@ LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.flo = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:63:47 + --> $DIR/const-pointer-values-in-various-types.rs:64:47 | LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey }; | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -113,7 +113,7 @@ LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.t | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:66:47 + --> $DIR/const-pointer-values-in-various-types.rs:67:47 | LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character }; | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -121,7 +121,7 @@ LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.c | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:69:39 + --> $DIR/const-pointer-values-in-various-types.rs:70:39 | LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -129,7 +129,7 @@ LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:72:41 + --> $DIR/const-pointer-values-in-various-types.rs:73:41 | LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -137,7 +137,7 @@ LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 } | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:75:41 + --> $DIR/const-pointer-values-in-various-types.rs:76:41 | LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -145,7 +145,7 @@ LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 } | a raw memory access tried to access part of a pointer value as raw bytes error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:78:5 + --> $DIR/const-pointer-values-in-various-types.rs:79:5 | LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes @@ -153,7 +153,7 @@ LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 } = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:81:43 + --> $DIR/const-pointer-values-in-various-types.rs:82:43 | LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -161,7 +161,7 @@ LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_12 | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:84:39 + --> $DIR/const-pointer-values-in-various-types.rs:85:39 | LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -169,7 +169,7 @@ LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:87:41 + --> $DIR/const-pointer-values-in-various-types.rs:88:41 | LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -177,7 +177,7 @@ LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:90:41 + --> $DIR/const-pointer-values-in-various-types.rs:91:41 | LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -185,7 +185,7 @@ LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; | a raw memory access tried to access part of a pointer value as raw bytes error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:93:5 + --> $DIR/const-pointer-values-in-various-types.rs:94:5 | LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes @@ -193,7 +193,7 @@ LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:96:43 + --> $DIR/const-pointer-values-in-various-types.rs:97:43 | LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -201,7 +201,7 @@ LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:99:41 + --> $DIR/const-pointer-values-in-various-types.rs:100:41 | LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -209,7 +209,7 @@ LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 | a raw memory access tried to access part of a pointer value as raw bytes error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:102:5 + --> $DIR/const-pointer-values-in-various-types.rs:103:5 | LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes @@ -217,7 +217,7 @@ LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:105:43 + --> $DIR/const-pointer-values-in-various-types.rs:106:43 | LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -225,7 +225,7 @@ LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_ | a raw memory access tried to access part of a pointer value as raw bytes error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:108:43 + --> $DIR/const-pointer-values-in-various-types.rs:109:43 | LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- diff --git a/src/test/ui/consts/const-eval/const_transmute.rs b/src/test/ui/consts/const-eval/const_transmute.rs index 0e0e003dcf476..4a7d8490ef25f 100644 --- a/src/test/ui/consts/const-eval/const_transmute.rs +++ b/src/test/ui/consts/const-eval/const_transmute.rs @@ -2,6 +2,7 @@ #![feature(const_fn_union)] +#[repr(C)] union Transmute { t: T, u: U, diff --git a/src/test/ui/consts/const-eval/double_check.rs b/src/test/ui/consts/const-eval/double_check.rs index 2cf6a5494dd8d..ff2fff7fb790e 100644 --- a/src/test/ui/consts/const-eval/double_check.rs +++ b/src/test/ui/consts/const-eval/double_check.rs @@ -8,6 +8,7 @@ enum Bar { C = 42, D = 99, } +#[repr(C)] union Union { foo: &'static Foo, bar: &'static Bar, diff --git a/src/test/ui/consts/const-eval/double_check2.rs b/src/test/ui/consts/const-eval/double_check2.rs index dc2b58faf9215..7c222b113cd7d 100644 --- a/src/test/ui/consts/const-eval/double_check2.rs +++ b/src/test/ui/consts/const-eval/double_check2.rs @@ -6,6 +6,7 @@ enum Bar { C = 42, D = 99, } +#[repr(C)] union Union { foo: &'static Foo, bar: &'static Bar, diff --git a/src/test/ui/consts/const-eval/double_check2.stderr b/src/test/ui/consts/const-eval/double_check2.stderr index 2b61d33852c98..9c56f1995208f 100644 --- a/src/test/ui/consts/const-eval/double_check2.stderr +++ b/src/test/ui/consts/const-eval/double_check2.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/double_check2.rs:15:1 + --> $DIR/double_check2.rs:16:1 | LL | / static FOO: (&Foo, &Bar) = unsafe {( LL | | Union { u8: &BAR }.foo, diff --git a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs index b0ae746ace58d..3f7bab065869a 100644 --- a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs +++ b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs @@ -2,6 +2,7 @@ fn main() {} +#[repr(C)] union Foo { u: u32, i: i32, diff --git a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr index 5bf43cb8b6add..6899b7b82c532 100644 --- a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr +++ b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr @@ -1,5 +1,5 @@ error[E0658]: unions in const fn are unstable - --> $DIR/feature-gate-const_fn_union.rs:11:5 + --> $DIR/feature-gate-const_fn_union.rs:12:5 | LL | Foo { u }.i | ^^^^^^^^^^^ diff --git a/src/test/ui/consts/const-eval/issue-49296.rs b/src/test/ui/consts/const-eval/issue-49296.rs index a7c3c5318d430..c6caeeffd22dd 100644 --- a/src/test/ui/consts/const-eval/issue-49296.rs +++ b/src/test/ui/consts/const-eval/issue-49296.rs @@ -4,6 +4,7 @@ #![feature(const_fn_union)] const unsafe fn transmute(t: T) -> U { + #[repr(C)] union Transmute { from: T, to: U, diff --git a/src/test/ui/consts/const-eval/issue-49296.stderr b/src/test/ui/consts/const-eval/issue-49296.stderr index 7a4bba8daa70b..48809e0ae649c 100644 --- a/src/test/ui/consts/const-eval/issue-49296.stderr +++ b/src/test/ui/consts/const-eval/issue-49296.stderr @@ -1,5 +1,5 @@ error: any use of this value will cause an error - --> $DIR/issue-49296.rs:18:16 + --> $DIR/issue-49296.rs:19:16 | LL | const X: u64 = *wat(42); | ---------------^^^^^^^^- diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs b/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs index 88181cb86100f..3edd4e086867b 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs @@ -2,6 +2,7 @@ #![allow(const_err)] +#[repr(C)] union Bar { a: &'static u8, b: usize, diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr index 519ba7d84b087..6618f1cd1c0b5 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_fn_fail.rs:20:27 + --> $DIR/promoted_const_fn_fail.rs:21:27 | LL | let x: &'static u8 = &(bar() + 1); | ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs index 061ab7eeb029d..7887e42653464 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs @@ -2,6 +2,7 @@ #![deny(const_err)] +#[repr(C)] union Bar { a: &'static u8, b: usize, diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr index 987d2304ae871..5f9f3bda87b15 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_fn_fail_deny_const_err.rs:21:27 + --> $DIR/promoted_const_fn_fail_deny_const_err.rs:22:27 | LL | let x: &'static u8 = &(bar() + 1); | ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.rs b/src/test/ui/consts/const-eval/ref_to_int_match.rs index b6a2ed1f9bcf4..45ce040fb9eef 100644 --- a/src/test/ui/consts/const-eval/ref_to_int_match.rs +++ b/src/test/ui/consts/const-eval/ref_to_int_match.rs @@ -9,6 +9,7 @@ fn main() { } } +#[repr(C)] union Foo { f: Int, r: &'static u32, diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.stderr index f8eafed68e43d..0be82e3434142 100644 --- a/src/test/ui/consts/const-eval/ref_to_int_match.stderr +++ b/src/test/ui/consts/const-eval/ref_to_int_match.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ref_to_int_match.rs:23:1 + --> $DIR/ref_to_int_match.rs:24:1 | LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs index d4b2220695102..483285aa4e123 100644 --- a/src/test/ui/consts/const-eval/ub-enum.rs +++ b/src/test/ui/consts/const-eval/ub-enum.rs @@ -10,6 +10,7 @@ struct Wrap(T); enum Enum { A = 0, } +#[repr(C)] union TransmuteEnum { in1: &'static u8, in2: usize, @@ -35,6 +36,7 @@ enum Enum2 { A = 2, } +#[repr(C)] union TransmuteEnum2 { in1: usize, in2: &'static u8, @@ -60,6 +62,7 @@ const BAD_ENUM2_OPTION_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }. // Invalid enum field content (mostly to test printing of paths for enum tuple // variants and tuples). +#[repr(C)] union TransmuteChar { a: u32, b: char, diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index 8ecb1aabdd0f7..30dd86592d469 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:22:1 + --> $DIR/ub-enum.rs:23:1 | LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant @@ -7,7 +7,7 @@ LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:25:1 + --> $DIR/ub-enum.rs:26:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant @@ -15,7 +15,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:28:1 + --> $DIR/ub-enum.rs:29:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { TransmuteEnum { in1: &1 }.out2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 0 @@ -23,7 +23,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { TransmuteEnum { in1: &1 }.out = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:46:1 + --> $DIR/ub-enum.rs:48:1 | LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant @@ -31,7 +31,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:48:1 + --> $DIR/ub-enum.rs:50:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant @@ -39,7 +39,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:50:1 + --> $DIR/ub-enum.rs:52:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { TransmuteEnum2 { in2: &0 }.out2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 2 @@ -47,7 +47,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { TransmuteEnum2 { in2: &0 }. = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:54:1 + --> $DIR/ub-enum.rs:56:1 | LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid enum discriminant @@ -55,7 +55,7 @@ LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:58:1 + --> $DIR/ub-enum.rs:60:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }.out3 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant @@ -63,7 +63,7 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { TransmuteEnum2 { in2: = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:68:1 + --> $DIR/ub-enum.rs:71:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected something less or equal to 1114111 diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs index 9edae1965ce16..8ce64ced7dff4 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.rs +++ b/src/test/ui/consts/const-eval/ub-nonnull.rs @@ -24,6 +24,7 @@ const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value +#[repr(C)] union Transmute { uninit: (), out: NonZeroU8, diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr index 7b3c97e5fbf96..de20c3d0b8cfe 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr @@ -41,7 +41,7 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:31:1 + --> $DIR/ub-nonnull.rs:32:1 | LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected something greater or equal to 1 @@ -49,7 +49,7 @@ LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:39:1 + --> $DIR/ub-nonnull.rs:40:1 | LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30 @@ -57,7 +57,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:45:1 + --> $DIR/ub-nonnull.rs:46:1 | LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30 diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr index f1702955ed7b1..cd3cc38467c36 100644 --- a/src/test/ui/consts/const-eval/ub-ref.stderr +++ b/src/test/ui/consts/const-eval/ub-ref.stderr @@ -15,7 +15,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:14:1 + --> $DIR/ub-ref.rs:17:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes @@ -23,7 +23,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:17:1 + --> $DIR/ub-ref.rs:20:1 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes @@ -31,7 +31,7 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:20:1 + --> $DIR/ub-ref.rs:23:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (created from integer) diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.rs b/src/test/ui/consts/const-eval/ub-uninhabit.rs index 42cba02f579b7..d2745d71bdb2f 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.rs +++ b/src/test/ui/consts/const-eval/ub-uninhabit.rs @@ -6,6 +6,7 @@ use std::mem; #[derive(Copy, Clone)] enum Bar {} +#[repr(C)] union TransmuteUnion { a: A, b: B, diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr index c8842ecc23ca2..43d91483797bf 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-uninhabit.rs:14:1 + --> $DIR/ub-uninhabit.rs:15:1 | LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type @@ -7,7 +7,7 @@ LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b } = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-uninhabit.rs:17:1 + --> $DIR/ub-uninhabit.rs:18:1 | LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at . @@ -15,7 +15,7 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-uninhabit.rs:20:1 + --> $DIR/ub-uninhabit.rs:21:1 | LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type diff --git a/src/test/ui/consts/const-eval/union-const-eval-field.rs b/src/test/ui/consts/const-eval/union-const-eval-field.rs index 56f3ef3db25d1..7f29a5bc24e4e 100644 --- a/src/test/ui/consts/const-eval/union-const-eval-field.rs +++ b/src/test/ui/consts/const-eval/union-const-eval-field.rs @@ -4,6 +4,7 @@ type Field1 = i32; type Field2 = f32; type Field3 = i64; +#[repr(C)] union DummyUnion { field1: Field1, field2: Field2, diff --git a/src/test/ui/consts/const-eval/union-const-eval-field.stderr b/src/test/ui/consts/const-eval/union-const-eval-field.stderr index 4a53337341e67..4d008a0e02ad7 100644 --- a/src/test/ui/consts/const-eval/union-const-eval-field.stderr +++ b/src/test/ui/consts/const-eval/union-const-eval-field.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/union-const-eval-field.rs:27:5 + --> $DIR/union-const-eval-field.rs:28:5 | LL | const FIELD3: Field3 = unsafe { UNION.field3 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes diff --git a/src/test/ui/consts/const-eval/union-ice.rs b/src/test/ui/consts/const-eval/union-ice.rs index 33736b360d33a..5a14c7fd99345 100644 --- a/src/test/ui/consts/const-eval/union-ice.rs +++ b/src/test/ui/consts/const-eval/union-ice.rs @@ -3,6 +3,7 @@ type Field1 = i32; type Field3 = i64; +#[repr(C)] union DummyUnion { field1: Field1, field3: Field3, diff --git a/src/test/ui/consts/const-eval/union-ice.stderr b/src/test/ui/consts/const-eval/union-ice.stderr index b25cb8c5aa021..8d950e86d27fc 100644 --- a/src/test/ui/consts/const-eval/union-ice.stderr +++ b/src/test/ui/consts/const-eval/union-ice.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ice.rs:13:1 + --> $DIR/union-ice.rs:14:1 | LL | const FIELD3: Field3 = unsafe { UNION.field3 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes @@ -7,7 +7,7 @@ LL | const FIELD3: Field3 = unsafe { UNION.field3 }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ice.rs:15:1 + --> $DIR/union-ice.rs:16:1 | LL | / const FIELD_PATH: Struct = Struct { LL | | a: 42, @@ -18,7 +18,7 @@ LL | | }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ice.rs:25:1 + --> $DIR/union-ice.rs:26:1 | LL | / const FIELD_PATH2: Struct2 = Struct2 { LL | | b: [ diff --git a/src/test/ui/consts/const-eval/union-ub.rs b/src/test/ui/consts/const-eval/union-ub.rs index cf436141c5a02..848826e6ef7f2 100644 --- a/src/test/ui/consts/const-eval/union-ub.rs +++ b/src/test/ui/consts/const-eval/union-ub.rs @@ -1,5 +1,6 @@ #![allow(const_err)] // make sure we cannot allow away the errors tested here +#[repr(C)] union DummyUnion { u8: u8, bool: bool, @@ -14,11 +15,13 @@ enum Enum { } #[derive(Copy, Clone)] +#[repr(C)] union Foo { a: bool, b: Enum, } +#[repr(C)] union Bar { foo: Foo, u8: u8, diff --git a/src/test/ui/consts/const-eval/union-ub.stderr b/src/test/ui/consts/const-eval/union-ub.stderr index 7baa55be6e11e..6a3a397585c89 100644 --- a/src/test/ui/consts/const-eval/union-ub.stderr +++ b/src/test/ui/consts/const-eval/union-ub.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub.rs:28:1 + --> $DIR/union-ub.rs:31:1 | LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something less or equal to 1 diff --git a/src/test/ui/consts/const-eval/union_promotion.rs b/src/test/ui/consts/const-eval/union_promotion.rs index d3566511ef8ee..7167f88a1185b 100644 --- a/src/test/ui/consts/const-eval/union_promotion.rs +++ b/src/test/ui/consts/const-eval/union_promotion.rs @@ -1,5 +1,6 @@ #![allow(const_err)] +#[repr(C)] union Foo { a: &'static u32, b: usize, diff --git a/src/test/ui/consts/const-eval/union_promotion.stderr b/src/test/ui/consts/const-eval/union_promotion.stderr index b530c02f2fb93..ed186e3ebd2f5 100644 --- a/src/test/ui/consts/const-eval/union_promotion.stderr +++ b/src/test/ui/consts/const-eval/union_promotion.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/union_promotion.rs:9:29 + --> $DIR/union_promotion.rs:10:29 | LL | let x: &'static bool = &unsafe { | ____________-------------____^ From fdc4f9028f838605d031248abda0ebfb7450bf9f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 28 Aug 2019 13:21:47 +0200 Subject: [PATCH 342/618] Add missing examples for Option type --- src/libcore/option.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 259ed36c57885..79bd04b724390 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1110,6 +1110,18 @@ impl Option { /// to the original one, additionally coercing the contents via [`Deref`]. /// /// [`Deref`]: ../../std/ops/trait.Deref.html + /// + /// # Examples + /// + /// ``` + /// #![feature(inner_deref)] + /// + /// let x: Option = Some("hey".to_owned()); + /// assert_eq!(x.as_deref(), Some("hey")); + /// + /// let x: Option = None; + /// assert_eq!(x.as_deref(), None); + /// ``` pub fn as_deref(&self) -> Option<&T::Target> { self.as_ref().map(|t| t.deref()) } @@ -1121,6 +1133,18 @@ impl Option { /// /// Leaves the original `Option` in-place, creating a new one containing a mutable reference to /// the inner type's `Deref::Target` type. + /// + /// # Examples + /// + /// ``` + /// #![feature(inner_deref)] + /// + /// let mut x: Option = Some("hey".to_owned()); + /// assert_eq!(x.as_deref_mut().map(|x| { + /// x.make_ascii_uppercase(); + /// x + /// }), Some("HEY".to_owned().as_mut_str())); + /// ``` pub fn as_deref_mut(&mut self) -> Option<&mut T::Target> { self.as_mut().map(|t| t.deref_mut()) } @@ -1199,6 +1223,13 @@ impl Clone for Option { #[stable(feature = "rust1", since = "1.0.0")] impl Default for Option { /// Returns [`None`][Option::None]. + /// + /// # Examples + /// + /// ``` + /// let opt: Option = Option::default(); + /// assert!(opt.is_none()); + /// ``` #[inline] fn default() -> Option { None } } From 4240168edae7c4ec9c8bf78892cbf5316ad7b781 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 30 Aug 2019 09:53:42 +0200 Subject: [PATCH 343/618] Update Clippy --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index a939d61cf7fea..70e7d075df7b3 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit a939d61cf7feac0f328aec07f050c4ac96c51d2c +Subproject commit 70e7d075df7b3e11e61fa99b30e1ede26cee6afd From 55800ce899d63dd80ad0c99e5617fc275b5e6644 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 30 Aug 2019 14:10:46 +0200 Subject: [PATCH 344/618] Skip wrapping arithmetic tests on emscripten for 128 bit integers --- src/test/ui/wrapping-int-combinations.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/ui/wrapping-int-combinations.rs b/src/test/ui/wrapping-int-combinations.rs index 431194ccd1dec..f0bc479ee0ff2 100644 --- a/src/test/ui/wrapping-int-combinations.rs +++ b/src/test/ui/wrapping-int-combinations.rs @@ -64,12 +64,14 @@ fn main() { wrapping_test!(i16, std::i16::MIN, std::i16::MAX); wrapping_test!(i32, std::i32::MIN, std::i32::MAX); wrapping_test!(i64, std::i64::MIN, std::i64::MAX); + #[cfg(not(target_os = "emscripten"))] wrapping_test!(i128, std::i128::MIN, std::i128::MAX); wrapping_test!(isize, std::isize::MIN, std::isize::MAX); wrapping_test!(u8, std::u8::MIN, std::u8::MAX); wrapping_test!(u16, std::u16::MIN, std::u16::MAX); wrapping_test!(u32, std::u32::MIN, std::u32::MAX); wrapping_test!(u64, std::u64::MIN, std::u64::MAX); + #[cfg(not(target_os = "emscripten"))] wrapping_test!(u128, std::u128::MIN, std::u128::MAX); wrapping_test!(usize, std::usize::MIN, std::usize::MAX); } From bb3474994b94472a292fec6ebfdc21cda4d8cc70 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 30 Aug 2019 15:04:12 +0200 Subject: [PATCH 345/618] add test --- src/test/ui/consts/const-eval/dangling.rs | 13 +++++++++++++ src/test/ui/consts/const-eval/dangling.stderr | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/test/ui/consts/const-eval/dangling.rs create mode 100644 src/test/ui/consts/const-eval/dangling.stderr diff --git a/src/test/ui/consts/const-eval/dangling.rs b/src/test/ui/consts/const-eval/dangling.rs new file mode 100644 index 0000000000000..b5d72d46f2861 --- /dev/null +++ b/src/test/ui/consts/const-eval/dangling.rs @@ -0,0 +1,13 @@ +#![feature(const_transmute, const_raw_ptr_deref)] + +use std::{mem, usize}; + +// Make sure we error with the right kind of error on a too large slice. +const TEST: () = { unsafe { //~ NOTE + let slice: *const [u8] = mem::transmute((1usize, usize::MAX)); + let _val = &*slice; //~ ERROR: any use of this value will cause an error + //~^ NOTE: total size is bigger than largest supported object + //~^^ on by default +} }; + +fn main() {} diff --git a/src/test/ui/consts/const-eval/dangling.stderr b/src/test/ui/consts/const-eval/dangling.stderr new file mode 100644 index 0000000000000..286de08009754 --- /dev/null +++ b/src/test/ui/consts/const-eval/dangling.stderr @@ -0,0 +1,16 @@ +error: any use of this value will cause an error + --> $DIR/dangling.rs:8:16 + | +LL | / const TEST: () = { unsafe { +LL | | let slice: *const [u8] = mem::transmute((1usize, usize::MAX)); +LL | | let _val = &*slice; + | | ^^^^^^^ invalid slice: total size is bigger than largest supported object +LL | | +LL | | +LL | | } }; + | |____- + | + = note: `#[deny(const_err)]` on by default + +error: aborting due to previous error + From 0e597d4c479b4533e38016b1adbe565b44aab922 Mon Sep 17 00:00:00 2001 From: Xiang Fan Date: Fri, 30 Aug 2019 21:17:36 +0800 Subject: [PATCH 346/618] Rev::rposition counts from the wrong end Because of a compiler bug that adding `Self: ExactSizeIterator` makes the compiler forget `Self::Item` is `::Item`, we remove this specialization for now. --- src/libcore/iter/adapters/mod.rs | 7 ------- src/libcore/tests/iter.rs | 6 ++++++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index f50781890ab22..8e1ac6082c8a8 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -66,13 +66,6 @@ impl Iterator for Rev where I: DoubleEndedIterator { { self.iter.rfind(predicate) } - - #[inline] - fn rposition

(&mut self, predicate: P) -> Option where - P: FnMut(Self::Item) -> bool - { - self.iter.position(predicate) - } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 3a4f76852a0d7..8e0658d87c1fb 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1688,6 +1688,12 @@ fn test_rposition() { assert!(v.iter().rposition(g).is_none()); } +#[test] +fn test_rev_rposition() { + let v = [0, 0, 1, 1]; + assert_eq!(v.iter().rev().rposition(|&x| x == 1), Some(1)); +} + #[test] #[should_panic] fn test_rposition_panic() { From 9fd203a01e0fe6fb307809fdfdbfcd3bda350cfc Mon Sep 17 00:00:00 2001 From: newpavlov Date: Fri, 30 Aug 2019 17:30:33 +0300 Subject: [PATCH 347/618] simplify code --- src/libstd/sys/wasi/thread.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index 987bf7580838b..28a504f197974 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -46,11 +46,18 @@ impl Thread { type_: wasi::EVENTTYPE_CLOCK, u: wasi::raw::__wasi_subscription_u { clock: clock }, }]; - let mut out: [wasi::Event; 1] = [unsafe { mem::zeroed() }]; - let n = unsafe { wasi::poll_oneoff(&in_, &mut out).unwrap() }; - let wasi::Event { userdata, error, type_, .. } = out[0]; - match (n, userdata, error) { - (1, CLOCK_ID, 0) if type_ == wasi::EVENTTYPE_CLOCK => {} + let (res, event) = unsafe { + let mut out: [wasi::Event; 1] = mem::zeroed(); + let res = wasi::poll_oneoff(&in_, &mut out); + (res, out[0]) + }; + match (res, event) { + (Ok(1), wasi::Event { + userdata: CLOCK_ID, + error: 0, + type_: wasi::EVENTTYPE_CLOCK, + .. + }) => {} _ => panic!("thread::sleep(): unexpected result of poll_oneoff"), } } From 403701f97628b85bfa3e5ec0e5ca82b81d53ba1e Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 30 Aug 2019 11:51:04 -0700 Subject: [PATCH 348/618] Don't try to use /dev/null on Fuchsia --- src/libstd/sys/unix/process/process_common.rs | 28 +++++++++++++++++-- .../sys/unix/process/process_fuchsia.rs | 15 ++++++---- src/libstd/sys/unix/process/zircon.rs | 2 +- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 6bb20bbe08794..511e67840803e 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -1,19 +1,27 @@ use crate::os::unix::prelude::*; -use crate::ffi::{OsString, OsStr, CString, CStr}; +use crate::ffi::{OsString, OsStr, CString}; use crate::fmt; use crate::io; use crate::ptr; use crate::sys::fd::FileDesc; -use crate::sys::fs::{File, OpenOptions}; +use crate::sys::fs::File; use crate::sys::pipe::{self, AnonPipe}; use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; use crate::collections::BTreeMap; +#[cfg(not(target_os = "fuchsia"))] +use { + crate::ffi::CStr, + crate::sys::fs::OpenOptions, +}; + use libc::{c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE}; cfg_if::cfg_if! { - if #[cfg(target_os = "redox")] { + if #[cfg(target_os = "fuchsia")] { + // fuchsia doesn't have /dev/null + } else if #[cfg(target_os = "redox")] { const DEV_NULL: &'static str = "null:\0"; } else { const DEV_NULL: &'static str = "/dev/null\0"; @@ -83,6 +91,11 @@ pub enum ChildStdio { Inherit, Explicit(c_int), Owned(FileDesc), + + // On Fuchsia, null stdio is the default, so we simply don't specify + // any actions at the time of spawning. + #[cfg(target_os = "fuchsia")] + Null, } pub enum Stdio { @@ -301,6 +314,7 @@ impl Stdio { Ok((ChildStdio::Owned(theirs.into_fd()), Some(ours))) } + #[cfg(not(target_os = "fuchsia"))] Stdio::Null => { let mut opts = OpenOptions::new(); opts.read(readable); @@ -311,6 +325,11 @@ impl Stdio { let fd = File::open_c(&path, &opts)?; Ok((ChildStdio::Owned(fd.into_fd()), None)) } + + #[cfg(target_os = "fuchsia")] + Stdio::Null => { + Ok((ChildStdio::Null, None)) + } } } } @@ -333,6 +352,9 @@ impl ChildStdio { ChildStdio::Inherit => None, ChildStdio::Explicit(fd) => Some(fd), ChildStdio::Owned(ref fd) => Some(fd.raw()), + + #[cfg(target_os = "fuchsia")] + ChildStdio::Null => None, } } } diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs index 7c6be9b0a6047..295ec59eb32cf 100644 --- a/src/libstd/sys/unix/process/process_fuchsia.rs +++ b/src/libstd/sys/unix/process/process_fuchsia.rs @@ -52,7 +52,7 @@ impl Command { None => ptr::null(), }; - let transfer_or_clone = |opt_fd, target_fd| if let Some(local_fd) = opt_fd { + let make_action = |local_io: &ChildStdio, target_fd| if let Some(local_fd) = local_io.fd() { fdio_spawn_action_t { action: FDIO_SPAWN_ACTION_TRANSFER_FD, local_fd, @@ -60,6 +60,10 @@ impl Command { ..Default::default() } } else { + if let ChildStdio::Null = local_io { + // acts as no-op + return Default::default(); + } fdio_spawn_action_t { action: FDIO_SPAWN_ACTION_CLONE_FD, local_fd: target_fd, @@ -69,9 +73,9 @@ impl Command { }; // Clone stdin, stdout, and stderr - let action1 = transfer_or_clone(stdio.stdin.fd(), 0); - let action2 = transfer_or_clone(stdio.stdout.fd(), 1); - let action3 = transfer_or_clone(stdio.stderr.fd(), 2); + let action1 = make_action(&stdio.stdin, 0); + let action2 = make_action(&stdio.stdout, 1); + let action3 = make_action(&stdio.stderr, 2); let actions = [action1, action2, action3]; // We don't want FileDesc::drop to be called on any stdio. fdio_spawn_etc @@ -86,7 +90,8 @@ impl Command { zx_cvt(fdio_spawn_etc( 0, FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE, - self.get_argv()[0], self.get_argv().as_ptr(), envp, 3, actions.as_ptr(), + self.get_argv()[0], self.get_argv().as_ptr(), envp, + actions.len() as size_t, actions.as_ptr(), &mut process_handle, ptr::null_mut(), ))?; diff --git a/src/libstd/sys/unix/process/zircon.rs b/src/libstd/sys/unix/process/zircon.rs index 9224bef7c4a5f..29032f5e0d200 100644 --- a/src/libstd/sys/unix/process/zircon.rs +++ b/src/libstd/sys/unix/process/zircon.rs @@ -120,7 +120,7 @@ pub struct fdio_spawn_action_t { extern { pub fn fdio_spawn_etc(job: zx_handle_t, flags: u32, path: *const c_char, argv: *const *const c_char, envp: *const *const c_char, - action_count: u64, actions: *const fdio_spawn_action_t, + action_count: size_t, actions: *const fdio_spawn_action_t, process: *mut zx_handle_t, err_msg: *mut c_char) -> zx_status_t; } From 3f6db849f7270b9126e6609a87058c1bc3aef1da Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Fri, 30 Aug 2019 14:05:39 -0500 Subject: [PATCH 349/618] actually compiles now? --- src/tools/rustbook/src/main.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index e155f3f7607f3..b2111442310ef 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -60,11 +60,14 @@ fn main() { #[cfg(feature = "linkcheck")] { err.downcast::() + .map(|broken_links| { + broken_links + .links() + .iter() + .inspect(|cause| eprintln!("\tCaused By: {}", cause)) + .any(|cause| !format!("{}", cause).contains("timed out")) + }) .unwrap_or(false) - .links() - .iter() - .inspect(|cause| eprintln!("\tCaused By: {}", cause)) - .any(|cause| !cause.contains("timed out")); } #[cfg(not(feature = "linkcheck"))] From 0b478e6d46f273041ea7a4e048083d7d4e54c8fe Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Fri, 30 Aug 2019 21:26:04 +0200 Subject: [PATCH 350/618] rustdoc use -Ccodegen-units=1 by default for test compile as the test is small we do not want split up in multiple codegen units and also as there is multiple test running at the same time this will reduce the number of concurrent threads --- src/librustdoc/test.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 31c0b85a481f5..88397aacac149 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -263,6 +263,7 @@ fn run_test( for extern_str in &options.extern_strs { compiler.arg("--extern").arg(&extern_str); } + compiler.arg("-Ccodegen-units=1"); for codegen_options_str in &options.codegen_options_strs { compiler.arg("-C").arg(&codegen_options_str); } From 533a356c49759da02fcb2457c62aed58af70579c Mon Sep 17 00:00:00 2001 From: Baoshan Pang Date: Fri, 30 Aug 2019 13:44:38 -0700 Subject: [PATCH 351/618] remove directory libstd/sys/vxworks/backtrace which is not used any more --- src/libstd/sys/vxworks/backtrace/mod.rs | 110 ------------------ .../sys/vxworks/backtrace/printing/dladdr.rs | 35 ------ .../sys/vxworks/backtrace/printing/mod.rs | 33 ------ .../vxworks/backtrace/tracing/backtrace_fn.rs | 39 ------- .../sys/vxworks/backtrace/tracing/gcc_s.rs | 99 ---------------- .../sys/vxworks/backtrace/tracing/mod.rs | 8 -- 6 files changed, 324 deletions(-) delete mode 100644 src/libstd/sys/vxworks/backtrace/mod.rs delete mode 100644 src/libstd/sys/vxworks/backtrace/printing/dladdr.rs delete mode 100644 src/libstd/sys/vxworks/backtrace/printing/mod.rs delete mode 100644 src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs delete mode 100644 src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs delete mode 100644 src/libstd/sys/vxworks/backtrace/tracing/mod.rs diff --git a/src/libstd/sys/vxworks/backtrace/mod.rs b/src/libstd/sys/vxworks/backtrace/mod.rs deleted file mode 100644 index 0887e5a4df937..0000000000000 --- a/src/libstd/sys/vxworks/backtrace/mod.rs +++ /dev/null @@ -1,110 +0,0 @@ -/// Backtrace support built on libgcc with some extra OS-specific support -/// -/// Some methods of getting a backtrace: -/// -/// * The backtrace() functions on unix. It turns out this doesn't work very -/// well for green threads on macOS, and the address to symbol portion of it -/// suffers problems that are described below. -/// -/// * Using libunwind. This is more difficult than it sounds because libunwind -/// isn't installed everywhere by default. It's also a bit of a hefty library, -/// so possibly not the best option. When testing, libunwind was excellent at -/// getting both accurate backtraces and accurate symbols across platforms. -/// This route was not chosen in favor of the next option, however. -/// -/// * We're already using libgcc_s for exceptions in rust (triggering thread -/// unwinding and running destructors on the stack), and it turns out that it -/// conveniently comes with a function that also gives us a backtrace. All of -/// these functions look like _Unwind_*, but it's not quite the full -/// repertoire of the libunwind API. Due to it already being in use, this was -/// the chosen route of getting a backtrace. -/// -/// After choosing libgcc_s for backtraces, the sad part is that it will only -/// give us a stack trace of instruction pointers. Thankfully these instruction -/// pointers are accurate (they work for green and native threads), but it's -/// then up to us again to figure out how to translate these addresses to -/// symbols. As with before, we have a few options. Before, that, a little bit -/// of an interlude about symbols. This is my very limited knowledge about -/// symbol tables, and this information is likely slightly wrong, but the -/// general idea should be correct. -/// -/// When talking about symbols, it's helpful to know a few things about where -/// symbols are located. Some symbols are located in the dynamic symbol table -/// of the executable which in theory means that they're available for dynamic -/// linking and lookup. Other symbols end up only in the local symbol table of -/// the file. This loosely corresponds to pub and priv functions in Rust. -/// -/// Armed with this knowledge, we know that our solution for address to symbol -/// translation will need to consult both the local and dynamic symbol tables. -/// With that in mind, here's our options of translating an address to -/// a symbol. -/// -/// * Use dladdr(). The original backtrace()-based idea actually uses dladdr() -/// behind the scenes to translate, and this is why backtrace() was not used. -/// Conveniently, this method works fantastically on macOS. It appears dladdr() -/// uses magic to consult the local symbol table, or we're putting everything -/// in the dynamic symbol table anyway. Regardless, for macOS, this is the -/// method used for translation. It's provided by the system and easy to do.o -/// -/// Sadly, all other systems have a dladdr() implementation that does not -/// consult the local symbol table. This means that most functions are blank -/// because they don't have symbols. This means that we need another solution. -/// -/// * Use unw_get_proc_name(). This is part of the libunwind api (not the -/// libgcc_s version of the libunwind api), but involves taking a dependency -/// to libunwind. We may pursue this route in the future if we bundle -/// libunwind, but libunwind was unwieldy enough that it was not chosen at -/// this time to provide this functionality. -/// -/// * Shell out to a utility like `readelf`. Crazy though it may sound, it's a -/// semi-reasonable solution. The stdlib already knows how to spawn processes, -/// so in theory it could invoke readelf, parse the output, and consult the -/// local/dynamic symbol tables from there. This ended up not getting chosen -/// due to the craziness of the idea plus the advent of the next option. -/// -/// * Use `libbacktrace`. It turns out that this is a small library bundled in -/// the gcc repository which provides backtrace and symbol translation -/// functionality. All we really need from it is the backtrace functionality, -/// and we only really need this on everything that's not macOS, so this is the -/// chosen route for now. -/// -/// In summary, the current situation uses libgcc_s to get a trace of stack -/// pointers, and we use dladdr() or libbacktrace to translate these addresses -/// to symbols. This is a bit of a hokey implementation as-is, but it works for -/// all unix platforms we support right now, so it at least gets the job done. - -pub use self::tracing::unwind_backtrace; -pub use self::printing::{foreach_symbol_fileline, resolve_symname}; - -// tracing impls: -mod tracing; -// symbol resolvers: -mod printing; - -#[cfg(not(target_os = "emscripten"))] -pub mod gnu { - use crate::io; - use crate::fs; - - use libc::c_char; - - #[cfg(not(any(target_os = "macos", target_os = "ios")))] - pub fn get_executable_filename() -> io::Result<(Vec, fs::File)> { - Err(io::Error::new(io::ErrorKind::Other, "Not implemented")) - } - - #[cfg(any(target_os = "macos", target_os = "ios"))] - pub fn get_executable_filename() -> io::Result<(Vec, fs::File)> { - use crate::env; - use crate::os::unix::ffi::OsStrExt; - - let filename = env::current_exe()?; - let file = fs::File::open(&filename)?; - let mut filename_cstr: Vec<_> = filename.as_os_str().as_bytes().iter() - .map(|&x| x as c_char).collect(); - filename_cstr.push(0); // Null terminate - Ok((filename_cstr, file)) - } -} - -pub struct BacktraceContext; diff --git a/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs b/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs deleted file mode 100644 index 202164dd3c4d7..0000000000000 --- a/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs +++ /dev/null @@ -1,35 +0,0 @@ -use crate::io; -use crate::intrinsics; -use crate::ffi::CStr; -use crate::sys::backtrace::BacktraceContext; -use crate::sys_common::backtrace::Frame; - -pub fn resolve_symname(frame: Frame, - callback: F, - _: &BacktraceContext) -> io::Result<()> - where F: FnOnce(Option<&str>) -> io::Result<()> -{ - unsafe { - let mut info: Dl_info = intrinsics::init(); - let symname = if dladdr(frame.exact_position as *mut _, &mut info) == 0 || - info.dli_sname.is_null() { - None - } else { - CStr::from_ptr(info.dli_sname).to_str().ok() - }; - callback(symname) - } -} - -#[repr(C)] -struct Dl_info { - dli_fname: *const libc::c_char, - dli_fbase: *mut libc::c_void, - dli_sname: *const libc::c_char, - dli_saddr: *mut libc::c_void, -} - -extern { - #[ link_name = "_rtld_dladdr" ] - fn dladdr(addr: *const libc::c_void, info: *mut Dl_info) -> libc::c_int; -} diff --git a/src/libstd/sys/vxworks/backtrace/printing/mod.rs b/src/libstd/sys/vxworks/backtrace/printing/mod.rs deleted file mode 100644 index d090caede437a..0000000000000 --- a/src/libstd/sys/vxworks/backtrace/printing/mod.rs +++ /dev/null @@ -1,33 +0,0 @@ -mod dladdr; - -use crate::sys::backtrace::BacktraceContext; -use crate::sys_common::backtrace::Frame; -use crate::io; - -#[cfg(target_os = "emscripten")] -pub use self::dladdr::resolve_symname; - -#[cfg(target_os = "emscripten")] -pub fn foreach_symbol_fileline(_: Frame, _: F, _: &BacktraceContext) -> io::Result -where - F: FnMut(&[u8], u32) -> io::Result<()> -{ - Ok(false) -} - -#[cfg(not(target_os = "emscripten"))] -pub use crate::sys_common::gnu::libbacktrace::foreach_symbol_fileline; - -#[cfg(not(target_os = "emscripten"))] -pub fn resolve_symname(frame: Frame, callback: F, bc: &BacktraceContext) -> io::Result<()> -where - F: FnOnce(Option<&str>) -> io::Result<()> -{ - crate::sys_common::gnu::libbacktrace::resolve_symname(frame, |symname| { - if symname.is_some() { - callback(symname) - } else { - dladdr::resolve_symname(frame, callback, bc) - } - }, bc) -} diff --git a/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs b/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs deleted file mode 100644 index a628d107ad6fb..0000000000000 --- a/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs +++ /dev/null @@ -1,39 +0,0 @@ -/// As always - iOS on arm uses SjLj exceptions and -/// _Unwind_Backtrace is even not available there. Still, -/// backtraces could be extracted using a backtrace function, -/// which thanks god is public -/// -/// As mentioned in a huge comment block in `super::super`, backtrace -/// doesn't play well with green threads, so while it is extremely nice and -/// simple to use it should be used only on iOS devices as the only viable -/// option. - -use crate::io; -use crate::ptr; -use crate::sys::backtrace::BacktraceContext; -use crate::sys_common::backtrace::Frame; - -#[inline(never)] // if we know this is a function call, we can skip it when - // tracing -pub fn unwind_backtrace(frames: &mut [Frame]) - -> io::Result<(usize, BacktraceContext)> -{ - const FRAME_LEN: usize = 100; - assert!(FRAME_LEN >= frames.len()); - let mut raw_frames = [ptr::null_mut(); FRAME_LEN]; - let nb_frames = unsafe { - backtrace(raw_frames.as_mut_ptr(), raw_frames.len() as libc::c_int) - } as usize; - for (from, to) in raw_frames.iter().zip(frames.iter_mut()).take(nb_frames) { - *to = Frame { - exact_position: *from as *mut u8, - symbol_addr: *from as *mut u8, - inline_context: 0, - }; - } - Ok((nb_frames as usize, BacktraceContext)) -} - -extern { - fn backtrace(buf: *mut *mut libc::c_void, sz: libc::c_int) -> libc::c_int; -} diff --git a/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs b/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs deleted file mode 100644 index e6379132bafbe..0000000000000 --- a/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs +++ /dev/null @@ -1,99 +0,0 @@ -use crate::error::Error; -use crate::fmt; -use crate::io; -use crate::sys::backtrace::BacktraceContext; -use crate::sys_common::backtrace::Frame; - -use unwind as uw; - -struct Context<'a> { - idx: usize, - frames: &'a mut [Frame], -} - -#[derive(Debug)] -struct UnwindError(uw::_Unwind_Reason_Code); - -impl Error for UnwindError { - fn description(&self) -> &'static str { - "unexpected return value while unwinding" - } -} - -impl fmt::Display for UnwindError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}: {:?}", self.description(), self.0) - } -} - -#[inline(never)] // if we know this is a function call, we can skip it when - // tracing -pub fn unwind_backtrace(frames: &mut [Frame]) - -> io::Result<(usize, BacktraceContext)> -{ - let mut cx = Context { - idx: 0, - frames, - }; - let result_unwind = unsafe { - uw::_Unwind_Backtrace(trace_fn, - &mut cx as *mut Context<'_> - as *mut libc::c_void) - }; - // See libunwind:src/unwind/Backtrace.c for the return values. - // No, there is no doc. - match result_unwind { - // These return codes seem to be benign and need to be ignored for backtraces - // to show up properly on all tested platforms. - uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => { - Ok((cx.idx, BacktraceContext)) - } - _ => { - Err(io::Error::new(io::ErrorKind::Other, - UnwindError(result_unwind))) - } - } -} - -extern fn trace_fn(ctx: *mut uw::_Unwind_Context, - arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code { - let cx = unsafe { &mut *(arg as *mut Context<'_>) }; - if cx.idx >= cx.frames.len() { - return uw::_URC_NORMAL_STOP; - } - - let mut ip_before_insn = 0; - let mut ip = unsafe { - uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void - }; - if !ip.is_null() && ip_before_insn == 0 { - // this is a non-signaling frame, so `ip` refers to the address - // after the calling instruction. account for that. - ip = (ip as usize - 1) as *mut _; - } - - // dladdr() on osx gets whiny when we use FindEnclosingFunction, and - // it appears to work fine without it, so we only use - // FindEnclosingFunction on non-osx platforms. In doing so, we get a - // slightly more accurate stack trace in the process. - // - // This is often because panic involves the last instruction of a - // function being "call std::rt::begin_unwind", with no ret - // instructions after it. This means that the return instruction - // pointer points *outside* of the calling function, and by - // unwinding it we go back to the original function. - let symaddr = if cfg!(target_os = "macos") || cfg!(target_os = "ios") { - ip - } else { - unsafe { uw::_Unwind_FindEnclosingFunction(ip) } - }; - - cx.frames[cx.idx] = Frame { - symbol_addr: symaddr as *mut u8, - exact_position: ip as *mut u8, - inline_context: 0, - }; - cx.idx += 1; - - uw::_URC_NO_REASON -} diff --git a/src/libstd/sys/vxworks/backtrace/tracing/mod.rs b/src/libstd/sys/vxworks/backtrace/tracing/mod.rs deleted file mode 100644 index 11863e6454525..0000000000000 --- a/src/libstd/sys/vxworks/backtrace/tracing/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub use self::imp::*; - -#[cfg(not(all(target_os = "ios", target_arch = "arm")))] -#[path = "gcc_s.rs"] -mod imp; -#[cfg(all(target_os = "ios", target_arch = "arm"))] -#[path = "backtrace_fn.rs"] -mod imp; From 96ac02b8b3aeebc463d434c57b4a2ada9a3003e6 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 29 Aug 2019 13:30:53 -0700 Subject: [PATCH 352/618] Use new `Place::is_indirect` API where possible --- src/librustc_mir/borrow_check/path_utils.rs | 23 ++++++------------- .../dataflow/impls/borrowed_locals.rs | 17 ++++---------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs index 43a012e1494f8..bac08090817d9 100644 --- a/src/librustc_mir/borrow_check/path_utils.rs +++ b/src/librustc_mir/borrow_check/path_utils.rs @@ -3,7 +3,7 @@ use crate::borrow_check::places_conflict; use crate::borrow_check::AccessDepth; use crate::dataflow::indexes::BorrowIndex; use rustc::mir::{BasicBlock, Location, Body, Place, PlaceBase}; -use rustc::mir::{ProjectionElem, BorrowKind}; +use rustc::mir::BorrowKind; use rustc::ty::{self, TyCtxt}; use rustc_data_structures::graph::dominators::Dominators; @@ -133,20 +133,11 @@ pub(super) fn is_active<'tcx>( /// Determines if a given borrow is borrowing local data /// This is called for all Yield statements on movable generators pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool { - place.iterate(|place_base, place_projection| { - match place_base { - PlaceBase::Static(..) => return false, - PlaceBase::Local(..) => {}, - } - - for proj in place_projection { - // Reborrow of already borrowed data is ignored - // Any errors will be caught on the initial borrow - if proj.elem == ProjectionElem::Deref { - return false; - } - } + match place.base { + PlaceBase::Static(_) => false, - true - }) + // Reborrow of already borrowed data is ignored + // Any errors will be caught on the initial borrow + PlaceBase::Local(_) => !place.is_indirect(), + } } diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index d94ebdbae24ae..1c43a553cc3c9 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -93,19 +93,10 @@ struct BorrowedLocalsVisitor<'gk> { } fn find_local(place: &Place<'_>) -> Option { - place.iterate(|place_base, place_projection| { - for proj in place_projection { - if proj.elem == ProjectionElem::Deref { - return None; - } - } - - if let PlaceBase::Local(local) = place_base { - Some(*local) - } else { - None - } - }) + match place.base { + PlaceBase::Local(local) if !place.is_indirect() => Some(local), + _ => None, + } } impl<'tcx> Visitor<'tcx> for BorrowedLocalsVisitor<'_> { From 960ecdce7c5b7638cdb2585088caa666928c2d37 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 29 Aug 2019 05:50:39 +0200 Subject: [PATCH 353/618] improper_ctypes: guard against accidental change to Unique. --- src/test/ui/lint/lint-ctypes-enum.rs | 2 ++ src/test/ui/lint/lint-ctypes-enum.stderr | 34 +++++++++++++++--------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/test/ui/lint/lint-ctypes-enum.rs b/src/test/ui/lint/lint-ctypes-enum.rs index 45eeffff7a6ac..e1f4b0b34ebaa 100644 --- a/src/test/ui/lint/lint-ctypes-enum.rs +++ b/src/test/ui/lint/lint-ctypes-enum.rs @@ -1,4 +1,5 @@ #![feature(transparent_enums, transparent_unions)] +#![feature(ptr_internals)] #![deny(improper_ctypes)] #![allow(dead_code)] @@ -44,6 +45,7 @@ extern { fn option_ref(x: Option<&'static u8>); fn option_fn(x: Option); fn nonnull(x: Option>); + fn unique(x: Option>); //~ ERROR enum has no representation hint fn nonzero_u8(x: Option); fn nonzero_u16(x: Option); fn nonzero_u32(x: Option); diff --git a/src/test/ui/lint/lint-ctypes-enum.stderr b/src/test/ui/lint/lint-ctypes-enum.stderr index 2a60cd12d9936..20e438606642c 100644 --- a/src/test/ui/lint/lint-ctypes-enum.stderr +++ b/src/test/ui/lint/lint-ctypes-enum.stderr @@ -1,61 +1,69 @@ error: `extern` block uses type `U` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:38:13 + --> $DIR/lint-ctypes-enum.rs:39:13 | LL | fn uf(x: U); | ^ | note: lint level defined here - --> $DIR/lint-ctypes-enum.rs:2:9 + --> $DIR/lint-ctypes-enum.rs:3:9 | LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum note: type defined here - --> $DIR/lint-ctypes-enum.rs:8:1 + --> $DIR/lint-ctypes-enum.rs:9:1 | LL | enum U { A } | ^^^^^^^^^^^^ error: `extern` block uses type `B` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:39:13 + --> $DIR/lint-ctypes-enum.rs:40:13 | LL | fn bf(x: B); | ^ | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum note: type defined here - --> $DIR/lint-ctypes-enum.rs:9:1 + --> $DIR/lint-ctypes-enum.rs:10:1 | LL | enum B { C, D } | ^^^^^^^^^^^^^^^ error: `extern` block uses type `T` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:40:13 + --> $DIR/lint-ctypes-enum.rs:41:13 | LL | fn tf(x: T); | ^ | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum note: type defined here - --> $DIR/lint-ctypes-enum.rs:10:1 + --> $DIR/lint-ctypes-enum.rs:11:1 | LL | enum T { E, F, G } | ^^^^^^^^^^^^^^^^^^ +error: `extern` block uses type `std::option::Option>` which is not FFI-safe: enum has no representation hint + --> $DIR/lint-ctypes-enum.rs:48:17 + | +LL | fn unique(x: Option>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI - --> $DIR/lint-ctypes-enum.rs:51:23 + --> $DIR/lint-ctypes-enum.rs:53:23 | LL | fn nonzero_u128(x: Option); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI - --> $DIR/lint-ctypes-enum.rs:58:23 + --> $DIR/lint-ctypes-enum.rs:60:23 | LL | fn nonzero_i128(x: Option); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `std::option::Option>` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:63:28 + --> $DIR/lint-ctypes-enum.rs:65:28 | LL | fn transparent_union(x: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -63,7 +71,7 @@ LL | fn transparent_union(x: Option>); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum error: `extern` block uses type `std::option::Option>` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:65:20 + --> $DIR/lint-ctypes-enum.rs:67:20 | LL | fn repr_rust(x: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,12 +79,12 @@ LL | fn repr_rust(x: Option>); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:66:20 + --> $DIR/lint-ctypes-enum.rs:68:20 | LL | fn no_result(x: Result<(), num::NonZeroI32>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors From 78f62c619006500485e96056f733d74be02cab8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 30 Aug 2019 17:45:34 -0700 Subject: [PATCH 354/618] Account for rounding errors when deciding the diagnostic boundaries --- src/librustc_errors/emitter.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 77d373e7a8ca8..fddb6c5c259c9 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -146,12 +146,12 @@ impl Margin { } else if self.label_right - self.span_left <= self.column_width { // Attempt to fit the code window considering only the spans and labels. let padding_left = (self.column_width - (self.label_right - self.span_left)) / 2; - self.computed_left = self.span_left - padding_left; + self.computed_left = max(self.span_left, padding_left) - padding_left; self.computed_right = self.computed_left + self.column_width; } else if self.span_right - self.span_left <= self.column_width { // Attempt to fit the code window considering the spans and labels plus padding. let padding_left = (self.column_width - (self.span_right - self.span_left)) / 5 * 2; - self.computed_left = self.span_left - padding_left; + self.computed_left = max(self.span_left, padding_left) - padding_left; self.computed_right = self.computed_left + self.column_width; } else { // Mostly give up but still don't show the full line. self.computed_left = self.span_left; From 3cc8087c4849fcbb8eeae208ace59bdf9b156ca8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 29 Aug 2019 08:52:13 +0200 Subject: [PATCH 355/618] qualify_consts: extractt 'determine_mode'. --- src/librustc_mir/transform/qualify_consts.rs | 49 ++++++++++---------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index a77421ce15008..959d21ecfadeb 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -30,6 +30,7 @@ use std::fmt; use std::ops::{Deref, Index, IndexMut}; use std::usize; +use rustc::hir::HirId; use crate::transform::{MirPass, MirSource}; use super::promote_consts::{self, Candidate, TempState}; @@ -1596,27 +1597,12 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { } let def_id = src.def_id(); - let id = tcx.hir().as_local_hir_id(def_id).unwrap(); - let mut const_promoted_temps = None; - let mode = match tcx.hir().body_owner_kind(id) { - hir::BodyOwnerKind::Closure => Mode::NonConstFn, - hir::BodyOwnerKind::Fn => { - if tcx.is_const_fn(def_id) { - Mode::ConstFn - } else { - Mode::NonConstFn - } - } - hir::BodyOwnerKind::Const => { - const_promoted_temps = Some(tcx.mir_const_qualif(def_id).1); - Mode::Const - } - hir::BodyOwnerKind::Static(hir::MutImmutable) => Mode::Static, - hir::BodyOwnerKind::Static(hir::MutMutable) => Mode::StaticMut, - }; + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); + + let mode = determine_mode(tcx, hir_id, def_id); debug!("run_pass: mode={:?}", mode); - if mode == Mode::NonConstFn || mode == Mode::ConstFn { + if let Mode::NonConstFn | Mode::ConstFn = mode { // This is ugly because Checker holds onto mir, // which can't be mutated until its scope ends. let (temps, candidates) = { @@ -1664,6 +1650,11 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { promote_consts::promote_candidates(def_id, body, tcx, temps, candidates) ); } else { + let const_promoted_temps = match mode { + Mode::Const => Some(tcx.mir_const_qualif(def_id).1), + _ => None, + }; + if !body.control_flow_destroyed.is_empty() { let mut locals = body.vars_iter(); if let Some(local) = locals.next() { @@ -1695,11 +1686,10 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { error.emit(); } } - let promoted_temps = if mode == Mode::Const { + let promoted_temps = match mode { // Already computed by `mir_const_qualif`. - const_promoted_temps.unwrap() - } else { - Checker::new(tcx, def_id, body, mode).check_const().1 + Mode::Const => const_promoted_temps.unwrap(), + _ => Checker::new(tcx, def_id, body, mode).check_const().1, }; // In `const` and `static` everything without `StorageDead` @@ -1747,7 +1737,7 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { let ty = body.return_ty(); tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(); - let cause = traits::ObligationCause::new(body.span, id, traits::SharedStatic); + let cause = traits::ObligationCause::new(body.span, hir_id, traits::SharedStatic); let mut fulfillment_cx = traits::FulfillmentContext::new(); fulfillment_cx.register_bound(&infcx, param_env, @@ -1765,6 +1755,17 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { } } +fn determine_mode(tcx: TyCtxt<'_>, hir_id: HirId, def_id: DefId) -> Mode { + match tcx.hir().body_owner_kind(hir_id) { + hir::BodyOwnerKind::Closure => Mode::NonConstFn, + hir::BodyOwnerKind::Fn if tcx.is_const_fn(def_id) => Mode::ConstFn, + hir::BodyOwnerKind::Fn => Mode::NonConstFn, + hir::BodyOwnerKind::Const => Mode::Const, + hir::BodyOwnerKind::Static(hir::MutImmutable) => Mode::Static, + hir::BodyOwnerKind::Static(hir::MutMutable) => Mode::StaticMut, + } +} + fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { let attrs = tcx.get_attrs(def_id); let attr = attrs.iter().find(|a| a.check_name(sym::rustc_args_required_const))?; From 8f184b369d6332195ef61f0395cf32bd787e4368 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 29 Aug 2019 08:58:52 +0200 Subject: [PATCH 356/618] qualify_consts: misc cleanup. --- src/librustc_mir/transform/qualify_consts.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 959d21ecfadeb..fcbb3433a62d9 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1714,12 +1714,8 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { }, target, .. - } => { - if promoted_temps.contains(index) { - terminator.kind = TerminatorKind::Goto { - target, - }; - } + } if promoted_temps.contains(index) => { + terminator.kind = TerminatorKind::Goto { target }; } _ => {} } @@ -1727,7 +1723,7 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { } // Statics must be Sync. - if mode == Mode::Static { + if let Mode::Static = mode { // `#[thread_local]` statics don't have to be `Sync`. for attr in &tcx.get_attrs(def_id)[..] { if attr.check_name(sym::thread_local) { From b6360fbc4c6d3898d51dfcbe9b042fef515133d1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 29 Aug 2019 09:10:26 +0200 Subject: [PATCH 357/618] qualify_consts: extract check_short_circuiting_in_const_local. --- src/librustc_mir/transform/qualify_consts.rs | 66 +++++++++++--------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index fcbb3433a62d9..0a9e2a5974300 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1655,37 +1655,8 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { _ => None, }; - if !body.control_flow_destroyed.is_empty() { - let mut locals = body.vars_iter(); - if let Some(local) = locals.next() { - let span = body.local_decls[local].source_info.span; - let mut error = tcx.sess.struct_span_err( - span, - &format!( - "new features like let bindings are not permitted in {}s \ - which also use short circuiting operators", - mode, - ), - ); - for (span, kind) in body.control_flow_destroyed.iter() { - error.span_note( - *span, - &format!("use of {} here does not actually short circuit due to \ - the const evaluator presently not being able to do control flow. \ - See https://github.com/rust-lang/rust/issues/49146 for more \ - information.", kind), - ); - } - for local in locals { - let span = body.local_decls[local].source_info.span; - error.span_note( - span, - "more locals defined here", - ); - } - error.emit(); - } - } + check_short_circuiting_in_const_local(tcx, body, mode); + let promoted_temps = match mode { // Already computed by `mir_const_qualif`. Mode::Const => const_promoted_temps.unwrap(), @@ -1762,6 +1733,39 @@ fn determine_mode(tcx: TyCtxt<'_>, hir_id: HirId, def_id: DefId) -> Mode { } } +fn check_short_circuiting_in_const_local(tcx: TyCtxt<'_>, body: &mut Body<'tcx>, mode: Mode) { + if body.control_flow_destroyed.is_empty() { + return; + } + + let mut locals = body.vars_iter(); + if let Some(local) = locals.next() { + let span = body.local_decls[local].source_info.span; + let mut error = tcx.sess.struct_span_err( + span, + &format!( + "new features like let bindings are not permitted in {}s \ + which also use short circuiting operators", + mode, + ), + ); + for (span, kind) in body.control_flow_destroyed.iter() { + error.span_note( + *span, + &format!("use of {} here does not actually short circuit due to \ + the const evaluator presently not being able to do control flow. \ + See https://github.com/rust-lang/rust/issues/49146 for more \ + information.", kind), + ); + } + for local in locals { + let span = body.local_decls[local].source_info.span; + error.span_note(span, "more locals defined here"); + } + error.emit(); + } +} + fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { let attrs = tcx.get_attrs(def_id); let attr = attrs.iter().find(|a| a.check_name(sym::rustc_args_required_const))?; From c1d440070e088c6b239bcf5f9f22dfc6d5b2b639 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 29 Aug 2019 09:15:59 +0200 Subject: [PATCH 358/618] qualify_consts: fuse prompted_temps. --- src/librustc_mir/transform/qualify_consts.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 0a9e2a5974300..b052d1e9bb468 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1650,16 +1650,10 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { promote_consts::promote_candidates(def_id, body, tcx, temps, candidates) ); } else { - let const_promoted_temps = match mode { - Mode::Const => Some(tcx.mir_const_qualif(def_id).1), - _ => None, - }; - check_short_circuiting_in_const_local(tcx, body, mode); let promoted_temps = match mode { - // Already computed by `mir_const_qualif`. - Mode::Const => const_promoted_temps.unwrap(), + Mode::Const => tcx.mir_const_qualif(def_id).1, _ => Checker::new(tcx, def_id, body, mode).check_const().1, }; From 7bfa2be4efa2d4649e8db7548f1980156d58017e Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 30 Aug 2019 18:21:57 -0700 Subject: [PATCH 359/618] fuchsia: Don't fail to spawn if no stdin exists --- .../sys/unix/process/process_fuchsia.rs | 57 ++++++++++++------- src/libstd/sys/unix/process/zircon.rs | 6 +- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs index 295ec59eb32cf..2b3795292f42a 100644 --- a/src/libstd/sys/unix/process/process_fuchsia.rs +++ b/src/libstd/sys/unix/process/process_fuchsia.rs @@ -52,30 +52,45 @@ impl Command { None => ptr::null(), }; - let make_action = |local_io: &ChildStdio, target_fd| if let Some(local_fd) = local_io.fd() { - fdio_spawn_action_t { - action: FDIO_SPAWN_ACTION_TRANSFER_FD, - local_fd, - target_fd, - ..Default::default() - } - } else { - if let ChildStdio::Null = local_io { - // acts as no-op - return Default::default(); - } - fdio_spawn_action_t { - action: FDIO_SPAWN_ACTION_CLONE_FD, - local_fd: target_fd, - target_fd, - ..Default::default() + let make_action = |local_io: &ChildStdio, target_fd| -> io::Result { + if let Some(local_fd) = local_io.fd() { + Ok(fdio_spawn_action_t { + action: FDIO_SPAWN_ACTION_TRANSFER_FD, + local_fd, + target_fd, + ..Default::default() + }) + } else { + if let ChildStdio::Null = local_io { + // acts as no-op + return Ok(Default::default()); + } + + let mut handle = ZX_HANDLE_INVALID; + let status = fdio_fd_clone(target_fd, &mut handle); + if status == ERR_INVALID_ARGS || status == ERR_NOT_SUPPORTED { + // This descriptor is closed; skip it rather than generating an + // error. + return Ok(Default::default()); + } + zx_cvt(status)?; + + let mut cloned_fd = 0; + zx_cvt(fdio_fd_create(handle, &mut cloned_fd))?; + + Ok(fdio_spawn_action_t { + action: FDIO_SPAWN_ACTION_TRANSFER_FD, + local_fd: cloned_fd as i32, + target_fd, + ..Default::default() + }) } }; // Clone stdin, stdout, and stderr - let action1 = make_action(&stdio.stdin, 0); - let action2 = make_action(&stdio.stdout, 1); - let action3 = make_action(&stdio.stderr, 2); + let action1 = make_action(&stdio.stdin, 0)?; + let action2 = make_action(&stdio.stdout, 1)?; + let action3 = make_action(&stdio.stderr, 2)?; let actions = [action1, action2, action3]; // We don't want FileDesc::drop to be called on any stdio. fdio_spawn_etc @@ -88,7 +103,7 @@ impl Command { let mut process_handle: zx_handle_t = 0; zx_cvt(fdio_spawn_etc( - 0, + ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE, self.get_argv()[0], self.get_argv().as_ptr(), envp, actions.len() as size_t, actions.as_ptr(), diff --git a/src/libstd/sys/unix/process/zircon.rs b/src/libstd/sys/unix/process/zircon.rs index 29032f5e0d200..1ba48de3c0785 100644 --- a/src/libstd/sys/unix/process/zircon.rs +++ b/src/libstd/sys/unix/process/zircon.rs @@ -2,8 +2,9 @@ use crate::convert::TryInto; use crate::io; -use crate::os::raw::c_char; use crate::i64; +use crate::mem::MaybeUninit; +use crate::os::raw::c_char; use libc::{c_int, c_void, size_t}; @@ -122,6 +123,9 @@ extern { argv: *const *const c_char, envp: *const *const c_char, action_count: size_t, actions: *const fdio_spawn_action_t, process: *mut zx_handle_t, err_msg: *mut c_char) -> zx_status_t; + + pub fn fdio_fd_clone(fd: c_int, out_handle: *mut zx_handle_t) -> zx_status_t; + pub fn fdio_fd_create(handle: zx_handle_t, fd: *mut c_int) -> zx_status_t; } // fdio_spawn_etc flags From 5f91ad0e3300c36033bf409ceefb00480fecbed3 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 30 Aug 2019 18:52:19 -0700 Subject: [PATCH 360/618] fuchsia: Fix default environment behavior when spawning --- src/libstd/sys/unix/process/process_fuchsia.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs index 2b3795292f42a..fff9fc6b3bbc8 100644 --- a/src/libstd/sys/unix/process/process_fuchsia.rs +++ b/src/libstd/sys/unix/process/process_fuchsia.rs @@ -48,8 +48,10 @@ impl Command { use crate::sys::process::zircon::*; let envp = match maybe_envp { - Some(envp) => envp.as_ptr(), + // None means to clone the current environment, which is done in the + // flags below. None => ptr::null(), + Some(envp) => envp.as_ptr(), }; let make_action = |local_io: &ChildStdio, target_fd| -> io::Result { @@ -104,7 +106,8 @@ impl Command { let mut process_handle: zx_handle_t = 0; zx_cvt(fdio_spawn_etc( ZX_HANDLE_INVALID, - FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE, + FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE + | FDIO_SPAWN_CLONE_ENVIRON, // this is ignored when envp is non-null self.get_argv()[0], self.get_argv().as_ptr(), envp, actions.len() as size_t, actions.as_ptr(), &mut process_handle, From bf90154410b372ad0c8731a6d470acd9bf820f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 30 Aug 2019 19:47:21 -0700 Subject: [PATCH 361/618] Tweak terminal width trimming Properly account for left margin when setting terminal width through CLI flag and don't trim code by default if we can't get the terminal's dimensions. --- src/librustc_errors/emitter.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index fddb6c5c259c9..02473cc86bdff 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -1304,11 +1304,11 @@ impl EmitterWriter { }; let column_width = if let Some(width) = self.terminal_width { - width + max(width, code_offset) - code_offset } else if self.ui_testing { 140 } else { - term_size::dimensions().map(|(w, _)| w - code_offset).unwrap_or(140) + term_size::dimensions().map(|(w, _)| w - code_offset).unwrap_or(std::usize::MAX) }; let margin = Margin::new( From 3c4d157c8419d73574587a22a8095ad32d860af5 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Fri, 30 Aug 2019 20:35:27 -0700 Subject: [PATCH 362/618] Fix unlock ordering in SGX synchronization primitives --- src/libstd/sys/sgx/condvar.rs | 3 +-- src/libstd/sys/sgx/mutex.rs | 4 ++-- src/libstd/sys/sgx/rwlock.rs | 34 +++++++++++++++++++-------------- src/libstd/sys/sgx/waitqueue.rs | 11 +++++++++-- 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/libstd/sys/sgx/condvar.rs b/src/libstd/sys/sgx/condvar.rs index 000bb19f2692a..cc1c04a83e752 100644 --- a/src/libstd/sys/sgx/condvar.rs +++ b/src/libstd/sys/sgx/condvar.rs @@ -27,8 +27,7 @@ impl Condvar { pub unsafe fn wait(&self, mutex: &Mutex) { let guard = self.inner.lock(); - mutex.unlock(); - WaitQueue::wait(guard); + WaitQueue::wait(guard, || mutex.unlock()); mutex.lock() } diff --git a/src/libstd/sys/sgx/mutex.rs b/src/libstd/sys/sgx/mutex.rs index f325fb1dd582f..662da8b3f6685 100644 --- a/src/libstd/sys/sgx/mutex.rs +++ b/src/libstd/sys/sgx/mutex.rs @@ -22,7 +22,7 @@ impl Mutex { let mut guard = self.inner.lock(); if *guard.lock_var() { // Another thread has the lock, wait - WaitQueue::wait(guard) + WaitQueue::wait(guard, ||{}) // Another thread has passed the lock to us } else { // We are just now obtaining the lock @@ -83,7 +83,7 @@ impl ReentrantMutex { match guard.lock_var().owner { Some(tcs) if tcs != thread::current() => { // Another thread has the lock, wait - WaitQueue::wait(guard); + WaitQueue::wait(guard, ||{}); // Another thread has passed the lock to us }, _ => { diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs index 30c47e44eef8e..e2f94b1d928e1 100644 --- a/src/libstd/sys/sgx/rwlock.rs +++ b/src/libstd/sys/sgx/rwlock.rs @@ -31,7 +31,7 @@ impl RWLock { if *wguard.lock_var() || !wguard.queue_empty() { // Another thread has or is waiting for the write lock, wait drop(wguard); - WaitQueue::wait(rguard); + WaitQueue::wait(rguard, ||{}); // Another thread has passed the lock to us } else { // No waiting writers, acquire the read lock @@ -62,7 +62,7 @@ impl RWLock { if *wguard.lock_var() || rguard.lock_var().is_some() { // Another thread has the lock, wait drop(rguard); - WaitQueue::wait(wguard); + WaitQueue::wait(wguard, ||{}); // Another thread has passed the lock to us } else { // We are just now obtaining the lock @@ -97,6 +97,7 @@ impl RWLock { if let Ok(mut wguard) = WaitQueue::notify_one(wguard) { // A writer was waiting, pass the lock *wguard.lock_var_mut() = true; + wguard.drop_after(rguard); } else { // No writers were waiting, the lock is released rtassert!(rguard.queue_empty()); @@ -117,21 +118,26 @@ impl RWLock { rguard: SpinMutexGuard<'_, WaitVariable>>, wguard: SpinMutexGuard<'_, WaitVariable>, ) { - if let Err(mut wguard) = WaitQueue::notify_one(wguard) { - // No writers waiting, release the write lock - *wguard.lock_var_mut() = false; - if let Ok(mut rguard) = WaitQueue::notify_all(rguard) { - // One or more readers were waiting, pass the lock to them - if let NotifiedTcs::All { count } = rguard.notified_tcs() { - *rguard.lock_var_mut() = Some(count) + match WaitQueue::notify_one(wguard) { + Err(mut wguard) => { + // No writers waiting, release the write lock + *wguard.lock_var_mut() = false; + if let Ok(mut rguard) = WaitQueue::notify_all(rguard) { + // One or more readers were waiting, pass the lock to them + if let NotifiedTcs::All { count } = rguard.notified_tcs() { + *rguard.lock_var_mut() = Some(count) + } else { + unreachable!() // called notify_all + } + rguard.drop_after(wguard); } else { - unreachable!() // called notify_all + // No readers waiting, the lock is released } - } else { - // No readers waiting, the lock is released + }, + Ok(wguard) => { + // There was a thread waiting for write, just pass the lock + wguard.drop_after(rguard); } - } else { - // There was a thread waiting for write, just pass the lock } } diff --git a/src/libstd/sys/sgx/waitqueue.rs b/src/libstd/sys/sgx/waitqueue.rs index d542f9b410127..3cb40e509b6b2 100644 --- a/src/libstd/sys/sgx/waitqueue.rs +++ b/src/libstd/sys/sgx/waitqueue.rs @@ -98,6 +98,12 @@ impl<'a, T> WaitGuard<'a, T> { pub fn notified_tcs(&self) -> NotifiedTcs { self.notified_tcs } + + /// Drop this `WaitGuard`, after dropping another `guard`. + pub fn drop_after(self, guard: U) { + drop(guard); + drop(self); + } } impl<'a, T> Deref for WaitGuard<'a, T> { @@ -140,7 +146,7 @@ impl WaitQueue { /// until a wakeup event. /// /// This function does not return until this thread has been awoken. - pub fn wait(mut guard: SpinMutexGuard<'_, WaitVariable>) { + pub fn wait(mut guard: SpinMutexGuard<'_, WaitVariable>, before_wait: F) { // very unsafe: check requirements of UnsafeList::push unsafe { let mut entry = UnsafeListEntry::new(SpinMutex::new(WaitEntry { @@ -149,6 +155,7 @@ impl WaitQueue { })); let entry = guard.queue.inner.push(&mut entry); drop(guard); + before_wait(); while !entry.lock().wake { // don't panic, this would invalidate `entry` during unwinding let eventset = rtunwrap!(Ok, usercalls::wait(EV_UNPARK, WAIT_INDEFINITE)); @@ -545,7 +552,7 @@ mod tests { assert!(WaitQueue::notify_one(wq2.lock()).is_ok()); }); - WaitQueue::wait(locked); + WaitQueue::wait(locked, ||{}); t1.join().unwrap(); } From 8af33b325377ea64fb9bbdc10073f9063293c9a6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 29 Aug 2019 09:35:37 +0200 Subject: [PATCH 363/618] qualify_consts: extract check_non_thread_local_static_is_sync --- src/librustc_mir/transform/qualify_consts.rs | 49 ++++++++++---------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index b052d1e9bb468..dbb994183e9d5 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1687,31 +1687,9 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { } } - // Statics must be Sync. if let Mode::Static = mode { - // `#[thread_local]` statics don't have to be `Sync`. - for attr in &tcx.get_attrs(def_id)[..] { - if attr.check_name(sym::thread_local) { - return; - } - } - let ty = body.return_ty(); - tcx.infer_ctxt().enter(|infcx| { - let param_env = ty::ParamEnv::empty(); - let cause = traits::ObligationCause::new(body.span, hir_id, traits::SharedStatic); - let mut fulfillment_cx = traits::FulfillmentContext::new(); - fulfillment_cx.register_bound(&infcx, - param_env, - ty, - tcx.require_lang_item( - lang_items::SyncTraitLangItem, - Some(body.span) - ), - cause); - if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&err, None, false); - } - }); + // `static`s (not `static mut`s) which are not `#[thread_local]` must be `Sync`. + check_non_thread_local_static_is_sync(tcx, body, def_id, hir_id); } } } @@ -1760,6 +1738,29 @@ fn check_short_circuiting_in_const_local(tcx: TyCtxt<'_>, body: &mut Body<'tcx>, } } +fn check_non_thread_local_static_is_sync( + tcx: TyCtxt<'tcx>, + body: &mut Body<'tcx>, + def_id: DefId, + hir_id: HirId, +) { + // `#[thread_local]` statics don't have to be `Sync`. + if tcx.has_attr(def_id, sym::thread_local) { + return; + } + + let ty = body.return_ty(); + tcx.infer_ctxt().enter(|infcx| { + let cause = traits::ObligationCause::new(body.span, hir_id, traits::SharedStatic); + let mut fulfillment_cx = traits::FulfillmentContext::new(); + let sync_def_id = tcx.require_lang_item(lang_items::SyncTraitLangItem, Some(body.span)); + fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), ty, sync_def_id, cause); + if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { + infcx.report_fulfillment_errors(&err, None, false); + } + }); +} + fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { let attrs = tcx.get_attrs(def_id); let attr = attrs.iter().find(|a| a.check_name(sym::rustc_args_required_const))?; From 2f733aad5a73b7cb8ceec37a8ecec497f8807034 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 29 Aug 2019 09:43:16 +0200 Subject: [PATCH 364/618] qualify_consts: extract remove_drop_and_storage_dead_on_promoted_locals. --- src/librustc_mir/transform/qualify_consts.rs | 63 +++++++++++--------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index dbb994183e9d5..fe02e120f3b49 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1656,35 +1656,7 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { Mode::Const => tcx.mir_const_qualif(def_id).1, _ => Checker::new(tcx, def_id, body, mode).check_const().1, }; - - // In `const` and `static` everything without `StorageDead` - // is `'static`, we don't have to create promoted MIR fragments, - // just remove `Drop` and `StorageDead` on "promoted" locals. - debug!("run_pass: promoted_temps={:?}", promoted_temps); - for block in body.basic_blocks_mut() { - block.statements.retain(|statement| { - match statement.kind { - StatementKind::StorageDead(index) => { - !promoted_temps.contains(index) - } - _ => true - } - }); - let terminator = block.terminator_mut(); - match terminator.kind { - TerminatorKind::Drop { - location: Place { - base: PlaceBase::Local(index), - projection: None, - }, - target, - .. - } if promoted_temps.contains(index) => { - terminator.kind = TerminatorKind::Goto { target }; - } - _ => {} - } - } + remove_drop_and_storage_dead_on_promoted_locals(body, promoted_temps); } if let Mode::Static = mode { @@ -1738,6 +1710,39 @@ fn check_short_circuiting_in_const_local(tcx: TyCtxt<'_>, body: &mut Body<'tcx>, } } +/// In `const` and `static` everything without `StorageDead` +/// is `'static`, we don't have to create promoted MIR fragments, +/// just remove `Drop` and `StorageDead` on "promoted" locals. +fn remove_drop_and_storage_dead_on_promoted_locals( + body: &mut Body<'tcx>, + promoted_temps: &BitSet, +) { + debug!("run_pass: promoted_temps={:?}", promoted_temps); + + for block in body.basic_blocks_mut() { + block.statements.retain(|statement| { + match statement.kind { + StatementKind::StorageDead(index) => !promoted_temps.contains(index), + _ => true + } + }); + let terminator = block.terminator_mut(); + match terminator.kind { + TerminatorKind::Drop { + location: Place { + base: PlaceBase::Local(index), + projection: None, + }, + target, + .. + } if promoted_temps.contains(index) => { + terminator.kind = TerminatorKind::Goto { target }; + } + _ => {} + } + } +} + fn check_non_thread_local_static_is_sync( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, From 9196af0b3647c29cb1c268ba9b01546df55fc004 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 29 Aug 2019 10:16:41 +0200 Subject: [PATCH 365/618] qualify_consts: extract error_min_const_fn_violation. --- src/librustc_mir/transform/qualify_consts.rs | 26 +++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index fe02e120f3b49..73475be24d445 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -25,6 +25,7 @@ use syntax::feature_gate::{emit_feature_err, GateIssue}; use syntax::symbol::sym; use syntax_pos::{Span, DUMMY_SP}; +use std::borrow::Cow; use std::cell::Cell; use std::fmt; use std::ops::{Deref, Index, IndexMut}; @@ -1607,26 +1608,14 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { // which can't be mutated until its scope ends. let (temps, candidates) = { let mut checker = Checker::new(tcx, def_id, body, mode); - if mode == Mode::ConstFn { + if let Mode::ConstFn = mode { if tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you { checker.check_const(); } else if tcx.is_min_const_fn(def_id) { - // enforce `min_const_fn` for stable const fns + // Enforce `min_const_fn` for stable `const fn`s. use super::qualify_min_const_fn::is_min_const_fn; if let Err((span, err)) = is_min_const_fn(tcx, def_id, body) { - let mut diag = struct_span_err!( - tcx.sess, - span, - E0723, - "{}", - err, - ); - diag.note("for more information, see issue \ - https://github.com/rust-lang/rust/issues/57563"); - diag.help( - "add `#![feature(const_fn)]` to the crate attributes to enable", - ); - diag.emit(); + error_min_const_fn_violation(tcx, span, err); } else { // this should not produce any errors, but better safe than sorry // FIXME(#53819) @@ -1677,6 +1666,13 @@ fn determine_mode(tcx: TyCtxt<'_>, hir_id: HirId, def_id: DefId) -> Mode { } } +fn error_min_const_fn_violation(tcx: TyCtxt<'_>, span: Span, msg: Cow<'_, str>) { + struct_span_err!(tcx.sess, span, E0723, "{}", msg) + .note("for more information, see issue https://github.com/rust-lang/rust/issues/57563") + .help("add `#![feature(const_fn)]` to the crate attributes to enable") + .emit(); +} + fn check_short_circuiting_in_const_local(tcx: TyCtxt<'_>, body: &mut Body<'tcx>, mode: Mode) { if body.control_flow_destroyed.is_empty() { return; From 0a8a3dd88a1216e7487b8e39179fbac16d07bafe Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 31 Aug 2019 06:17:10 +0200 Subject: [PATCH 366/618] qualify_consts: move thread_local condition out. --- src/librustc_mir/transform/qualify_consts.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 73475be24d445..32b49ee942300 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1648,9 +1648,9 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { remove_drop_and_storage_dead_on_promoted_locals(body, promoted_temps); } - if let Mode::Static = mode { + if mode == Mode::Static && !tcx.has_attr(def_id, sym::thread_local) { // `static`s (not `static mut`s) which are not `#[thread_local]` must be `Sync`. - check_non_thread_local_static_is_sync(tcx, body, def_id, hir_id); + check_static_is_sync(tcx, body, hir_id); } } } @@ -1739,17 +1739,7 @@ fn remove_drop_and_storage_dead_on_promoted_locals( } } -fn check_non_thread_local_static_is_sync( - tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, - def_id: DefId, - hir_id: HirId, -) { - // `#[thread_local]` statics don't have to be `Sync`. - if tcx.has_attr(def_id, sym::thread_local) { - return; - } - +fn check_static_is_sync(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, hir_id: HirId) { let ty = body.return_ty(); tcx.infer_ctxt().enter(|infcx| { let cause = traits::ObligationCause::new(body.span, hir_id, traits::SharedStatic); From 5187a3e15723c85cd7ef3418b0c0e61c79709f4c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 31 Aug 2019 07:08:23 +0200 Subject: [PATCH 367/618] Harden param_attrs test wrt. usage of proc macro attrs. --- .../auxiliary/ident-mac.rs | 11 + .../proc-macro-cannot-be-used.rs | 60 +++++ .../proc-macro-cannot-be-used.stderr | 228 ++++++++++++++++++ 3 files changed, 299 insertions(+) create mode 100644 src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr diff --git a/src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs b/src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs new file mode 100644 index 0000000000000..b62cf31205fd3 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs @@ -0,0 +1,11 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn id(_: TokenStream, input: TokenStream) -> TokenStream { input } diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs new file mode 100644 index 0000000000000..8defa26e48d8d --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs @@ -0,0 +1,60 @@ +// aux-build:ident-mac.rs + +#![feature(param_attrs)] +#![feature(c_variadic)] + +extern crate ident_mac; +use ident_mac::id; + +struct W(u8); + +extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } +//~^ ERROR the attribute `id` is currently unknown to the compiler +//~| ERROR the attribute `id` is currently unknown to the compiler + +unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {} +//~^ ERROR the attribute `id` is currently unknown to the compiler + +type Alias = extern "C" fn(#[id] u8, #[id] ...); + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + +fn free(#[id] arg1: u8) { + //~^ ERROR the attribute `id` is currently unknown to the compiler + let lam = |#[id] W(x), #[id] y| (); + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler +} + +impl W { + fn inherent1(#[id] self, #[id] arg1: u8) {} + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + fn inherent2(#[id] &self, #[id] arg1: u8) {} + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + fn inherent4<'a>(#[id] self: Box, #[id] arg1: u8) {} + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler +} + +trait A { + fn trait1(#[id] self, #[id] arg1: u8); + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + fn trait2(#[id] &self, #[id] arg1: u8); + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + //~^ ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler + //~| ERROR the attribute `id` is currently unknown to the compiler +} + +fn main() {} diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr new file mode 100644 index 0000000000000..69b9a46b3d502 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr @@ -0,0 +1,228 @@ +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:11:21 + | +LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:11:38 + | +LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:15:38 + | +LL | unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:18:28 + | +LL | type Alias = extern "C" fn(#[id] u8, #[id] ...); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:18:38 + | +LL | type Alias = extern "C" fn(#[id] u8, #[id] ...); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:22:9 + | +LL | fn free(#[id] arg1: u8) { + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:24:16 + | +LL | let lam = |#[id] W(x), #[id] y| (); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:24:28 + | +LL | let lam = |#[id] W(x), #[id] y| (); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:30:18 + | +LL | fn inherent1(#[id] self, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:30:30 + | +LL | fn inherent1(#[id] self, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:33:18 + | +LL | fn inherent2(#[id] &self, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:33:31 + | +LL | fn inherent2(#[id] &self, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:36:22 + | +LL | fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:36:42 + | +LL | fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:39:22 + | +LL | fn inherent4<'a>(#[id] self: Box, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:39:45 + | +LL | fn inherent4<'a>(#[id] self: Box, #[id] arg1: u8) {} + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:45:15 + | +LL | fn trait1(#[id] self, #[id] arg1: u8); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:45:27 + | +LL | fn trait1(#[id] self, #[id] arg1: u8); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:48:15 + | +LL | fn trait2(#[id] &self, #[id] arg1: u8); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:48:28 + | +LL | fn trait2(#[id] &self, #[id] arg1: u8); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:51:19 + | +LL | fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:51:39 + | +LL | fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:54:19 + | +LL | fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:54:42 + | +LL | fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error[E0658]: the attribute `id` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-cannot-be-used.rs:54:58 + | +LL | fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(custom_attribute)]` to the crate attributes to enable + +error: aborting due to 25 previous errors + +For more information about this error, try `rustc --explain E0658`. From 444bc3ca6607f7bdeb088b34db23c01e056900b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 24 Aug 2019 14:44:43 -0700 Subject: [PATCH 368/618] Use span label instead of note for cause in E0631 --- src/librustc/traits/error_reporting.rs | 37 +- .../anonymous-higher-ranked-lifetime.stderr | 154 ++----- .../associated-const-array-len.stderr | 9 +- ...iated-const-type-parameter-arrays-2.stderr | 8 +- ...ociated-const-type-parameter-arrays.stderr | 8 +- .../bad-bounds-on-assoc-in-trait.stderr | 24 +- ...nding-to-type-defined-in-supertrait.stderr | 16 +- .../associated-types-bound-failure.stderr | 8 +- .../associated-types-eq-3.stderr | 8 +- .../associated-types-eq-hr.stderr | 102 ++--- .../associated-types-issue-20346.stderr | 8 +- ...ated-types-multiple-types-one-trait.stderr | 16 +- ...associated-types-overridden-binding.stderr | 8 +- .../associated-types-path-2.stderr | 18 +- .../higher-ranked-projection.bad.stderr | 11 +- .../ui/async-await/async-fn-nonsend.stderr | 32 +- src/test/ui/chalkify/type_inference.stderr | 8 +- .../expect-fn-supply-fn.stderr | 45 +- .../expect-infer-var-appearing-twice.stderr | 15 +- ...ds-cant-promote-superkind-in-struct.stderr | 8 +- .../ui/closures/closure-bounds-subtype.stderr | 8 +- .../ui/consts/too_generic_eval_ice.stderr | 16 +- src/test/ui/defaulted-never-note.stderr | 8 +- src/test/ui/derives/deriving-copyclone.stderr | 24 +- .../issue-39802-show-5-trait-impls.stderr | 24 +- .../ui/did_you_mean/recursion_limit.stderr | 8 +- src/test/ui/error-codes/E0271.stderr | 8 +- src/test/ui/error-codes/E0275.stderr | 8 +- src/test/ui/error-codes/E0277-2.stderr | 8 +- src/test/ui/error-codes/E0277.stderr | 9 +- src/test/ui/error-codes/E0283.stderr | 9 +- .../ui/error-should-say-copy-not-pod.stderr | 9 +- .../extern/extern-types-not-sync-send.stderr | 16 +- .../ui/extern/extern-types-unsized.stderr | 32 +- .../ui/extern/extern-wrong-value-type.stderr | 8 +- src/test/ui/fmt/send-sync.stderr | 16 +- src/test/ui/fn/fn-trait-formatting.stderr | 8 +- ...erator-yielding-or-returning-itself.stderr | 18 +- src/test/ui/generator/not-send-sync.stderr | 16 +- src/test/ui/generator/static-not-unpin.stderr | 9 +- src/test/ui/hrtb/hrtb-conflate-regions.stderr | 16 +- ...b-exists-forall-trait-contravariant.stderr | 16 +- .../hrtb-exists-forall-trait-covariant.stderr | 16 +- .../hrtb-exists-forall-trait-invariant.stderr | 16 +- ...igher-ranker-supertraits-transitive.stderr | 14 +- .../hrtb-higher-ranker-supertraits.stderr | 28 +- src/test/ui/hrtb/hrtb-just-for-static.stderr | 32 +- src/test/ui/hrtb/issue-46989.stderr | 8 +- src/test/ui/impl-trait/auto-trait-leak.stderr | 8 +- .../ui/impl-trait/auto-trait-leak2.stderr | 16 +- src/test/ui/issues/issue-1920-1.stderr | 9 +- src/test/ui/issues/issue-1920-2.stderr | 9 +- src/test/ui/issues/issue-1920-3.stderr | 9 +- src/test/ui/issues/issue-20005.stderr | 8 +- src/test/ui/issues/issue-20413.stderr | 16 +- src/test/ui/issues/issue-21763.stderr | 8 +- src/test/ui/issues/issue-21837.stderr | 8 +- src/test/ui/issues/issue-21974.stderr | 9 +- src/test/ui/issues/issue-24204.stderr | 8 +- src/test/ui/issues/issue-24424.stderr | 9 +- src/test/ui/issues/issue-25076.stderr | 9 +- src/test/ui/issues/issue-29147.stderr | 9 +- src/test/ui/issues/issue-32963.stderr | 9 +- src/test/ui/issues/issue-39970.stderr | 8 +- src/test/ui/issues/issue-40827.stderr | 16 +- src/test/ui/issues/issue-43623.stderr | 24 +- src/test/ui/issues/issue-47706.stderr | 15 +- src/test/ui/issues/issue-60283.stderr | 28 +- src/test/ui/iterators/bound.stderr | 7 +- src/test/ui/kindck/kindck-copy.stderr | 97 ++--- .../kindck/kindck-impl-type-params-2.stderr | 8 +- .../kindck/kindck-inherited-copy-bound.stderr | 8 +- .../ui/kindck/kindck-nonsendable-1.stderr | 8 +- src/test/ui/kindck/kindck-send-object.stderr | 16 +- src/test/ui/kindck/kindck-send-object1.stderr | 16 +- src/test/ui/kindck/kindck-send-object2.stderr | 16 +- src/test/ui/kindck/kindck-send-owned.stderr | 8 +- src/test/ui/kindck/kindck-send-unsafe.stderr | 8 +- .../overlap-marker-trait.stderr | 9 +- src/test/ui/mismatched_types/E0631.stderr | 36 +- .../mismatched_types/closure-arg-count.stderr | 26 +- .../closure-arg-type-mismatch.stderr | 18 +- .../mismatched_types/closure-mismatch.stderr | 16 +- .../ui/mismatched_types/fn-variance-1.stderr | 18 +- .../unboxed-closures-vtable-mismatch.stderr | 9 +- src/test/ui/mut/mutable-enum-indirect.stderr | 8 +- src/test/ui/mutexguard-sync.stderr | 8 +- src/test/ui/namespace/namespace-mix.stderr | 396 ++++++------------ src/test/ui/no_send-enum.stderr | 8 +- src/test/ui/no_send-rc.stderr | 8 +- src/test/ui/no_send-struct.stderr | 8 +- src/test/ui/no_share-enum.stderr | 8 +- src/test/ui/no_share-struct.stderr | 8 +- src/test/ui/not-panic/not-panic-safe-2.stderr | 16 +- src/test/ui/not-panic/not-panic-safe-3.stderr | 16 +- src/test/ui/not-panic/not-panic-safe-4.stderr | 16 +- src/test/ui/not-panic/not-panic-safe-5.stderr | 8 +- src/test/ui/not-panic/not-panic-safe-6.stderr | 16 +- src/test/ui/not-panic/not-panic-safe.stderr | 8 +- src/test/ui/not-sync.stderr | 48 +-- src/test/ui/object-does-not-impl-trait.stderr | 8 +- .../ui/on-unimplemented/multiple-impls.stderr | 24 +- src/test/ui/on-unimplemented/on-impl.stderr | 8 +- src/test/ui/on-unimplemented/on-trait.stderr | 16 +- src/test/ui/overlap-marker-trait.stderr | 9 +- src/test/ui/phantom-oibit.stderr | 16 +- .../recursion/recursive-requirements.stderr | 16 +- src/test/ui/span/issue-29595.stderr | 9 +- src/test/ui/str/str-mut-idx.stderr | 8 +- .../structs/struct-path-alias-bounds.stderr | 9 +- src/test/ui/substs-ppaux.normal.stderr | 8 +- src/test/ui/substs-ppaux.verbose.stderr | 8 +- src/test/ui/suggestions/into-str.stderr | 8 +- .../trait-alias-cross-crate.stderr | 16 +- .../traits/trait-alias/trait-alias-wf.stderr | 7 +- ...-bounds-on-structs-and-enums-in-fns.stderr | 18 +- ...ounds-on-structs-and-enums-in-impls.stderr | 9 +- ...-bounds-on-structs-and-enums-locals.stderr | 18 +- ...-bounds-on-structs-and-enums-static.stderr | 9 +- .../trait-bounds-on-structs-and-enums.stderr | 60 +-- ...ait-static-method-generic-inference.stderr | 9 +- ...its-inductive-overflow-simultaneous.stderr | 8 +- ...inductive-overflow-supertrait-oibit.stderr | 8 +- ...raits-inductive-overflow-supertrait.stderr | 8 +- ...raits-inductive-overflow-two-traits.stderr | 9 +- .../ui/traits/traits-negative-impls.stderr | 56 +-- .../traits-repeated-supertrait-ambig.stderr | 17 +- .../trivial-bounds/trivial-bounds-leak.stderr | 16 +- src/test/ui/try-operator-on-main.stderr | 7 +- .../ui/type/type-annotation-needed.stderr | 9 +- src/test/ui/type/type-check-defaults.stderr | 61 +-- .../ui/type/type-check/issue-40294.stderr | 9 +- .../type-params-in-different-spaces-2.stderr | 16 +- ...ypeck-default-trait-impl-assoc-type.stderr | 8 +- ...ault-trait-impl-constituent-types-2.stderr | 8 +- ...efault-trait-impl-constituent-types.stderr | 8 +- ...ck-default-trait-impl-negation-send.stderr | 8 +- ...ck-default-trait-impl-negation-sync.stderr | 24 +- .../typeck-default-trait-impl-negation.stderr | 16 +- ...ypeck-default-trait-impl-precedence.stderr | 8 +- ...ypeck-default-trait-impl-send-param.stderr | 8 +- .../typeck/typeck-unsafe-always-share.stderr | 32 +- .../unboxed-closure-sugar-default.stderr | 9 +- .../unboxed-closure-sugar-equiv.stderr | 9 +- .../unboxed-closures-fnmut-as-fn.stderr | 8 +- .../unboxed-closures-unsafe-extern-fn.stderr | 40 +- .../unboxed-closures-wrong-abi.stderr | 40 +- ...d-closures-wrong-arg-type-extern-fn.stderr | 40 +- .../unevaluated_fixed_size_array_len.stderr | 8 +- src/test/ui/union/union-generic.stderr | 18 +- .../ui/unsized/unsized-bare-typaram.stderr | 7 +- src/test/ui/unsized/unsized-enum.stderr | 8 +- .../unsized-inherent-impl-self-type.stderr | 8 +- src/test/ui/unsized/unsized-struct.stderr | 16 +- .../unsized-trait-impl-self-type.stderr | 8 +- src/test/ui/unsized3.stderr | 32 +- src/test/ui/wf/wf-const-type.stderr | 8 +- src/test/ui/wf/wf-enum-bound.stderr | 8 +- .../wf/wf-enum-fields-struct-variant.stderr | 8 +- src/test/ui/wf/wf-enum-fields.stderr | 8 +- src/test/ui/wf/wf-fn-where-clause.stderr | 8 +- .../wf/wf-impl-associated-type-trait.stderr | 8 +- src/test/ui/wf/wf-in-fn-arg.stderr | 8 +- src/test/ui/wf/wf-in-fn-ret.stderr | 8 +- src/test/ui/wf/wf-in-fn-type-arg.stderr | 8 +- src/test/ui/wf/wf-in-fn-type-ret.stderr | 8 +- src/test/ui/wf/wf-in-fn-where-clause.stderr | 8 +- src/test/ui/wf/wf-in-obj-type-trait.stderr | 8 +- ...f-inherent-impl-method-where-clause.stderr | 8 +- .../wf/wf-inherent-impl-where-clause.stderr | 8 +- src/test/ui/wf/wf-static-type.stderr | 8 +- src/test/ui/wf/wf-struct-bound.stderr | 8 +- src/test/ui/wf/wf-struct-field.stderr | 8 +- .../wf/wf-trait-associated-type-bound.stderr | 8 +- .../wf/wf-trait-associated-type-trait.stderr | 8 +- src/test/ui/wf/wf-trait-bound.stderr | 8 +- src/test/ui/wf/wf-trait-default-fn-arg.stderr | 8 +- src/test/ui/wf/wf-trait-default-fn-ret.stderr | 8 +- .../wf-trait-default-fn-where-clause.stderr | 8 +- src/test/ui/wf/wf-trait-fn-arg.stderr | 8 +- src/test/ui/wf/wf-trait-fn-ret.stderr | 8 +- .../ui/wf/wf-trait-fn-where-clause.stderr | 8 +- src/test/ui/wf/wf-trait-superbound.stderr | 8 +- ...traints-are-local-for-inherent-impl.stderr | 8 +- ...onstraints-are-local-for-trait-impl.stderr | 8 +- .../where-clauses-unsatisfied.stderr | 9 +- .../ui/where-clauses/where-for-self-2.stderr | 16 +- 187 files changed, 1177 insertions(+), 2058 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 93742c83be440..aa0fcafbb0e6b 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -657,19 +657,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { span, E0277, "{}", - message.unwrap_or_else(|| - format!("the trait bound `{}` is not satisfied{}", - trait_ref.to_predicate(), post_message) - )); + message.unwrap_or_else(|| format!( + "the trait bound `{}` is not satisfied{}", + trait_ref.to_predicate(), + post_message, + ))); let explanation = if obligation.cause.code == ObligationCauseCode::MainFunctionType { "consider using `()`, or a `Result`".to_owned() } else { - format!("{}the trait `{}` is not implemented for `{}`", + format!( + "{}the trait `{}` is not implemented for `{}`", pre_message, trait_ref, - trait_ref.self_ty()) + trait_ref.self_ty(), + ) }; if let Some(ref s) = label { @@ -1535,17 +1538,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.note("only the last element of a tuple may have a dynamically sized type"); } ObligationCauseCode::ProjectionWf(data) => { - err.note(&format!("required so that the projection `{}` is well-formed", - data)); + err.note(&format!( + "required so that the projection `{}` is well-formed", + data, + )); } ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => { - err.note(&format!("required so that reference `{}` does not outlive its referent", - ref_ty)); + err.note(&format!( + "required so that reference `{}` does not outlive its referent", + ref_ty, + )); } ObligationCauseCode::ObjectTypeBound(object_ty, region) => { - err.note(&format!("required so that the lifetime bound of `{}` for `{}` \ - is satisfied", - region, object_ty)); + err.note(&format!( + "required so that the lifetime bound of `{}` for `{}` is satisfied", + region, + object_ty, + )); } ObligationCauseCode::ItemObligation(item_def_id) => { let item_name = tcx.def_path_str(item_def_id); @@ -1553,7 +1562,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Some(sp) = tcx.hir().span_if_local(item_def_id) { let sp = tcx.sess.source_map().def_span(sp); - err.span_note(sp, &msg); + err.span_label(sp, &msg); } else { err.note(&msg); } diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr index 0ca3ca8437463..c65a44bfbccfe 100644 --- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr +++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr @@ -5,12 +5,9 @@ LL | f1(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'r, 's> fn(&'r (), &'s ()) -> _` - | -note: required by `f1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1 - | +... LL | fn f1(_: F) where F: Fn(&(), &()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------------ required by `f1` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5 @@ -19,12 +16,9 @@ LL | f1(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&(), &()) -> _` - | -note: required by `f1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1 - | +... LL | fn f1(_: F) where F: Fn(&(), &()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------------ required by `f1` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 @@ -33,12 +27,9 @@ LL | f2(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'a, 'r> fn(&'a (), &'r ()) -> _` - | -note: required by `f2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1 - | +... LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------------------------------------------- required by `f2` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 @@ -47,12 +38,9 @@ LL | f2(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&'a (), &()) -> _` - | -note: required by `f2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1 - | +... LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------------------------------------------- required by `f2` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 @@ -61,12 +49,9 @@ LL | f3(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'r> fn(&(), &'r ()) -> _` - | -note: required by `f3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1 - | +... LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------------------- required by `f3` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 @@ -75,12 +60,9 @@ LL | f3(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&(), &()) -> _` - | -note: required by `f3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1 - | +... LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------------------- required by `f3` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 @@ -89,12 +71,9 @@ LL | f4(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'s, 'r> fn(&'s (), &'r ()) -> _` - | -note: required by `f4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1 - | +... LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------------------------------------------- required by `f4` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 @@ -103,12 +82,9 @@ LL | f4(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&(), &'r ()) -> _` - | -note: required by `f4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1 - | +... LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------------------------------------------- required by `f4` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 @@ -117,12 +93,9 @@ LL | f5(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'r> fn(&'r (), &'r ()) -> _` - | -note: required by `f5` - --> $DIR/anonymous-higher-ranked-lifetime.rs:31:1 - | +... LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -------------------------------------------------- required by `f5` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 @@ -131,12 +104,9 @@ LL | f5(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&'r (), &'r ()) -> _` - | -note: required by `f5` - --> $DIR/anonymous-higher-ranked-lifetime.rs:31:1 - | +... LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -------------------------------------------------- required by `f5` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 @@ -145,12 +115,9 @@ LL | g1(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'r> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>) -> _` - | -note: required by `g1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1 - | +... LL | fn g1(_: F) where F: Fn(&(), Box) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------------------------- required by `g1` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 @@ -159,12 +126,9 @@ LL | g1(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` - | -note: required by `g1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1 - | +... LL | fn g1(_: F) where F: Fn(&(), Box) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------------------------- required by `g1` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5 @@ -173,12 +137,9 @@ LL | g2(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'r> fn(&'r (), for<'s> fn(&'s ())) -> _` - | -note: required by `g2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1 - | +... LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------------------------------------- required by `g2` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5 @@ -187,12 +148,9 @@ LL | g2(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&(), for<'r> fn(&'r ())) -> _` - | -note: required by `g2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1 - | +... LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------------------------------------- required by `g2` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5 @@ -201,12 +159,9 @@ LL | g3(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'s> fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` - | -note: required by `g3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1 - | +... LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------------------------------------ required by `g3` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5 @@ -215,12 +170,9 @@ LL | g3(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` - | -note: required by `g3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1 - | +... LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------------------------------------ required by `g3` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5 @@ -229,12 +181,9 @@ LL | g4(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'s> fn(&'s (), for<'r> fn(&'r ())) -> _` - | -note: required by `g4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:37:1 - | +... LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --------------------------------------------------- required by `g4` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5 @@ -243,12 +192,9 @@ LL | g4(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `fn(&(), for<'r> fn(&'r ())) -> _` - | -note: required by `g4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:37:1 - | +... LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --------------------------------------------------- required by `g4` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5 @@ -257,12 +203,9 @@ LL | h1(|_: (), _: (), _: (), _: ()| {}); | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` | | | expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<(dyn for<'t0> std::ops::Fn(&'t0 ()) + 'static)>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _` - | -note: required by `h1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1 - | +... LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -------------------------------------------------------------------- required by `h1` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5 @@ -271,12 +214,9 @@ LL | h1(|_: (), _: (), _: (), _: ()| {}); | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` | | | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &(), for<'r, 's> fn(&'r (), &'s ())) -> _` - | -note: required by `h1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1 - | +... LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -------------------------------------------------------------------- required by `h1` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5 @@ -285,12 +225,9 @@ LL | h2(|_: (), _: (), _: (), _: ()| {}); | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` | | | expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _` - | -note: required by `h2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:41:1 - | +... LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --------------------------------------------------------------------------------- required by `h2` error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5 @@ -299,12 +236,9 @@ LL | h2(|_: (), _: (), _: (), _: ()| {}); | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` | | | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &'t0 (), for<'r, 's> fn(&'r (), &'s ())) -> _` - | -note: required by `h2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:41:1 - | +... LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --------------------------------------------------------------------------------- required by `h2` error: aborting due to 22 previous errors diff --git a/src/test/ui/associated-const/associated-const-array-len.stderr b/src/test/ui/associated-const/associated-const-array-len.stderr index ff56d112c8184..2fdfa3da3086c 100644 --- a/src/test/ui/associated-const/associated-const-array-len.stderr +++ b/src/test/ui/associated-const/associated-const-array-len.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/associated-const-array-len.rs:5:16 | +LL | const ID: usize; + | ---------------- required by `Foo::ID` +... LL | const X: [i32; ::ID] = [0, 1, 2]; | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` - | -note: required by `Foo::ID` - --> $DIR/associated-const-array-len.rs:2:5 - | -LL | const ID: usize; - | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr index 573b8ed39bcaa..30b6b4f3909b2 100644 --- a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr +++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `A: Foo` is not satisfied --> $DIR/associated-const-type-parameter-arrays-2.rs:16:22 | +LL | const Y: usize; + | --------------- required by `Foo::Y` +... LL | let _array = [4; ::Y]; | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` | = help: consider adding a `where A: Foo` bound -note: required by `Foo::Y` - --> $DIR/associated-const-type-parameter-arrays-2.rs:2:5 - | -LL | const Y: usize; - | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr index bf1ee38571404..30fa9891a13e1 100644 --- a/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr +++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `A: Foo` is not satisfied --> $DIR/associated-const-type-parameter-arrays.rs:16:23 | +LL | const Y: usize; + | --------------- required by `Foo::Y` +... LL | let _array: [u32; ::Y]; | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` | = help: consider adding a `where A: Foo` bound -note: required by `Foo::Y` - --> $DIR/associated-const-type-parameter-arrays.rs:2:5 - | -LL | const Y: usize; - | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr index aebf29cc332ab..06e8230aa1589 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr @@ -24,6 +24,9 @@ LL | | } error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 | +LL | trait Case1 { + | ----------- required by `Case1` +... LL | / fn assume_case1() { LL | | LL | | @@ -35,15 +38,13 @@ LL | | } | = help: the trait `std::marker::Send` is not implemented for `<::C as std::iter::Iterator>::Item` = help: consider adding a `where <::C as std::iter::Iterator>::Item: std::marker::Send` bound -note: required by `Case1` - --> $DIR/bad-bounds-on-assoc-in-trait.rs:22:1 - | -LL | trait Case1 { - | ^^^^^^^^^^^ error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 | +LL | trait Case1 { + | ----------- required by `Case1` +... LL | / fn assume_case1() { LL | | LL | | @@ -55,15 +56,13 @@ LL | | } | = help: the trait `std::marker::Sync` is not implemented for `<::C as std::iter::Iterator>::Item` = help: consider adding a `where <::C as std::iter::Iterator>::Item: std::marker::Sync` bound -note: required by `Case1` - --> $DIR/bad-bounds-on-assoc-in-trait.rs:22:1 - | -LL | trait Case1 { - | ^^^^^^^^^^^ error[E0277]: `<_ as Lam<&'a u8>>::App` doesn't implement `std::fmt::Debug` --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 | +LL | trait Case1 { + | ----------- required by `Case1` +... LL | / fn assume_case1() { LL | | LL | | @@ -74,11 +73,6 @@ LL | | } | |_^ `<_ as Lam<&'a u8>>::App` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` | = help: the trait `for<'a> std::fmt::Debug` is not implemented for `<_ as Lam<&'a u8>>::App` -note: required by `Case1` - --> $DIR/bad-bounds-on-assoc-in-trait.rs:22:1 - | -LL | trait Case1 { - | ^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr index 89c48d50cdb65..a3049892abc39 100644 --- a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr @@ -1,30 +1,26 @@ error[E0271]: type mismatch resolving `::Color == Blue` --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:31:10 | +LL | fn blue_car>(c: C) { + | ------------------------------------ required by `blue_car` +... LL | fn b() { blue_car(ModelT); } | ^^^^^^^^ expected struct `Black`, found struct `Blue` | = note: expected type `Black` found type `Blue` -note: required by `blue_car` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:27:1 - | -LL | fn blue_car>(c: C) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving `::Color == Black` --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:32:10 | +LL | fn black_car>(c: C) { + | -------------------------------------- required by `black_car` +... LL | fn c() { black_car(ModelU); } | ^^^^^^^^^ expected struct `Blue`, found struct `Black` | = note: expected type `Blue` found type `Black` -note: required by `black_car` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:24:1 - | -LL | fn black_car>(c: C) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/associated-types-bound-failure.stderr b/src/test/ui/associated-types/associated-types-bound-failure.stderr index 502fb4f1c3033..54654b95edd90 100644 --- a/src/test/ui/associated-types/associated-types-bound-failure.stderr +++ b/src/test/ui/associated-types/associated-types-bound-failure.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `::R: ToInt` is not satisfied --> $DIR/associated-types-bound-failure.rs:17:5 | +LL | fn to_int(&self) -> isize; + | -------------------------- required by `ToInt::to_int` +... LL | ToInt::to_int(&g.get()) | ^^^^^^^^^^^^^ the trait `ToInt` is not implemented for `::R` | = help: consider adding a `where ::R: ToInt` bound -note: required by `ToInt::to_int` - --> $DIR/associated-types-bound-failure.rs:4:5 - | -LL | fn to_int(&self) -> isize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-eq-3.stderr b/src/test/ui/associated-types/associated-types-eq-3.stderr index 66fa4c288ca46..0f8c5257d445f 100644 --- a/src/test/ui/associated-types/associated-types-eq-3.stderr +++ b/src/test/ui/associated-types/associated-types-eq-3.stderr @@ -10,16 +10,14 @@ LL | let _: Bar = x.boo(); error[E0271]: type mismatch resolving `::A == Bar` --> $DIR/associated-types-eq-3.rs:38:5 | +LL | fn foo1>(x: I) { + | ---------------------------- required by `foo1` +... LL | foo1(a); | ^^^^ expected usize, found struct `Bar` | = note: expected type `usize` found type `Bar` -note: required by `foo1` - --> $DIR/associated-types-eq-3.rs:18:1 - | -LL | fn foo1>(x: I) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving `::A == Bar` --> $DIR/associated-types-eq-3.rs:41:9 diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 353829c2f7631..05e6ed69812ad 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -1,124 +1,108 @@ error[E0271]: type mismatch resolving `for<'x> >::A == &'x isize` --> $DIR/associated-types-eq-hr.rs:82:5 | -LL | foo::(); - | ^^^^^^^^^^^^^^^^^ expected usize, found isize - | - = note: expected type `&usize` - found type `&isize` -note: required by `foo` - --> $DIR/associated-types-eq-hr.rs:44:1 - | LL | / fn foo() LL | | where T : for<'x> TheTrait<&'x isize, A = &'x isize> LL | | { LL | | // ok for IntStruct, but not UintStruct LL | | } - | |_^ + | |_- required by `foo` +... +LL | foo::(); + | ^^^^^^^^^^^^^^^^^ expected usize, found isize + | + = note: expected type `&usize` + found type `&isize` error[E0271]: type mismatch resolving `for<'x> >::A == &'x usize` --> $DIR/associated-types-eq-hr.rs:86:5 | -LL | bar::(); - | ^^^^^^^^^^^^^^^^ expected isize, found usize - | - = note: expected type `&isize` - found type `&usize` -note: required by `bar` - --> $DIR/associated-types-eq-hr.rs:50:1 - | LL | / fn bar() LL | | where T : for<'x> TheTrait<&'x isize, A = &'x usize> LL | | { LL | | // ok for UintStruct, but not IntStruct LL | | } - | |_^ + | |_- required by `bar` +... +LL | bar::(); + | ^^^^^^^^^^^^^^^^ expected isize, found usize + | + = note: expected type `&isize` + found type `&usize` error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied --> $DIR/associated-types-eq-hr.rs:91:5 | -LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` - | - = help: the following implementations were found: - > -note: required by `tuple_one` - --> $DIR/associated-types-eq-hr.rs:56:1 - | LL | / fn tuple_one() LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> LL | | { LL | | // not ok for tuple, two lifetimes and we pick first LL | | } - | |_^ + | |_- required by `tuple_one` +... +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` + | + = help: the following implementations were found: + > error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'x isize` --> $DIR/associated-types-eq-hr.rs:91:5 | -LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime - | -note: required by `tuple_one` - --> $DIR/associated-types-eq-hr.rs:56:1 - | LL | / fn tuple_one() LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> LL | | { LL | | // not ok for tuple, two lifetimes and we pick first LL | | } - | |_^ + | |_- required by `tuple_one` +... +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied --> $DIR/associated-types-eq-hr.rs:97:5 | -LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` - | - = help: the following implementations were found: - > -note: required by `tuple_two` - --> $DIR/associated-types-eq-hr.rs:62:1 - | LL | / fn tuple_two() LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> LL | | { LL | | // not ok for tuple, two lifetimes and we pick second LL | | } - | |_^ + | |_- required by `tuple_two` +... +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` + | + = help: the following implementations were found: + > error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'y isize` --> $DIR/associated-types-eq-hr.rs:97:5 | -LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime - | -note: required by `tuple_two` - --> $DIR/associated-types-eq-hr.rs:62:1 - | LL | / fn tuple_two() LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> LL | | { LL | | // not ok for tuple, two lifetimes and we pick second LL | | } - | |_^ + | |_- required by `tuple_two` +... +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied --> $DIR/associated-types-eq-hr.rs:107:5 | -LL | tuple_four::(); - | ^^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` - | - = help: the following implementations were found: - > -note: required by `tuple_four` - --> $DIR/associated-types-eq-hr.rs:74:1 - | LL | / fn tuple_four() LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)> LL | | { LL | | // not ok for tuple, two lifetimes, and lifetime matching is invariant LL | | } - | |_^ + | |_- required by `tuple_four` +... +LL | tuple_four::(); + | ^^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` + | + = help: the following implementations were found: + > error: aborting due to 7 previous errors diff --git a/src/test/ui/associated-types/associated-types-issue-20346.stderr b/src/test/ui/associated-types/associated-types-issue-20346.stderr index 7d5b16c6e62d0..7d6c025d69d55 100644 --- a/src/test/ui/associated-types/associated-types-issue-20346.stderr +++ b/src/test/ui/associated-types/associated-types-issue-20346.stderr @@ -1,16 +1,14 @@ error[E0271]: type mismatch resolving ` as Iterator>::Item == std::option::Option` --> $DIR/associated-types-issue-20346.rs:34:5 | +LL | fn is_iterator_of>(_: &I) {} + | ------------------------------------------------ required by `is_iterator_of` +... LL | is_iterator_of::, _>(&adapter); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found enum `std::option::Option` | = note: expected type `T` found type `std::option::Option` -note: required by `is_iterator_of` - --> $DIR/associated-types-issue-20346.rs:15:1 - | -LL | fn is_iterator_of>(_: &I) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr index 2926bdae0525b..4a2a6d03c607f 100644 --- a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr +++ b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr @@ -3,28 +3,24 @@ error[E0271]: type mismatch resolving `::Y == i32` | LL | want_y(t); | ^^^^^^ expected associated type, found i32 +... +LL | fn want_y>(t: &T) { } + | ------------------------------ required by `want_y` | = note: expected type `::Y` found type `i32` -note: required by `want_y` - --> $DIR/associated-types-multiple-types-one-trait.rs:44:1 - | -LL | fn want_y>(t: &T) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving `::X == u32` --> $DIR/associated-types-multiple-types-one-trait.rs:18:5 | LL | want_x(t); | ^^^^^^ expected associated type, found u32 +... +LL | fn want_x>(t: &T) { } + | ------------------------------ required by `want_x` | = note: expected type `::X` found type `u32` -note: required by `want_x` - --> $DIR/associated-types-multiple-types-one-trait.rs:42:1 - | -LL | fn want_x>(t: &T) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.stderr b/src/test/ui/associated-types/associated-types-overridden-binding.stderr index a26ee23894f6d..a7238541cd96e 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding.stderr @@ -1,14 +1,10 @@ error[E0284]: type annotations required: cannot resolve `::Item == i32` --> $DIR/associated-types-overridden-binding.rs:4:1 | +LL | trait Foo: Iterator {} + | ------------------------------- required by `Foo` LL | trait Bar: Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: required by `Foo` - --> $DIR/associated-types-overridden-binding.rs:3:1 - | -LL | trait Foo: Iterator {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr index 1405cb1b4736c..a8fcaeac95d5f 100644 --- a/src/test/ui/associated-types/associated-types-path-2.stderr +++ b/src/test/ui/associated-types/associated-types-path-2.stderr @@ -11,14 +11,11 @@ LL | f1(2i32, 4u32); error[E0277]: the trait bound `u32: Foo` is not satisfied --> $DIR/associated-types-path-2.rs:29:5 | +LL | pub fn f1(a: T, x: T::A) {} + | -------------------------------- required by `f1` +... LL | f1(2u32, 4u32); | ^^ the trait `Foo` is not implemented for `u32` - | -note: required by `f1` - --> $DIR/associated-types-path-2.rs:13:1 - | -LL | pub fn f1(a: T, x: T::A) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `u32: Foo` is not satisfied --> $DIR/associated-types-path-2.rs:29:5 @@ -29,14 +26,11 @@ LL | f1(2u32, 4u32); error[E0277]: the trait bound `u32: Foo` is not satisfied --> $DIR/associated-types-path-2.rs:35:5 | +LL | pub fn f1(a: T, x: T::A) {} + | -------------------------------- required by `f1` +... LL | f1(2u32, 4i32); | ^^ the trait `Foo` is not implemented for `u32` - | -note: required by `f1` - --> $DIR/associated-types-path-2.rs:13:1 - | -LL | pub fn f1(a: T, x: T::A) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `u32: Foo` is not satisfied --> $DIR/associated-types-path-2.rs:35:5 diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index cc69e849fe144..22d44888e951b 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -1,16 +1,13 @@ error[E0271]: type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _` --> $DIR/higher-ranked-projection.rs:25:5 | -LL | foo(()); - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime - | -note: required by `foo` - --> $DIR/higher-ranked-projection.rs:14:1 - | LL | / fn foo(_t: T) LL | | where for<'a> &'a T: Mirror LL | | {} - | |__^ + | |__- required by `foo` +... +LL | foo(()); + | ^^^ expected bound lifetime parameter 'a, found concrete lifetime error: aborting due to previous error diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 6b4fff2dc6844..fad90b29c0e6e 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -1,6 +1,9 @@ error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:50:5 | +LL | fn assert_send(_: impl Send) {} + | ---------------------------- required by `assert_send` +... LL | assert_send(local_dropped_before_await()); | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely | @@ -11,15 +14,13 @@ LL | assert_send(local_dropped_before_await()); = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` -note: required by `assert_send` - --> $DIR/async-fn-nonsend.rs:47:1 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:52:5 | +LL | fn assert_send(_: impl Send) {} + | ---------------------------- required by `assert_send` +... LL | assert_send(non_send_temporary_in_match()); | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely | @@ -30,15 +31,13 @@ LL | assert_send(non_send_temporary_in_match()); = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {fn(impl std::fmt::Debug) -> std::option::Option {std::option::Option::::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option, impl std::future::Future, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` -note: required by `assert_send` - --> $DIR/async-fn-nonsend.rs:47:1 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely --> $DIR/async-fn-nonsend.rs:54:5 | +LL | fn assert_send(_: impl Send) {} + | ---------------------------- required by `assert_send` +... LL | assert_send(non_sync_with_method_call()); | ^^^^^^^^^^^ `dyn std::fmt::Write` cannot be sent between threads safely | @@ -51,15 +50,13 @@ LL | assert_send(non_sync_with_method_call()); = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` -note: required by `assert_send` - --> $DIR/async-fn-nonsend.rs:47:1 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely --> $DIR/async-fn-nonsend.rs:54:5 | +LL | fn assert_send(_: impl Send) {} + | ---------------------------- required by `assert_send` +... LL | assert_send(non_sync_with_method_call()); | ^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely | @@ -76,11 +73,6 @@ LL | assert_send(non_sync_with_method_call()); = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` -note: required by `assert_send` - --> $DIR/async-fn-nonsend.rs:47:1 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr index 6cb33f2f2c8c6..15c52f461c183 100644 --- a/src/test/ui/chalkify/type_inference.stderr +++ b/src/test/ui/chalkify/type_inference.stderr @@ -10,17 +10,15 @@ LL | only_foo(x); error[E0277]: the trait bound `{float}: Bar` is not satisfied --> $DIR/type_inference.rs:25:5 | +LL | fn only_bar(_x: T) { } + | -------------------------- required by `only_bar` +... LL | only_bar(x); | ^^^^^^^^ the trait `Bar` is not implemented for `{float}` | = help: the following implementations were found: -note: required by `only_bar` - --> $DIR/type_inference.rs:12:1 - | -LL | fn only_bar(_x: T) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index 40fab4d4edf78..c618c2c550ba1 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -39,53 +39,44 @@ LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); error[E0631]: type mismatch in closure arguments --> $DIR/expect-fn-supply-fn.rs:30:5 | -LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` - | | - | expected signature of `fn(fn(&'a u32), &i32) -> _` - | -note: required by `with_closure_expecting_fn_with_free_region` - --> $DIR/expect-fn-supply-fn.rs:1:1 - | LL | / fn with_closure_expecting_fn_with_free_region(_: F) LL | | where F: for<'a> FnOnce(fn(&'a u32), &i32) LL | | { LL | | } - | |_^ + | |_- required by `with_closure_expecting_fn_with_free_region` +... +LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` + | | + | expected signature of `fn(fn(&'a u32), &i32) -> _` error[E0631]: type mismatch in closure arguments --> $DIR/expect-fn-supply-fn.rs:37:5 | -LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` - | | - | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` - | -note: required by `with_closure_expecting_fn_with_bound_region` - --> $DIR/expect-fn-supply-fn.rs:6:1 - | LL | / fn with_closure_expecting_fn_with_bound_region(_: F) LL | | where F: FnOnce(fn(&u32), &i32) LL | | { LL | | } - | |_^ + | |_- required by `with_closure_expecting_fn_with_bound_region` +... +LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` + | | + | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` error[E0631]: type mismatch in closure arguments --> $DIR/expect-fn-supply-fn.rs:46:5 | -LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` - | | - | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` - | -note: required by `with_closure_expecting_fn_with_bound_region` - --> $DIR/expect-fn-supply-fn.rs:6:1 - | LL | / fn with_closure_expecting_fn_with_bound_region(_: F) LL | | where F: FnOnce(fn(&u32), &i32) LL | | { LL | | } - | |_^ + | |_- required by `with_closure_expecting_fn_with_bound_region` +... +LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` + | | + | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` error: aborting due to 5 previous errors diff --git a/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr b/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr index c9a697496de59..a2b3a66dc4d23 100644 --- a/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr +++ b/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr @@ -1,19 +1,16 @@ error[E0631]: type mismatch in closure arguments --> $DIR/expect-infer-var-appearing-twice.rs:14:5 | -LL | with_closure(|x: u32, y: i32| { - | ^^^^^^^^^^^^ ---------------- found signature of `fn(u32, i32) -> _` - | | - | expected signature of `fn(_, _) -> _` - | -note: required by `with_closure` - --> $DIR/expect-infer-var-appearing-twice.rs:1:1 - | LL | / fn with_closure(_: F) LL | | where F: FnOnce(A, A) LL | | { LL | | } - | |_^ + | |_- required by `with_closure` +... +LL | with_closure(|x: u32, y: i32| { + | ^^^^^^^^^^^^ ---------------- found signature of `fn(u32, i32) -> _` + | | + | expected signature of `fn(_, _) -> _` error: aborting due to previous error diff --git a/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr index 81c4f4e00aba0..51077b1b2922e 100644 --- a/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr +++ b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr @@ -1,6 +1,9 @@ error[E0277]: `F` cannot be sent between threads safely --> $DIR/closure-bounds-cant-promote-superkind-in-struct.rs:5:1 | +LL | struct X where F: FnOnce() + 'static + Send { + | ---------------------------------------------- required by `X` +... LL | / fn foo(blk: F) -> X where F: FnOnce() + 'static { LL | | LL | | return X { field: blk }; @@ -9,11 +12,6 @@ LL | | } | = help: the trait `std::marker::Send` is not implemented for `F` = help: consider adding a `where F: std::marker::Send` bound -note: required by `X` - --> $DIR/closure-bounds-cant-promote-superkind-in-struct.rs:1:1 - | -LL | struct X where F: FnOnce() + 'static + Send { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/closures/closure-bounds-subtype.stderr b/src/test/ui/closures/closure-bounds-subtype.stderr index 3b9fd10af3860..4958bd06d9b16 100644 --- a/src/test/ui/closures/closure-bounds-subtype.stderr +++ b/src/test/ui/closures/closure-bounds-subtype.stderr @@ -1,16 +1,14 @@ error[E0277]: `F` cannot be shared between threads safely --> $DIR/closure-bounds-subtype.rs:13:5 | +LL | fn take_const_owned(_: F) where F: FnOnce() + Sync + Send { + | ------------------------------------------------------------ required by `take_const_owned` +... LL | take_const_owned(f); | ^^^^^^^^^^^^^^^^ `F` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `F` = help: consider adding a `where F: std::marker::Sync` bound -note: required by `take_const_owned` - --> $DIR/closure-bounds-subtype.rs:4:1 - | -LL | fn take_const_owned(_: F) where F: FnOnce() + Sync + Send { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr index eef79421270ce..0733a51233e33 100644 --- a/src/test/ui/consts/too_generic_eval_ice.stderr +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -14,32 +14,28 @@ LL | [5; Self::HOST_SIZE] == [6; 0] error[E0277]: the size for values of type `A` cannot be known at compilation time --> $DIR/too_generic_eval_ice.rs:7:13 | +LL | pub struct Foo(A, B); + | --------------------------- required by `Foo` +... LL | [5; Self::HOST_SIZE] == [6; 0] | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `A` = note: to learn more, visit = help: consider adding a `where A: std::marker::Sized` bound -note: required by `Foo` - --> $DIR/too_generic_eval_ice.rs:1:1 - | -LL | pub struct Foo(A, B); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `B` cannot be known at compilation time --> $DIR/too_generic_eval_ice.rs:7:13 | +LL | pub struct Foo(A, B); + | --------------------------- required by `Foo` +... LL | [5; Self::HOST_SIZE] == [6; 0] | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `B` = note: to learn more, visit = help: consider adding a `where B: std::marker::Sized` bound -note: required by `Foo` - --> $DIR/too_generic_eval_ice.rs:1:1 - | -LL | pub struct Foo(A, B); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/defaulted-never-note.stderr b/src/test/ui/defaulted-never-note.stderr index 45174c322947d..277477a0b0acd 100644 --- a/src/test/ui/defaulted-never-note.stderr +++ b/src/test/ui/defaulted-never-note.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied --> $DIR/defaulted-never-note.rs:26:5 | +LL | fn foo(_t: T) {} + | ----------------------------------------------- required by `foo` +... LL | foo(_x); | ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!` | = note: the trait is implemented for `()`. Possibly this error has been caused by changes to Rust's type-inference algorithm (see: https://github.com/rust-lang/rust/issues/48950 for more info). Consider whether you meant to use the type `()` here instead. -note: required by `foo` - --> $DIR/defaulted-never-note.rs:21:1 - | -LL | fn foo(_t: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/derives/deriving-copyclone.stderr b/src/test/ui/derives/deriving-copyclone.stderr index e6060c269e10a..46b6a0d337695 100644 --- a/src/test/ui/derives/deriving-copyclone.stderr +++ b/src/test/ui/derives/deriving-copyclone.stderr @@ -1,41 +1,35 @@ error[E0277]: the trait bound `C: std::marker::Copy` is not satisfied --> $DIR/deriving-copyclone.rs:31:5 | +LL | fn is_copy(_: T) {} + | ------------------------- required by `is_copy` +... LL | is_copy(B { a: 1, b: C }); | ^^^^^^^ the trait `std::marker::Copy` is not implemented for `C` | = note: required because of the requirements on the impl of `std::marker::Copy` for `B` -note: required by `is_copy` - --> $DIR/deriving-copyclone.rs:18:1 - | -LL | fn is_copy(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `C: std::clone::Clone` is not satisfied --> $DIR/deriving-copyclone.rs:32:5 | +LL | fn is_clone(_: T) {} + | --------------------------- required by `is_clone` +... LL | is_clone(B { a: 1, b: C }); | ^^^^^^^^ the trait `std::clone::Clone` is not implemented for `C` | = note: required because of the requirements on the impl of `std::clone::Clone` for `B` -note: required by `is_clone` - --> $DIR/deriving-copyclone.rs:19:1 - | -LL | fn is_clone(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `D: std::marker::Copy` is not satisfied --> $DIR/deriving-copyclone.rs:35:5 | +LL | fn is_copy(_: T) {} + | ------------------------- required by `is_copy` +... LL | is_copy(B { a: 1, b: D }); | ^^^^^^^ the trait `std::marker::Copy` is not implemented for `D` | = note: required because of the requirements on the impl of `std::marker::Copy` for `B` -note: required by `is_copy` - --> $DIR/deriving-copyclone.rs:18:1 - | -LL | fn is_copy(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index cfb1da037dc07..ea2017f485a7b 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `i8: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:24:5 | +LL | fn bar(&self){} + | ------------- required by `Foo::bar` +... LL | Foo::::bar(&1i8); | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i8` | @@ -10,15 +13,13 @@ LL | Foo::::bar(&1i8); > > > -note: required by `Foo::bar` - --> $DIR/issue-39802-show-5-trait-impls.rs:2:5 - | -LL | fn bar(&self){} - | ^^^^^^^^^^^^^ error[E0277]: the trait bound `u8: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:25:5 | +LL | fn bar(&self){} + | ------------- required by `Foo::bar` +... LL | Foo::::bar(&1u8); | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u8` | @@ -27,15 +28,13 @@ LL | Foo::::bar(&1u8); > > > -note: required by `Foo::bar` - --> $DIR/issue-39802-show-5-trait-impls.rs:2:5 - | -LL | fn bar(&self){} - | ^^^^^^^^^^^^^ error[E0277]: the trait bound `bool: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:26:5 | +LL | fn bar(&self){} + | ------------- required by `Foo::bar` +... LL | Foo::::bar(&true); | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `bool` | @@ -45,11 +44,6 @@ LL | Foo::::bar(&true); > > and 2 others -note: required by `Foo::bar` - --> $DIR/issue-39802-show-5-trait-impls.rs:2:5 - | -LL | fn bar(&self){} - | ^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr index a646d98324e09..745d90a5d4cbf 100644 --- a/src/test/ui/did_you_mean/recursion_limit.stderr +++ b/src/test/ui/did_you_mean/recursion_limit.stderr @@ -1,6 +1,9 @@ error[E0275]: overflow evaluating the requirement `J: std::marker::Send` --> $DIR/recursion_limit.rs:34:5 | +LL | fn is_send() { } + | -------------------- required by `is_send` +... LL | is_send::(); | ^^^^^^^^^^^^ | @@ -14,11 +17,6 @@ LL | is_send::(); = note: required because it appears within the type `C` = note: required because it appears within the type `B` = note: required because it appears within the type `A` -note: required by `is_send` - --> $DIR/recursion_limit.rs:31:1 - | -LL | fn is_send() { } - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0271.stderr b/src/test/ui/error-codes/E0271.stderr index 16c3ab9d7425b..0afcbcc79eee9 100644 --- a/src/test/ui/error-codes/E0271.stderr +++ b/src/test/ui/error-codes/E0271.stderr @@ -1,16 +1,14 @@ error[E0271]: type mismatch resolving `::AssociatedType == u32` --> $DIR/E0271.rs:10:5 | +LL | fn foo(t: T) where T: Trait { + | -------------------------------------------------- required by `foo` +... LL | foo(3_i8); | ^^^ expected reference, found u32 | = note: expected type `&'static str` found type `u32` -note: required by `foo` - --> $DIR/E0271.rs:3:1 - | -LL | fn foo(t: T) where T: Trait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr index 40991cb2297c9..f607a9fbbf269 100644 --- a/src/test/ui/error-codes/E0275.stderr +++ b/src/test/ui/error-codes/E0275.stderr @@ -1,6 +1,9 @@ error[E0275]: overflow evaluating the requirement `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo` --> $DIR/E0275.rs:5:1 | +LL | trait Foo {} + | --------- required by `Foo` +... LL | impl Foo for T where Bar: Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -132,11 +135,6 @@ LL | impl Foo for T where Bar: Foo {} = note: required because of the requirements on the impl of `Foo` for `Bar>>` = note: required because of the requirements on the impl of `Foo` for `Bar>` = note: required because of the requirements on the impl of `Foo` for `Bar` -note: required by `Foo` - --> $DIR/E0275.rs:1:1 - | -LL | trait Foo {} - | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0277-2.stderr b/src/test/ui/error-codes/E0277-2.stderr index a4db1c8b09523..b42849cd84201 100644 --- a/src/test/ui/error-codes/E0277-2.stderr +++ b/src/test/ui/error-codes/E0277-2.stderr @@ -1,6 +1,9 @@ error[E0277]: `*const u8` cannot be sent between threads safely --> $DIR/E0277-2.rs:16:5 | +LL | fn is_send() { } + | --------------------- required by `is_send` +... LL | is_send::(); | ^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely | @@ -8,11 +11,6 @@ LL | is_send::(); = note: required because it appears within the type `Baz` = note: required because it appears within the type `Bar` = note: required because it appears within the type `Foo` -note: required by `is_send` - --> $DIR/E0277-2.rs:13:1 - | -LL | fn is_send() { } - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0277.stderr b/src/test/ui/error-codes/E0277.stderr index e5e416da883de..352102dd38629 100644 --- a/src/test/ui/error-codes/E0277.stderr +++ b/src/test/ui/error-codes/E0277.stderr @@ -13,14 +13,11 @@ LL | fn f(p: Path) { } error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/E0277.rs:17:5 | +LL | fn some_func(foo: T) { + | ---------------------------- required by `some_func` +... LL | some_func(5i32); | ^^^^^^^^^ the trait `Foo` is not implemented for `i32` - | -note: required by `some_func` - --> $DIR/E0277.rs:9:1 - | -LL | fn some_func(foo: T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr index e1f53e592fc85..1d99f99c62383 100644 --- a/src/test/ui/error-codes/E0283.stderr +++ b/src/test/ui/error-codes/E0283.stderr @@ -1,14 +1,11 @@ error[E0283]: type annotations required: cannot resolve `_: Generator` --> $DIR/E0283.rs:18:21 | +LL | fn create() -> u32; + | ------------------- required by `Generator::create` +... LL | let cont: u32 = Generator::create(); | ^^^^^^^^^^^^^^^^^ - | -note: required by `Generator::create` - --> $DIR/E0283.rs:2:5 - | -LL | fn create() -> u32; - | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-should-say-copy-not-pod.stderr b/src/test/ui/error-should-say-copy-not-pod.stderr index 7143f8c914dd0..78d54c3836db4 100644 --- a/src/test/ui/error-should-say-copy-not-pod.stderr +++ b/src/test/ui/error-should-say-copy-not-pod.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied --> $DIR/error-should-say-copy-not-pod.rs:6:5 | +LL | fn check_bound(_: T) {} + | ---------------------------- required by `check_bound` +... LL | check_bound("nocopy".to_string()); | ^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` - | -note: required by `check_bound` - --> $DIR/error-should-say-copy-not-pod.rs:3:1 - | -LL | fn check_bound(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/extern/extern-types-not-sync-send.stderr b/src/test/ui/extern/extern-types-not-sync-send.stderr index bc9d96df776ed..0f32d4489dece 100644 --- a/src/test/ui/extern/extern-types-not-sync-send.stderr +++ b/src/test/ui/extern/extern-types-not-sync-send.stderr @@ -1,28 +1,24 @@ error[E0277]: `A` cannot be shared between threads safely --> $DIR/extern-types-not-sync-send.rs:13:5 | +LL | fn assert_sync() { } + | ---------------------------------- required by `assert_sync` +... LL | assert_sync::(); | ^^^^^^^^^^^^^^^^ `A` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `A` -note: required by `assert_sync` - --> $DIR/extern-types-not-sync-send.rs:9:1 - | -LL | fn assert_sync() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `A` cannot be sent between threads safely --> $DIR/extern-types-not-sync-send.rs:16:5 | +LL | fn assert_send() { } + | ---------------------------------- required by `assert_send` +... LL | assert_send::(); | ^^^^^^^^^^^^^^^^ `A` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `A` -note: required by `assert_send` - --> $DIR/extern-types-not-sync-send.rs:10:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/extern/extern-types-unsized.stderr b/src/test/ui/extern/extern-types-unsized.stderr index 4e4f5550fe833..06527d973e2ab 100644 --- a/src/test/ui/extern/extern-types-unsized.stderr +++ b/src/test/ui/extern/extern-types-unsized.stderr @@ -1,50 +1,47 @@ error[E0277]: the size for values of type `A` cannot be known at compilation time --> $DIR/extern-types-unsized.rs:22:5 | +LL | fn assert_sized() { } + | -------------------- required by `assert_sized` +... LL | assert_sized::(); | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `A` = note: to learn more, visit -note: required by `assert_sized` - --> $DIR/extern-types-unsized.rs:19:1 - | -LL | fn assert_sized() { } - | ^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `A` cannot be known at compilation time --> $DIR/extern-types-unsized.rs:25:5 | +LL | fn assert_sized() { } + | -------------------- required by `assert_sized` +... LL | assert_sized::(); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `Foo`, the trait `std::marker::Sized` is not implemented for `A` = note: to learn more, visit = note: required because it appears within the type `Foo` -note: required by `assert_sized` - --> $DIR/extern-types-unsized.rs:19:1 - | -LL | fn assert_sized() { } - | ^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `A` cannot be known at compilation time --> $DIR/extern-types-unsized.rs:28:5 | +LL | fn assert_sized() { } + | -------------------- required by `assert_sized` +... LL | assert_sized::>(); | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `Bar`, the trait `std::marker::Sized` is not implemented for `A` = note: to learn more, visit = note: required because it appears within the type `Bar` -note: required by `assert_sized` - --> $DIR/extern-types-unsized.rs:19:1 - | -LL | fn assert_sized() { } - | ^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `A` cannot be known at compilation time --> $DIR/extern-types-unsized.rs:31:5 | +LL | fn assert_sized() { } + | -------------------- required by `assert_sized` +... LL | assert_sized::>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | @@ -52,11 +49,6 @@ LL | assert_sized::>>(); = note: to learn more, visit = note: required because it appears within the type `Bar` = note: required because it appears within the type `Bar>` -note: required by `assert_sized` - --> $DIR/extern-types-unsized.rs:19:1 - | -LL | fn assert_sized() { } - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/extern/extern-wrong-value-type.stderr b/src/test/ui/extern/extern-wrong-value-type.stderr index dce33f3d6323d..52fcb90e6de0c 100644 --- a/src/test/ui/extern/extern-wrong-value-type.stderr +++ b/src/test/ui/extern/extern-wrong-value-type.stderr @@ -1,16 +1,14 @@ error[E0277]: expected a `std::ops::Fn<()>` closure, found `extern "C" fn() {f}` --> $DIR/extern-wrong-value-type.rs:9:5 | +LL | fn is_fn(_: F) where F: Fn() {} + | ------------------------------- required by `is_fn` +... LL | is_fn(f); | ^^^^^ expected an `Fn<()>` closure, found `extern "C" fn() {f}` | = help: the trait `std::ops::Fn<()>` is not implemented for `extern "C" fn() {f}` = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ } -note: required by `is_fn` - --> $DIR/extern-wrong-value-type.rs:4:1 - | -LL | fn is_fn(_: F) where F: Fn() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/fmt/send-sync.stderr b/src/test/ui/fmt/send-sync.stderr index 1f698c90cb9a4..599dcfaa72617 100644 --- a/src/test/ui/fmt/send-sync.stderr +++ b/src/test/ui/fmt/send-sync.stderr @@ -1,6 +1,9 @@ error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely --> $DIR/send-sync.rs:8:5 | +LL | fn send(_: T) {} + | ---------------------- required by `send` +... LL | send(format_args!("{:?}", c)); | ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely | @@ -12,15 +15,13 @@ LL | send(format_args!("{:?}", c)); = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]` = note: required because of the requirements on the impl of `std::marker::Send` for `&[std::fmt::ArgumentV1<'_>]` = note: required because it appears within the type `std::fmt::Arguments<'_>` -note: required by `send` - --> $DIR/send-sync.rs:1:1 - | -LL | fn send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely --> $DIR/send-sync.rs:9:5 | +LL | fn sync(_: T) {} + | ---------------------- required by `sync` +... LL | sync(format_args!("{:?}", c)); | ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely | @@ -32,11 +33,6 @@ LL | sync(format_args!("{:?}", c)); = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]` = note: required because it appears within the type `&[std::fmt::ArgumentV1<'_>]` = note: required because it appears within the type `std::fmt::Arguments<'_>` -note: required by `sync` - --> $DIR/send-sync.rs:2:1 - | -LL | fn sync(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/fn/fn-trait-formatting.stderr b/src/test/ui/fn/fn-trait-formatting.stderr index 504bc2605ec38..20d7d9ea5b7a8 100644 --- a/src/test/ui/fn/fn-trait-formatting.stderr +++ b/src/test/ui/fn/fn-trait-formatting.stderr @@ -28,15 +28,13 @@ LL | let _: () = (box || -> isize { unimplemented!() }) as Box` closure, found `{integer}` --> $DIR/fn-trait-formatting.rs:19:5 | +LL | fn needs_fn(x: F) where F: Fn(isize) -> isize {} + | ------------------------------------------------ required by `needs_fn` +... LL | needs_fn(1); | ^^^^^^^^ expected an `Fn<(isize,)>` closure, found `{integer}` | = help: the trait `std::ops::Fn<(isize,)>` is not implemented for `{integer}` -note: required by `needs_fn` - --> $DIR/fn-trait-formatting.rs:3:1 - | -LL | fn needs_fn(x: F) where F: Fn(isize) -> isize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator-yielding-or-returning-itself.stderr index 42591683fe4e3..1049bb6240a24 100644 --- a/src/test/ui/generator-yielding-or-returning-itself.stderr +++ b/src/test/ui/generator-yielding-or-returning-itself.stderr @@ -16,20 +16,18 @@ LL | | }) error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _] as std::ops::Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _]` --> $DIR/generator-yielding-or-returning-itself.rs:28:5 | -LL | want_cyclic_generator_yield(|| { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size - | - = note: closures cannot capture themselves or take themselves as argument; - this error may be the result of a recent compiler bug-fix, - see https://github.com/rust-lang/rust/issues/46062 for more details -note: required by `want_cyclic_generator_yield` - --> $DIR/generator-yielding-or-returning-itself.rs:22:1 - | LL | / pub fn want_cyclic_generator_yield(_: T) LL | | where T: Generator LL | | { LL | | } - | |_^ + | |_- required by `want_cyclic_generator_yield` +... +LL | want_cyclic_generator_yield(|| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size + | + = note: closures cannot capture themselves or take themselves as argument; + this error may be the result of a recent compiler bug-fix, + see https://github.com/rust-lang/rust/issues/46062 for more details error: aborting due to 2 previous errors diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index 7ea9832c99a24..51416ce0d2f7a 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -1,32 +1,28 @@ error[E0277]: `std::cell::Cell` cannot be shared between threads safely --> $DIR/not-send-sync.rs:16:5 | +LL | fn assert_send(_: T) {} + | ----------------------------- required by `main::assert_send` +... LL | assert_send(|| { | ^^^^^^^^^^^ `std::cell::Cell` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell` = note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::Cell` = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 a:&std::cell::Cell _]` -note: required by `main::assert_send` - --> $DIR/not-send-sync.rs:7:5 - | -LL | fn assert_send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::cell::Cell` cannot be shared between threads safely --> $DIR/not-send-sync.rs:9:5 | +LL | fn assert_sync(_: T) {} + | ----------------------------- required by `main::assert_sync` +... LL | assert_sync(|| { | ^^^^^^^^^^^ `std::cell::Cell` cannot be shared between threads safely | = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell` = note: required because it appears within the type `{std::cell::Cell, ()}` = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]` -note: required by `main::assert_sync` - --> $DIR/not-send-sync.rs:6:5 - | -LL | fn assert_sync(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/generator/static-not-unpin.stderr b/src/test/ui/generator/static-not-unpin.stderr index 404d3069f79f3..28a6fac5b85e3 100644 --- a/src/test/ui/generator/static-not-unpin.stderr +++ b/src/test/ui/generator/static-not-unpin.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]: std::marker::Unpin` is not satisfied --> $DIR/static-not-unpin.rs:14:5 | +LL | fn assert_unpin(_: T) { + | ------------------------------- required by `assert_unpin` +... LL | assert_unpin(generator); | ^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]` - | -note: required by `assert_unpin` - --> $DIR/static-not-unpin.rs:7:1 - | -LL | fn assert_unpin(_: T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 20265d66c6f43..e0b968b67645e 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -1,19 +1,17 @@ error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied --> $DIR/hrtb-conflate-regions.rs:27:10 | -LL | fn b() { want_foo2::(); } - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct` - | - = help: the following implementations were found: - > -note: required by `want_foo2` - --> $DIR/hrtb-conflate-regions.rs:8:1 - | LL | / fn want_foo2() LL | | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> LL | | { LL | | } - | |_^ + | |_- required by `want_foo2` +... +LL | fn b() { want_foo2::(); } + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct` + | + = help: the following implementations were found: + > error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr index 7f2ca037f0f49..bc58b8e16aaf2 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr @@ -1,20 +1,18 @@ error[E0277]: the trait bound `(): Trait fn(&'b u32)>` is not satisfied --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 | -LL | foo::<()>(); - | ^^^^^^^^^ the trait `Trait fn(&'b u32)>` is not implemented for `()` - | - = help: the following implementations were found: - <() as Trait> -note: required by `foo` - --> $DIR/hrtb-exists-forall-trait-contravariant.rs:8:1 - | LL | / fn foo() LL | | where LL | | T: Trait fn(&'b u32)>, LL | | { LL | | } - | |_^ + | |_- required by `foo` +... +LL | foo::<()>(); + | ^^^^^^^^^ the trait `Trait fn(&'b u32)>` is not implemented for `()` + | + = help: the following implementations were found: + <() as Trait> error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr index cd5982e7588a7..441f75135f3a4 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr @@ -1,20 +1,18 @@ error[E0277]: the trait bound `(): Trait fn(fn(&'b u32))>` is not satisfied --> $DIR/hrtb-exists-forall-trait-covariant.rs:36:5 | -LL | foo::<()>(); - | ^^^^^^^^^ the trait `Trait fn(fn(&'b u32))>` is not implemented for `()` - | - = help: the following implementations were found: - <() as Trait> -note: required by `foo` - --> $DIR/hrtb-exists-forall-trait-covariant.rs:8:1 - | LL | / fn foo() LL | | where LL | | T: Trait fn(fn(&'b u32))>, LL | | { LL | | } - | |_^ + | |_- required by `foo` +... +LL | foo::<()>(); + | ^^^^^^^^^ the trait `Trait fn(fn(&'b u32))>` is not implemented for `()` + | + = help: the following implementations were found: + <() as Trait> error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index f10e427a545fb..a11949735b9d2 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -1,20 +1,18 @@ error[E0277]: the trait bound `(): Trait fn(std::cell::Cell<&'b u32>)>` is not satisfied --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 | -LL | foo::<()>(); - | ^^^^^^^^^ the trait `Trait fn(std::cell::Cell<&'b u32>)>` is not implemented for `()` - | - = help: the following implementations were found: - <() as Trait)>> -note: required by `foo` - --> $DIR/hrtb-exists-forall-trait-invariant.rs:10:1 - | LL | / fn foo() LL | | where LL | | T: Trait fn(Cell<&'b u32>)>, LL | | { LL | | } - | |_^ + | |_- required by `foo` +... +LL | foo::<()>(); + | ^^^^^^^^^ the trait `Trait fn(std::cell::Cell<&'b u32>)>` is not implemented for `()` + | + = help: the following implementations were found: + <() as Trait)>> error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr index b5d945fe15ca0..0cddd353d679e 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr @@ -1,18 +1,16 @@ error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5 | -LL | want_bar_for_any_ccx(b); - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` - | - = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound -note: required by `want_bar_for_any_ccx` - --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:31:1 - | LL | / fn want_bar_for_any_ccx(b: &B) LL | | where B : for<'ccx> Bar<'ccx> LL | | { LL | | } - | |_^ + | |_- required by `want_bar_for_any_ccx` +... +LL | want_bar_for_any_ccx(b); + | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` + | + = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr index 20a8fd459fa41..6df486ebaff38 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr @@ -1,31 +1,25 @@ error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:18:5 | -LL | want_foo_for_any_tcx(f); - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` - | - = help: consider adding a `where for<'tcx> F: Foo<'tcx>` bound -note: required by `want_foo_for_any_tcx` - --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 - | +LL | want_foo_for_any_tcx(f); + | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` +... LL | / fn want_foo_for_any_tcx(f: &F) LL | | where F : for<'tcx> Foo<'tcx> LL | | { LL | | want_foo_for_some_tcx(f); LL | | want_foo_for_any_tcx(f); LL | | } - | |_^ + | |_- required by `want_foo_for_any_tcx` + | + = help: consider adding a `where for<'tcx> F: Foo<'tcx>` bound error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:35:5 | -LL | want_bar_for_any_ccx(b); - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` - | - = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound -note: required by `want_bar_for_any_ccx` - --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1 - | +LL | want_bar_for_any_ccx(b); + | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` +... LL | / fn want_bar_for_any_ccx(b: &B) LL | | where B : for<'ccx> Bar<'ccx> LL | | { @@ -33,7 +27,9 @@ LL | | want_foo_for_some_tcx(b); ... | LL | | want_bar_for_any_ccx(b); LL | | } - | |_^ + | |_- required by `want_bar_for_any_ccx` + | + = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 115851ddf9385..b2938e541fdd8 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -1,36 +1,32 @@ error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied --> $DIR/hrtb-just-for-static.rs:24:5 | -LL | want_hrtb::() - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt` - | - = help: the following implementations were found: - > -note: required by `want_hrtb` - --> $DIR/hrtb-just-for-static.rs:8:1 - | LL | / fn want_hrtb() LL | | where T : for<'a> Foo<&'a isize> LL | | { LL | | } - | |_^ + | |_- required by `want_hrtb` +... +LL | want_hrtb::() + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt` + | + = help: the following implementations were found: + > error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied --> $DIR/hrtb-just-for-static.rs:30:5 | -LL | want_hrtb::<&'a u32>() - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32` - | - = help: the following implementations were found: - <&'a u32 as Foo<&'a isize>> -note: required by `want_hrtb` - --> $DIR/hrtb-just-for-static.rs:8:1 - | LL | / fn want_hrtb() LL | | where T : for<'a> Foo<&'a isize> LL | | { LL | | } - | |_^ + | |_- required by `want_hrtb` +... +LL | want_hrtb::<&'a u32>() + | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32` + | + = help: the following implementations were found: + <&'a u32 as Foo<&'a isize>> error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr index b308291d5c0eb..57eaf2aad2bc5 100644 --- a/src/test/ui/hrtb/issue-46989.stderr +++ b/src/test/ui/hrtb/issue-46989.stderr @@ -1,16 +1,14 @@ error[E0277]: the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied --> $DIR/issue-46989.rs:40:5 | +LL | fn assert_foo() {} + | ----------------------- required by `assert_foo` +... LL | assert_foo::(); | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)` | = help: the following implementations were found: -note: required by `assert_foo` - --> $DIR/issue-46989.rs:37:1 - | -LL | fn assert_foo() {} - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index 61450d3203cd8..af641a89e7f9c 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -72,16 +72,14 @@ LL | | } error[E0277]: `std::rc::Rc` cannot be sent between threads safely --> $DIR/auto-trait-leak.rs:15:5 | +LL | fn send(_: T) {} + | ---------------------- required by `send` +... LL | send(cycle2().clone()); | ^^^^ `std::rc::Rc` cannot be sent between threads safely | = help: within `impl std::clone::Clone`, the trait `std::marker::Send` is not implemented for `std::rc::Rc` = note: required because it appears within the type `impl std::clone::Clone` -note: required by `send` - --> $DIR/auto-trait-leak.rs:4:1 - | -LL | fn send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr index 19899ff83f7c3..460af7dedbea8 100644 --- a/src/test/ui/impl-trait/auto-trait-leak2.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr @@ -1,32 +1,28 @@ error[E0277]: `std::rc::Rc>` cannot be sent between threads safely --> $DIR/auto-trait-leak2.rs:13:5 | +LL | fn send(_: T) {} + | ---------------------- required by `send` +... LL | send(before()); | ^^^^ `std::rc::Rc>` cannot be sent between threads safely | = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc>` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:7:5: 7:22 p:std::rc::Rc>]` = note: required because it appears within the type `impl std::ops::Fn<(i32,)>` -note: required by `send` - --> $DIR/auto-trait-leak2.rs:10:1 - | -LL | fn send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::rc::Rc>` cannot be sent between threads safely --> $DIR/auto-trait-leak2.rs:16:5 | +LL | fn send(_: T) {} + | ---------------------- required by `send` +... LL | send(after()); | ^^^^ `std::rc::Rc>` cannot be sent between threads safely | = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc>` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22 p:std::rc::Rc>]` = note: required because it appears within the type `impl std::ops::Fn<(i32,)>` -note: required by `send` - --> $DIR/auto-trait-leak2.rs:10:1 - | -LL | fn send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-1920-1.stderr b/src/test/ui/issues/issue-1920-1.stderr index b3ac05031b00f..c62cbb0cf8b96 100644 --- a/src/test/ui/issues/issue-1920-1.stderr +++ b/src/test/ui/issues/issue-1920-1.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `foo::issue_1920::S: std::clone::Clone` is not satisfied --> $DIR/issue-1920-1.rs:12:5 | +LL | fn assert_clone() where T : Clone { } + | ------------------------------------ required by `assert_clone` +... LL | assert_clone::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `foo::issue_1920::S` - | -note: required by `assert_clone` - --> $DIR/issue-1920-1.rs:9:1 - | -LL | fn assert_clone() where T : Clone { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-1920-2.stderr b/src/test/ui/issues/issue-1920-2.stderr index a000a87302bf7..aad076244699a 100644 --- a/src/test/ui/issues/issue-1920-2.stderr +++ b/src/test/ui/issues/issue-1920-2.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `bar::S: std::clone::Clone` is not satisfied --> $DIR/issue-1920-2.rs:10:5 | +LL | fn assert_clone() where T : Clone { } + | ------------------------------------ required by `assert_clone` +... LL | assert_clone::(); | ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `bar::S` - | -note: required by `assert_clone` - --> $DIR/issue-1920-2.rs:7:1 - | -LL | fn assert_clone() where T : Clone { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-1920-3.stderr b/src/test/ui/issues/issue-1920-3.stderr index 62e47a6866e63..4378ea49755a7 100644 --- a/src/test/ui/issues/issue-1920-3.stderr +++ b/src/test/ui/issues/issue-1920-3.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `issue_1920::S: std::clone::Clone` is not satisfied --> $DIR/issue-1920-3.rs:14:5 | +LL | fn assert_clone() where T : Clone { } + | ------------------------------------ required by `assert_clone` +... LL | assert_clone::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `issue_1920::S` - | -note: required by `assert_clone` - --> $DIR/issue-1920-3.rs:11:1 - | -LL | fn assert_clone() where T : Clone { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20005.stderr b/src/test/ui/issues/issue-20005.stderr index e271005e74d1d..2754d6bdd8306 100644 --- a/src/test/ui/issues/issue-20005.stderr +++ b/src/test/ui/issues/issue-20005.stderr @@ -1,6 +1,9 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/issue-20005.rs:8:5 | +LL | trait From { + | --------------- required by `From` +... LL | / fn to( LL | | self LL | | ) -> >::Result where Dst: From { @@ -11,11 +14,6 @@ LL | | } = help: the trait `std::marker::Sized` is not implemented for `Self` = note: to learn more, visit = help: consider adding a `where Self: std::marker::Sized` bound -note: required by `From` - --> $DIR/issue-20005.rs:1:1 - | -LL | trait From { - | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr index 762816c5a98c4..72a8fe4283b56 100644 --- a/src/test/ui/issues/issue-20413.stderr +++ b/src/test/ui/issues/issue-20413.stderr @@ -9,6 +9,9 @@ LL | struct NoData; error[E0275]: overflow evaluating the requirement `NoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo` --> $DIR/issue-20413.rs:8:1 | +LL | trait Foo { + | --------- required by `Foo` +... LL | / impl Foo for T where NoData: Foo { LL | | LL | | fn answer(self) { @@ -146,15 +149,13 @@ LL | | } = note: required because of the requirements on the impl of `Foo` for `NoData>>` = note: required because of the requirements on the impl of `Foo` for `NoData>` = note: required because of the requirements on the impl of `Foo` for `NoData` -note: required by `Foo` - --> $DIR/issue-20413.rs:1:1 - | -LL | trait Foo { - | ^^^^^^^^^ error[E0275]: overflow evaluating the requirement `NoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo` --> $DIR/issue-20413.rs:10:3 | +LL | trait Foo { + | --------- required by `Foo` +... LL | / fn answer(self) { LL | | LL | | let val: NoData = NoData; @@ -289,11 +290,6 @@ LL | | } = note: required because of the requirements on the impl of `Foo` for `NoData>>` = note: required because of the requirements on the impl of `Foo` for `NoData>` = note: required because of the requirements on the impl of `Foo` for `NoData` -note: required by `Foo` - --> $DIR/issue-20413.rs:1:1 - | -LL | trait Foo { - | ^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-21763.stderr b/src/test/ui/issues/issue-21763.stderr index 87c048fdf4c11..99d004a973a26 100644 --- a/src/test/ui/issues/issue-21763.stderr +++ b/src/test/ui/issues/issue-21763.stderr @@ -1,6 +1,9 @@ error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely --> $DIR/issue-21763.rs:9:5 | +LL | fn foo() {} + | ----------------- required by `foo` +... LL | foo::, Rc<()>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely | @@ -9,11 +12,6 @@ LL | foo::, Rc<()>>>(); = note: required because of the requirements on the impl of `std::marker::Send` for `hashbrown::raw::RawTable<(std::rc::Rc<()>, std::rc::Rc<()>)>` = note: required because it appears within the type `hashbrown::map::HashMap, std::rc::Rc<()>, std::collections::hash_map::RandomState>` = note: required because it appears within the type `std::collections::HashMap, std::rc::Rc<()>>` -note: required by `foo` - --> $DIR/issue-21763.rs:6:1 - | -LL | fn foo() {} - | ^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-21837.stderr b/src/test/ui/issues/issue-21837.stderr index 3111d3a47414b..20d02a90315d0 100644 --- a/src/test/ui/issues/issue-21837.stderr +++ b/src/test/ui/issues/issue-21837.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: Bound` is not satisfied --> $DIR/issue-21837.rs:8:9 | +LL | pub struct Foo(T); + | ---------------------------- required by `Foo` +... LL | impl Trait2 for Foo {} | ^^^^^^ the trait `Bound` is not implemented for `T` | = help: consider adding a `where T: Bound` bound -note: required by `Foo` - --> $DIR/issue-21837.rs:2:1 - | -LL | pub struct Foo(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-21974.stderr b/src/test/ui/issues/issue-21974.stderr index 85e59d7bede5f..a6cce7846e81d 100644 --- a/src/test/ui/issues/issue-21974.stderr +++ b/src/test/ui/issues/issue-21974.stderr @@ -1,6 +1,9 @@ error[E0283]: type annotations required: cannot resolve `&'a T: Foo` --> $DIR/issue-21974.rs:10:1 | +LL | trait Foo { + | --------- required by `Foo` +... LL | / fn foo<'a,'b,T>(x: &'a T, y: &'b T) LL | | where &'a T : Foo, LL | | &'b T : Foo @@ -9,12 +12,6 @@ LL | | x.foo(); LL | | y.foo(); LL | | } | |_^ - | -note: required by `Foo` - --> $DIR/issue-21974.rs:6:1 - | -LL | trait Foo { - | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24204.stderr b/src/test/ui/issues/issue-24204.stderr index 8e04c0ddccea6..eb9aada389f8f 100644 --- a/src/test/ui/issues/issue-24204.stderr +++ b/src/test/ui/issues/issue-24204.stderr @@ -1,16 +1,14 @@ error[E0271]: type mismatch resolving `<::A as MultiDispatch>::O == T` --> $DIR/issue-24204.rs:14:1 | +LL | trait Trait: Sized { + | ------------------ required by `Trait` +... LL | fn test>(b: i32) -> T where T::A: MultiDispatch { T::new(b) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found type parameter | = note: expected type `<::A as MultiDispatch>::O` found type `T` -note: required by `Trait` - --> $DIR/issue-24204.rs:7:1 - | -LL | trait Trait: Sized { - | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24424.stderr b/src/test/ui/issues/issue-24424.stderr index 4c6ac0180a873..7ff019a30a864 100644 --- a/src/test/ui/issues/issue-24424.stderr +++ b/src/test/ui/issues/issue-24424.stderr @@ -1,14 +1,11 @@ error[E0283]: type annotations required: cannot resolve `T0: Trait0<'l0>` --> $DIR/issue-24424.rs:4:1 | +LL | trait Trait0<'l0> {} + | ----------------- required by `Trait0` +LL | LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: required by `Trait0` - --> $DIR/issue-24424.rs:2:1 - | -LL | trait Trait0<'l0> {} - | ^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-25076.stderr b/src/test/ui/issues/issue-25076.stderr index 435ab13edada5..b583a6b54bf9f 100644 --- a/src/test/ui/issues/issue-25076.stderr +++ b/src/test/ui/issues/issue-25076.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `(): InOut<_>` is not satisfied --> $DIR/issue-25076.rs:10:5 | +LL | fn do_fold>(init: B, f: F) {} + | ------------------------------------------------ required by `do_fold` +... LL | do_fold(bot(), ()); | ^^^^^^^ the trait `InOut<_>` is not implemented for `()` - | -note: required by `do_fold` - --> $DIR/issue-25076.rs:5:1 - | -LL | fn do_fold>(init: B, f: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-29147.stderr b/src/test/ui/issues/issue-29147.stderr index 3b42186b25138..0dc9b0c9e10cd 100644 --- a/src/test/ui/issues/issue-29147.stderr +++ b/src/test/ui/issues/issue-29147.stderr @@ -1,14 +1,11 @@ error[E0283]: type annotations required: cannot resolve `S5<_>: Foo` --> $DIR/issue-29147.rs:21:13 | +LL | trait Foo { fn xxx(&self); } + | -------------- required by `Foo::xxx` +... LL | let _ = >::xxx; | ^^^^^^^^^^^^ - | -note: required by `Foo::xxx` - --> $DIR/issue-29147.rs:10:13 - | -LL | trait Foo { fn xxx(&self); } - | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-32963.stderr b/src/test/ui/issues/issue-32963.stderr index a31a74a07f46e..2960f4e598997 100644 --- a/src/test/ui/issues/issue-32963.stderr +++ b/src/test/ui/issues/issue-32963.stderr @@ -12,14 +12,11 @@ LL | size_of_copy::(); error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied --> $DIR/issue-32963.rs:8:5 | +LL | fn size_of_copy() -> usize { mem::size_of::() } + | ------------------------------------------ required by `size_of_copy` +... LL | size_of_copy::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `dyn Misc` - | -note: required by `size_of_copy` - --> $DIR/issue-32963.rs:5:1 - | -LL | fn size_of_copy() -> usize { mem::size_of::() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-39970.stderr b/src/test/ui/issues/issue-39970.stderr index e4f158706457c..f15f771fa9f6e 100644 --- a/src/test/ui/issues/issue-39970.stderr +++ b/src/test/ui/issues/issue-39970.stderr @@ -1,17 +1,15 @@ error[E0271]: type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()` --> $DIR/issue-39970.rs:19:5 | +LL | fn visit() {} + | ---------- required by `Visit::visit` +... LL | <() as Visit>::visit(); | ^^^^^^^^^^^^^^^^^^^^ expected &(), found () | = note: expected type `&()` found type `()` = note: required because of the requirements on the impl of `Visit` for `()` -note: required by `Visit::visit` - --> $DIR/issue-39970.rs:6:5 - | -LL | fn visit() {} - | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-40827.stderr b/src/test/ui/issues/issue-40827.stderr index 96b411bfb1d22..9131120671f4c 100644 --- a/src/test/ui/issues/issue-40827.stderr +++ b/src/test/ui/issues/issue-40827.stderr @@ -1,6 +1,9 @@ error[E0277]: `std::rc::Rc` cannot be sent between threads safely --> $DIR/issue-40827.rs:14:5 | +LL | fn f(_: T) {} + | ------------------- required by `f` +... LL | f(Foo(Arc::new(Bar::B(None)))); | ^ `std::rc::Rc` cannot be sent between threads safely | @@ -8,15 +11,13 @@ LL | f(Foo(Arc::new(Bar::B(None)))); = note: required because it appears within the type `Bar` = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc` = note: required because it appears within the type `Foo` -note: required by `f` - --> $DIR/issue-40827.rs:11:1 - | -LL | fn f(_: T) {} - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::rc::Rc` cannot be shared between threads safely --> $DIR/issue-40827.rs:14:5 | +LL | fn f(_: T) {} + | ------------------- required by `f` +... LL | f(Foo(Arc::new(Bar::B(None)))); | ^ `std::rc::Rc` cannot be shared between threads safely | @@ -24,11 +25,6 @@ LL | f(Foo(Arc::new(Bar::B(None)))); = note: required because it appears within the type `Bar` = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc` = note: required because it appears within the type `Foo` -note: required by `f` - --> $DIR/issue-40827.rs:11:1 - | -LL | fn f(_: T) {} - | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-43623.stderr b/src/test/ui/issues/issue-43623.stderr index b5674105f75d2..d843629e8a26f 100644 --- a/src/test/ui/issues/issue-43623.stderr +++ b/src/test/ui/issues/issue-43623.stderr @@ -1,41 +1,31 @@ error[E0631]: type mismatch in function arguments --> $DIR/issue-43623.rs:14:5 | -LL | break_me::; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | expected signature of `for<'b> fn(>::Assoc) -> _` - | found signature of `fn(_) -> _` - | -note: required by `break_me` - --> $DIR/issue-43623.rs:11:1 - | LL | / pub fn break_me(f: F) LL | | where T: for<'b> Trait<'b>, LL | | F: for<'b> FnMut(>::Assoc) { LL | | break_me::; + | | ^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected signature of `for<'b> fn(>::Assoc) -> _` + | | found signature of `fn(_) -> _` LL | | LL | | LL | | } - | |_^ + | |_- required by `break_me` error[E0271]: type mismatch resolving `for<'b> >::Assoc,)>>::Output == ()` --> $DIR/issue-43623.rs:14:5 | -LL | break_me::; - | ^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'b, found concrete lifetime - | -note: required by `break_me` - --> $DIR/issue-43623.rs:11:1 - | LL | / pub fn break_me(f: F) LL | | where T: for<'b> Trait<'b>, LL | | F: for<'b> FnMut(>::Assoc) { LL | | break_me::; + | | ^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'b, found concrete lifetime LL | | LL | | LL | | } - | |_^ + | |_- required by `break_me` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-47706.stderr b/src/test/ui/issues/issue-47706.stderr index fa2e00cde4dff..c47eebb8e5c07 100644 --- a/src/test/ui/issues/issue-47706.stderr +++ b/src/test/ui/issues/issue-47706.stderr @@ -10,21 +10,18 @@ LL | self.foo.map(Foo::new) error[E0593]: function is expected to take 0 arguments, but it takes 1 argument --> $DIR/issue-47706.rs:27:5 | -LL | Bar(i32), - | -------- takes 1 argument +LL | Bar(i32), + | -------- takes 1 argument ... -LL | foo(Qux::Bar); - | ^^^ expected function that takes 0 arguments - | -note: required by `foo` - --> $DIR/issue-47706.rs:20:1 - | LL | / fn foo(f: F) LL | | where LL | | F: Fn(), LL | | { LL | | } - | |_^ + | |_- required by `foo` +... +LL | foo(Qux::Bar); + | ^^^ expected function that takes 0 arguments error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr index a79b1959dca2f..a977ba392769f 100644 --- a/src/test/ui/issues/issue-60283.stderr +++ b/src/test/ui/issues/issue-60283.stderr @@ -1,33 +1,27 @@ error[E0631]: type mismatch in function arguments --> $DIR/issue-60283.rs:14:5 | -LL | foo((), drop) - | ^^^ - | | - | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` - | found signature of `fn(_) -> _` - | -note: required by `foo` - --> $DIR/issue-60283.rs:9:1 - | LL | / pub fn foo(_: T, _: F) LL | | where T: for<'a> Trait<'a>, LL | | F: for<'a> FnMut(>::Item) {} - | |_________________________________________________^ + | |_________________________________________________- required by `foo` +... +LL | foo((), drop) + | ^^^ + | | + | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` + | found signature of `fn(_) -> _` error[E0271]: type mismatch resolving `for<'a> } as std::ops::FnOnce<(<() as Trait<'a>>::Item,)>>::Output == ()` --> $DIR/issue-60283.rs:14:5 | -LL | foo((), drop) - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime - | -note: required by `foo` - --> $DIR/issue-60283.rs:9:1 - | LL | / pub fn foo(_: T, _: F) LL | | where T: for<'a> Trait<'a>, LL | | F: for<'a> FnMut(>::Item) {} - | |_________________________________________________^ + | |_________________________________________________- required by `foo` +... +LL | foo((), drop) + | ^^^ expected bound lifetime parameter 'a, found concrete lifetime error: aborting due to 2 previous errors diff --git a/src/test/ui/iterators/bound.stderr b/src/test/ui/iterators/bound.stderr index 14057387c4f40..92a91ff4cb1ba 100644 --- a/src/test/ui/iterators/bound.stderr +++ b/src/test/ui/iterators/bound.stderr @@ -1,16 +1,13 @@ error[E0277]: `u8` is not an iterator --> $DIR/bound.rs:2:10 | +LL | struct S(I); + | ------------------------- required by `S` LL | struct T(S); | ^^^^^ `u8` is not an iterator | = help: the trait `std::iter::Iterator` is not implemented for `u8` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` -note: required by `S` - --> $DIR/bound.rs:1:1 - | -LL | struct S(I); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-copy.stderr b/src/test/ui/kindck/kindck-copy.stderr index 929a807656209..1fe59460e057f 100644 --- a/src/test/ui/kindck/kindck-copy.stderr +++ b/src/test/ui/kindck/kindck-copy.stderr @@ -1,138 +1,107 @@ error[E0277]: the trait bound `&'static mut isize: std::marker::Copy` is not satisfied --> $DIR/kindck-copy.rs:27:5 | +LL | fn assert_copy() { } + | ------------------------ required by `assert_copy` +... LL | assert_copy::<&'static mut isize>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'static mut isize` | = help: the following implementations were found: -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `&'a mut isize: std::marker::Copy` is not satisfied --> $DIR/kindck-copy.rs:28:5 | +LL | fn assert_copy() { } + | ------------------------ required by `assert_copy` +... LL | assert_copy::<&'a mut isize>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'a mut isize` | = help: the following implementations were found: -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::boxed::Box: std::marker::Copy` is not satisfied --> $DIR/kindck-copy.rs:31:5 | +LL | fn assert_copy() { } + | ------------------------ required by `assert_copy` +... LL | assert_copy::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied --> $DIR/kindck-copy.rs:32:5 | +LL | fn assert_copy() { } + | ------------------------ required by `assert_copy` +... LL | assert_copy::(); | ^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::vec::Vec: std::marker::Copy` is not satisfied --> $DIR/kindck-copy.rs:33:5 | +LL | fn assert_copy() { } + | ------------------------ required by `assert_copy` +... LL | assert_copy:: >(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::vec::Vec` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::boxed::Box<&'a mut isize>: std::marker::Copy` is not satisfied --> $DIR/kindck-copy.rs:34:5 | +LL | fn assert_copy() { } + | ------------------------ required by `assert_copy` +... LL | assert_copy::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<&'a mut isize>` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::boxed::Box: std::marker::Copy` is not satisfied --> $DIR/kindck-copy.rs:42:5 | +LL | fn assert_copy() { } + | ------------------------ required by `assert_copy` +... LL | assert_copy::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::boxed::Box: std::marker::Copy` is not satisfied --> $DIR/kindck-copy.rs:43:5 | +LL | fn assert_copy() { } + | ------------------------ required by `assert_copy` +... LL | assert_copy::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `&'a mut (dyn Dummy + std::marker::Send + 'a): std::marker::Copy` is not satisfied --> $DIR/kindck-copy.rs:46:5 | +LL | fn assert_copy() { } + | ------------------------ required by `assert_copy` +... LL | assert_copy::<&'a mut (dyn Dummy + Send)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'a mut (dyn Dummy + std::marker::Send + 'a)` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `MyNoncopyStruct: std::marker::Copy` is not satisfied --> $DIR/kindck-copy.rs:64:5 | +LL | fn assert_copy() { } + | ------------------------ required by `assert_copy` +... LL | assert_copy::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `MyNoncopyStruct` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::rc::Rc: std::marker::Copy` is not satisfied --> $DIR/kindck-copy.rs:67:5 | +LL | fn assert_copy() { } + | ------------------------ required by `assert_copy` +... LL | assert_copy::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::rc::Rc` - | -note: required by `assert_copy` - --> $DIR/kindck-copy.rs:5:1 - | -LL | fn assert_copy() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 11 previous errors diff --git a/src/test/ui/kindck/kindck-impl-type-params-2.stderr b/src/test/ui/kindck/kindck-impl-type-params-2.stderr index bd971c903727b..6d599423d2548 100644 --- a/src/test/ui/kindck/kindck-impl-type-params-2.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params-2.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied --> $DIR/kindck-impl-type-params-2.rs:13:5 | +LL | fn take_param(foo: &T) { } + | ----------------------------- required by `take_param` +... LL | take_param(&x); | ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<{integer}>` | = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>` -note: required by `take_param` - --> $DIR/kindck-impl-type-params-2.rs:9:1 - | -LL | fn take_param(foo: &T) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.stderr index 1e719e2608425..a53063157fc8e 100644 --- a/src/test/ui/kindck/kindck-inherited-copy-bound.stderr +++ b/src/test/ui/kindck/kindck-inherited-copy-bound.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied --> $DIR/kindck-inherited-copy-bound.rs:18:5 | +LL | fn take_param(foo: &T) { } + | ----------------------------- required by `take_param` +... LL | take_param(&x); | ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<{integer}>` | = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>` -note: required by `take_param` - --> $DIR/kindck-inherited-copy-bound.rs:14:1 - | -LL | fn take_param(foo: &T) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/kindck-inherited-copy-bound.rs:24:19 diff --git a/src/test/ui/kindck/kindck-nonsendable-1.stderr b/src/test/ui/kindck/kindck-nonsendable-1.stderr index 2aacd2741d388..6d60de888c98d 100644 --- a/src/test/ui/kindck/kindck-nonsendable-1.stderr +++ b/src/test/ui/kindck/kindck-nonsendable-1.stderr @@ -1,16 +1,14 @@ error[E0277]: `std::rc::Rc` cannot be sent between threads safely --> $DIR/kindck-nonsendable-1.rs:9:5 | +LL | fn bar(_: F) { } + | ------------------------------- required by `bar` +... LL | bar(move|| foo(x)); | ^^^ `std::rc::Rc` cannot be sent between threads safely | = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc` = note: required because it appears within the type `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc]` -note: required by `bar` - --> $DIR/kindck-nonsendable-1.rs:5:1 - | -LL | fn bar(_: F) { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-send-object.stderr b/src/test/ui/kindck/kindck-send-object.stderr index c9aadd85a53f2..3ca2d730cbae9 100644 --- a/src/test/ui/kindck/kindck-send-object.stderr +++ b/src/test/ui/kindck/kindck-send-object.stderr @@ -1,31 +1,27 @@ error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely --> $DIR/kindck-send-object.rs:12:5 | +LL | fn assert_send() { } + | ------------------------ required by `assert_send` +... LL | assert_send::<&'static (dyn Dummy + 'static)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'static)` = note: required because of the requirements on the impl of `std::marker::Send` for `&'static (dyn Dummy + 'static)` -note: required by `assert_send` - --> $DIR/kindck-send-object.rs:5:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dyn Dummy` cannot be sent between threads safely --> $DIR/kindck-send-object.rs:17:5 | +LL | fn assert_send() { } + | ------------------------ required by `assert_send` +... LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dyn Dummy` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique` = note: required because it appears within the type `std::boxed::Box` -note: required by `assert_send` - --> $DIR/kindck-send-object.rs:5:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/kindck/kindck-send-object1.stderr b/src/test/ui/kindck/kindck-send-object1.stderr index 757b41ab6cb7e..0f5f7e0890b23 100644 --- a/src/test/ui/kindck/kindck-send-object1.stderr +++ b/src/test/ui/kindck/kindck-send-object1.stderr @@ -1,16 +1,14 @@ error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely --> $DIR/kindck-send-object1.rs:10:5 | +LL | fn assert_send() { } + | -------------------------------- required by `assert_send` +... LL | assert_send::<&'a dyn Dummy>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'a)` = note: required because of the requirements on the impl of `std::marker::Send` for `&'a (dyn Dummy + 'a)` -note: required by `assert_send` - --> $DIR/kindck-send-object1.rs:5:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0477]: the type `&'a (dyn Dummy + std::marker::Sync + 'a)` does not fulfill the required lifetime --> $DIR/kindck-send-object1.rs:14:5 @@ -23,17 +21,15 @@ LL | assert_send::<&'a (dyn Dummy + Sync)>(); error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely --> $DIR/kindck-send-object1.rs:29:5 | +LL | fn assert_send() { } + | -------------------------------- required by `assert_send` +... LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `(dyn Dummy + 'a)` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(dyn Dummy + 'a)>` = note: required because it appears within the type `std::boxed::Box<(dyn Dummy + 'a)>` -note: required by `assert_send` - --> $DIR/kindck-send-object1.rs:5:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/kindck/kindck-send-object2.stderr b/src/test/ui/kindck/kindck-send-object2.stderr index c1c9db9da839a..72cd985cc8639 100644 --- a/src/test/ui/kindck/kindck-send-object2.stderr +++ b/src/test/ui/kindck/kindck-send-object2.stderr @@ -1,31 +1,27 @@ error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely --> $DIR/kindck-send-object2.rs:7:5 | +LL | fn assert_send() { } + | ------------------------ required by `assert_send` +... LL | assert_send::<&'static dyn Dummy>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'static)` = note: required because of the requirements on the impl of `std::marker::Send` for `&'static (dyn Dummy + 'static)` -note: required by `assert_send` - --> $DIR/kindck-send-object2.rs:3:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dyn Dummy` cannot be sent between threads safely --> $DIR/kindck-send-object2.rs:12:5 | +LL | fn assert_send() { } + | ------------------------ required by `assert_send` +... LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dyn Dummy` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique` = note: required because it appears within the type `std::boxed::Box` -note: required by `assert_send` - --> $DIR/kindck-send-object2.rs:3:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/kindck/kindck-send-owned.stderr b/src/test/ui/kindck/kindck-send-owned.stderr index 75c757dc54646..ee919f02d6537 100644 --- a/src/test/ui/kindck/kindck-send-owned.stderr +++ b/src/test/ui/kindck/kindck-send-owned.stderr @@ -1,17 +1,15 @@ error[E0277]: `*mut u8` cannot be sent between threads safely --> $DIR/kindck-send-owned.rs:12:5 | +LL | fn assert_send() { } + | ------------------------ required by `assert_send` +... LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut u8` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `*mut u8` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<*mut u8>` = note: required because it appears within the type `std::boxed::Box<*mut u8>` -note: required by `assert_send` - --> $DIR/kindck-send-owned.rs:3:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-send-unsafe.stderr b/src/test/ui/kindck/kindck-send-unsafe.stderr index 2fbb07a0df51a..a87e1c7db2a2e 100644 --- a/src/test/ui/kindck/kindck-send-unsafe.stderr +++ b/src/test/ui/kindck/kindck-send-unsafe.stderr @@ -1,15 +1,13 @@ error[E0277]: `*mut &'a isize` cannot be sent between threads safely --> $DIR/kindck-send-unsafe.rs:6:5 | +LL | fn assert_send() { } + | ------------------------ required by `assert_send` +... LL | assert_send::<*mut &'a isize>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut &'a isize` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `*mut &'a isize` -note: required by `assert_send` - --> $DIR/kindck-send-unsafe.rs:3:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr b/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr index f4a52a65af6aa..4e79fbdeadc5c 100644 --- a/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr +++ b/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `NotDebugOrDisplay: Marker` is not satisfied --> $DIR/overlap-marker-trait.rs:27:5 | +LL | fn is_marker() { } + | ------------------------- required by `is_marker` +... LL | is_marker::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay` - | -note: required by `is_marker` - --> $DIR/overlap-marker-trait.rs:15:1 - | -LL | fn is_marker() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/E0631.stderr b/src/test/ui/mismatched_types/E0631.stderr index 8662bb7795382..319eb86480af5 100644 --- a/src/test/ui/mismatched_types/E0631.stderr +++ b/src/test/ui/mismatched_types/E0631.stderr @@ -1,60 +1,48 @@ error[E0631]: type mismatch in closure arguments --> $DIR/E0631.rs:7:5 | +LL | fn foo(_: F) {} + | -------------------------- required by `foo` +... LL | foo(|_: isize| {}); | ^^^ ---------- found signature of `fn(isize) -> _` | | | expected signature of `fn(usize) -> _` - | -note: required by `foo` - --> $DIR/E0631.rs:3:1 - | -LL | fn foo(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments --> $DIR/E0631.rs:8:5 | +LL | fn bar>(_: F) {} + | -------------------------- required by `bar` +... LL | bar(|_: isize| {}); | ^^^ ---------- found signature of `fn(isize) -> _` | | | expected signature of `fn(usize) -> _` - | -note: required by `bar` - --> $DIR/E0631.rs:4:1 - | -LL | fn bar>(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in function arguments --> $DIR/E0631.rs:9:5 | +LL | fn foo(_: F) {} + | -------------------------- required by `foo` +... LL | fn f(_: u64) {} | ------------ found signature of `fn(u64) -> _` ... LL | foo(f); | ^^^ expected signature of `fn(usize) -> _` - | -note: required by `foo` - --> $DIR/E0631.rs:3:1 - | -LL | fn foo(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in function arguments --> $DIR/E0631.rs:10:5 | +LL | fn bar>(_: F) {} + | -------------------------- required by `bar` +LL | fn main() { LL | fn f(_: u64) {} | ------------ found signature of `fn(u64) -> _` ... LL | bar(f); | ^^^ expected signature of `fn(usize) -> _` - | -note: required by `bar` - --> $DIR/E0631.rs:4:1 - | -LL | fn bar>(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 25d5d25ec1deb..b7b5b50b0b4e4 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -45,16 +45,13 @@ LL | [1, 2, 3].sort_by(|tuple, tuple2| panic!()); error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:13:5 | +LL | fn f>(_: F) {} + | ------------------------ required by `f` +... LL | f(|| panic!()); | ^ -- takes 0 arguments | | | expected closure that takes 1 argument - | -note: required by `f` - --> $DIR/closure-arg-count.rs:3:1 - | -LL | fn f>(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the closure to take and ignore the expected argument | LL | f(|_| panic!()); @@ -63,16 +60,13 @@ LL | f(|_| panic!()); error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:15:5 | +LL | fn f>(_: F) {} + | ------------------------ required by `f` +... LL | f( move || panic!()); | ^ ---------- takes 0 arguments | | | expected closure that takes 1 argument - | -note: required by `f` - --> $DIR/closure-arg-count.rs:3:1 - | -LL | fn f>(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the closure to take and ignore the expected argument | LL | f( move |_| panic!()); @@ -148,14 +142,10 @@ error[E0593]: function is expected to take 0 arguments, but it takes 1 argument LL | call(Foo); | ^^^^ expected function that takes 0 arguments ... +LL | fn call(_: F) where F: FnOnce() -> R {} + | ------------------------------------------ required by `call` LL | struct Foo(u8); | --------------- takes 1 argument - | -note: required by `call` - --> $DIR/closure-arg-count.rs:42:1 - | -LL | fn call(_: F) where F: FnOnce() -> R {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 14 previous errors diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index d4ccf8d451c12..2a65759dd17f8 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -25,29 +25,23 @@ LL | a.iter().map(|_: (u16, u16)| 45); error[E0631]: type mismatch in function arguments --> $DIR/closure-arg-type-mismatch.rs:10:5 | +LL | fn baz(_: F) {} + | ------------------------------ required by `baz` +LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); | ^^^ | | | expected signature of `for<'r> fn(*mut &'r u32) -> _` | found signature of `fn(*mut &'a u32) -> _` - | -note: required by `baz` - --> $DIR/closure-arg-type-mismatch.rs:8:1 - | -LL | fn baz(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving `for<'r> >::Output == ()` --> $DIR/closure-arg-type-mismatch.rs:10:5 | +LL | fn baz(_: F) {} + | ------------------------------ required by `baz` +LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); | ^^^ expected bound lifetime parameter, found concrete lifetime - | -note: required by `baz` - --> $DIR/closure-arg-type-mismatch.rs:8:1 - | -LL | fn baz(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 7161f6979087a..0fe4909eaa778 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -1,30 +1,26 @@ error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.rs:8:9: 8:15] as std::ops::FnOnce<(&'r (),)>>::Output == ()` --> $DIR/closure-mismatch.rs:8:5 | +LL | fn baz(_: T) {} + | -------------------- required by `baz` +... LL | baz(|_| ()); | ^^^ expected bound lifetime parameter, found concrete lifetime | = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` -note: required by `baz` - --> $DIR/closure-mismatch.rs:5:1 - | -LL | fn baz(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments --> $DIR/closure-mismatch.rs:8:5 | +LL | fn baz(_: T) {} + | -------------------- required by `baz` +... LL | baz(|_| ()); | ^^^ ------ found signature of `fn(_) -> _` | | | expected signature of `for<'r> fn(&'r ()) -> _` | = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` -note: required by `baz` - --> $DIR/closure-mismatch.rs:5:1 - | -LL | fn baz(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr index c15d6620e18da..d4db7bda06e7e 100644 --- a/src/test/ui/mismatched_types/fn-variance-1.stderr +++ b/src/test/ui/mismatched_types/fn-variance-1.stderr @@ -3,15 +3,12 @@ error[E0631]: type mismatch in function arguments | LL | fn takes_mut(x: &mut isize) { } | --------------------------- found signature of `for<'r> fn(&'r mut isize) -> _` +LL | +LL | fn apply(t: T, f: F) where F: FnOnce(T) { + | --------------------------------------------- required by `apply` ... LL | apply(&3, takes_mut); | ^^^^^ expected signature of `fn(&{integer}) -> _` - | -note: required by `apply` - --> $DIR/fn-variance-1.rs:5:1 - | -LL | fn apply(t: T, f: F) where F: FnOnce(T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in function arguments --> $DIR/fn-variance-1.rs:15:5 @@ -19,14 +16,11 @@ error[E0631]: type mismatch in function arguments LL | fn takes_imm(x: &isize) { } | ----------------------- found signature of `for<'r> fn(&'r isize) -> _` ... +LL | fn apply(t: T, f: F) where F: FnOnce(T) { + | --------------------------------------------- required by `apply` +... LL | apply(&mut 3, takes_imm); | ^^^^^ expected signature of `fn(&mut {integer}) -> _` - | -note: required by `apply` - --> $DIR/fn-variance-1.rs:5:1 - | -LL | fn apply(t: T, f: F) where F: FnOnce(T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr index 47aa3c21f5301..53c9fcd70a23d 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -1,17 +1,14 @@ error[E0631]: type mismatch in closure arguments --> $DIR/unboxed-closures-vtable-mismatch.rs:15:13 | +LL | fn call_itisize>(y: isize, mut f: F) -> isize { + | -------------------------------------------------------------------- required by `call_it` +... LL | let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y }); | ----------------------------- found signature of `fn(usize, isize) -> _` LL | LL | let z = call_it(3, f); | ^^^^^^^ expected signature of `fn(isize, isize) -> _` - | -note: required by `call_it` - --> $DIR/unboxed-closures-vtable-mismatch.rs:7:1 - | -LL | fn call_itisize>(y: isize, mut f: F) -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/mut/mutable-enum-indirect.stderr b/src/test/ui/mut/mutable-enum-indirect.stderr index 1268e487f333d..4efb10b56290e 100644 --- a/src/test/ui/mut/mutable-enum-indirect.stderr +++ b/src/test/ui/mut/mutable-enum-indirect.stderr @@ -1,17 +1,15 @@ error[E0277]: `NoSync` cannot be shared between threads safely --> $DIR/mutable-enum-indirect.rs:17:5 | +LL | fn bar(_: T) {} + | --------------------- required by `bar` +... LL | bar(&x); | ^^^ `NoSync` cannot be shared between threads safely | = help: within `&Foo`, the trait `std::marker::Sync` is not implemented for `NoSync` = note: required because it appears within the type `Foo` = note: required because it appears within the type `&Foo` -note: required by `bar` - --> $DIR/mutable-enum-indirect.rs:13:1 - | -LL | fn bar(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/mutexguard-sync.stderr b/src/test/ui/mutexguard-sync.stderr index d1f7d13937578..4a93c9f09b788 100644 --- a/src/test/ui/mutexguard-sync.stderr +++ b/src/test/ui/mutexguard-sync.stderr @@ -1,16 +1,14 @@ error[E0277]: `std::cell::Cell` cannot be shared between threads safely --> $DIR/mutexguard-sync.rs:11:5 | +LL | fn test_sync(_t: T) {} + | ---------------------------- required by `test_sync` +... LL | test_sync(guard); | ^^^^^^^^^ `std::cell::Cell` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell` = note: required because of the requirements on the impl of `std::marker::Sync` for `std::sync::MutexGuard<'_, std::cell::Cell>` -note: required by `test_sync` - --> $DIR/mutexguard-sync.rs:5:1 - | -LL | fn test_sync(_t: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index ef2d0d87f09d5..39aaddb390caa 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -69,530 +69,398 @@ LL | use namespace_mix::xm8::V; error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:33:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m1::S{}); | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::S: Impossible` is not satisfied --> $DIR/namespace-mix.rs:35:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m2::S{}); | ^^^^^ the trait `Impossible` is not implemented for `c::S` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:36:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m2::S); | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:39:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm1::S{}); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::S: Impossible` is not satisfied --> $DIR/namespace-mix.rs:41:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm2::S{}); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:42:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm2::S); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:55:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m3::TS{}); | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `fn() -> c::TS {c::TS}: Impossible` is not satisfied --> $DIR/namespace-mix.rs:56:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m3::TS); | ^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::TS: Impossible` is not satisfied --> $DIR/namespace-mix.rs:57:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m4::TS{}); | ^^^^^ the trait `Impossible` is not implemented for `c::TS` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:58:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m4::TS); | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:61:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm3::TS{}); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}: Impossible` is not satisfied --> $DIR/namespace-mix.rs:62:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm3::TS); | ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::TS: Impossible` is not satisfied --> $DIR/namespace-mix.rs:63:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm4::TS{}); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:64:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm4::TS); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:77:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m5::US{}); | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::US: Impossible` is not satisfied --> $DIR/namespace-mix.rs:78:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m5::US); | ^^^^^ the trait `Impossible` is not implemented for `c::US` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::US: Impossible` is not satisfied --> $DIR/namespace-mix.rs:79:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m6::US{}); | ^^^^^ the trait `Impossible` is not implemented for `c::US` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:80:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m6::US); | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:83:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm5::US{}); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfied --> $DIR/namespace-mix.rs:84:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm5::US); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfied --> $DIR/namespace-mix.rs:85:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm6::US{}); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:86:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm6::US); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:99:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m7::V{}); | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:101:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m8::V{}); | ^^^^^ the trait `Impossible` is not implemented for `c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:102:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m8::V); | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:105:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm7::V{}); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:107:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm8::V{}); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:108:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm8::V); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:121:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m9::TV{}); | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `fn() -> c::E {c::E::TV}: Impossible` is not satisfied --> $DIR/namespace-mix.rs:122:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(m9::TV); | ^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:123:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(mA::TV{}); | ^^^^^ the trait `Impossible` is not implemented for `c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:124:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(mA::TV); | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:127:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm9::TV{}); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}: Impossible` is not satisfied --> $DIR/namespace-mix.rs:128:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xm9::TV); | ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:129:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xmA::TV{}); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:130:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xmA::TV); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:143:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(mB::UV{}); | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:144:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(mB::UV); | ^^^^^ the trait `Impossible` is not implemented for `c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:145:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(mC::UV{}); | ^^^^^ the trait `Impossible` is not implemented for `c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:146:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(mC::UV); | ^^^^^ the trait `Impossible` is not implemented for `c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:149:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xmB::UV{}); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:150:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xmB::UV); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:151:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xmC::UV{}); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:152:5 | +LL | fn check(_: T) {} + | ----------------------------- required by `check` +... LL | check(xmC::UV); | ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` - | -note: required by `check` - --> $DIR/namespace-mix.rs:21:1 - | -LL | fn check(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 48 previous errors diff --git a/src/test/ui/no_send-enum.stderr b/src/test/ui/no_send-enum.stderr index 71e3aee919431..d1f3398ff9027 100644 --- a/src/test/ui/no_send-enum.stderr +++ b/src/test/ui/no_send-enum.stderr @@ -1,16 +1,14 @@ error[E0277]: `NoSend` cannot be sent between threads safely --> $DIR/no_send-enum.rs:16:5 | +LL | fn bar(_: T) {} + | --------------------- required by `bar` +... LL | bar(x); | ^^^ `NoSend` cannot be sent between threads safely | = help: within `Foo`, the trait `std::marker::Send` is not implemented for `NoSend` = note: required because it appears within the type `Foo` -note: required by `bar` - --> $DIR/no_send-enum.rs:12:1 - | -LL | fn bar(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/no_send-rc.stderr b/src/test/ui/no_send-rc.stderr index 2028cf77374f1..eaf3103060eff 100644 --- a/src/test/ui/no_send-rc.stderr +++ b/src/test/ui/no_send-rc.stderr @@ -1,15 +1,13 @@ error[E0277]: `std::rc::Rc<{integer}>` cannot be sent between threads safely --> $DIR/no_send-rc.rs:7:5 | +LL | fn bar(_: T) {} + | --------------------- required by `bar` +... LL | bar(x); | ^^^ `std::rc::Rc<{integer}>` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc<{integer}>` -note: required by `bar` - --> $DIR/no_send-rc.rs:3:1 - | -LL | fn bar(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/no_send-struct.stderr b/src/test/ui/no_send-struct.stderr index ca4ae054fd0f9..1808cef45f184 100644 --- a/src/test/ui/no_send-struct.stderr +++ b/src/test/ui/no_send-struct.stderr @@ -1,15 +1,13 @@ error[E0277]: `Foo` cannot be sent between threads safely --> $DIR/no_send-struct.rs:15:5 | +LL | fn bar(_: T) {} + | --------------------- required by `bar` +... LL | bar(x); | ^^^ `Foo` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `Foo` -note: required by `bar` - --> $DIR/no_send-struct.rs:11:1 - | -LL | fn bar(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/no_share-enum.stderr b/src/test/ui/no_share-enum.stderr index 64d791d02623e..5a9b7cae0b9f6 100644 --- a/src/test/ui/no_share-enum.stderr +++ b/src/test/ui/no_share-enum.stderr @@ -1,16 +1,14 @@ error[E0277]: `NoSync` cannot be shared between threads safely --> $DIR/no_share-enum.rs:14:5 | +LL | fn bar(_: T) {} + | --------------------- required by `bar` +... LL | bar(x); | ^^^ `NoSync` cannot be shared between threads safely | = help: within `Foo`, the trait `std::marker::Sync` is not implemented for `NoSync` = note: required because it appears within the type `Foo` -note: required by `bar` - --> $DIR/no_share-enum.rs:10:1 - | -LL | fn bar(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/no_share-struct.stderr b/src/test/ui/no_share-struct.stderr index fc4bcfb5b3e7e..c12ee7c5eae85 100644 --- a/src/test/ui/no_share-struct.stderr +++ b/src/test/ui/no_share-struct.stderr @@ -1,15 +1,13 @@ error[E0277]: `Foo` cannot be shared between threads safely --> $DIR/no_share-struct.rs:12:5 | +LL | fn bar(_: T) {} + | --------------------- required by `bar` +... LL | bar(x); | ^^^ `Foo` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `Foo` -note: required by `bar` - --> $DIR/no_share-struct.rs:8:1 - | -LL | fn bar(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/not-panic/not-panic-safe-2.stderr b/src/test/ui/not-panic/not-panic-safe-2.stderr index 4db127a463932..5bacf0bbc6b45 100644 --- a/src/test/ui/not-panic/not-panic-safe-2.stderr +++ b/src/test/ui/not-panic/not-panic-safe-2.stderr @@ -1,21 +1,22 @@ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-2.rs:10:5 | +LL | fn assert() {} + | ----------------------------------- required by `assert` +... LL | assert::>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | = help: within `std::cell::RefCell`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::rc::Rc>` -note: required by `assert` - --> $DIR/not-panic-safe-2.rs:7:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-2.rs:10:5 | +LL | fn assert() {} + | ----------------------------------- required by `assert` +... LL | assert::>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | @@ -23,11 +24,6 @@ LL | assert::>>(); = note: required because it appears within the type `std::cell::Cell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::rc::Rc>` -note: required by `assert` - --> $DIR/not-panic-safe-2.rs:7:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/not-panic/not-panic-safe-3.stderr b/src/test/ui/not-panic/not-panic-safe-3.stderr index 1f87f20f2e284..6d2a450115dff 100644 --- a/src/test/ui/not-panic/not-panic-safe-3.stderr +++ b/src/test/ui/not-panic/not-panic-safe-3.stderr @@ -1,21 +1,22 @@ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-3.rs:10:5 | +LL | fn assert() {} + | ----------------------------------- required by `assert` +... LL | assert::>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | = help: within `std::cell::RefCell`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::sync::Arc>` -note: required by `assert` - --> $DIR/not-panic-safe-3.rs:7:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-3.rs:10:5 | +LL | fn assert() {} + | ----------------------------------- required by `assert` +... LL | assert::>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | @@ -23,11 +24,6 @@ LL | assert::>>(); = note: required because it appears within the type `std::cell::Cell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::sync::Arc>` -note: required by `assert` - --> $DIR/not-panic-safe-3.rs:7:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/not-panic/not-panic-safe-4.stderr b/src/test/ui/not-panic/not-panic-safe-4.stderr index 24f649002960c..e28f169b72b6c 100644 --- a/src/test/ui/not-panic/not-panic-safe-4.stderr +++ b/src/test/ui/not-panic/not-panic-safe-4.stderr @@ -1,21 +1,22 @@ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-4.rs:9:5 | +LL | fn assert() {} + | ----------------------------------- required by `assert` +... LL | assert::<&RefCell>(); | ^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | = help: within `std::cell::RefCell`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::RefCell` -note: required by `assert` - --> $DIR/not-panic-safe-4.rs:6:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-4.rs:9:5 | +LL | fn assert() {} + | ----------------------------------- required by `assert` +... LL | assert::<&RefCell>(); | ^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | @@ -23,11 +24,6 @@ LL | assert::<&RefCell>(); = note: required because it appears within the type `std::cell::Cell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::RefCell` -note: required by `assert` - --> $DIR/not-panic-safe-4.rs:6:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/not-panic/not-panic-safe-5.stderr b/src/test/ui/not-panic/not-panic-safe-5.stderr index a603acb2f1fed..f8c4fe68dde7b 100644 --- a/src/test/ui/not-panic/not-panic-safe-5.stderr +++ b/src/test/ui/not-panic/not-panic-safe-5.stderr @@ -1,16 +1,14 @@ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-5.rs:9:5 | +LL | fn assert() {} + | ----------------------------------- required by `assert` +... LL | assert::<*const UnsafeCell>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | = help: the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `*const std::cell::UnsafeCell` -note: required by `assert` - --> $DIR/not-panic-safe-5.rs:6:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/not-panic/not-panic-safe-6.stderr b/src/test/ui/not-panic/not-panic-safe-6.stderr index a4c75ec7c6188..2cd780590729c 100644 --- a/src/test/ui/not-panic/not-panic-safe-6.stderr +++ b/src/test/ui/not-panic/not-panic-safe-6.stderr @@ -1,21 +1,22 @@ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-6.rs:9:5 | +LL | fn assert() {} + | ----------------------------------- required by `assert` +... LL | assert::<*mut RefCell>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | = help: within `std::cell::RefCell`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `*mut std::cell::RefCell` -note: required by `assert` - --> $DIR/not-panic-safe-6.rs:6:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the type `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-6.rs:9:5 | +LL | fn assert() {} + | ----------------------------------- required by `assert` +... LL | assert::<*mut RefCell>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | @@ -23,11 +24,6 @@ LL | assert::<*mut RefCell>(); = note: required because it appears within the type `std::cell::Cell` = note: required because it appears within the type `std::cell::RefCell` = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `*mut std::cell::RefCell` -note: required by `assert` - --> $DIR/not-panic-safe-6.rs:6:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/not-panic/not-panic-safe.stderr b/src/test/ui/not-panic/not-panic-safe.stderr index 2d12e697d5a7a..315ea17971aa9 100644 --- a/src/test/ui/not-panic/not-panic-safe.stderr +++ b/src/test/ui/not-panic/not-panic-safe.stderr @@ -1,15 +1,13 @@ error[E0277]: the type `&mut i32` may not be safely transferred across an unwind boundary --> $DIR/not-panic-safe.rs:9:5 | +LL | fn assert() {} + | ----------------------------------- required by `assert` +... LL | assert::<&mut i32>(); | ^^^^^^^^^^^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary | = help: the trait `std::panic::UnwindSafe` is not implemented for `&mut i32` -note: required by `assert` - --> $DIR/not-panic-safe.rs:6:1 - | -LL | fn assert() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/not-sync.stderr b/src/test/ui/not-sync.stderr index d102528bc6e92..57f1122be2b35 100644 --- a/src/test/ui/not-sync.stderr +++ b/src/test/ui/not-sync.stderr @@ -1,80 +1,68 @@ error[E0277]: `std::cell::Cell` cannot be shared between threads safely --> $DIR/not-sync.rs:8:5 | +LL | fn test() {} + | ------------------ required by `test` +... LL | test::>(); | ^^^^^^^^^^^^^^^^^ `std::cell::Cell` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell` -note: required by `test` - --> $DIR/not-sync.rs:5:1 - | -LL | fn test() {} - | ^^^^^^^^^^^^^^^^^^ error[E0277]: `std::cell::RefCell` cannot be shared between threads safely --> $DIR/not-sync.rs:10:5 | +LL | fn test() {} + | ------------------ required by `test` +... LL | test::>(); | ^^^^^^^^^^^^^^^^^^^^ `std::cell::RefCell` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` -note: required by `test` - --> $DIR/not-sync.rs:5:1 - | -LL | fn test() {} - | ^^^^^^^^^^^^^^^^^^ error[E0277]: `std::rc::Rc` cannot be shared between threads safely --> $DIR/not-sync.rs:13:5 | +LL | fn test() {} + | ------------------ required by `test` +... LL | test::>(); | ^^^^^^^^^^^^^^^ `std::rc::Rc` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc` -note: required by `test` - --> $DIR/not-sync.rs:5:1 - | -LL | fn test() {} - | ^^^^^^^^^^^^^^^^^^ error[E0277]: `std::rc::Weak` cannot be shared between threads safely --> $DIR/not-sync.rs:15:5 | +LL | fn test() {} + | ------------------ required by `test` +... LL | test::>(); | ^^^^^^^^^^^^^^^^^ `std::rc::Weak` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::rc::Weak` -note: required by `test` - --> $DIR/not-sync.rs:5:1 - | -LL | fn test() {} - | ^^^^^^^^^^^^^^^^^^ error[E0277]: `std::sync::mpsc::Receiver` cannot be shared between threads safely --> $DIR/not-sync.rs:18:5 | +LL | fn test() {} + | ------------------ required by `test` +... LL | test::>(); | ^^^^^^^^^^^^^^^^^^^^^ `std::sync::mpsc::Receiver` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Receiver` -note: required by `test` - --> $DIR/not-sync.rs:5:1 - | -LL | fn test() {} - | ^^^^^^^^^^^^^^^^^^ error[E0277]: `std::sync::mpsc::Sender` cannot be shared between threads safely --> $DIR/not-sync.rs:20:5 | +LL | fn test() {} + | ------------------ required by `test` +... LL | test::>(); | ^^^^^^^^^^^^^^^^^^^ `std::sync::mpsc::Sender` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender` -note: required by `test` - --> $DIR/not-sync.rs:5:1 - | -LL | fn test() {} - | ^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/object-does-not-impl-trait.stderr b/src/test/ui/object-does-not-impl-trait.stderr index 288ce9682c209..d3add6398bd98 100644 --- a/src/test/ui/object-does-not-impl-trait.stderr +++ b/src/test/ui/object-does-not-impl-trait.stderr @@ -1,14 +1,10 @@ error[E0277]: the trait bound `std::boxed::Box: Foo` is not satisfied --> $DIR/object-does-not-impl-trait.rs:6:35 | +LL | fn take_foo(f: F) {} + | ------------------------ required by `take_foo` LL | fn take_object(f: Box) { take_foo(f); } | ^^^^^^^^ the trait `Foo` is not implemented for `std::boxed::Box` - | -note: required by `take_foo` - --> $DIR/object-does-not-impl-trait.rs:5:1 - | -LL | fn take_foo(f: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr index 5d5db21f7263c..b286265bf01c0 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.stderr +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/multiple-impls.rs:33:5 | +LL | fn index(&self, index: Idx) -> &Self::Output; + | --------------------------------------------- required by `Index::index` +... LL | Index::index(&[] as &[i32], 2u32); | ^^^^^^^^^^^^ trait message | = help: the trait `Index` is not implemented for `[i32]` -note: required by `Index::index` - --> $DIR/multiple-impls.rs:12:5 - | -LL | fn index(&self, index: Idx) -> &Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/multiple-impls.rs:33:5 @@ -22,15 +20,13 @@ LL | Index::index(&[] as &[i32], 2u32); error[E0277]: the trait bound `[i32]: Index>` is not satisfied --> $DIR/multiple-impls.rs:36:5 | +LL | fn index(&self, index: Idx) -> &Self::Output; + | --------------------------------------------- required by `Index::index` +... LL | Index::index(&[] as &[i32], Foo(2u32)); | ^^^^^^^^^^^^ on impl for Foo | = help: the trait `Index>` is not implemented for `[i32]` -note: required by `Index::index` - --> $DIR/multiple-impls.rs:12:5 - | -LL | fn index(&self, index: Idx) -> &Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `[i32]: Index>` is not satisfied --> $DIR/multiple-impls.rs:36:5 @@ -43,15 +39,13 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); error[E0277]: the trait bound `[i32]: Index>` is not satisfied --> $DIR/multiple-impls.rs:39:5 | +LL | fn index(&self, index: Idx) -> &Self::Output; + | --------------------------------------------- required by `Index::index` +... LL | Index::index(&[] as &[i32], Bar(2u32)); | ^^^^^^^^^^^^ on impl for Bar | = help: the trait `Index>` is not implemented for `[i32]` -note: required by `Index::index` - --> $DIR/multiple-impls.rs:12:5 - | -LL | fn index(&self, index: Idx) -> &Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `[i32]: Index>` is not satisfied --> $DIR/multiple-impls.rs:39:5 diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr index 79cf22f609c79..78dc9a53761c5 100644 --- a/src/test/ui/on-unimplemented/on-impl.stderr +++ b/src/test/ui/on-unimplemented/on-impl.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/on-impl.rs:22:5 | +LL | fn index(&self, index: Idx) -> &Self::Output; + | --------------------------------------------- required by `Index::index` +... LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice | = help: the trait `Index` is not implemented for `[i32]` -note: required by `Index::index` - --> $DIR/on-impl.rs:9:5 - | -LL | fn index(&self, index: Idx) -> &Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/on-impl.rs:22:5 diff --git a/src/test/ui/on-unimplemented/on-trait.stderr b/src/test/ui/on-unimplemented/on-trait.stderr index ece8dee0afe97..992f53b1da6b6 100644 --- a/src/test/ui/on-unimplemented/on-trait.stderr +++ b/src/test/ui/on-unimplemented/on-trait.stderr @@ -1,28 +1,24 @@ error[E0277]: the trait bound `std::option::Option>: MyFromIterator<&u8>` is not satisfied --> $DIR/on-trait.rs:28:30 | +LL | fn collect, B: MyFromIterator>(it: I) -> B { + | -------------------------------------------------------------------- required by `collect` +... LL | let y: Option> = collect(x.iter()); // this should give approximately the same error for x.iter().collect() | ^^^^^^^ a collection of type `std::option::Option>` cannot be built from an iterator over elements of type `&u8` | = help: the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option>` -note: required by `collect` - --> $DIR/on-trait.rs:22:1 - | -LL | fn collect, B: MyFromIterator>(it: I) -> B { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::string::String: Bar::Foo` is not satisfied --> $DIR/on-trait.rs:31:21 | +LL | fn foobar>() -> T { + | ---------------------------------------------- required by `foobar` +... LL | let x: String = foobar(); | ^^^^^^ test error `std::string::String` with `u8` `_` `u32` in `Bar::Foo` | = help: the trait `Bar::Foo` is not implemented for `std::string::String` -note: required by `foobar` - --> $DIR/on-trait.rs:12:1 - | -LL | fn foobar>() -> T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/overlap-marker-trait.stderr b/src/test/ui/overlap-marker-trait.stderr index a59af8dcdbcf7..a66e3990e8bd9 100644 --- a/src/test/ui/overlap-marker-trait.stderr +++ b/src/test/ui/overlap-marker-trait.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `NotDebugOrDisplay: Marker` is not satisfied --> $DIR/overlap-marker-trait.rs:30:5 | +LL | fn is_marker() { } + | ------------------------- required by `is_marker` +... LL | is_marker::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay` - | -note: required by `is_marker` - --> $DIR/overlap-marker-trait.rs:18:1 - | -LL | fn is_marker() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/phantom-oibit.stderr b/src/test/ui/phantom-oibit.stderr index ec8b3181bc553..284102a6df028 100644 --- a/src/test/ui/phantom-oibit.stderr +++ b/src/test/ui/phantom-oibit.stderr @@ -1,6 +1,9 @@ error[E0277]: `T` cannot be shared between threads safely --> $DIR/phantom-oibit.rs:21:5 | +LL | fn is_zen(_: T) {} + | ----------------------- required by `is_zen` +... LL | is_zen(x) | ^^^^^^ `T` cannot be shared between threads safely | @@ -9,15 +12,13 @@ LL | is_zen(x) = note: required because of the requirements on the impl of `Zen` for `&T` = note: required because it appears within the type `std::marker::PhantomData<&T>` = note: required because it appears within the type `Guard<'_, T>` -note: required by `is_zen` - --> $DIR/phantom-oibit.rs:18:1 - | -LL | fn is_zen(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` cannot be shared between threads safely --> $DIR/phantom-oibit.rs:26:5 | +LL | fn is_zen(_: T) {} + | ----------------------- required by `is_zen` +... LL | is_zen(x) | ^^^^^^ `T` cannot be shared between threads safely | @@ -27,11 +28,6 @@ LL | is_zen(x) = note: required because it appears within the type `std::marker::PhantomData<&T>` = note: required because it appears within the type `Guard<'_, T>` = note: required because it appears within the type `Nested>` -note: required by `is_zen` - --> $DIR/phantom-oibit.rs:18:1 - | -LL | fn is_zen(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/recursion/recursive-requirements.stderr b/src/test/ui/recursion/recursive-requirements.stderr index b3041902acac3..9846c938ba90b 100644 --- a/src/test/ui/recursion/recursive-requirements.stderr +++ b/src/test/ui/recursion/recursive-requirements.stderr @@ -1,20 +1,21 @@ error[E0277]: `*const Bar` cannot be shared between threads safely --> $DIR/recursive-requirements.rs:16:12 | +LL | struct AssertSync(PhantomData); + | ------------------------------------------- required by `AssertSync` +... LL | let _: AssertSync = unimplemented!(); | ^^^^^^^^^^^^^^^ `*const Bar` cannot be shared between threads safely | = help: within `Foo`, the trait `std::marker::Sync` is not implemented for `*const Bar` = note: required because it appears within the type `Foo` -note: required by `AssertSync` - --> $DIR/recursive-requirements.rs:3:1 - | -LL | struct AssertSync(PhantomData); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `*const Foo` cannot be shared between threads safely --> $DIR/recursive-requirements.rs:16:12 | +LL | struct AssertSync(PhantomData); + | ------------------------------------------- required by `AssertSync` +... LL | let _: AssertSync = unimplemented!(); | ^^^^^^^^^^^^^^^ `*const Foo` cannot be shared between threads safely | @@ -22,11 +23,6 @@ LL | let _: AssertSync = unimplemented!(); = note: required because it appears within the type `Bar` = note: required because it appears within the type `std::marker::PhantomData` = note: required because it appears within the type `Foo` -note: required by `AssertSync` - --> $DIR/recursive-requirements.rs:3:1 - | -LL | struct AssertSync(PhantomData); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr index 24dfdf8ebc299..1d3e33e4b0503 100644 --- a/src/test/ui/span/issue-29595.stderr +++ b/src/test/ui/span/issue-29595.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `u8: Tr` is not satisfied --> $DIR/issue-29595.rs:6:17 | +LL | const C: Self; + | -------------- required by `Tr::C` +... LL | let a: u8 = Tr::C; | ^^^^^ the trait `Tr` is not implemented for `u8` - | -note: required by `Tr::C` - --> $DIR/issue-29595.rs:2:5 - | -LL | const C: Self; - | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index beb2272452363..08baa478b8bfa 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr @@ -1,16 +1,14 @@ error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/str-mut-idx.rs:4:15 | +LL | fn bot() -> T { loop {} } + | ---------------- required by `bot` +... LL | s[1..2] = bot(); | ^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `str` = note: to learn more, visit -note: required by `bot` - --> $DIR/str-mut-idx.rs:1:1 - | -LL | fn bot() -> T { loop {} } - | ^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/str-mut-idx.rs:4:5 diff --git a/src/test/ui/structs/struct-path-alias-bounds.stderr b/src/test/ui/structs/struct-path-alias-bounds.stderr index 70eb2610ea5d2..1c2c205e01c1b 100644 --- a/src/test/ui/structs/struct-path-alias-bounds.stderr +++ b/src/test/ui/structs/struct-path-alias-bounds.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `NoClone: std::clone::Clone` is not satisfied --> $DIR/struct-path-alias-bounds.rs:9:13 | +LL | struct S { a: T } + | ------------------ required by `S` +... LL | let s = A { a: NoClone }; | ^ the trait `std::clone::Clone` is not implemented for `NoClone` - | -note: required by `S` - --> $DIR/struct-path-alias-bounds.rs:3:1 - | -LL | struct S { a: T } - | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/substs-ppaux.normal.stderr b/src/test/ui/substs-ppaux.normal.stderr index b3b879ef9acbe..4a8c99cdef3f5 100644 --- a/src/test/ui/substs-ppaux.normal.stderr +++ b/src/test/ui/substs-ppaux.normal.stderr @@ -61,17 +61,15 @@ LL | let x: () = foo::<'static>; error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/substs-ppaux.rs:49:5 | +LL | fn bar<'a, T>() where T: 'a {} + | --------------------------- required by `Foo::bar` +... LL | >::bar; | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `str` = note: to learn more, visit = note: required because of the requirements on the impl of `Foo<'_, '_, u8>` for `str` -note: required by `Foo::bar` - --> $DIR/substs-ppaux.rs:7:5 - | -LL | fn bar<'a, T>() where T: 'a {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/substs-ppaux.verbose.stderr b/src/test/ui/substs-ppaux.verbose.stderr index 363018db232d8..3314eb60cdea6 100644 --- a/src/test/ui/substs-ppaux.verbose.stderr +++ b/src/test/ui/substs-ppaux.verbose.stderr @@ -61,17 +61,15 @@ LL | let x: () = foo::<'static>; error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/substs-ppaux.rs:49:5 | +LL | fn bar<'a, T>() where T: 'a {} + | --------------------------- required by `Foo::bar` +... LL | >::bar; | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `str` = note: to learn more, visit = note: required because of the requirements on the impl of `Foo<'_#0r, '_#1r, u8>` for `str` -note: required by `Foo::bar` - --> $DIR/substs-ppaux.rs:7:5 - | -LL | fn bar<'a, T>() where T: 'a {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index 3e28700ce9552..da5aeb63b909a 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -1,16 +1,14 @@ error[E0277]: the trait bound `&str: std::convert::From` is not satisfied --> $DIR/into-str.rs:4:5 | +LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {} + | ------------------------------------------- required by `foo` +... LL | foo(String::new()); | ^^^ the trait `std::convert::From` is not implemented for `&str` | = note: to coerce a `std::string::String` into a `&str`, use `&*` as a prefix = note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String` -note: required by `foo` - --> $DIR/into-str.rs:1:1 - | -LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr b/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr index 972d213ac8f8f..8403b2ebaca10 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr @@ -1,28 +1,24 @@ error[E0277]: `std::rc::Rc` cannot be sent between threads safely --> $DIR/trait-alias-cross-crate.rs:14:5 | +LL | fn use_alias() {} + | --------------------------- required by `use_alias` +... LL | use_alias::>(); | ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc` -note: required by `use_alias` - --> $DIR/trait-alias-cross-crate.rs:10:1 - | -LL | fn use_alias() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::rc::Rc` cannot be shared between threads safely --> $DIR/trait-alias-cross-crate.rs:14:5 | +LL | fn use_alias() {} + | --------------------------- required by `use_alias` +... LL | use_alias::>(); | ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc` -note: required by `use_alias` - --> $DIR/trait-alias-cross-crate.rs:10:1 - | -LL | fn use_alias() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-alias/trait-alias-wf.stderr b/src/test/ui/traits/trait-alias/trait-alias-wf.stderr index ee2dd5b24afed..ca6d058471667 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-wf.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-wf.stderr @@ -1,15 +1,12 @@ error[E0277]: the trait bound `T: Foo` is not satisfied --> $DIR/trait-alias-wf.rs:5:1 | +LL | trait A {} + | --------------- required by `A` LL | trait B = A; | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T` | = help: consider adding a `where T: Foo` bound -note: required by `A` - --> $DIR/trait-alias-wf.rs:4:1 - | -LL | trait A {} - | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr index 6fdd2ceaaac9c..3c68d461f80d6 100644 --- a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr +++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr @@ -1,26 +1,20 @@ error[E0277]: the trait bound `u32: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:13:1 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | fn explode(x: Foo) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u32` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:3:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `f32: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:16:1 | +LL | enum Bar { + | ----------------- required by `Bar` +... LL | fn kaboom(y: Bar) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `f32` - | -note: required by `Bar` - --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:7:1 - | -LL | enum Bar { - | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr index 15441b583cef2..7e8db610fe233 100644 --- a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr +++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `u16: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums-in-impls.rs:20:6 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | impl PolyTrait> for Struct { | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u16` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums-in-impls.rs:3:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr index cdcfff97bd020..070b7b013e5cc 100644 --- a/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr +++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr @@ -1,26 +1,20 @@ error[E0277]: the trait bound `usize: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:15:14 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | let baz: Foo = loop { }; | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:5:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `{integer}: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:10:15 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | let foo = Foo { | ^^^ the trait `Trait` is not implemented for `{integer}` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:5:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr index b019c2979202f..722f01750cb66 100644 --- a/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr +++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `usize: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums-static.rs:9:11 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | static X: Foo = Foo { | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums-static.rs:5:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr index 9a4cc90f3a5e0..bd76df8071a53 100644 --- a/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr +++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr @@ -1,89 +1,71 @@ error[E0277]: the trait bound `T: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:13:9 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | impl Foo { | ^^^^^^ the trait `Trait` is not implemented for `T` | = help: consider adding a `where T: Trait` bound -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `isize: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:19:5 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | a: Foo, | ^^^^^^^^^^^^^ the trait `Trait` is not implemented for `isize` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `usize: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:23:10 | +LL | enum Bar { + | ----------------- required by `Bar` +... LL | Quux(Bar), | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` - | -note: required by `Bar` - --> $DIR/trait-bounds-on-structs-and-enums.rs:7:1 - | -LL | enum Bar { - | ^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `U: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:27:5 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | b: Foo, | ^^^^^^^^^ the trait `Trait` is not implemented for `U` | = help: consider adding a `where U: Trait` bound -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `V: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:31:21 | +LL | enum Bar { + | ----------------- required by `Bar` +... LL | EvenMoreBadness(Bar), | ^^^^^^ the trait `Trait` is not implemented for `V` | = help: consider adding a `where V: Trait` bound -note: required by `Bar` - --> $DIR/trait-bounds-on-structs-and-enums.rs:7:1 - | -LL | enum Bar { - | ^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `i32: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:35:5 | +LL | struct Foo { + | ------------------- required by `Foo` +... LL | Foo, | ^^^^^^^^ the trait `Trait` is not implemented for `i32` - | -note: required by `Foo` - --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `u8: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:39:22 | +LL | enum Bar { + | ----------------- required by `Bar` +... LL | DictionaryLike { field: Bar }, | ^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u8` - | -note: required by `Bar` - --> $DIR/trait-bounds-on-structs-and-enums.rs:7:1 - | -LL | enum Bar { - | ^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/traits/trait-static-method-generic-inference.stderr b/src/test/ui/traits/trait-static-method-generic-inference.stderr index 390d21c4a699e..a99536d31ef84 100644 --- a/src/test/ui/traits/trait-static-method-generic-inference.stderr +++ b/src/test/ui/traits/trait-static-method-generic-inference.stderr @@ -1,14 +1,11 @@ error[E0283]: type annotations required: cannot resolve `_: base::HasNew` --> $DIR/trait-static-method-generic-inference.rs:24:25 | +LL | fn new() -> T; + | -------------- required by `base::HasNew::new` +... LL | let _f: base::Foo = base::HasNew::new(); | ^^^^^^^^^^^^^^^^^ - | -note: required by `base::HasNew::new` - --> $DIR/trait-static-method-generic-inference.rs:8:9 - | -LL | fn new() -> T; - | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr b/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr index cd8501e4df421..b29d726fbba94 100644 --- a/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr @@ -1,15 +1,13 @@ error[E0275]: overflow evaluating the requirement `{integer}: Tweedledum` --> $DIR/traits-inductive-overflow-simultaneous.rs:18:5 | +LL | fn is_ee(t: T) { + | ------------------------ required by `is_ee` +... LL | is_ee(4); | ^^^^^ | = note: required because of the requirements on the impl of `Combo` for `{integer}` -note: required by `is_ee` - --> $DIR/traits-inductive-overflow-simultaneous.rs:13:1 - | -LL | fn is_ee(t: T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr index 87e7ba3e7efcf..0b543616d7c9a 100644 --- a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr @@ -7,15 +7,13 @@ LL | auto trait Magic: Copy {} error[E0277]: the trait bound `NoClone: std::marker::Copy` is not satisfied --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:15:18 | +LL | fn copy(x: T) -> (T, T) { (x, x) } + | --------------------------------- required by `copy` +... LL | let (a, b) = copy(NoClone); | ^^^^ the trait `std::marker::Copy` is not implemented for `NoClone` | = note: required because of the requirements on the impl of `Magic` for `NoClone` -note: required by `copy` - --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:9:1 - | -LL | fn copy(x: T) -> (T, T) { (x, x) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr index 769582a778bcf..92747be7d2c6b 100644 --- a/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr @@ -1,15 +1,13 @@ error[E0275]: overflow evaluating the requirement `NoClone: Magic` --> $DIR/traits-inductive-overflow-supertrait.rs:13:18 | +LL | fn copy(x: T) -> (T, T) { (x, x) } + | --------------------------------- required by `copy` +... LL | let (a, b) = copy(NoClone); | ^^^^ | = note: required because of the requirements on the impl of `Magic` for `NoClone` -note: required by `copy` - --> $DIR/traits-inductive-overflow-supertrait.rs:7:1 - | -LL | fn copy(x: T) -> (T, T) { (x, x) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr index 61adbf00f7188..58d7fcd56c71e 100644 --- a/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr @@ -1,14 +1,11 @@ error[E0275]: overflow evaluating the requirement `*mut (): Magic` --> $DIR/traits-inductive-overflow-two-traits.rs:19:5 | +LL | fn wizard() { check::<::X>(); } + | --------------------- required by `wizard` +... LL | wizard::<*mut ()>(); | ^^^^^^^^^^^^^^^^^ - | -note: required by `wizard` - --> $DIR/traits-inductive-overflow-two-traits.rs:16:1 - | -LL | fn wizard() { check::<::X>(); } - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/traits-negative-impls.stderr b/src/test/ui/traits/traits-negative-impls.stderr index 1bdd73eb6f9b1..23bd334a3e776 100644 --- a/src/test/ui/traits/traits-negative-impls.stderr +++ b/src/test/ui/traits/traits-negative-impls.stderr @@ -1,74 +1,67 @@ error[E0277]: `dummy::TestType` cannot be sent between threads safely --> $DIR/traits-negative-impls.rs:23:5 | +LL | struct Outer(T); + | ------------------------- required by `Outer` +... LL | Outer(TestType); | ^^^^^ `dummy::TestType` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dummy::TestType` -note: required by `Outer` - --> $DIR/traits-negative-impls.rs:10:1 - | -LL | struct Outer(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dummy::TestType` cannot be sent between threads safely --> $DIR/traits-negative-impls.rs:23:5 | +LL | struct Outer(T); + | ------------------------- required by `Outer` +... LL | Outer(TestType); | ^^^^^^^^^^^^^^^ `dummy::TestType` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dummy::TestType` -note: required by `Outer` - --> $DIR/traits-negative-impls.rs:10:1 - | -LL | struct Outer(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dummy1b::TestType` cannot be sent between threads safely --> $DIR/traits-negative-impls.rs:32:5 | +LL | fn is_send(_: T) {} + | ------------------------- required by `is_send` +... LL | is_send(TestType); | ^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dummy1b::TestType` -note: required by `is_send` - --> $DIR/traits-negative-impls.rs:16:1 - | -LL | fn is_send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dummy1c::TestType` cannot be sent between threads safely --> $DIR/traits-negative-impls.rs:40:5 | +LL | fn is_send(_: T) {} + | ------------------------- required by `is_send` +... LL | is_send((8, TestType)); | ^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely | = help: within `({integer}, dummy1c::TestType)`, the trait `std::marker::Send` is not implemented for `dummy1c::TestType` = note: required because it appears within the type `({integer}, dummy1c::TestType)` -note: required by `is_send` - --> $DIR/traits-negative-impls.rs:16:1 - | -LL | fn is_send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dummy2::TestType` cannot be sent between threads safely --> $DIR/traits-negative-impls.rs:48:5 | +LL | fn is_send(_: T) {} + | ------------------------- required by `is_send` +... LL | is_send(Box::new(TestType)); | ^^^^^^^ `dummy2::TestType` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `dummy2::TestType` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique` = note: required because it appears within the type `std::boxed::Box` -note: required by `is_send` - --> $DIR/traits-negative-impls.rs:16:1 - | -LL | fn is_send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dummy3::TestType` cannot be sent between threads safely --> $DIR/traits-negative-impls.rs:56:5 | +LL | fn is_send(_: T) {} + | ------------------------- required by `is_send` +... LL | is_send(Box::new(Outer2(TestType))); | ^^^^^^^ `dummy3::TestType` cannot be sent between threads safely | @@ -76,25 +69,18 @@ LL | is_send(Box::new(Outer2(TestType))); = note: required because it appears within the type `Outer2` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique>` = note: required because it appears within the type `std::boxed::Box>` -note: required by `is_send` - --> $DIR/traits-negative-impls.rs:16:1 - | -LL | fn is_send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `main::TestType` cannot be sent between threads safely --> $DIR/traits-negative-impls.rs:66:5 | +LL | fn is_sync(_: T) {} + | ------------------------- required by `is_sync` +... LL | is_sync(Outer2(TestType)); | ^^^^^^^ `main::TestType` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `main::TestType` = note: required because of the requirements on the impl of `std::marker::Sync` for `Outer2` -note: required by `is_sync` - --> $DIR/traits-negative-impls.rs:17:1 - | -LL | fn is_sync(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr b/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr index 5d1c91376868f..db77e82adbd00 100644 --- a/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr +++ b/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr @@ -15,27 +15,22 @@ LL | c.same_as(22) error[E0277]: the trait bound `dyn CompareToInts: CompareTo` is not satisfied --> $DIR/traits-repeated-supertrait-ambig.rs:34:5 | +LL | fn same_as(&self, t: T) -> bool; + | -------------------------------- required by `CompareTo::same_as` +... LL | CompareToInts::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo` is not implemented for `dyn CompareToInts` - | -note: required by `CompareTo::same_as` - --> $DIR/traits-repeated-supertrait-ambig.rs:9:5 - | -LL | fn same_as(&self, t: T) -> bool; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `C: CompareTo` is not satisfied --> $DIR/traits-repeated-supertrait-ambig.rs:38:5 | +LL | fn same_as(&self, t: T) -> bool; + | -------------------------------- required by `CompareTo::same_as` +... LL | CompareTo::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^ the trait `CompareTo` is not implemented for `C` | = help: consider adding a `where C: CompareTo` bound -note: required by `CompareTo::same_as` - --> $DIR/traits-repeated-supertrait-ambig.rs:9:5 - | -LL | fn same_as(&self, t: T) -> bool; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `i64: CompareTo` is not satisfied --> $DIR/traits-repeated-supertrait-ambig.rs:42:23 diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr index 46b4b2a878492..f0f048159ec73 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -21,26 +21,20 @@ LL | 3i32.test(); error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/trivial-bounds-leak.rs:25:5 | +LL | fn test(&self); + | --------------- required by `Foo::test` +... LL | Foo::test(&4i32); | ^^^^^^^^^ the trait `Foo` is not implemented for `i32` - | -note: required by `Foo::test` - --> $DIR/trivial-bounds-leak.rs:5:5 - | -LL | fn test(&self); - | ^^^^^^^^^^^^^^^ error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/trivial-bounds-leak.rs:26:5 | LL | generic_function(5i32); | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` - | -note: required by `generic_function` - --> $DIR/trivial-bounds-leak.rs:29:1 - | +... LL | fn generic_function(t: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --------------------------------- required by `generic_function` error: aborting due to 4 previous errors diff --git a/src/test/ui/try-operator-on-main.stderr b/src/test/ui/try-operator-on-main.stderr index 9f120e009485e..6878cd80629bc 100644 --- a/src/test/ui/try-operator-on-main.stderr +++ b/src/test/ui/try-operator-on-main.stderr @@ -21,12 +21,9 @@ error[E0277]: the trait bound `(): std::ops::Try` is not satisfied | LL | try_trait_generic::<()>(); | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Try` is not implemented for `()` - | -note: required by `try_trait_generic` - --> $DIR/try-operator-on-main.rs:20:1 - | +... LL | fn try_trait_generic() -> T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------------------------------- required by `try_trait_generic` error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` --> $DIR/try-operator-on-main.rs:22:5 diff --git a/src/test/ui/type/type-annotation-needed.stderr b/src/test/ui/type/type-annotation-needed.stderr index 92ae9746b150b..1dd2aafeb62fa 100644 --- a/src/test/ui/type/type-annotation-needed.stderr +++ b/src/test/ui/type/type-annotation-needed.stderr @@ -1,14 +1,11 @@ error[E0283]: type annotations required: cannot resolve `_: std::convert::Into` --> $DIR/type-annotation-needed.rs:5:5 | +LL | fn foo>(x: i32) {} + | ------------------------------- required by `foo` +... LL | foo(42); | ^^^ - | -note: required by `foo` - --> $DIR/type-annotation-needed.rs:1:1 - | -LL | fn foo>(x: i32) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr index a46d79ec3183e..42cca76451fd1 100644 --- a/src/test/ui/type/type-check-defaults.stderr +++ b/src/test/ui/type/type-check-defaults.stderr @@ -1,90 +1,71 @@ error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32` --> $DIR/type-check-defaults.rs:6:19 | +LL | struct Foo>(T, U); + | ---------------------------------------- required by `Foo` LL | struct WellFormed>(Z); | ^ a collection of type `i32` cannot be built from `std::iter::Iterator` | = help: the trait `std::iter::FromIterator` is not implemented for `i32` -note: required by `Foo` - --> $DIR/type-check-defaults.rs:5:1 - | -LL | struct Foo>(T, U); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32` --> $DIR/type-check-defaults.rs:8:27 | +LL | struct Foo>(T, U); + | ---------------------------------------- required by `Foo` +... LL | struct WellFormedNoBounds>(Z); | ^ a collection of type `i32` cannot be built from `std::iter::Iterator` | = help: the trait `std::iter::FromIterator` is not implemented for `i32` -note: required by `Foo` - --> $DIR/type-check-defaults.rs:5:1 - | -LL | struct Foo>(T, U); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied --> $DIR/type-check-defaults.rs:11:1 | -LL | struct Bounds(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` - | -note: required by `Bounds` - --> $DIR/type-check-defaults.rs:11:1 - | LL | struct Bounds(T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `std::marker::Copy` is not implemented for `std::string::String` + | required by `Bounds` error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied --> $DIR/type-check-defaults.rs:14:1 | -LL | struct WhereClause(T) where T: Copy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` - | -note: required by `WhereClause` - --> $DIR/type-check-defaults.rs:14:1 - | LL | struct WhereClause(T) where T: Copy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `std::marker::Copy` is not implemented for `std::string::String` + | required by `WhereClause` error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied --> $DIR/type-check-defaults.rs:17:1 | LL | trait TraitBound {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` - | -note: required by `TraitBound` - --> $DIR/type-check-defaults.rs:17:1 - | -LL | trait TraitBound {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -------------------------------^^^ + | | + | the trait `std::marker::Copy` is not implemented for `std::string::String` + | required by `TraitBound` error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/type-check-defaults.rs:21:1 | +LL | trait Super { } + | -------------------- required by `Super` LL | trait Base: Super { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `Super` - --> $DIR/type-check-defaults.rs:20:1 - | -LL | trait Super { } - | ^^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add `u8` to `i32` --> $DIR/type-check-defaults.rs:24:1 | LL | trait ProjectionPred> where T::Item : Add {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8` + | ------------------------------------------------------------------------^^^ + | | + | no implementation for `i32 + u8` + | required by `ProjectionPred` | = help: the trait `std::ops::Add` is not implemented for `i32` -note: required by `ProjectionPred` - --> $DIR/type-check-defaults.rs:24:1 - | -LL | trait ProjectionPred> where T::Item : Add {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/type/type-check/issue-40294.stderr b/src/test/ui/type/type-check/issue-40294.stderr index 254875fcaab3a..732a81c8a244a 100644 --- a/src/test/ui/type/type-check/issue-40294.stderr +++ b/src/test/ui/type/type-check/issue-40294.stderr @@ -1,6 +1,9 @@ error[E0283]: type annotations required: cannot resolve `&'a T: Foo` --> $DIR/issue-40294.rs:5:1 | +LL | trait Foo: Sized { + | ---------------- required by `Foo` +... LL | / fn foo<'a,'b,T>(x: &'a T, y: &'b T) LL | | where &'a T : Foo, LL | | &'b T : Foo @@ -9,12 +12,6 @@ LL | | x.foo(); LL | | y.foo(); LL | | } | |_^ - | -note: required by `Foo` - --> $DIR/issue-40294.rs:1:1 - | -LL | trait Foo: Sized { - | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type/type-params-in-different-spaces-2.stderr b/src/test/ui/type/type-params-in-different-spaces-2.stderr index 15db94ef1e3c3..7d4bbc813c09c 100644 --- a/src/test/ui/type/type-params-in-different-spaces-2.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-2.stderr @@ -1,28 +1,24 @@ error[E0277]: the trait bound `Self: Tr` is not satisfied --> $DIR/type-params-in-different-spaces-2.rs:10:9 | +LL | fn op(_: T) -> Self; + | -------------------- required by `Tr::op` +... LL | Tr::op(u) | ^^^^^^ the trait `Tr` is not implemented for `Self` | = help: consider adding a `where Self: Tr` bound -note: required by `Tr::op` - --> $DIR/type-params-in-different-spaces-2.rs:5:5 - | -LL | fn op(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: Tr` is not satisfied --> $DIR/type-params-in-different-spaces-2.rs:16:9 | +LL | fn op(_: T) -> Self; + | -------------------- required by `Tr::op` +... LL | Tr::op(u) | ^^^^^^ the trait `Tr` is not implemented for `Self` | = help: consider adding a `where Self: Tr` bound -note: required by `Tr::op` - --> $DIR/type-params-in-different-spaces-2.rs:5:5 - | -LL | fn op(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr index a31ee83ae1ccc..7fb3731be23e6 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr @@ -3,14 +3,12 @@ error[E0277]: `::AssocType` cannot be sent between threads safely | LL | is_send::(); | ^^^^^^^^^^^^^^^^^^^^^^^ `::AssocType` cannot be sent between threads safely +... +LL | fn is_send() { + | -------------------- required by `is_send` | = help: the trait `std::marker::Send` is not implemented for `::AssocType` = help: consider adding a `where ::AssocType: std::marker::Send` bound -note: required by `is_send` - --> $DIR/typeck-default-trait-impl-assoc-type.rs:12:1 - | -LL | fn is_send() { - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr index db1d7d8c0b74b..8389356fdd6f6 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr @@ -1,17 +1,15 @@ error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)` --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:16:5 | +LL | fn is_mytrait() {} + | --------------------------- required by `is_mytrait` +... LL | is_mytrait::<(MyS2, MyS)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2` | = help: the following implementations were found: = note: required because it appears within the type `(MyS2, MyS)` -note: required by `is_mytrait` - --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:11:1 - | -LL | fn is_mytrait() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr index 0f90518964340..eee186feea67d 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr @@ -1,16 +1,14 @@ error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied --> $DIR/typeck-default-trait-impl-constituent-types.rs:20:5 | +LL | fn is_mytrait() {} + | --------------------------- required by `is_mytrait` +... LL | is_mytrait::(); | ^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `MyS2` | = help: the following implementations were found: -note: required by `is_mytrait` - --> $DIR/typeck-default-trait-impl-constituent-types.rs:15:1 - | -LL | fn is_mytrait() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr index 8442f47e82c48..1e6adeb430998 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr @@ -1,15 +1,13 @@ error[E0277]: `MyNotSendable` cannot be sent between threads safely --> $DIR/typeck-default-trait-impl-negation-send.rs:19:5 | +LL | fn is_send() {} + | --------------------- required by `is_send` +... LL | is_send::(); | ^^^^^^^^^^^^^^^^^^^^^^^^ `MyNotSendable` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `MyNotSendable` -note: required by `is_send` - --> $DIR/typeck-default-trait-impl-negation-send.rs:15:1 - | -LL | fn is_send() {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr index 4d435bf4e8b24..d4f8f5ad82c9e 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr @@ -1,43 +1,37 @@ error[E0277]: `MyNotSync` cannot be shared between threads safely --> $DIR/typeck-default-trait-impl-negation-sync.rs:33:5 | +LL | fn is_sync() {} + | --------------------- required by `is_sync` +... LL | is_sync::(); | ^^^^^^^^^^^^^^^^^^^^ `MyNotSync` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `MyNotSync` -note: required by `is_sync` - --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:1 - | -LL | fn is_sync() {} - | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::cell::UnsafeCell` cannot be shared between threads safely --> $DIR/typeck-default-trait-impl-negation-sync.rs:36:5 | +LL | fn is_sync() {} + | --------------------- required by `is_sync` +... LL | is_sync::(); | ^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell` cannot be shared between threads safely | = help: within `MyTypeWUnsafe`, the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell` = note: required because it appears within the type `MyTypeWUnsafe` -note: required by `is_sync` - --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:1 - | -LL | fn is_sync() {} - | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `Managed` cannot be shared between threads safely --> $DIR/typeck-default-trait-impl-negation-sync.rs:39:5 | +LL | fn is_sync() {} + | --------------------- required by `is_sync` +... LL | is_sync::(); | ^^^^^^^^^^^^^^^^^^^^^^^^ `Managed` cannot be shared between threads safely | = help: within `MyTypeManaged`, the trait `std::marker::Sync` is not implemented for `Managed` = note: required because it appears within the type `MyTypeManaged` -note: required by `is_sync` - --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:1 - | -LL | fn is_sync() {} - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr index 751083d0358b6..e993098b2deed 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr @@ -1,30 +1,26 @@ error[E0277]: the trait bound `ThisImplsUnsafeTrait: MyTrait` is not satisfied --> $DIR/typeck-default-trait-impl-negation.rs:21:5 | +LL | fn is_my_trait() {} + | ---------------------------- required by `is_my_trait` +... LL | is_my_trait::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `ThisImplsUnsafeTrait` | = help: the following implementations were found: -note: required by `is_my_trait` - --> $DIR/typeck-default-trait-impl-negation.rs:16:1 - | -LL | fn is_my_trait() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `ThisImplsTrait: MyUnsafeTrait` is not satisfied --> $DIR/typeck-default-trait-impl-negation.rs:24:5 | +LL | fn is_my_unsafe_trait() {} + | ----------------------------------------- required by `is_my_unsafe_trait` +... LL | is_my_unsafe_trait::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyUnsafeTrait` is not implemented for `ThisImplsTrait` | = help: the following implementations were found: -note: required by `is_my_unsafe_trait` - --> $DIR/typeck-default-trait-impl-negation.rs:17:1 - | -LL | fn is_my_unsafe_trait() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr b/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr index d45cbb27a5f16..d87a6384e5c01 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied --> $DIR/typeck-default-trait-impl-precedence.rs:18:5 | +LL | fn is_defaulted() { } + | ------------------------------ required by `is_defaulted` +... LL | is_defaulted::<&'static u32>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32` | = note: required because of the requirements on the impl of `Defaulted` for `&'static u32` -note: required by `is_defaulted` - --> $DIR/typeck-default-trait-impl-precedence.rs:11:1 - | -LL | fn is_defaulted() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr b/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr index a850cc7b377d0..5f3a5bc6e0054 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr @@ -3,14 +3,12 @@ error[E0277]: `T` cannot be sent between threads safely | LL | is_send::() | ^^^^^^^^^^^^ `T` cannot be sent between threads safely +... +LL | fn is_send() { + | -------------------- required by `is_send` | = help: the trait `std::marker::Send` is not implemented for `T` = help: consider adding a `where T: std::marker::Send` bound -note: required by `is_send` - --> $DIR/typeck-default-trait-impl-send-param.rs:8:1 - | -LL | fn is_send() { - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-unsafe-always-share.stderr b/src/test/ui/typeck/typeck-unsafe-always-share.stderr index ff351afdcaedf..7ed85a14259aa 100644 --- a/src/test/ui/typeck/typeck-unsafe-always-share.stderr +++ b/src/test/ui/typeck/typeck-unsafe-always-share.stderr @@ -1,55 +1,47 @@ error[E0277]: `std::cell::UnsafeCell>` cannot be shared between threads safely --> $DIR/typeck-unsafe-always-share.rs:19:5 | +LL | fn test(s: T) {} + | ---------------------- required by `test` +... LL | test(us); | ^^^^ `std::cell::UnsafeCell>` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell>` -note: required by `test` - --> $DIR/typeck-unsafe-always-share.rs:15:1 - | -LL | fn test(s: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::cell::UnsafeCell` cannot be shared between threads safely --> $DIR/typeck-unsafe-always-share.rs:23:5 | +LL | fn test(s: T) {} + | ---------------------- required by `test` +... LL | test(uns); | ^^^^ `std::cell::UnsafeCell` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell` -note: required by `test` - --> $DIR/typeck-unsafe-always-share.rs:15:1 - | -LL | fn test(s: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::cell::UnsafeCell` cannot be shared between threads safely --> $DIR/typeck-unsafe-always-share.rs:27:5 | +LL | fn test(s: T) {} + | ---------------------- required by `test` +... LL | test(ms); | ^^^^ `std::cell::UnsafeCell` cannot be shared between threads safely | = help: within `MySync`, the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell` = note: required because it appears within the type `MySync` -note: required by `test` - --> $DIR/typeck-unsafe-always-share.rs:15:1 - | -LL | fn test(s: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `NoSync` cannot be shared between threads safely --> $DIR/typeck-unsafe-always-share.rs:30:5 | +LL | fn test(s: T) {} + | ---------------------- required by `test` +... LL | test(NoSync); | ^^^^ `NoSync` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `NoSync` -note: required by `test` - --> $DIR/typeck-unsafe-always-share.rs:15:1 - | -LL | fn test(s: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr index fd5ef4b9df15a..dd024b76c3ba7 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `dyn Foo<(isize,), isize, Output = ()>: Eq>` is not satisfied --> $DIR/unboxed-closure-sugar-default.rs:21:5 | +LL | fn eq() where A : Eq { } + | -------------------------------------------- required by `eq` +... LL | eq::, dyn Foo(isize)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq>` is not implemented for `dyn Foo<(isize,), isize, Output = ()>` - | -note: required by `eq` - --> $DIR/unboxed-closure-sugar-default.rs:14:1 - | -LL | fn eq() where A : Eq { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr index 005a86bc2178b..83754bd36ef2a 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr @@ -1,15 +1,12 @@ error[E0277]: the trait bound `dyn Foo<(char,), Output = ()>: Eq>` is not satisfied --> $DIR/unboxed-closure-sugar-equiv.rs:43:5 | +LL | fn eq>() { } + | ----------------------------------- required by `eq` +... LL | / eq::< dyn Foo<(),Output=()>, LL | | dyn Foo(char) >(); | |_______________________________________________________________________^ the trait `Eq>` is not implemented for `dyn Foo<(char,), Output = ()>` - | -note: required by `eq` - --> $DIR/unboxed-closure-sugar-equiv.rs:16:1 - | -LL | fn eq>() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr index fcf11290c81d9..d64e54a548442 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr @@ -1,15 +1,13 @@ error[E0277]: expected a `std::ops::Fn<(isize,)>` closure, found `S` --> $DIR/unboxed-closures-fnmut-as-fn.rs:28:13 | +LL | fn call_itisize>(f: &F, x: isize) -> isize { + | -------------------------------------------------------- required by `call_it` +... LL | let x = call_it(&S, 22); | ^^^^^^^ expected an `Fn<(isize,)>` closure, found `S` | = help: the trait `std::ops::Fn<(isize,)>` is not implemented for `S` -note: required by `call_it` - --> $DIR/unboxed-closures-fnmut-as-fn.rs:23:1 - | -LL | fn call_itisize>(f: &F, x: isize) -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index ca0298283661f..3d20b5df1e3f3 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -1,67 +1,57 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:13 | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | --------------------------------------------------------- required by `call_it` +... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -note: required by `call_it` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:7:1 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:13 | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | --------------------------------------------------------- required by `call_it` +... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -note: required by `call_it` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:7:1 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:13 | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | -------------------------------------------------------------------- required by `call_it_mut` +... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -note: required by `call_it_mut` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:8:1 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:13 | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | -------------------------------------------------------------------- required by `call_it_mut` +... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -note: required by `call_it_mut` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:8:1 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:24:13 | +LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } + | ----------------------------------------------------------------- required by `call_it_once` +... LL | let z = call_it_once(square, 22); | ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -note: required by `call_it_once` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:1 - | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr index 0abc58aeebfe5..f435a05e04901 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -1,67 +1,57 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-abi.rs:12:13 | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | --------------------------------------------------------- required by `call_it` +... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -note: required by `call_it` - --> $DIR/unboxed-closures-wrong-abi.rs:7:1 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-abi.rs:12:13 | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | --------------------------------------------------------- required by `call_it` +... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -note: required by `call_it` - --> $DIR/unboxed-closures-wrong-abi.rs:7:1 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-abi.rs:18:13 | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | -------------------------------------------------------------------- required by `call_it_mut` +... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -note: required by `call_it_mut` - --> $DIR/unboxed-closures-wrong-abi.rs:8:1 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-abi.rs:18:13 | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | -------------------------------------------------------------------- required by `call_it_mut` +... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -note: required by `call_it_mut` - --> $DIR/unboxed-closures-wrong-abi.rs:8:1 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-abi.rs:24:13 | +LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } + | ----------------------------------------------------------------- required by `call_it_once` +... LL | let z = call_it_once(square, 22); | ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -note: required by `call_it_once` - --> $DIR/unboxed-closures-wrong-abi.rs:9:1 - | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index 19b87ad171a51..efdb2e8efa4e8 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -1,67 +1,57 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:13 | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | --------------------------------------------------------- required by `call_it` +... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -note: required by `call_it` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:8:1 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:13 | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | --------------------------------------------------------- required by `call_it` +... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -note: required by `call_it` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:8:1 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:13 | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | -------------------------------------------------------------------- required by `call_it_mut` +... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -note: required by `call_it_mut` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:9:1 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:13 | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | -------------------------------------------------------------------- required by `call_it_mut` +... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -note: required by `call_it_mut` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:9:1 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:25:13 | +LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } + | ----------------------------------------------------------------- required by `call_it_once` +... LL | let z = call_it_once(square, 22); | ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -note: required by `call_it_once` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:1 - | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/unevaluated_fixed_size_array_len.stderr b/src/test/ui/unevaluated_fixed_size_array_len.stderr index be6ed8d56232e..2079f6fd53173 100644 --- a/src/test/ui/unevaluated_fixed_size_array_len.stderr +++ b/src/test/ui/unevaluated_fixed_size_array_len.stderr @@ -1,16 +1,14 @@ error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied --> $DIR/unevaluated_fixed_size_array_len.rs:12:5 | +LL | fn foo(); + | --------- required by `Foo::foo` +... LL | <[(); 0] as Foo>::foo() | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]` | = help: the following implementations were found: <[(); 1] as Foo> -note: required by `Foo::foo` - --> $DIR/unevaluated_fixed_size_array_len.rs:4:5 - | -LL | fn foo(); - | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/union/union-generic.stderr b/src/test/ui/union/union-generic.stderr index 6a3216db64301..f13b2def6db84 100644 --- a/src/test/ui/union/union-generic.stderr +++ b/src/test/ui/union/union-generic.stderr @@ -1,26 +1,20 @@ error[E0277]: the trait bound `std::rc::Rc: std::marker::Copy` is not satisfied --> $DIR/union-generic.rs:8:13 | +LL | union U { + | ---------------- required by `U` +... LL | let u = U { a: Rc::new(0u32) }; | ^ the trait `std::marker::Copy` is not implemented for `std::rc::Rc` - | -note: required by `U` - --> $DIR/union-generic.rs:3:1 - | -LL | union U { - | ^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::rc::Rc: std::marker::Copy` is not satisfied --> $DIR/union-generic.rs:10:13 | +LL | union U { + | ---------------- required by `U` +... LL | let u = U::> { a: Default::default() }; | ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::rc::Rc` - | -note: required by `U` - --> $DIR/union-generic.rs:3:1 - | -LL | union U { - | ^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/unsized/unsized-bare-typaram.stderr b/src/test/ui/unsized/unsized-bare-typaram.stderr index cee1459c7915d..c39c648f661c6 100644 --- a/src/test/ui/unsized/unsized-bare-typaram.stderr +++ b/src/test/ui/unsized/unsized-bare-typaram.stderr @@ -1,17 +1,14 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/unsized-bare-typaram.rs:2:23 | +LL | fn bar() { } + | ------------------ required by `bar` LL | fn foo() { bar::() } | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit = help: consider adding a `where T: std::marker::Sized` bound -note: required by `bar` - --> $DIR/unsized-bare-typaram.rs:1:1 - | -LL | fn bar() { } - | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-enum.stderr b/src/test/ui/unsized/unsized-enum.stderr index 20857a1d65e75..dff934834ef2c 100644 --- a/src/test/ui/unsized/unsized-enum.stderr +++ b/src/test/ui/unsized/unsized-enum.stderr @@ -1,17 +1,15 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/unsized-enum.rs:6:36 | +LL | enum Foo { FooSome(U), FooNone } + | ----------- required by `Foo` +LL | fn foo1() { not_sized::>() } // Hunky dory. LL | fn foo2() { not_sized::>() } | ^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit = help: consider adding a `where T: std::marker::Sized` bound -note: required by `Foo` - --> $DIR/unsized-enum.rs:4:1 - | -LL | enum Foo { FooSome(U), FooNone } - | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr index 98eecabc84cb8..1a726bb089f6e 100644 --- a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr @@ -1,17 +1,15 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized-inherent-impl-self-type.rs:7:17 | +LL | struct S5(Y); + | ---------------- required by `S5` +LL | LL | impl S5 { | ^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit = help: consider adding a `where X: std::marker::Sized` bound -note: required by `S5` - --> $DIR/unsized-inherent-impl-self-type.rs:5:1 - | -LL | struct S5(Y); - | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-struct.stderr b/src/test/ui/unsized/unsized-struct.stderr index 7add65c07866b..795115154e72b 100644 --- a/src/test/ui/unsized/unsized-struct.stderr +++ b/src/test/ui/unsized/unsized-struct.stderr @@ -1,21 +1,22 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/unsized-struct.rs:6:36 | +LL | struct Foo { data: T } + | ------------- required by `Foo` +LL | fn foo1() { not_sized::>() } // Hunky dory. LL | fn foo2() { not_sized::>() } | ^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit = help: consider adding a `where T: std::marker::Sized` bound -note: required by `Foo` - --> $DIR/unsized-struct.rs:4:1 - | -LL | struct Foo { data: T } - | ^^^^^^^^^^^^^ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/unsized-struct.rs:13:24 | +LL | fn is_sized() { } + | ---------------------- required by `is_sized` +... LL | fn bar2() { is_sized::>() } | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | @@ -23,11 +24,6 @@ LL | fn bar2() { is_sized::>() } = note: to learn more, visit = help: consider adding a `where T: std::marker::Sized` bound = note: required because it appears within the type `Bar` -note: required by `is_sized` - --> $DIR/unsized-struct.rs:1:1 - | -LL | fn is_sized() { } - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr index c39f3652b647c..f399f8ded1085 100644 --- a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr @@ -1,17 +1,15 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized-trait-impl-self-type.rs:10:17 | +LL | struct S5(Y); + | ---------------- required by `S5` +LL | LL | impl T3 for S5 { | ^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit = help: consider adding a `where X: std::marker::Sized` bound -note: required by `S5` - --> $DIR/unsized-trait-impl-self-type.rs:8:1 - | -LL | struct S5(Y); - | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unsized3.stderr b/src/test/ui/unsized3.stderr index 2c7b86c5d8284..9064aa14d429f 100644 --- a/src/test/ui/unsized3.stderr +++ b/src/test/ui/unsized3.stderr @@ -3,34 +3,33 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim | LL | f2::(x); | ^^^^^^^ doesn't have a size known at compile-time +... +LL | fn f2(x: &X) { + | --------------- required by `f2` | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit = help: consider adding a `where X: std::marker::Sized` bound -note: required by `f2` - --> $DIR/unsized3.rs:10:1 - | -LL | fn f2(x: &X) { - | ^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:18:5 | LL | f4::(x); | ^^^^^^^ doesn't have a size known at compile-time +... +LL | fn f4(x: &X) { + | ------------------ required by `f4` | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit = help: consider adding a `where X: std::marker::Sized` bound -note: required by `f4` - --> $DIR/unsized3.rs:21:1 - | -LL | fn f4(x: &X) { - | ^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:33:5 | +LL | fn f5(x: &Y) {} + | --------------- required by `f5` +... LL | f5(x1); | ^^ doesn't have a size known at compile-time | @@ -38,11 +37,6 @@ LL | f5(x1); = note: to learn more, visit = help: consider adding a `where X: std::marker::Sized` bound = note: required because it appears within the type `S` -note: required by `f5` - --> $DIR/unsized3.rs:24:1 - | -LL | fn f5(x: &Y) {} - | ^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:40:5 @@ -72,6 +66,9 @@ LL | f5(&(32, *x1)); error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:45:5 | +LL | fn f5(x: &Y) {} + | --------------- required by `f5` +... LL | f5(&(32, *x1)); | ^^ doesn't have a size known at compile-time | @@ -80,11 +77,6 @@ LL | f5(&(32, *x1)); = help: consider adding a `where X: std::marker::Sized` bound = note: required because it appears within the type `S` = note: required because it appears within the type `({integer}, S)` -note: required by `f5` - --> $DIR/unsized3.rs:24:1 - | -LL | fn f5(x: &Y) {} - | ^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/wf/wf-const-type.stderr b/src/test/ui/wf/wf-const-type.stderr index 4df429259ed1f..531aadc25dd2a 100644 --- a/src/test/ui/wf/wf-const-type.stderr +++ b/src/test/ui/wf/wf-const-type.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `NotCopy: std::marker::Copy` is not satisfied --> $DIR/wf-const-type.rs:10:12 | +LL | struct IsCopy { t: T } + | --------------------- required by `IsCopy` +... LL | const FOO: IsCopy> = IsCopy { t: None }; | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `NotCopy` | = note: required because of the requirements on the impl of `std::marker::Copy` for `std::option::Option` -note: required by `IsCopy` - --> $DIR/wf-const-type.rs:7:1 - | -LL | struct IsCopy { t: T } - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-enum-bound.stderr b/src/test/ui/wf/wf-enum-bound.stderr index de28a882f13c3..d5632f4a9c24e 100644 --- a/src/test/ui/wf/wf-enum-bound.stderr +++ b/src/test/ui/wf/wf-enum-bound.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-enum-bound.rs:9:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +LL | LL | / enum SomeEnum LL | | where T: ExtraCopy LL | | { @@ -9,11 +12,6 @@ LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-enum-bound.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-enum-fields-struct-variant.stderr b/src/test/ui/wf/wf-enum-fields-struct-variant.stderr index 6c1267cf7e1b4..51ee23fc5aa6d 100644 --- a/src/test/ui/wf/wf-enum-fields-struct-variant.stderr +++ b/src/test/ui/wf/wf-enum-fields-struct-variant.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied --> $DIR/wf-enum-fields-struct-variant.rs:13:9 | +LL | struct IsCopy { + | --------------------- required by `IsCopy` +... LL | f: IsCopy | ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A` | = help: consider adding a `where A: std::marker::Copy` bound -note: required by `IsCopy` - --> $DIR/wf-enum-fields-struct-variant.rs:7:1 - | -LL | struct IsCopy { - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-enum-fields.stderr b/src/test/ui/wf/wf-enum-fields.stderr index 9c4eec6c5fbf0..5f4e7c66f54ca 100644 --- a/src/test/ui/wf/wf-enum-fields.stderr +++ b/src/test/ui/wf/wf-enum-fields.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied --> $DIR/wf-enum-fields.rs:12:17 | +LL | struct IsCopy { + | --------------------- required by `IsCopy` +... LL | SomeVariant(IsCopy) | ^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A` | = help: consider adding a `where A: std::marker::Copy` bound -note: required by `IsCopy` - --> $DIR/wf-enum-fields.rs:7:1 - | -LL | struct IsCopy { - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-fn-where-clause.stderr b/src/test/ui/wf/wf-fn-where-clause.stderr index b50e895d8655c..4bc2e370f29fa 100644 --- a/src/test/ui/wf/wf-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-fn-where-clause.stderr @@ -1,17 +1,15 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-fn-where-clause.rs:8:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +LL | LL | / fn foo() where T: ExtraCopy LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-fn-where-clause.rs:6:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `(dyn std::marker::Copy + 'static)` cannot be known at compilation time --> $DIR/wf-fn-where-clause.rs:12:1 diff --git a/src/test/ui/wf/wf-impl-associated-type-trait.stderr b/src/test/ui/wf/wf-impl-associated-type-trait.stderr index 158b55a3f4165..ceafb4f61578b 100644 --- a/src/test/ui/wf/wf-impl-associated-type-trait.stderr +++ b/src/test/ui/wf/wf-impl-associated-type-trait.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: MyHash` is not satisfied --> $DIR/wf-impl-associated-type-trait.rs:17:5 | +LL | pub struct MySet { + | -------------------------- required by `MySet` +... LL | type Bar = MySet; | ^^^^^^^^^^^^^^^^^^^^ the trait `MyHash` is not implemented for `T` | = help: consider adding a `where T: MyHash` bound -note: required by `MySet` - --> $DIR/wf-impl-associated-type-trait.rs:8:1 - | -LL | pub struct MySet { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-arg.stderr b/src/test/ui/wf/wf-in-fn-arg.stderr index 8635dad851667..e7432f8198734 100644 --- a/src/test/ui/wf/wf-in-fn-arg.stderr +++ b/src/test/ui/wf/wf-in-fn-arg.stderr @@ -1,17 +1,15 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-in-fn-arg.rs:10:1 | +LL | struct MustBeCopy { + | ------------------------- required by `MustBeCopy` +... LL | / fn bar(_: &MustBeCopy) LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `MustBeCopy` - --> $DIR/wf-in-fn-arg.rs:6:1 - | -LL | struct MustBeCopy { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-ret.stderr b/src/test/ui/wf/wf-in-fn-ret.stderr index 3879f7b0a4bf0..005ffe84502de 100644 --- a/src/test/ui/wf/wf-in-fn-ret.stderr +++ b/src/test/ui/wf/wf-in-fn-ret.stderr @@ -1,17 +1,15 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-in-fn-ret.rs:10:1 | +LL | struct MustBeCopy { + | ------------------------- required by `MustBeCopy` +... LL | / fn bar() -> MustBeCopy LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `MustBeCopy` - --> $DIR/wf-in-fn-ret.rs:6:1 - | -LL | struct MustBeCopy { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-type-arg.stderr b/src/test/ui/wf/wf-in-fn-type-arg.stderr index 40cb4a7050cca..b4cd921040225 100644 --- a/src/test/ui/wf/wf-in-fn-type-arg.stderr +++ b/src/test/ui/wf/wf-in-fn-type-arg.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-in-fn-type-arg.rs:9:5 | +LL | struct MustBeCopy { + | ------------------------- required by `MustBeCopy` +... LL | x: fn(MustBeCopy) | ^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `MustBeCopy` - --> $DIR/wf-in-fn-type-arg.rs:3:1 - | -LL | struct MustBeCopy { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-type-ret.stderr b/src/test/ui/wf/wf-in-fn-type-ret.stderr index 059f164e25c28..988fbed8e9107 100644 --- a/src/test/ui/wf/wf-in-fn-type-ret.stderr +++ b/src/test/ui/wf/wf-in-fn-type-ret.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-in-fn-type-ret.rs:9:5 | +LL | struct MustBeCopy { + | ------------------------- required by `MustBeCopy` +... LL | x: fn() -> MustBeCopy | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `MustBeCopy` - --> $DIR/wf-in-fn-type-ret.rs:3:1 - | -LL | struct MustBeCopy { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-where-clause.stderr b/src/test/ui/wf/wf-in-fn-where-clause.stderr index 1e732a3341c0b..0af38ddcffea3 100644 --- a/src/test/ui/wf/wf-in-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-in-fn-where-clause.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-in-fn-where-clause.rs:9:1 | +LL | trait MustBeCopy { + | ------------------------ required by `MustBeCopy` +... LL | / fn bar() LL | | where T: MustBeCopy LL | | { @@ -8,11 +11,6 @@ LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `MustBeCopy` - --> $DIR/wf-in-fn-where-clause.rs:6:1 - | -LL | trait MustBeCopy { - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-obj-type-trait.stderr b/src/test/ui/wf/wf-in-obj-type-trait.stderr index 2c85dd042e7ba..0f4b4e417ca4f 100644 --- a/src/test/ui/wf/wf-in-obj-type-trait.stderr +++ b/src/test/ui/wf/wf-in-obj-type-trait.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-in-obj-type-trait.rs:11:5 | +LL | struct MustBeCopy { + | ------------------------- required by `MustBeCopy` +... LL | x: dyn Object> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `MustBeCopy` - --> $DIR/wf-in-obj-type-trait.rs:5:1 - | -LL | struct MustBeCopy { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr b/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr index b79093f7d0235..1e258864d0367 100644 --- a/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr +++ b/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr @@ -1,16 +1,14 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-inherent-impl-method-where-clause.rs:12:5 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +... LL | / fn foo(self) where T: ExtraCopy LL | | {} | |______^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-inherent-impl-method-where-clause.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-inherent-impl-where-clause.stderr b/src/test/ui/wf/wf-inherent-impl-where-clause.stderr index f10ff841acbf6..4c389b3ef3ef2 100644 --- a/src/test/ui/wf/wf-inherent-impl-where-clause.stderr +++ b/src/test/ui/wf/wf-inherent-impl-where-clause.stderr @@ -1,17 +1,15 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-inherent-impl-where-clause.rs:11:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +... LL | / impl Foo where T: ExtraCopy LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-inherent-impl-where-clause.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-static-type.stderr b/src/test/ui/wf/wf-static-type.stderr index 4234c7161b1b2..05a628d7c3e19 100644 --- a/src/test/ui/wf/wf-static-type.stderr +++ b/src/test/ui/wf/wf-static-type.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `NotCopy: std::marker::Copy` is not satisfied --> $DIR/wf-static-type.rs:10:13 | +LL | struct IsCopy { t: T } + | --------------------- required by `IsCopy` +... LL | static FOO: IsCopy> = IsCopy { t: None }; | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `NotCopy` | = note: required because of the requirements on the impl of `std::marker::Copy` for `std::option::Option` -note: required by `IsCopy` - --> $DIR/wf-static-type.rs:7:1 - | -LL | struct IsCopy { t: T } - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-struct-bound.stderr b/src/test/ui/wf/wf-struct-bound.stderr index 1fdcced90cc56..2028a0baa17fb 100644 --- a/src/test/ui/wf/wf-struct-bound.stderr +++ b/src/test/ui/wf/wf-struct-bound.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-struct-bound.rs:9:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +LL | LL | / struct SomeStruct LL | | where T: ExtraCopy LL | | { @@ -9,11 +12,6 @@ LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-struct-bound.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-struct-field.stderr b/src/test/ui/wf/wf-struct-field.stderr index e609f93ff700b..d2bff253678ee 100644 --- a/src/test/ui/wf/wf-struct-field.stderr +++ b/src/test/ui/wf/wf-struct-field.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied --> $DIR/wf-struct-field.rs:12:5 | +LL | struct IsCopy { + | --------------------- required by `IsCopy` +... LL | data: IsCopy | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A` | = help: consider adding a `where A: std::marker::Copy` bound -note: required by `IsCopy` - --> $DIR/wf-struct-field.rs:7:1 - | -LL | struct IsCopy { - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-associated-type-bound.stderr b/src/test/ui/wf/wf-trait-associated-type-bound.stderr index 658d41218e483..d5b2b5762a43a 100644 --- a/src/test/ui/wf/wf-trait-associated-type-bound.stderr +++ b/src/test/ui/wf/wf-trait-associated-type-bound.stderr @@ -1,17 +1,15 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-trait-associated-type-bound.rs:9:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +LL | LL | / trait SomeTrait { LL | | type Type1: ExtraCopy; LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-trait-associated-type-bound.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-associated-type-trait.stderr b/src/test/ui/wf/wf-trait-associated-type-trait.stderr index 70fabcd4b3074..d8ab955048239 100644 --- a/src/test/ui/wf/wf-trait-associated-type-trait.stderr +++ b/src/test/ui/wf/wf-trait-associated-type-trait.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `::Type1: std::marker::Copy` is not satisfied --> $DIR/wf-trait-associated-type-trait.rs:11:5 | +LL | struct IsCopy { x: T } + | --------------------- required by `IsCopy` +... LL | type Type2 = IsCopy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `::Type1` | = help: consider adding a `where ::Type1: std::marker::Copy` bound -note: required by `IsCopy` - --> $DIR/wf-trait-associated-type-trait.rs:7:1 - | -LL | struct IsCopy { x: T } - | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-bound.stderr b/src/test/ui/wf/wf-trait-bound.stderr index 5cc9451bf5cac..85f12b2de5489 100644 --- a/src/test/ui/wf/wf-trait-bound.stderr +++ b/src/test/ui/wf/wf-trait-bound.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied --> $DIR/wf-trait-bound.rs:9:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +LL | LL | / trait SomeTrait LL | | where T: ExtraCopy LL | | { @@ -8,11 +11,6 @@ LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` | = help: consider adding a `where U: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-trait-bound.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-default-fn-arg.stderr b/src/test/ui/wf/wf-trait-default-fn-arg.stderr index e713389223654..4d0e1f2f0f4cc 100644 --- a/src/test/ui/wf/wf-trait-default-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-arg.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied --> $DIR/wf-trait-default-fn-arg.rs:11:5 | +LL | struct Bar { value: Box } + | ----------------------- required by `Bar` +... LL | / fn bar(&self, x: &Bar) { LL | | LL | | // @@ -9,11 +12,6 @@ LL | | } | |_____^ the trait `std::cmp::Eq` is not implemented for `Self` | = help: consider adding a `where Self: std::cmp::Eq` bound -note: required by `Bar` - --> $DIR/wf-trait-default-fn-arg.rs:8:1 - | -LL | struct Bar { value: Box } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-default-fn-ret.stderr b/src/test/ui/wf/wf-trait-default-fn-ret.stderr index 5a310a826dd90..e82b76b61c4a9 100644 --- a/src/test/ui/wf/wf-trait-default-fn-ret.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-ret.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied --> $DIR/wf-trait-default-fn-ret.rs:11:5 | +LL | struct Bar { value: Box } + | ----------------------- required by `Bar` +... LL | / fn bar(&self) -> Bar { LL | | LL | | // @@ -10,11 +13,6 @@ LL | | } | |_____^ the trait `std::cmp::Eq` is not implemented for `Self` | = help: consider adding a `where Self: std::cmp::Eq` bound -note: required by `Bar` - --> $DIR/wf-trait-default-fn-ret.rs:8:1 - | -LL | struct Bar { value: Box } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr index d5a00be6d3464..6504f6698d9b1 100644 --- a/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied --> $DIR/wf-trait-default-fn-where-clause.rs:11:5 | +LL | trait Bar { } + | ---------------------- required by `Bar` +... LL | / fn bar(&self) where A: Bar { LL | | LL | | // @@ -9,11 +12,6 @@ LL | | } | |_____^ the trait `std::cmp::Eq` is not implemented for `Self` | = help: consider adding a `where Self: std::cmp::Eq` bound -note: required by `Bar` - --> $DIR/wf-trait-default-fn-where-clause.rs:8:1 - | -LL | trait Bar { } - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-fn-arg.stderr b/src/test/ui/wf/wf-trait-fn-arg.stderr index 2b26eac9c06b6..0887d4b2fcda2 100644 --- a/src/test/ui/wf/wf-trait-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-fn-arg.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied --> $DIR/wf-trait-fn-arg.rs:10:5 | +LL | struct Bar { value: Box } + | ----------------------- required by `Bar` +... LL | fn bar(&self, x: &Bar); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` | = help: consider adding a `where Self: std::cmp::Eq` bound -note: required by `Bar` - --> $DIR/wf-trait-fn-arg.rs:7:1 - | -LL | struct Bar { value: Box } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-fn-ret.stderr b/src/test/ui/wf/wf-trait-fn-ret.stderr index 70f07f02e93ea..5555081498c61 100644 --- a/src/test/ui/wf/wf-trait-fn-ret.stderr +++ b/src/test/ui/wf/wf-trait-fn-ret.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied --> $DIR/wf-trait-fn-ret.rs:10:5 | +LL | struct Bar { value: Box } + | ----------------------- required by `Bar` +... LL | fn bar(&self) -> &Bar; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` | = help: consider adding a `where Self: std::cmp::Eq` bound -note: required by `Bar` - --> $DIR/wf-trait-fn-ret.rs:7:1 - | -LL | struct Bar { value: Box } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-fn-where-clause.stderr index 2d6223e6d9332..5e8fd8982390d 100644 --- a/src/test/ui/wf/wf-trait-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-trait-fn-where-clause.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied --> $DIR/wf-trait-fn-where-clause.rs:10:5 | +LL | struct Bar { value: Box } + | ----------------------- required by `Bar` +... LL | fn bar(&self) where Self: Sized, Bar: Copy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` | = help: consider adding a `where Self: std::cmp::Eq` bound -note: required by `Bar` - --> $DIR/wf-trait-fn-where-clause.rs:7:1 - | -LL | struct Bar { value: Box } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-superbound.stderr b/src/test/ui/wf/wf-trait-superbound.stderr index a3c4ab58f65f7..377ca640536cf 100644 --- a/src/test/ui/wf/wf-trait-superbound.stderr +++ b/src/test/ui/wf/wf-trait-superbound.stderr @@ -1,16 +1,14 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/wf-trait-superbound.rs:9:1 | +LL | trait ExtraCopy { } + | ----------------------- required by `ExtraCopy` +LL | LL | / trait SomeTrait: ExtraCopy { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `ExtraCopy` - --> $DIR/wf-trait-superbound.rs:7:1 - | -LL | trait ExtraCopy { } - | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr index 125b65b1872e5..f923c6798829f 100644 --- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:13:9 | +LL | fn require_copy(x: T) {} + | ------------------------------ required by `require_copy` +... LL | require_copy(self.x); | ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `require_copy` - --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:1:1 - | -LL | fn require_copy(x: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr index eb555b181f48a..32736836ef8a3 100644 --- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr @@ -1,15 +1,13 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:18:9 | +LL | fn require_copy(x: T) {} + | ------------------------------ required by `require_copy` +... LL | require_copy(self.x); | ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound -note: required by `require_copy` - --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:1:1 - | -LL | fn require_copy(x: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr b/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr index fb69e2d141129..e59d6089ea539 100644 --- a/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr +++ b/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr @@ -1,14 +1,11 @@ error[E0277]: the trait bound `Struct: std::cmp::Eq` is not satisfied --> $DIR/where-clauses-unsatisfied.rs:6:10 | +LL | fn equal(a: &T, b: &T) -> bool where T : Eq { a == b } + | ---------------------------------------------- required by `equal` +... LL | drop(equal(&Struct, &Struct)) | ^^^^^ the trait `std::cmp::Eq` is not implemented for `Struct` - | -note: required by `equal` - --> $DIR/where-clauses-unsatisfied.rs:1:1 - | -LL | fn equal(a: &T, b: &T) -> bool where T : Eq { a == b } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index dbe68b82c24cb..32dc0e7359cbe 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,18 +1,16 @@ error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied --> $DIR/where-for-self-2.rs:21:5 | -LL | foo(&X); - | ^^^ the trait `for<'a> Bar` is not implemented for `&'a _` - | - = help: the following implementations were found: - <&'static u32 as Bar> -note: required by `foo` - --> $DIR/where-for-self-2.rs:16:1 - | LL | / fn foo(x: &T) LL | | where for<'a> &'a T: Bar LL | | {} - | |__^ + | |__- required by `foo` +... +LL | foo(&X); + | ^^^ the trait `for<'a> Bar` is not implemented for `&'a _` + | + = help: the following implementations were found: + <&'static u32 as Bar> error: aborting due to previous error From 5384d5584f6fd596df3a86e2cd4e0281b27d10db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 24 Aug 2019 14:45:03 -0700 Subject: [PATCH 369/618] Suggest call fn ctor passed as arg to fn with type param bounds --- src/librustc/traits/error_reporting.rs | 68 +++++++++++++++++-- ...as-arg-where-it-should-have-been-called.rs | 10 +++ ...rg-where-it-should-have-been-called.stderr | 14 ++++ ...as-arg-where-it-should-have-been-called.rs | 18 +++++ ...rg-where-it-should-have-been-called.stderr | 14 ++++ 5 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs create mode 100644 src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr create mode 100644 src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs create mode 100644 src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index aa0fcafbb0e6b..07083f155d62a 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1,20 +1,21 @@ use super::{ + ConstEvalFailure, + EvaluationResult, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, + ObjectSafetyViolation, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, - TraitNotObjectSafe, - ConstEvalFailure, + Overflow, PredicateObligation, SelectionContext, SelectionError, - ObjectSafetyViolation, - Overflow, + TraitNotObjectSafe, }; use crate::hir; @@ -35,7 +36,7 @@ use crate::util::nodemap::{FxHashMap, FxHashSet}; use errors::{Applicability, DiagnosticBuilder}; use std::fmt; use syntax::ast; -use syntax::symbol::sym; +use syntax::symbol::{sym, kw}; use syntax_pos::{DUMMY_SP, Span, ExpnKind}; impl<'a, 'tcx> InferCtxt<'a, 'tcx> { @@ -669,8 +670,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } else { format!( "{}the trait `{}` is not implemented for `{}`", - pre_message, - trait_ref, + pre_message, + trait_ref, trait_ref.self_ty(), ) }; @@ -689,6 +690,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err); + self.suggest_fn_call(&obligation, &mut err, &trait_ref); self.suggest_remove_reference(&obligation, &mut err, &trait_ref); self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref); @@ -956,6 +958,58 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + fn suggest_fn_call( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::Binder>, + ) { + let self_ty = trait_ref.self_ty(); + match self_ty.sty { + ty::FnDef(def_id, _) => { + // We tried to apply the bound to an `fn`. Check wether calling it + // would evaluate to a type that *would* satisfy the trait binding. + // If it would, suggest calling it: `bar(foo)` -> `bar(foo)`. This + // case is *very* to hit if `foo` is `async`. + let output_ty = self_ty.fn_sig(self.tcx).output(); + let new_trait_ref = ty::TraitRef { + def_id: trait_ref.def_id(), + substs: self.tcx.mk_substs_trait(output_ty.skip_binder(), &[]), + }; + let obligation = Obligation::new( + obligation.cause.clone(), + obligation.param_env, + new_trait_ref.to_predicate(), + ); + match self.evaluate_obligation(&obligation) { + Ok(EvaluationResult::EvaluatedToOk) | + Ok(EvaluationResult::EvaluatedToOkModuloRegions) | + Ok(EvaluationResult::EvaluatedToAmbig) => { + if let Some(hir::Node::Item(hir::Item { + ident, + node: hir::ItemKind::Fn(.., body_id), + .. + })) = self.tcx.hir().get_if_local(def_id) { + let body = self.tcx.hir().body(*body_id); + err.help(&format!( + "it looks like you forgot to use parentheses to \ + call the function: `{}({})`", + ident, + body.arguments.iter() + .map(|arg| match &arg.pat.node { + hir::PatKind::Binding(_, _, ident, None) + if ident.name != kw::SelfLower => ident.to_string(), + _ => "_".to_string(), + }).collect::>().join(", "))); + } + } + _ => {} + } + } + _ => {} + } + } + /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`, /// suggest removing these references until we reach a type that implements the trait. fn suggest_remove_reference( diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs new file mode 100644 index 0000000000000..a2d2ba145bc5e --- /dev/null +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs @@ -0,0 +1,10 @@ +// edition:2018 +use std::future::Future; + +async fn foo() {} + +fn bar(f: impl Future) {} + +fn main() { + bar(foo); //~ERROR E0277 +} diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr new file mode 100644 index 0000000000000..5735f725dc380 --- /dev/null +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `fn() -> impl std::future::Future {foo}: std::future::Future` is not satisfied + --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:9:5 + | +LL | fn bar(f: impl Future) {} + | --------------------------------- required by `bar` +... +LL | bar(foo); + | ^^^ the trait `std::future::Future` is not implemented for `fn() -> impl std::future::Future {foo}` + | + = help: it looks like you forgot to use parentheses to call the function: `foo()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs new file mode 100644 index 0000000000000..acd149c5854e8 --- /dev/null +++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs @@ -0,0 +1,18 @@ +// edition:2018 +trait T { + type O; +} + +struct S; + +impl T for S { + type O = (); +} + +fn foo() -> impl T { S } + +fn bar(f: impl T) {} + +fn main() { + bar(foo); //~ERROR E0277 +} diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr new file mode 100644 index 0000000000000..2e4505c740588 --- /dev/null +++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `fn() -> impl T {foo}: T` is not satisfied + --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:17:5 + | +LL | fn bar(f: impl T) {} + | ----------------------- required by `bar` +... +LL | bar(foo); + | ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}` + | + = help: it looks like you forgot to use parentheses to call the function: `foo()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 7604eed2a9bf5cf67f9bcf742f030148afb8fe2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 25 Aug 2019 11:27:04 -0700 Subject: [PATCH 370/618] review comments: reword comment --- src/librustc/traits/error_reporting.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 07083f155d62a..ff3626ffb8576 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -967,10 +967,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let self_ty = trait_ref.self_ty(); match self_ty.sty { ty::FnDef(def_id, _) => { - // We tried to apply the bound to an `fn`. Check wether calling it - // would evaluate to a type that *would* satisfy the trait binding. - // If it would, suggest calling it: `bar(foo)` -> `bar(foo)`. This - // case is *very* to hit if `foo` is `async`. + // We tried to apply the bound to an `fn`. Check whether calling it would evaluate + // to a type that *would* satisfy the trait binding. If it would, suggest calling + // it: `bar(foo)` -> `bar(foo)`. This case is *very* likely to be hit if `foo` is + // `async`. let output_ty = self_ty.fn_sig(self.tcx).output(); let new_trait_ref = ty::TraitRef { def_id: trait_ref.def_id(), From 9d15b6fb95d7aed3bcadaadaf0516c4733c4f439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 31 Aug 2019 00:15:52 -0700 Subject: [PATCH 371/618] fix rebase --- src/librustc/traits/error_reporting.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index ff3626ffb8576..181efeb2f985b 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -995,7 +995,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "it looks like you forgot to use parentheses to \ call the function: `{}({})`", ident, - body.arguments.iter() + body.params.iter() .map(|arg| match &arg.pat.node { hir::PatKind::Binding(_, _, ident, None) if ident.name != kw::SelfLower => ident.to_string(), From c621919deb00448e2287213a0d0bc65ff382af66 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 31 Aug 2019 15:35:20 +0100 Subject: [PATCH 372/618] Kill borrows from assignments after generating new borrows --- src/librustc_mir/dataflow/impls/borrows.rs | 8 ++++---- src/test/ui/nll/self-assign-ref-mut.rs | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/nll/self-assign-ref-mut.rs diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 018fd2e97b264..2ea6c4ae10fdc 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -269,10 +269,6 @@ impl<'a, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'tcx> { debug!("Borrows::statement_effect: stmt={:?}", stmt); match stmt.kind { mir::StatementKind::Assign(ref lhs, ref rhs) => { - // Make sure there are no remaining borrows for variables - // that are assigned over. - self.kill_borrows_on_place(trans, lhs); - if let mir::Rvalue::Ref(_, _, ref place) = **rhs { if place.ignore_borrow( self.tcx, @@ -287,6 +283,10 @@ impl<'a, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'tcx> { trans.gen(*index); } + + // Make sure there are no remaining borrows for variables + // that are assigned over. + self.kill_borrows_on_place(trans, lhs); } mir::StatementKind::StorageDead(local) => { diff --git a/src/test/ui/nll/self-assign-ref-mut.rs b/src/test/ui/nll/self-assign-ref-mut.rs new file mode 100644 index 0000000000000..1ca4cf3a775ca --- /dev/null +++ b/src/test/ui/nll/self-assign-ref-mut.rs @@ -0,0 +1,20 @@ +// Check that `*y` isn't borrowed after `y = y`. + +// check-pass + +fn main() { + let mut x = 1; + { + let mut y = &mut x; + y = y; + y; + } + x; + { + let mut y = &mut x; + y = y; + y = y; + y; + } + x; +} From c8e474871ab5c13b0bdd92caecfb0bbc99f96541 Mon Sep 17 00:00:00 2001 From: John Erickson Date: Fri, 9 Aug 2019 06:49:10 -0700 Subject: [PATCH 373/618] Update BufWriter example to include call to flush() --- src/libstd/io/buffered.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index aaf628e6c260f..70d80a2ea9025 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -364,10 +364,10 @@ impl Seek for BufReader { /// times. It also provides no advantage when writing to a destination that is /// in memory, like a `Vec`. /// -/// When the `BufWriter` is dropped, the contents of its buffer will be written -/// out. However, any errors that happen in the process of flushing the buffer -/// when the writer is dropped will be ignored. Code that wishes to handle such -/// errors must manually call [`flush`] before the writer is dropped. +/// It is critical to call [`flush`] before `BufWriter` is dropped. Though +/// dropping will attempt to flush the the contents of the buffer, any errors +/// that happen in the process will be ignored. Calling ['flush'] ensures that +/// the buffer is empty and all errors have been observed. /// /// # Examples /// @@ -398,11 +398,12 @@ impl Seek for BufReader { /// for i in 0..10 { /// stream.write(&[i+1]).unwrap(); /// } +/// stream.flush().unwrap(); /// ``` /// /// By wrapping the stream with a `BufWriter`, these ten writes are all grouped -/// together by the buffer, and will all be written out in one system call when -/// the `stream` is dropped. +/// together by the buffer and will all be written out in one system call when +/// the `stream` is flushed. /// /// [`Write`]: ../../std/io/trait.Write.html /// [`TcpStream::write`]: ../../std/net/struct.TcpStream.html#method.write From cccce09dda14a3a76a61fc3abade19479a927534 Mon Sep 17 00:00:00 2001 From: John Erickson Date: Fri, 9 Aug 2019 07:36:39 -0700 Subject: [PATCH 374/618] Add in generic type to description of BufReader and BufWriter --- src/libstd/io/buffered.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 70d80a2ea9025..2dc7d6fe6d2ac 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -9,21 +9,21 @@ use crate::io::{self, Initializer, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom, IoSliceMut}; use crate::memchr; -/// The `BufReader` struct adds buffering to any reader. +/// The `BufReader` struct adds buffering to any reader. /// /// It can be excessively inefficient to work directly with a [`Read`] instance. /// For example, every call to [`read`][`TcpStream::read`] on [`TcpStream`] -/// results in a system call. A `BufReader` performs large, infrequent reads on +/// results in a system call. A `BufReader` performs large, infrequent reads on /// the underlying [`Read`] and maintains an in-memory buffer of the results. /// -/// `BufReader` can improve the speed of programs that make *small* and +/// `BufReader` can improve the speed of programs that make *small* and /// *repeated* read calls to the same file or network socket. It does not /// help when reading very large amounts at once, or reading just one or a few /// times. It also provides no advantage when reading from a source that is /// already in memory, like a `Vec`. /// -/// When the `BufReader` is dropped, the contents of its buffer will be -/// discarded. Creating multiple instances of a `BufReader` on the same +/// When the `BufReader` is dropped, the contents of its buffer will be +/// discarded. Creating multiple instances of a `BufReader` on the same /// stream can cause data loss. /// /// [`Read`]: ../../std/io/trait.Read.html @@ -56,7 +56,7 @@ pub struct BufReader { } impl BufReader { - /// Creates a new `BufReader` with a default buffer capacity. The default is currently 8 KB, + /// Creates a new `BufReader` with a default buffer capacity. The default is currently 8 KB, /// but may change in the future. /// /// # Examples @@ -76,7 +76,7 @@ impl BufReader { BufReader::with_capacity(DEFAULT_BUF_SIZE, inner) } - /// Creates a new `BufReader` with the specified buffer capacity. + /// Creates a new `BufReader` with the specified buffer capacity. /// /// # Examples /// @@ -177,7 +177,7 @@ impl BufReader { &self.buf[self.pos..self.cap] } - /// Unwraps this `BufReader`, returning the underlying reader. + /// Unwraps this `BufReader`, returning the underlying reader. /// /// Note that any leftover data in the internal buffer is lost. /// @@ -304,7 +304,7 @@ impl Seek for BufReader { /// Seek to an offset, in bytes, in the underlying reader. /// /// The position used for seeking with `SeekFrom::Current(_)` is the - /// position the underlying reader would be at if the `BufReader` had no + /// position the underlying reader would be at if the `BufReader` had no /// internal buffer. /// /// Seeking always discards the internal buffer, even if the seek position @@ -355,16 +355,16 @@ impl Seek for BufReader { /// It can be excessively inefficient to work directly with something that /// implements [`Write`]. For example, every call to /// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A -/// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying +/// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying /// writer in large, infrequent batches. /// -/// `BufWriter` can improve the speed of programs that make *small* and +/// `BufWriter` can improve the speed of programs that make *small* and /// *repeated* write calls to the same file or network socket. It does not /// help when writing very large amounts at once, or writing just one or a few /// times. It also provides no advantage when writing to a destination that is /// in memory, like a `Vec`. /// -/// It is critical to call [`flush`] before `BufWriter` is dropped. Though +/// It is critical to call [`flush`] before `BufWriter` is dropped. Though /// dropping will attempt to flush the the contents of the buffer, any errors /// that happen in the process will be ignored. Calling ['flush'] ensures that /// the buffer is empty and all errors have been observed. @@ -386,7 +386,7 @@ impl Seek for BufReader { /// /// Because we're not buffering, we write each one in turn, incurring the /// overhead of a system call per byte written. We can fix this with a -/// `BufWriter`: +/// `BufWriter`: /// /// ```no_run /// use std::io::prelude::*; @@ -401,7 +401,7 @@ impl Seek for BufReader { /// stream.flush().unwrap(); /// ``` /// -/// By wrapping the stream with a `BufWriter`, these ten writes are all grouped +/// By wrapping the stream with a `BufWriter`, these ten writes are all grouped /// together by the buffer and will all be written out in one system call when /// the `stream` is flushed. /// @@ -448,7 +448,7 @@ pub struct BufWriter { pub struct IntoInnerError(W, Error); impl BufWriter { - /// Creates a new `BufWriter` with a default buffer capacity. The default is currently 8 KB, + /// Creates a new `BufWriter` with a default buffer capacity. The default is currently 8 KB, /// but may change in the future. /// /// # Examples @@ -464,7 +464,7 @@ impl BufWriter { BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner) } - /// Creates a new `BufWriter` with the specified buffer capacity. + /// Creates a new `BufWriter` with the specified buffer capacity. /// /// # Examples /// @@ -565,7 +565,7 @@ impl BufWriter { &self.buf } - /// Unwraps this `BufWriter`, returning the underlying writer. + /// Unwraps this `BufWriter`, returning the underlying writer. /// /// The buffer is written out before returning the writer. /// From 1b946106b7955d3dcde26719b9b62a5a2c4b78fe Mon Sep 17 00:00:00 2001 From: John Erickson Date: Mon, 12 Aug 2019 15:36:11 -0700 Subject: [PATCH 375/618] clarify that not all errors are observed --- src/libstd/io/buffered.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 2dc7d6fe6d2ac..9593a1bae0a3c 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -366,8 +366,9 @@ impl Seek for BufReader { /// /// It is critical to call [`flush`] before `BufWriter` is dropped. Though /// dropping will attempt to flush the the contents of the buffer, any errors -/// that happen in the process will be ignored. Calling ['flush'] ensures that -/// the buffer is empty and all errors have been observed. +/// that happen in the process of dropping will be ignored. Calling ['flush'] +/// ensures that the buffer is empty and thus dropping will not even attempt +/// file operations. /// /// # Examples /// From 7bb2d8b0765e6737f43b501135d91bc8ab64db7a Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 31 Aug 2019 15:43:24 +0100 Subject: [PATCH 376/618] Slightly clean up the error for recursive `async fn` * Make it clear that type erasure is required, not just pointer indirection. * Don't make the message specific to direct recursion. --- src/librustc_typeck/check/mod.rs | 4 ++-- .../ui/async-await/recursive-async-impl-trait-type.stderr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a80550486d627..7855008a28221 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1420,8 +1420,8 @@ fn check_opaque_for_cycles<'tcx>( tcx.sess, span, E0733, "recursion in an `async fn` requires boxing", ) - .span_label(span, "an `async fn` cannot invoke itself directly") - .note("a recursive `async fn` must be rewritten to return a boxed future.") + .span_label(span, "recursive `async fn`") + .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`.") .emit(); } else { let mut err = struct_span_err!( diff --git a/src/test/ui/async-await/recursive-async-impl-trait-type.stderr b/src/test/ui/async-await/recursive-async-impl-trait-type.stderr index 8781a9c444d0a..9ee014021804e 100644 --- a/src/test/ui/async-await/recursive-async-impl-trait-type.stderr +++ b/src/test/ui/async-await/recursive-async-impl-trait-type.stderr @@ -2,9 +2,9 @@ error[E0733]: recursion in an `async fn` requires boxing --> $DIR/recursive-async-impl-trait-type.rs:5:40 | LL | async fn recursive_async_function() -> () { - | ^^ an `async fn` cannot invoke itself directly + | ^^ recursive `async fn` | - = note: a recursive `async fn` must be rewritten to return a boxed future. + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`. error: aborting due to previous error From 877faf38440ada48b0c27100fa3c456b35bc5612 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 31 Aug 2019 15:44:09 +0100 Subject: [PATCH 377/618] Check impl trait substs when checking for recursive types This prevents mutual `async fn` recursion --- src/librustc/ty/util.rs | 6 ++-- ...utually-recursive-async-impl-trait-type.rs | 13 +++++++ ...lly-recursive-async-impl-trait-type.stderr | 19 ++++++++++ ...-impl-trait-type--through-non-recursize.rs | 25 +++++++++++++ ...l-trait-type--through-non-recursize.stderr | 35 +++++++++++++++++++ 5 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs create mode 100644 src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr create mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs create mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 7a77418050cdb..a08c82a0ae82f 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -709,8 +709,10 @@ impl<'tcx> TyCtxt<'tcx> { substs: SubstsRef<'tcx>, ) -> Option> { if self.found_recursion { - None - } else if self.seen_opaque_tys.insert(def_id) { + return None; + } + let substs = substs.fold_with(self); + if self.seen_opaque_tys.insert(def_id) { let generic_ty = self.tcx.type_of(def_id); let concrete_ty = generic_ty.subst(self.tcx, substs); let expanded_ty = self.fold_ty(concrete_ty); diff --git a/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs new file mode 100644 index 0000000000000..bb2a61f03ce1f --- /dev/null +++ b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs @@ -0,0 +1,13 @@ +// edition:2018 +// Test that impl trait does not allow creating recursive types that are +// otherwise forbidden when using `async` and `await`. + +async fn rec_1() { //~ ERROR recursion in an `async fn` + rec_2().await; +} + +async fn rec_2() { //~ ERROR recursion in an `async fn` + rec_1().await; +} + +fn main() {} diff --git a/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr new file mode 100644 index 0000000000000..9249308936e54 --- /dev/null +++ b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr @@ -0,0 +1,19 @@ +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/mutually-recursive-async-impl-trait-type.rs:5:18 + | +LL | async fn rec_1() { + | ^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`. + +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18 + | +LL | async fn rec_2() { + | ^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`. + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0733`. diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs new file mode 100644 index 0000000000000..cfd9c0ec5b45b --- /dev/null +++ b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs @@ -0,0 +1,25 @@ +// Test that impl trait does not allow creating recursive types that are +// otherwise forbidden. Even when there's an opaque type in another crate +// hiding this. + +fn id(t: T) -> impl Sized { t } + +fn recursive_id() -> impl Sized { //~ ERROR opaque type expands to a recursive type + id(recursive_id2()) +} + +fn recursive_id2() -> impl Sized { //~ ERROR opaque type expands to a recursive type + id(recursive_id()) +} + +fn wrap(t: T) -> impl Sized { (t,) } + +fn recursive_wrap() -> impl Sized { //~ ERROR opaque type expands to a recursive type + wrap(recursive_wrap2()) +} + +fn recursive_wrap2() -> impl Sized { //~ ERROR opaque type expands to a recursive type + wrap(recursive_wrap()) +} + +fn main() {} diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr new file mode 100644 index 0000000000000..7572c6c1bf057 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr @@ -0,0 +1,35 @@ +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:7:22 + | +LL | fn recursive_id() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: type resolves to itself + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:11:23 + | +LL | fn recursive_id2() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: type resolves to itself + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:17:24 + | +LL | fn recursive_wrap() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: expanded type is `((impl Sized,),)` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:21:25 + | +LL | fn recursive_wrap2() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: expanded type is `((impl Sized,),)` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0720`. From e2e1175ce25b6a69954b0ad3cdb15c1b684b1d92 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sat, 31 Aug 2019 23:09:37 +0800 Subject: [PATCH 378/618] Update sync condvar doc style --- src/libstd/sync/condvar.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index aeff57716e86b..65ce19f2a1b3a 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -28,14 +28,14 @@ impl WaitTimeoutResult { /// once the boolean has been updated and notified. /// /// ``` - /// use std::sync::{Arc, Mutex, Condvar}; + /// use std::sync::{Arc, Condvar, Mutex}; /// use std::thread; /// use std::time::Duration; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); /// let pair2 = pair.clone(); /// - /// thread::spawn(move|| { + /// thread::spawn(move || { /// let (lock, cvar) = &*pair2; /// /// // Let's wait 20 milliseconds before notifying the condvar. From 823c3b984541b13c2083b7bd8025d8d679a2c13b Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Sat, 31 Aug 2019 17:01:56 +0200 Subject: [PATCH 379/618] Improve documentation around allocation accessors --- src/librustc/mir/interpret/allocation.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 8f47bf9d0fd5a..8e824aeb7916a 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -581,8 +581,10 @@ impl<'tcx, Tag, Extra> Allocation { /// Run-length encoding of the undef mask. /// Used to copy parts of a mask multiple times to another allocation. pub struct AllocationDefinedness { + /// The lengths of ranges that are run-length encoded. ranges: smallvec::SmallVec::<[u64; 1]>, - first: bool, + /// The definedness of the first range. + initial: bool, } /// Transferring the definedness mask to other allocations. @@ -606,9 +608,9 @@ impl Allocation { // where each element toggles the state let mut ranges = smallvec::SmallVec::<[u64; 1]>::new(); - let first = self.undef_mask.get(src.offset); + let initial = self.undef_mask.get(src.offset); let mut cur_len = 1; - let mut cur = first; + let mut cur = initial; for i in 1..size.bytes() { // FIXME: optimize to bitshift the current undef block's bits and read the top bit @@ -623,7 +625,7 @@ impl Allocation { ranges.push(cur_len); - AllocationDefinedness { ranges, first, } + AllocationDefinedness { ranges, initial, } } /// Apply multiple instances of the run-length encoding to the undef_mask. @@ -640,7 +642,7 @@ impl Allocation { self.undef_mask.set_range_inbounds( dest.offset, dest.offset + size * repeat, - defined.first, + defined.initial, ); return; } @@ -648,7 +650,7 @@ impl Allocation { for mut j in 0..repeat { j *= size.bytes(); j += dest.offset.bytes(); - let mut cur = defined.first; + let mut cur = defined.initial; for range in &defined.ranges { let old_j = j; j += range; @@ -725,9 +727,9 @@ impl Allocation { // shift offsets from source allocation to destination allocation offset + dest_offset - src.offset, reloc, - ) + ) }) - ); + ); } AllocationRelocations { @@ -735,6 +737,9 @@ impl Allocation { } } + /// Apply a relocation copy. + /// The affected range, as defined in the parameters to `prepare_relocation_copy` is expected + /// to be clear of relocations. pub fn mark_relocation_range( &mut self, relocations: AllocationRelocations, From 754a875e15f778ed5bdd49b4208956b3003949c4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 31 Aug 2019 16:31:50 +0100 Subject: [PATCH 380/618] Add some more tests for underscore imports --- .../auxiliary/duplicate.rs | 0 .../auxiliary/underscore-imports.rs | 0 .../basic.rs | 0 .../basic.stderr | 0 src/test/ui/underscore-imports/cycle.rs | 18 +++++++++++++++ .../duplicate.rs | 0 .../intercrate.rs | 0 src/test/ui/underscore-imports/shadow.rs | 23 +++++++++++++++++++ src/test/ui/underscore-imports/shadow.stderr | 13 +++++++++++ .../unused-2018.rs | 0 .../unused-2018.stderr | 0 11 files changed, 54 insertions(+) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/auxiliary/duplicate.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/auxiliary/underscore-imports.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/basic.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/basic.stderr (100%) create mode 100644 src/test/ui/underscore-imports/cycle.rs rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/duplicate.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/intercrate.rs (100%) create mode 100644 src/test/ui/underscore-imports/shadow.rs create mode 100644 src/test/ui/underscore-imports/shadow.stderr rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/unused-2018.rs (100%) rename src/test/ui/{rfc-2166-underscore-imports => underscore-imports}/unused-2018.stderr (100%) diff --git a/src/test/ui/rfc-2166-underscore-imports/auxiliary/duplicate.rs b/src/test/ui/underscore-imports/auxiliary/duplicate.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/auxiliary/duplicate.rs rename to src/test/ui/underscore-imports/auxiliary/duplicate.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs b/src/test/ui/underscore-imports/auxiliary/underscore-imports.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs rename to src/test/ui/underscore-imports/auxiliary/underscore-imports.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.rs b/src/test/ui/underscore-imports/basic.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/basic.rs rename to src/test/ui/underscore-imports/basic.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.stderr b/src/test/ui/underscore-imports/basic.stderr similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/basic.stderr rename to src/test/ui/underscore-imports/basic.stderr diff --git a/src/test/ui/underscore-imports/cycle.rs b/src/test/ui/underscore-imports/cycle.rs new file mode 100644 index 0000000000000..bacf9b2d5a96a --- /dev/null +++ b/src/test/ui/underscore-imports/cycle.rs @@ -0,0 +1,18 @@ +// Check that cyclic glob imports are allowed with underscore imports + +// check-pass + +mod x { + pub use crate::y::*; + pub use std::ops::Deref as _; +} + +mod y { + pub use crate::x::*; + pub use std::ops::Deref as _; +} + +pub fn main() { + use x::*; + (&0).deref(); +} diff --git a/src/test/ui/rfc-2166-underscore-imports/duplicate.rs b/src/test/ui/underscore-imports/duplicate.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/duplicate.rs rename to src/test/ui/underscore-imports/duplicate.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/intercrate.rs b/src/test/ui/underscore-imports/intercrate.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/intercrate.rs rename to src/test/ui/underscore-imports/intercrate.rs diff --git a/src/test/ui/underscore-imports/shadow.rs b/src/test/ui/underscore-imports/shadow.rs new file mode 100644 index 0000000000000..325f2001b9ede --- /dev/null +++ b/src/test/ui/underscore-imports/shadow.rs @@ -0,0 +1,23 @@ +// Check that underscore imports don't cause glob imports to be unshadowed + +mod a { + pub use std::ops::Deref as Shadow; +} + +mod b { + pub use crate::a::*; + macro_rules! m { + ($i:ident) => { pub struct $i; } + } + m!(Shadow); +} + +mod c { + use crate::b::Shadow as _; // Only imports the struct + + fn f(x: &()) { + x.deref(); //~ ERROR no method named `deref` found + } +} + +fn main() {} diff --git a/src/test/ui/underscore-imports/shadow.stderr b/src/test/ui/underscore-imports/shadow.stderr new file mode 100644 index 0000000000000..92adca2c70490 --- /dev/null +++ b/src/test/ui/underscore-imports/shadow.stderr @@ -0,0 +1,13 @@ +error[E0599]: no method named `deref` found for type `&()` in the current scope + --> $DIR/shadow.rs:19:11 + | +LL | x.deref(); + | ^^^^^ + | + = help: items from traits can only be used if the trait is in scope + = note: the following trait is implemented but not in scope, perhaps add a `use` for it: + `use std::ops::Deref;` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs b/src/test/ui/underscore-imports/unused-2018.rs similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/unused-2018.rs rename to src/test/ui/underscore-imports/unused-2018.rs diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr b/src/test/ui/underscore-imports/unused-2018.stderr similarity index 100% rename from src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr rename to src/test/ui/underscore-imports/unused-2018.stderr From c4d0c285fe19a921e75002866b2cfdf1d0f59370 Mon Sep 17 00:00:00 2001 From: Julian Gehring Date: Sat, 31 Aug 2019 17:36:55 +0100 Subject: [PATCH 381/618] Fix word repetition in str documentation Fixes a few repetitions of "like like" in the `trim*` methods documentation of `str`. --- src/libcore/str/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 752c372e93e3a..5e5b5593fd8a7 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -3558,7 +3558,7 @@ impl str { /// A string is a sequence of bytes. `start` in this context means the first /// position of that byte string; for a left-to-right language like English or /// Russian, this will be left side, and for right-to-left languages like - /// like Arabic or Hebrew, this will be the right side. + /// Arabic or Hebrew, this will be the right side. /// /// # Examples /// @@ -3595,7 +3595,7 @@ impl str { /// A string is a sequence of bytes. `end` in this context means the last /// position of that byte string; for a left-to-right language like English or /// Russian, this will be right side, and for right-to-left languages like - /// like Arabic or Hebrew, this will be the left side. + /// Arabic or Hebrew, this will be the left side. /// /// # Examples /// @@ -3762,7 +3762,7 @@ impl str { /// A string is a sequence of bytes. `start` in this context means the first /// position of that byte string; for a left-to-right language like English or /// Russian, this will be left side, and for right-to-left languages like - /// like Arabic or Hebrew, this will be the right side. + /// Arabic or Hebrew, this will be the right side. /// /// # Examples /// @@ -3801,7 +3801,7 @@ impl str { /// A string is a sequence of bytes. `end` in this context means the last /// position of that byte string; for a left-to-right language like English or /// Russian, this will be right side, and for right-to-left languages like - /// like Arabic or Hebrew, this will be the left side. + /// Arabic or Hebrew, this will be the left side. /// /// # Examples /// From f3c435eb780dec5c1d390a3b43cdfb4f1528d70d Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Sat, 31 Aug 2019 21:21:29 +0200 Subject: [PATCH 382/618] Reorder AllocationDefinedness members This improves the clarity of the documentation a bit since they can reference each other when reading the member docs in sequence. --- src/librustc/mir/interpret/allocation.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 8e824aeb7916a..db24c14083768 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -581,10 +581,11 @@ impl<'tcx, Tag, Extra> Allocation { /// Run-length encoding of the undef mask. /// Used to copy parts of a mask multiple times to another allocation. pub struct AllocationDefinedness { - /// The lengths of ranges that are run-length encoded. - ranges: smallvec::SmallVec::<[u64; 1]>, /// The definedness of the first range. initial: bool, + /// The lengths of ranges that are run-length encoded. + /// The definedness of the ranges alternate starting with `initial`. + ranges: smallvec::SmallVec::<[u64; 1]>, } /// Transferring the definedness mask to other allocations. From aee6cd937a3fff26a5d13f0a8570cafe5fb8a11c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 31 Aug 2019 13:40:20 -0700 Subject: [PATCH 383/618] Fix nll tests --- .../expect-fn-supply-fn.nll.stderr | 45 ++++++++----------- .../ui/kindck/kindck-send-object1.nll.stderr | 16 +++---- 2 files changed, 24 insertions(+), 37 deletions(-) diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr index 7e4ac4e8ce656..565c60e5216dd 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr @@ -1,53 +1,44 @@ error[E0631]: type mismatch in closure arguments --> $DIR/expect-fn-supply-fn.rs:30:5 | -LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` - | | - | expected signature of `fn(fn(&'a u32), &i32) -> _` - | -note: required by `with_closure_expecting_fn_with_free_region` - --> $DIR/expect-fn-supply-fn.rs:1:1 - | LL | / fn with_closure_expecting_fn_with_free_region(_: F) LL | | where F: for<'a> FnOnce(fn(&'a u32), &i32) LL | | { LL | | } - | |_^ + | |_- required by `with_closure_expecting_fn_with_free_region` +... +LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` + | | + | expected signature of `fn(fn(&'a u32), &i32) -> _` error[E0631]: type mismatch in closure arguments --> $DIR/expect-fn-supply-fn.rs:37:5 | -LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` - | | - | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` - | -note: required by `with_closure_expecting_fn_with_bound_region` - --> $DIR/expect-fn-supply-fn.rs:6:1 - | LL | / fn with_closure_expecting_fn_with_bound_region(_: F) LL | | where F: FnOnce(fn(&u32), &i32) LL | | { LL | | } - | |_^ + | |_- required by `with_closure_expecting_fn_with_bound_region` +... +LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` + | | + | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` error[E0631]: type mismatch in closure arguments --> $DIR/expect-fn-supply-fn.rs:46:5 | -LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` - | | - | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` - | -note: required by `with_closure_expecting_fn_with_bound_region` - --> $DIR/expect-fn-supply-fn.rs:6:1 - | LL | / fn with_closure_expecting_fn_with_bound_region(_: F) LL | | where F: FnOnce(fn(&u32), &i32) LL | | { LL | | } - | |_^ + | |_- required by `with_closure_expecting_fn_with_bound_region` +... +LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` + | | + | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` error: aborting due to 3 previous errors diff --git a/src/test/ui/kindck/kindck-send-object1.nll.stderr b/src/test/ui/kindck/kindck-send-object1.nll.stderr index 998dc90456f14..c7d18cd8b8bb1 100644 --- a/src/test/ui/kindck/kindck-send-object1.nll.stderr +++ b/src/test/ui/kindck/kindck-send-object1.nll.stderr @@ -1,31 +1,27 @@ error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely --> $DIR/kindck-send-object1.rs:10:5 | +LL | fn assert_send() { } + | -------------------------------- required by `assert_send` +... LL | assert_send::<&'a dyn Dummy>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'a)` = note: required because of the requirements on the impl of `std::marker::Send` for `&'a (dyn Dummy + 'a)` -note: required by `assert_send` - --> $DIR/kindck-send-object1.rs:5:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely --> $DIR/kindck-send-object1.rs:29:5 | +LL | fn assert_send() { } + | -------------------------------- required by `assert_send` +... LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `(dyn Dummy + 'a)` = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(dyn Dummy + 'a)>` = note: required because it appears within the type `std::boxed::Box<(dyn Dummy + 'a)>` -note: required by `assert_send` - --> $DIR/kindck-send-object1.rs:5:1 - | -LL | fn assert_send() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors From 84567190e0d36f9a61f9bc833bd9fa559aeb0089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 31 Aug 2019 13:42:53 -0700 Subject: [PATCH 384/618] Use saturating_sub --- src/librustc_errors/emitter.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 02473cc86bdff..a0ce761cfa277 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -146,12 +146,12 @@ impl Margin { } else if self.label_right - self.span_left <= self.column_width { // Attempt to fit the code window considering only the spans and labels. let padding_left = (self.column_width - (self.label_right - self.span_left)) / 2; - self.computed_left = max(self.span_left, padding_left) - padding_left; + self.computed_left = self.span_left.saturating_sub(padding_left); self.computed_right = self.computed_left + self.column_width; } else if self.span_right - self.span_left <= self.column_width { // Attempt to fit the code window considering the spans and labels plus padding. let padding_left = (self.column_width - (self.span_right - self.span_left)) / 5 * 2; - self.computed_left = max(self.span_left, padding_left) - padding_left; + self.computed_left = self.span_left.saturating_sub(padding_left); self.computed_right = self.computed_left + self.column_width; } else { // Mostly give up but still don't show the full line. self.computed_left = self.span_left; @@ -1304,11 +1304,13 @@ impl EmitterWriter { }; let column_width = if let Some(width) = self.terminal_width { - max(width, code_offset) - code_offset + width.saturating_sub(code_offset) } else if self.ui_testing { 140 } else { - term_size::dimensions().map(|(w, _)| w - code_offset).unwrap_or(std::usize::MAX) + term_size::dimensions() + .map(|(w, _)| w.saturating_sub(code_offset)) + .unwrap_or(std::usize::MAX) }; let margin = Margin::new( From 5e933b490b17de43b5c9b45b77088732f17b7ffd Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 31 Aug 2019 15:13:16 -0400 Subject: [PATCH 385/618] Add x86_64-linux-kernel target This adds a target specification for Linux kernel modules on x86_64, as well as base code that can be shared with other architectures. --- src/librustc_target/spec/linux_kernel_base.rs | 26 ++++++++++++++++ src/librustc_target/spec/mod.rs | 3 ++ .../spec/x86_64_linux_kernel.rs | 31 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 src/librustc_target/spec/linux_kernel_base.rs create mode 100644 src/librustc_target/spec/x86_64_linux_kernel.rs diff --git a/src/librustc_target/spec/linux_kernel_base.rs b/src/librustc_target/spec/linux_kernel_base.rs new file mode 100644 index 0000000000000..fae44836fa821 --- /dev/null +++ b/src/librustc_target/spec/linux_kernel_base.rs @@ -0,0 +1,26 @@ +use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelroLevel, TargetOptions}; +use std::default::Default; + +pub fn opts() -> TargetOptions { + let mut pre_link_args = LinkArgs::new(); + pre_link_args.insert( + LinkerFlavor::Gcc, + vec!["-Wl,--as-needed".to_string(), "-Wl,-z,noexecstack".to_string()], + ); + + TargetOptions { + disable_redzone: true, + panic_strategy: PanicStrategy::Abort, + stack_probes: true, + eliminate_frame_pointer: false, + linker_is_gnu: true, + position_independent_executables: true, + needs_plt: true, + relro_level: RelroLevel::Full, + relocation_model: "static".to_string(), + target_family: Some("unix".to_string()), + pre_link_args, + + ..Default::default() + } +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 539e28f7088e3..503d8a08b6f4f 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -53,6 +53,7 @@ mod freebsd_base; mod haiku_base; mod hermit_base; mod linux_base; +mod linux_kernel_base; mod linux_musl_base; mod openbsd_base; mod netbsd_base; @@ -386,6 +387,8 @@ supported_targets! { ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi), ("aarch64-linux-android", aarch64_linux_android), + ("x86_64-linux-kernel", x86_64_linux_kernel), + ("aarch64-unknown-freebsd", aarch64_unknown_freebsd), ("armv6-unknown-freebsd", armv6_unknown_freebsd), ("armv7-unknown-freebsd", armv7_unknown_freebsd), diff --git a/src/librustc_target/spec/x86_64_linux_kernel.rs b/src/librustc_target/spec/x86_64_linux_kernel.rs new file mode 100644 index 0000000000000..a80b021208ed7 --- /dev/null +++ b/src/librustc_target/spec/x86_64_linux_kernel.rs @@ -0,0 +1,31 @@ +// This defines the amd64 target for the Linux Kernel. See the linux-kernel-base module for +// generic Linux kernel options. + +use crate::spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::linux_kernel_base::opts(); + base.cpu = "x86-64".to_string(); + base.max_atomic_width = Some(64); + base.features = + "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float" + .to_string(); + base.code_model = Some("kernel".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + + Ok(Target { + // FIXME: Some dispute, the linux-on-clang folks think this should use "Linux" + llvm_target: "x86_64-elf".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), + target_os: "none".to_string(), + target_env: "gnu".to_string(), + target_vendor: "unknown".to_string(), + arch: "x86_64".to_string(), + linker_flavor: LinkerFlavor::Gcc, + + options: base, + }) +} From cab607edcfe556343aa4fcb3de6229a790fc5e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 31 Aug 2019 18:34:50 -0700 Subject: [PATCH 386/618] Emit a single error on if expr with expectation and no else clause --- src/librustc_typeck/check/_match.rs | 41 ++++++--- src/test/ui/if/if-without-else-as-fn-expr.rs | 6 -- .../ui/if/if-without-else-as-fn-expr.stderr | 83 ++----------------- src/test/ui/issues/issue-50577.rs | 1 - src/test/ui/issues/issue-50577.stderr | 15 +--- 5 files changed, 38 insertions(+), 108 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index efc37cc04b212..3983a3b820391 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -112,23 +112,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.diverges.set(pats_diverge); - let arm_ty = self.check_expr_with_expectation(&arm.body, expected); - all_arms_diverge &= self.diverges.get(); - - let span = expr.span; - - if source_if { + let arm_ty = if source_if { let then_expr = &arms[0].body; match (i, if_no_else) { - (0, _) => coercion.coerce(self, &self.misc(span), &arm.body, arm_ty), - (_, true) => self.if_fallback_coercion(span, then_expr, &mut coercion), + (0, _) => { + let arm_ty = self.check_expr_with_expectation(&arm.body, expected); + all_arms_diverge &= self.diverges.get(); + coercion.coerce(self, &self.misc(expr.span), &arm.body, arm_ty); + arm_ty + } + (_, true) => { + if self.if_fallback_coercion(expr.span, then_expr, &mut coercion) { + tcx.types.err + } else { + let arm_ty = self.check_expr_with_expectation(&arm.body, expected); + all_arms_diverge &= self.diverges.get(); + arm_ty + } + } (_, _) => { + let arm_ty = self.check_expr_with_expectation(&arm.body, expected); + all_arms_diverge &= self.diverges.get(); let then_ty = prior_arm_ty.unwrap(); - let cause = self.if_cause(span, then_expr, &arm.body, then_ty, arm_ty); + let cause = self.if_cause(expr.span, then_expr, &arm.body, then_ty, arm_ty); coercion.coerce(self, &cause, &arm.body, arm_ty); + arm_ty } } } else { + let arm_ty = self.check_expr_with_expectation(&arm.body, expected); + all_arms_diverge &= self.diverges.get(); let arm_span = if let hir::ExprKind::Block(blk, _) = &arm.body.node { // Point at the block expr instead of the entire block blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span) @@ -139,7 +152,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The reason for the first arm to fail is not that the match arms diverge, // but rather that there's a prior obligation that doesn't hold. 0 => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)), - _ => (span, ObligationCauseCode::MatchExpressionArm { + _ => (expr.span, ObligationCauseCode::MatchExpressionArm { arm_span, source: match_src, prior_arms: other_arms.clone(), @@ -153,7 +166,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if other_arms.len() > 5 { other_arms.remove(0); } - } + arm_ty + }; prior_arm_ty = Some(arm_ty); } @@ -185,11 +199,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, then_expr: &'tcx hir::Expr, coercion: &mut CoerceMany<'tcx, '_, rustc::hir::Arm>, - ) { + ) -> bool { // If this `if` expr is the parent's function return expr, // the cause of the type coercion is the return type, point at it. (#25228) let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, span); let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse); + let mut error = false; coercion.coerce_forced_unit(self, &cause, &mut |err| { if let Some((span, msg)) = &ret_reason { err.span_label(*span, msg.as_str()); @@ -200,7 +215,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } err.note("`if` expressions without `else` evaluate to `()`"); err.help("consider adding an `else` block that evaluates to the expected type"); + error = true; }, ret_reason.is_none()); + error } fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, span: Span) -> Option<(Span, String)> { diff --git a/src/test/ui/if/if-without-else-as-fn-expr.rs b/src/test/ui/if/if-without-else-as-fn-expr.rs index 15892de83854c..826371be35f45 100644 --- a/src/test/ui/if/if-without-else-as-fn-expr.rs +++ b/src/test/ui/if/if-without-else-as-fn-expr.rs @@ -3,7 +3,6 @@ fn foo(bar: usize) -> usize { return 3; } //~^^^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] } fn foo2(bar: usize) -> usize { @@ -11,7 +10,6 @@ fn foo2(bar: usize) -> usize { return 3; }; //~^^^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] x } @@ -20,7 +18,6 @@ fn foo3(bar: usize) -> usize { 3 } //~^^^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] } fn foo_let(bar: usize) -> usize { @@ -28,7 +25,6 @@ fn foo_let(bar: usize) -> usize { return 3; } //~^^^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] } fn foo2_let(bar: usize) -> usize { @@ -36,7 +32,6 @@ fn foo2_let(bar: usize) -> usize { return 3; }; //~^^^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] x } @@ -45,7 +40,6 @@ fn foo3_let(bar: usize) -> usize { 3 } //~^^^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] } // FIXME(60254): deduplicate first error in favor of second. diff --git a/src/test/ui/if/if-without-else-as-fn-expr.stderr b/src/test/ui/if/if-without-else-as-fn-expr.stderr index 06600b1cb9aea..b49c2aa6319df 100644 --- a/src/test/ui/if/if-without-else-as-fn-expr.stderr +++ b/src/test/ui/if/if-without-else-as-fn-expr.stderr @@ -1,14 +1,3 @@ -error[E0308]: mismatched types - --> $DIR/if-without-else-as-fn-expr.rs:2:5 - | -LL | / if bar % 5 == 0 { -LL | | return 3; -LL | | } - | |_____^ expected usize, found () - | - = note: expected type `usize` - found type `()` - error[E0317]: if may be missing an else clause --> $DIR/if-without-else-as-fn-expr.rs:2:5 | @@ -24,20 +13,8 @@ LL | | } = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error[E0308]: mismatched types - --> $DIR/if-without-else-as-fn-expr.rs:10:20 - | -LL | let x: usize = if bar % 5 == 0 { - | ____________________^ -LL | | return 3; -LL | | }; - | |_____^ expected usize, found () - | - = note: expected type `usize` - found type `()` - error[E0317]: if may be missing an else clause - --> $DIR/if-without-else-as-fn-expr.rs:10:20 + --> $DIR/if-without-else-as-fn-expr.rs:9:20 | LL | let x: usize = if bar % 5 == 0 { | _________-__________^ @@ -52,19 +29,8 @@ LL | | }; = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error[E0308]: mismatched types - --> $DIR/if-without-else-as-fn-expr.rs:19:5 - | -LL | / if bar % 5 == 0 { -LL | | 3 -LL | | } - | |_____^ expected usize, found () - | - = note: expected type `usize` - found type `()` - error[E0317]: if may be missing an else clause - --> $DIR/if-without-else-as-fn-expr.rs:19:5 + --> $DIR/if-without-else-as-fn-expr.rs:17:5 | LL | fn foo3(bar: usize) -> usize { | ----- expected `usize` because of this return type @@ -78,19 +44,8 @@ LL | | } = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error[E0308]: mismatched types - --> $DIR/if-without-else-as-fn-expr.rs:27:5 - | -LL | / if let 0 = 1 { -LL | | return 3; -LL | | } - | |_____^ expected usize, found () - | - = note: expected type `usize` - found type `()` - error[E0317]: if may be missing an else clause - --> $DIR/if-without-else-as-fn-expr.rs:27:5 + --> $DIR/if-without-else-as-fn-expr.rs:24:5 | LL | fn foo_let(bar: usize) -> usize { | ----- expected `usize` because of this return type @@ -104,20 +59,8 @@ LL | | } = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error[E0308]: mismatched types - --> $DIR/if-without-else-as-fn-expr.rs:35:20 - | -LL | let x: usize = if let 0 = 1 { - | ____________________^ -LL | | return 3; -LL | | }; - | |_____^ expected usize, found () - | - = note: expected type `usize` - found type `()` - error[E0317]: if may be missing an else clause - --> $DIR/if-without-else-as-fn-expr.rs:35:20 + --> $DIR/if-without-else-as-fn-expr.rs:31:20 | LL | let x: usize = if let 0 = 1 { | _________-__________^ @@ -132,19 +75,8 @@ LL | | }; = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error[E0308]: mismatched types - --> $DIR/if-without-else-as-fn-expr.rs:44:5 - | -LL | / if let 0 = 1 { -LL | | 3 -LL | | } - | |_____^ expected usize, found () - | - = note: expected type `usize` - found type `()` - error[E0317]: if may be missing an else clause - --> $DIR/if-without-else-as-fn-expr.rs:44:5 + --> $DIR/if-without-else-as-fn-expr.rs:39:5 | LL | fn foo3_let(bar: usize) -> usize { | ----- expected `usize` because of this return type @@ -158,7 +90,6 @@ LL | | } = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error: aborting due to 12 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0308, E0317. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0317`. diff --git a/src/test/ui/issues/issue-50577.rs b/src/test/ui/issues/issue-50577.rs index bf892a8daa27f..f0f1dc6c28667 100644 --- a/src/test/ui/issues/issue-50577.rs +++ b/src/test/ui/issues/issue-50577.rs @@ -2,6 +2,5 @@ fn main() { enum Foo { Drop = assert_eq!(1, 1) //~^ ERROR if may be missing an else clause - //~| ERROR mismatched types [E0308] } } diff --git a/src/test/ui/issues/issue-50577.stderr b/src/test/ui/issues/issue-50577.stderr index 413c8c5c80b52..0c3ba2ea4f94d 100644 --- a/src/test/ui/issues/issue-50577.stderr +++ b/src/test/ui/issues/issue-50577.stderr @@ -1,13 +1,3 @@ -error[E0308]: mismatched types - --> $DIR/issue-50577.rs:3:16 - | -LL | Drop = assert_eq!(1, 1) - | ^^^^^^^^^^^^^^^^ expected isize, found () - | - = note: expected type `isize` - found type `()` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - error[E0317]: if may be missing an else clause --> $DIR/issue-50577.rs:3:16 | @@ -23,7 +13,6 @@ LL | Drop = assert_eq!(1, 1) = help: consider adding an `else` block that evaluates to the expected type = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0308, E0317. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0317`. From aae2b245e4c3958ca37d6eaa58b89d955d0b66e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 31 Aug 2019 18:42:13 -0700 Subject: [PATCH 387/618] deduplicate code --- src/librustc_typeck/check/_match.rs | 40 ++++++++++++----------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 3983a3b820391..63d059bdf2a80 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -112,36 +112,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.diverges.set(pats_diverge); - let arm_ty = if source_if { + let arm_ty = if source_if && if_no_else && i != 0 && self.if_fallback_coercion( + expr.span, + &arms[0].body, + &mut coercion, + ) { + tcx.types.err + } else { + // Only call this if this is not an `if` expr with an expected type and no `else` + // clause to avoid duplicated type errors. (#60254) + let arm_ty = self.check_expr_with_expectation(&arm.body, expected); + all_arms_diverge &= self.diverges.get(); + arm_ty + }; + if source_if { let then_expr = &arms[0].body; match (i, if_no_else) { - (0, _) => { - let arm_ty = self.check_expr_with_expectation(&arm.body, expected); - all_arms_diverge &= self.diverges.get(); - coercion.coerce(self, &self.misc(expr.span), &arm.body, arm_ty); - arm_ty - } - (_, true) => { - if self.if_fallback_coercion(expr.span, then_expr, &mut coercion) { - tcx.types.err - } else { - let arm_ty = self.check_expr_with_expectation(&arm.body, expected); - all_arms_diverge &= self.diverges.get(); - arm_ty - } - } + (0, _) => coercion.coerce(self, &self.misc(expr.span), &arm.body, arm_ty), + (_, true) => {} // Handled above to avoid duplicated type errors (#60254). (_, _) => { - let arm_ty = self.check_expr_with_expectation(&arm.body, expected); - all_arms_diverge &= self.diverges.get(); let then_ty = prior_arm_ty.unwrap(); let cause = self.if_cause(expr.span, then_expr, &arm.body, then_ty, arm_ty); coercion.coerce(self, &cause, &arm.body, arm_ty); - arm_ty } } } else { - let arm_ty = self.check_expr_with_expectation(&arm.body, expected); - all_arms_diverge &= self.diverges.get(); let arm_span = if let hir::ExprKind::Block(blk, _) = &arm.body.node { // Point at the block expr instead of the entire block blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span) @@ -166,8 +161,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if other_arms.len() > 5 { other_arms.remove(0); } - arm_ty - }; + } prior_arm_ty = Some(arm_ty); } From 6ed50f4777b65f117648dc2f524d684424c2730d Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Sat, 31 Aug 2019 20:00:08 -0700 Subject: [PATCH 388/618] Rename test locals to work around LLDB bug LLDB's expression parser can't unambiguously resolve local variables in some cases, as described in #47938. Work around this by using names that don't shadow direct submodules of `core`. --- src/test/debuginfo/boxed-struct.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/debuginfo/boxed-struct.rs b/src/test/debuginfo/boxed-struct.rs index c0ff90c3ffb9b..8709fb681704b 100644 --- a/src/test/debuginfo/boxed-struct.rs +++ b/src/test/debuginfo/boxed-struct.rs @@ -8,11 +8,11 @@ // gdb-command:run -// gdb-command:print *unique +// gdb-command:print *boxed_with_padding // gdbg-check:$1 = {x = 99, y = 999, z = 9999, w = 99999} // gdbr-check:$1 = boxed_struct::StructWithSomePadding {x: 99, y: 999, z: 9999, w: 99999} -// gdb-command:print *unique_dtor +// gdb-command:print *boxed_with_dtor // gdbg-check:$2 = {x = 77, y = 777, z = 7777, w = 77777} // gdbr-check:$2 = boxed_struct::StructWithDestructor {x: 77, y: 777, z: 7777, w: 77777} @@ -21,13 +21,13 @@ // lldb-command:run -// lldb-command:print *unique +// lldb-command:print *boxed_with_padding // lldbg-check:[...]$0 = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 } -// lldbr-check:(boxed_struct::StructWithSomePadding) *unique = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 } +// lldbr-check:(boxed_struct::StructWithSomePadding) *boxed_with_padding = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 } -// lldb-command:print *unique_dtor +// lldb-command:print *boxed_with_dtor // lldbg-check:[...]$1 = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 } -// lldbr-check:(boxed_struct::StructWithDestructor) *unique_dtor = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 } +// lldbr-check:(boxed_struct::StructWithDestructor) *boxed_with_dtor = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 } #![allow(unused_variables)] #![feature(box_syntax)] @@ -54,9 +54,9 @@ impl Drop for StructWithDestructor { fn main() { - let unique: Box<_> = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }; + let boxed_with_padding: Box<_> = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }; - let unique_dtor: Box<_> = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }; + let boxed_with_dtor: Box<_> = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }; zzz(); // #break } From f0b30c7ded69123cffe26b54fb1feedf45d1c5a8 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Sun, 1 Sep 2019 08:49:26 +0200 Subject: [PATCH 389/618] remove the unstable rustdoc parameter --linker use the code generation parameter -Clinker (same parameter as rustc) to control what linker to use for building the rustdoc test executables. closes: #63816 --- src/bootstrap/bin/rustdoc.rs | 5 ++++- src/doc/rustdoc/src/unstable-features.md | 13 ------------- src/librustdoc/config.rs | 5 ----- src/librustdoc/lib.rs | 3 --- src/librustdoc/test.rs | 3 --- src/test/run-make-fulldeps/tools.mk | 2 +- src/tools/compiletest/src/runtest.rs | 6 +----- 7 files changed, 6 insertions(+), 31 deletions(-) diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index 766a3463ecd8b..a13ff69a7b56f 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -5,6 +5,7 @@ use std::env; use std::process::Command; use std::path::PathBuf; +use std::ffi::OsString; fn main() { let args = env::args_os().skip(1).collect::>(); @@ -44,7 +45,9 @@ fn main() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } if let Some(linker) = env::var_os("RUSTC_TARGET_LINKER") { - cmd.arg("--linker").arg(linker).arg("-Z").arg("unstable-options"); + let mut arg = OsString::from("-Clinker="); + arg.push(&linker); + cmd.arg(arg); } // Bootstrap's Cargo-command builder sets this variable to the current Rust version; let's pick diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 6e32468b64dee..993fc8412836e 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -311,19 +311,6 @@ When `rustdoc` receives this flag, it will print an extra "Version (version)" in the crate root's docs. You can use this flag to differentiate between different versions of your library's documentation. -### `--linker`: control the linker used for documentation tests - -Using this flag looks like this: - -```bash -$ rustdoc --test src/lib.rs -Z unstable-options --linker foo -$ rustdoc --test README.md -Z unstable-options --linker foo -``` - -When `rustdoc` runs your documentation tests, it needs to compile and link the tests as executables -before running them. This flag can be used to change the linker used on these executables. It's -equivalent to passing `-C linker=foo` to `rustc`. - ### `--sort-modules-by-appearance`: control how items on module pages are sorted Using this flag looks like this: diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 30b1706f29464..d261408fc148a 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -60,8 +60,6 @@ pub struct Options { pub edition: Edition, /// The path to the sysroot. Used during the compilation process. pub maybe_sysroot: Option, - /// Linker to use when building doctests. - pub linker: Option, /// Lint information passed over the command-line. pub lint_opts: Vec<(String, Level)>, /// Whether to ask rustc to describe the lints it knows. Practically speaking, this will not be @@ -130,7 +128,6 @@ impl fmt::Debug for Options { .field("target", &self.target) .field("edition", &self.edition) .field("maybe_sysroot", &self.maybe_sysroot) - .field("linker", &self.linker) .field("lint_opts", &self.lint_opts) .field("describe_lints", &self.describe_lints) .field("lint_cap", &self.lint_cap) @@ -454,7 +451,6 @@ impl Options { let playground_url = matches.opt_str("playground-url"); let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from); let display_warnings = matches.opt_present("display-warnings"); - let linker = matches.opt_str("linker").map(PathBuf::from); let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance"); let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default(); let enable_minification = !matches.opt_present("disable-minification"); @@ -489,7 +485,6 @@ impl Options { target, edition, maybe_sysroot, - linker, lint_opts, describe_lints, lint_cap, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 87dac0f226896..dfa0db0d23b74 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -242,9 +242,6 @@ fn opts() -> Vec { unstable("crate-version", |o| { o.optopt("", "crate-version", "crate version to print into documentation", "VERSION") }), - unstable("linker", |o| { - o.optopt("", "linker", "linker used for building executable test code", "PATH") - }), unstable("sort-modules-by-appearance", |o| { o.optflag("", "sort-modules-by-appearance", "sort modules by where they appear in the \ program, rather than alphabetically") diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 31c0b85a481f5..41df1ff8cd04e 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -266,9 +266,6 @@ fn run_test( for codegen_options_str in &options.codegen_options_strs { compiler.arg("-C").arg(&codegen_options_str); } - if let Some(linker) = options.linker { - compiler.arg(&format!("-C linker={:?}", linker)); - } if no_run { compiler.arg("--emit=metadata"); } diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk index 3b4df73cdfd6d..9a113b7fa6370 100644 --- a/src/test/run-make-fulldeps/tools.mk +++ b/src/test/run-make-fulldeps/tools.mk @@ -12,7 +12,7 @@ RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) $(RUSTFLAGS) RUSTDOC := $(BARE_RUSTDOC) -L $(TARGET_RPATH_DIR) ifdef RUSTC_LINKER RUSTC := $(RUSTC) -Clinker=$(RUSTC_LINKER) -RUSTDOC := $(RUSTDOC) --linker $(RUSTC_LINKER) -Z unstable-options +RUSTDOC := $(RUSTDOC) -Clinker=$(RUSTC_LINKER) endif #CC := $(CC) -L $(TMPDIR) HTMLDOCCK := $(PYTHON) $(S)/src/etc/htmldocck.py diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3da6be74129f4..03c5177ee5202 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1603,11 +1603,7 @@ impl<'test> TestCx<'test> { .args(&self.props.compile_flags); if let Some(ref linker) = self.config.linker { - rustdoc - .arg("--linker") - .arg(linker) - .arg("-Z") - .arg("unstable-options"); + rustdoc.arg(format!("-Clinker={}", linker)); } self.compose_and_run_compiler(rustdoc, None) From e5530519502baf3ae37fa94eda27c2461d8c94aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Sep 2019 00:08:44 -0700 Subject: [PATCH 390/618] review comment --- src/librustc/traits/error_reporting.rs | 3 +-- ...-ctor-passed-as-arg-where-it-should-have-been-called.stderr | 2 +- ...-ctor-passed-as-arg-where-it-should-have-been-called.stderr | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 181efeb2f985b..b38e1f5f83937 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -992,8 +992,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { })) = self.tcx.hir().get_if_local(def_id) { let body = self.tcx.hir().body(*body_id); err.help(&format!( - "it looks like you forgot to use parentheses to \ - call the function: `{}({})`", + "use parentheses to call the function: `{}({})`", ident, body.params.iter() .map(|arg| match &arg.pat.node { diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 5735f725dc380..3141b1b65f9ba 100644 --- a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -7,7 +7,7 @@ LL | fn bar(f: impl Future) {} LL | bar(foo); | ^^^ the trait `std::future::Future` is not implemented for `fn() -> impl std::future::Future {foo}` | - = help: it looks like you forgot to use parentheses to call the function: `foo()` + = help: use parentheses to call the function: `foo()` error: aborting due to previous error diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 2e4505c740588..2cc4653fabe2d 100644 --- a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -7,7 +7,7 @@ LL | fn bar(f: impl T) {} LL | bar(foo); | ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}` | - = help: it looks like you forgot to use parentheses to call the function: `foo()` + = help: use parentheses to call the function: `foo()` error: aborting due to previous error From a9ce33c059d0a91fb12a79d75aa1a868d76bf6f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Sep 2019 02:22:42 -0700 Subject: [PATCH 391/618] Account for arbitrary self types in E0599 --- src/librustc/ty/context.rs | 18 +++++ src/librustc_typeck/check/expr.rs | 72 +++++++++++++------ src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/method/suggest.rs | 9 +-- src/librustc_typeck/check/mod.rs | 2 +- .../no-method-suggested-traits.stderr | 8 +++ .../point-at-arbitrary-self-type-method.rs | 9 +++ ...point-at-arbitrary-self-type-method.stderr | 15 ++++ ...int-at-arbitrary-self-type-trait-method.rs | 10 +++ ...at-arbitrary-self-type-trait-method.stderr | 18 +++++ src/test/ui/traits/trait-item-privacy.stderr | 7 ++ 11 files changed, 144 insertions(+), 26 deletions(-) create mode 100644 src/test/ui/self/point-at-arbitrary-self-type-method.rs create mode 100644 src/test/ui/self/point-at-arbitrary-self-type-method.stderr create mode 100644 src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs create mode 100644 src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index e240e0df8b948..f355e231914d2 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2402,6 +2402,24 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_generic_adt(def_id, ty) } + #[inline] + pub fn mk_pin(self, ty: Ty<'tcx>) -> Ty<'tcx> { + let def_id = self.require_lang_item(lang_items::PinTypeLangItem, None); + self.mk_generic_adt(def_id, ty) + } + + #[inline] + pub fn mk_rc(self, ty: Ty<'tcx>) -> Ty<'tcx> { + let def_id = self.require_lang_item(lang_items::Rc, None); + self.mk_generic_adt(def_id, ty) + } + + #[inline] + pub fn mk_arc(self, ty: Ty<'tcx>) -> Ty<'tcx> { + let def_id = self.require_lang_item(lang_items::Arc, None); + self.mk_generic_adt(def_id, ty) + } + #[inline] pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> { let def_id = self.require_lang_item(lang_items::MaybeUninitLangItem, None); diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index a53fb12367d0e..efff8bcdacbcf 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -12,7 +12,7 @@ use crate::check::fatally_break_rust; use crate::check::report_unexpected_variant_res; use crate::check::Needs; use crate::check::TupleArgumentsFlag::DontTupleArguments; -use crate::check::method::SelfSource; +use crate::check::method::{probe, SelfSource}; use crate::util::common::ErrorReported; use crate::util::nodemap::FxHashMap; use crate::astconv::AstConv as _; @@ -775,35 +775,65 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // no need to check for bot/err -- callee does that let rcvr_t = self.structurally_resolved_type(args[0].span, rcvr_t); - let method = match self.lookup_method(rcvr_t, - segment, - span, - expr, - rcvr) { + let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t| { + if let Ok(pick) = self.lookup_probe( + span, + segment.ident, + new_rcvr_t, + rcvr, + probe::ProbeScope::AllTraits, + ) { + err.span_label( + pick.item.ident.span, + &format!("the method is available for `{}` here", new_rcvr_t), + ); + } + }; + + let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr) { Ok(method) => { self.write_method_call(expr.hir_id, method); Ok(method) } Err(error) => { if segment.ident.name != kw::Invalid { - self.report_method_error(span, - rcvr_t, - segment.ident, - SelfSource::MethodCall(rcvr), - error, - Some(args)); + if let Some(mut err) = self.report_method_error( + span, + rcvr_t, + segment.ident, + SelfSource::MethodCall(rcvr), + error, + Some(args), + ) { + if let ty::Adt(..) = rcvr_t.sty { + // Try alternative arbitrary self types that could fulfill this call. + // FIXME: probe for all types that *could* be arbitrary self-types, not + // just this whitelist. + let box_rcvr_t = self.tcx.mk_box(rcvr_t); + try_alt_rcvr(&mut err, box_rcvr_t); + let pin_rcvr_t = self.tcx.mk_pin(rcvr_t); + try_alt_rcvr(&mut err, pin_rcvr_t); + let arc_rcvr_t = self.tcx.mk_arc(rcvr_t); + try_alt_rcvr(&mut err, arc_rcvr_t); + let rc_rcvr_t = self.tcx.mk_rc(rcvr_t); + try_alt_rcvr(&mut err, rc_rcvr_t); + } + err.emit(); + } } Err(()) } }; // Call the generic checker. - self.check_method_argument_types(span, - expr.span, - method, - &args[1..], - DontTupleArguments, - expected) + self.check_method_argument_types( + span, + expr.span, + method, + &args[1..], + DontTupleArguments, + expected, + ) } fn check_expr_cast( @@ -1466,8 +1496,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let struct_variant_def = def.non_enum_variant(); let field_names = self.available_field_names(struct_variant_def); if !field_names.is_empty() { - err.note(&format!("available fields are: {}", - self.name_series_display(field_names))); + err.note(&format!( + "available fields are: {}", + self.name_series_display(field_names), + )); } } } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index a7e4f8e5c6289..1509c0f8a2196 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -245,7 +245,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(result.callee) } - fn lookup_probe( + pub fn lookup_probe( &self, span: Span, method_name: ast::Ident, diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 440e7e5d0e314..72e6f59715960 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -69,12 +69,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { source: SelfSource<'b>, error: MethodError<'tcx>, args: Option<&'tcx [hir::Expr]>, - ) { + ) -> Option> { let orig_span = span; let mut span = span; // Avoid suggestions when we don't know what's going on. if rcvr_ty.references_error() { - return; + return None; } let print_disambiguation_help = | @@ -314,7 +314,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => {} } err.emit(); - return; + return None; } else { span = item_name.span; let mut err = struct_span_err!( @@ -529,7 +529,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - err.emit(); + return Some(err); } MethodError::Ambiguity(sources) => { @@ -573,6 +573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bug!("no return type expectations but got BadReturnType") } } + None } fn suggest_use_candidates(&self, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a80550486d627..2d9cacea68f31 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3580,7 +3580,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { SelfSource::QPath(qself), error, None, - ); + ).map(|mut e| e.emit()); } result }); diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index d980d7cccadd5..002b60f9f258d 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -49,6 +49,14 @@ LL | use foo::Bar; error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&char>>` in the current scope --> $DIR/no-method-suggested-traits.rs:32:43 | +LL | fn method(&self) {} + | ------ + | | + | the method is available for `std::boxed::Box>>` here + | the method is available for `std::pin::Pin>>` here + | the method is available for `std::sync::Arc>>` here + | the method is available for `std::rc::Rc>>` here +... LL | std::rc::Rc::new(&mut Box::new(&'a')).method(); | ^^^^^^ | diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.rs b/src/test/ui/self/point-at-arbitrary-self-type-method.rs new file mode 100644 index 0000000000000..0f7deeacad292 --- /dev/null +++ b/src/test/ui/self/point-at-arbitrary-self-type-method.rs @@ -0,0 +1,9 @@ +struct A; + +impl A { + fn foo(self: Box) {} +} + +fn main() { + A.foo(); //~ ERROR E0599 +} diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr new file mode 100644 index 0000000000000..06dad7caa6735 --- /dev/null +++ b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `foo` found for type `A` in the current scope + --> $DIR/point-at-arbitrary-self-type-method.rs:8:7 + | +LL | struct A; + | --------- method `foo` not found for this +... +LL | fn foo(self: Box) {} + | --- the method is available for `std::boxed::Box` here +... +LL | A.foo(); + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs new file mode 100644 index 0000000000000..53d992771186f --- /dev/null +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs @@ -0,0 +1,10 @@ +trait B { fn foo(self: Box); } +struct A; + +impl B for A { + fn foo(self: Box) {} +} + +fn main() { + A.foo() //~ ERROR E0599 +} diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr new file mode 100644 index 0000000000000..90cd3b8074580 --- /dev/null +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -0,0 +1,18 @@ +error[E0599]: no method named `foo` found for type `A` in the current scope + --> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7 + | +LL | trait B { fn foo(self: Box); } + | --- the method is available for `std::boxed::Box` here +LL | struct A; + | --------- method `foo` not found for this +... +LL | A.foo() + | ^^^ + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `foo`, perhaps you need to implement it: + candidate #1: `B` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index de699a69fa8bc..ce2919c8e7741 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -17,6 +17,13 @@ error[E0599]: no method named `b` found for type `S` in the current scope LL | struct S; | --------- method `b` not found for this ... +LL | fn b(&self) { } + | - + | | + | the method is available for `std::boxed::Box` here + | the method is available for `std::sync::Arc` here + | the method is available for `std::rc::Rc` here +... LL | S.b(); | ^ | From 84ccbe2076cf37bc13c32a89ccc57a57281b8708 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 1 Sep 2019 12:15:33 +0200 Subject: [PATCH 392/618] librustc_errors: Extract sugg/subst handling into method An initial refactoring before working on #61809. This moves the whole block into a method so that it can be reused in the annotate-snippet output. It's already used in the new emitter, but there's no UI tests with suggestions included in this PR. A first look at some UI tests with suggestions showed that there's some more work to do in [annotate-snippet-rs][annotate-snippet-rs] before the new output is closer to the current one. --- .../annotate_snippet_emitter_writer.rs | 4 +- src/librustc_errors/emitter.rs | 40 ++++++++++++++----- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index 255af3122e70c..3bed5d81dc514 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -30,10 +30,8 @@ pub struct AnnotateSnippetEmitterWriter { impl Emitter for AnnotateSnippetEmitterWriter { /// The entry point for the diagnostics generation fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { - let primary_span = db.span.clone(); let children = db.children.clone(); - // FIXME(#59346): Collect suggestions (see emitter.rs) - let suggestions: &[_] = &[]; + let (primary_span, suggestions) = self.primary_span_formatted(&db); // FIXME(#59346): Add `fix_multispans_in_std_macros` function from emitter.rs diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 77d373e7a8ca8..0a9c927ef40a1 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -191,16 +191,25 @@ pub trait Emitter { fn should_show_explain(&self) -> bool { true } -} -impl Emitter for EmitterWriter { - fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { + /// Formats the substitutions of the primary_span + /// + /// The are a lot of conditions to this method, but in short: + /// + /// * If the current `Diagnostic` has only one visible `CodeSuggestion`, + /// we format the `help` suggestion depending on the content of the + /// substitutions. In that case, we return the modified span only. + /// + /// * If the current `Diagnostic` has multiple suggestions, + /// we return the original `primary_span` and the original suggestions. + fn primary_span_formatted<'a>( + &mut self, + db: &'a DiagnosticBuilder<'_> + ) -> (MultiSpan, &'a [CodeSuggestion]) { let mut primary_span = db.span.clone(); - let mut children = db.children.clone(); - let mut suggestions: &[_] = &[]; - if let Some((sugg, rest)) = db.suggestions.split_first() { if rest.is_empty() && + // ^ if there is only one suggestion // don't display multi-suggestions as labels sugg.substitutions.len() == 1 && // don't display multipart suggestions as labels @@ -216,21 +225,34 @@ impl Emitter for EmitterWriter { { let substitution = &sugg.substitutions[0].parts[0].snippet.trim(); let msg = if substitution.len() == 0 || sugg.style.hide_inline() { - // This substitution is only removal or we explicitly don't want to show the - // code inline, don't show it + // This substitution is only removal OR we explicitly don't want to show the + // code inline (`hide_inline`). Therefore, we don't show the substitution. format!("help: {}", sugg.msg) } else { + // Show the default suggestion text with the substitution format!("help: {}: `{}`", sugg.msg, substitution) }; primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg); + + // We return only the modified primary_span + (primary_span, &[]) } else { // if there are multiple suggestions, print them all in full // to be consistent. We could try to figure out if we can // make one (or the first one) inline, but that would give // undue importance to a semi-random suggestion - suggestions = &db.suggestions; + (primary_span, &db.suggestions) } + } else { + (primary_span, &db.suggestions) } + } +} + +impl Emitter for EmitterWriter { + fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { + let mut children = db.children.clone(); + let (mut primary_span, suggestions) = self.primary_span_formatted(&db); self.fix_multispans_in_std_macros(&mut primary_span, &mut children, From 35c9e5f1229d8b634ebd98c49e35c74e237e17f7 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 1 Sep 2019 22:05:50 +0900 Subject: [PATCH 393/618] Fix const_err with `-(-0.0)` --- src/librustc_mir/transform/const_prop.rs | 14 +------------- src/test/ui/consts/const-err2.rs | 1 - src/test/ui/consts/const-err2.stderr | 20 +++++++------------- src/test/ui/consts/issue-64059.rs | 5 +++++ 4 files changed, 13 insertions(+), 27 deletions(-) create mode 100644 src/test/ui/consts/issue-64059.rs diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index f261fdc268b5b..00118c05c9451 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -6,7 +6,7 @@ use std::cell::Cell; use rustc::hir::def::DefKind; use rustc::mir::{ AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, - Local, NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind, + Local, NullOp, StatementKind, Statement, LocalKind, Static, StaticKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem, SourceScope, SourceScopeLocalData, LocalDecl, }; @@ -407,18 +407,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let arg = self.eval_operand(arg, source_info)?; let val = self.use_ecx(source_info, |this| { let prim = this.ecx.read_immediate(arg)?; - match op { - UnOp::Neg => { - // Need to do overflow check here: For actual CTFE, MIR - // generation emits code that does this before calling the op. - if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) { - throw_panic!(OverflowNeg) - } - } - UnOp::Not => { - // Cannot overflow - } - } // Now run the actual operation. this.ecx.unary_op(op, prim) })?; diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs index a5f685a159b39..5aab1972a9bd5 100644 --- a/src/test/ui/consts/const-err2.rs +++ b/src/test/ui/consts/const-err2.rs @@ -13,7 +13,6 @@ fn black_box(_: T) { fn main() { let a = -std::i8::MIN; - //~^ ERROR const_err let b = 200u8 + 200u8 + 200u8; //~^ ERROR const_err let c = 200u8 * 4; diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr index 659c3afc618a9..63d037764a13d 100644 --- a/src/test/ui/consts/const-err2.stderr +++ b/src/test/ui/consts/const-err2.stderr @@ -1,8 +1,8 @@ error: this expression will panic at runtime - --> $DIR/const-err2.rs:15:13 + --> $DIR/const-err2.rs:16:13 | -LL | let a = -std::i8::MIN; - | ^^^^^^^^^^^^^ attempt to negate with overflow +LL | let b = 200u8 + 200u8 + 200u8; + | ^^^^^^^^^^^^^ attempt to add with overflow | note: lint level defined here --> $DIR/const-err2.rs:8:9 @@ -11,28 +11,22 @@ LL | #![deny(const_err)] | ^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/const-err2.rs:17:13 - | -LL | let b = 200u8 + 200u8 + 200u8; - | ^^^^^^^^^^^^^ attempt to add with overflow - -error: this expression will panic at runtime - --> $DIR/const-err2.rs:19:13 + --> $DIR/const-err2.rs:18:13 | LL | let c = 200u8 * 4; | ^^^^^^^^^ attempt to multiply with overflow error: this expression will panic at runtime - --> $DIR/const-err2.rs:21:13 + --> $DIR/const-err2.rs:20:13 | LL | let d = 42u8 - (42u8 + 1); | ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow error: index out of bounds: the len is 1 but the index is 1 - --> $DIR/const-err2.rs:23:14 + --> $DIR/const-err2.rs:22:14 | LL | let _e = [5u8][1]; | ^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/issue-64059.rs b/src/test/ui/consts/issue-64059.rs new file mode 100644 index 0000000000000..c4c895fef66cf --- /dev/null +++ b/src/test/ui/consts/issue-64059.rs @@ -0,0 +1,5 @@ +// run-pass + +fn main() { + let _ = -(-0.0); +} From 0c9aeba5f44b9ddb259154484d2ed6c270da6211 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 1 Sep 2019 10:09:45 -0400 Subject: [PATCH 394/618] Remove no-prefer-dynamic from valgrind tests --- src/test/run-pass-valgrind/cast-enum-with-dtor.rs | 2 -- src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs | 2 -- src/test/run-pass-valgrind/cleanup-stdin.rs | 2 -- src/test/run-pass-valgrind/down-with-thread-dtors.rs | 1 - src/test/run-pass-valgrind/dst-dtor-1.rs | 2 -- src/test/run-pass-valgrind/dst-dtor-2.rs | 2 -- src/test/run-pass-valgrind/dst-dtor-3.rs | 2 -- src/test/run-pass-valgrind/dst-dtor-4.rs | 2 -- src/test/run-pass-valgrind/exit-flushes.rs | 1 - src/test/run-pass-valgrind/osx-frameworks.rs | 1 - 10 files changed, 17 deletions(-) diff --git a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs index 42445b9056f9d..93c47d32f92a1 100644 --- a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs +++ b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - #![allow(dead_code)] // check dtor calling order when casting enums. diff --git a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs index 925ffe75fe785..fb2b4d476355e 100644 --- a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs +++ b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - // This would previously leak the Box because we wouldn't // schedule cleanups when auto borrowing trait objects. // This program should be valgrind clean. diff --git a/src/test/run-pass-valgrind/cleanup-stdin.rs b/src/test/run-pass-valgrind/cleanup-stdin.rs index 3505074293264..cf8f81cf5aa7c 100644 --- a/src/test/run-pass-valgrind/cleanup-stdin.rs +++ b/src/test/run-pass-valgrind/cleanup-stdin.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - fn main() { let _ = std::io::stdin(); let _ = std::io::stdout(); diff --git a/src/test/run-pass-valgrind/down-with-thread-dtors.rs b/src/test/run-pass-valgrind/down-with-thread-dtors.rs index c3567a9b20097..8531b8d832604 100644 --- a/src/test/run-pass-valgrind/down-with-thread-dtors.rs +++ b/src/test/run-pass-valgrind/down-with-thread-dtors.rs @@ -1,4 +1,3 @@ -// no-prefer-dynamic // ignore-emscripten thread_local!(static FOO: Foo = Foo); diff --git a/src/test/run-pass-valgrind/dst-dtor-1.rs b/src/test/run-pass-valgrind/dst-dtor-1.rs index 7533a7bd2353b..5b8433f614567 100644 --- a/src/test/run-pass-valgrind/dst-dtor-1.rs +++ b/src/test/run-pass-valgrind/dst-dtor-1.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - static mut DROP_RAN: bool = false; struct Foo; diff --git a/src/test/run-pass-valgrind/dst-dtor-2.rs b/src/test/run-pass-valgrind/dst-dtor-2.rs index ebf0c17fecb56..991fe00950bba 100644 --- a/src/test/run-pass-valgrind/dst-dtor-2.rs +++ b/src/test/run-pass-valgrind/dst-dtor-2.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - static mut DROP_RAN: isize = 0; struct Foo; diff --git a/src/test/run-pass-valgrind/dst-dtor-3.rs b/src/test/run-pass-valgrind/dst-dtor-3.rs index e15908dfcc31f..f0c2dda5ab05b 100644 --- a/src/test/run-pass-valgrind/dst-dtor-3.rs +++ b/src/test/run-pass-valgrind/dst-dtor-3.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - #![feature(unsized_tuple_coercion)] static mut DROP_RAN: bool = false; diff --git a/src/test/run-pass-valgrind/dst-dtor-4.rs b/src/test/run-pass-valgrind/dst-dtor-4.rs index 52bf0c364b24d..ad6d46f7c0886 100644 --- a/src/test/run-pass-valgrind/dst-dtor-4.rs +++ b/src/test/run-pass-valgrind/dst-dtor-4.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - #![feature(unsized_tuple_coercion)] static mut DROP_RAN: isize = 0; diff --git a/src/test/run-pass-valgrind/exit-flushes.rs b/src/test/run-pass-valgrind/exit-flushes.rs index cd5edb84bdfe4..a68c6f3355644 100644 --- a/src/test/run-pass-valgrind/exit-flushes.rs +++ b/src/test/run-pass-valgrind/exit-flushes.rs @@ -1,4 +1,3 @@ -// no-prefer-dynamic // ignore-cloudabi // ignore-emscripten // ignore-sgx no processes diff --git a/src/test/run-pass-valgrind/osx-frameworks.rs b/src/test/run-pass-valgrind/osx-frameworks.rs index 4ea804a184474..ea1403645a515 100644 --- a/src/test/run-pass-valgrind/osx-frameworks.rs +++ b/src/test/run-pass-valgrind/osx-frameworks.rs @@ -1,4 +1,3 @@ -// no-prefer-dynamic // pretty-expanded FIXME #23616 #![feature(rustc_private)] From 3a6aadaa8c915c3dea42c0b1fb6d96f227166148 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 2 Sep 2019 01:05:38 +0900 Subject: [PATCH 395/618] Add `opt-level` check --- src/librustc_mir/transform/const_prop.rs | 16 ++- src/test/ui/consts/const-err2.rs | 3 - src/test/ui/consts/const-err2.stderr | 28 +--- .../ui/consts/const-eval/promoted_errors.rs | 1 - .../consts/const-eval/promoted_errors.stderr | 30 ++--- ...t-method-self-inherit-builtin-trait.stderr | 6 + src/test/ui/issues/issue-8460-const.rs | 10 -- src/test/ui/issues/issue-8460-const.stderr | 120 +++++------------- 8 files changed, 67 insertions(+), 147 deletions(-) create mode 100644 src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.stderr diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 00118c05c9451..37e14004ce841 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -6,7 +6,7 @@ use std::cell::Cell; use rustc::hir::def::DefKind; use rustc::mir::{ AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, - Local, NullOp, StatementKind, Statement, LocalKind, Static, StaticKind, + Local, NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem, SourceScope, SourceScopeLocalData, LocalDecl, }; @@ -405,8 +405,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } let arg = self.eval_operand(arg, source_info)?; + let is_release_mode = self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2; let val = self.use_ecx(source_info, |this| { let prim = this.ecx.read_immediate(arg)?; + match op { + UnOp::Neg => { + if is_release_mode + && prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) { + throw_panic!(OverflowNeg) + } + } + UnOp::Not => { + // Cannot overflow + } + } // Now run the actual operation. this.ecx.unary_op(op, prim) })?; @@ -473,7 +485,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Scalar::from_bool(overflow).into(), ) } else { - if overflow { + if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 && overflow { let err = err_panic!(Overflow(op)).into(); let _: Option<()> = self.use_ecx(source_info, |_| Err(err)); return None; diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs index 5aab1972a9bd5..6da6addf60a1c 100644 --- a/src/test/ui/consts/const-err2.rs +++ b/src/test/ui/consts/const-err2.rs @@ -14,11 +14,8 @@ fn black_box(_: T) { fn main() { let a = -std::i8::MIN; let b = 200u8 + 200u8 + 200u8; - //~^ ERROR const_err let c = 200u8 * 4; - //~^ ERROR const_err let d = 42u8 - (42u8 + 1); - //~^ ERROR const_err let _e = [5u8][1]; //~^ ERROR const_err black_box(a); diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr index 63d037764a13d..30855fd215ff3 100644 --- a/src/test/ui/consts/const-err2.stderr +++ b/src/test/ui/consts/const-err2.stderr @@ -1,8 +1,8 @@ -error: this expression will panic at runtime - --> $DIR/const-err2.rs:16:13 +error: index out of bounds: the len is 1 but the index is 1 + --> $DIR/const-err2.rs:19:14 | -LL | let b = 200u8 + 200u8 + 200u8; - | ^^^^^^^^^^^^^ attempt to add with overflow +LL | let _e = [5u8][1]; + | ^^^^^^^^ | note: lint level defined here --> $DIR/const-err2.rs:8:9 @@ -10,23 +10,5 @@ note: lint level defined here LL | #![deny(const_err)] | ^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/const-err2.rs:18:13 - | -LL | let c = 200u8 * 4; - | ^^^^^^^^^ attempt to multiply with overflow - -error: this expression will panic at runtime - --> $DIR/const-err2.rs:20:13 - | -LL | let d = 42u8 - (42u8 + 1); - | ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow - -error: index out of bounds: the len is 1 but the index is 1 - --> $DIR/const-err2.rs:22:14 - | -LL | let _e = [5u8][1]; - | ^^^^^^^^ - -error: aborting due to 4 previous errors +error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index cd989731452b3..a9a7a66fe614f 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -5,7 +5,6 @@ fn main() { println!("{}", 0u32 - 1); let _x = 0u32 - 1; - //~^ ERROR this expression will panic at runtime [const_err] println!("{}", 1/(1-1)); //~^ ERROR attempt to divide by zero [const_err] //~| ERROR reaching this expression at runtime will panic or abort [const_err] diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr index 40d5c73e86679..3940fa13d7892 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.stderr @@ -1,8 +1,8 @@ -error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:7:14 +error: attempt to divide by zero + --> $DIR/promoted_errors.rs:8:20 | -LL | let _x = 0u32 - 1; - | ^^^^^^^^ attempt to subtract with overflow +LL | println!("{}", 1/(1-1)); + | ^^^^^^^ | note: lint level defined here --> $DIR/promoted_errors.rs:3:9 @@ -10,53 +10,47 @@ note: lint level defined here LL | #![deny(const_err)] | ^^^^^^^^^ -error: attempt to divide by zero - --> $DIR/promoted_errors.rs:9:20 - | -LL | println!("{}", 1/(1-1)); - | ^^^^^^^ - error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:9:20 + --> $DIR/promoted_errors.rs:8:20 | LL | println!("{}", 1/(1-1)); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:12:14 + --> $DIR/promoted_errors.rs:11:14 | LL | let _x = 1/(1-1); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:12:14 + --> $DIR/promoted_errors.rs:11:14 | LL | let _x = 1/(1-1); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:15:20 + --> $DIR/promoted_errors.rs:14:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:15:20 + --> $DIR/promoted_errors.rs:14:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:18:14 + --> $DIR/promoted_errors.rs:17:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:18:14 + --> $DIR/promoted_errors.rs:17:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ attempt to divide by zero -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors diff --git a/src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.stderr b/src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.stderr new file mode 100644 index 0000000000000..5160c9e72a9c4 --- /dev/null +++ b/src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.stderr @@ -0,0 +1,6 @@ +error: failed to remove $TEST_BUILD_DIR/issues/issue-8171-default-method-self-inherit-builtin-trait/issue-8171-default-method-self-inherit-builtin-trait.issue_8171_default_method_self_inherit_builtin_trait.7rcbfp3g-cgu.0.rcgu.o: 指定ã•ã‚ŒãŸãƒ‘スãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 (os error 3) + +error: failed to remove $TEST_BUILD_DIR/issues/issue-8171-default-method-self-inherit-builtin-trait/issue-8171-default-method-self-inherit-builtin-trait.issue_8171_default_method_self_inherit_builtin_trait.7rcbfp3g-cgu.1.rcgu.o: 指定ã•ã‚ŒãŸãƒ‘スãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 (os error 3) + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs index 611d280f774c0..6a5b98fa9b190 100644 --- a/src/test/ui/issues/issue-8460-const.rs +++ b/src/test/ui/issues/issue-8460-const.rs @@ -6,19 +6,14 @@ use std::thread; fn main() { assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero //~| ERROR this expression will panic at runtime @@ -36,19 +31,14 @@ fn main() { //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero //~| ERROR this expression will panic at runtime diff --git a/src/test/ui/issues/issue-8460-const.stderr b/src/test/ui/issues/issue-8460-const.stderr index 31b1da4f804ab..b9fbf0bdaa609 100644 --- a/src/test/ui/issues/issue-8460-const.stderr +++ b/src/test/ui/issues/issue-8460-const.stderr @@ -10,239 +10,179 @@ note: lint level defined here LL | #![deny(const_err)] | ^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:7:36 - | -LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^^^ attempt to divide with overflow - error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:10:36 + --> $DIR/issue-8460-const.rs:9:36 | LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:10:36 - | -LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^ attempt to divide with overflow - error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:13:36 + --> $DIR/issue-8460-const.rs:11:36 | LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:13:36 - | -LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to divide with overflow - error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:16:36 + --> $DIR/issue-8460-const.rs:13:36 | LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:16:36 - | -LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to divide with overflow - error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:19:36 + --> $DIR/issue-8460-const.rs:15:36 | LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:19:36 - | -LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to divide with overflow - error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:22:36 + --> $DIR/issue-8460-const.rs:17:36 | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:22:36 + --> $DIR/issue-8460-const.rs:17:36 | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:25:36 + --> $DIR/issue-8460-const.rs:20:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:25:36 + --> $DIR/issue-8460-const.rs:20:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:28:36 + --> $DIR/issue-8460-const.rs:23:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:28:36 + --> $DIR/issue-8460-const.rs:23:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:31:36 + --> $DIR/issue-8460-const.rs:26:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:31:36 + --> $DIR/issue-8460-const.rs:26:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:34:36 + --> $DIR/issue-8460-const.rs:29:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:34:36 + --> $DIR/issue-8460-const.rs:29:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:37:36 + --> $DIR/issue-8460-const.rs:32:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:37:36 - | -LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:40:36 + --> $DIR/issue-8460-const.rs:34:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:40:36 - | -LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^ attempt to calculate the remainder with overflow - error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:43:36 + --> $DIR/issue-8460-const.rs:36:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:43:36 - | -LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:46:36 + --> $DIR/issue-8460-const.rs:38:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:46:36 - | -LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:49:36 + --> $DIR/issue-8460-const.rs:40:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:49:36 - | -LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:52:36 + --> $DIR/issue-8460-const.rs:42:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:52:36 + --> $DIR/issue-8460-const.rs:42:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:55:36 + --> $DIR/issue-8460-const.rs:45:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:55:36 + --> $DIR/issue-8460-const.rs:45:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:58:36 + --> $DIR/issue-8460-const.rs:48:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:58:36 + --> $DIR/issue-8460-const.rs:48:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:61:36 + --> $DIR/issue-8460-const.rs:51:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:61:36 + --> $DIR/issue-8460-const.rs:51:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:64:36 + --> $DIR/issue-8460-const.rs:54:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:64:36 + --> $DIR/issue-8460-const.rs:54:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero -error: aborting due to 40 previous errors +error: aborting due to 30 previous errors From ab12dfeb164fb06d19ce24acd8268eebfd6440fa Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Mon, 2 Sep 2019 00:38:05 +0800 Subject: [PATCH 396/618] following the same style --- src/tools/compiletest/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index bde49ff391c8c..467b7771c152e 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -335,7 +335,7 @@ pub fn parse_config(args: Vec) -> Config { runtool: matches.opt_str("runtool"), host_rustcflags: matches.opt_str("host-rustcflags"), target_rustcflags: matches.opt_str("target-rustcflags"), - target: target, + target, host: opt_str2(matches.opt_str("host")), cdb, gdb, @@ -345,7 +345,7 @@ pub fn parse_config(args: Vec) -> Config { lldb_native_rust, llvm_version: matches.opt_str("llvm-version"), system_llvm: matches.opt_present("system-llvm"), - android_cross_path: android_cross_path, + android_cross_path, adb_path: opt_str2(matches.opt_str("adb-path")), adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")), adb_device_status: opt_str2(matches.opt_str("target")).contains("android") From 4a0872b37efbd982aed7e29f166e4ccb095f5779 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 2 Sep 2019 02:18:16 +0900 Subject: [PATCH 397/618] Add `overflow_check` check --- src/librustc_mir/transform/const_prop.rs | 8 ++++++-- ...-8171-default-method-self-inherit-builtin-trait.stderr | 6 ------ 2 files changed, 6 insertions(+), 8 deletions(-) delete mode 100644 src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.stderr diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 37e14004ce841..b43323687cda3 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -405,11 +405,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } let arg = self.eval_operand(arg, source_info)?; - let is_release_mode = self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2; + let is_release_mode = self.tcx.sess.overflow_checks(); let val = self.use_ecx(source_info, |this| { let prim = this.ecx.read_immediate(arg)?; match op { UnOp::Neg => { + // We don't have to check overflow here when we already + // check it in release mode. if is_release_mode && prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) { throw_panic!(OverflowNeg) @@ -485,7 +487,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Scalar::from_bool(overflow).into(), ) } else { - if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 && overflow { + // We don't have to check overflow here when we already + // check it in release mode. + if self.tcx.sess.overflow_checks() && overflow { let err = err_panic!(Overflow(op)).into(); let _: Option<()> = self.use_ecx(source_info, |_| Err(err)); return None; diff --git a/src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.stderr b/src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.stderr deleted file mode 100644 index 5160c9e72a9c4..0000000000000 --- a/src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: failed to remove $TEST_BUILD_DIR/issues/issue-8171-default-method-self-inherit-builtin-trait/issue-8171-default-method-self-inherit-builtin-trait.issue_8171_default_method_self_inherit_builtin_trait.7rcbfp3g-cgu.0.rcgu.o: 指定ã•ã‚ŒãŸãƒ‘スãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 (os error 3) - -error: failed to remove $TEST_BUILD_DIR/issues/issue-8171-default-method-self-inherit-builtin-trait/issue-8171-default-method-self-inherit-builtin-trait.issue_8171_default_method_self_inherit_builtin_trait.7rcbfp3g-cgu.1.rcgu.o: 指定ã•ã‚ŒãŸãƒ‘スãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 (os error 3) - -error: aborting due to 2 previous errors - From f53c2179ba2ae35bd241a28027fb703aec89139b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Sep 2019 10:49:07 -0700 Subject: [PATCH 398/618] review comments --- src/librustc_typeck/check/_match.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 63d059bdf2a80..7427ae9ce8de3 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -117,14 +117,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &arms[0].body, &mut coercion, ) { - tcx.types.err + tcx.types.err } else { // Only call this if this is not an `if` expr with an expected type and no `else` // clause to avoid duplicated type errors. (#60254) - let arm_ty = self.check_expr_with_expectation(&arm.body, expected); - all_arms_diverge &= self.diverges.get(); - arm_ty + self.check_expr_with_expectation(&arm.body, expected) }; + all_arms_diverge &= self.diverges.get(); if source_if { let then_expr = &arms[0].body; match (i, if_no_else) { @@ -188,6 +187,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Handle the fallback arm of a desugared if(-let) like a missing else. + /// + /// Returns `true` if there was an error forcing the coercion to the `()` type. fn if_fallback_coercion( &self, span: Span, From 8e9825aeb9bce905ed230733bf2a5b4b07f25eb9 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 2 Sep 2019 03:06:11 +0900 Subject: [PATCH 399/618] Fix overflow_check --- src/librustc_mir/transform/const_prop.rs | 14 +- src/test/ui/consts/const-err2.rs | 4 + src/test/ui/consts/const-err2.stderr | 34 ++++- .../ui/consts/const-eval/promoted_errors.rs | 1 + .../consts/const-eval/promoted_errors.stderr | 30 +++-- src/test/ui/consts/issue-64059.rs | 3 +- src/test/ui/consts/issue-64059.stderr | 10 ++ src/test/ui/issues/issue-8460-const.rs | 10 ++ src/test/ui/issues/issue-8460-const.stderr | 120 +++++++++++++----- 9 files changed, 170 insertions(+), 56 deletions(-) create mode 100644 src/test/ui/consts/issue-64059.stderr diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index b43323687cda3..091e68cd0669c 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -405,14 +405,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } let arg = self.eval_operand(arg, source_info)?; - let is_release_mode = self.tcx.sess.overflow_checks(); + let oflo_check = self.tcx.sess.overflow_checks(); let val = self.use_ecx(source_info, |this| { let prim = this.ecx.read_immediate(arg)?; match op { UnOp::Neg => { - // We don't have to check overflow here when we already - // check it in release mode. - if is_release_mode + // We check overflow in debug mode already + // so should only check in release mode. + if !oflo_check && prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) { throw_panic!(OverflowNeg) } @@ -487,9 +487,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Scalar::from_bool(overflow).into(), ) } else { - // We don't have to check overflow here when we already - // check it in release mode. - if self.tcx.sess.overflow_checks() && overflow { + // We check overflow in debug mode already + // so should only check in release mode. + if !self.tcx.sess.overflow_checks() && overflow { let err = err_panic!(Overflow(op)).into(); let _: Option<()> = self.use_ecx(source_info, |_| Err(err)); return None; diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs index 6da6addf60a1c..a5f685a159b39 100644 --- a/src/test/ui/consts/const-err2.rs +++ b/src/test/ui/consts/const-err2.rs @@ -13,9 +13,13 @@ fn black_box(_: T) { fn main() { let a = -std::i8::MIN; + //~^ ERROR const_err let b = 200u8 + 200u8 + 200u8; + //~^ ERROR const_err let c = 200u8 * 4; + //~^ ERROR const_err let d = 42u8 - (42u8 + 1); + //~^ ERROR const_err let _e = [5u8][1]; //~^ ERROR const_err black_box(a); diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr index 30855fd215ff3..659c3afc618a9 100644 --- a/src/test/ui/consts/const-err2.stderr +++ b/src/test/ui/consts/const-err2.stderr @@ -1,8 +1,8 @@ -error: index out of bounds: the len is 1 but the index is 1 - --> $DIR/const-err2.rs:19:14 +error: this expression will panic at runtime + --> $DIR/const-err2.rs:15:13 | -LL | let _e = [5u8][1]; - | ^^^^^^^^ +LL | let a = -std::i8::MIN; + | ^^^^^^^^^^^^^ attempt to negate with overflow | note: lint level defined here --> $DIR/const-err2.rs:8:9 @@ -10,5 +10,29 @@ note: lint level defined here LL | #![deny(const_err)] | ^^^^^^^^^ -error: aborting due to previous error +error: this expression will panic at runtime + --> $DIR/const-err2.rs:17:13 + | +LL | let b = 200u8 + 200u8 + 200u8; + | ^^^^^^^^^^^^^ attempt to add with overflow + +error: this expression will panic at runtime + --> $DIR/const-err2.rs:19:13 + | +LL | let c = 200u8 * 4; + | ^^^^^^^^^ attempt to multiply with overflow + +error: this expression will panic at runtime + --> $DIR/const-err2.rs:21:13 + | +LL | let d = 42u8 - (42u8 + 1); + | ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + +error: index out of bounds: the len is 1 but the index is 1 + --> $DIR/const-err2.rs:23:14 + | +LL | let _e = [5u8][1]; + | ^^^^^^^^ + +error: aborting due to 5 previous errors diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index a9a7a66fe614f..cd989731452b3 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -5,6 +5,7 @@ fn main() { println!("{}", 0u32 - 1); let _x = 0u32 - 1; + //~^ ERROR this expression will panic at runtime [const_err] println!("{}", 1/(1-1)); //~^ ERROR attempt to divide by zero [const_err] //~| ERROR reaching this expression at runtime will panic or abort [const_err] diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr index 3940fa13d7892..40d5c73e86679 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.stderr @@ -1,8 +1,8 @@ -error: attempt to divide by zero - --> $DIR/promoted_errors.rs:8:20 +error: this expression will panic at runtime + --> $DIR/promoted_errors.rs:7:14 | -LL | println!("{}", 1/(1-1)); - | ^^^^^^^ +LL | let _x = 0u32 - 1; + | ^^^^^^^^ attempt to subtract with overflow | note: lint level defined here --> $DIR/promoted_errors.rs:3:9 @@ -10,47 +10,53 @@ note: lint level defined here LL | #![deny(const_err)] | ^^^^^^^^^ +error: attempt to divide by zero + --> $DIR/promoted_errors.rs:9:20 + | +LL | println!("{}", 1/(1-1)); + | ^^^^^^^ + error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:8:20 + --> $DIR/promoted_errors.rs:9:20 | LL | println!("{}", 1/(1-1)); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:11:14 + --> $DIR/promoted_errors.rs:12:14 | LL | let _x = 1/(1-1); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:11:14 + --> $DIR/promoted_errors.rs:12:14 | LL | let _x = 1/(1-1); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:14:20 + --> $DIR/promoted_errors.rs:15:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:14:20 + --> $DIR/promoted_errors.rs:15:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:17:14 + --> $DIR/promoted_errors.rs:18:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:17:14 + --> $DIR/promoted_errors.rs:18:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ attempt to divide by zero -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/src/test/ui/consts/issue-64059.rs b/src/test/ui/consts/issue-64059.rs index c4c895fef66cf..30b8744cb7fa7 100644 --- a/src/test/ui/consts/issue-64059.rs +++ b/src/test/ui/consts/issue-64059.rs @@ -1,5 +1,4 @@ -// run-pass - fn main() { let _ = -(-0.0); + //~^ ERROR: this expression will panic at runtime } diff --git a/src/test/ui/consts/issue-64059.stderr b/src/test/ui/consts/issue-64059.stderr new file mode 100644 index 0000000000000..6f27653421bd6 --- /dev/null +++ b/src/test/ui/consts/issue-64059.stderr @@ -0,0 +1,10 @@ +error: this expression will panic at runtime + --> $DIR/issue-64059.rs:2:13 + | +LL | let _ = -(-0.0); + | ^^^^^^^ attempt to negate with overflow + | + = note: `#[deny(const_err)]` on by default + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs index 6a5b98fa9b190..611d280f774c0 100644 --- a/src/test/ui/issues/issue-8460-const.rs +++ b/src/test/ui/issues/issue-8460-const.rs @@ -6,14 +6,19 @@ use std::thread; fn main() { assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero //~| ERROR this expression will panic at runtime @@ -31,14 +36,19 @@ fn main() { //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero //~| ERROR this expression will panic at runtime diff --git a/src/test/ui/issues/issue-8460-const.stderr b/src/test/ui/issues/issue-8460-const.stderr index b9fbf0bdaa609..31b1da4f804ab 100644 --- a/src/test/ui/issues/issue-8460-const.stderr +++ b/src/test/ui/issues/issue-8460-const.stderr @@ -10,179 +10,239 @@ note: lint level defined here LL | #![deny(const_err)] | ^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:7:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to divide with overflow + error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:9:36 + --> $DIR/issue-8460-const.rs:10:36 | LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:10:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to divide with overflow + error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:11:36 + --> $DIR/issue-8460-const.rs:13:36 | LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: attempt to divide with overflow +error: this expression will panic at runtime --> $DIR/issue-8460-const.rs:13:36 | +LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: attempt to divide with overflow + --> $DIR/issue-8460-const.rs:16:36 + | LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:16:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:15:36 + --> $DIR/issue-8460-const.rs:19:36 | LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:19:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:17:36 + --> $DIR/issue-8460-const.rs:22:36 | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:17:36 + --> $DIR/issue-8460-const.rs:22:36 | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:20:36 + --> $DIR/issue-8460-const.rs:25:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:20:36 + --> $DIR/issue-8460-const.rs:25:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:23:36 + --> $DIR/issue-8460-const.rs:28:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:23:36 + --> $DIR/issue-8460-const.rs:28:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:26:36 + --> $DIR/issue-8460-const.rs:31:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:26:36 + --> $DIR/issue-8460-const.rs:31:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:29:36 + --> $DIR/issue-8460-const.rs:34:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:29:36 + --> $DIR/issue-8460-const.rs:34:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:32:36 + --> $DIR/issue-8460-const.rs:37:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:37:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:34:36 + --> $DIR/issue-8460-const.rs:40:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:40:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to calculate the remainder with overflow + error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:36:36 + --> $DIR/issue-8460-const.rs:43:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:43:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:38:36 + --> $DIR/issue-8460-const.rs:46:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:46:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:40:36 + --> $DIR/issue-8460-const.rs:49:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:49:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:42:36 + --> $DIR/issue-8460-const.rs:52:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:42:36 + --> $DIR/issue-8460-const.rs:52:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:45:36 + --> $DIR/issue-8460-const.rs:55:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:45:36 + --> $DIR/issue-8460-const.rs:55:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:48:36 + --> $DIR/issue-8460-const.rs:58:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:48:36 + --> $DIR/issue-8460-const.rs:58:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:51:36 + --> $DIR/issue-8460-const.rs:61:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:51:36 + --> $DIR/issue-8460-const.rs:61:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:54:36 + --> $DIR/issue-8460-const.rs:64:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:54:36 + --> $DIR/issue-8460-const.rs:64:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero -error: aborting due to 30 previous errors +error: aborting due to 40 previous errors From 141f5a7558289acb6c7aaf9c6500eb9f6dbeec1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Sep 2019 11:20:33 -0700 Subject: [PATCH 400/618] review comments --- src/librustc/ty/context.rs | 16 +----- src/librustc_typeck/check/expr.rs | 94 ++++++++++++++++++------------- 2 files changed, 57 insertions(+), 53 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index f355e231914d2..17c9e520bcea2 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2403,20 +2403,8 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_pin(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = self.require_lang_item(lang_items::PinTypeLangItem, None); - self.mk_generic_adt(def_id, ty) - } - - #[inline] - pub fn mk_rc(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = self.require_lang_item(lang_items::Rc, None); - self.mk_generic_adt(def_id, ty) - } - - #[inline] - pub fn mk_arc(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = self.require_lang_item(lang_items::Arc, None); + pub fn mk_lang_item(self, ty: Ty<'tcx>, item: lang_items::LangItem) -> Ty<'tcx> { + let def_id = self.require_lang_item(item, None); self.mk_generic_adt(def_id, ty) } diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index efff8bcdacbcf..fbaa9904d8303 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -12,7 +12,7 @@ use crate::check::fatally_break_rust; use crate::check::report_unexpected_variant_res; use crate::check::Needs; use crate::check::TupleArgumentsFlag::DontTupleArguments; -use crate::check::method::{probe, SelfSource}; +use crate::check::method::{probe, SelfSource, MethodError}; use crate::util::common::ErrorReported; use crate::util::nodemap::FxHashMap; use crate::astconv::AstConv as _; @@ -29,6 +29,7 @@ use rustc::hir::def::{CtorKind, Res, DefKind}; use rustc::hir::ptr::P; use rustc::infer; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc::middle::lang_items; use rustc::mir::interpret::GlobalId; use rustc::ty; use rustc::ty::adjustment::{ @@ -775,21 +776,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // no need to check for bot/err -- callee does that let rcvr_t = self.structurally_resolved_type(args[0].span, rcvr_t); - let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t| { - if let Ok(pick) = self.lookup_probe( - span, - segment.ident, - new_rcvr_t, - rcvr, - probe::ProbeScope::AllTraits, - ) { - err.span_label( - pick.item.ident.span, - &format!("the method is available for `{}` here", new_rcvr_t), - ); - } - }; - let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr) { Ok(method) => { self.write_method_call(expr.hir_id, method); @@ -797,29 +783,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Err(error) => { if segment.ident.name != kw::Invalid { - if let Some(mut err) = self.report_method_error( - span, - rcvr_t, - segment.ident, - SelfSource::MethodCall(rcvr), - error, - Some(args), - ) { - if let ty::Adt(..) = rcvr_t.sty { - // Try alternative arbitrary self types that could fulfill this call. - // FIXME: probe for all types that *could* be arbitrary self-types, not - // just this whitelist. - let box_rcvr_t = self.tcx.mk_box(rcvr_t); - try_alt_rcvr(&mut err, box_rcvr_t); - let pin_rcvr_t = self.tcx.mk_pin(rcvr_t); - try_alt_rcvr(&mut err, pin_rcvr_t); - let arc_rcvr_t = self.tcx.mk_arc(rcvr_t); - try_alt_rcvr(&mut err, arc_rcvr_t); - let rc_rcvr_t = self.tcx.mk_rc(rcvr_t); - try_alt_rcvr(&mut err, rc_rcvr_t); - } - err.emit(); - } + self.report_extended_method_error(segment, span, args, rcvr_t, error); } Err(()) } @@ -836,6 +800,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } + fn report_extended_method_error( + &self, + segment: &hir::PathSegment, + span: Span, + args: &'tcx [hir::Expr], + rcvr_t: Ty<'tcx>, + error: MethodError<'tcx> + ) { + let rcvr = &args[0]; + let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t| { + if let Ok(pick) = self.lookup_probe( + span, + segment.ident, + new_rcvr_t, + rcvr, + probe::ProbeScope::AllTraits, + ) { + err.span_label( + pick.item.ident.span, + &format!("the method is available for `{}` here", new_rcvr_t), + ); + } + }; + + if let Some(mut err) = self.report_method_error( + span, + rcvr_t, + segment.ident, + SelfSource::MethodCall(rcvr), + error, + Some(args), + ) { + if let ty::Adt(..) = rcvr_t.sty { + // Try alternative arbitrary self types that could fulfill this call. + // FIXME: probe for all types that *could* be arbitrary self-types, not + // just this whitelist. + let box_rcvr_t = self.tcx.mk_box(rcvr_t); + try_alt_rcvr(&mut err, box_rcvr_t); + let pin_rcvr_t = self.tcx.mk_lang_item( + rcvr_t, + lang_items::PinTypeLangItem, + ); + try_alt_rcvr(&mut err, pin_rcvr_t); + let arc_rcvr_t = self.tcx.mk_lang_item(rcvr_t, lang_items::Arc); + try_alt_rcvr(&mut err, arc_rcvr_t); + let rc_rcvr_t = self.tcx.mk_lang_item(rcvr_t, lang_items::Rc); + try_alt_rcvr(&mut err, rc_rcvr_t); + } + err.emit(); + } + } + fn check_expr_cast( &self, e: &'tcx hir::Expr, From 0cd9c1623fb5858990892fed2fbf7c06e7b25f22 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 2 Sep 2019 03:40:35 +0900 Subject: [PATCH 401/618] Fix condition and tests' flags --- src/librustc_mir/transform/const_prop.rs | 1 + src/test/ui/consts/const-err2.rs | 2 + src/test/ui/consts/const-err2.stderr | 28 ++-- .../ui/consts/const-eval/promoted_errors.rs | 5 +- .../consts/const-eval/promoted_errors.stderr | 32 +++-- src/test/ui/consts/issue-64059.rs | 4 +- src/test/ui/consts/issue-64059.stderr | 10 -- src/test/ui/issues/issue-8460-const.rs | 12 +- src/test/ui/issues/issue-8460-const.stderr | 122 +++++------------- 9 files changed, 75 insertions(+), 141 deletions(-) delete mode 100644 src/test/ui/consts/issue-64059.stderr diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 091e68cd0669c..e4b186736e2a1 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -413,6 +413,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // We check overflow in debug mode already // so should only check in release mode. if !oflo_check + && prim.layout.ty.is_signed() && prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) { throw_panic!(OverflowNeg) } diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs index a5f685a159b39..cd6ac47bd92a8 100644 --- a/src/test/ui/consts/const-err2.rs +++ b/src/test/ui/consts/const-err2.rs @@ -5,6 +5,8 @@ #![feature(rustc_attrs)] #![allow(exceeding_bitshifts)] +// compile-flags: -C overflow-checks=on -O + #![deny(const_err)] fn black_box(_: T) { diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr index 659c3afc618a9..ecfced7f0db8b 100644 --- a/src/test/ui/consts/const-err2.stderr +++ b/src/test/ui/consts/const-err2.stderr @@ -1,35 +1,35 @@ -error: this expression will panic at runtime - --> $DIR/const-err2.rs:15:13 +error: attempt to negate with overflow + --> $DIR/const-err2.rs:17:13 | LL | let a = -std::i8::MIN; - | ^^^^^^^^^^^^^ attempt to negate with overflow + | ^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/const-err2.rs:8:9 + --> $DIR/const-err2.rs:10:9 | LL | #![deny(const_err)] | ^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/const-err2.rs:17:13 +error: attempt to add with overflow + --> $DIR/const-err2.rs:19:13 | LL | let b = 200u8 + 200u8 + 200u8; - | ^^^^^^^^^^^^^ attempt to add with overflow + | ^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/const-err2.rs:19:13 +error: attempt to multiply with overflow + --> $DIR/const-err2.rs:21:13 | LL | let c = 200u8 * 4; - | ^^^^^^^^^ attempt to multiply with overflow + | ^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/const-err2.rs:21:13 +error: attempt to subtract with overflow + --> $DIR/const-err2.rs:23:13 | LL | let d = 42u8 - (42u8 + 1); - | ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + | ^^^^^^^^^^^^^^^^^ error: index out of bounds: the len is 1 but the index is 1 - --> $DIR/const-err2.rs:23:14 + --> $DIR/const-err2.rs:25:14 | LL | let _e = [5u8][1]; | ^^^^^^^^ diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index cd989731452b3..7adb394144bdd 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -1,11 +1,12 @@ -// compile-flags: -O +// compile-flags: -C overflow-checks=on -O #![deny(const_err)] fn main() { println!("{}", 0u32 - 1); + //~^ ERROR attempt to subtract with overflow let _x = 0u32 - 1; - //~^ ERROR this expression will panic at runtime [const_err] + //~^ ERROR attempt to subtract with overflow println!("{}", 1/(1-1)); //~^ ERROR attempt to divide by zero [const_err] //~| ERROR reaching this expression at runtime will panic or abort [const_err] diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr index 40d5c73e86679..fe63d0800dd7c 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.stderr @@ -1,8 +1,8 @@ -error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:7:14 +error: attempt to subtract with overflow + --> $DIR/promoted_errors.rs:6:20 | -LL | let _x = 0u32 - 1; - | ^^^^^^^^ attempt to subtract with overflow +LL | println!("{}", 0u32 - 1); + | ^^^^^^^^ | note: lint level defined here --> $DIR/promoted_errors.rs:3:9 @@ -10,53 +10,59 @@ note: lint level defined here LL | #![deny(const_err)] | ^^^^^^^^^ +error: attempt to subtract with overflow + --> $DIR/promoted_errors.rs:8:14 + | +LL | let _x = 0u32 - 1; + | ^^^^^^^^ + error: attempt to divide by zero - --> $DIR/promoted_errors.rs:9:20 + --> $DIR/promoted_errors.rs:10:20 | LL | println!("{}", 1/(1-1)); | ^^^^^^^ error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:9:20 + --> $DIR/promoted_errors.rs:10:20 | LL | println!("{}", 1/(1-1)); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:12:14 + --> $DIR/promoted_errors.rs:13:14 | LL | let _x = 1/(1-1); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:12:14 + --> $DIR/promoted_errors.rs:13:14 | LL | let _x = 1/(1-1); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:15:20 + --> $DIR/promoted_errors.rs:16:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:15:20 + --> $DIR/promoted_errors.rs:16:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:18:14 + --> $DIR/promoted_errors.rs:19:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:18:14 + --> $DIR/promoted_errors.rs:19:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ attempt to divide by zero -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors diff --git a/src/test/ui/consts/issue-64059.rs b/src/test/ui/consts/issue-64059.rs index 30b8744cb7fa7..38911c3dcf692 100644 --- a/src/test/ui/consts/issue-64059.rs +++ b/src/test/ui/consts/issue-64059.rs @@ -1,4 +1,6 @@ +// compile-flags: -C overflow-checks=on -O +// run-pass + fn main() { let _ = -(-0.0); - //~^ ERROR: this expression will panic at runtime } diff --git a/src/test/ui/consts/issue-64059.stderr b/src/test/ui/consts/issue-64059.stderr deleted file mode 100644 index 6f27653421bd6..0000000000000 --- a/src/test/ui/consts/issue-64059.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: this expression will panic at runtime - --> $DIR/issue-64059.rs:2:13 - | -LL | let _ = -(-0.0); - | ^^^^^^^ attempt to negate with overflow - | - = note: `#[deny(const_err)]` on by default - -error: aborting due to previous error - diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs index 611d280f774c0..c3f53e3298b2b 100644 --- a/src/test/ui/issues/issue-8460-const.rs +++ b/src/test/ui/issues/issue-8460-const.rs @@ -1,3 +1,5 @@ +// compile-flags: -C overflow-checks=on -O + #![deny(const_err)] use std::{isize, i8, i16, i32, i64}; @@ -6,19 +8,14 @@ use std::thread; fn main() { assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero //~| ERROR this expression will panic at runtime @@ -36,19 +33,14 @@ fn main() { //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero //~| ERROR this expression will panic at runtime diff --git a/src/test/ui/issues/issue-8460-const.stderr b/src/test/ui/issues/issue-8460-const.stderr index 31b1da4f804ab..914323227ddd2 100644 --- a/src/test/ui/issues/issue-8460-const.stderr +++ b/src/test/ui/issues/issue-8460-const.stderr @@ -1,248 +1,188 @@ error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:7:36 + --> $DIR/issue-8460-const.rs:9:36 | LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/issue-8460-const.rs:1:9 + --> $DIR/issue-8460-const.rs:3:9 | LL | #![deny(const_err)] | ^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:7:36 - | -LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^^^ attempt to divide with overflow - error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:10:36 + --> $DIR/issue-8460-const.rs:11:36 | LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:10:36 - | -LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^ attempt to divide with overflow - error: attempt to divide with overflow --> $DIR/issue-8460-const.rs:13:36 | LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:13:36 - | -LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to divide with overflow - error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:16:36 + --> $DIR/issue-8460-const.rs:15:36 | LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:16:36 - | -LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to divide with overflow - error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:19:36 + --> $DIR/issue-8460-const.rs:17:36 | LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:19:36 - | -LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to divide with overflow - error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:22:36 + --> $DIR/issue-8460-const.rs:19:36 | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:22:36 + --> $DIR/issue-8460-const.rs:19:36 | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:25:36 + --> $DIR/issue-8460-const.rs:22:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:25:36 + --> $DIR/issue-8460-const.rs:22:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:28:36 + --> $DIR/issue-8460-const.rs:25:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:28:36 + --> $DIR/issue-8460-const.rs:25:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:31:36 + --> $DIR/issue-8460-const.rs:28:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:31:36 + --> $DIR/issue-8460-const.rs:28:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:34:36 + --> $DIR/issue-8460-const.rs:31:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:34:36 + --> $DIR/issue-8460-const.rs:31:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:37:36 + --> $DIR/issue-8460-const.rs:34:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:37:36 - | -LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:40:36 + --> $DIR/issue-8460-const.rs:36:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:40:36 - | -LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^ attempt to calculate the remainder with overflow - error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:43:36 + --> $DIR/issue-8460-const.rs:38:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:43:36 - | -LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:46:36 + --> $DIR/issue-8460-const.rs:40:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:46:36 - | -LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:49:36 + --> $DIR/issue-8460-const.rs:42:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:49:36 - | -LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:52:36 + --> $DIR/issue-8460-const.rs:44:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:52:36 + --> $DIR/issue-8460-const.rs:44:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:55:36 + --> $DIR/issue-8460-const.rs:47:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:55:36 + --> $DIR/issue-8460-const.rs:47:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:58:36 + --> $DIR/issue-8460-const.rs:50:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:58:36 + --> $DIR/issue-8460-const.rs:50:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:61:36 + --> $DIR/issue-8460-const.rs:53:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:61:36 + --> $DIR/issue-8460-const.rs:53:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:64:36 + --> $DIR/issue-8460-const.rs:56:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:64:36 + --> $DIR/issue-8460-const.rs:56:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero -error: aborting due to 40 previous errors +error: aborting due to 30 previous errors From a937d8cdeb56ed72897ecf14469f89f18814554c Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 2 Sep 2019 05:01:39 +0900 Subject: [PATCH 402/618] Fix tests again --- src/test/ui/consts/const-err2.rs | 3 +- src/test/ui/consts/const-err2.stderr | 28 +-- src/test/ui/consts/const-err3.rs | 30 +++ src/test/ui/consts/const-err3.stderr | 38 ++++ .../ui/consts/const-eval/promoted_errors.rs | 5 +- .../consts/const-eval/promoted_errors.stderr | 32 ++- .../ui/consts/const-eval/promoted_errors2.rs | 22 ++ .../consts/const-eval/promoted_errors2.stderr | 68 +++++++ src/test/ui/consts/issue-64059-2.rs | 6 + src/test/ui/consts/issue-64059.rs | 1 - src/test/ui/issues/issue-8460-const.rs | 12 +- src/test/ui/issues/issue-8460-const.stderr | 122 +++++++++--- src/test/ui/issues/issue-8460-const2.rs | 59 ++++++ src/test/ui/issues/issue-8460-const2.stderr | 188 ++++++++++++++++++ 14 files changed, 542 insertions(+), 72 deletions(-) create mode 100644 src/test/ui/consts/const-err3.rs create mode 100644 src/test/ui/consts/const-err3.stderr create mode 100644 src/test/ui/consts/const-eval/promoted_errors2.rs create mode 100644 src/test/ui/consts/const-eval/promoted_errors2.stderr create mode 100644 src/test/ui/consts/issue-64059-2.rs create mode 100644 src/test/ui/issues/issue-8460-const2.rs create mode 100644 src/test/ui/issues/issue-8460-const2.stderr diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs index cd6ac47bd92a8..ecbcc2a4b496f 100644 --- a/src/test/ui/consts/const-err2.rs +++ b/src/test/ui/consts/const-err2.rs @@ -5,7 +5,6 @@ #![feature(rustc_attrs)] #![allow(exceeding_bitshifts)] -// compile-flags: -C overflow-checks=on -O #![deny(const_err)] @@ -23,7 +22,7 @@ fn main() { let d = 42u8 - (42u8 + 1); //~^ ERROR const_err let _e = [5u8][1]; - //~^ ERROR const_err + //~^ ERROR index out of bounds black_box(a); black_box(b); black_box(c); diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr index ecfced7f0db8b..1d84d44dc27b3 100644 --- a/src/test/ui/consts/const-err2.stderr +++ b/src/test/ui/consts/const-err2.stderr @@ -1,35 +1,35 @@ -error: attempt to negate with overflow - --> $DIR/const-err2.rs:17:13 +error: this expression will panic at runtime + --> $DIR/const-err2.rs:16:13 | LL | let a = -std::i8::MIN; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ attempt to negate with overflow | note: lint level defined here - --> $DIR/const-err2.rs:10:9 + --> $DIR/const-err2.rs:9:9 | LL | #![deny(const_err)] | ^^^^^^^^^ -error: attempt to add with overflow - --> $DIR/const-err2.rs:19:13 +error: this expression will panic at runtime + --> $DIR/const-err2.rs:18:13 | LL | let b = 200u8 + 200u8 + 200u8; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ attempt to add with overflow -error: attempt to multiply with overflow - --> $DIR/const-err2.rs:21:13 +error: this expression will panic at runtime + --> $DIR/const-err2.rs:20:13 | LL | let c = 200u8 * 4; - | ^^^^^^^^^ + | ^^^^^^^^^ attempt to multiply with overflow -error: attempt to subtract with overflow - --> $DIR/const-err2.rs:23:13 +error: this expression will panic at runtime + --> $DIR/const-err2.rs:22:13 | LL | let d = 42u8 - (42u8 + 1); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow error: index out of bounds: the len is 1 but the index is 1 - --> $DIR/const-err2.rs:25:14 + --> $DIR/const-err2.rs:24:14 | LL | let _e = [5u8][1]; | ^^^^^^^^ diff --git a/src/test/ui/consts/const-err3.rs b/src/test/ui/consts/const-err3.rs new file mode 100644 index 0000000000000..a9cf04cda7a5a --- /dev/null +++ b/src/test/ui/consts/const-err3.rs @@ -0,0 +1,30 @@ +// needed because negating int::MIN will behave differently between +// optimized compilation and unoptimized compilation and thus would +// lead to different lints being emitted +// compile-flags: -C overflow-checks=on -O + +#![feature(rustc_attrs)] +#![allow(exceeding_bitshifts)] + +#![deny(const_err)] + +fn black_box(_: T) { + unimplemented!() +} + +fn main() { + let a = -std::i8::MIN; + //~^ ERROR const_err + let b = 200u8 + 200u8 + 200u8; + //~^ ERROR const_err + let c = 200u8 * 4; + //~^ ERROR const_err + let d = 42u8 - (42u8 + 1); + //~^ ERROR const_err + let _e = [5u8][1]; + //~^ ERROR const_err + black_box(a); + black_box(b); + black_box(c); + black_box(d); +} diff --git a/src/test/ui/consts/const-err3.stderr b/src/test/ui/consts/const-err3.stderr new file mode 100644 index 0000000000000..0602707be7040 --- /dev/null +++ b/src/test/ui/consts/const-err3.stderr @@ -0,0 +1,38 @@ +error: attempt to negate with overflow + --> $DIR/const-err3.rs:16:13 + | +LL | let a = -std::i8::MIN; + | ^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/const-err3.rs:9:9 + | +LL | #![deny(const_err)] + | ^^^^^^^^^ + +error: attempt to add with overflow + --> $DIR/const-err3.rs:18:13 + | +LL | let b = 200u8 + 200u8 + 200u8; + | ^^^^^^^^^^^^^ + +error: attempt to multiply with overflow + --> $DIR/const-err3.rs:20:13 + | +LL | let c = 200u8 * 4; + | ^^^^^^^^^ + +error: attempt to subtract with overflow + --> $DIR/const-err3.rs:22:13 + | +LL | let d = 42u8 - (42u8 + 1); + | ^^^^^^^^^^^^^^^^^ + +error: index out of bounds: the len is 1 but the index is 1 + --> $DIR/const-err3.rs:24:14 + | +LL | let _e = [5u8][1]; + | ^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index 7adb394144bdd..45941398f4b66 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -1,12 +1,11 @@ -// compile-flags: -C overflow-checks=on -O +// compile-flags: -O #![deny(const_err)] fn main() { println!("{}", 0u32 - 1); - //~^ ERROR attempt to subtract with overflow let _x = 0u32 - 1; - //~^ ERROR attempt to subtract with overflow + //~^ ERROR const_err println!("{}", 1/(1-1)); //~^ ERROR attempt to divide by zero [const_err] //~| ERROR reaching this expression at runtime will panic or abort [const_err] diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr index fe63d0800dd7c..40d5c73e86679 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.stderr @@ -1,8 +1,8 @@ -error: attempt to subtract with overflow - --> $DIR/promoted_errors.rs:6:20 +error: this expression will panic at runtime + --> $DIR/promoted_errors.rs:7:14 | -LL | println!("{}", 0u32 - 1); - | ^^^^^^^^ +LL | let _x = 0u32 - 1; + | ^^^^^^^^ attempt to subtract with overflow | note: lint level defined here --> $DIR/promoted_errors.rs:3:9 @@ -10,59 +10,53 @@ note: lint level defined here LL | #![deny(const_err)] | ^^^^^^^^^ -error: attempt to subtract with overflow - --> $DIR/promoted_errors.rs:8:14 - | -LL | let _x = 0u32 - 1; - | ^^^^^^^^ - error: attempt to divide by zero - --> $DIR/promoted_errors.rs:10:20 + --> $DIR/promoted_errors.rs:9:20 | LL | println!("{}", 1/(1-1)); | ^^^^^^^ error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:10:20 + --> $DIR/promoted_errors.rs:9:20 | LL | println!("{}", 1/(1-1)); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:13:14 + --> $DIR/promoted_errors.rs:12:14 | LL | let _x = 1/(1-1); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:13:14 + --> $DIR/promoted_errors.rs:12:14 | LL | let _x = 1/(1-1); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:16:20 + --> $DIR/promoted_errors.rs:15:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:16:20 + --> $DIR/promoted_errors.rs:15:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:19:14 + --> $DIR/promoted_errors.rs:18:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:19:14 + --> $DIR/promoted_errors.rs:18:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ attempt to divide by zero -error: aborting due to 10 previous errors +error: aborting due to 9 previous errors diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs new file mode 100644 index 0000000000000..7adb394144bdd --- /dev/null +++ b/src/test/ui/consts/const-eval/promoted_errors2.rs @@ -0,0 +1,22 @@ +// compile-flags: -C overflow-checks=on -O + +#![deny(const_err)] + +fn main() { + println!("{}", 0u32 - 1); + //~^ ERROR attempt to subtract with overflow + let _x = 0u32 - 1; + //~^ ERROR attempt to subtract with overflow + println!("{}", 1/(1-1)); + //~^ ERROR attempt to divide by zero [const_err] + //~| ERROR reaching this expression at runtime will panic or abort [const_err] + let _x = 1/(1-1); + //~^ ERROR const_err + //~| ERROR const_err + println!("{}", 1/(false as u32)); + //~^ ERROR attempt to divide by zero [const_err] + //~| ERROR reaching this expression at runtime will panic or abort [const_err] + let _x = 1/(false as u32); + //~^ ERROR const_err + //~| ERROR const_err +} diff --git a/src/test/ui/consts/const-eval/promoted_errors2.stderr b/src/test/ui/consts/const-eval/promoted_errors2.stderr new file mode 100644 index 0000000000000..2819e6e8fdbe0 --- /dev/null +++ b/src/test/ui/consts/const-eval/promoted_errors2.stderr @@ -0,0 +1,68 @@ +error: attempt to subtract with overflow + --> $DIR/promoted_errors2.rs:6:20 + | +LL | println!("{}", 0u32 - 1); + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/promoted_errors2.rs:3:9 + | +LL | #![deny(const_err)] + | ^^^^^^^^^ + +error: attempt to subtract with overflow + --> $DIR/promoted_errors2.rs:8:14 + | +LL | let _x = 0u32 - 1; + | ^^^^^^^^ + +error: attempt to divide by zero + --> $DIR/promoted_errors2.rs:10:20 + | +LL | println!("{}", 1/(1-1)); + | ^^^^^^^ + +error: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors2.rs:10:20 + | +LL | println!("{}", 1/(1-1)); + | ^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/promoted_errors2.rs:13:14 + | +LL | let _x = 1/(1-1); + | ^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/promoted_errors2.rs:13:14 + | +LL | let _x = 1/(1-1); + | ^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/promoted_errors2.rs:16:20 + | +LL | println!("{}", 1/(false as u32)); + | ^^^^^^^^^^^^^^^^ + +error: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors2.rs:16:20 + | +LL | println!("{}", 1/(false as u32)); + | ^^^^^^^^^^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/promoted_errors2.rs:19:14 + | +LL | let _x = 1/(false as u32); + | ^^^^^^^^^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/promoted_errors2.rs:19:14 + | +LL | let _x = 1/(false as u32); + | ^^^^^^^^^^^^^^^^ attempt to divide by zero + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/consts/issue-64059-2.rs b/src/test/ui/consts/issue-64059-2.rs new file mode 100644 index 0000000000000..38911c3dcf692 --- /dev/null +++ b/src/test/ui/consts/issue-64059-2.rs @@ -0,0 +1,6 @@ +// compile-flags: -C overflow-checks=on -O +// run-pass + +fn main() { + let _ = -(-0.0); +} diff --git a/src/test/ui/consts/issue-64059.rs b/src/test/ui/consts/issue-64059.rs index 38911c3dcf692..c4c895fef66cf 100644 --- a/src/test/ui/consts/issue-64059.rs +++ b/src/test/ui/consts/issue-64059.rs @@ -1,4 +1,3 @@ -// compile-flags: -C overflow-checks=on -O // run-pass fn main() { diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs index c3f53e3298b2b..611d280f774c0 100644 --- a/src/test/ui/issues/issue-8460-const.rs +++ b/src/test/ui/issues/issue-8460-const.rs @@ -1,5 +1,3 @@ -// compile-flags: -C overflow-checks=on -O - #![deny(const_err)] use std::{isize, i8, i16, i32, i64}; @@ -8,14 +6,19 @@ use std::thread; fn main() { assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); //~^ ERROR attempt to divide with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero //~| ERROR this expression will panic at runtime @@ -33,14 +36,19 @@ fn main() { //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow + //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero //~| ERROR this expression will panic at runtime diff --git a/src/test/ui/issues/issue-8460-const.stderr b/src/test/ui/issues/issue-8460-const.stderr index 914323227ddd2..31b1da4f804ab 100644 --- a/src/test/ui/issues/issue-8460-const.stderr +++ b/src/test/ui/issues/issue-8460-const.stderr @@ -1,188 +1,248 @@ error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:9:36 + --> $DIR/issue-8460-const.rs:7:36 | LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/issue-8460-const.rs:3:9 + --> $DIR/issue-8460-const.rs:1:9 | LL | #![deny(const_err)] | ^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:7:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to divide with overflow + error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:11:36 + --> $DIR/issue-8460-const.rs:10:36 | LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:10:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to divide with overflow + error: attempt to divide with overflow --> $DIR/issue-8460-const.rs:13:36 | LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:13:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:15:36 + --> $DIR/issue-8460-const.rs:16:36 | LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:16:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:17:36 + --> $DIR/issue-8460-const.rs:19:36 | LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ -error: attempt to divide by zero +error: this expression will panic at runtime --> $DIR/issue-8460-const.rs:19:36 | +LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: attempt to divide by zero + --> $DIR/issue-8460-const.rs:22:36 + | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:19:36 + --> $DIR/issue-8460-const.rs:22:36 | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:22:36 + --> $DIR/issue-8460-const.rs:25:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:22:36 + --> $DIR/issue-8460-const.rs:25:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:25:36 + --> $DIR/issue-8460-const.rs:28:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:25:36 + --> $DIR/issue-8460-const.rs:28:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:28:36 + --> $DIR/issue-8460-const.rs:31:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:28:36 + --> $DIR/issue-8460-const.rs:31:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:31:36 + --> $DIR/issue-8460-const.rs:34:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:31:36 + --> $DIR/issue-8460-const.rs:34:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:34:36 + --> $DIR/issue-8460-const.rs:37:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:37:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:36:36 + --> $DIR/issue-8460-const.rs:40:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:40:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to calculate the remainder with overflow + error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:38:36 + --> $DIR/issue-8460-const.rs:43:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:43:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:40:36 + --> $DIR/issue-8460-const.rs:46:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:46:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:42:36 + --> $DIR/issue-8460-const.rs:49:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ +error: this expression will panic at runtime + --> $DIR/issue-8460-const.rs:49:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:44:36 + --> $DIR/issue-8460-const.rs:52:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:44:36 + --> $DIR/issue-8460-const.rs:52:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:47:36 + --> $DIR/issue-8460-const.rs:55:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:47:36 + --> $DIR/issue-8460-const.rs:55:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:50:36 + --> $DIR/issue-8460-const.rs:58:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:50:36 + --> $DIR/issue-8460-const.rs:58:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:53:36 + --> $DIR/issue-8460-const.rs:61:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:53:36 + --> $DIR/issue-8460-const.rs:61:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:56:36 + --> $DIR/issue-8460-const.rs:64:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:56:36 + --> $DIR/issue-8460-const.rs:64:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero -error: aborting due to 30 previous errors +error: aborting due to 40 previous errors diff --git a/src/test/ui/issues/issue-8460-const2.rs b/src/test/ui/issues/issue-8460-const2.rs new file mode 100644 index 0000000000000..c3f53e3298b2b --- /dev/null +++ b/src/test/ui/issues/issue-8460-const2.rs @@ -0,0 +1,59 @@ +// compile-flags: -C overflow-checks=on -O + +#![deny(const_err)] + +use std::{isize, i8, i16, i32, i64}; +use std::thread; + +fn main() { + assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime +} diff --git a/src/test/ui/issues/issue-8460-const2.stderr b/src/test/ui/issues/issue-8460-const2.stderr new file mode 100644 index 0000000000000..b688ec1367794 --- /dev/null +++ b/src/test/ui/issues/issue-8460-const2.stderr @@ -0,0 +1,188 @@ +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:9:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/issue-8460-const2.rs:3:9 + | +LL | #![deny(const_err)] + | ^^^^^^^^^ + +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:11:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^ + +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:13:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:15:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:17:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:19:36 + | +LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + | ^^^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:19:36 + | +LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:22:36 + | +LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + | ^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:22:36 + | +LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + | ^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:25:36 + | +LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:25:36 + | +LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:28:36 + | +LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:28:36 + | +LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:31:36 + | +LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:31:36 + | +LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:34:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:36:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^ + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:38:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:40:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:42:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:44:36 + | +LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + | ^^^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:44:36 + | +LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:47:36 + | +LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + | ^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:47:36 + | +LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + | ^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:50:36 + | +LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:50:36 + | +LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:53:36 + | +LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:53:36 + | +LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:56:36 + | +LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:56:36 + | +LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: aborting due to 30 previous errors + From 334d4657322a95b4160e03fecc815fc38ac56e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Sep 2019 20:13:59 -0700 Subject: [PATCH 403/618] Point at appropriate arm on type error on if/else/match with one non-! arm --- src/librustc_typeck/check/mod.rs | 43 ++++++++++++++++--- ...-to-type-err-cause-on-impl-trait-return.rs | 2 +- ...type-err-cause-on-impl-trait-return.stderr | 20 ++++----- 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a80550486d627..4a0b3879cb991 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3687,6 +3687,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail + /// expression's `Span`, otherwise return `expr.span`. This is done to give bettern errors + /// when given code like the following: + /// ```text + /// if false { return 0i32; } else { 1u32 } + /// // ^^^^ point at this instead of the whole `if` expression + /// ``` + fn get_expr_coercion_span(&self, expr: &hir::Expr) -> syntax_pos::Span { + if let hir::ExprKind::Match(_, arms, _) = &expr.node { + let arm_spans: Vec = arms.iter().filter_map(|arm| { + self.in_progress_tables + .and_then(|tables| tables.borrow().node_type_opt(arm.body.hir_id)) + .and_then(|arm_ty| { + if arm_ty.is_never() { + None + } else { + Some(match &arm.body.node { + // Point at the tail expression when possible. + hir::ExprKind::Block(block, _) => block.expr + .as_ref() + .map(|e| e.span) + .unwrap_or(block.span), + _ => arm.body.span, + }) + } + }) + }).collect(); + if arm_spans.len() == 1 { + return arm_spans[0]; + } + } + expr.span + } + fn check_block_with_expected( &self, blk: &'tcx hir::Block, @@ -3746,12 +3780,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let coerce = ctxt.coerce.as_mut().unwrap(); if let Some(tail_expr_ty) = tail_expr_ty { let tail_expr = tail_expr.unwrap(); - let cause = self.cause(tail_expr.span, - ObligationCauseCode::BlockTailExpression(blk.hir_id)); - coerce.coerce(self, - &cause, - tail_expr, - tail_expr_ty); + let span = self.get_expr_coercion_span(tail_expr); + let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id)); + coerce.coerce(self, &cause, tail_expr, tail_expr_ty); } else { // Subtle: if there is no explicit tail expression, // that is typically equivalent to a tail expression diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs index 95b40368143ef..d416db628c03f 100644 --- a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs +++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs @@ -17,10 +17,10 @@ fn bar() -> impl std::fmt::Display { fn baz() -> impl std::fmt::Display { if false { - //~^ ERROR mismatched types return 0i32; } else { 1u32 + //~^ ERROR mismatched types } } diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr index ee1e36081e778..47644d66d1a2c 100644 --- a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr +++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr @@ -29,18 +29,16 @@ LL | return 1u32; found type `u32` error[E0308]: mismatched types - --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:19:5 + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:22:9 | -LL | fn baz() -> impl std::fmt::Display { - | ---------------------- expected because this return type... -LL | / if false { -LL | | -LL | | return 0i32; - | | ---- ...is found to be `i32` here -LL | | } else { -LL | | 1u32 -LL | | } - | |_____^ expected i32, found u32 +LL | fn baz() -> impl std::fmt::Display { + | ---------------------- expected because this return type... +LL | if false { +LL | return 0i32; + | ---- ...is found to be `i32` here +LL | } else { +LL | 1u32 + | ^^^^ expected i32, found u32 | = note: expected type `i32` found type `u32` From b0bb3017c12d8e2cafb6a9852a10e12dc8e044e9 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 2 Sep 2019 13:50:44 +0200 Subject: [PATCH 404/618] Update xLTO compatibility table in rustc book. --- src/doc/rustc/src/linker-plugin-lto.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md index 2ae726c4ba61d..6f1bbe60569fd 100644 --- a/src/doc/rustc/src/linker-plugin-lto.md +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -105,5 +105,6 @@ The following table shows known good combinations of toolchain versions. | Rust 1.34 | ✗ | ✓ | | Rust 1.35 | ✗ | ✓ | | Rust 1.36 | ✗ | ✓ | +| Rust 1.37 | ✗ | ✓ | Note that the compatibility policy for this feature might change in the future. From a80ab3a2f85240ec2f9bda00f7cae1abc50865ef Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 24 Aug 2019 23:45:47 +0200 Subject: [PATCH 405/618] Generate version file if it doesn't exist --- src/bootstrap/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 6805474aa049f..7983c973cf1ec 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -375,7 +375,7 @@ impl Step for Standalone { up_to_date(&footer, &html) && up_to_date(&favicon, &html) && up_to_date(&full_toc, &html) && - up_to_date(&version_info, &html) && + (builder.config.dry_run || up_to_date(&version_info, &html)) && (builder.config.dry_run || up_to_date(&rustdoc, &html)) { continue } From 991f4366336820a61dd7f22e849c57d4a64b41ea Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 2 Sep 2019 15:58:05 +0200 Subject: [PATCH 406/618] Fix regex replacement in theme detection --- src/librustdoc/html/static/storage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index 40a6a156972f6..eae998ca3ecbf 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -119,7 +119,7 @@ function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) { function getSystemValue() { var property = getComputedStyle(document.documentElement).getPropertyValue('content'); - return property.replace(/\"\'/g, ""); + return property.replace(/[\"\']/g, ""); } switchTheme(currentTheme, mainTheme, From bf44f12d66b011bf14c4bbe4a652a853ef3e52cb Mon Sep 17 00:00:00 2001 From: nathanwhit Date: Mon, 2 Sep 2019 12:00:55 -0400 Subject: [PATCH 407/618] Ignore check-run-results tests for wasm32-bare Ignores run-pass tests with the `check-run-results` flag enabled for the wasm32-bare ("wasm32-unknown-unknown") target, as it does not support printing to stdout/stderr. --- src/tools/compiletest/src/header.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index dcd4f14f354d1..3ba8cffe2b559 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -137,6 +137,11 @@ impl EarlyProps { config.parse_needs_sanitizer_support(ln) { props.ignore = Ignore::Ignore; } + + if config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln) { + props.ignore = Ignore::Ignore; + } + } if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoGdbLldb) && From dd870d742244fc8c9399bfac6f91e15a51d02d08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Sep 2019 10:19:09 -0700 Subject: [PATCH 408/618] fix typo --- src/librustc_typeck/check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4a0b3879cb991..2cfe080771456 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3688,7 +3688,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail - /// expression's `Span`, otherwise return `expr.span`. This is done to give bettern errors + /// expression's `Span`, otherwise return `expr.span`. This is done to give better errors /// when given code like the following: /// ```text /// if false { return 0i32; } else { 1u32 } From 46877e289087c67d03572019fca9792d95e55e0c Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Wed, 28 Aug 2019 20:18:25 -0400 Subject: [PATCH 409/618] Fix const eval bug breaking run-pass tests in Miri PR #63580 broke miri's ability to run the run-pass test suite with MIR optimizations enabled. The issue was that we weren't properly handling the substs and DefId associated with a Promoted value. This didn't break anything in rustc because in rustc this code runs before the Inliner pass which is where the DefId and substs can diverge from their initial values. It broke Miri though because it ran this code again after running the optimization pass. --- src/librustc_mir/interpret/place.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 23c9e7fdf67ce..f358bb00f4d12 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -585,8 +585,9 @@ where use rustc::mir::StaticKind; Ok(match place_static.kind { - StaticKind::Promoted(promoted, _) => { - let instance = self.frame().instance; + StaticKind::Promoted(promoted, promoted_substs) => { + let substs = self.subst_from_frame_and_normalize_erasing_regions(promoted_substs); + let instance = ty::Instance::new(place_static.def_id, substs); self.const_eval_raw(GlobalId { instance, promoted: Some(promoted), From dd323f8a72327aba0b4771ea08a8b007bba995ca Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 2 Sep 2019 17:28:37 -0400 Subject: [PATCH 410/618] Emit error on intrinsic to fn ptr casts --- src/librustc/infer/error_reporting/mod.rs | 3 +++ src/librustc/ty/error.rs | 5 +++++ src/librustc/ty/structural_impls.rs | 2 ++ src/librustc_typeck/check/cast.rs | 4 ++++ src/librustc_typeck/check/coercion.rs | 6 ++++++ src/test/ui/reify-intrinsic.rs | 15 +++++++++++++++ src/test/ui/reify-intrinsic.stderr | 22 ++++++++++++++++++++++ 7 files changed, 57 insertions(+) create mode 100644 src/test/ui/reify-intrinsic.rs create mode 100644 src/test/ui/reify-intrinsic.stderr diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 9be73cf3c6d16..e684ccfeeb7ed 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1636,6 +1636,9 @@ impl<'tcx> ObligationCause<'tcx> { TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => { Error0644("closure/generator type that references itself") } + TypeError::IntrinsicCast => { + Error0308("cannot coerce intrinsics to function pointers") + } _ => Error0308("mismatched types"), }, } diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index c70006b68d69a..fe8f94ab1d314 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -46,6 +46,8 @@ pub enum TypeError<'tcx> { ExistentialMismatch(ExpectedFound<&'tcx ty::List>>), ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>), + + IntrinsicCast, } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] @@ -179,6 +181,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { ConstMismatch(ref values) => { write!(f, "expected `{}`, found `{}`", values.expected, values.found) } + IntrinsicCast => { + write!(f, "cannot coerce intrinsics to function pointers") + } } } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 649a5244728ba..ec7cf1a13c596 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -748,6 +748,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { Sorts(ref x) => return tcx.lift(x).map(Sorts), ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch), ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch), + IntrinsicCast => IntrinsicCast, }) } } @@ -1338,6 +1339,7 @@ EnumTypeFoldableImpl! { (ty::error::TypeError::Sorts)(x), (ty::error::TypeError::ExistentialMismatch)(x), (ty::error::TypeError::ConstMismatch)(x), + (ty::error::TypeError::IntrinsicCast), } } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 55e7a10f1aaa4..c216cc92b1e58 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -40,6 +40,7 @@ use rustc::ty::{self, Ty, TypeFoldable, TypeAndMut}; use rustc::ty::subst::SubstsRef; use rustc::ty::adjustment::AllowTwoPhase; use rustc::ty::cast::{CastKind, CastTy}; +use rustc::ty::error::TypeError; use rustc::middle::lang_items; use syntax::ast; use syntax_pos::Span; @@ -461,6 +462,9 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.expr_ty, fcx.tcx.mk_fn_ptr(f), AllowTwoPhase::No); + if let Err(TypeError::IntrinsicCast) = res { + return Err(CastError::IllegalCast); + } if res.is_err() { return Err(CastError::NonScalar); } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 61b9c2a15ba16..f2e1a6e29d6fc 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -70,6 +70,7 @@ use std::ops::Deref; use syntax::feature_gate; use syntax::symbol::sym; use syntax_pos; +use rustc_target::spec::abi::Abi; struct Coerce<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -689,6 +690,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { match b.sty { ty::FnPtr(_) => { let a_sig = a.fn_sig(self.tcx); + // Intrinsics are not coercible to function pointers + if a_sig.abi() == Abi::RustIntrinsic || + a_sig.abi() == Abi::PlatformIntrinsic { + return Err(TypeError::IntrinsicCast); + } let InferOk { value: a_sig, mut obligations } = self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig); diff --git a/src/test/ui/reify-intrinsic.rs b/src/test/ui/reify-intrinsic.rs new file mode 100644 index 0000000000000..09baa059e5567 --- /dev/null +++ b/src/test/ui/reify-intrinsic.rs @@ -0,0 +1,15 @@ +// check-fail + +#![feature(intrinsics)] + +fn a() { + let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute; + //~^ ERROR cannot coerce +} + +fn b() { + let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; + //~^ ERROR casting +} + +fn main() {} diff --git a/src/test/ui/reify-intrinsic.stderr b/src/test/ui/reify-intrinsic.stderr new file mode 100644 index 0000000000000..4a1bd77cf7ee9 --- /dev/null +++ b/src/test/ui/reify-intrinsic.stderr @@ -0,0 +1,22 @@ +error[E0308]: cannot coerce intrinsics to function pointers + --> $DIR/reify-intrinsic.rs:6:64 + | +LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute; + | ^^^^^^^^^^^^^^^^^^^ + | | + | cannot coerce intrinsics to function pointers + | help: use parentheses to call this function: `std::mem::transmute(...)` + | + = note: expected type `unsafe extern "rust-intrinsic" fn(isize) -> usize` + found type `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` + +error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid + --> $DIR/reify-intrinsic.rs:11:13 + | +LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0606. +For more information about an error, try `rustc --explain E0308`. From c430d743e90967e621e27cdbb8bd64de67969ca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Sep 2019 17:37:50 -0700 Subject: [PATCH 411/618] Add match test cases --- ...-to-type-err-cause-on-impl-trait-return.rs | 29 +++++++++++ ...type-err-cause-on-impl-trait-return.stderr | 48 ++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs index d416db628c03f..58109be447e07 100644 --- a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs +++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs @@ -33,4 +33,33 @@ fn qux() -> impl std::fmt::Display { } } +fn bat() -> impl std::fmt::Display { + match 13 { + 0 => return 0i32, + _ => 1u32, + //~^ ERROR mismatched types + } +} + +fn can() -> impl std::fmt::Display { + match 13 { + //~^ ERROR mismatched types + 0 => return 0i32, + 1 => 1u32, + _ => 2u32, + } +} + +fn cat() -> impl std::fmt::Display { + match 13 { + 0 => { + return 0i32; + } + _ => { + 1u32 + //~^ ERROR mismatched types + } + } +} + fn main() {} diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr index 47644d66d1a2c..314ff84ae3c46 100644 --- a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr +++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr @@ -59,6 +59,52 @@ LL | | } = note: expected type `i32` found type `u32` -error: aborting due to 4 previous errors +error[E0308]: mismatched types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:39:14 + | +LL | fn bat() -> impl std::fmt::Display { + | ---------------------- expected because this return type... +LL | match 13 { +LL | 0 => return 0i32, + | ---- ...is found to be `i32` here +LL | _ => 1u32, + | ^^^^ expected i32, found u32 + | + = note: expected type `i32` + found type `u32` + +error[E0308]: mismatched types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:45:5 + | +LL | fn can() -> impl std::fmt::Display { + | ---------------------- expected because this return type... +LL | / match 13 { +LL | | +LL | | 0 => return 0i32, + | | ---- ...is found to be `i32` here +LL | | 1 => 1u32, +LL | | _ => 2u32, +LL | | } + | |_____^ expected i32, found u32 + | + = note: expected type `i32` + found type `u32` + +error[E0308]: mismatched types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:59:13 + | +LL | fn cat() -> impl std::fmt::Display { + | ---------------------- expected because this return type... +... +LL | return 0i32; + | ---- ...is found to be `i32` here +... +LL | 1u32 + | ^^^^ expected i32, found u32 + | + = note: expected type `i32` + found type `u32` + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0308`. From 37f5cc22391e693523e8320a1d5c214610790911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Sep 2019 18:03:54 -0700 Subject: [PATCH 412/618] Do not complain about unconstrained params when Self is Ty Error --- .../constrained_generic_params.rs | 18 ++++++++---------- src/librustc_typeck/impl_wf_check.rs | 4 ++++ src/test/ui/issues/issue-36836.rs | 5 +++++ src/test/ui/issues/issue-36836.stderr | 9 +++++++++ 4 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/issues/issue-36836.rs create mode 100644 src/test/ui/issues/issue-36836.stderr diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs index 79a04b9423a8e..c95f81506cd59 100644 --- a/src/librustc_typeck/constrained_generic_params.rs +++ b/src/librustc_typeck/constrained_generic_params.rs @@ -20,10 +20,10 @@ impl From for Parameter { } /// Returns the set of parameters constrained by the impl header. -pub fn parameters_for_impl<'tcx>(impl_self_ty: Ty<'tcx>, - impl_trait_ref: Option>) - -> FxHashSet -{ +pub fn parameters_for_impl<'tcx>( + impl_self_ty: Ty<'tcx>, + impl_trait_ref: Option>, +) -> FxHashSet { let vec = match impl_trait_ref { Some(tr) => parameters_for(&tr, false), None => parameters_for(&impl_self_ty, false), @@ -36,12 +36,10 @@ pub fn parameters_for_impl<'tcx>(impl_self_ty: Ty<'tcx>, /// uniquely determined by `t` (see RFC 447). If it is true, return the list /// of parameters whose values are needed in order to constrain `ty` - these /// differ, with the latter being a superset, in the presence of projections. -pub fn parameters_for<'tcx, T>(t: &T, - include_nonconstraining: bool) - -> Vec - where T: TypeFoldable<'tcx> -{ - +pub fn parameters_for<'tcx, T: TypeFoldable<'tcx>>( + t: &T, + include_nonconstraining: bool, +) -> Vec { let mut collector = ParameterCollector { parameters: vec![], include_nonconstraining, diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index fcfd9adef54df..8e69fbd9a79ef 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -99,6 +99,10 @@ fn enforce_impl_params_are_constrained( ) { // Every lifetime used in an associated type must be constrained. let impl_self_ty = tcx.type_of(impl_def_id); + if impl_self_ty.sty == ty::Error { + // Don't complain about unconstrained type params when self ty doesn't exist. (#36836) + return; + } let impl_generics = tcx.generics_of(impl_def_id); let impl_predicates = tcx.predicates_of(impl_def_id); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); diff --git a/src/test/ui/issues/issue-36836.rs b/src/test/ui/issues/issue-36836.rs new file mode 100644 index 0000000000000..56d5a7cca4566 --- /dev/null +++ b/src/test/ui/issues/issue-36836.rs @@ -0,0 +1,5 @@ +trait Foo {} + +impl Foo for Bar {} //~ ERROR cannot find type `Bar` in this scope + +fn main() {} diff --git a/src/test/ui/issues/issue-36836.stderr b/src/test/ui/issues/issue-36836.stderr new file mode 100644 index 0000000000000..bfda9b0bbdd7e --- /dev/null +++ b/src/test/ui/issues/issue-36836.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Bar` in this scope + --> $DIR/issue-36836.rs:3:17 + | +LL | impl Foo for Bar {} + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. From 3ea932ab0e622104c97d3818350388de3012c833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Sep 2019 18:21:58 -0700 Subject: [PATCH 413/618] Refer to "`self` type" instead of "receiver type" --- src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/traits/object_safety.rs | 16 ++-- src/librustc_typeck/check/wfcheck.rs | 36 ++++----- src/librustc_typeck/error_codes.rs | 78 ++++++++++++++++++- src/test/ui/did_you_mean/issue-40006.stderr | 2 +- src/test/ui/error-codes/E0033-teach.rs | 2 +- src/test/ui/error-codes/E0033-teach.stderr | 2 +- src/test/ui/error-codes/E0033.rs | 2 +- src/test/ui/error-codes/E0033.stderr | 2 +- .../explicit-self-lifetime-mismatch.rs | 4 +- .../explicit-self-lifetime-mismatch.stderr | 4 +- src/test/ui/issues/issue-17740.rs | 4 +- src/test/ui/issues/issue-17740.stderr | 4 +- src/test/ui/issues/issue-17905-2.rs | 4 +- src/test/ui/issues/issue-17905-2.stderr | 4 +- src/test/ui/issues/issue-19380.stderr | 2 +- src/test/ui/issues/issue-56806.rs | 5 +- src/test/ui/issues/issue-56806.stderr | 5 +- .../object-safety-no-static.stderr | 2 +- src/test/ui/resolve/issue-3907-2.stderr | 2 +- src/test/ui/span/issue-27522.rs | 2 +- src/test/ui/span/issue-27522.stderr | 5 +- src/test/ui/traits/trait-object-safety.stderr | 4 +- src/test/ui/ufcs/ufcs-explicit-self-bad.rs | 14 ++-- .../ui/ufcs/ufcs-explicit-self-bad.stderr | 23 +++--- 25 files changed, 155 insertions(+), 75 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 9be73cf3c6d16..baaccea16cb9b 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1627,7 +1627,7 @@ impl<'tcx> ObligationCause<'tcx> { MainFunctionType => Error0580("main function has wrong type"), StartFunctionType => Error0308("start function has wrong type"), IntrinsicType => Error0308("intrinsic has wrong type"), - MethodReceiver => Error0308("mismatched method receiver"), + MethodReceiver => Error0308("mismatched `self` parameter type"), // In the case where we have no more specific thing to // say, also take a look at the error code, maybe we can diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 7ea7bf0257cf7..aac722b56a983 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -47,13 +47,15 @@ impl ObjectSafetyViolation { "the trait cannot use `Self` as a type parameter \ in the supertraits or where-clauses".into(), ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) => - format!("method `{}` has no receiver", name).into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) => - format!("method `{}` references the `Self` type \ - in its arguments or return type", name).into(), - ObjectSafetyViolation::Method(name, - MethodViolationCode::WhereClauseReferencesSelf(_)) => - format!("method `{}` references the `Self` type in where clauses", name).into(), + format!("associated function `{}` has no `self` parameter", name).into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) => format!( + "method `{}` references the `Self` type in its arguments or return type", + name, + ).into(), + ObjectSafetyViolation::Method( + name, + MethodViolationCode::WhereClauseReferencesSelf(_), + ) => format!("method `{}` references the `Self` type in where clauses", name).into(), ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) => format!("method `{}` has generic type parameters", name).into(), ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) => diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index f95b3e44bf0f7..ac8ee43dd0801 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -762,19 +762,19 @@ fn check_opaque_types<'fcx, 'tcx>( substituted_predicates } +const HELP_FOR_SELF_TYPE: &str = + "consider changing to `self`, `&self`, `&mut self`, `self: Box`, \ + `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one \ + of the previous types except `Self`)"; + fn check_method_receiver<'fcx, 'tcx>( fcx: &FnCtxt<'fcx, 'tcx>, method_sig: &hir::MethodSig, method: &ty::AssocItem, self_ty: Ty<'tcx>, ) { - const HELP_FOR_SELF_TYPE: &str = - "consider changing to `self`, `&self`, `&mut self`, `self: Box`, \ - `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one \ - of the previous types except `Self`)"; // Check that the method has a valid receiver type, given the type `Self`. - debug!("check_method_receiver({:?}, self_ty={:?})", - method, self_ty); + debug!("check_method_receiver({:?}, self_ty={:?})", method, self_ty); if !method.method_has_self_argument { return; @@ -805,12 +805,7 @@ fn check_method_receiver<'fcx, 'tcx>( if fcx.tcx.features().arbitrary_self_types { if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) { // Report error; `arbitrary_self_types` was enabled. - fcx.tcx.sess.diagnostic().mut_span_err( - span, &format!("invalid method receiver type: {:?}", receiver_ty) - ).note("type of `self` must be `Self` or a type that dereferences to it") - .help(HELP_FOR_SELF_TYPE) - .code(DiagnosticId::Error("E0307".into())) - .emit(); + e0307(fcx, span, receiver_ty); } } else { if !receiver_is_valid(fcx, span, receiver_ty, self_ty, false) { @@ -830,17 +825,22 @@ fn check_method_receiver<'fcx, 'tcx>( .emit(); } else { // Report error; would not have worked with `arbitrary_self_types`. - fcx.tcx.sess.diagnostic().mut_span_err( - span, &format!("invalid method receiver type: {:?}", receiver_ty) - ).note("type must be `Self` or a type that dereferences to it") - .help(HELP_FOR_SELF_TYPE) - .code(DiagnosticId::Error("E0307".into())) - .emit(); + e0307(fcx, span, receiver_ty); } } } } +fn e0307(fcx: &FnCtxt<'fcx, 'tcx>, span: Span, receiver_ty: Ty<'_>) { + fcx.tcx.sess.diagnostic().mut_span_err( + span, + &format!("invalid `self` parameter type: {:?}", receiver_ty) + ).note("type of `self` must be `Self` or a type that dereferences to it") + .help(HELP_FOR_SELF_TYPE) + .code(DiagnosticId::Error("E0307".into())) + .emit(); +} + /// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If /// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly /// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index b52183d4b1b56..ae0f17892959d 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -2425,6 +2425,83 @@ struct Bar { x: Foo } ``` "##, +E0307: r##" +This error indicates that the `self` parameter in a method has an invalid +"reciever type". + +Methods take a special first parameter, of which there are three variants: +`self`, `&self`, and `&mut self`. The type `Self` acts as an alias to the +type of the current trait implementor, or "receiver type". Besides the +already mentioned `Self`, `&Self` and `&mut Self` valid receiver types, the +following are also valid, if less common: `self: Box`, +`self: Rc`, `self: Arc`, and `self: Pin

` (where P is one of +the previous types except `Self`). + +``` +# struct Foo; +trait Trait { + fn foo(&self); +// ^^^^^ this let's you refer to the type that implements this trait +} +impl Trait for Foo { +// ^^^ this is the "receiver type" + fn foo(&self) {} +// ^^^^^ this is of type `Foo` +} +``` + +The above is equivalent to: + +``` +# struct Foo; +# trait Trait { +# fn foo(&self); +# } +impl Trait for Foo { + fn foo(&self: &Foo) {} +} +``` + +When using an invalid reciver type, like in the following example, + +```compile_fail,E0307 +# struct Foo; +# struct Bar; +# trait Trait { +# fn foo(&self); +# } +impl Trait for Struct { + fn foo(&self: &Bar) {} +} +``` + +The nightly feature [Arbintrary self types][AST] extends the accepted +receiver type to also include any type that can dereference to `Self`: + +``` +#![feature(arbitrary_self_types)] + +struct Foo; +struct Bar; + +// Because you can dereference `Bar` into `Foo`... +impl std::ops::Deref for Bar { + type Target = Foo; + + fn deref(&self) -> &Foo { + &Foo + } +} + +impl Foo { + fn foo(self: Bar) {} +// ^^^^^^^^^ ...it can be used as the receiver type +} +``` + +[AST]: https://doc.rust-lang.org/unstable-book/language-features/arbitrary-self-types.html +"##, + E0321: r##" A cross-crate opt-out trait was implemented on something which wasn't a struct or enum type. Erroneous code example: @@ -4851,7 +4928,6 @@ register_diagnostics! { // E0247, // E0248, // value used as a type, now reported earlier during resolution as E0412 // E0249, - E0307, // invalid method `self` type // E0319, // trait impls for defaulted traits allowed just for structs/enums // E0372, // coherence not object safe E0377, // the trait `CoerceUnsized` may only be implemented for a coercion diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 87e48cd1e1cd9..6f219a6e0b1fe 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -62,7 +62,7 @@ error[E0038]: the trait `X` cannot be made into an object LL | impl dyn X { | ^^^^^ the trait `X` cannot be made into an object | - = note: method `xxx` has no receiver + = note: associated function `xxx` has no `self` parameter error: aborting due to 9 previous errors diff --git a/src/test/ui/error-codes/E0033-teach.rs b/src/test/ui/error-codes/E0033-teach.rs index 6a27b07fa8b77..9b5e719781281 100644 --- a/src/test/ui/error-codes/E0033-teach.rs +++ b/src/test/ui/error-codes/E0033-teach.rs @@ -8,7 +8,7 @@ fn main() { let trait_obj: &dyn SomeTrait = SomeTrait; //~^ ERROR expected value, found trait `SomeTrait` //~| ERROR E0038 - //~| method `foo` has no receiver + //~| associated function `foo` has no `self` parameter let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033-teach.stderr b/src/test/ui/error-codes/E0033-teach.stderr index fb630de7fc147..1d4c2d788a43b 100644 --- a/src/test/ui/error-codes/E0033-teach.stderr +++ b/src/test/ui/error-codes/E0033-teach.stderr @@ -10,7 +10,7 @@ error[E0038]: the trait `SomeTrait` cannot be made into an object LL | let trait_obj: &dyn SomeTrait = SomeTrait; | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object | - = note: method `foo` has no receiver + = note: associated function `foo` has no `self` parameter error[E0033]: type `&dyn SomeTrait` cannot be dereferenced --> $DIR/E0033-teach.rs:13:9 diff --git a/src/test/ui/error-codes/E0033.rs b/src/test/ui/error-codes/E0033.rs index 582600e110ba0..86dacfd1a47ba 100644 --- a/src/test/ui/error-codes/E0033.rs +++ b/src/test/ui/error-codes/E0033.rs @@ -6,7 +6,7 @@ fn main() { let trait_obj: &dyn SomeTrait = SomeTrait; //~^ ERROR expected value, found trait `SomeTrait` //~| ERROR E0038 - //~| method `foo` has no receiver + //~| associated function `foo` has no `self` parameter let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033.stderr b/src/test/ui/error-codes/E0033.stderr index fe9f45d86a6a0..803d7917e5638 100644 --- a/src/test/ui/error-codes/E0033.stderr +++ b/src/test/ui/error-codes/E0033.stderr @@ -10,7 +10,7 @@ error[E0038]: the trait `SomeTrait` cannot be made into an object LL | let trait_obj: &dyn SomeTrait = SomeTrait; | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object | - = note: method `foo` has no receiver + = note: associated function `foo` has no `self` parameter error[E0033]: type `&dyn SomeTrait` cannot be dereferenced --> $DIR/E0033.rs:11:9 diff --git a/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs b/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs index 82c64bcf6a767..9ab8e13893bc7 100644 --- a/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs +++ b/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs @@ -6,11 +6,11 @@ struct Foo<'a,'b> { impl<'a,'b> Foo<'a,'b> { fn bar(self: Foo<'b,'a> - //~^ ERROR mismatched method receiver + //~^ ERROR mismatched `self` parameter type //~| expected type `Foo<'a, 'b>` //~| found type `Foo<'b, 'a>` //~| lifetime mismatch - //~| ERROR mismatched method receiver + //~| ERROR mismatched `self` parameter type //~| expected type `Foo<'a, 'b>` //~| found type `Foo<'b, 'a>` //~| lifetime mismatch diff --git a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr index e6f9eded9a4f3..4bf2d573d4f96 100644 --- a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr +++ b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr @@ -1,4 +1,4 @@ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/explicit-self-lifetime-mismatch.rs:8:12 | LL | Foo<'b,'a> @@ -17,7 +17,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at LL | impl<'a,'b> Foo<'a,'b> { | ^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/explicit-self-lifetime-mismatch.rs:8:12 | LL | Foo<'b,'a> diff --git a/src/test/ui/issues/issue-17740.rs b/src/test/ui/issues/issue-17740.rs index c131b895849ae..b47568400c3b7 100644 --- a/src/test/ui/issues/issue-17740.rs +++ b/src/test/ui/issues/issue-17740.rs @@ -4,11 +4,11 @@ struct Foo<'a> { impl <'a> Foo<'a>{ fn bar(self: &mut Foo) { - //~^ mismatched method receiver + //~^ mismatched `self` parameter type //~| expected type `Foo<'a>` //~| found type `Foo<'_>` //~| lifetime mismatch - //~| mismatched method receiver + //~| mismatched `self` parameter type //~| expected type `Foo<'a>` //~| found type `Foo<'_>` //~| lifetime mismatch diff --git a/src/test/ui/issues/issue-17740.stderr b/src/test/ui/issues/issue-17740.stderr index 7ab0fa4d818b0..b8a0a0676319a 100644 --- a/src/test/ui/issues/issue-17740.stderr +++ b/src/test/ui/issues/issue-17740.stderr @@ -1,4 +1,4 @@ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/issue-17740.rs:6:18 | LL | fn bar(self: &mut Foo) { @@ -23,7 +23,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at LL | impl <'a> Foo<'a>{ | ^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/issue-17740.rs:6:18 | LL | fn bar(self: &mut Foo) { diff --git a/src/test/ui/issues/issue-17905-2.rs b/src/test/ui/issues/issue-17905-2.rs index 259d945018938..44279cc867b46 100644 --- a/src/test/ui/issues/issue-17905-2.rs +++ b/src/test/ui/issues/issue-17905-2.rs @@ -6,8 +6,8 @@ impl Pair< isize > { fn say(self: &Pair<&str, isize>) { -//~^ ERROR mismatched method receiver -//~| ERROR mismatched method receiver +//~^ ERROR mismatched `self` parameter type +//~| ERROR mismatched `self` parameter type println!("{:?}", self); } } diff --git a/src/test/ui/issues/issue-17905-2.stderr b/src/test/ui/issues/issue-17905-2.stderr index e3909e0c1253f..585bc9c14883b 100644 --- a/src/test/ui/issues/issue-17905-2.stderr +++ b/src/test/ui/issues/issue-17905-2.stderr @@ -1,4 +1,4 @@ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/issue-17905-2.rs:8:18 | LL | fn say(self: &Pair<&str, isize>) { @@ -21,7 +21,7 @@ note: ...does not necessarily outlive the lifetime '_ as defined on the impl at LL | &str, | ^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/issue-17905-2.rs:8:18 | LL | fn say(self: &Pair<&str, isize>) { diff --git a/src/test/ui/issues/issue-19380.stderr b/src/test/ui/issues/issue-19380.stderr index 27e3ff57bf9ab..d70a7c2b5299c 100644 --- a/src/test/ui/issues/issue-19380.stderr +++ b/src/test/ui/issues/issue-19380.stderr @@ -4,7 +4,7 @@ error[E0038]: the trait `Qiz` cannot be made into an object LL | foos: &'static [&'static (dyn Qiz + 'static)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object | - = note: method `qiz` has no receiver + = note: associated function `qiz` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/issues/issue-56806.rs b/src/test/ui/issues/issue-56806.rs index b6454e578e6af..b1dac26d65a15 100644 --- a/src/test/ui/issues/issue-56806.rs +++ b/src/test/ui/issues/issue-56806.rs @@ -1,7 +1,6 @@ pub trait Trait { fn dyn_instead_of_self(self: Box); - //~^ ERROR invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)> + //~^ ERROR invalid `self` parameter type } -pub fn main() { -} +pub fn main() {} diff --git a/src/test/ui/issues/issue-56806.stderr b/src/test/ui/issues/issue-56806.stderr index fae6a26720f36..a4f9aadcfef3e 100644 --- a/src/test/ui/issues/issue-56806.stderr +++ b/src/test/ui/issues/issue-56806.stderr @@ -1,11 +1,12 @@ -error[E0307]: invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)> +error[E0307]: invalid `self` parameter type: std::boxed::Box<(dyn Trait + 'static)> --> $DIR/issue-56806.rs:2:34 | LL | fn dyn_instead_of_self(self: Box); | ^^^^^^^^^^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error: aborting due to previous error +For more information about this error, try `rustc --explain E0307`. diff --git a/src/test/ui/object-safety/object-safety-no-static.stderr b/src/test/ui/object-safety/object-safety-no-static.stderr index da8dd657c2a9d..c189c358b4223 100644 --- a/src/test/ui/object-safety/object-safety-no-static.stderr +++ b/src/test/ui/object-safety/object-safety-no-static.stderr @@ -4,7 +4,7 @@ error[E0038]: the trait `Foo` cannot be made into an object LL | fn foo_implicit(b: Box) -> Box { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | - = note: method `foo` has no receiver + = note: associated function `foo` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr index 968c1f3e463d0..63ac11dc8ae01 100644 --- a/src/test/ui/resolve/issue-3907-2.stderr +++ b/src/test/ui/resolve/issue-3907-2.stderr @@ -4,7 +4,7 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object LL | fn bar(_x: Foo) {} | ^^^^^^^^^^^^^^^ the trait `issue_3907::Foo` cannot be made into an object | - = note: method `bar` has no receiver + = note: associated function `bar` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/span/issue-27522.rs b/src/test/ui/span/issue-27522.rs index 5c9893f64a6ee..7a0cfb679ed67 100644 --- a/src/test/ui/span/issue-27522.rs +++ b/src/test/ui/span/issue-27522.rs @@ -3,7 +3,7 @@ struct SomeType {} trait Foo { - fn handler(self: &SomeType); //~ ERROR invalid method receiver type + fn handler(self: &SomeType); //~ ERROR invalid `self` parameter type } fn main() {} diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr index 88dfee1cada3f..8a254a9685543 100644 --- a/src/test/ui/span/issue-27522.stderr +++ b/src/test/ui/span/issue-27522.stderr @@ -1,11 +1,12 @@ -error[E0307]: invalid method receiver type: &SomeType +error[E0307]: invalid `self` parameter type: &SomeType --> $DIR/issue-27522.rs:6:22 | LL | fn handler(self: &SomeType); | ^^^^^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error: aborting due to previous error +For more information about this error, try `rustc --explain E0307`. diff --git a/src/test/ui/traits/trait-object-safety.stderr b/src/test/ui/traits/trait-object-safety.stderr index 68edc17870534..7f6bc0ebb70e5 100644 --- a/src/test/ui/traits/trait-object-safety.stderr +++ b/src/test/ui/traits/trait-object-safety.stderr @@ -4,7 +4,7 @@ error[E0038]: the trait `Tr` cannot be made into an object LL | let _: &dyn Tr = &St; | ^^^ the trait `Tr` cannot be made into an object | - = note: method `foo` has no receiver + = note: associated function `foo` has no `self` parameter = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St` error[E0038]: the trait `Tr` cannot be made into an object @@ -13,7 +13,7 @@ error[E0038]: the trait `Tr` cannot be made into an object LL | let _: &dyn Tr = &St; | ^^^^^^^ the trait `Tr` cannot be made into an object | - = note: method `foo` has no receiver + = note: associated function `foo` has no `self` parameter error: aborting due to 2 previous errors diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs index c6ff94a5e7606..bdb8e197fbe49 100644 --- a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs +++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs @@ -6,7 +6,7 @@ struct Foo { impl Foo { fn foo(self: isize, x: isize) -> isize { - //~^ ERROR invalid method receiver type + //~^ ERROR invalid `self` parameter type self.f + x } } @@ -17,11 +17,11 @@ struct Bar { impl Bar { fn foo(self: Bar, x: isize) -> isize { - //~^ ERROR invalid method receiver type + //~^ ERROR invalid `self` parameter type x } fn bar(self: &Bar, x: isize) -> isize { - //~^ ERROR invalid method receiver type + //~^ ERROR invalid `self` parameter type x } } @@ -34,14 +34,14 @@ trait SomeTrait { impl<'a, T> SomeTrait for &'a Bar { fn dummy1(self: &&'a Bar) { } - fn dummy2(self: &Bar) {} //~ ERROR mismatched method receiver - //~^ ERROR mismatched method receiver + fn dummy2(self: &Bar) {} //~ ERROR mismatched `self` parameter type + //~^ ERROR mismatched `self` parameter type fn dummy3(self: &&Bar) {} - //~^ ERROR mismatched method receiver + //~^ ERROR mismatched `self` parameter type //~| expected type `&'a Bar` //~| found type `&Bar` //~| lifetime mismatch - //~| ERROR mismatched method receiver + //~| ERROR mismatched `self` parameter type //~| expected type `&'a Bar` //~| found type `&Bar` //~| lifetime mismatch diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr index 6da20e37577b0..b2fe1b281fc99 100644 --- a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr +++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -1,31 +1,31 @@ -error[E0307]: invalid method receiver type: isize +error[E0307]: invalid `self` parameter type: isize --> $DIR/ufcs-explicit-self-bad.rs:8:18 | LL | fn foo(self: isize, x: isize) -> isize { | ^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0307]: invalid method receiver type: Bar +error[E0307]: invalid `self` parameter type: Bar --> $DIR/ufcs-explicit-self-bad.rs:19:18 | LL | fn foo(self: Bar, x: isize) -> isize { | ^^^^^^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0307]: invalid method receiver type: &Bar +error[E0307]: invalid `self` parameter type: &Bar --> $DIR/ufcs-explicit-self-bad.rs:23:18 | LL | fn bar(self: &Bar, x: isize) -> isize { | ^^^^^^^^^^^ | - = note: type must be `Self` or a type that dereferences to it + = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:37:21 | LL | fn dummy2(self: &Bar) {} @@ -44,7 +44,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at LL | impl<'a, T> SomeTrait for &'a Bar { | ^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:37:21 | LL | fn dummy2(self: &Bar) {} @@ -63,7 +63,7 @@ note: ...does not necessarily outlive the anonymous lifetime #1 defined on the m LL | fn dummy2(self: &Bar) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:39:21 | LL | fn dummy3(self: &&Bar) {} @@ -82,7 +82,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at LL | impl<'a, T> SomeTrait for &'a Bar { | ^^ -error[E0308]: mismatched method receiver +error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:39:21 | LL | fn dummy3(self: &&Bar) {} @@ -103,4 +103,5 @@ LL | fn dummy3(self: &&Bar) {} error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0307, E0308. +For more information about an error, try `rustc --explain E0307`. From c1e5e5c56717c5fe224db425d891c274a3f3cb5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Sep 2019 20:22:22 -0700 Subject: [PATCH 414/618] On object safety violation, point at source when possible --- src/librustc/traits/error_reporting.rs | 5 +- src/librustc/traits/object_safety.rs | 54 +++++++++++-------- .../associated-const-in-trait.stderr | 5 +- ...mpl-trait-for-trait-object-safe.old.stderr | 4 +- ...impl-trait-for-trait-object-safe.re.stderr | 4 +- src/test/ui/did_you_mean/issue-40006.stderr | 5 +- src/test/ui/error-codes/E0033-teach.rs | 3 +- src/test/ui/error-codes/E0033-teach.stderr | 7 +-- src/test/ui/error-codes/E0033.rs | 3 +- src/test/ui/error-codes/E0033.stderr | 7 +-- src/test/ui/error-codes/E0038.stderr | 5 +- src/test/ui/issues/issue-18959.stderr | 5 +- src/test/ui/issues/issue-19380.stderr | 5 +- src/test/ui/issues/issue-19538.stderr | 9 ++-- src/test/ui/issues/issue-50781.stderr | 4 +- .../object-safety-associated-consts.stderr | 5 +- .../object-safety-generics.stderr | 10 ++-- .../object-safety-mentions-Self.stderr | 10 ++-- .../object-safety-no-static.stderr | 5 +- src/test/ui/resolve/issue-3907-2.stderr | 2 - ...rbitrary-self-types-not-object-safe.stderr | 9 ++-- src/test/ui/traits/trait-item-privacy.stderr | 13 +++-- src/test/ui/traits/trait-object-safety.stderr | 9 ++-- src/test/ui/traits/trait-test-2.stderr | 15 ++++-- ...ter-defaults-referencing-Self-ppaux.stderr | 5 +- src/test/ui/wf/wf-object-safe.stderr | 5 +- 26 files changed, 129 insertions(+), 84 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index b38e1f5f83937..03cc00d87e3cd 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1384,7 +1384,10 @@ impl<'tcx> TyCtxt<'tcx> { let mut reported_violations = FxHashSet::default(); for violation in violations { if reported_violations.insert(violation.clone()) { - err.note(&violation.error_msg()); + match violation.span() { + Some(span) => err.span_label(span, violation.error_msg()), + None => err.note(&violation.error_msg()), + }; } } Some(err) diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index aac722b56a983..50f497e302e6d 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -32,10 +32,10 @@ pub enum ObjectSafetyViolation { SupertraitSelf, /// Method has something illegal. - Method(ast::Name, MethodViolationCode), + Method(ast::Name, MethodViolationCode, Span), /// Associated const. - AssocConst(ast::Name), + AssocConst(ast::Name, Span), } impl ObjectSafetyViolation { @@ -46,24 +46,33 @@ impl ObjectSafetyViolation { ObjectSafetyViolation::SupertraitSelf => "the trait cannot use `Self` as a type parameter \ in the supertraits or where-clauses".into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) => + ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod, _) => format!("associated function `{}` has no `self` parameter", name).into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) => format!( + ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf, _) => format!( "method `{}` references the `Self` type in its arguments or return type", name, ).into(), ObjectSafetyViolation::Method( name, - MethodViolationCode::WhereClauseReferencesSelf(_), + MethodViolationCode::WhereClauseReferencesSelf, + _, ) => format!("method `{}` references the `Self` type in where clauses", name).into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) => + ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => format!("method `{}` has generic type parameters", name).into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) => + ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => format!("method `{}`'s receiver cannot be dispatched on", name).into(), - ObjectSafetyViolation::AssocConst(name) => + ObjectSafetyViolation::AssocConst(name, _) => format!("the trait cannot contain associated consts like `{}`", name).into(), } } + + pub fn span(&self) -> Option { + match self { + ObjectSafetyViolation::AssocConst(_, span) | + ObjectSafetyViolation::Method(_, _, span) => Some(*span), + _ => None, + } + } } /// Reasons a method might not be object-safe. @@ -76,7 +85,7 @@ pub enum MethodViolationCode { ReferencesSelf, /// e.g., `fn foo(&self) where Self: Clone` - WhereClauseReferencesSelf(Span), + WhereClauseReferencesSelf, /// e.g., `fn foo()` Generic, @@ -90,9 +99,10 @@ impl<'tcx> TyCtxt<'tcx> { /// astconv -- currently, `Self` in supertraits. This is needed /// because `object_safety_violations` can't be used during /// type collection. - pub fn astconv_object_safety_violations(self, trait_def_id: DefId) - -> Vec - { + pub fn astconv_object_safety_violations( + self, + trait_def_id: DefId, + ) -> Vec { debug_assert!(self.generics_of(trait_def_id).has_self); let violations = traits::supertrait_def_ids(self, trait_def_id) .filter(|&def_id| self.predicates_reference_self(def_id, true)) @@ -130,7 +140,7 @@ impl<'tcx> TyCtxt<'tcx> { } match self.virtual_call_violation_for_method(trait_def_id, method) { - None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true, + None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true, Some(_) => false, } } @@ -140,12 +150,15 @@ impl<'tcx> TyCtxt<'tcx> { let mut violations: Vec<_> = self.associated_items(trait_def_id) .filter(|item| item.kind == ty::AssocKind::Method) .filter_map(|item| - self.object_safety_violation_for_method(trait_def_id, &item) - .map(|code| ObjectSafetyViolation::Method(item.ident.name, code)) + self.object_safety_violation_for_method(trait_def_id, &item).map(|code| { + ObjectSafetyViolation::Method(item.ident.name, code, item.ident.span) + }) ).filter(|violation| { - if let ObjectSafetyViolation::Method(_, - MethodViolationCode::WhereClauseReferencesSelf(span)) = violation - { + if let ObjectSafetyViolation::Method( + _, + MethodViolationCode::WhereClauseReferencesSelf, + span, + ) = violation { // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id. // It's also hard to get a use site span, so we use the method definition span. self.lint_node_note( @@ -171,7 +184,7 @@ impl<'tcx> TyCtxt<'tcx> { violations.extend(self.associated_items(trait_def_id) .filter(|item| item.kind == ty::AssocKind::Const) - .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name))); + .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span))); debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}", trait_def_id, @@ -327,8 +340,7 @@ impl<'tcx> TyCtxt<'tcx> { .visit_tys_shallow(|t| { self.contains_illegal_self_type_reference(trait_def_id, t) }) { - let span = self.def_span(method.def_id); - return Some(MethodViolationCode::WhereClauseReferencesSelf(span)); + return Some(MethodViolationCode::WhereClauseReferencesSelf); } let receiver_ty = self.liberate_late_bound_regions( diff --git a/src/test/ui/associated-const/associated-const-in-trait.stderr b/src/test/ui/associated-const/associated-const-in-trait.stderr index dff268a55c909..a5d7fc5b70246 100644 --- a/src/test/ui/associated-const/associated-const-in-trait.stderr +++ b/src/test/ui/associated-const/associated-const-in-trait.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/associated-const-in-trait.rs:9:6 | +LL | const N: usize; + | - the trait cannot contain associated consts like `N` +... LL | impl dyn Trait { | ^^^^^^^^^ the trait `Trait` cannot be made into an object - | - = note: the trait cannot contain associated consts like `N` error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr index c38d7456a9952..2626eab3cbf23 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr @@ -1,10 +1,10 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6 | +LL | trait NotObjectSafe { fn eq(&self, other: Self); } + | -- method `eq` references the `Self` type in its arguments or return type LL | impl NotObjectSafe for dyn NotObjectSafe { } | ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object - | - = note: method `eq` references the `Self` type in its arguments or return type error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr index c38d7456a9952..2626eab3cbf23 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr @@ -1,10 +1,10 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6 | +LL | trait NotObjectSafe { fn eq(&self, other: Self); } + | -- method `eq` references the `Self` type in its arguments or return type LL | impl NotObjectSafe for dyn NotObjectSafe { } | ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object - | - = note: method `eq` references the `Self` type in its arguments or return type error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 6f219a6e0b1fe..5b384045a486a 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -61,8 +61,9 @@ error[E0038]: the trait `X` cannot be made into an object | LL | impl dyn X { | ^^^^^ the trait `X` cannot be made into an object - | - = note: associated function `xxx` has no `self` parameter +... +LL | fn xxx() { ### } + | --- associated function `xxx` has no `self` parameter error: aborting due to 9 previous errors diff --git a/src/test/ui/error-codes/E0033-teach.rs b/src/test/ui/error-codes/E0033-teach.rs index 9b5e719781281..1943965139423 100644 --- a/src/test/ui/error-codes/E0033-teach.rs +++ b/src/test/ui/error-codes/E0033-teach.rs @@ -1,14 +1,13 @@ // compile-flags: -Z teach trait SomeTrait { - fn foo(); + fn foo(); //~ associated function `foo` has no `self` parameter } fn main() { let trait_obj: &dyn SomeTrait = SomeTrait; //~^ ERROR expected value, found trait `SomeTrait` //~| ERROR E0038 - //~| associated function `foo` has no `self` parameter let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033-teach.stderr b/src/test/ui/error-codes/E0033-teach.stderr index 1d4c2d788a43b..80f3d4441bd9f 100644 --- a/src/test/ui/error-codes/E0033-teach.stderr +++ b/src/test/ui/error-codes/E0033-teach.stderr @@ -7,13 +7,14 @@ LL | let trait_obj: &dyn SomeTrait = SomeTrait; error[E0038]: the trait `SomeTrait` cannot be made into an object --> $DIR/E0033-teach.rs:8:20 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | let trait_obj: &dyn SomeTrait = SomeTrait; | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object - | - = note: associated function `foo` has no `self` parameter error[E0033]: type `&dyn SomeTrait` cannot be dereferenced - --> $DIR/E0033-teach.rs:13:9 + --> $DIR/E0033-teach.rs:12:9 | LL | let &invalid = trait_obj; | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced diff --git a/src/test/ui/error-codes/E0033.rs b/src/test/ui/error-codes/E0033.rs index 86dacfd1a47ba..e5f0530f45ff8 100644 --- a/src/test/ui/error-codes/E0033.rs +++ b/src/test/ui/error-codes/E0033.rs @@ -1,12 +1,11 @@ trait SomeTrait { - fn foo(); + fn foo(); //~ associated function `foo` has no `self` parameter } fn main() { let trait_obj: &dyn SomeTrait = SomeTrait; //~^ ERROR expected value, found trait `SomeTrait` //~| ERROR E0038 - //~| associated function `foo` has no `self` parameter let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033.stderr b/src/test/ui/error-codes/E0033.stderr index 803d7917e5638..c2843796cc851 100644 --- a/src/test/ui/error-codes/E0033.stderr +++ b/src/test/ui/error-codes/E0033.stderr @@ -7,13 +7,14 @@ LL | let trait_obj: &dyn SomeTrait = SomeTrait; error[E0038]: the trait `SomeTrait` cannot be made into an object --> $DIR/E0033.rs:6:20 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | let trait_obj: &dyn SomeTrait = SomeTrait; | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object - | - = note: associated function `foo` has no `self` parameter error[E0033]: type `&dyn SomeTrait` cannot be dereferenced - --> $DIR/E0033.rs:11:9 + --> $DIR/E0033.rs:10:9 | LL | let &invalid = trait_obj; | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr index e3d7593e42a71..93a7681393b29 100644 --- a/src/test/ui/error-codes/E0038.stderr +++ b/src/test/ui/error-codes/E0038.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/E0038.rs:5:1 | +LL | fn foo(&self) -> Self; + | --- method `foo` references the `Self` type in its arguments or return type +... LL | fn call_foo(x: Box) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object - | - = note: method `foo` references the `Self` type in its arguments or return type error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18959.stderr b/src/test/ui/issues/issue-18959.stderr index 63c33b7f4472d..d5e7092801ecd 100644 --- a/src/test/ui/issues/issue-18959.stderr +++ b/src/test/ui/issues/issue-18959.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-18959.rs:11:1 | +LL | pub trait Foo { fn foo(&self, ext_thing: &T); } + | --- method `foo` has generic type parameters +... LL | fn foo(b: &dyn Bar) { | ^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `foo` has generic type parameters error: aborting due to previous error diff --git a/src/test/ui/issues/issue-19380.stderr b/src/test/ui/issues/issue-19380.stderr index d70a7c2b5299c..92bfdf1f26e93 100644 --- a/src/test/ui/issues/issue-19380.stderr +++ b/src/test/ui/issues/issue-19380.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Qiz` cannot be made into an object --> $DIR/issue-19380.rs:11:3 | +LL | fn qiz(); + | --- associated function `qiz` has no `self` parameter +... LL | foos: &'static [&'static (dyn Qiz + 'static)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object - | - = note: associated function `qiz` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/issues/issue-19538.stderr b/src/test/ui/issues/issue-19538.stderr index e5da0a9b0dac3..5415a45f7d621 100644 --- a/src/test/ui/issues/issue-19538.stderr +++ b/src/test/ui/issues/issue-19538.stderr @@ -1,18 +1,21 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-19538.rs:17:15 | +LL | fn foo(&self, val: T); + | --- method `foo` has generic type parameters +... LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `foo` has generic type parameters error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-19538.rs:17:30 | +LL | fn foo(&self, val: T); + | --- method `foo` has generic type parameters +... LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^ the trait `Bar` cannot be made into an object | - = note: method `foo` has generic type parameters = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&mut dyn Bar>` for `&mut Thing` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-50781.stderr b/src/test/ui/issues/issue-50781.stderr index c98f78c51ee5f..02475ea97e3d1 100644 --- a/src/test/ui/issues/issue-50781.stderr +++ b/src/test/ui/issues/issue-50781.stderr @@ -1,8 +1,8 @@ error: the trait `X` cannot be made into an object - --> $DIR/issue-50781.rs:6:5 + --> $DIR/issue-50781.rs:6:8 | LL | fn foo(&self) where Self: Trait; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ | note: lint level defined here --> $DIR/issue-50781.rs:1:9 diff --git a/src/test/ui/object-safety/object-safety-associated-consts.stderr b/src/test/ui/object-safety/object-safety-associated-consts.stderr index 55f9e3f9f138b..7d5aa00356e0b 100644 --- a/src/test/ui/object-safety/object-safety-associated-consts.stderr +++ b/src/test/ui/object-safety/object-safety-associated-consts.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-associated-consts.rs:9:1 | +LL | const X: usize; + | - the trait cannot contain associated consts like `X` +... LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: the trait cannot contain associated consts like `X` error: aborting due to previous error diff --git a/src/test/ui/object-safety/object-safety-generics.stderr b/src/test/ui/object-safety/object-safety-generics.stderr index d66cdb98448d4..b25e0052e4163 100644 --- a/src/test/ui/object-safety/object-safety-generics.stderr +++ b/src/test/ui/object-safety/object-safety-generics.stderr @@ -1,18 +1,20 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-generics.rs:14:1 | +LL | fn bar(&self, t: T); + | --- method `bar` has generic type parameters +... LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `bar` has generic type parameters error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-generics.rs:19:1 | +LL | fn bar(&self, t: T); + | --- method `bar` has generic type parameters +... LL | fn make_bar_explicit(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `bar` has generic type parameters error: aborting due to 2 previous errors diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.stderr index c0c471c2b1e72..e2d1e773809bb 100644 --- a/src/test/ui/object-safety/object-safety-mentions-Self.stderr +++ b/src/test/ui/object-safety/object-safety-mentions-Self.stderr @@ -1,18 +1,20 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-mentions-Self.rs:17:1 | +LL | fn bar(&self, x: &Self); + | --- method `bar` references the `Self` type in its arguments or return type +... LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | - = note: method `bar` references the `Self` type in its arguments or return type error[E0038]: the trait `Baz` cannot be made into an object --> $DIR/object-safety-mentions-Self.rs:22:1 | +LL | fn bar(&self) -> Self; + | --- method `bar` references the `Self` type in its arguments or return type +... LL | fn make_baz(t: &T) -> &dyn Baz { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object - | - = note: method `bar` references the `Self` type in its arguments or return type error: aborting due to 2 previous errors diff --git a/src/test/ui/object-safety/object-safety-no-static.stderr b/src/test/ui/object-safety/object-safety-no-static.stderr index c189c358b4223..0de783f60ea47 100644 --- a/src/test/ui/object-safety/object-safety-no-static.stderr +++ b/src/test/ui/object-safety/object-safety-no-static.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/object-safety-no-static.rs:8:1 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | fn foo_implicit(b: Box) -> Box { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object - | - = note: associated function `foo` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr index 63ac11dc8ae01..087d1a5b9d365 100644 --- a/src/test/ui/resolve/issue-3907-2.stderr +++ b/src/test/ui/resolve/issue-3907-2.stderr @@ -3,8 +3,6 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object | LL | fn bar(_x: Foo) {} | ^^^^^^^^^^^^^^^ the trait `issue_3907::Foo` cannot be made into an object - | - = note: associated function `bar` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr index e45bc2657f1ea..9fb1500afce47 100644 --- a/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr @@ -1,18 +1,21 @@ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/arbitrary-self-types-not-object-safe.rs:31:32 | +LL | fn foo(self: &Rc) -> usize; + | --- method `foo`'s receiver cannot be dispatched on +... LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^ the trait `Foo` cannot be made into an object - | - = note: method `foo`'s receiver cannot be dispatched on error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/arbitrary-self-types-not-object-safe.rs:31:13 | +LL | fn foo(self: &Rc) -> usize; + | --- method `foo`'s receiver cannot be dispatched on +... LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | - = note: method `foo`'s receiver cannot be dispatched on = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::rc::Rc` error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index de699a69fa8bc..aec648d7b8473 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -103,12 +103,17 @@ LL | C::A; error[E0038]: the trait `assoc_const::C` cannot be made into an object --> $DIR/trait-item-privacy.rs:101:5 | +LL | const A: u8 = 0; + | - the trait cannot contain associated consts like `A` +... +LL | const B: u8 = 0; + | - the trait cannot contain associated consts like `B` +... +LL | const C: u8 = 0; + | - the trait cannot contain associated consts like `C` +... LL | C::A; | ^^^^ the trait `assoc_const::C` cannot be made into an object - | - = note: the trait cannot contain associated consts like `C` - = note: the trait cannot contain associated consts like `B` - = note: the trait cannot contain associated consts like `A` error[E0223]: ambiguous associated type --> $DIR/trait-item-privacy.rs:115:12 diff --git a/src/test/ui/traits/trait-object-safety.stderr b/src/test/ui/traits/trait-object-safety.stderr index 7f6bc0ebb70e5..3ac1e96b30c95 100644 --- a/src/test/ui/traits/trait-object-safety.stderr +++ b/src/test/ui/traits/trait-object-safety.stderr @@ -1,19 +1,22 @@ error[E0038]: the trait `Tr` cannot be made into an object --> $DIR/trait-object-safety.rs:15:22 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | let _: &dyn Tr = &St; | ^^^ the trait `Tr` cannot be made into an object | - = note: associated function `foo` has no `self` parameter = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St` error[E0038]: the trait `Tr` cannot be made into an object --> $DIR/trait-object-safety.rs:15:12 | +LL | fn foo(); + | --- associated function `foo` has no `self` parameter +... LL | let _: &dyn Tr = &St; | ^^^^^^^ the trait `Tr` cannot be made into an object - | - = note: associated function `foo` has no `self` parameter error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr index 5d5251925a1ae..4d2aca0d4094a 100644 --- a/src/test/ui/traits/trait-test-2.stderr +++ b/src/test/ui/traits/trait-test-2.stderr @@ -13,20 +13,25 @@ LL | 10.blah::(); error[E0038]: the trait `bar` cannot be made into an object --> $DIR/trait-test-2.rs:11:16 | +LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } + | --- ---- method `blah` has generic type parameters + | | + | method `dup` references the `Self` type in its arguments or return type +... LL | (box 10 as Box).dup(); | ^^^^^^^^^^^^ the trait `bar` cannot be made into an object - | - = note: method `dup` references the `Self` type in its arguments or return type - = note: method `blah` has generic type parameters error[E0038]: the trait `bar` cannot be made into an object --> $DIR/trait-test-2.rs:11:6 | +LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } + | --- ---- method `blah` has generic type parameters + | | + | method `dup` references the `Self` type in its arguments or return type +... LL | (box 10 as Box).dup(); | ^^^^^^ the trait `bar` cannot be made into an object | - = note: method `dup` references the `Self` type in its arguments or return type - = note: method `blah` has generic type parameters = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box<{integer}>` error: aborting due to 4 previous errors diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr index 58727ea0fef99..03df5b8211889 100644 --- a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr +++ b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr @@ -13,10 +13,11 @@ LL | let y = x as dyn MyAdd; error[E0038]: the trait `MyAdd` cannot be made into an object --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18 | +LL | trait MyAdd { fn add(&self, other: &Rhs) -> Self; } + | --- method `add` references the `Self` type in its arguments or return type +... LL | let y = x as dyn MyAdd; | ^^^^^^^^^^^^^^ the trait `MyAdd` cannot be made into an object - | - = note: method `add` references the `Self` type in its arguments or return type error: aborting due to 2 previous errors diff --git a/src/test/ui/wf/wf-object-safe.stderr b/src/test/ui/wf/wf-object-safe.stderr index 3b264ecd580ec..d11af11f05051 100644 --- a/src/test/ui/wf/wf-object-safe.stderr +++ b/src/test/ui/wf/wf-object-safe.stderr @@ -1,10 +1,11 @@ error[E0038]: the trait `A` cannot be made into an object --> $DIR/wf-object-safe.rs:9:13 | +LL | fn foo(&self, _x: &Self); + | --- method `foo` references the `Self` type in its arguments or return type +... LL | let _x: &dyn A; | ^^^^^^ the trait `A` cannot be made into an object - | - = note: method `foo` references the `Self` type in its arguments or return type error: aborting due to previous error From 3cb1ed4279d8ca4528e3777d5470ca7dc85a976a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Sep 2019 20:51:31 -0700 Subject: [PATCH 415/618] review comments --- src/librustc_typeck/constrained_generic_params.rs | 4 ++-- src/test/ui/issues/issue-36836.rs | 10 ++++++++++ src/test/ui/issues/issue-36836.stderr | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs index c95f81506cd59..dd44f86717fe5 100644 --- a/src/librustc_typeck/constrained_generic_params.rs +++ b/src/librustc_typeck/constrained_generic_params.rs @@ -36,8 +36,8 @@ pub fn parameters_for_impl<'tcx>( /// uniquely determined by `t` (see RFC 447). If it is true, return the list /// of parameters whose values are needed in order to constrain `ty` - these /// differ, with the latter being a superset, in the presence of projections. -pub fn parameters_for<'tcx, T: TypeFoldable<'tcx>>( - t: &T, +pub fn parameters_for<'tcx>( + t: &impl TypeFoldable<'tcx>, include_nonconstraining: bool, ) -> Vec { let mut collector = ParameterCollector { diff --git a/src/test/ui/issues/issue-36836.rs b/src/test/ui/issues/issue-36836.rs index 56d5a7cca4566..99c56213153e4 100644 --- a/src/test/ui/issues/issue-36836.rs +++ b/src/test/ui/issues/issue-36836.rs @@ -1,3 +1,13 @@ +// Previously, in addition to the real cause of the problem as seen below, +// the compiler would tell the user: +// +// ``` +// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or +// predicates +// ``` +// +// With this test, we check that only the relevant error is emitted. + trait Foo {} impl Foo for Bar {} //~ ERROR cannot find type `Bar` in this scope diff --git a/src/test/ui/issues/issue-36836.stderr b/src/test/ui/issues/issue-36836.stderr index bfda9b0bbdd7e..418194fac9923 100644 --- a/src/test/ui/issues/issue-36836.stderr +++ b/src/test/ui/issues/issue-36836.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `Bar` in this scope - --> $DIR/issue-36836.rs:3:17 + --> $DIR/issue-36836.rs:13:17 | LL | impl Foo for Bar {} | ^^^ not found in this scope From bb99fc31d0a8f962662e636938cf96f0f70d3803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Sep 2019 21:08:34 -0700 Subject: [PATCH 416/618] review comment: update error code descr --- src/librustc_typeck/error_codes.rs | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index ae0f17892959d..ebfa6acf23e00 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -212,7 +212,7 @@ match string { E0033: r##" This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a pattern. Every trait defines a type, but because the -size of trait implementors isn't fixed, this type has no compile-time size. +size of trait implementers isn't fixed, this type has no compile-time size. Therefore, all accesses to trait types must be through pointers. If you encounter this error you should try to avoid dereferencing the pointer. @@ -2430,23 +2430,23 @@ This error indicates that the `self` parameter in a method has an invalid "reciever type". Methods take a special first parameter, of which there are three variants: -`self`, `&self`, and `&mut self`. The type `Self` acts as an alias to the -type of the current trait implementor, or "receiver type". Besides the -already mentioned `Self`, `&Self` and `&mut Self` valid receiver types, the -following are also valid, if less common: `self: Box`, -`self: Rc`, `self: Arc`, and `self: Pin

` (where P is one of -the previous types except `Self`). +`self`, `&self`, and `&mut self`. These are syntactic sugar for +`self: Self`, `self: &Self`, and `self: &mut Self` respectively. The type +`Self` acts as an alias to the type of the current trait implementer, or +"receiver type". Besides the already mentioned `Self`, `&Self` and +`&mut Self` valid receiver types, the following are also valid: +`self: Box`, `self: Rc`, `self: Arc`, and `self: Pin

` +(where P is one of the previous types except `Self`). ``` # struct Foo; trait Trait { fn foo(&self); -// ^^^^^ this let's you refer to the type that implements this trait } + impl Trait for Foo { -// ^^^ this is the "receiver type" fn foo(&self) {} -// ^^^^^ this is of type `Foo` +// ^^^^^ this the receiver type `&Foo` } ``` @@ -2458,11 +2458,12 @@ The above is equivalent to: # fn foo(&self); # } impl Trait for Foo { - fn foo(&self: &Foo) {} + fn foo(self: &Foo) {} } ``` -When using an invalid reciver type, like in the following example, +E0307 will be emitted by the compiler when using an invalid reciver type, +like in the following example: ```compile_fail,E0307 # struct Foo; @@ -2471,12 +2472,13 @@ When using an invalid reciver type, like in the following example, # fn foo(&self); # } impl Trait for Struct { - fn foo(&self: &Bar) {} + fn foo(self: &Bar) {} } ``` The nightly feature [Arbintrary self types][AST] extends the accepted -receiver type to also include any type that can dereference to `Self`: +set of receiver types to also include any type that can dereference to +`Self`: ``` #![feature(arbitrary_self_types)] From efe85943b3a5e7b3920db5a5a53183c75fc80d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Sep 2019 22:11:29 -0700 Subject: [PATCH 417/618] account for DUMMY_SP and correct wording --- src/librustc/error_codes.rs | 2 +- src/librustc/traits/object_safety.rs | 8 ++++---- .../coherence-impl-trait-for-trait-object-safe.old.stderr | 2 +- .../coherence-impl-trait-for-trait-object-safe.re.stderr | 2 +- src/test/ui/error-codes/E0038.stderr | 2 +- .../ui/object-safety/object-safety-mentions-Self.stderr | 4 ++-- src/test/ui/resolve/issue-3907-2.stderr | 2 ++ src/test/ui/traits/trait-test-2.stderr | 4 ++-- .../type-parameter-defaults-referencing-Self-ppaux.stderr | 2 +- src/test/ui/wf/wf-object-safe.stderr | 2 +- 10 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 2d09013f675a7..937a9ea6c1bd4 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -39,7 +39,7 @@ Generally, `Self: Sized` is used to indicate that the trait should not be used as a trait object. If the trait comes from your own crate, consider removing this restriction. -### Method references the `Self` type in its arguments or return type +### Method references the `Self` type in its parameters or return type This happens when a trait has a method like the following: diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 50f497e302e6d..5392e9100c6d1 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -20,7 +20,7 @@ use std::borrow::Cow; use std::iter::{self}; use syntax::ast::{self}; use syntax::symbol::InternedString; -use syntax_pos::Span; +use syntax_pos::{Span, DUMMY_SP}; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum ObjectSafetyViolation { @@ -49,7 +49,7 @@ impl ObjectSafetyViolation { ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod, _) => format!("associated function `{}` has no `self` parameter", name).into(), ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf, _) => format!( - "method `{}` references the `Self` type in its arguments or return type", + "method `{}` references the `Self` type in its parameters or return type", name, ).into(), ObjectSafetyViolation::Method( @@ -67,9 +67,9 @@ impl ObjectSafetyViolation { } pub fn span(&self) -> Option { - match self { + match *self { ObjectSafetyViolation::AssocConst(_, span) | - ObjectSafetyViolation::Method(_, _, span) => Some(*span), + ObjectSafetyViolation::Method(_, _, span) if span != DUMMY_SP => Some(span), _ => None, } } diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr index 2626eab3cbf23..18a7cea95bdb9 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6 | LL | trait NotObjectSafe { fn eq(&self, other: Self); } - | -- method `eq` references the `Self` type in its arguments or return type + | -- method `eq` references the `Self` type in its parameters or return type LL | impl NotObjectSafe for dyn NotObjectSafe { } | ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr index 2626eab3cbf23..18a7cea95bdb9 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6 | LL | trait NotObjectSafe { fn eq(&self, other: Self); } - | -- method `eq` references the `Self` type in its arguments or return type + | -- method `eq` references the `Self` type in its parameters or return type LL | impl NotObjectSafe for dyn NotObjectSafe { } | ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr index 93a7681393b29..5c4d6d53c4626 100644 --- a/src/test/ui/error-codes/E0038.stderr +++ b/src/test/ui/error-codes/E0038.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/E0038.rs:5:1 | LL | fn foo(&self) -> Self; - | --- method `foo` references the `Self` type in its arguments or return type + | --- method `foo` references the `Self` type in its parameters or return type ... LL | fn call_foo(x: Box) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.stderr index e2d1e773809bb..971e79cb0210f 100644 --- a/src/test/ui/object-safety/object-safety-mentions-Self.stderr +++ b/src/test/ui/object-safety/object-safety-mentions-Self.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-mentions-Self.rs:17:1 | LL | fn bar(&self, x: &Self); - | --- method `bar` references the `Self` type in its arguments or return type + | --- method `bar` references the `Self` type in its parameters or return type ... LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object @@ -11,7 +11,7 @@ error[E0038]: the trait `Baz` cannot be made into an object --> $DIR/object-safety-mentions-Self.rs:22:1 | LL | fn bar(&self) -> Self; - | --- method `bar` references the `Self` type in its arguments or return type + | --- method `bar` references the `Self` type in its parameters or return type ... LL | fn make_baz(t: &T) -> &dyn Baz { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr index 087d1a5b9d365..63ac11dc8ae01 100644 --- a/src/test/ui/resolve/issue-3907-2.stderr +++ b/src/test/ui/resolve/issue-3907-2.stderr @@ -3,6 +3,8 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object | LL | fn bar(_x: Foo) {} | ^^^^^^^^^^^^^^^ the trait `issue_3907::Foo` cannot be made into an object + | + = note: associated function `bar` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr index 4d2aca0d4094a..83c2c06527493 100644 --- a/src/test/ui/traits/trait-test-2.stderr +++ b/src/test/ui/traits/trait-test-2.stderr @@ -16,7 +16,7 @@ error[E0038]: the trait `bar` cannot be made into an object LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } | --- ---- method `blah` has generic type parameters | | - | method `dup` references the `Self` type in its arguments or return type + | method `dup` references the `Self` type in its parameters or return type ... LL | (box 10 as Box).dup(); | ^^^^^^^^^^^^ the trait `bar` cannot be made into an object @@ -27,7 +27,7 @@ error[E0038]: the trait `bar` cannot be made into an object LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } | --- ---- method `blah` has generic type parameters | | - | method `dup` references the `Self` type in its arguments or return type + | method `dup` references the `Self` type in its parameters or return type ... LL | (box 10 as Box).dup(); | ^^^^^^ the trait `bar` cannot be made into an object diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr index 03df5b8211889..b315fe9df8afd 100644 --- a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr +++ b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr @@ -14,7 +14,7 @@ error[E0038]: the trait `MyAdd` cannot be made into an object --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18 | LL | trait MyAdd { fn add(&self, other: &Rhs) -> Self; } - | --- method `add` references the `Self` type in its arguments or return type + | --- method `add` references the `Self` type in its parameters or return type ... LL | let y = x as dyn MyAdd; | ^^^^^^^^^^^^^^ the trait `MyAdd` cannot be made into an object diff --git a/src/test/ui/wf/wf-object-safe.stderr b/src/test/ui/wf/wf-object-safe.stderr index d11af11f05051..0d8441f87e7e7 100644 --- a/src/test/ui/wf/wf-object-safe.stderr +++ b/src/test/ui/wf/wf-object-safe.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `A` cannot be made into an object --> $DIR/wf-object-safe.rs:9:13 | LL | fn foo(&self, _x: &Self); - | --- method `foo` references the `Self` type in its arguments or return type + | --- method `foo` references the `Self` type in its parameters or return type ... LL | let _x: &dyn A; | ^^^^^^ the trait `A` cannot be made into an object From 05dcd0e7e3ad44a34266cbca3eb6aa755fb0b56d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2019 15:48:14 +1000 Subject: [PATCH 418/618] Remove `LocalInternedString` uses from `librustc_typeck`. --- src/librustc_typeck/check/expr.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index a53fb12367d0e..2a7b26db35bfc 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -19,7 +19,7 @@ use crate::astconv::AstConv as _; use errors::{Applicability, DiagnosticBuilder}; use syntax::ast; -use syntax::symbol::{Symbol, LocalInternedString, kw, sym}; +use syntax::symbol::{Symbol, kw, sym}; use syntax::source_map::Span; use syntax::util::lev_distance::find_best_match_for_name; use rustc::hir; @@ -1198,7 +1198,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => { // prevent all specified fields from being suggested - let skip_fields = skip_fields.iter().map(|ref x| x.ident.as_str()); + let skip_fields = skip_fields.iter().map(|ref x| x.ident.name); if let Some(field_name) = Self::suggest_field_name( variant, &field.ident.as_str(), @@ -1242,11 +1242,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Return an hint about the closest match in field names fn suggest_field_name(variant: &'tcx ty::VariantDef, field: &str, - skip: Vec) + skip: Vec) -> Option { let names = variant.fields.iter().filter_map(|field| { // ignore already set fields and private fields from non-local crates - if skip.iter().any(|x| *x == field.ident.as_str()) || + if skip.iter().any(|&x| x == field.ident.name) || (!variant.def_id.is_local() && field.vis != Visibility::Public) { None From a8975a0752d52741615728394a0a8a867187ae01 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2019 16:02:32 +1000 Subject: [PATCH 419/618] Remove `LocalInternedString` uses from `librustc/lint/`. --- src/librustc/lint/context.rs | 4 ++-- src/librustc/lint/levels.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index affda256322a4..77df93080cd16 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -33,7 +33,7 @@ use crate::util::common::time; use std::default::Default as StdDefault; use syntax::ast; use syntax::edition; -use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}}; +use syntax_pos::{MultiSpan, Span, symbol::Symbol}; use errors::DiagnosticBuilder; use crate::hir; use crate::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; @@ -405,7 +405,7 @@ impl LintStore { pub fn check_lint_name( &self, lint_name: &str, - tool_name: Option, + tool_name: Option, ) -> CheckLintNameResult<'_> { let complete_name = if let Some(tool_name) = tool_name { format!("{}::{}", tool_name, lint_name) diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 139f4343117af..cbc6dbdba7e6c 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -291,7 +291,7 @@ impl<'a> LintLevelsBuilder<'a> { continue; } - Some(tool_ident.as_str()) + Some(tool_ident.name) } else { None }; From 8c74eb77902dc5c4fdf853e9159dd5fadd00601d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2019 17:21:58 +1000 Subject: [PATCH 420/618] Move path parsing earlier. It's a hot enough path that moving it slightly earlier gives a tiny but easy speedup. --- src/libsyntax/parse/parser/expr.rs | 56 ++++++++++++++++-------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 5b9f0f1df6718..e502a08f4b253 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -889,6 +889,36 @@ impl<'a> Parser<'a> { hi = path.span; return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs)); } + if self.token.is_path_start() { + let path = self.parse_path(PathStyle::Expr)?; + + // `!`, as an operator, is prefix, so we know this isn't that + if self.eat(&token::Not) { + // MACRO INVOCATION expression + let (delim, tts) = self.expect_delimited_token_tree()?; + hi = self.prev_span; + ex = ExprKind::Mac(Mac { + path, + tts, + delim, + span: lo.to(hi), + prior_type_ascription: self.last_type_ascription, + }); + } else if self.check(&token::OpenDelim(token::Brace)) { + if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) { + return expr; + } else { + hi = path.span; + ex = ExprKind::Path(None, path); + } + } else { + hi = path.span; + ex = ExprKind::Path(None, path); + } + + let expr = self.mk_expr(lo.to(hi), ex, attrs); + return self.maybe_recover_from_bad_qpath(expr, true); + } if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) { return self.parse_lambda_expr(attrs); } @@ -1007,32 +1037,6 @@ impl<'a> Parser<'a> { let (await_hi, e_kind) = self.parse_incorrect_await_syntax(lo, self.prev_span)?; hi = await_hi; ex = e_kind; - } else if self.token.is_path_start() { - let path = self.parse_path(PathStyle::Expr)?; - - // `!`, as an operator, is prefix, so we know this isn't that - if self.eat(&token::Not) { - // MACRO INVOCATION expression - let (delim, tts) = self.expect_delimited_token_tree()?; - hi = self.prev_span; - ex = ExprKind::Mac(Mac { - path, - tts, - delim, - span: lo.to(hi), - prior_type_ascription: self.last_type_ascription, - }); - } else if self.check(&token::OpenDelim(token::Brace)) { - if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) { - return expr; - } else { - hi = path.span; - ex = ExprKind::Path(None, path); - } - } else { - hi = path.span; - ex = ExprKind::Path(None, path); - } } else { if !self.unclosed_delims.is_empty() && self.check(&token::Semi) { // Don't complain about bare semicolons after unclosed braces From 23c76ff7b912f16f6fdbde167306b08e59353427 Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Tue, 3 Sep 2019 12:17:03 +0200 Subject: [PATCH 421/618] Added warning around code with reference to uninit bytes --- src/libstd/io/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 5060f368229bb..495c0c8d17256 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -371,6 +371,14 @@ where loop { if g.len == g.buf.len() { unsafe { + // FIXME(danielhenrymantilla): #42788 + // + // - This creates a (mut) reference to a slice of + // _uninitialized integers_. + // + // - This having defined behavior is **unstable**: + // it could become UB in the future, + // at which point it would have be changed. g.buf.reserve(reservation_size(r)); let capacity = g.buf.capacity(); g.buf.set_len(capacity); From e85b181638f228b6dd6b0aa10d41552f4de5ea58 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 3 Sep 2019 15:33:30 +0200 Subject: [PATCH 422/618] unused_parens: fix for or-patterns + &(mut x) --- src/librustc_lint/unused.rs | 81 ++++++++-- .../ui/lint/issue-54538-unused-parens-lint.rs | 90 ++++++++--- .../issue-54538-unused-parens-lint.stderr | 149 ++++++++++++++---- 3 files changed, 256 insertions(+), 64 deletions(-) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 90e467713968b..39c0698aeec9f 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -398,18 +398,37 @@ impl UnusedParens { } } - fn check_unused_parens_pat(&self, - cx: &EarlyContext<'_>, - value: &ast::Pat, - msg: &str) { - if let ast::PatKind::Paren(_) = value.node { + fn check_unused_parens_pat( + &self, + cx: &EarlyContext<'_>, + value: &ast::Pat, + avoid_or: bool, + avoid_mut: bool, + ) { + use ast::{PatKind, BindingMode::ByValue, Mutability::Mutable}; + + if let PatKind::Paren(inner) = &value.node { + match inner.node { + // The lint visitor will visit each subpattern of `p`. We do not want to lint + // any range pattern no matter where it occurs in the pattern. For something like + // `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume + // that if there are unnecessary parens they serve a purpose of readability. + PatKind::Range(..) => return, + // Avoid `p0 | .. | pn` if we should. + PatKind::Or(..) if avoid_or => return, + // Avoid `mut x` and `mut x @ p` if we should: + PatKind::Ident(ByValue(Mutable), ..) if avoid_mut => return, + // Otherwise proceed with linting. + _ => {} + } + let pattern_text = if let Ok(snippet) = cx.sess().source_map() .span_to_snippet(value.span) { snippet } else { pprust::pat_to_string(value) }; - Self::remove_outer_parens(cx, value.span, &pattern_text, msg, (false, false)); + Self::remove_outer_parens(cx, value.span, &pattern_text, "pattern", (false, false)); } } @@ -474,6 +493,13 @@ impl EarlyLintPass for UnusedParens { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { use syntax::ast::ExprKind::*; let (value, msg, followed_by_block, left_pos, right_pos) = match e.node { + Let(ref pats, ..) => { + for p in pats { + self.check_unused_parens_pat(cx, p, false, false); + } + return; + } + If(ref cond, ref block, ..) => { let left = e.span.lo() + syntax_pos::BytePos(2); let right = block.span.lo(); @@ -486,7 +512,8 @@ impl EarlyLintPass for UnusedParens { (cond, "`while` condition", true, Some(left), Some(right)) }, - ForLoop(_, ref cond, ref block, ..) => { + ForLoop(ref pat, ref cond, ref block, ..) => { + self.check_unused_parens_pat(cx, pat, false, false); (cond, "`for` head expression", true, None, Some(block.span.lo())) } @@ -531,26 +558,46 @@ impl EarlyLintPass for UnusedParens { } fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) { - use ast::PatKind::{Paren, Range}; - // The lint visitor will visit each subpattern of `p`. We do not want to lint any range - // pattern no matter where it occurs in the pattern. For something like `&(a..=b)`, there - // is a recursive `check_pat` on `a` and `b`, but we will assume that if there are - // unnecessary parens they serve a purpose of readability. - if let Paren(ref pat) = p.node { - match pat.node { - Range(..) => {} - _ => self.check_unused_parens_pat(cx, &p, "pattern") - } + use ast::{PatKind::*, Mutability}; + match &p.node { + // Do not lint on `(..)` as that will result in the other arms being useless. + Paren(_) + // The other cases do not contain sub-patterns. + | Wild | Rest | Lit(..) | Mac(..) | Range(..) | Ident(.., None) | Path(..) => return, + // These are list-like patterns; parens can always be removed. + TupleStruct(_, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { + self.check_unused_parens_pat(cx, p, false, false); + }, + Struct(_, fps, _) => for f in fps { + self.check_unused_parens_pat(cx, &f.pat, false, false); + }, + // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106. + Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false), + // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342. + // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106. + Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Immutable), } } fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { if let ast::StmtKind::Local(ref local) = s.node { + self.check_unused_parens_pat(cx, &local.pat, false, false); + if let Some(ref value) = local.init { self.check_unused_parens_expr(cx, &value, "assigned value", false, None, None); } } } + + fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) { + self.check_unused_parens_pat(cx, ¶m.pat, true, false); + } + + fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { + for p in &arm.pats { + self.check_unused_parens_pat(cx, p, false, false); + } + } } declare_lint! { diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.rs b/src/test/ui/lint/issue-54538-unused-parens-lint.rs index eda9e2cdfaa2f..c442c39fe010e 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.rs +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.rs @@ -1,25 +1,75 @@ -// build-pass (FIXME(62277): could be check-pass?) +#![feature(box_patterns)] + +#![feature(or_patterns)] +//~^ WARN the feature `or_patterns` is incomplete #![allow(ellipsis_inclusive_range_patterns)] #![allow(unreachable_patterns)] #![allow(unused_variables)] -#![warn(unused_parens)] +#![deny(unused_parens)] + +fn lint_on_top_level() { + let (a) = 0; //~ ERROR unnecessary parentheses around pattern + for (a) in 0..1 {} //~ ERROR unnecessary parentheses around pattern + if let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern + while let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern + fn foo((a): u8) {} //~ ERROR unnecessary parentheses around pattern + let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern +} + +// Don't lint in these cases (#64106). +fn or_patterns_no_lint() { + match Box::new(0) { + box (0 | 1) => {} // Should not lint as `box 0 | 1` binds as `(box 0) | 1`. + _ => {} + } + + match 0 { + x @ (0 | 1) => {} // Should not lint as `x @ 0 | 1` binds as `(x @ 0) | 1`. + _ => {} + } + + if let &(0 | 1) = &0 {} // Should also not lint. + if let &mut (0 | 1) = &mut 0 {} // Same. + + fn foo((Ok(a) | Err(a)): Result) {} // Doesn't parse if we remove parens for now. + //~^ ERROR identifier `a` is bound more than once + + let _ = |(Ok(a) | Err(a)): Result| 1; // `|Ok(a) | Err(a)| 1` parses as bit-or. + //~^ ERROR identifier `a` is bound more than once +} + +fn or_patterns_will_lint() { + if let (0 | 1) = 0 {} //~ ERROR unnecessary parentheses around pattern + if let ((0 | 1),) = (0,) {} //~ ERROR unnecessary parentheses around pattern + if let [(0 | 1)] = [0] {} //~ ERROR unnecessary parentheses around pattern + if let 0 | (1 | 2) = 0 {} //~ ERROR unnecessary parentheses around pattern + struct TS(u8); + if let TS((0 | 1)) = TS(0) {} //~ ERROR unnecessary parentheses around pattern + struct NS { f: u8 } + if let NS { f: (0 | 1) } = (NS { f: 0 }) {} //~ ERROR unnecessary parentheses around pattern +} + +// Don't lint on `&(mut x)` because `&mut x` means something else (#55342). +fn deref_mut_binding_no_lint() { + let &(mut x) = &0; +} fn main() { match 1 { - (_) => {} //~ WARNING: unnecessary parentheses around pattern - (y) => {} //~ WARNING: unnecessary parentheses around pattern - (ref r) => {} //~ WARNING: unnecessary parentheses around pattern - (e @ 1...2) => {} //~ WARNING: unnecessary parentheses around outer pattern - (1...2) => {} // Non ambiguous range pattern should not warn + (_) => {} //~ ERROR unnecessary parentheses around pattern + (y) => {} //~ ERROR unnecessary parentheses around pattern + (ref r) => {} //~ ERROR unnecessary parentheses around pattern + (e @ 1...2) => {} //~ ERROR unnecessary parentheses around pattern + (1...2) => {} // Non ambiguous range pattern should not warn e @ (3...4) => {} // Non ambiguous range pattern should not warn } match &1 { - (e @ &(1...2)) => {} //~ WARNING: unnecessary parentheses around outer pattern - &(_) => {} //~ WARNING: unnecessary parentheses around pattern - e @ &(1...2) => {} // Ambiguous range pattern should not warn - &(1...2) => {} // Ambiguous range pattern should not warn + (e @ &(1...2)) => {} //~ ERROR unnecessary parentheses around pattern + &(_) => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1...2) => {} // Ambiguous range pattern should not warn + &(1...2) => {} // Ambiguous range pattern should not warn } match &1 { @@ -28,19 +78,19 @@ fn main() { } match 1 { - (_) => {} //~ WARNING: unnecessary parentheses around pattern - (y) => {} //~ WARNING: unnecessary parentheses around pattern - (ref r) => {} //~ WARNING: unnecessary parentheses around pattern - (e @ 1..=2) => {} //~ WARNING: unnecessary parentheses around outer pattern - (1..=2) => {} // Non ambiguous range pattern should not warn + (_) => {} //~ ERROR unnecessary parentheses around pattern + (y) => {} //~ ERROR unnecessary parentheses around pattern + (ref r) => {} //~ ERROR unnecessary parentheses around pattern + (e @ 1..=2) => {} //~ ERROR unnecessary parentheses around pattern + (1..=2) => {} // Non ambiguous range pattern should not warn e @ (3..=4) => {} // Non ambiguous range pattern should not warn } match &1 { - (e @ &(1..=2)) => {} //~ WARNING: unnecessary parentheses around outer pattern - &(_) => {} //~ WARNING: unnecessary parentheses around pattern - e @ &(1..=2) => {} // Ambiguous range pattern should not warn - &(1..=2) => {} // Ambiguous range pattern should not warn + (e @ &(1..=2)) => {} //~ ERROR unnecessary parentheses around pattern + &(_) => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1..=2) => {} // Ambiguous range pattern should not warn + &(1..=2) => {} // Ambiguous range pattern should not warn } match &1 { diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr index 3b312198952a5..a3e0fb938b3c6 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr @@ -1,78 +1,173 @@ -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:10:9 +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/issue-54538-unused-parens-lint.rs:35:25 | -LL | (_) => {} +LL | fn foo((Ok(a) | Err(a)): Result) {} // Doesn't parse if we remove parens for now. + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/issue-54538-unused-parens-lint.rs:38:27 + | +LL | let _ = |(Ok(a) | Err(a)): Result| 1; // `|Ok(a) | Err(a)| 1` parses as bit-or. + | ^ used in a pattern more than once + +warning: the feature `or_patterns` is incomplete and may cause the compiler to crash + --> $DIR/issue-54538-unused-parens-lint.rs:3:12 + | +LL | #![feature(or_patterns)] + | ^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:12:9 + | +LL | let (a) = 0; | ^^^ help: remove these parentheses | note: lint level defined here - --> $DIR/issue-54538-unused-parens-lint.rs:6:9 + --> $DIR/issue-54538-unused-parens-lint.rs:9:9 | -LL | #![warn(unused_parens)] +LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:11:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:13:9 + | +LL | for (a) in 0..1 {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:14:12 + | +LL | if let (a) = 0 {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:15:15 + | +LL | while let (a) = 0 {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:16:12 + | +LL | fn foo((a): u8) {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:17:14 + | +LL | let _ = |(a): u8| 0; + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:43:12 + | +LL | if let (0 | 1) = 0 {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:44:13 + | +LL | if let ((0 | 1),) = (0,) {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:45:13 + | +LL | if let [(0 | 1)] = [0] {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:46:16 + | +LL | if let 0 | (1 | 2) = 0 {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:48:15 + | +LL | if let TS((0 | 1)) = TS(0) {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:50:20 + | +LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {} + | ^^^^^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:60:9 + | +LL | (_) => {} + | ^^^ help: remove these parentheses + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:61:9 | LL | (y) => {} | ^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:12:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:62:9 | LL | (ref r) => {} | ^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:13:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:63:9 | LL | (e @ 1...2) => {} | ^^^^^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:19:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:69:9 | LL | (e @ &(1...2)) => {} | ^^^^^^^^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:20:10 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:70:10 | LL | &(_) => {} | ^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:31:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:81:9 | LL | (_) => {} | ^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:32:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:82:9 | LL | (y) => {} | ^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:33:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:83:9 | LL | (ref r) => {} | ^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:34:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:84:9 | LL | (e @ 1..=2) => {} | ^^^^^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:40:9 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:90:9 | LL | (e @ &(1..=2)) => {} | ^^^^^^^^^^^^^^ help: remove these parentheses -warning: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:41:10 +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:91:10 | LL | &(_) => {} | ^^^ help: remove these parentheses +error: aborting due to 26 previous errors + +For more information about this error, try `rustc --explain E0416`. From b03d3dc478ba13f405cf9a877a4894de096a1cc1 Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Tue, 3 Sep 2019 15:36:21 +0200 Subject: [PATCH 423/618] Changed comment to better reflect std's exceptional situation --- src/libstd/io/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 495c0c8d17256..0386dbd490d03 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -374,11 +374,11 @@ where // FIXME(danielhenrymantilla): #42788 // // - This creates a (mut) reference to a slice of - // _uninitialized integers_. + // _uninitialized_ integers, which is **undefined behavior** // - // - This having defined behavior is **unstable**: - // it could become UB in the future, - // at which point it would have be changed. + // - Only the standard library gets to soundly "ignore" this, + // based on its privileged knowledge of unstable rustc + // internals; g.buf.reserve(reservation_size(r)); let capacity = g.buf.capacity(); g.buf.set_len(capacity); From 3284734f789ad1a4c71576c20664bfa80e78f539 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 3 Sep 2019 20:22:03 +0900 Subject: [PATCH 424/618] Update Clippy --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index 70e7d075df7b3..aeadf1562c024 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 70e7d075df7b3e11e61fa99b30e1ede26cee6afd +Subproject commit aeadf1562c024d3c5421e61dc6b8d48c2d7902f5 From 0662fcf4f950ec2800f0b1e02254ef2389b55079 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Tue, 3 Sep 2019 14:37:53 +0000 Subject: [PATCH 425/618] make wasi a target-specific dependency --- src/libstd/Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 0d04b7a274037..173bcea0846a0 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -24,7 +24,6 @@ compiler_builtins = { version = "0.1.16" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] } -wasi = { version = "0.7.0", features = ['rustc-dep-of-std', 'alloc'] } [dependencies.backtrace] version = "0.3.35" @@ -57,6 +56,9 @@ dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] } +[target.wasm32-wasi.dependencies] +wasi = { version = "0.7.0", features = ['rustc-dep-of-std', 'alloc'] } + [build-dependencies] cc = "1.0" From 28b518474ed2a5dee812e4f356f71f4c60628421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Sep 2019 08:03:09 -0700 Subject: [PATCH 426/618] review comments: error code text --- src/librustc_typeck/error_codes.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index ebfa6acf23e00..a2b1f16ef3de7 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -2431,26 +2431,28 @@ This error indicates that the `self` parameter in a method has an invalid Methods take a special first parameter, of which there are three variants: `self`, `&self`, and `&mut self`. These are syntactic sugar for -`self: Self`, `self: &Self`, and `self: &mut Self` respectively. The type -`Self` acts as an alias to the type of the current trait implementer, or -"receiver type". Besides the already mentioned `Self`, `&Self` and -`&mut Self` valid receiver types, the following are also valid: -`self: Box`, `self: Rc`, `self: Arc`, and `self: Pin

` -(where P is one of the previous types except `Self`). +`self: Self`, `self: &Self`, and `self: &mut Self` respectively. ``` # struct Foo; trait Trait { fn foo(&self); +// ^^^^^ `self` here is a reference to the receiver object } impl Trait for Foo { fn foo(&self) {} -// ^^^^^ this the receiver type `&Foo` +// ^^^^^ the receiver type is `&Foo` } ``` -The above is equivalent to: +The type `Self` acts as an alias to the type of the current trait +implementer, or "receiver type". Besides the already mentioned `Self`, +`&Self` and `&mut Self` valid receiver types, the following are also valid: +`self: Box`, `self: Rc`, `self: Arc`, and `self: Pin

` +(where P is one of the previous types except `Self`). Note that `Self` can +also be the underlying implementing type, like `Foo` in the following +example: ``` # struct Foo; From 4a79633ad2ff5ce1641405daefc41a13d786dacf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Sep 2019 08:05:54 -0700 Subject: [PATCH 427/618] review comments --- src/librustc/traits/object_safety.rs | 4 +++- src/test/ui/self/arbitrary-self-types-not-object-safe.stderr | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 5392e9100c6d1..f7f459cd27f68 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -60,13 +60,15 @@ impl ObjectSafetyViolation { ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => format!("method `{}` has generic type parameters", name).into(), ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => - format!("method `{}`'s receiver cannot be dispatched on", name).into(), + format!("method `{}`'s `self` parameter cannot be dispatched on", name).into(), ObjectSafetyViolation::AssocConst(name, _) => format!("the trait cannot contain associated consts like `{}`", name).into(), } } pub fn span(&self) -> Option { + // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so + // diagnostics use a `note` instead of a `span_label`. match *self { ObjectSafetyViolation::AssocConst(_, span) | ObjectSafetyViolation::Method(_, _, span) if span != DUMMY_SP => Some(span), diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr index 9fb1500afce47..e6eba377a9578 100644 --- a/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/arbitrary-self-types-not-object-safe.rs:31:32 | LL | fn foo(self: &Rc) -> usize; - | --- method `foo`'s receiver cannot be dispatched on + | --- method `foo`'s `self` parameter cannot be dispatched on ... LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^ the trait `Foo` cannot be made into an object @@ -11,7 +11,7 @@ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/arbitrary-self-types-not-object-safe.rs:31:13 | LL | fn foo(self: &Rc) -> usize; - | --- method `foo`'s receiver cannot be dispatched on + | --- method `foo`'s `self` parameter cannot be dispatched on ... LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object From e16ce8007a129fc3829d5ed9c1fed5cd4fb6c2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Sep 2019 08:07:35 -0700 Subject: [PATCH 428/618] fix error code test --- src/librustc_typeck/error_codes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index a2b1f16ef3de7..093446d28533e 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -2473,7 +2473,7 @@ like in the following example: # trait Trait { # fn foo(&self); # } -impl Trait for Struct { +impl Trait for Foo { fn foo(self: &Bar) {} } ``` From 12adc395c375d4ab14d24624a0ccdd519d5a5978 Mon Sep 17 00:00:00 2001 From: nathanwhit Date: Tue, 3 Sep 2019 11:56:08 -0400 Subject: [PATCH 429/618] Strip remote-test-client output from run stdout The remote-test-client outputs a message of the form "uploaded "/", waiting for result" onto stdout when executing a test, which is then captured in the process result. This needs to be removed when comparing the results of the run-pass test execution. --- src/tools/compiletest/src/runtest.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 7b5e0752b3673..8fb1302936c66 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2951,8 +2951,24 @@ impl<'test> TestCx<'test> { let expected_stderr = self.load_expected_output(stderr_kind); let expected_stdout = self.load_expected_output(stdout_kind); - let normalized_stdout = - self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout); + let normalized_stdout = match output_kind { + TestOutput::Run if self.config.remote_test_client.is_some() => { + // When tests are run using the remote-test-client, the string + // 'uploaded "$TEST_BUILD_DIR/, waiting for result"' + // is printed to stdout by the client and then captured in the ProcRes, + // so it needs to be removed when comparing the run-pass test execution output + lazy_static! { + static ref REMOTE_TEST_RE: Regex = Regex::new( + "^uploaded \"\\$TEST_BUILD_DIR(/[[:alnum:]_\\-]+)+\", waiting for result\n" + ).unwrap(); + } + REMOTE_TEST_RE.replace( + &self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout), + "" + ).to_string() + } + _ => self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout) + }; let stderr = if explicit_format { proc_res.stderr.clone() From 87866714ee1cf3fba6e659f46413e361b9088362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Sep 2019 08:12:28 -0700 Subject: [PATCH 430/618] fix comment and add delay_span_bug --- src/librustc_typeck/impl_wf_check.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 8e69fbd9a79ef..82acbf7c74803 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -12,7 +12,7 @@ use crate::constrained_generic_params as cgp; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::def_id::DefId; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc::ty::query::Providers; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use std::collections::hash_map::Entry::{Occupied, Vacant}; @@ -99,8 +99,13 @@ fn enforce_impl_params_are_constrained( ) { // Every lifetime used in an associated type must be constrained. let impl_self_ty = tcx.type_of(impl_def_id); - if impl_self_ty.sty == ty::Error { - // Don't complain about unconstrained type params when self ty doesn't exist. (#36836) + if impl_self_ty.references_error() { + // Don't complain about unconstrained type params when self ty isn't known due to errors. + // (#36836) + tcx.sess.delay_span_bug(tcx.def_span(impl_def_id), &format( + "potentially unconstrained type parameters weren't evaluated on `{:?}`", + impl_self_ty, + )); return; } let impl_generics = tcx.generics_of(impl_def_id); From c44ffafab902e687ef01d2366a7de7237e25245c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Sep 2019 08:33:06 -0700 Subject: [PATCH 431/618] review comment --- src/librustc_typeck/impl_wf_check.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 82acbf7c74803..bc0f17c3bf0fb 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -102,10 +102,10 @@ fn enforce_impl_params_are_constrained( if impl_self_ty.references_error() { // Don't complain about unconstrained type params when self ty isn't known due to errors. // (#36836) - tcx.sess.delay_span_bug(tcx.def_span(impl_def_id), &format( - "potentially unconstrained type parameters weren't evaluated on `{:?}`", - impl_self_ty, - )); + tcx.sess.delay_span_bug( + tcx.def_span(impl_def_id), + "potentially unconstrained type parameters weren't evaluated", + ); return; } let impl_generics = tcx.generics_of(impl_def_id); From 925a766bc0d34f8808e9902c47bea54b09540774 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Wed, 28 Aug 2019 20:28:42 -0700 Subject: [PATCH 432/618] Add Yaah to clippy toolstain notification list --- src/tools/publish_toolstate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 1411f4c0b05a2..2e2505b7f0246 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -22,7 +22,7 @@ # List of people to ping when the status of a tool or a book changed. MAINTAINERS = { 'miri': '@oli-obk @RalfJung @eddyb', - 'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk @phansch @flip1995', + 'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk @phansch @flip1995 @yaahc', 'rls': '@Xanewok', 'rustfmt': '@topecongiro', 'book': '@carols10cents @steveklabnik', From fa893a322570ea60cc8815b3dddb5311f0cb3b63 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 31 Aug 2019 20:08:06 +0300 Subject: [PATCH 433/618] use TokenStream rather than &[TokenTree] for built-in macros That way, we don't loose the jointness info --- .../src/language-features/plugin.md | 6 +-- src/librustc_metadata/encoder.rs | 2 +- src/libsyntax/diagnostics/plugin.rs | 46 +++++++++---------- src/libsyntax/ext/base.rs | 27 +++++------ src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/print/pprust.rs | 6 +-- src/libsyntax/tokenstream.rs | 2 +- src/libsyntax_ext/asm.rs | 24 ++++------ src/libsyntax_ext/assert.rs | 6 +-- src/libsyntax_ext/cfg.rs | 6 +-- src/libsyntax_ext/compile_error.rs | 4 +- src/libsyntax_ext/concat.rs | 4 +- src/libsyntax_ext/concat_idents.rs | 10 ++-- src/libsyntax_ext/env.rs | 6 +-- src/libsyntax_ext/format.rs | 10 ++-- src/libsyntax_ext/global_asm.rs | 6 +-- src/libsyntax_ext/log_syntax.rs | 4 +- src/libsyntax_ext/source_util.rs | 18 ++++---- src/libsyntax_ext/trace_macros.rs | 27 +++++++---- .../ui-fulldeps/auxiliary/roman-numerals.rs | 6 +-- 20 files changed, 109 insertions(+), 113 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 53e8393ec52e4..68877b48433d5 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -57,12 +57,12 @@ extern crate rustc; extern crate rustc_driver; use syntax::parse::token::{self, Token}; -use syntax::tokenstream::TokenTree; +use syntax::tokenstream::{TokenTree, TokenStream}; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax_pos::Span; use rustc_driver::plugin::Registry; -fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) +fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: TokenStream) -> Box { static NUMERALS: &'static [(&'static str, usize)] = &[ @@ -78,7 +78,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) return DummyResult::any(sp); } - let text = match args[0] { + let text = match args.into_trees().next().unwrap() { TokenTree::Token(Token { kind: token::Ident(s, _), .. }) => s.to_string(), _ => { cx.span_err(sp, "argument should be a single identifier"); diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index db212408d8ebd..f430f01542efe 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1354,7 +1354,7 @@ impl EncodeContext<'tcx> { let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); Entry { kind: EntryKind::MacroDef(self.lazy(MacroDef { - body: pprust::tokens_to_string(macro_def.body.clone()), + body: pprust::tts_to_string(macro_def.body.clone()), legacy: macro_def.legacy, })), visibility: self.lazy(ty::Visibility::Public), diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index e9a55af52e878..5de39c8d14d17 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -6,7 +6,7 @@ use crate::ext::base::{ExtCtxt, MacEager, MacResult}; use crate::parse::token::{self, Token}; use crate::ptr::P; use crate::symbol::kw; -use crate::tokenstream::{TokenTree}; +use crate::tokenstream::{TokenTree, TokenStream}; use smallvec::smallvec; use syntax_pos::Span; @@ -27,12 +27,11 @@ pub type ErrorMap = BTreeMap; pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt<'_>, span: Span, - token_tree: &[TokenTree]) + tts: TokenStream) -> Box { - let code = match token_tree { - [ - TokenTree::Token(Token { kind: token::Ident(code, _), .. }) - ] => code, + assert_eq!(tts.len(), 1); + let code = match tts.into_trees().next() { + Some(TokenTree::Token(Token { kind: token::Ident(code, _), .. })) => code, _ => unreachable!() }; @@ -62,20 +61,21 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt<'_>, pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt<'_>, span: Span, - token_tree: &[TokenTree]) + tts: TokenStream) -> Box { - let (code, description) = match token_tree { - [ - TokenTree::Token(Token { kind: token::Ident(code, _), .. }) - ] => { - (*code, None) - }, - [ - TokenTree::Token(Token { kind: token::Ident(code, _), .. }), - TokenTree::Token(Token { kind: token::Comma, .. }), - TokenTree::Token(Token { kind: token::Literal(token::Lit { symbol, .. }), ..}) - ] => { - (*code, Some(*symbol)) + assert!(tts.len() == 1 || tts.len() == 3); + let mut cursor = tts.into_trees(); + let code = match cursor.next() { + Some(TokenTree::Token(Token { kind: token::Ident(code, _), .. })) => code, + _ => unreachable!() + }; + let description = match (cursor.next(), cursor.next()) { + (None, None) => None, + ( + Some(TokenTree::Token(Token { kind: token::Comma, .. })), + Some(TokenTree::Token(Token { kind: token::Literal(token::Lit { symbol, .. }), ..})) + ) => { + Some(symbol) }, _ => unreachable!() }; @@ -121,12 +121,12 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt<'_>, pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt<'_>, span: Span, - token_tree: &[TokenTree]) + tts: TokenStream) -> Box { - assert_eq!(token_tree.len(), 3); - let ident = match &token_tree[2] { + assert_eq!(tts.len(), 3); + let ident = match tts.into_trees().nth(2) { // DIAGNOSTICS ident. - &TokenTree::Token(Token { kind: token::Ident(name, _), span }) + Some(TokenTree::Token(Token { kind: token::Ident(name, _), span })) => Ident::new(name, span), _ => unreachable!() }; diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 5d68983d7cb66..109ba041016c6 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -10,7 +10,7 @@ use crate::parse::token; use crate::ptr::P; use crate::symbol::{kw, sym, Ident, Symbol}; use crate::{ThinVec, MACRO_ARGUMENTS}; -use crate::tokenstream::{self, TokenStream, TokenTree}; +use crate::tokenstream::{self, TokenStream}; use crate::visit::Visitor; use errors::{DiagnosticBuilder, DiagnosticId}; @@ -235,18 +235,18 @@ pub trait TTMacroExpander { } pub type MacroExpanderFn = - for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, &[tokenstream::TokenTree]) + for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> Box; impl TTMacroExpander for F - where F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, &[tokenstream::TokenTree]) + where F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> Box { fn expand<'cx>( &self, ecx: &'cx mut ExtCtxt<'_>, span: Span, - input: TokenStream, + mut input: TokenStream, ) -> Box { struct AvoidInterpolatedIdents; @@ -268,10 +268,8 @@ impl TTMacroExpander for F mut_visit::noop_visit_mac(mac, self) } } - - let input: Vec<_> = - input.trees().map(|mut tt| { AvoidInterpolatedIdents.visit_tt(&mut tt); tt }).collect(); - (*self)(ecx, span, &input) + AvoidInterpolatedIdents.visit_tts(&mut input); + (*self)(ecx, span, input) } } @@ -677,7 +675,7 @@ impl SyntaxExtension { } pub fn dummy_bang(edition: Edition) -> SyntaxExtension { - fn expander<'cx>(_: &'cx mut ExtCtxt<'_>, span: Span, _: &[TokenTree]) + fn expander<'cx>(_: &'cx mut ExtCtxt<'_>, span: Span, _: TokenStream) -> Box { DummyResult::any(span) } @@ -811,9 +809,8 @@ impl<'a> ExtCtxt<'a> { pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> { expand::MacroExpander::new(self, true) } - - pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree]) -> parser::Parser<'a> { - parse::stream_to_parser(self.parse_sess, tts.iter().cloned().collect(), MACRO_ARGUMENTS) + pub fn new_parser_from_tts(&self, stream: TokenStream) -> parser::Parser<'a> { + parse::stream_to_parser(self.parse_sess, stream, MACRO_ARGUMENTS) } pub fn source_map(&self) -> &'a SourceMap { self.parse_sess.source_map() } pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess } @@ -1019,7 +1016,7 @@ pub fn expr_to_string(cx: &mut ExtCtxt<'_>, expr: P, err_msg: &str) /// done as rarely as possible). pub fn check_zero_tts(cx: &ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, name: &str) { if !tts.is_empty() { cx.span_err(sp, &format!("{} takes no arguments", name)); @@ -1030,7 +1027,7 @@ pub fn check_zero_tts(cx: &ExtCtxt<'_>, /// expect exactly one string literal, or emit an error and return `None`. pub fn get_single_str_from_tts(cx: &mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, name: &str) -> Option { let mut p = cx.new_parser_from_tts(tts); @@ -1053,7 +1050,7 @@ pub fn get_single_str_from_tts(cx: &mut ExtCtxt<'_>, /// parsing error, emit a non-fatal error and return `None`. pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree]) -> Option>> { + tts: TokenStream) -> Option>> { let mut p = cx.new_parser_from_tts(tts); let mut es = Vec::new(); while p.token != token::Eof { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 7b4a516744642..4fd0c367288bf 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -701,7 +701,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { path: &Path, span: Span, ) -> AstFragment { - let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::>()); + let mut parser = self.cx.new_parser_from_tts(toks); match parser.parse_ast_fragment(kind, false) { Ok(fragment) => { parser.ensure_complete_parse(path, kind.name(), span); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index bead941b20d5a..37305055e62a3 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -356,11 +356,7 @@ pub fn tt_to_string(tt: tokenstream::TokenTree) -> String { to_string(|s| s.print_tt(tt, false)) } -pub fn tts_to_string(tts: &[tokenstream::TokenTree]) -> String { - tokens_to_string(tts.iter().cloned().collect()) -} - -pub fn tokens_to_string(tokens: TokenStream) -> String { +pub fn tts_to_string(tokens: TokenStream) -> String { to_string(|s| s.print_tts(tokens, false)) } diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 0d9f3769ce904..480553586197e 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -506,7 +506,7 @@ impl Cursor { impl fmt::Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&pprust::tokens_to_string(self.clone())) + f.write_str(&pprust::tts_to_string(self.clone())) } } diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 28f907441d872..328b307361d9e 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -8,13 +8,12 @@ use errors::DiagnosticBuilder; use syntax::ast; use syntax::ext::base::{self, *}; -use syntax::parse; use syntax::parse::token::{self, Token}; use syntax::ptr::P; use syntax::symbol::{kw, sym, Symbol}; use syntax::ast::AsmDialect; use syntax_pos::Span; -use syntax::tokenstream; +use syntax::tokenstream::{self, TokenStream}; use syntax::{span_err, struct_span_err}; enum State { @@ -43,7 +42,7 @@ const OPTIONS: &[Symbol] = &[sym::volatile, sym::alignstack, sym::intel]; pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree]) + tts: TokenStream) -> Box { let mut inline_asm = match parse_inline_asm(cx, sp, tts) { Ok(Some(inline_asm)) => inline_asm, @@ -71,20 +70,20 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, fn parse_inline_asm<'a>( cx: &mut ExtCtxt<'a>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, ) -> Result, DiagnosticBuilder<'a>> { // Split the tts before the first colon, to avoid `asm!("x": y)` being // parsed as `asm!(z)` with `z = "x": y` which is type ascription. - let first_colon = tts.iter() + let first_colon = tts.trees() .position(|tt| { - match *tt { + match tt { tokenstream::TokenTree::Token(Token { kind: token::Colon, .. }) | tokenstream::TokenTree::Token(Token { kind: token::ModSep, .. }) => true, _ => false, } }) .unwrap_or(tts.len()); - let mut p = cx.new_parser_from_tts(&tts[first_colon..]); + let mut p = cx.new_parser_from_tts(tts.trees().skip(first_colon).collect()); let mut asm = kw::Invalid; let mut asm_str_style = None; let mut outputs = Vec::new(); @@ -110,7 +109,8 @@ fn parse_inline_asm<'a>( )); } // Nested parser, stop before the first colon (see above). - let mut p2 = cx.new_parser_from_tts(&tts[..first_colon]); + let mut p2 = + cx.new_parser_from_tts(tts.trees().take(first_colon).collect()); if p2.token == token::Eof { let mut err = @@ -129,12 +129,8 @@ fn parse_inline_asm<'a>( // This is most likely malformed. if p2.token != token::Eof { let mut extra_tts = p2.parse_all_token_trees()?; - extra_tts.extend(tts[first_colon..].iter().cloned()); - p = parse::stream_to_parser( - cx.parse_sess, - extra_tts.into_iter().collect(), - Some("inline assembly"), - ); + extra_tts.extend(tts.trees().skip(first_colon)); + p = cx.new_parser_from_tts(extra_tts.into_iter().collect()); } asm = s; diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs index 84583d0e5eca7..001996e1db718 100644 --- a/src/libsyntax_ext/assert.rs +++ b/src/libsyntax_ext/assert.rs @@ -13,7 +13,7 @@ use syntax_pos::{Span, DUMMY_SP}; pub fn expand_assert<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[TokenTree], + tts: TokenStream, ) -> Box { let Assert { cond_expr, custom_message } = match parse_assert(cx, sp, tts) { Ok(assert) => assert, @@ -59,9 +59,9 @@ struct Assert { fn parse_assert<'a>( cx: &mut ExtCtxt<'a>, sp: Span, - tts: &[TokenTree] + stream: TokenStream ) -> Result> { - let mut parser = cx.new_parser_from_tts(tts); + let mut parser = cx.new_parser_from_tts(stream); if parser.token == token::Eof { let mut err = cx.struct_span_err(sp, "macro requires a boolean expression as an argument"); diff --git a/src/libsyntax_ext/cfg.rs b/src/libsyntax_ext/cfg.rs index 21cee8ae1cb9c..0342e442df2e9 100644 --- a/src/libsyntax_ext/cfg.rs +++ b/src/libsyntax_ext/cfg.rs @@ -7,14 +7,14 @@ use errors::DiagnosticBuilder; use syntax::ast; use syntax::ext::base::{self, *}; use syntax::attr; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; use syntax::parse::token; use syntax_pos::Span; pub fn expand_cfg( cx: &mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, ) -> Box { let sp = cx.with_legacy_ctxt(sp); @@ -33,7 +33,7 @@ pub fn expand_cfg( fn parse_cfg<'a>( cx: &mut ExtCtxt<'a>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, ) -> Result> { let mut p = cx.new_parser_from_tts(tts); diff --git a/src/libsyntax_ext/compile_error.rs b/src/libsyntax_ext/compile_error.rs index 59d3f2c9c7813..24f3a66d4ae19 100644 --- a/src/libsyntax_ext/compile_error.rs +++ b/src/libsyntax_ext/compile_error.rs @@ -2,11 +2,11 @@ use syntax::ext::base::{self, *}; use syntax_pos::Span; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; pub fn expand_compile_error<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree]) + tts: TokenStream) -> Box { let var = match get_single_str_from_tts(cx, sp, tts, "compile_error!") { None => return DummyResult::any(sp), diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index ffa5154ca0c36..514e95390bca8 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -1,14 +1,14 @@ use syntax::ast; use syntax::ext::base::{self, DummyResult}; use syntax::symbol::Symbol; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; use std::string::String; pub fn expand_syntax_ext( cx: &mut base::ExtCtxt<'_>, sp: syntax_pos::Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, ) -> Box { let es = match base::get_exprs_from_tts(cx, sp, tts) { Some(e) => e, diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index 96677072d1b80..73de25b222586 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -6,11 +6,11 @@ use syntax::parse::token::{self, Token}; use syntax::ptr::P; use syntax_pos::Span; use syntax_pos::symbol::Symbol; -use syntax::tokenstream::TokenTree; +use syntax::tokenstream::{TokenTree, TokenStream}; pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[TokenTree]) + tts: TokenStream) -> Box { if tts.is_empty() { cx.span_err(sp, "concat_idents! takes 1 or more arguments."); @@ -18,9 +18,9 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>, } let mut res_str = String::new(); - for (i, e) in tts.iter().enumerate() { + for (i, e) in tts.into_trees().enumerate() { if i & 1 == 1 { - match *e { + match e { TokenTree::Token(Token { kind: token::Comma, .. }) => {} _ => { cx.span_err(sp, "concat_idents! expecting comma."); @@ -28,7 +28,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>, } } } else { - match *e { + match e { TokenTree::Token(Token { kind: token::Ident(name, _), .. }) => res_str.push_str(&name.as_str()), _ => { diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index 6343d218de829..179b7fe00a97a 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -7,13 +7,13 @@ use syntax::ast::{self, Ident, GenericArg}; use syntax::ext::base::{self, *}; use syntax::symbol::{kw, sym, Symbol}; use syntax_pos::Span; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; use std::env; pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree]) + tts: TokenStream) -> Box { let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") { None => return DummyResult::any(sp), @@ -45,7 +45,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>, pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree]) + tts: TokenStream) -> Box { let mut exprs = match get_exprs_from_tts(cx, sp, tts) { Some(ref exprs) if exprs.is_empty() => { diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 47394c02b4186..ad275f421af49 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -11,7 +11,7 @@ use syntax::ext::base::{self, *}; use syntax::parse::token; use syntax::ptr::P; use syntax::symbol::{Symbol, sym}; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; use syntax_pos::{MultiSpan, Span}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -126,7 +126,7 @@ struct Context<'a, 'b> { fn parse_args<'a>( ecx: &mut ExtCtxt<'a>, sp: Span, - tts: &[tokenstream::TokenTree] + tts: TokenStream, ) -> Result<(P, Vec>, FxHashMap), DiagnosticBuilder<'a>> { let mut args = Vec::>::new(); let mut names = FxHashMap::::default(); @@ -794,7 +794,7 @@ impl<'a, 'b> Context<'a, 'b> { fn expand_format_args_impl<'cx>( ecx: &'cx mut ExtCtxt<'_>, mut sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, nl: bool, ) -> Box { sp = ecx.with_def_site_ctxt(sp); @@ -812,7 +812,7 @@ fn expand_format_args_impl<'cx>( pub fn expand_format_args<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, ) -> Box { expand_format_args_impl(ecx, sp, tts, false) } @@ -820,7 +820,7 @@ pub fn expand_format_args<'cx>( pub fn expand_format_args_nl<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree], + tts: TokenStream, ) -> Box { expand_format_args_impl(ecx, sp, tts, true) } diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs index a8b61593db749..6140f0df58af9 100644 --- a/src/libsyntax_ext/global_asm.rs +++ b/src/libsyntax_ext/global_asm.rs @@ -16,12 +16,12 @@ use syntax::ext::base::{self, *}; use syntax::parse::token; use syntax::ptr::P; use syntax_pos::Span; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; use smallvec::smallvec; pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, - tts: &[tokenstream::TokenTree]) -> Box { + tts: TokenStream) -> Box { match parse_global_asm(cx, sp, tts) { Ok(Some(global_asm)) => { MacEager::items(smallvec![P(ast::Item { @@ -45,7 +45,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, fn parse_global_asm<'a>( cx: &mut ExtCtxt<'a>, sp: Span, - tts: &[tokenstream::TokenTree] + tts: TokenStream ) -> Result, DiagnosticBuilder<'a>> { let mut p = cx.new_parser_from_tts(tts); diff --git a/src/libsyntax_ext/log_syntax.rs b/src/libsyntax_ext/log_syntax.rs index cbdfd08b4977f..d09d72a97be15 100644 --- a/src/libsyntax_ext/log_syntax.rs +++ b/src/libsyntax_ext/log_syntax.rs @@ -1,11 +1,11 @@ use syntax::ext::base; use syntax::print; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; use syntax_pos; pub fn expand_syntax_ext<'cx>(_cx: &'cx mut base::ExtCtxt<'_>, sp: syntax_pos::Span, - tts: &[tokenstream::TokenTree]) + tts: TokenStream) -> Box { println!("{}", print::pprust::tts_to_string(tts)); diff --git a/src/libsyntax_ext/source_util.rs b/src/libsyntax_ext/source_util.rs index e008ed710e4d0..9dc9d66b86f1d 100644 --- a/src/libsyntax_ext/source_util.rs +++ b/src/libsyntax_ext/source_util.rs @@ -4,7 +4,7 @@ use syntax::parse::{self, token, DirectoryOwnership}; use syntax::print::pprust; use syntax::ptr::P; use syntax::symbol::Symbol; -use syntax::tokenstream; +use syntax::tokenstream::TokenStream; use smallvec::SmallVec; use syntax_pos::{self, Pos, Span}; @@ -16,7 +16,7 @@ use rustc_data_structures::sync::Lrc; // a given file into the current one. /// line!(): expands to the current line number -pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { base::check_zero_tts(cx, sp, tts, "line!"); @@ -27,7 +27,7 @@ pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree } /* column!(): expands to the current column number */ -pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { base::check_zero_tts(cx, sp, tts, "column!"); @@ -40,7 +40,7 @@ pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTr /// file!(): expands to the current filename */ /// The source_file (`loc.file`) contains a bunch more information we could spit /// out if we wanted. -pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { base::check_zero_tts(cx, sp, tts, "file!"); @@ -49,13 +49,13 @@ pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name.to_string()))) } -pub fn expand_stringify(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_stringify(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { let s = pprust::tts_to_string(tts); base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))) } -pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { base::check_zero_tts(cx, sp, tts, "module_path!"); let mod_path = &cx.current_expansion.module.mod_path; @@ -67,7 +67,7 @@ pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree] /// include! : parse the given file as an expr /// This is generally a bad idea because it's going to behave /// unhygienically. -pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { let file = match get_single_str_from_tts(cx, sp, tts, "include!") { Some(f) => f, @@ -105,7 +105,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstrea } // include_str! : read the given file, insert it as a literal string expr -pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") { Some(f) => f, @@ -130,7 +130,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::To } } -pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) +pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") { Some(f) => f, diff --git a/src/libsyntax_ext/trace_macros.rs b/src/libsyntax_ext/trace_macros.rs index 0dce8a36f4c7b..d83c24046d9e5 100644 --- a/src/libsyntax_ext/trace_macros.rs +++ b/src/libsyntax_ext/trace_macros.rs @@ -1,20 +1,27 @@ use syntax::ext::base::{self, ExtCtxt}; use syntax::symbol::kw; use syntax_pos::Span; -use syntax::tokenstream::TokenTree; +use syntax::tokenstream::{TokenTree, TokenStream}; pub fn expand_trace_macros(cx: &mut ExtCtxt<'_>, sp: Span, - tt: &[TokenTree]) + tt: TokenStream) -> Box { - match tt { - [TokenTree::Token(token)] if token.is_keyword(kw::True) => { - cx.set_trace_macros(true); - } - [TokenTree::Token(token)] if token.is_keyword(kw::False) => { - cx.set_trace_macros(false); - } - _ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"), + let mut cursor = tt.into_trees(); + let mut err = false; + let value = match &cursor.next() { + Some(TokenTree::Token(token)) if token.is_keyword(kw::True) => true, + Some(TokenTree::Token(token)) if token.is_keyword(kw::False) => false, + _ => { + err = true; + false + }, + }; + err |= cursor.next().is_some(); + if err { + cx.span_err(sp, "trace_macros! accepts only `true` or `false`") + } else { + cx.set_trace_macros(value); } base::DummyResult::any_valid(sp) diff --git a/src/test/ui-fulldeps/auxiliary/roman-numerals.rs b/src/test/ui-fulldeps/auxiliary/roman-numerals.rs index 027025b72b31b..2b57e9289b525 100644 --- a/src/test/ui-fulldeps/auxiliary/roman-numerals.rs +++ b/src/test/ui-fulldeps/auxiliary/roman-numerals.rs @@ -15,12 +15,12 @@ extern crate rustc; extern crate rustc_driver; use syntax::parse::token::{self, Token}; -use syntax::tokenstream::TokenTree; +use syntax::tokenstream::{TokenTree, TokenStream}; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax_pos::Span; use rustc_driver::plugin::Registry; -fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) +fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: TokenStream) -> Box { static NUMERALS: &'static [(&'static str, usize)] = &[ @@ -36,7 +36,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) return DummyResult::any(sp); } - let text = match args[0] { + let text = match args.into_trees().next().unwrap() { TokenTree::Token(Token { kind: token::Ident(s, _), .. }) => s.to_string(), _ => { cx.span_err(sp, "argument should be a single identifier"); From 613649584a9571168c292f82156aee1c173337a8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 3 Sep 2019 17:43:25 +0300 Subject: [PATCH 434/618] use consistent naming for buildin expansion functions --- src/libsyntax_ext/concat.rs | 2 +- src/libsyntax_ext/concat_idents.rs | 8 ++++---- src/libsyntax_ext/lib.rs | 6 +++--- src/libsyntax_ext/log_syntax.rs | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index 514e95390bca8..fc56dff65e4e2 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -5,7 +5,7 @@ use syntax::tokenstream::TokenStream; use std::string::String; -pub fn expand_syntax_ext( +pub fn expand_concat( cx: &mut base::ExtCtxt<'_>, sp: syntax_pos::Span, tts: TokenStream, diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index 73de25b222586..6391b62b58dc9 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -8,10 +8,10 @@ use syntax_pos::Span; use syntax_pos::symbol::Symbol; use syntax::tokenstream::{TokenTree, TokenStream}; -pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: TokenStream) - -> Box { +pub fn expand_concat_idents<'cx>(cx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream) + -> Box { if tts.is_empty() { cx.span_err(sp, "concat_idents! takes 1 or more arguments."); return DummyResult::any(sp); diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 1a6176916623b..26ef80b2b06df 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -67,8 +67,8 @@ pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, e cfg: cfg::expand_cfg, column: source_util::expand_column, compile_error: compile_error::expand_compile_error, - concat_idents: concat_idents::expand_syntax_ext, - concat: concat::expand_syntax_ext, + concat_idents: concat_idents::expand_concat_idents, + concat: concat::expand_concat, env: env::expand_env, file: source_util::expand_file, format_args_nl: format::expand_format_args_nl, @@ -78,7 +78,7 @@ pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, e include_str: source_util::expand_include_str, include: source_util::expand_include, line: source_util::expand_line, - log_syntax: log_syntax::expand_syntax_ext, + log_syntax: log_syntax::expand_log_syntax, module_path: source_util::expand_mod, option_env: env::expand_option_env, stringify: source_util::expand_stringify, diff --git a/src/libsyntax_ext/log_syntax.rs b/src/libsyntax_ext/log_syntax.rs index d09d72a97be15..92130bfaf68e3 100644 --- a/src/libsyntax_ext/log_syntax.rs +++ b/src/libsyntax_ext/log_syntax.rs @@ -3,7 +3,7 @@ use syntax::print; use syntax::tokenstream::TokenStream; use syntax_pos; -pub fn expand_syntax_ext<'cx>(_cx: &'cx mut base::ExtCtxt<'_>, +pub fn expand_log_syntax<'cx>(_cx: &'cx mut base::ExtCtxt<'_>, sp: syntax_pos::Span, tts: TokenStream) -> Box { From 98bd8fd88c3750cfc33b6ae56a0ff1078940bdc6 Mon Sep 17 00:00:00 2001 From: Dario Gonzalez Date: Fri, 26 Apr 2019 13:52:56 -0700 Subject: [PATCH 435/618] Added ability to crosscompile doctests --- src/librustdoc/config.rs | 10 ++++++ src/librustdoc/html/markdown.rs | 34 +++++++++++++++++---- src/librustdoc/html/markdown/tests.rs | 44 ++++++++++++++------------- src/librustdoc/lib.rs | 12 ++++++++ src/librustdoc/test.rs | 42 +++++++++++++++++++++---- 5 files changed, 109 insertions(+), 33 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index d261408fc148a..6d1258fe3a390 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -77,6 +77,10 @@ pub struct Options { /// Optional path to persist the doctest executables to, defaults to a /// temporary directory if not set. pub persist_doctests: Option, + /// Runtool to run doctests with + pub runtool: Option, + /// Arguments to pass to the runtool + pub runtool_args: Vec, // Options that affect the documentation process @@ -140,6 +144,8 @@ impl fmt::Debug for Options { .field("show_coverage", &self.show_coverage) .field("crate_version", &self.crate_version) .field("render_options", &self.render_options) + .field("runtool", &self.runtool) + .field("runtool_args", &self.runtool_args) .finish() } } @@ -466,6 +472,8 @@ impl Options { let codegen_options_strs = matches.opt_strs("C"); let lib_strs = matches.opt_strs("L"); let extern_strs = matches.opt_strs("extern"); + let runtool = matches.opt_str("runtool"); + let runtool_args = matches.opt_strs("runtool-arg"); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); @@ -496,6 +504,8 @@ impl Options { show_coverage, crate_version, persist_doctests, + runtool, + runtool_args, render_options: RenderOptions { output, external_html, diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 74413a7f905d4..45f2efd411fae 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -272,7 +272,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { )) }); - let tooltip = if ignore { + let tooltip = if ignore != Ignore::None { Some(("This example is not tested".to_owned(), "ignore")) } else if compile_fail { Some(("This example deliberately fails to compile".to_owned(), "compile_fail")) @@ -286,7 +286,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { s.push_str(&highlight::render_with_highlighting( &text, Some(&format!("rust-example-rendered{}", - if ignore { " ignore" } + if ignore != Ignore::None { " ignore" } else if compile_fail { " compile_fail" } else if explicit_edition { " edition " } else { "" })), @@ -297,7 +297,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { s.push_str(&highlight::render_with_highlighting( &text, Some(&format!("rust-example-rendered{}", - if ignore { " ignore" } + if ignore != Ignore::None { " ignore" } else if compile_fail { " compile_fail" } else if explicit_edition { " edition " } else { "" })), @@ -607,7 +607,7 @@ pub struct LangString { original: String, pub should_panic: bool, pub no_run: bool, - pub ignore: bool, + pub ignore: Ignore, pub rust: bool, pub test_harness: bool, pub compile_fail: bool, @@ -616,13 +616,20 @@ pub struct LangString { pub edition: Option } +#[derive(Eq, PartialEq, Clone, Debug)] +pub enum Ignore { + All, + None, + Some(Vec), +} + impl LangString { fn all_false() -> LangString { LangString { original: String::new(), should_panic: false, no_run: false, - ignore: false, + ignore: Ignore::None, rust: true, // NB This used to be `notrust = false` test_harness: false, compile_fail: false, @@ -637,6 +644,7 @@ impl LangString { let mut seen_rust_tags = false; let mut seen_other_tags = false; let mut data = LangString::all_false(); + let mut ignores = vec![]; data.original = string.to_owned(); let tokens = string.split(|c: char| @@ -651,7 +659,11 @@ impl LangString { seen_rust_tags = seen_other_tags == false; } "no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; } - "ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; } + "ignore" => { data.ignore = Ignore::All; seen_rust_tags = !seen_other_tags; } + x if x.starts_with("ignore-") => { + ignores.push(x.trim_start_matches("ignore-").to_owned()); + seen_rust_tags = !seen_other_tags; + } "allow_fail" => { data.allow_fail = true; seen_rust_tags = !seen_other_tags; } "rust" => { data.rust = true; seen_rust_tags = true; } "test_harness" => { @@ -680,6 +692,16 @@ impl LangString { } } + match data.ignore { + Ignore::All => {}, + Ignore::None => { + if !ignores.is_empty() { + data.ignore = Ignore::Some(ignores); + } + }, + _ => unreachable!(), + } + data.rust &= !seen_other_tags || seen_rust_tags; data diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index a95c29038d46f..5d6811a29a3eb 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -1,4 +1,4 @@ -use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap}; +use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap, Ignore}; use super::plain_summary_line; use std::cell::RefCell; use syntax::edition::{Edition, DEFAULT_EDITION}; @@ -26,10 +26,10 @@ fn test_unique_id() { #[test] fn test_lang_string_parse() { fn t(s: &str, - should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool, + should_panic: bool, no_run: bool, ignore: Ignore, rust: bool, test_harness: bool, compile_fail: bool, allow_fail: bool, error_codes: Vec, - edition: Option) { - assert_eq!(LangString::parse(s, ErrorCodes::Yes), LangString { + edition: Option) { + assert_eq!(LangString::parse(s, ErrorCodes::Yes, true), LangString { should_panic, no_run, ignore, @@ -42,6 +42,7 @@ fn test_lang_string_parse() { edition, }) } + let ignore_foo = Ignore::Some(vec!("foo".to_string())); fn v() -> Vec { Vec::new() @@ -50,23 +51,24 @@ fn test_lang_string_parse() { // ignore-tidy-linelength // marker | should_panic | no_run | ignore | rust | test_harness // | compile_fail | allow_fail | error_codes | edition - t("", false, false, false, true, false, false, false, v(), None); - t("rust", false, false, false, true, false, false, false, v(), None); - t("sh", false, false, false, false, false, false, false, v(), None); - t("ignore", false, false, true, true, false, false, false, v(), None); - t("should_panic", true, false, false, true, false, false, false, v(), None); - t("no_run", false, true, false, true, false, false, false, v(), None); - t("test_harness", false, false, false, true, true, false, false, v(), None); - t("compile_fail", false, true, false, true, false, true, false, v(), None); - t("allow_fail", false, false, false, true, false, false, true, v(), None); - t("{.no_run .example}", false, true, false, true, false, false, false, v(), None); - t("{.sh .should_panic}", true, false, false, false, false, false, false, v(), None); - t("{.example .rust}", false, false, false, true, false, false, false, v(), None); - t("{.test_harness .rust}", false, false, false, true, true, false, false, v(), None); - t("text, no_run", false, true, false, false, false, false, false, v(), None); - t("text,no_run", false, true, false, false, false, false, false, v(), None); - t("edition2015", false, false, false, true, false, false, false, v(), Some(Edition::Edition2015)); - t("edition2018", false, false, false, true, false, false, false, v(), Some(Edition::Edition2018)); + t("", false, false, Ignore::None, true, false, false, false, v(), None); + t("rust", false, false, Ignore::None, true, false, false, false, v(), None); + t("sh", false, false, Ignore::None, false, false, false, false, v(), None); + t("ignore", false, false, Ignore::All, true, false, false, false, v(), None); + t("ignore-foo", false, false, ignore_foo, true, false, false, false, v(), None); + t("should_panic", true, false, Ignore::None, true, false, false, false, v(), None); + t("no_run", false, true, Ignore::None, true, false, false, false, v(), None); + t("test_harness", false, false, Ignore::None, true, true, false, false, v(), None); + t("compile_fail", false, true, Ignore::None, true, false, true, false, v(), None); + t("allow_fail", false, false, Ignore::None, true, false, false, true, v(), None); + t("{.no_run .example}", false, true, Ignore::None, true, false, false, false, v(), None); + t("{.sh .should_panic}", true, false, Ignore::None, false, false, false, false, v(), None); + t("{.example .rust}", false, false, Ignore::None, true, false, false, false, v(), None); + t("{.test_harness .rust}", false, false, Ignore::None, true, true, false, false, v(), None); + t("text, no_run", false, true, Ignore::None, false, false, false, false, v(), None); + t("text,no_run", false, true, Ignore::None, false, false, false, false, v(), None); + t("edition2015", false, false, Ignore::None, true, false, false, false, v(), Some(Edition::Edition2015)); + t("edition2018", false, false, Ignore::None, true, false, false, false, v(), Some(Edition::Edition2018)); } #[test] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index dfa0db0d23b74..c5ac2440f6791 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -355,6 +355,18 @@ fn opts() -> Vec { "show-coverage", "calculate percentage of public items with documentation") }), + unstable("runtool", |o| { + o.optopt("", + "runtool", + "", + "The tool to run tests with when building for a different target than host") + }), + unstable("runtool-arg", |o| { + o.optmulti("", + "runtool-arg", + "", + "One (of possibly many) arguments to pass to the runtool") + }), ] } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index adcc9930b6c33..2c9e530b9e6b1 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -1,5 +1,6 @@ use rustc_data_structures::sync::Lrc; use rustc_interface::interface; +use rustc_target::spec::TargetTriple; use rustc::hir; use rustc::hir::intravisit; use rustc::session::{self, config, DiagnosticOutput}; @@ -22,7 +23,7 @@ use testing; use crate::clean::Attributes; use crate::config::Options; -use crate::html::markdown::{self, ErrorCodes, LangString}; +use crate::html::markdown::{self, ErrorCodes, LangString, Ignore}; #[derive(Clone, Default)] pub struct TestOptions { @@ -44,7 +45,7 @@ pub fn run(options: Options) -> i32 { vec![config::CrateType::Dylib] }; - let sessopts = config::Options { + let mut sessopts = config::Options { maybe_sysroot: options.maybe_sysroot.clone(), search_paths: options.libs.clone(), crate_types, @@ -59,7 +60,7 @@ pub fn run(options: Options) -> i32 { edition: options.edition, ..config::Options::default() }; - + options.target.as_ref().map(|t| { sessopts.target_triple = t.clone() }); let config = interface::Config { opts: sessopts, crate_cfg: config::parse_cfgspecs(options.cfgs.clone()), @@ -181,6 +182,9 @@ fn run_test( should_panic: bool, no_run: bool, as_test_harness: bool, + runtool: Option, + runtool_args: Vec, + target: Option, compile_fail: bool, mut error_codes: Vec, opts: &TestOptions, @@ -315,7 +319,15 @@ fn run_test( } // Run the code! - let mut cmd = Command::new(output_file); + let mut cmd; + + if let Some(tool) = runtool { + cmd = Command::new(tool); + cmd.arg(output_file); + cmd.args(runtool_args); + }else{ + cmd = Command::new(output_file); + } match cmd.output() { Err(e) => return Err(TestFailure::ExecutionError(e)), @@ -661,12 +673,27 @@ impl Tester for Collector { let opts = self.opts.clone(); let edition = config.edition.unwrap_or(self.options.edition.clone()); let options = self.options.clone(); + let maybe_sysroot = self.maybe_sysroot.clone(); + let linker = self.linker.clone(); + let edition = config.edition.unwrap_or(self.edition); + let persist_doctests = self.persist_doctests.clone(); + let runtool = self.runtool.clone(); + let runtool_args = self.runtool_args.clone(); + let target = self.target.clone(); + let target_str = target.as_ref().map(|t| t.to_string()); debug!("creating test {}: {}", name, test); self.tests.push(testing::TestDescAndFn { desc: testing::TestDesc { - name: testing::DynTestName(name), - ignore: config.ignore, + name: testing::DynTestName(name.clone()), + ignore: match config.ignore { + Ignore::All => true, + Ignore::None => false, + Ignore::Some(ref ignores) => { + target_str.map_or(false, + |s| ignores.iter().any(|t| s.contains(t))) + }, + }, // compiler failures are test failures should_panic: testing::ShouldPanic::No, allow_fail: config.allow_fail, @@ -681,6 +708,9 @@ impl Tester for Collector { config.should_panic, config.no_run, config.test_harness, + runtool, + runtool_args, + target, config.compile_fail, config.error_codes, &opts, From 3f7640884128c6d2acaa9aee3b582cc372044b6d Mon Sep 17 00:00:00 2001 From: Dario Gonzalez Date: Thu, 6 Jun 2019 16:01:53 -0700 Subject: [PATCH 436/618] added feature gate enable-per-target-ignores updated and augmented tests in html/markdown.rs --- src/librustdoc/config.rs | 7 +++++++ src/librustdoc/html/markdown.rs | 17 +++++++++++------ src/librustdoc/lib.rs | 5 +++++ src/librustdoc/markdown.rs | 2 +- src/librustdoc/passes/mod.rs | 2 +- src/librustdoc/test.rs | 7 +++++-- 6 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 6d1258fe3a390..d8fe8d6c8a362 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -81,6 +81,10 @@ pub struct Options { pub runtool: Option, /// Arguments to pass to the runtool pub runtool_args: Vec, + /// Whether to allow ignoring doctests on a per-target basis + /// For example, using ignore-foo to ignore running the doctest on any target that + /// contains "foo" as a substring + pub enable_per_target_ignores: bool, // Options that affect the documentation process @@ -146,6 +150,7 @@ impl fmt::Debug for Options { .field("render_options", &self.render_options) .field("runtool", &self.runtool) .field("runtool_args", &self.runtool_args) + .field("enable-per-target-ignores", &self.enable_per_target_ignores) .finish() } } @@ -474,6 +479,7 @@ impl Options { let extern_strs = matches.opt_strs("extern"); let runtool = matches.opt_str("runtool"); let runtool_args = matches.opt_strs("runtool-arg"); + let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores"); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); @@ -506,6 +512,7 @@ impl Options { persist_doctests, runtool, runtool_args, + enable_per_target_ignores, render_options: RenderOptions { output, external_html, diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 45f2efd411fae..cdc6d4eda4006 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -199,7 +199,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { let ignore; let edition; if let Some(Event::Start(Tag::CodeBlock(lang))) = event { - let parse_result = LangString::parse(&lang, self.check_error_codes); + let parse_result = LangString::parse(&lang, self.check_error_codes, false); if !parse_result.rust { return Some(Event::Start(Tag::CodeBlock(lang))); } @@ -551,7 +551,8 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { } } -pub fn find_testable_code(doc: &str, tests: &mut T, error_codes: ErrorCodes) { +pub fn find_testable_code(doc: &str, tests: &mut T, error_codes: ErrorCodes, + enable_per_target_ignores: bool) { let mut parser = Parser::new(doc); let mut prev_offset = 0; let mut nb_lines = 0; @@ -564,7 +565,7 @@ pub fn find_testable_code(doc: &str, tests: &mut T, error_codes let block_info = if s.is_empty() { LangString::all_false() } else { - LangString::parse(&*s, error_codes) + LangString::parse(&*s, error_codes, enable_per_target_ignores) }; if !block_info.rust { continue; @@ -639,7 +640,11 @@ impl LangString { } } - fn parse(string: &str, allow_error_code_check: ErrorCodes) -> LangString { + fn parse( + string: &str, + allow_error_code_check: ErrorCodes, + enable_per_target_ignores: bool + ) -> LangString { let allow_error_code_check = allow_error_code_check.as_bool(); let mut seen_rust_tags = false; let mut seen_other_tags = false; @@ -660,7 +665,7 @@ impl LangString { } "no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; } "ignore" => { data.ignore = Ignore::All; seen_rust_tags = !seen_other_tags; } - x if x.starts_with("ignore-") => { + x if enable_per_target_ignores && x.starts_with("ignore-") => { ignores.push(x.trim_start_matches("ignore-").to_owned()); seen_rust_tags = !seen_other_tags; } @@ -941,7 +946,7 @@ crate fn rust_code_blocks(md: &str) -> Vec { let lang_string = if syntax.is_empty() { LangString::all_false() } else { - LangString::parse(&*syntax, ErrorCodes::Yes) + LangString::parse(&*syntax, ErrorCodes::Yes, false) }; if lang_string.rust { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index c5ac2440f6791..8f6067da08335 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -355,6 +355,11 @@ fn opts() -> Vec { "show-coverage", "calculate percentage of public items with documentation") }), + unstable("enable-per-target-ignores", |o| { + o.optflag("", + "enable-per-target-ignores", + "parse ignore-foo for ignoring doctests on a per-target basis") + }), unstable("runtool", |o| { o.optopt("", "runtool", diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index a30fc05f36acd..67faec6bd3d0c 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -147,7 +147,7 @@ pub fn test(mut options: Options, diag: &errors::Handler) -> i32 { collector.set_position(DUMMY_SP); let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); - find_testable_code(&input_str, &mut collector, codes); + find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores); options.test_args.insert(0, "rustdoctest".to_string()); testing::test_main(&options.test_args, collector.tests, diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 641a6df221446..3bb1d0deca78d 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -336,7 +336,7 @@ pub fn look_for_tests<'tcx>( found_tests: 0, }; - find_testable_code(&dox, &mut tests, ErrorCodes::No); + find_testable_code(&dox, &mut tests, ErrorCodes::No, false); if check_missing_code == true && tests.found_tests == 0 { let sp = span_of_attrs(&item.attrs).substitute_dummy(item.source.span()); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 2c9e530b9e6b1..a30ac1a512893 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -325,7 +325,7 @@ fn run_test( cmd = Command::new(tool); cmd.arg(output_file); cmd.args(runtool_args); - }else{ + } else { cmd = Command::new(output_file); } @@ -857,7 +857,10 @@ impl<'a, 'hir> HirCollector<'a, 'hir> { // anything else, this will combine them for us. if let Some(doc) = attrs.collapsed_doc_value() { self.collector.set_position(attrs.span.unwrap_or(DUMMY_SP)); - markdown::find_testable_code(&doc, self.collector, self.codes); + markdown::find_testable_code(&doc, + self.collector, + self.codes, + self.collector.enable_per_target_ignores); } nested(self); From 657e24c56b11a45ee1cc019eb0763838f4437475 Mon Sep 17 00:00:00 2001 From: Dario Gonzalez Date: Tue, 11 Jun 2019 11:06:34 -0700 Subject: [PATCH 437/618] changed target from option to plain target, populated with host triple at argument parsing time if no --target arguments --- src/librustdoc/config.rs | 8 +++++--- src/librustdoc/core.rs | 3 +-- src/librustdoc/test.rs | 8 +++----- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index d8fe8d6c8a362..995a340143f78 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -9,7 +9,7 @@ use rustc::session; use rustc::session::config::{CrateType, parse_crate_types_from_list}; use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs}; use rustc::session::config::{nightly_options, build_codegen_options, build_debugging_options, - get_cmd_lint_options, ExternEntry}; + get_cmd_lint_options, host_triple, ExternEntry}; use rustc::session::search_paths::SearchPath; use rustc_driver; use rustc_target::spec::TargetTriple; @@ -54,7 +54,7 @@ pub struct Options { /// Debugging (`-Z`) options to pass to the compiler. pub debugging_options: DebuggingOptions, /// The target used to compile the crate against. - pub target: Option, + pub target: TargetTriple, /// Edition used when reading the crate. Defaults to "2015". Also used by default when /// compiling doctests from the crate. pub edition: Edition, @@ -425,7 +425,9 @@ impl Options { } } - let target = matches.opt_str("target").map(|target| { + let target = matches.opt_str("target").map_or( + TargetTriple::from_triple(host_triple()), + |target| { if target.ends_with(".json") { TargetTriple::TargetPath(PathBuf::from(target)) } else { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 9cfcad4271966..66a32c73e0f16 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -13,7 +13,6 @@ use rustc_interface::interface; use rustc_driver::abort_on_err; use rustc_resolve as resolve; use rustc_metadata::cstore::CStore; -use rustc_target::spec::TargetTriple; use syntax::source_map; use syntax::attr; @@ -313,7 +312,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt lint_cap: Some(lint_cap.unwrap_or_else(|| lint::Forbid)), cg: codegen_options, externs, - target_triple: target.unwrap_or(host_triple), + target_triple: target, // Ensure that rustdoc works even if rustc is feature-staged unstable_features: UnstableFeatures::Allow, actually_rustdoc: true, diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index a30ac1a512893..daec977810682 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -60,7 +60,6 @@ pub fn run(options: Options) -> i32 { edition: options.edition, ..config::Options::default() }; - options.target.as_ref().map(|t| { sessopts.target_triple = t.clone() }); let config = interface::Config { opts: sessopts, crate_cfg: config::parse_cfgspecs(options.cfgs.clone()), @@ -184,7 +183,7 @@ fn run_test( as_test_harness: bool, runtool: Option, runtool_args: Vec, - target: Option, + target: TargetTriple, compile_fail: bool, mut error_codes: Vec, opts: &TestOptions, @@ -680,7 +679,7 @@ impl Tester for Collector { let runtool = self.runtool.clone(); let runtool_args = self.runtool_args.clone(); let target = self.target.clone(); - let target_str = target.as_ref().map(|t| t.to_string()); + let target_str = target.to_string(); debug!("creating test {}: {}", name, test); self.tests.push(testing::TestDescAndFn { @@ -690,8 +689,7 @@ impl Tester for Collector { Ignore::All => true, Ignore::None => false, Ignore::Some(ref ignores) => { - target_str.map_or(false, - |s| ignores.iter().any(|t| s.contains(t))) + ignores.iter().any(|s| target_str.contains(s)) }, }, // compiler failures are test failures From 14110ebd936747eff905ec4e444a02a4a74f6e11 Mon Sep 17 00:00:00 2001 From: Dario Gonzalez Date: Wed, 12 Jun 2019 10:49:41 -0700 Subject: [PATCH 438/618] added rustdoc book documentation, improved behavior when unstable flag not present --- src/doc/rustdoc/src/unstable-features.md | 50 ++++++++++++++++++++++++ src/librustdoc/html/markdown.rs | 14 ++----- src/librustdoc/test.rs | 2 + 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 993fc8412836e..49d05b5038df7 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -471,3 +471,53 @@ Some methodology notes about what rustdoc counts in this metric: Public items that are not documented can be seen with the built-in `missing_docs` lint. Private items that are not documented can be seen with Clippy's `missing_docs_in_private_items` lint. + +### `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --enable-per-target-ignores +``` + +This flag allows you to tag doctests with compiltest style `ignore-foo` filters that prevent +rustdoc from running that test if the target triple string contains foo. For example: + +```rust +///```ignore-foo,ignore-bar +///assert!(2 == 2); +///``` +struct Foo; +``` + +This will not be run when the build target is `super-awesome-foo` or `less-bar-awesome`. +If the flag is not enabled, then rustdoc will consume the filter, but do nothing with it, and +the above example will be run for all targets. +If you want to preserve backwards compatibility for older versions of rustdoc, you can use + +```rust +///```ignore,ignore-foo +///assert!(2 == 2); +///``` +struct Foo; +``` + +In older versions, this will be ignored on all targets, but on newer versions `ignore-gnu` will +override `ignore`. + +### `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it + +Using thses options looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --runtool runner --runtool-arg --do-thing --runtool-arg --do-other-thing +``` + +These options can be used to run the doctest under a program, and also pass arguments to +that program. For example, if you want to run your doctests under valgrind you might run + +```bash +$ rustdoc src/lib.rs -Z unstable-options --runtool valgrind +``` + +Another use case would be to run a test inside an emulator, or through a Virtual Machine. diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index cdc6d4eda4006..05e6c77256e7b 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -665,7 +665,7 @@ impl LangString { } "no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; } "ignore" => { data.ignore = Ignore::All; seen_rust_tags = !seen_other_tags; } - x if enable_per_target_ignores && x.starts_with("ignore-") => { + x if x.starts_with("ignore-") => if enable_per_target_ignores { ignores.push(x.trim_start_matches("ignore-").to_owned()); seen_rust_tags = !seen_other_tags; } @@ -696,15 +696,9 @@ impl LangString { _ => { seen_other_tags = true } } } - - match data.ignore { - Ignore::All => {}, - Ignore::None => { - if !ignores.is_empty() { - data.ignore = Ignore::Some(ignores); - } - }, - _ => unreachable!(), + // ignore-foo overrides ignore + if !ignores.is_empty() { + data.ignore = Ignore::Some(ignores); } data.rust &= !seen_other_tags || seen_rust_tags; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index daec977810682..840eeda9ad7ca 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -58,8 +58,10 @@ pub fn run(options: Options) -> i32 { ..config::basic_debugging_options() }, edition: options.edition, + target_triple: options.target.clone(), ..config::Options::default() }; + let config = interface::Config { opts: sessopts, crate_cfg: config::parse_cfgspecs(options.cfgs.clone()), From 20b9ea88c7360bfbcf76021db568463deb158bc1 Mon Sep 17 00:00:00 2001 From: Baoshan Pang Date: Tue, 3 Sep 2019 19:01:14 -0700 Subject: [PATCH 439/618] change RUST_TEST_DYLINK to RUST_VXWORKS_TEST_DYLINK --- src/tools/compiletest/src/runtest.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 0bc77c6c502dc..7b68896df7e66 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1727,7 +1727,7 @@ impl<'test> TestCx<'test> { fn is_vxworks_pure_static(&self) -> bool { if self.config.target.contains("vxworks") { - match env::var("RUST_TEST_DYLINK") { + match env::var("RUST_VXWORKS_TEST_DYLINK") { Ok(s) => s != "1", _ => true } @@ -1738,7 +1738,7 @@ impl<'test> TestCx<'test> { fn is_vxworks_pure_dynamic(&self) -> bool { if self.config.target.contains("vxworks") { - match env::var("RUST_TEST_DYLINK") { + match env::var("RUST_VXWORKS_TEST_DYLINK") { Ok(s) => s == "1", _ => false } From 0ad111f8bb9bf534c9d2a9ba46d6850907c757e3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2019 16:06:42 +1000 Subject: [PATCH 440/618] Remove `LocalInternedString` uses from `librustc/ty/`. This is not a compelling change in isolation, but it is a necessary step. --- src/librustc/ty/mod.rs | 6 +----- src/librustc_codegen_llvm/callee.rs | 2 +- src/librustc_codegen_llvm/consts.rs | 2 +- src/librustc_codegen_llvm/debuginfo/metadata.rs | 2 +- src/librustc_codegen_llvm/debuginfo/mod.rs | 2 +- src/librustc_codegen_ssa/back/symbol_export.rs | 2 +- src/librustc_codegen_ssa/mono_item.rs | 2 +- src/librustc_codegen_utils/symbol_names_test.rs | 2 +- src/librustc_mir/monomorphize/partitioning.rs | 2 +- 9 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 56505c04f0f0c..2da50f37409ae 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -46,7 +46,7 @@ use std::ops::Range; use syntax::ast::{self, Name, Ident, NodeId}; use syntax::attr; use syntax::ext::hygiene::ExpnId; -use syntax::symbol::{kw, sym, Symbol, LocalInternedString, InternedString}; +use syntax::symbol::{kw, sym, Symbol, InternedString}; use syntax_pos::Span; use smallvec; @@ -3386,10 +3386,6 @@ impl SymbolName { name: InternedString::intern(name) } } - - pub fn as_str(&self) -> LocalInternedString { - self.name.as_str() - } } impl fmt::Display for SymbolName { diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 2c0a6f631b739..35d5107842d5b 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -37,7 +37,7 @@ pub fn get_fn( return llfn; } - let sym = tcx.symbol_name(instance).as_str(); + let sym = tcx.symbol_name(instance).name.as_str(); debug!("get_fn({:?}: {:?}) => {}", instance, sig, sym); // Create a fn pointer with the substituted signature. diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 0077df3cf5eea..d2362a3da6fa8 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -203,7 +203,7 @@ impl CodegenCx<'ll, 'tcx> { def_id); let ty = instance.ty(self.tcx); - let sym = self.tcx.symbol_name(instance).as_str(); + let sym = self.tcx.symbol_name(instance).name.as_str(); debug!("get_static: sym={} instance={:?}", sym, instance); diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 928532a1f4760..d0b607bd88ee4 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -2251,7 +2251,7 @@ pub fn create_global_var_metadata( None } else { let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)); - Some(SmallCStr::new(&linkage_name.as_str())) + Some(SmallCStr::new(&linkage_name.name.as_str())) }; let global_align = cx.align_of(variable_type); diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 548ea0b1036e0..cad2bcdc05fc9 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -290,7 +290,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let scope_line = span_start(self, span).line; let function_name = CString::new(name).unwrap(); - let linkage_name = SmallCStr::new(&linkage_name.as_str()); + let linkage_name = SmallCStr::new(&linkage_name.name.as_str()); let mut flags = DIFlags::FlagPrototyped; diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index 2d9220f897cff..7e700e6819426 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -121,7 +121,7 @@ fn reachable_non_generics_provider( }) .map(|def_id| { let export_level = if special_runtime_crate { - let name = tcx.symbol_name(Instance::mono(tcx, def_id)).as_str(); + let name = tcx.symbol_name(Instance::mono(tcx, def_id)).name.as_str(); // We can probably do better here by just ensuring that // it has hidden visibility rather than public // visibility, as this is primarily here to ensure it's diff --git a/src/librustc_codegen_ssa/mono_item.rs b/src/librustc_codegen_ssa/mono_item.rs index 4446f1a3a5ce2..5801963c101ef 100644 --- a/src/librustc_codegen_ssa/mono_item.rs +++ b/src/librustc_codegen_ssa/mono_item.rs @@ -58,7 +58,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { self.to_raw_string(), cx.codegen_unit().name()); - let symbol_name = self.symbol_name(cx.tcx()).as_str(); + let symbol_name = self.symbol_name(cx.tcx()).name.as_str(); debug!("symbol {}", &symbol_name); diff --git a/src/librustc_codegen_utils/symbol_names_test.rs b/src/librustc_codegen_utils/symbol_names_test.rs index f562744dbe753..51269be4e9f40 100644 --- a/src/librustc_codegen_utils/symbol_names_test.rs +++ b/src/librustc_codegen_utils/symbol_names_test.rs @@ -40,7 +40,7 @@ impl SymbolNamesTest<'tcx> { let instance = Instance::mono(tcx, def_id); let mangled = self.tcx.symbol_name(instance); tcx.sess.span_err(attr.span, &format!("symbol-name({})", mangled)); - if let Ok(demangling) = rustc_demangle::try_demangle(&mangled.as_str()) { + if let Ok(demangling) = rustc_demangle::try_demangle(&mangled.name.as_str()) { tcx.sess.span_err(attr.span, &format!("demangling({})", demangling)); tcx.sess.span_err(attr.span, &format!("demangling-alt({:#})", demangling)); } diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index ad9db4e0aa8d8..c193911247e2b 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -777,7 +777,7 @@ where debug!("CodegenUnit {}:", cgu.name()); for (mono_item, linkage) in cgu.items() { - let symbol_name = mono_item.symbol_name(tcx).as_str(); + let symbol_name = mono_item.symbol_name(tcx).name.as_str(); let symbol_hash_start = symbol_name.rfind('h'); let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..]) .unwrap_or(""); From b50db34e4dd1321b4f075eaa6bc88fc8f95e17fc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2019 16:11:18 +1000 Subject: [PATCH 441/618] Remove `LocalInternedString` uses from `librustc_codegen_llvm/consts.rs`. --- src/librustc_codegen_llvm/consts.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index d2362a3da6fa8..24741542d432c 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -11,12 +11,11 @@ use rustc::mir::interpret::{ConstValue, Allocation, read_target_uint, Pointer, ErrorHandled, GlobalId}; use rustc::mir::mono::MonoItem; use rustc::hir::Node; -use syntax_pos::Span; use rustc_target::abi::HasDataLayout; -use syntax::symbol::sym; -use syntax_pos::symbol::LocalInternedString; use rustc::ty::{self, Ty, Instance}; use rustc_codegen_ssa::traits::*; +use syntax::symbol::{Symbol, sym}; +use syntax_pos::Span; use rustc::ty::layout::{self, Size, Align, LayoutOf}; @@ -104,10 +103,11 @@ fn check_and_apply_linkage( cx: &CodegenCx<'ll, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, - sym: LocalInternedString, + sym: Symbol, span: Span ) -> &'ll Value { let llty = cx.layout_of(ty).llvm_type(cx); + let sym = sym.as_str(); if let Some(linkage) = attrs.linkage { debug!("get_static: sym={} linkage={:?}", sym, linkage); @@ -203,7 +203,7 @@ impl CodegenCx<'ll, 'tcx> { def_id); let ty = instance.ty(self.tcx); - let sym = self.tcx.symbol_name(instance).name.as_str(); + let sym = self.tcx.symbol_name(instance).name.as_symbol(); debug!("get_static: sym={} instance={:?}", sym, instance); @@ -214,11 +214,12 @@ impl CodegenCx<'ll, 'tcx> { Node::Item(&hir::Item { ref attrs, span, node: hir::ItemKind::Static(..), .. }) => { - if self.get_declared_value(&sym[..]).is_some() { + let sym_str = sym.as_str(); + if self.get_declared_value(&sym_str).is_some() { span_bug!(span, "Conflicting symbol names for static?"); } - let g = self.define_global(&sym[..], llty).unwrap(); + let g = self.define_global(&sym_str, llty).unwrap(); if !self.tcx.is_reachable_non_generic(def_id) { unsafe { From d78b33a807445165307a645309c0283cb8ff182e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2019 16:23:21 +1000 Subject: [PATCH 442/618] Remove `LocalInternedString` uses from `librustc_codegen_llvm`. --- src/librustc_codegen_llvm/builder.rs | 6 +++--- src/librustc_codegen_llvm/common.rs | 13 +++++++------ src/librustc_codegen_llvm/context.rs | 4 ++-- src/librustc_codegen_ssa/mir/block.rs | 11 +++++------ src/librustc_codegen_ssa/traits/statics.rs | 6 +++--- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 894e5c2fd3d93..fc23ef1d47e5b 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -5,7 +5,6 @@ use crate::context::CodegenCx; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; -use syntax::symbol::LocalInternedString; use rustc_codegen_ssa::common::{IntPredicate, TypeKind, RealPredicate}; use rustc_codegen_ssa::MemFlags; use libc::{c_uint, c_char}; @@ -24,6 +23,7 @@ use std::ffi::CStr; use std::ops::{Deref, Range}; use std::ptr; use std::iter::TrustedLen; +use syntax::symbol::Symbol; // All Builders must have an llfn associated with them #[must_use] @@ -1082,8 +1082,8 @@ impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> { fn static_panic_msg( &mut self, - msg: Option, - filename: LocalInternedString, + msg: Option, + filename: Symbol, line: Self::Value, col: Self::Value, kind: &str, diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index 19f18088579b3..c337e35460e18 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -17,7 +17,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef; use libc::{c_uint, c_char}; -use syntax::symbol::LocalInternedString; +use syntax::symbol::Symbol; use syntax::ast::Mutability; pub use crate::context::CodegenCx; @@ -122,7 +122,7 @@ impl CodegenCx<'ll, 'tcx> { fn const_cstr( &self, - s: LocalInternedString, + s: Symbol, null_terminated: bool, ) -> &'ll Value { unsafe { @@ -130,9 +130,10 @@ impl CodegenCx<'ll, 'tcx> { return llval; } + let s_str = s.as_str(); let sc = llvm::LLVMConstStringInContext(self.llcx, - s.as_ptr() as *const c_char, - s.len() as c_uint, + s_str.as_ptr() as *const c_char, + s_str.len() as c_uint, !null_terminated as Bool); let sym = self.generate_local_symbol_name("str"); let g = self.define_global(&sym[..], self.val_ty(sc)).unwrap_or_else(||{ @@ -147,8 +148,8 @@ impl CodegenCx<'ll, 'tcx> { } } - pub fn const_str_slice(&self, s: LocalInternedString) -> &'ll Value { - let len = s.len(); + pub fn const_str_slice(&self, s: Symbol) -> &'ll Value { + let len = s.as_str().len(); let cs = consts::ptrcast(self.const_cstr(s, false), self.type_ptr_to(self.layout_of(self.tcx.mk_str()).llvm_type(self))); self.const_fat_ptr(cs, self.const_usize(len as u64)) diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index a2aaaddf0931c..58ce97039099e 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -29,7 +29,7 @@ use std::cell::{Cell, RefCell}; use std::iter; use std::str; use std::sync::Arc; -use syntax::symbol::LocalInternedString; +use syntax::symbol::Symbol; use syntax::source_map::{DUMMY_SP, Span}; use crate::abi::Abi; @@ -52,7 +52,7 @@ pub struct CodegenCx<'ll, 'tcx> { pub vtables: RefCell, Option>), &'ll Value>>, /// Cache of constant strings, - pub const_cstr_cache: RefCell>, + pub const_cstr_cache: RefCell>, /// Reverse-direction for const ptrs cast from globals. /// Key is a Value holding a *T, diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index d2a7571fde1e2..134c321456b6c 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -14,7 +14,7 @@ use crate::traits::*; use std::borrow::Cow; -use syntax::symbol::LocalInternedString; +use syntax::symbol::Symbol; use syntax_pos::Pos; use super::{FunctionCx, LocalRef}; @@ -397,7 +397,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Get the location information. let loc = bx.sess().source_map().lookup_char_pos(span.lo()); - let filename = LocalInternedString::intern(&loc.file.name.to_string()); + let filename = Symbol::intern(&loc.file.name.to_string()); let line = bx.const_u32(loc.line as u32); let col = bx.const_u32(loc.col.to_usize() as u32 + 1); @@ -418,8 +418,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { vec![file_line_col, index, len]) } _ => { - let str = msg.description(); - let msg_str = LocalInternedString::intern(str); + let msg_str = Symbol::intern(msg.description()); let msg_file_line_col = bx.static_panic_msg( Some(msg_str), filename, @@ -531,7 +530,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let layout = bx.layout_of(ty); if layout.abi.is_uninhabited() { let loc = bx.sess().source_map().lookup_char_pos(span.lo()); - let filename = LocalInternedString::intern(&loc.file.name.to_string()); + let filename = Symbol::intern(&loc.file.name.to_string()); let line = bx.const_u32(loc.line as u32); let col = bx.const_u32(loc.col.to_usize() as u32 + 1); @@ -539,7 +538,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { "Attempted to instantiate uninhabited type {}", ty ); - let msg_str = LocalInternedString::intern(&str); + let msg_str = Symbol::intern(&str); let msg_file_line_col = bx.static_panic_msg( Some(msg_str), filename, diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs index 6983311d797dc..73c4c05397917 100644 --- a/src/librustc_codegen_ssa/traits/statics.rs +++ b/src/librustc_codegen_ssa/traits/statics.rs @@ -1,5 +1,5 @@ use super::BackendTypes; -use syntax_pos::symbol::LocalInternedString; +use syntax_pos::symbol::Symbol; use rustc::hir::def_id::DefId; use rustc::ty::layout::Align; @@ -12,8 +12,8 @@ pub trait StaticBuilderMethods: BackendTypes { fn get_static(&mut self, def_id: DefId) -> Self::Value; fn static_panic_msg( &mut self, - msg: Option, - filename: LocalInternedString, + msg: Option, + filename: Symbol, line: Self::Value, col: Self::Value, kind: &str, From bf536dde3b603a0eb4ab9d351010c29799e28676 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2019 17:10:12 +1000 Subject: [PATCH 443/618] Remove `LocalInternedString` uses from `librustc/traits/`. --- src/librustc/traits/on_unimplemented.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 0a42b6b46f2c9..5a988d9509e80 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -9,10 +9,9 @@ use syntax::ast::{MetaItem, NestedMetaItem}; use syntax::attr; use syntax::symbol::{Symbol, kw, sym}; use syntax_pos::Span; -use syntax_pos::symbol::LocalInternedString; #[derive(Clone, Debug)] -pub struct OnUnimplementedFormatString(LocalInternedString); +pub struct OnUnimplementedFormatString(Symbol); #[derive(Debug)] pub struct OnUnimplementedDirective { @@ -89,19 +88,19 @@ impl<'tcx> OnUnimplementedDirective { if item.check_name(sym::message) && message.is_none() { if let Some(message_) = item.value_str() { message = Some(OnUnimplementedFormatString::try_parse( - tcx, trait_def_id, message_.as_str(), span)?); + tcx, trait_def_id, message_, span)?); continue; } } else if item.check_name(sym::label) && label.is_none() { if let Some(label_) = item.value_str() { label = Some(OnUnimplementedFormatString::try_parse( - tcx, trait_def_id, label_.as_str(), span)?); + tcx, trait_def_id, label_, span)?); continue; } } else if item.check_name(sym::note) && note.is_none() { if let Some(note_) = item.value_str() { note = Some(OnUnimplementedFormatString::try_parse( - tcx, trait_def_id, note_.as_str(), span)?); + tcx, trait_def_id, note_, span)?); continue; } } else if item.check_name(sym::on) && is_root && @@ -154,7 +153,7 @@ impl<'tcx> OnUnimplementedDirective { message: None, subcommands: vec![], label: Some(OnUnimplementedFormatString::try_parse( - tcx, trait_def_id, value.as_str(), attr.span)?), + tcx, trait_def_id, value, attr.span)?), note: None, })) } else { @@ -218,7 +217,7 @@ impl<'tcx> OnUnimplementedFormatString { fn try_parse( tcx: TyCtxt<'tcx>, trait_def_id: DefId, - from: LocalInternedString, + from: Symbol, err_sp: Span, ) -> Result { let result = OnUnimplementedFormatString(from); @@ -234,7 +233,8 @@ impl<'tcx> OnUnimplementedFormatString { ) -> Result<(), ErrorReported> { let name = tcx.item_name(trait_def_id); let generics = tcx.generics_of(trait_def_id); - let parser = Parser::new(&self.0, None, vec![], false); + let s = self.0.as_str(); + let parser = Parser::new(&s, None, vec![], false); let mut result = Ok(()); for token in parser { match token { @@ -294,7 +294,8 @@ impl<'tcx> OnUnimplementedFormatString { }).collect::>(); let empty_string = String::new(); - let parser = Parser::new(&self.0, None, vec![], false); + let s = self.0.as_str(); + let parser = Parser::new(&s, None, vec![], false); parser.map(|p| match p { Piece::String(s) => s, From 69ae8d9dfd9927d3db9d1d2676ca429c76007405 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Sep 2019 09:13:56 +1000 Subject: [PATCH 444/618] Remove `LocalInternedString::as_interned_str()`. It's unused. --- src/libsyntax_pos/symbol.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index f44716e013ec8..42db2d21991e4 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1169,12 +1169,6 @@ impl LocalInternedString { } } - pub fn as_interned_str(self) -> InternedString { - InternedString { - symbol: Symbol::intern(self.string) - } - } - #[inline] pub fn get(&self) -> &str { // This returns a valid string since we ensure that `self` outlives the interner From 224daa64bd3d8f34afaacd73ffc972153fe75eda Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Sep 2019 09:30:54 +1000 Subject: [PATCH 445/618] Remove `LocalInternedString::get`. It has a single use, which is easily changed to something better. --- src/librustc_mir/borrow_check/error_reporting.rs | 2 +- src/libsyntax_pos/symbol.rs | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 251d4b727c754..9f25e98052ec4 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -336,7 +336,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let local = &self.body.local_decls[local_index]; match local.name { Some(name) if !local.from_compiler_desugaring() => { - buf.push_str(name.as_str().get()); + buf.push_str(&name.as_str()); Ok(()) } _ => Err(()), diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 42db2d21991e4..6c47ff823b96b 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1168,15 +1168,6 @@ impl LocalInternedString { string: unsafe { std::mem::transmute::<&str, &str>(string) } } } - - #[inline] - pub fn get(&self) -> &str { - // This returns a valid string since we ensure that `self` outlives the interner - // by creating the interner on a thread which outlives threads which can access it. - // This type cannot move to a thread which outlives the interner since it does - // not implement Send. - self.string - } } impl std::convert::AsRef for LocalInternedString From 6025fc843a216a0bff9f25014dc61018266e0aa1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Sep 2019 09:45:57 +1000 Subject: [PATCH 446/618] Remove hashing impls for `LocalInternedString`. --- src/librustc/hir/map/collector.rs | 2 +- src/librustc/ich/impls_syntax.rs | 23 +---------------------- src/libsyntax_pos/symbol.rs | 2 +- 3 files changed, 3 insertions(+), 24 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 773bb8dde0690..b8bd1d73fc28b 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -186,7 +186,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { }); let mut upstream_crates: Vec<_> = cstore.crates_untracked().iter().map(|&cnum| { - let name = cstore.crate_name_untracked(cnum).as_str(); + let name = cstore.crate_name_untracked(cnum).as_interned_str(); let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint(); let hash = cstore.crate_hash_untracked(cnum); (name, disambiguator, hash) diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 05e2c7854b49c..ddfca3a4cfb72 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -9,7 +9,7 @@ use std::mem; use syntax::ast; use syntax::feature_gate; use syntax::parse::token; -use syntax::symbol::{InternedString, LocalInternedString}; +use syntax::symbol::InternedString; use syntax::tokenstream; use syntax_pos::SourceFile; @@ -39,27 +39,6 @@ impl<'a> ToStableHashKey> for InternedString { } } -impl<'a> HashStable> for LocalInternedString { - #[inline] - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - let s: &str = &**self; - s.hash_stable(hcx, hasher); - } -} - -impl<'a> ToStableHashKey> for LocalInternedString { - type KeyType = LocalInternedString; - - #[inline] - fn to_stable_hash_key(&self, - _: &StableHashingContext<'a>) - -> LocalInternedString { - self.clone() - } -} - impl<'a> HashStable> for ast::Name { #[inline] fn hash_stable(&self, diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 6c47ff823b96b..aeea3c920af57 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1152,7 +1152,7 @@ fn with_interner T>(f: F) -> T { // FIXME: ensure that the interner outlives any thread which uses // `LocalInternedString`, by creating a new thread right after constructing the // interner. -#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)] +#[derive(Clone, Copy, Eq, PartialOrd, Ord)] pub struct LocalInternedString { string: &'static str, } From a1cd79ff4e407ccaa1e3f7ac794812251600970c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Sep 2019 09:48:03 +1000 Subject: [PATCH 447/618] Remove `Encodable`/`Decodable` impls for `LocalInternedString`. --- src/libsyntax_pos/symbol.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index aeea3c920af57..32ca1fdff9393 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1231,18 +1231,6 @@ impl fmt::Display for LocalInternedString { } } -impl Decodable for LocalInternedString { - fn decode(d: &mut D) -> Result { - Ok(LocalInternedString::intern(&d.read_str()?)) - } -} - -impl Encodable for LocalInternedString { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(self.string) - } -} - /// An alternative to `Symbol` that is focused on string contents. It has two /// main differences to `Symbol`. /// From 7a1bc79cbd6fbf5577e5216b8e2f3c29cbbacb29 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Sep 2019 09:49:23 +1000 Subject: [PATCH 448/618] Remove `LocalInternedString::intern`. --- src/libsyntax_pos/symbol.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 32ca1fdff9393..5c6031327013c 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1157,19 +1157,6 @@ pub struct LocalInternedString { string: &'static str, } -impl LocalInternedString { - /// Maps a string to its interned representation. - pub fn intern(string: &str) -> Self { - let string = with_interner(|interner| { - let symbol = interner.intern(string); - interner.strings[symbol.0.as_usize()] - }); - LocalInternedString { - string: unsafe { std::mem::transmute::<&str, &str>(string) } - } - } -} - impl std::convert::AsRef for LocalInternedString where str: std::convert::AsRef From cc17b1bc3c877c5cf9a2f5de58535477607972f2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Sep 2019 09:19:27 +1000 Subject: [PATCH 449/618] Add `Symbol::{with,with2}`. And remove the `unsafe` blocks, they're not necessary. Also rewrite `InternedString::{with,with2}` to use the new functions. Finally, add some comments about the speed of the `as_str()`/`as_interned_str()` functions. --- src/libsyntax_pos/symbol.rs | 42 +++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 5c6031327013c..3a4dc1f5a096b 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -818,10 +818,14 @@ impl Ident { with_interner(|interner| interner.is_gensymed(self.name)) } + /// Convert the name to a `LocalInternedString`. This is a slowish + /// operation because it requires locking the symbol interner. pub fn as_str(self) -> LocalInternedString { self.name.as_str() } + /// Convert the name to an `InternedString`. This is a slowish operation + /// because it requires locking the symbol interner. pub fn as_interned_str(self) -> InternedString { self.name.as_interned_str() } @@ -916,6 +920,25 @@ impl Symbol { with_interner(|interner| interner.intern(string)) } + /// Access the symbol's chars. This is a slowish operation because it + /// requires locking the symbol interner. + pub fn with R, R>(self, f: F) -> R { + with_interner(|interner| { + f(interner.get(self)) + }) + } + + /// Access two symbols' chars. This is a slowish operation because it + /// requires locking the symbol interner, but it is faster than calling + /// `with()` twice. + fn with2 R, R>(self, other: Symbol, f: F) -> R { + with_interner(|interner| { + f(interner.get(self), interner.get(other)) + }) + } + + /// Convert to a `LocalInternedString`. This is a slowish operation because + /// it requires locking the symbol interner. pub fn as_str(self) -> LocalInternedString { with_interner(|interner| unsafe { LocalInternedString { @@ -924,6 +947,8 @@ impl Symbol { }) } + /// Convert to an `InternedString`. This is a slowish operation because it + /// requires locking the symbol interner. pub fn as_interned_str(self) -> InternedString { with_interner(|interner| InternedString { symbol: interner.interned(self) @@ -1245,28 +1270,19 @@ impl InternedString { } pub fn with R, R>(self, f: F) -> R { - let str = with_interner(|interner| { - interner.get(self.symbol) as *const str - }); - // This is safe because the interner keeps string alive until it is dropped. - // We can access it because we know the interner is still alive since we use a - // scoped thread local to access it, and it was alive at the beginning of this scope - unsafe { f(&*str) } + self.symbol.with(f) } fn with2 R, R>(self, other: &InternedString, f: F) -> R { - let (self_str, other_str) = with_interner(|interner| { - (interner.get(self.symbol) as *const str, - interner.get(other.symbol) as *const str) - }); - // This is safe for the same reason that `with` is safe. - unsafe { f(&*self_str, &*other_str) } + self.symbol.with2(other.symbol, f) } pub fn as_symbol(self) -> Symbol { self.symbol } + /// Convert to a `LocalInternedString`. This is a slowish operation because it + /// requires locking the symbol interner. pub fn as_str(self) -> LocalInternedString { self.symbol.as_str() } From 2adb246b5c6bfcaae09971c9d54810cb7d58d43e Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Thu, 18 Jul 2019 12:32:06 +0200 Subject: [PATCH 450/618] NLL: New Polonius version --- Cargo.lock | 4 ++-- src/librustc/Cargo.toml | 2 +- src/librustc_mir/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e0d30647809a9..6a5d4ebc1ecdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2324,9 +2324,9 @@ checksum = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" [[package]] name = "polonius-engine" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b8a5defa2aef9ba4999aaa745fbc01c622ecea35964a306adc3e44be4f3b5b" +checksum = "50fa9dbfd0d3d60594da338cfe6f94028433eecae4b11b7e83fd99759227bbfe" dependencies = [ "datafrog", "log", diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 0222a3dde7ab9..a479fabafc014 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -21,7 +21,7 @@ scoped-tls = "1.0" log = { version = "0.4", features = ["release_max_level_info", "std"] } rustc-rayon = "0.2.0" rustc-rayon-core = "0.2.0" -polonius-engine = "0.9.0" +polonius-engine = "0.10.0" rustc_apfloat = { path = "../librustc_apfloat" } rustc_target = { path = "../librustc_target" } rustc_macros = { path = "../librustc_macros" } diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 21008c737289f..1c0b0b63c0bbd 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -15,7 +15,7 @@ either = "1.5.0" dot = { path = "../libgraphviz", package = "graphviz" } log = "0.4" log_settings = "0.1.1" -polonius-engine = "0.9.0" +polonius-engine = "0.10.0" rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } From 996ba932ccd03f2372c5c25eaf5f5025d397a73c Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Thu, 18 Jul 2019 12:38:32 +0200 Subject: [PATCH 451/618] NLL: Adapt to the new Polonius types --- src/librustc_mir/borrow_check/flows.rs | 4 ++-- src/librustc_mir/borrow_check/nll/facts.rs | 16 +++++++++++++--- src/librustc_mir/borrow_check/nll/mod.rs | 4 ++-- .../nll/type_check/liveness/trace.rs | 14 +++++++------- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index bb217a1f965e2..4400e0c8395a2 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -12,7 +12,7 @@ use crate::borrow_check::location::LocationIndex; use polonius_engine::Output; use crate::dataflow::indexes::BorrowIndex; -use crate::dataflow::move_paths::HasMoveData; +use crate::dataflow::move_paths::{HasMoveData, MovePathIndex}; use crate::dataflow::Borrows; use crate::dataflow::EverInitializedPlaces; use crate::dataflow::MaybeUninitializedPlaces; @@ -21,7 +21,7 @@ use either::Either; use std::fmt; use std::rc::Rc; -crate type PoloniusOutput = Output; +crate type PoloniusOutput = Output; // (forced to be `pub` due to its use as an associated type below.) crate struct Flows<'b, 'tcx> { diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index 05451cdfb83d8..10ce3a099cf2b 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -1,5 +1,5 @@ use crate::borrow_check::location::{LocationIndex, LocationTable}; -use crate::dataflow::indexes::BorrowIndex; +use crate::dataflow::indexes::{BorrowIndex, MovePathIndex}; use polonius_engine::AllFacts as PoloniusAllFacts; use polonius_engine::Atom; use rustc::mir::Local; @@ -11,7 +11,7 @@ use std::fs::{self, File}; use std::io::Write; use std::path::Path; -crate type AllFacts = PoloniusAllFacts; +crate type AllFacts = PoloniusAllFacts; crate trait AllFactsExt { /// Returns `true` if there is a need to gather `AllFacts` given the @@ -65,7 +65,11 @@ impl AllFactsExt for AllFacts { var_drop_used, var_uses_region, var_drops_region, - var_initialized_on_exit, + var_maybe_initialized_on_exit, + parent, + var_starts_path, + initialized_at, + moved_out_at, ]) } Ok(()) @@ -84,6 +88,12 @@ impl Atom for LocationIndex { } } +impl Atom for MovePathIndex { + fn index(self) -> usize { + Idx::index(self) + } +} + struct FactWriter<'w> { location_table: &'w LocationTable, dir: &'w Path, diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 11ec154e5b5c1..19a3d0eb03d56 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -4,7 +4,7 @@ use crate::borrow_check::nll::facts::AllFactsExt; use crate::borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints}; use crate::borrow_check::nll::region_infer::values::RegionValueElements; use crate::dataflow::indexes::BorrowIndex; -use crate::dataflow::move_paths::MoveData; +use crate::dataflow::move_paths::{MoveData, MovePathIndex}; use crate::dataflow::FlowAtLocation; use crate::dataflow::MaybeInitializedPlaces; use crate::transform::MirSource; @@ -87,7 +87,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( errors_buffer: &mut Vec, ) -> ( RegionInferenceContext<'tcx>, - Option>>, + Option>>, Option>, ) { let mut all_facts = if AllFacts::enabled(infcx.tcx) { diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 039ed939ada7c..de085fc480a0e 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -134,7 +134,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { // FIXME: this is temporary until we can generate our own initialization if self.cx.typeck.borrowck_context.all_facts.is_some() { - self.add_polonius_var_initialized_on_exit_for(local) + self.add_polonius_var_maybe_initialized_on_exit_for(local) } self.compute_use_live_points_for(local); @@ -161,14 +161,14 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { // // FIXME: this analysis (the initialization tracking) should be // done in Polonius, but isn't yet. - fn add_polonius_var_initialized_on_exit_for(&mut self, local: Local) { + fn add_polonius_var_maybe_initialized_on_exit_for(&mut self, local: Local) { let move_path = self.cx.move_data.rev_lookup.find_local(local); let facts = self.cx.typeck.borrowck_context.all_facts.as_mut().unwrap(); for block in self.cx.body.basic_blocks().indices() { debug!("polonius: generating initialization facts for {:?} in {:?}", local, block); // iterate through the block, applying the effects of each statement - // up to and including location, and populate `var_initialized_on_exit` + // up to and including location, and populate `var_maybe_initialized_on_exit` self.cx.flow_inits.reset_to_entry_of(block); let start_location = Location { block, statement_index: 0 }; self.cx.flow_inits.apply_local_effect(start_location); @@ -181,7 +181,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { // statement has not yet taken effect: if self.cx.flow_inits.has_any_child_of(move_path).is_some() { facts - .var_initialized_on_exit + .var_maybe_initialized_on_exit .push((local, self.cx.location_table.start_index(current_location))); } @@ -190,7 +190,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { if self.cx.flow_inits.has_any_child_of(move_path).is_some() { facts - .var_initialized_on_exit + .var_maybe_initialized_on_exit .push((local, self.cx.location_table.mid_index(current_location))); } } @@ -199,7 +199,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { if self.cx.flow_inits.has_any_child_of(move_path).is_some() { facts - .var_initialized_on_exit + .var_maybe_initialized_on_exit .push((local, self.cx.location_table.start_index(terminator_location))); } @@ -208,7 +208,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { if self.cx.flow_inits.has_any_child_of(move_path).is_some() { facts - .var_initialized_on_exit + .var_maybe_initialized_on_exit .push((local, self.cx.location_table.mid_index(terminator_location))); } } From 6b09477e91ba7cb6b657b87a51ebd0b127e5ca67 Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Fri, 19 Jul 2019 15:38:54 +0200 Subject: [PATCH 452/618] Polonius: emit initialization/move tracking facts - var_starts_path - parent - initialized_at - moved_out_at This also switches to the intended emission of `var_drop_used` fact emission, where that fact is always emitted on a drop-use of a variable, regardless of its initialization status, as Polonius now handles that. --- src/librustc_mir/borrow_check/nll/mod.rs | 60 ++++++++++++++++++- .../nll/type_check/liveness/polonius.rs | 9 ++- .../nll/type_check/liveness/trace.rs | 5 -- src/librustc_mir/dataflow/move_paths/mod.rs | 9 ++- 4 files changed, 74 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 19a3d0eb03d56..9b920eb15599d 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -4,14 +4,14 @@ use crate::borrow_check::nll::facts::AllFactsExt; use crate::borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints}; use crate::borrow_check::nll::region_infer::values::RegionValueElements; use crate::dataflow::indexes::BorrowIndex; -use crate::dataflow::move_paths::{MoveData, MovePathIndex}; +use crate::dataflow::move_paths::{InitLocation, MoveData, MovePathIndex, InitKind}; use crate::dataflow::FlowAtLocation; use crate::dataflow::MaybeInitializedPlaces; use crate::transform::MirSource; use crate::borrow_check::Upvar; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Body, Promoted}; +use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Location, Body, LocalKind, BasicBlock, Promoted}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::Diagnostic; @@ -69,6 +69,61 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( universal_regions } + +// This function populates an AllFacts instance with base facts related to +// MovePaths and needed for the move analysis. +fn populate_polonius_move_facts(all_facts: &mut AllFacts, move_data: &MoveData<'_>, location_table: &LocationTable, body: &Body<'_>) { + all_facts.var_starts_path.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(v, &m)| (v, m))); + + for (idx, move_path) in move_data.move_paths.iter_enumerated() { + all_facts.parent.extend(move_path.parents(&move_data.move_paths).iter().map(|&parent| (parent, idx))); + } + + // initialized_at + for init in move_data.inits.iter() { + + match init.location { + InitLocation::Statement(location) => { + let block_data = &body[location.block]; + let is_terminator = location.statement_index == block_data.statements.len(); + + if is_terminator && init.kind == InitKind::NonPanicPathOnly { + // We are at the terminator of an init that has a panic path, + // and where the init should not happen on panic + + for &successor in block_data.terminator().successors() { + if body[successor].is_cleanup { + continue; + } + + // The initialization happened in (or rather, when arriving at) + // the successors, but not in the unwind block. + let first_statement = Location { block: successor, statement_index: 0}; + all_facts.initialized_at.push((init.path, location_table.start_index(first_statement))); + } + + } else { + // In all other cases, the initialization just happens at the + // midpoint, like any other effect. + all_facts.initialized_at.push((init.path, location_table.mid_index(location))); + } + }, + // Arguments are initialized on function entry + InitLocation::Argument(local) => { + assert!(body.local_kind(local) == LocalKind::Arg); + let fn_entry = Location {block: BasicBlock::from_u32(0u32), statement_index: 0 }; + all_facts.initialized_at.push((init.path, location_table.start_index(fn_entry))); + + } + } + } + + + // moved_out_at + // deinitialisation is assumed to always happen! + all_facts.moved_out_at.extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source)))); +} + /// Computes the (non-lexical) regions from the input MIR. /// /// This may result in errors being reported. @@ -123,6 +178,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( all_facts .universal_region .extend(universal_regions.universal_regions()); + populate_polonius_move_facts(all_facts, move_data, location_table, body); } // Create the region inference context, taking ownership of the diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs index 20d7ec55e3e84..dcdacbbe5be06 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs @@ -13,6 +13,7 @@ struct LivenessPointFactsExtractor<'me> { var_defined: &'me mut VarPointRelations, var_used: &'me mut VarPointRelations, location_table: &'me LocationTable, + var_drop_used: &'me mut VarPointRelations, } // A Visitor to walk through the MIR and extract point-wise facts @@ -30,6 +31,11 @@ impl LivenessPointFactsExtractor<'_> { debug!("LivenessFactsExtractor::insert_use()"); self.var_used.push((local, self.location_to_index(location))); } + + fn insert_drop_use(&mut self, local: Local, location: Location) { + debug!("LivenessFactsExtractor::insert_drop_use()"); + self.var_drop_used.push((local, self.location_to_index(location))); + } } impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> { @@ -37,8 +43,8 @@ impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> { match categorize(context) { Some(DefUse::Def) => self.insert_def(local, location), Some(DefUse::Use) => self.insert_use(local, location), + Some(DefUse::Drop) => self.insert_drop_use(local, location), _ => (), - // NOTE: Drop handling is now done in trace() } } } @@ -65,6 +71,7 @@ pub(super) fn populate_var_liveness_facts( LivenessPointFactsExtractor { var_defined: &mut facts.var_defined, var_used: &mut facts.var_used, + var_drop_used: &mut facts.var_drop_used, location_table, } .visit_body(mir); diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index de085fc480a0e..1e1768a8e4601 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -273,11 +273,6 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,); if self.cx.initialized_at_terminator(location.block, mpi) { - // FIXME: this analysis (the initialization tracking) should be - // done in Polonius, but isn't yet. - if let Some(facts) = self.cx.typeck.borrowck_context.all_facts { - facts.var_drop_used.push((local, self.cx.location_table.mid_index(location))); - } if self.drop_live_at.insert(drop_point) { self.drop_locations.push(location); self.stack.push(drop_point); diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index e5a19572170a7..07b9b662a07aa 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -1,9 +1,10 @@ use rustc::ty::{Ty, TyCtxt}; use rustc::mir::*; use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec, Enumerated}; use smallvec::SmallVec; use syntax_pos::{Span}; +use core::slice::Iter; use std::fmt; use std::ops::{Index, IndexMut}; @@ -262,6 +263,12 @@ impl MovePathLookup { pub fn find_local(&self, local: Local) -> MovePathIndex { self.locals[local] } + + /// An enumerated iterator of `local`s and their associated + /// `MovePathIndex`es. + pub fn iter_locals_enumerated(&self) -> Enumerated> { + self.locals.iter_enumerated() + } } #[derive(Debug)] From 9f39e001df1f665ce4f2bdbc38576f5fcc02f898 Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Tue, 6 Aug 2019 12:12:36 +0200 Subject: [PATCH 453/618] Polonius: Rename `parent` and `var_starts_path` --- src/librustc_mir/borrow_check/nll/facts.rs | 5 ++--- src/librustc_mir/borrow_check/nll/mod.rs | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index 10ce3a099cf2b..9458b24f07d90 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -65,9 +65,8 @@ impl AllFactsExt for AllFacts { var_drop_used, var_uses_region, var_drops_region, - var_maybe_initialized_on_exit, - parent, - var_starts_path, + child, + path_belongs_to_var, initialized_at, moved_out_at, ]) diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 9b920eb15599d..4c76d14bdbbbb 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -73,10 +73,10 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( // This function populates an AllFacts instance with base facts related to // MovePaths and needed for the move analysis. fn populate_polonius_move_facts(all_facts: &mut AllFacts, move_data: &MoveData<'_>, location_table: &LocationTable, body: &Body<'_>) { - all_facts.var_starts_path.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(v, &m)| (v, m))); + all_facts.path_belongs_to_var.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(v, &m)| (m, v))); - for (idx, move_path) in move_data.move_paths.iter_enumerated() { - all_facts.parent.extend(move_path.parents(&move_data.move_paths).iter().map(|&parent| (parent, idx))); + for (child, move_path) in move_data.move_paths.iter_enumerated() { + all_facts.child.extend(move_path.parents(&move_data.move_paths).iter().map(|&parent| (child, parent))); } // initialized_at From 6568b086a27c750c9ac69a00f5146a3b51881fb7 Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Fri, 16 Aug 2019 15:39:17 +0200 Subject: [PATCH 454/618] Polonius: don't emit `var_maybe_initialized_on_exit` --- .../nll/type_check/liveness/trace.rs | 63 ------------------- 1 file changed, 63 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 1e1768a8e4601..0990074c990d0 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -131,12 +131,6 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { for local in live_locals { self.reset_local_state(); self.add_defs_for(local); - - // FIXME: this is temporary until we can generate our own initialization - if self.cx.typeck.borrowck_context.all_facts.is_some() { - self.add_polonius_var_maybe_initialized_on_exit_for(local) - } - self.compute_use_live_points_for(local); self.compute_drop_live_points_for(local); @@ -157,63 +151,6 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } - // WARNING: panics if self.cx.typeck.borrowck_context.all_facts != None - // - // FIXME: this analysis (the initialization tracking) should be - // done in Polonius, but isn't yet. - fn add_polonius_var_maybe_initialized_on_exit_for(&mut self, local: Local) { - let move_path = self.cx.move_data.rev_lookup.find_local(local); - let facts = self.cx.typeck.borrowck_context.all_facts.as_mut().unwrap(); - for block in self.cx.body.basic_blocks().indices() { - debug!("polonius: generating initialization facts for {:?} in {:?}", local, block); - - // iterate through the block, applying the effects of each statement - // up to and including location, and populate `var_maybe_initialized_on_exit` - self.cx.flow_inits.reset_to_entry_of(block); - let start_location = Location { block, statement_index: 0 }; - self.cx.flow_inits.apply_local_effect(start_location); - - for statement_index in 0..self.cx.body[block].statements.len() { - let current_location = Location { block, statement_index }; - - self.cx.flow_inits.reconstruct_statement_effect(current_location); - - // statement has not yet taken effect: - if self.cx.flow_inits.has_any_child_of(move_path).is_some() { - facts - .var_maybe_initialized_on_exit - .push((local, self.cx.location_table.start_index(current_location))); - } - - // statement has now taken effect - self.cx.flow_inits.apply_local_effect(current_location); - - if self.cx.flow_inits.has_any_child_of(move_path).is_some() { - facts - .var_maybe_initialized_on_exit - .push((local, self.cx.location_table.mid_index(current_location))); - } - } - - let terminator_location = self.cx.body.terminator_loc(block); - - if self.cx.flow_inits.has_any_child_of(move_path).is_some() { - facts - .var_maybe_initialized_on_exit - .push((local, self.cx.location_table.start_index(terminator_location))); - } - - // apply the effects of the terminator and push it if needed - self.cx.flow_inits.reset_to_exit_of(block); - - if self.cx.flow_inits.has_any_child_of(move_path).is_some() { - facts - .var_maybe_initialized_on_exit - .push((local, self.cx.location_table.mid_index(terminator_location))); - } - } - } - /// Clear the value of fields that are "per local variable". fn reset_local_state(&mut self) { self.defs.clear(); From 9cd1a1157199b8303bc4fb5af3ae0fab6b91e786 Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Fri, 16 Aug 2019 15:42:22 +0200 Subject: [PATCH 455/618] Polonius: don't emit `region_live_at` --- src/librustc_mir/borrow_check/nll/facts.rs | 1 - .../nll/type_check/liveness/mod.rs | 2 +- .../nll/type_check/liveness/trace.rs | 18 ------------------ 3 files changed, 1 insertion(+), 20 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index 9458b24f07d90..b11e5e7a85d0e 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -58,7 +58,6 @@ impl AllFactsExt for AllFacts { cfg_edge, killed, outlives, - region_live_at, invalidates, var_used, var_defined, diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs index 8970009b6ee9f..25d7985653c0e 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs @@ -58,7 +58,7 @@ pub(super) fn generate<'tcx>( }; if !live_locals.is_empty() { - trace::trace(typeck, body, elements, flow_inits, move_data, live_locals, location_table); + trace::trace(typeck, body, elements, flow_inits, move_data, live_locals); polonius::populate_var_liveness_facts(typeck, body, location_table); } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 0990074c990d0..eba52ae3384b0 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -1,4 +1,3 @@ -use crate::borrow_check::location::LocationTable; use crate::borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements}; use crate::borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap; use crate::borrow_check::nll::type_check::liveness::polonius; @@ -38,7 +37,6 @@ pub(super) fn trace( flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>, move_data: &MoveData<'tcx>, live_locals: Vec, - location_table: &LocationTable, ) { debug!("trace()"); @@ -52,7 +50,6 @@ pub(super) fn trace( local_use_map, move_data, drop_data: FxHashMap::default(), - location_table, }; LivenessResults::new(cx).compute_for_all_locals(live_locals); @@ -82,9 +79,6 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> { /// Index indicating where each variable is assigned, used, or /// dropped. local_use_map: &'me LocalUseMap, - - /// Maps between a MIR Location and a LocationIndex - location_table: &'me LocationTable, } struct DropData<'tcx> { @@ -405,7 +399,6 @@ impl LivenessContext<'_, '_, '_, 'tcx> { &mut self.typeck, value, live_at, - self.location_table, ) } @@ -462,7 +455,6 @@ impl LivenessContext<'_, '_, '_, 'tcx> { &mut self.typeck, kind, live_at, - self.location_table, ); polonius::add_var_drops_regions(&mut self.typeck, dropped_local, &kind); @@ -474,7 +466,6 @@ impl LivenessContext<'_, '_, '_, 'tcx> { typeck: &mut TypeChecker<'_, 'tcx>, value: impl TypeFoldable<'tcx>, live_at: &HybridBitSet, - location_table: &LocationTable, ) { debug!("make_all_regions_live(value={:?})", value); debug!( @@ -491,15 +482,6 @@ impl LivenessContext<'_, '_, '_, 'tcx> { .constraints .liveness_constraints .add_elements(live_region_vid, live_at); - - // FIXME: remove this when we can generate our own region-live-at reliably - if let Some(facts) = typeck.borrowck_context.all_facts { - for point in live_at.iter() { - let loc = elements.to_location(point); - facts.region_live_at.push((live_region_vid, location_table.start_index(loc))); - facts.region_live_at.push((live_region_vid, location_table.mid_index(loc))); - } - } }); } From 560ef6d7103f18581b1dcc57de480247ba638677 Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Wed, 7 Aug 2019 17:44:35 +0200 Subject: [PATCH 456/618] Polonius: emit variable access facts --- src/librustc_mir/borrow_check/nll/facts.rs | 1 + .../nll/type_check/liveness/mod.rs | 2 +- .../nll/type_check/liveness/polonius.rs | 58 +++++++++++++++---- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index b11e5e7a85d0e..f0beb4d3ae32d 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -68,6 +68,7 @@ impl AllFactsExt for AllFacts { path_belongs_to_var, initialized_at, moved_out_at, + path_accessed_at, ]) } Ok(()) diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs index 25d7985653c0e..3f2ec1ba97017 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs @@ -60,7 +60,7 @@ pub(super) fn generate<'tcx>( if !live_locals.is_empty() { trace::trace(typeck, body, elements, flow_inits, move_data, live_locals); - polonius::populate_var_liveness_facts(typeck, body, location_table); + polonius::populate_access_facts(typeck, body, location_table, move_data); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs index dcdacbbe5be06..d61464b3f387d 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs @@ -1,23 +1,28 @@ use crate::borrow_check::location::{LocationIndex, LocationTable}; +use crate::dataflow::indexes::MovePathIndex; +use crate::dataflow::move_paths::{LookupResult, MoveData}; use crate::util::liveness::{categorize, DefUse}; -use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc::mir::{Body, Local, Location}; +use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; +use rustc::mir::{Body, Local, Location, Place}; use rustc::ty::subst::Kind; use rustc::ty::Ty; use super::TypeChecker; type VarPointRelations = Vec<(Local, LocationIndex)>; +type MovePathPointRelations = Vec<(MovePathIndex, LocationIndex)>; -struct LivenessPointFactsExtractor<'me> { +struct UseFactsExtractor<'me> { var_defined: &'me mut VarPointRelations, var_used: &'me mut VarPointRelations, location_table: &'me LocationTable, var_drop_used: &'me mut VarPointRelations, + move_data: &'me MoveData<'me>, + path_accessed_at: &'me mut MovePathPointRelations, } // A Visitor to walk through the MIR and extract point-wise facts -impl LivenessPointFactsExtractor<'_> { +impl UseFactsExtractor<'_> { fn location_to_index(&self, location: Location) -> LocationIndex { self.location_table.mid_index(location) } @@ -36,9 +41,21 @@ impl LivenessPointFactsExtractor<'_> { debug!("LivenessFactsExtractor::insert_drop_use()"); self.var_drop_used.push((local, self.location_to_index(location))); } + + fn insert_path_access(&mut self, path: MovePathIndex, location: Location) { + debug!("LivenessFactsExtractor::insert_path_access({:?}, {:?})", path, location); + self.path_accessed_at.push((path, self.location_to_index(location))); + } + + fn place_to_mpi(&self, place: &Place<'_>) -> Option { + match self.move_data.rev_lookup.find(place.as_ref()) { + LookupResult::Exact(mpi) => Some(mpi), + LookupResult::Parent(mmpi) => mmpi, + } + } } -impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> { +impl Visitor<'tcx> for UseFactsExtractor<'_> { fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) { match categorize(context) { Some(DefUse::Def) => self.insert_def(local, location), @@ -47,6 +64,24 @@ impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> { _ => (), } } + + fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { + self.super_place(place, context, location); + match context { + PlaceContext::NonMutatingUse(_) => { + if let Some(mpi) = self.place_to_mpi(place) { + self.insert_path_access(mpi, location); + } + } + + PlaceContext::MutatingUse(MutatingUseContext::Borrow) => { + if let Some(mpi) = self.place_to_mpi(place) { + self.insert_path_access(mpi, location); + } + } + _ => (), + } + } } fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty<'tcx>) { @@ -60,24 +95,27 @@ fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty }); } -pub(super) fn populate_var_liveness_facts( +pub(super) fn populate_access_facts( typeck: &mut TypeChecker<'_, 'tcx>, - mir: &Body<'tcx>, + body: &Body<'tcx>, location_table: &LocationTable, + move_data: &MoveData<'_>, ) { debug!("populate_var_liveness_facts()"); if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() { - LivenessPointFactsExtractor { + UseFactsExtractor { var_defined: &mut facts.var_defined, var_used: &mut facts.var_used, var_drop_used: &mut facts.var_drop_used, + path_accessed_at: &mut facts.path_accessed_at, location_table, + move_data, } - .visit_body(mir); + .visit_body(body); } - for (local, local_decl) in mir.local_decls.iter_enumerated() { + for (local, local_decl) in body.local_decls.iter_enumerated() { add_var_uses_regions(typeck, local, local_decl.ty); } } From 28312b5b0604444b5806cfb42ea11a1be14098ac Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Mon, 19 Aug 2019 15:56:16 +0200 Subject: [PATCH 457/618] Rustfmt the files I touched --- src/librustc_mir/borrow_check/nll/mod.rs | 37 +++- .../nll/type_check/liveness/local_use_map.rs | 22 +- .../nll/type_check/liveness/trace.rs | 14 +- .../dataflow/move_paths/abs_domain.rs | 40 ++-- .../dataflow/move_paths/builder.rs | 200 +++++++++--------- src/librustc_mir/dataflow/move_paths/mod.rs | 42 ++-- 6 files changed, 187 insertions(+), 168 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 4c76d14bdbbbb..1ff3228afa376 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -11,7 +11,8 @@ use crate::transform::MirSource; use crate::borrow_check::Upvar; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Location, Body, LocalKind, BasicBlock, Promoted}; +use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, + Local, Location, Body, LocalKind, BasicBlock, Promoted}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::Diagnostic; @@ -72,11 +73,27 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( // This function populates an AllFacts instance with base facts related to // MovePaths and needed for the move analysis. -fn populate_polonius_move_facts(all_facts: &mut AllFacts, move_data: &MoveData<'_>, location_table: &LocationTable, body: &Body<'_>) { - all_facts.path_belongs_to_var.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(v, &m)| (m, v))); +fn populate_polonius_move_facts( + all_facts: &mut AllFacts, + move_data: &MoveData<'_>, + location_table: &LocationTable, + body: &Body<'_>) { + all_facts + .path_belongs_to_var + .extend( + move_data + .rev_lookup + .iter_locals_enumerated() + .map(|(v, &m)| (m, v))); for (child, move_path) in move_data.move_paths.iter_enumerated() { - all_facts.child.extend(move_path.parents(&move_data.move_paths).iter().map(|&parent| (child, parent))); + all_facts + .child + .extend( + move_path + .parents(&move_data.move_paths) + .iter() + .map(|&parent| (child, parent))); } // initialized_at @@ -99,7 +116,9 @@ fn populate_polonius_move_facts(all_facts: &mut AllFacts, move_data: &MoveData<' // The initialization happened in (or rather, when arriving at) // the successors, but not in the unwind block. let first_statement = Location { block: successor, statement_index: 0}; - all_facts.initialized_at.push((init.path, location_table.start_index(first_statement))); + all_facts + .initialized_at + .push((init.path, location_table.start_index(first_statement))); } } else { @@ -121,7 +140,13 @@ fn populate_polonius_move_facts(all_facts: &mut AllFacts, move_data: &MoveData<' // moved_out_at // deinitialisation is assumed to always happen! - all_facts.moved_out_at.extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source)))); + all_facts + .moved_out_at + .extend( + move_data + .moves + .iter() + .map(|mo| (mo.path, location_table.mid_index(mo.source)))); } /// Computes the (non-lexical) regions from the input MIR. diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs index 2a066538cc234..049d83bb22f1b 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs @@ -1,7 +1,7 @@ use crate::borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements}; use crate::util::liveness::{categorize, DefUse}; use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc::mir::{Local, Location, Body}; +use rustc::mir::{Body, Local, Location}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::vec_linked_list as vll; @@ -72,16 +72,10 @@ impl LocalUseMap { let mut locals_with_use_data: IndexVec = IndexVec::from_elem_n(false, body.local_decls.len()); - live_locals - .iter() - .for_each(|&local| locals_with_use_data[local] = true); - - LocalUseMapBuild { - local_use_map: &mut local_use_map, - elements, - locals_with_use_data, - } - .visit_body(body); + live_locals.iter().for_each(|&local| locals_with_use_data[local] = true); + + LocalUseMapBuild { local_use_map: &mut local_use_map, elements, locals_with_use_data } + .visit_body(body); local_use_map } @@ -151,10 +145,8 @@ impl LocalUseMapBuild<'_> { location: Location, ) { let point_index = elements.point_from_location(location); - let appearance_index = appearances.push(Appearance { - point_index, - next: *first_appearance, - }); + let appearance_index = + appearances.push(Appearance { point_index, next: *first_appearance }); *first_appearance = Some(appearance_index); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index eba52ae3384b0..9b55881cb1b10 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -394,12 +394,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { ) { debug!("add_use_live_facts_for(value={:?})", value); - Self::make_all_regions_live( - self.elements, - &mut self.typeck, - value, - live_at, - ) + Self::make_all_regions_live(self.elements, &mut self.typeck, value, live_at) } /// Some variable with type `live_ty` is "drop live" at `location` @@ -450,12 +445,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { // All things in the `outlives` array may be touched by // the destructor and must be live at this point. for &kind in &drop_data.dropck_result.kinds { - Self::make_all_regions_live( - self.elements, - &mut self.typeck, - kind, - live_at, - ); + Self::make_all_regions_live(self.elements, &mut self.typeck, kind, live_at); polonius::add_var_drops_regions(&mut self.typeck, dropped_local, &kind); } diff --git a/src/librustc_mir/dataflow/move_paths/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs index b26547c4ff77e..d97f3b7417286 100644 --- a/src/librustc_mir/dataflow/move_paths/abs_domain.rs +++ b/src/librustc_mir/dataflow/move_paths/abs_domain.rs @@ -11,7 +11,7 @@ //! `a[x]` would still overlap them both. But that is not this //! representation does today.) -use rustc::mir::{Local, PlaceElem, Operand, ProjectionElem}; +use rustc::mir::{Local, Operand, PlaceElem, ProjectionElem}; use rustc::ty::Ty; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] @@ -26,36 +26,36 @@ pub trait Lift { } impl<'tcx> Lift for Operand<'tcx> { type Abstract = AbstractOperand; - fn lift(&self) -> Self::Abstract { AbstractOperand } + fn lift(&self) -> Self::Abstract { + AbstractOperand + } } impl Lift for Local { type Abstract = AbstractOperand; - fn lift(&self) -> Self::Abstract { AbstractOperand } + fn lift(&self) -> Self::Abstract { + AbstractOperand + } } impl<'tcx> Lift for Ty<'tcx> { type Abstract = AbstractType; - fn lift(&self) -> Self::Abstract { AbstractType } + fn lift(&self) -> Self::Abstract { + AbstractType + } } impl<'tcx> Lift for PlaceElem<'tcx> { type Abstract = AbstractElem; fn lift(&self) -> Self::Abstract { match *self { - ProjectionElem::Deref => - ProjectionElem::Deref, - ProjectionElem::Field(ref f, ty) => - ProjectionElem::Field(f.clone(), ty.lift()), - ProjectionElem::Index(ref i) => - ProjectionElem::Index(i.lift()), - ProjectionElem::Subslice {from, to} => - ProjectionElem::Subslice { from: from, to: to }, - ProjectionElem::ConstantIndex {offset,min_length,from_end} => - ProjectionElem::ConstantIndex { - offset, - min_length, - from_end, - }, - ProjectionElem::Downcast(a, u) => - ProjectionElem::Downcast(a, u.clone()), + ProjectionElem::Deref => ProjectionElem::Deref, + ProjectionElem::Field(ref f, ty) => ProjectionElem::Field(f.clone(), ty.lift()), + ProjectionElem::Index(ref i) => ProjectionElem::Index(i.lift()), + ProjectionElem::Subslice { from, to } => { + ProjectionElem::Subslice { from: from, to: to } + } + ProjectionElem::ConstantIndex { offset, min_length, from_end } => { + ProjectionElem::ConstantIndex { offset, min_length, from_end } + } + ProjectionElem::Downcast(a, u) => ProjectionElem::Downcast(a, u.clone()), } } } diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 366b96b53b423..81451c2500c47 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -1,16 +1,18 @@ -use rustc::ty::{self, TyCtxt}; -use rustc::mir::*; use rustc::mir::tcx::RvalueInitializationState; -use rustc_data_structures::indexed_vec::{IndexVec}; -use smallvec::{SmallVec, smallvec}; +use rustc::mir::*; +use rustc::ty::{self, TyCtxt}; +use rustc_data_structures::indexed_vec::IndexVec; +use smallvec::{smallvec, SmallVec}; use std::collections::hash_map::Entry; use std::mem; use super::abs_domain::Lift; -use super::{LocationMap, MoveData, MovePath, MovePathLookup, MovePathIndex, MoveOut, MoveOutIndex}; -use super::{MoveError, InitIndex, Init, InitLocation, LookupResult, InitKind}; use super::IllegalMoveOriginKind::*; +use super::{Init, InitIndex, InitKind, InitLocation, LookupResult, MoveError}; +use super::{ + LocationMap, MoveData, MoveOut, MoveOutIndex, MovePath, MovePathIndex, MovePathLookup, +}; struct MoveDataBuilder<'a, 'tcx> { body: &'a Body<'tcx>, @@ -33,15 +35,19 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { moves: IndexVec::new(), loc_map: LocationMap::new(body), rev_lookup: MovePathLookup { - locals: body.local_decls.indices().map(|i| { - Self::new_move_path( - &mut move_paths, - &mut path_map, - &mut init_path_map, - None, - Place::from(i), - ) - }).collect(), + locals: body + .local_decls + .indices() + .map(|i| { + Self::new_move_path( + &mut move_paths, + &mut path_map, + &mut init_path_map, + None, + Place::from(i), + ) + }) + .collect(), projections: Default::default(), }, move_paths, @@ -49,27 +55,22 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { inits: IndexVec::new(), init_loc_map: LocationMap::new(body), init_path_map, - } + }, } } - fn new_move_path(move_paths: &mut IndexVec>, - path_map: &mut IndexVec>, - init_path_map: &mut IndexVec>, - parent: Option, - place: Place<'tcx>) - -> MovePathIndex - { - let move_path = move_paths.push(MovePath { - next_sibling: None, - first_child: None, - parent, - place, - }); + fn new_move_path( + move_paths: &mut IndexVec>, + path_map: &mut IndexVec>, + init_path_map: &mut IndexVec>, + parent: Option, + place: Place<'tcx>, + ) -> MovePathIndex { + let move_path = + move_paths.push(MovePath { next_sibling: None, first_child: None, parent, place }); if let Some(parent) = parent { - let next_sibling = - mem::replace(&mut move_paths[parent].first_child, Some(move_path)); + let next_sibling = mem::replace(&mut move_paths[parent].first_child, Some(move_path)); move_paths[move_path].next_sibling = next_sibling; } @@ -91,9 +92,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { /// problematic for borrowck. /// /// Maybe we should have separate "borrowck" and "moveck" modes. - fn move_path_for(&mut self, place: &Place<'tcx>) - -> Result> - { + fn move_path_for(&mut self, place: &Place<'tcx>) -> Result> { debug!("lookup({:?})", place); place.iterate(|place_base, place_projection| { let mut base = match place_base { @@ -108,39 +107,46 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { let tcx = self.builder.tcx; let place_ty = Place::ty_from(place_base, &proj.base, body, tcx).ty; match place_ty.sty { - ty::Ref(..) | ty::RawPtr(..) => + ty::Ref(..) | ty::RawPtr(..) => { return Err(MoveError::cannot_move_out_of( self.loc, BorrowedContent { target_place: Place { base: place_base.clone(), projection: Some(Box::new(proj.clone())), - } - })), - ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => - return Err(MoveError::cannot_move_out_of(self.loc, - InteriorOfTypeWithDestructor { - container_ty: place_ty - })), + }, + }, + )); + } + ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => { + return Err(MoveError::cannot_move_out_of( + self.loc, + InteriorOfTypeWithDestructor { container_ty: place_ty }, + )); + } // move out of union - always move the entire union - ty::Adt(adt, _) if adt.is_union() => - return Err(MoveError::UnionMove { path: base }), - ty::Slice(_) => + ty::Adt(adt, _) if adt.is_union() => { + return Err(MoveError::UnionMove { path: base }); + } + ty::Slice(_) => { return Err(MoveError::cannot_move_out_of( self.loc, InteriorOfSliceOrArray { - ty: place_ty, is_index: match proj.elem { + ty: place_ty, + is_index: match proj.elem { ProjectionElem::Index(..) => true, - _ => false + _ => false, }, - })), + }, + )); + } ty::Array(..) => match proj.elem { - ProjectionElem::Index(..) => + ProjectionElem::Index(..) => { return Err(MoveError::cannot_move_out_of( self.loc, - InteriorOfSliceOrArray { - ty: place_ty, is_index: true - })), + InteriorOfSliceOrArray { ty: place_ty, is_index: true }, + )); + } _ => { // FIXME: still badly broken } @@ -186,7 +192,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { fn finalize( - self + self, ) -> Result, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> { debug!("{}", { debug!("moves for {:?}:", self.body.span); @@ -200,11 +206,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { "done dumping moves" }); - if !self.errors.is_empty() { - Err((self.data, self.errors)) - } else { - Ok(self.data) - } + if !self.errors.is_empty() { Err((self.data, self.errors)) } else { Ok(self.data) } } } @@ -222,10 +224,7 @@ pub(super) fn gather_moves<'tcx>( builder.gather_statement(source, stmt); } - let terminator_loc = Location { - block: bb, - statement_index: block.statements.len() - }; + let terminator_loc = Location { block: bb, statement_index: block.statements.len() }; builder.gather_terminator(terminator_loc, block.terminator()); } @@ -238,11 +237,12 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { let path = self.data.rev_lookup.locals[arg]; let init = self.data.inits.push(Init { - path, kind: InitKind::Deep, location: InitLocation::Argument(arg), + path, + kind: InitKind::Deep, + location: InitLocation::Argument(arg), }); - debug!("gather_args: adding init {:?} of {:?} for argument {:?}", - init, path, arg); + debug!("gather_args: adding init {:?} of {:?} for argument {:?}", init, path, arg); self.data.init_path_map[path].push(init); } @@ -297,26 +297,26 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { StatementKind::StorageDead(local) => { self.gather_move(&Place::from(local)); } - StatementKind::SetDiscriminant{ .. } => { - span_bug!(stmt.source_info.span, - "SetDiscriminant should not exist during borrowck"); + StatementKind::SetDiscriminant { .. } => { + span_bug!( + stmt.source_info.span, + "SetDiscriminant should not exist during borrowck" + ); } - StatementKind::Retag { .. } | - StatementKind::AscribeUserType(..) | - StatementKind::Nop => {} + StatementKind::Retag { .. } + | StatementKind::AscribeUserType(..) + | StatementKind::Nop => {} } } fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) { match *rvalue { - Rvalue::Use(ref operand) | - Rvalue::Repeat(ref operand, _) | - Rvalue::Cast(_, ref operand, _) | - Rvalue::UnaryOp(_, ref operand) => { - self.gather_operand(operand) - } - Rvalue::BinaryOp(ref _binop, ref lhs, ref rhs) | - Rvalue::CheckedBinaryOp(ref _binop, ref lhs, ref rhs) => { + Rvalue::Use(ref operand) + | Rvalue::Repeat(ref operand, _) + | Rvalue::Cast(_, ref operand, _) + | Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand), + Rvalue::BinaryOp(ref _binop, ref lhs, ref rhs) + | Rvalue::CheckedBinaryOp(ref _binop, ref lhs, ref rhs) => { self.gather_operand(lhs); self.gather_operand(rhs); } @@ -325,11 +325,11 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { self.gather_operand(operand); } } - Rvalue::Ref(..) | - Rvalue::Discriminant(..) | - Rvalue::Len(..) | - Rvalue::NullaryOp(NullOp::SizeOf, _) | - Rvalue::NullaryOp(NullOp::Box, _) => { + Rvalue::Ref(..) + | Rvalue::Discriminant(..) + | Rvalue::Len(..) + | Rvalue::NullaryOp(NullOp::SizeOf, _) + | Rvalue::NullaryOp(NullOp::Box, _) => { // This returns an rvalue with uninitialized contents. We can't // move out of it here because it is an rvalue - assignments always // completely initialize their place. @@ -346,13 +346,13 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { fn gather_terminator(&mut self, term: &Terminator<'tcx>) { match term.kind { - TerminatorKind::Goto { target: _ } | - TerminatorKind::Resume | - TerminatorKind::Abort | - TerminatorKind::GeneratorDrop | - TerminatorKind::FalseEdges { .. } | - TerminatorKind::FalseUnwind { .. } | - TerminatorKind::Unreachable => { } + TerminatorKind::Goto { target: _ } + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::GeneratorDrop + | TerminatorKind::FalseEdges { .. } + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::Unreachable => {} TerminatorKind::Return => { self.gather_move(&Place::RETURN_PLACE); @@ -399,9 +399,9 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { fn gather_operand(&mut self, operand: &Operand<'tcx>) { match *operand { - Operand::Constant(..) | - Operand::Copy(..) => {} // not-a-move - Operand::Move(ref place) => { // a move + Operand::Constant(..) | Operand::Copy(..) => {} // not-a-move + Operand::Move(ref place) => { + // a move self.gather_move(place); } } @@ -419,8 +419,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { }; let move_out = self.builder.data.moves.push(MoveOut { path: path, source: self.loc }); - debug!("gather_move({:?}, {:?}): adding move {:?} of {:?}", - self.loc, place, move_out, path); + debug!( + "gather_move({:?}, {:?}): adding move {:?} of {:?}", + self.loc, place, move_out, path + ); self.builder.data.path_map[path].push(move_out); self.builder.data.loc_map[self.loc].push(move_out); @@ -452,8 +454,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { kind, }); - debug!("gather_init({:?}, {:?}): adding init {:?} of {:?}", - self.loc, place, init, path); + debug!( + "gather_init({:?}, {:?}): adding init {:?} of {:?}", + self.loc, place, init, path + ); self.builder.data.init_path_map[path].push(init); self.builder.data.init_loc_map[self.loc].push(init); diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 07b9b662a07aa..5028e9650918c 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -1,10 +1,10 @@ -use rustc::ty::{Ty, TyCtxt}; +use core::slice::Iter; use rustc::mir::*; +use rustc::ty::{Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::indexed_vec::{Idx, IndexVec, Enumerated}; +use rustc_data_structures::indexed_vec::{Enumerated, Idx, IndexVec}; use smallvec::SmallVec; -use syntax_pos::{Span}; -use core::slice::Iter; +use syntax_pos::Span; use std::fmt; use std::ops::{Index, IndexMut}; @@ -138,12 +138,17 @@ impl IndexMut for LocationMap { } } -impl LocationMap where T: Default + Clone { +impl LocationMap +where + T: Default + Clone, +{ fn new(body: &Body<'_>) -> Self { LocationMap { - map: body.basic_blocks().iter().map(|block| { - vec![T::default(); block.statements.len()+1] - }).collect() + map: body + .basic_blocks() + .iter() + .map(|block| vec![T::default(); block.statements.len() + 1]) + .collect(), } } } @@ -179,7 +184,6 @@ pub struct Init { pub kind: InitKind, } - /// Initializations can be from an argument or from a statement. Arguments /// do not have locations, in those cases the `Local` is kept.. #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -225,7 +229,7 @@ pub struct MovePathLookup { /// subsequent search so that it is solely relative to that /// base-place). For the remaining lookup, we map the projection /// elem to the associated MovePathIndex. - projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex> + projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>, } mod builder; @@ -233,7 +237,7 @@ mod builder; #[derive(Copy, Clone, Debug)] pub enum LookupResult { Exact(MovePathIndex), - Parent(Option) + Parent(Option), } impl MovePathLookup { @@ -296,7 +300,7 @@ pub(crate) enum IllegalMoveOriginKind<'tcx> { InteriorOfTypeWithDestructor { container_ty: Ty<'tcx> }, /// Illegal move due to attempt to move out of a slice or array. - InteriorOfSliceOrArray { ty: Ty<'tcx>, is_index: bool, }, + InteriorOfSliceOrArray { ty: Ty<'tcx>, is_index: bool }, } #[derive(Debug)] @@ -325,11 +329,15 @@ impl<'tcx> MoveData<'tcx> { pub fn base_local(&self, mut mpi: MovePathIndex) -> Option { loop { let path = &self.move_paths[mpi]; - if let Place { - base: PlaceBase::Local(l), - projection: None, - } = path.place { return Some(l); } - if let Some(parent) = path.parent { mpi = parent; continue } else { return None } + if let Place { base: PlaceBase::Local(l), projection: None } = path.place { + return Some(l); + } + if let Some(parent) = path.parent { + mpi = parent; + continue; + } else { + return None; + } } } } From 41deb835498391623388555b8d44fa358c804be7 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 4 Sep 2019 18:32:00 +0900 Subject: [PATCH 458/618] Add compile flag --- src/test/ui/issues/issue-8460-const.rs | 2 + src/test/ui/issues/issue-8460-const.stderr | 82 +++++++++++----------- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs index 611d280f774c0..4637814b277a4 100644 --- a/src/test/ui/issues/issue-8460-const.rs +++ b/src/test/ui/issues/issue-8460-const.rs @@ -1,3 +1,5 @@ +// compile-flags: -O + #![deny(const_err)] use std::{isize, i8, i16, i32, i64}; diff --git a/src/test/ui/issues/issue-8460-const.stderr b/src/test/ui/issues/issue-8460-const.stderr index 31b1da4f804ab..7e5a22e651ee5 100644 --- a/src/test/ui/issues/issue-8460-const.stderr +++ b/src/test/ui/issues/issue-8460-const.stderr @@ -1,245 +1,245 @@ error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:7:36 + --> $DIR/issue-8460-const.rs:9:36 | LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/issue-8460-const.rs:1:9 + --> $DIR/issue-8460-const.rs:3:9 | LL | #![deny(const_err)] | ^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:7:36 + --> $DIR/issue-8460-const.rs:9:36 | LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to divide with overflow error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:10:36 + --> $DIR/issue-8460-const.rs:12:36 | LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:10:36 + --> $DIR/issue-8460-const.rs:12:36 | LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^ attempt to divide with overflow error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:13:36 + --> $DIR/issue-8460-const.rs:15:36 | LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:13:36 + --> $DIR/issue-8460-const.rs:15:36 | LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to divide with overflow error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:16:36 + --> $DIR/issue-8460-const.rs:18:36 | LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:16:36 + --> $DIR/issue-8460-const.rs:18:36 | LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to divide with overflow error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:19:36 + --> $DIR/issue-8460-const.rs:21:36 | LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:19:36 + --> $DIR/issue-8460-const.rs:21:36 | LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to divide with overflow error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:22:36 + --> $DIR/issue-8460-const.rs:24:36 | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:22:36 + --> $DIR/issue-8460-const.rs:24:36 | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:25:36 + --> $DIR/issue-8460-const.rs:27:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:25:36 + --> $DIR/issue-8460-const.rs:27:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:28:36 + --> $DIR/issue-8460-const.rs:30:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:28:36 + --> $DIR/issue-8460-const.rs:30:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:31:36 + --> $DIR/issue-8460-const.rs:33:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:31:36 + --> $DIR/issue-8460-const.rs:33:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:34:36 + --> $DIR/issue-8460-const.rs:36:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:34:36 + --> $DIR/issue-8460-const.rs:36:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ attempt to divide by zero error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:37:36 + --> $DIR/issue-8460-const.rs:39:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:37:36 + --> $DIR/issue-8460-const.rs:39:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:40:36 + --> $DIR/issue-8460-const.rs:42:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:40:36 + --> $DIR/issue-8460-const.rs:42:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:43:36 + --> $DIR/issue-8460-const.rs:45:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:43:36 + --> $DIR/issue-8460-const.rs:45:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:46:36 + --> $DIR/issue-8460-const.rs:48:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:46:36 + --> $DIR/issue-8460-const.rs:48:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:49:36 + --> $DIR/issue-8460-const.rs:51:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:49:36 + --> $DIR/issue-8460-const.rs:51:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:52:36 + --> $DIR/issue-8460-const.rs:54:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:52:36 + --> $DIR/issue-8460-const.rs:54:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:55:36 + --> $DIR/issue-8460-const.rs:57:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:55:36 + --> $DIR/issue-8460-const.rs:57:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:58:36 + --> $DIR/issue-8460-const.rs:60:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:58:36 + --> $DIR/issue-8460-const.rs:60:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:61:36 + --> $DIR/issue-8460-const.rs:63:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:61:36 + --> $DIR/issue-8460-const.rs:63:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:64:36 + --> $DIR/issue-8460-const.rs:66:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:64:36 + --> $DIR/issue-8460-const.rs:66:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero From a0c186c34f67c7eb3b392755091dd3a17f5acbdf Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 21 Jul 2019 14:50:39 +0300 Subject: [PATCH 459/618] remove XID and Pattern_White_Space unicode tables from libcore They are only used by rustc_lexer, and are not needed elsewhere. So we move the relevant definitions into rustc_lexer (while the actual unicode data comes from the unicode-xid crate) and make the rest of the compiler use it. --- Cargo.lock | 17 +- src/libcore/char/methods.rs | 23 -- src/libcore/unicode/mod.rs | 5 - src/libcore/unicode/tables.rs | 375 ------------------ src/libcore/unicode/unicode.py | 9 +- src/libfmt_macros/Cargo.toml | 2 +- src/libfmt_macros/lib.rs | 10 +- src/librustc_lexer/Cargo.toml | 8 +- src/librustc_lexer/src/lib.rs | 63 ++- src/librustc_mir/Cargo.toml | 1 + src/librustc_mir/borrow_check/move_errors.rs | 5 +- .../borrow_check/mutability_errors.rs | 4 +- src/librustdoc/lib.rs | 1 + src/librustdoc/test.rs | 5 +- src/libsyntax/ext/proc_macro_server.rs | 4 +- src/libsyntax_ext/Cargo.toml | 1 + 16 files changed, 69 insertions(+), 464 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e0d30647809a9..1b916576bc99c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1011,6 +1011,7 @@ dependencies = [ name = "fmt_macros" version = "0.0.0" dependencies = [ + "rustc_lexer", "syntax_pos", ] @@ -2372,7 +2373,7 @@ version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" dependencies = [ - "unicode-xid", + "unicode-xid 0.1.0", ] [[package]] @@ -3290,7 +3291,7 @@ dependencies = [ name = "rustc_lexer" version = "0.1.0" dependencies = [ - "unicode-xid", + "unicode-xid 0.2.0", ] [[package]] @@ -3368,6 +3369,7 @@ dependencies = [ "rustc_apfloat", "rustc_data_structures", "rustc_errors", + "rustc_lexer", "rustc_target", "serialize", "smallvec", @@ -3976,7 +3978,7 @@ checksum = "641e117d55514d6d918490e47102f7e08d096fdde360247e4a10f7a91a8478d3" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-xid 0.1.0", ] [[package]] @@ -3988,7 +3990,7 @@ dependencies = [ "proc-macro2", "quote", "syn", - "unicode-xid", + "unicode-xid 0.1.0", ] [[package]] @@ -4017,6 +4019,7 @@ dependencies = [ "log", "rustc_data_structures", "rustc_errors", + "rustc_lexer", "rustc_target", "smallvec", "syntax", @@ -4532,6 +4535,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" + [[package]] name = "unicode_categories" version = "0.1.1" diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index e91bf53c5b418..a69eb0f6d4b20 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -547,29 +547,6 @@ impl char { } } - /// Returns `true` if this `char` satisfies the `XID_Start` Unicode property, and false - /// otherwise. - /// - /// `XID_Start` is a Unicode Derived Property specified in - /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), - /// mostly similar to `ID_Start` but modified for closure under `NFKx`. - #[unstable(feature = "unicode_internals", issue = "0")] - pub fn is_xid_start(self) -> bool { - derived_property::XID_Start(self) - } - - /// Returns `true` if this `char` satisfies the `XID_Continue` Unicode property, and false - /// otherwise. - /// - /// `XID_Continue` is a Unicode Derived Property specified in - /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), - /// mostly similar to `ID_Continue` but modified for closure under NFKx. - #[unstable(feature = "unicode_internals", issue = "0")] - #[inline] - pub fn is_xid_continue(self) -> bool { - derived_property::XID_Continue(self) - } - /// Returns `true` if this `char` is lowercase. /// /// 'Lowercase' is defined according to the terms of the Unicode Derived Core diff --git a/src/libcore/unicode/mod.rs b/src/libcore/unicode/mod.rs index 272727def61d6..a3ec9fd51f064 100644 --- a/src/libcore/unicode/mod.rs +++ b/src/libcore/unicode/mod.rs @@ -13,8 +13,3 @@ pub mod derived_property { pub mod conversions { pub use crate::unicode::tables::conversions::{to_lower, to_upper}; } - -// For use in libsyntax -pub mod property { - pub use crate::unicode::tables::property::Pattern_White_Space; -} diff --git a/src/libcore/unicode/tables.rs b/src/libcore/unicode/tables.rs index 3fae3a46ada6b..5b5be48543121 100644 --- a/src/libcore/unicode/tables.rs +++ b/src/libcore/unicode/tables.rs @@ -890,384 +890,9 @@ pub(crate) mod derived_property { Uppercase_table.lookup(c) } - const XID_Continue_table: &super::BoolTrie = &super::BoolTrie { - r1: [ - 0x03ff000000000000, 0x07fffffe87fffffe, 0x04a0040000000000, 0xff7fffffff7fffff, - 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, - 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0000501f0003ffc3, - 0xffffffffffffffff, 0xb8dfffffffffffff, 0xfffffffbffffd7c0, 0xffbfffffffffffff, - 0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffffffffcfb, 0xffffffffffffffff, - 0xfffeffffffffffff, 0xffffffff027fffff, 0xbffffffffffe01ff, 0x000787ffffff00b6, - 0xffffffff07ff0000, 0xffffc3ffffffffff, 0xffffffffffffffff, 0x9ffffdff9fefffff, - 0xffffffffffff0000, 0xffffffffffffe7ff, 0x0003ffffffffffff, 0x243fffffffffffff - ], - r2: [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 4, 32, 33, 34, 4, 4, 4, 4, 4, 35, 36, 37, 38, 39, 40, - 41, 42, 4, 4, 4, 4, 4, 4, 4, 4, 43, 44, 45, 46, 47, 4, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 4, 61, 4, 62, 63, 64, 65, 66, 4, 4, 4, 67, 4, 4, 4, 4, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 79, 80, 4, 81, 82, 83, 84, 85, 60, 60, 60, 60, 60, 60, 60, 60, 86, - 42, 87, 88, 89, 4, 90, 91, 60, 60, 60, 60, 60, 60, 60, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 52, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 93, 94, 4, 4, 4, 4, 95, 96, 4, 97, 98, 4, 99, 100, 101, 62, 4, 102, 103, - 104, 4, 105, 106, 107, 4, 108, 109, 110, 4, 111, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 112, 113, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 4, 4, 4, 4, 4, 103, 4, 114, - 115, 116, 97, 117, 4, 118, 4, 4, 119, 120, 121, 122, 123, 124, 4, 125, 126, 127, 128, - 129 - ], - r3: &[ - 0x00003fffffffffff, 0x000007ff0fffffff, 0x3fdfffff00000000, 0xfffffffbfff80000, - 0xffffffffffffffff, 0xfffeffcfffffffff, 0xf3c5fdfffff99fef, 0x5003ffcfb080799f, - 0xd36dfdfffff987ee, 0x003fffc05e023987, 0xf3edfdfffffbbfee, 0xfe00ffcf00013bbf, - 0xf3edfdfffff99fee, 0x0002ffcfb0c0399f, 0xc3ffc718d63dc7ec, 0x0000ffc000813dc7, - 0xe3fffdfffffddfff, 0x0000ffcf07603ddf, 0xf3effdfffffddfef, 0x0006ffcf40603ddf, - 0xfffffffffffddfef, 0xfc00ffcf80f07ddf, 0x2ffbfffffc7fffec, 0x000cffc0ff5f847f, - 0x07fffffffffffffe, 0x0000000003ff7fff, 0x3fffffaffffff7d6, 0x00000000f3ff3f5f, - 0xc2a003ff03000001, 0xfffe1ffffffffeff, 0x1ffffffffeffffdf, 0x0000000000000040, - 0xffffffffffff03ff, 0xffffffff3fffffff, 0xf7ffffffffff20bf, 0xffffffff3d7f3dff, - 0x7f3dffffffff3dff, 0xffffffffff7fff3d, 0xffffffffff3dffff, 0x0003fe00e7ffffff, - 0xffffffff0000ffff, 0x3f3fffffffffffff, 0xfffffffffffffffe, 0xffff9fffffffffff, - 0xffffffff07fffffe, 0x01ffc7ffffffffff, 0x001fffff001fdfff, 0x000ddfff000fffff, - 0x000003ff308fffff, 0xffffffff03ff3800, 0x01ffffffffffffff, 0xffff07ffffffffff, - 0x003fffffffffffff, 0x0fff0fff7fffffff, 0x001f3fffffffffc0, 0xffff0fffffffffff, - 0x0000000007ff03ff, 0xffffffff0fffffff, 0x9fffffff7fffffff, 0x3fff008003ff03ff, - 0x0000000000000000, 0x000ff80003ff0fff, 0x000fffffffffffff, 0x00ffffffffffffff, - 0x3fffffffffffe3ff, 0xe7ffffffffff01ff, 0x07fffffffff70000, 0xfbffffffffffffff, - 0xffffffff3f3fffff, 0x3fffffffaaff3f3f, 0x5fdfffffffffffff, 0x1fdc1fff0fcf1fdc, - 0x8000000000000000, 0x8002000000100001, 0x000000001fff0000, 0x0001ffe21fff0000, - 0xf3fffd503f2ffc84, 0xffffffff000043e0, 0x00000000000001ff, 0xffff7fffffffffff, - 0xffffffff7fffffff, 0x000ff81fffffffff, 0xffff20bfffffffff, 0x800080ffffffffff, - 0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f, 0x1f3efffe000000e0, 0xfffffffee67fffff, - 0xf7ffffffffffffff, 0xfffeffffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, - 0x0000ffffffffffff, 0x0000000000001fff, 0x3fffffffffff0000, 0x00000fffffff1fff, - 0xbff0ffffffffffff, 0x0003ffffffffffff, 0xfffffffcff800000, 0xfffffffffffff9ff, - 0xff8000000000007c, 0x000000ffffffffff, 0xe8ffffff03ff003f, 0xffff3fffffffffff, - 0x1fffffff000fffff, 0x7fffffff03ff8001, 0x007fffffffffffff, 0xfc7fffff03ff3fff, - 0x007cffff38000007, 0xffff7f7f007e7e7e, 0xffff00fff7ffffff, 0x03ff37ffffffffff, - 0xffff000fffffffff, 0x0ffffffffffff87f, 0x0000000003ffffff, 0x5f7ffdffe0f8007f, - 0xffffffffffffffdb, 0xfffffffffff80000, 0xfffffff03fffffff, 0x3fffffffffffffff, - 0xffffffffffff0000, 0xfffffffffffcffff, 0x03ff0000000000ff, 0x0018ffff0000ffff, - 0xaa8a00000000e000, 0x1fffffffffffffff, 0x87fffffe03ff0000, 0xffffffc007fffffe, - 0x7fffffffffffffff, 0x000000001cfcfcfc - ], - r4: [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13, - 14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 - ], - r5: &[ - 0, 1, 2, 3, 4, 5, 4, 6, 4, 4, 7, 8, 9, 10, 11, 12, 2, 2, 13, 14, 15, 16, 4, 4, 2, 2, 2, - 2, 17, 18, 4, 4, 19, 20, 21, 22, 23, 4, 24, 4, 25, 26, 27, 28, 29, 30, 31, 4, 2, 32, 33, - 33, 34, 4, 4, 4, 4, 4, 4, 4, 35, 36, 4, 37, 2, 38, 3, 39, 40, 41, 2, 42, 43, 4, 44, 45, - 46, 47, 4, 4, 2, 48, 2, 49, 4, 4, 50, 51, 2, 52, 53, 54, 55, 4, 4, 4, 3, 4, 56, 57, 4, - 4, 58, 59, 60, 61, 62, 53, 4, 4, 4, 4, 63, 64, 65, 4, 66, 67, 68, 4, 4, 4, 4, 37, 4, 4, - 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 4, 2, 70, 2, 2, 2, 71, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 70, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 72, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 2, 2, 2, 2, 2, 2, 2, 2, 53, 73, 4, 74, 17, 75, 76, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, - 4, 4, 2, 77, 78, 79, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 80, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 21, 81, 2, 2, 2, 2, - 2, 82, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 83, 84, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 85, 86, 4, 4, 87, 4, 4, 4, 4, 4, 4, 2, 88, 89, 90, 91, 92, 2, 2, 2, 2, 93, 94, 95, - 96, 97, 98, 4, 4, 4, 4, 4, 4, 4, 4, 99, 100, 101, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 102, 4, 4, 4, 103, 104, 4, 4, 4, 4, 4, 105, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 106, 2, 107, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 108, 109, 110, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 111, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 11, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 112, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 113, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 114, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 115, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 - ], - r6: &[ - 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, - 0x0000000000000000, 0x001fffffffffffff, 0x2000000000000000, 0xffffffff1fffffff, - 0x000000010001ffff, 0xffffe000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, - 0x00000000003eff0f, 0xffff03ff3fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, - 0x0000000fffffffff, 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, - 0x007fffff003fffff, 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, - 0xc0ffffffffffffff, 0x873ffffffeeff06f, 0x1fffffff00000000, 0x000000001fffffff, - 0x0000007ffffffeff, 0x003fffffffffffff, 0x0007ffff003fffff, 0x000000000003ffff, - 0x00000000000001ff, 0x0007ffffffffffff, 0x03ff00ffffffffff, 0xffff00801fffffff, - 0x000000000001ffff, 0x007fffff00000000, 0x8000ffc00000007f, 0x03ff01ffffff0000, - 0xffdfffffffffffff, 0x004fffffffff0070, 0x0000000017ff1e1f, 0x40fffffffffbffff, - 0xffff01ffbfffbd7f, 0x03ff07ffffffffff, 0xfbedfdfffff99fef, 0x001f1fcfe081399f, - 0x00000000c3ff07ff, 0x0000000003ff00bf, 0xff3fffffffffffff, 0x000000003f000001, - 0x0000000003ff0011, 0x01ffffffffffffff, 0x00000000000003ff, 0x03ff0fffe7ffffff, - 0xffffffff00000000, 0x800003ffffffffff, 0xfffffcff00000000, 0x0000001bfcffffff, - 0x7fffffffffffffff, 0xffffffffffff0080, 0x0000000023ffffff, 0xff7ffffffffffdff, - 0xfffc000003ff0001, 0x007ffefffffcffff, 0xb47ffffffffffb7f, 0xfffffdbf03ff00ff, - 0x000003ff01fb7fff, 0x0000000003ffffff, 0x00007fffffffffff, 0x000000000000000f, - 0x000000000000007f, 0x000003ff7fffffff, 0x001f3fffffff0000, 0xe0fffff803ff000f, - 0x000000000000ffff, 0xffffffffffff87ff, 0x00000000ffff80ff, 0x0000000b00000000, - 0x00ffffffffffffff, 0xffff00f000070000, 0x0fffffffffffffff, 0x1fff07ffffffffff, - 0x0000000063ff01ff, 0xf807e3e000000000, 0x00003c0000000fe7, 0x000000000000001c, - 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, - 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, - 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0xffffffffffffcff7, 0xf87fffffffffffff, - 0x00201fffffffffff, 0x0000fffef8000010, 0x000007dbf9ffff7f, 0x3fff1fffffffffff, - 0x00000000000043ff, 0x03ffffffffffffff, 0x00000000007f001f, 0x0000000003ff0fff, - 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, - 0xffff0003ffffffff, 0x00000001ffffffff, 0x000000003fffffff, 0x0000ffffffffffff - ], - }; - - pub fn XID_Continue(c: char) -> bool { - XID_Continue_table.lookup(c) - } - - const XID_Start_table: &super::BoolTrie = &super::BoolTrie { - r1: [ - 0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff, - 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, - 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0000501f0003ffc3, - 0x0000000000000000, 0xb8df000000000000, 0xfffffffbffffd740, 0xffbfffffffffffff, - 0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffffffffc03, 0xffffffffffffffff, - 0xfffeffffffffffff, 0xffffffff027fffff, 0x00000000000001ff, 0x000787ffffff0000, - 0xffffffff00000000, 0xfffec000000007ff, 0xffffffffffffffff, 0x9c00c060002fffff, - 0x0000fffffffd0000, 0xffffffffffffe000, 0x0002003fffffffff, 0x043007fffffffc00 - ], - r2: [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 23, 25, 26, 27, 28, 29, 3, 30, 31, 32, 33, 34, 34, 34, 34, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 34, 34, 34, 34, 34, 34, 34, 34, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 3, 61, 62, 63, 64, 65, 66, 67, 68, 34, 34, 34, 3, 34, 34, - 34, 34, 69, 70, 71, 72, 3, 73, 74, 3, 75, 76, 77, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 78, - 79, 34, 80, 81, 82, 83, 84, 3, 3, 3, 3, 3, 3, 3, 3, 85, 42, 86, 87, 88, 34, 89, 90, 3, - 3, 3, 3, 3, 3, 3, 3, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 53, 3, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 91, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 92, 93, 34, 34, 34, 34, 94, - 95, 96, 91, 97, 34, 98, 99, 100, 48, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 34, 113, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 114, 115, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 34, 34, 34, 34, 34, - 116, 34, 117, 118, 119, 120, 121, 34, 122, 34, 34, 123, 124, 125, 126, 3, 127, 34, 128, - 129, 130, 131, 132 - ], - r3: &[ - 0x00000110043fffff, 0x000007ff01ffffff, 0x3fdfffff00000000, 0x0000000000000000, - 0x23fffffffffffff0, 0xfffe0003ff010000, 0x23c5fdfffff99fe1, 0x10030003b0004000, - 0x036dfdfffff987e0, 0x001c00005e000000, 0x23edfdfffffbbfe0, 0x0200000300010000, - 0x23edfdfffff99fe0, 0x00020003b0000000, 0x03ffc718d63dc7e8, 0x0000000000010000, - 0x23fffdfffffddfe0, 0x0000000307000000, 0x23effdfffffddfe1, 0x0006000340000000, - 0x27fffffffffddfe0, 0xfc00000380704000, 0x2ffbfffffc7fffe0, 0x000000000000007f, - 0x0005fffffffffffe, 0x2005ffaffffff7d6, 0x00000000f000005f, 0x0000000000000001, - 0x00001ffffffffeff, 0x0000000000001f00, 0x800007ffffffffff, 0xffe1c0623c3f0000, - 0xffffffff00004003, 0xf7ffffffffff20bf, 0xffffffffffffffff, 0xffffffff3d7f3dff, - 0x7f3dffffffff3dff, 0xffffffffff7fff3d, 0xffffffffff3dffff, 0x0000000007ffffff, - 0xffffffff0000ffff, 0x3f3fffffffffffff, 0xfffffffffffffffe, 0xffff9fffffffffff, - 0xffffffff07fffffe, 0x01ffc7ffffffffff, 0x0003ffff0003dfff, 0x0001dfff0003ffff, - 0x000fffffffffffff, 0x0000000010800000, 0xffffffff00000000, 0x01ffffffffffffff, - 0xffff05ffffffffff, 0x003fffffffffffff, 0x000000007fffffff, 0x001f3fffffff0000, - 0xffff0fffffffffff, 0x00000000000003ff, 0xffffffff007fffff, 0x00000000001fffff, - 0x0000008000000000, 0x000fffffffffffe0, 0x0000000000000fe0, 0xfc00c001fffffff8, - 0x0000003fffffffff, 0x0000000fffffffff, 0x3ffffffffc00e000, 0xe7ffffffffff01ff, - 0x046fde0000000000, 0xffffffff3f3fffff, 0x3fffffffaaff3f3f, 0x5fdfffffffffffff, - 0x1fdc1fff0fcf1fdc, 0x8002000000000000, 0x000000001fff0000, 0xf3fffd503f2ffc84, - 0xffffffff000043e0, 0x00000000000001ff, 0xffff7fffffffffff, 0xffffffff7fffffff, - 0x000c781fffffffff, 0xffff20bfffffffff, 0x000080ffffffffff, 0x7f7f7f7f007fffff, - 0x000000007f7f7f7f, 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, - 0xfffeffffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, 0x0000ffffffffffff, - 0x0000000000001fff, 0x3fffffffffff0000, 0x00000c00ffff1fff, 0x80007fffffffffff, - 0xffffffff3fffffff, 0xfffffffcff800000, 0xfffffffffffff9ff, 0xff8000000000007c, - 0x00000007fffff7bb, 0x000ffffffffffffc, 0x68fc000000000000, 0xffff003ffffffc00, - 0x1fffffff0000007f, 0x0007fffffffffff0, 0x7c00ffdf00008000, 0x000001ffffffffff, - 0xc47fffff00000ff7, 0x3e62ffffffffffff, 0x001c07ff38000005, 0xffff7f7f007e7e7e, - 0xffff00fff7ffffff, 0x00000007ffffffff, 0xffff000fffffffff, 0x0ffffffffffff87f, - 0xffff3fffffffffff, 0x0000000003ffffff, 0x5f7ffdffa0f8007f, 0xffffffffffffffdb, - 0x0003ffffffffffff, 0xfffffffffff80000, 0xfffffff03fffffff, 0x3fffffffffffffff, - 0xffffffffffff0000, 0xfffffffffffcffff, 0x03ff0000000000ff, 0xaa8a000000000000, - 0x1fffffffffffffff, 0x07fffffe00000000, 0xffffffc007fffffe, 0x7fffffff3fffffff, - 0x000000001cfcfcfc - ], - r4: [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13, - 14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 - ], - r5: &[ - 0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 13, 14, 15, 4, 4, 2, 2, 2, - 2, 16, 17, 4, 4, 18, 19, 20, 21, 22, 4, 23, 4, 24, 25, 26, 27, 28, 29, 30, 4, 2, 31, 32, - 32, 15, 4, 4, 4, 4, 4, 4, 4, 33, 34, 4, 35, 36, 4, 37, 38, 39, 40, 41, 42, 43, 4, 44, - 20, 45, 46, 4, 4, 5, 47, 48, 49, 4, 4, 50, 51, 48, 52, 53, 4, 54, 4, 4, 4, 55, 4, 56, - 57, 4, 4, 58, 59, 60, 61, 62, 63, 4, 4, 4, 4, 64, 65, 66, 4, 67, 68, 69, 4, 4, 4, 4, 70, - 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 71, 4, 2, 50, 2, 2, 2, 72, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 50, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 73, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 63, 20, 4, 74, 48, 75, 66, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 2, 4, 4, 2, 76, 77, 78, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 79, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 20, 80, 2, - 2, 2, 2, 2, 81, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 82, 83, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 84, 85, 86, 87, 88, 2, 2, 2, 2, 89, 90, - 91, 92, 93, 94, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 95, 96, 4, 4, 4, 4, 4, 55, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 97, 2, 98, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 99, 100, 101, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 102, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 103, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 104, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 105, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 - ], - r6: &[ - 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, - 0x0000000000000000, 0x001fffffffffffff, 0xffffffff1fffffff, 0x000000000001ffff, - 0xffffe000ffffffff, 0x003fffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, - 0xffff00003fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff, - 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, - 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff, - 0x003ffffffeef0001, 0x1fffffff00000000, 0x000000001fffffff, 0x0000001ffffffeff, - 0x003fffffffffffff, 0x0007ffff003fffff, 0x000000000003ffff, 0x00000000000001ff, - 0x0007ffffffffffff, 0xffff00801fffffff, 0x000000000000003f, 0x007fffff00000000, - 0x00fffffffffffff8, 0x0000fffffffffff8, 0x000001ffffff0000, 0x0000007ffffffff8, - 0x0047ffffffff0010, 0x0007fffffffffff8, 0x000000001400001e, 0x00000ffffffbffff, - 0xffff01ffbfffbd7f, 0x23edfdfffff99fe0, 0x00000003e0010000, 0x0000000080000780, - 0x0000ffffffffffff, 0x00000000000000b0, 0x00007fffffffffff, 0x000000000f000000, - 0x0000000000000010, 0x010007ffffffffff, 0x0000000007ffffff, 0x00000fffffffffff, - 0xffffffff00000000, 0x80000000ffffffff, 0xfffffcff00000000, 0x0000000a0001ffff, - 0x0407fffffffff801, 0xfffffffff0010000, 0x00000000200003ff, 0x01ffffffffffffff, - 0x00007ffffffffdff, 0xfffc000000000001, 0x000000000000ffff, 0x0001fffffffffb7f, - 0xfffffdbf00000040, 0x00000000010003ff, 0x0007ffff00000000, 0x0000000003ffffff, - 0x000000000000000f, 0x000000000000007f, 0x00003fffffff0000, 0xe0fffff80000000f, - 0x00000000000107ff, 0x00000000fff80000, 0x0000000b00000000, 0x00ffffffffffffff, - 0xffff00f000070000, 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000003ff01ff, - 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, - 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, - 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0x0000000000000ff7, 0x3f801fffffffffff, - 0x0000000000004000, 0x000000000000001f, 0x000000000000080f, 0x0af7fe96ffffffef, - 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, 0xffff0003ffffffff, - 0x00000001ffffffff, 0x000000003fffffff - ], - }; - - pub fn XID_Start(c: char) -> bool { - XID_Start_table.lookup(c) - } - } pub(crate) mod property { - const Pattern_White_Space_table: &super::SmallBoolTrie = &super::SmallBoolTrie { - r1: &[ - 0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 - ], - r2: &[ - 0x0000000100003e00, 0x0000000000000000, 0x0000000000000020, 0x000003000000c000 - ], - }; - - pub fn Pattern_White_Space(c: char) -> bool { - Pattern_White_Space_table.lookup(c) - } - const White_Space_table: &super::SmallBoolTrie = &super::SmallBoolTrie { r1: &[ 0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, diff --git a/src/libcore/unicode/unicode.py b/src/libcore/unicode/unicode.py index 6de5d9e033b93..89894f7932d79 100755 --- a/src/libcore/unicode/unicode.py +++ b/src/libcore/unicode/unicode.py @@ -728,7 +728,7 @@ def generate_property_module(mod, grouped_categories, category_subset): yield "pub(crate) mod %s {\n" % mod for cat in sorted(category_subset): - if cat in ("Cc", "White_Space", "Pattern_White_Space"): + if cat in ("Cc", "White_Space"): generator = generate_small_bool_trie("%s_table" % cat, grouped_categories[cat]) else: generator = generate_bool_trie("%s_table" % cat, grouped_categories[cat]) @@ -841,19 +841,18 @@ def main(): unicode_data = load_unicode_data(get_path(UnicodeFiles.UNICODE_DATA)) load_special_casing(get_path(UnicodeFiles.SPECIAL_CASING), unicode_data) - want_derived = {"XID_Start", "XID_Continue", "Alphabetic", "Lowercase", "Uppercase", + want_derived = {"Alphabetic", "Lowercase", "Uppercase", "Cased", "Case_Ignorable", "Grapheme_Extend"} derived = load_properties(get_path(UnicodeFiles.DERIVED_CORE_PROPERTIES), want_derived) props = load_properties(get_path(UnicodeFiles.PROPS), - {"White_Space", "Join_Control", "Noncharacter_Code_Point", - "Pattern_White_Space"}) + {"White_Space", "Join_Control", "Noncharacter_Code_Point"}) # Category tables for (name, categories, category_subset) in ( ("general_category", unicode_data.general_categories, ["N", "Cc"]), ("derived_property", derived, want_derived), - ("property", props, ["White_Space", "Pattern_White_Space"]) + ("property", props, ["White_Space"]) ): for fragment in generate_property_module(name, categories, category_subset): buf.write(fragment) diff --git a/src/libfmt_macros/Cargo.toml b/src/libfmt_macros/Cargo.toml index 82a9e34c065b1..fff4ec716dfda 100644 --- a/src/libfmt_macros/Cargo.toml +++ b/src/libfmt_macros/Cargo.toml @@ -10,4 +10,4 @@ path = "lib.rs" [dependencies] syntax_pos = { path = "../libsyntax_pos" } - +rustc_lexer = { path = "../librustc_lexer" } diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 985abaf2c1bd5..98fa2bd061516 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -23,6 +23,7 @@ use std::string; use std::iter; use syntax_pos::{InnerSpan, Symbol}; +use rustc_lexer::character_properties::{is_id_start, is_id_continue}; #[derive(Copy, Clone)] struct InnerOffset(usize); @@ -597,12 +598,11 @@ impl<'a> Parser<'a> { } } - /// Parses a word starting at the current position. A word is considered to - /// be an alphabetic character followed by any number of alphanumeric - /// characters. + /// Parses a word starting at the current position. A word is the same as + /// Rust identifier, except that it can't start with `_` character. fn word(&mut self) -> &'a str { let start = match self.cur.peek() { - Some(&(pos, c)) if c.is_xid_start() => { + Some(&(pos, c)) if c != '_' && is_id_start(c) => { self.cur.next(); pos } @@ -611,7 +611,7 @@ impl<'a> Parser<'a> { } }; while let Some(&(pos, c)) = self.cur.peek() { - if c.is_xid_continue() { + if is_id_continue(c) { self.cur.next(); } else { return &self.input[start..pos]; diff --git a/src/librustc_lexer/Cargo.toml b/src/librustc_lexer/Cargo.toml index 0dbcda618ecac..675d3065c5b28 100644 --- a/src/librustc_lexer/Cargo.toml +++ b/src/librustc_lexer/Cargo.toml @@ -4,12 +4,12 @@ name = "rustc_lexer" version = "0.1.0" edition = "2018" -# Note that this crate purposefully does not depend on other rustc crates -[dependencies] -unicode-xid = { version = "0.1.0", optional = true } - # Note: do not remove this blank `[lib]` section. # This will be used when publishing this crate as `rustc-ap-rustc_lexer`. [lib] doctest = false name = "rustc_lexer" + +# Note that this crate purposefully does not depend on other rustc crates +[dependencies] +unicode-xid = "0.2.0" diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs index 41b47befaf141..26e5e6fc8c4b1 100644 --- a/src/librustc_lexer/src/lib.rs +++ b/src/librustc_lexer/src/lib.rs @@ -1,6 +1,5 @@ -// We want to be able to build this crate with a stable compiler, so feature -// flags should be optional. -#![cfg_attr(not(feature = "unicode-xid"), feature(unicode_internals))] +// We want to be able to build this crate with a stable compiler, so no +// `#![feature]` attributes should be added. mod cursor; pub mod unescape; @@ -507,23 +506,39 @@ impl Cursor<'_> { } pub mod character_properties { - // this is Pattern_White_Space - #[cfg(feature = "unicode-xid")] + // See [UAX #31](http://unicode.org/reports/tr31) for definitions of these + // classes. + + // This is Pattern_White_Space. + // + // Note that this set is stable (ie, it doesn't change with different + // Unicode versions), so it's ok to just hard-code the values. pub fn is_whitespace(c: char) -> bool { match c { - '\u{0009}' | '\u{000A}' | '\u{000B}' | '\u{000C}' | '\u{000D}' | '\u{0020}' - | '\u{0085}' | '\u{200E}' | '\u{200F}' | '\u{2028}' | '\u{2029}' => true, + // Usual ASCII suspects + | '\u{0009}' // \t + | '\u{000A}' // \n + | '\u{000B}' // vertical tab + | '\u{000C}' // form feed + | '\u{000D}' // \r + | '\u{0020}' // space + + // NEXT LINE from latin1 + | '\u{0085}' + + // Bidi markers + | '\u{200E}' // LEFT-TO-RIGHT MARK + | '\u{200F}' // RIGHT-TO-LEFT MARK + + // Dedicated whitespace characters from Unicode + | '\u{2028}' // LINE SEPARATOR + | '\u{2029}' // PARAGRAPH SEPARATOR + => true, _ => false, } } - #[cfg(not(feature = "unicode-xid"))] - pub fn is_whitespace(c: char) -> bool { - core::unicode::property::Pattern_White_Space(c) - } - - // this is XID_Start OR '_' (which formally is not a XID_Start) - #[cfg(feature = "unicode-xid")] + // This is XID_Start OR '_' (which formally is not a XID_Start). pub fn is_id_start(c: char) -> bool { ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') @@ -531,16 +546,7 @@ pub mod character_properties { || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_start(c)) } - #[cfg(not(feature = "unicode-xid"))] - pub fn is_id_start(c: char) -> bool { - ('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z') - || c == '_' - || (c > '\x7f' && c.is_xid_start()) - } - - // this is XID_Continue - #[cfg(feature = "unicode-xid")] + // This is XID_Continue. pub fn is_id_continue(c: char) -> bool { ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') @@ -548,13 +554,4 @@ pub mod character_properties { || c == '_' || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(c)) } - - #[cfg(not(feature = "unicode-xid"))] - pub fn is_id_continue(c: char) -> bool { - ('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z') - || ('0' <= c && c <= '9') - || c == '_' - || (c > '\x7f' && c.is_xid_continue()) - } } diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 21008c737289f..4e68708adfc3e 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -20,6 +20,7 @@ rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } +rustc_lexer = { path = "../librustc_lexer" } rustc_serialize = { path = "../libserialize", package = "serialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index f10ff71b15e68..abcb70b719741 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -1,8 +1,7 @@ -use core::unicode::property::Pattern_White_Space; - use rustc::mir::*; use rustc::ty; use rustc_errors::{DiagnosticBuilder,Applicability}; +use rustc_lexer::character_properties::is_whitespace; use syntax_pos::Span; use crate::borrow_check::MirBorrowckCtxt; @@ -526,7 +525,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let suggestion; let to_remove; if pat_snippet.starts_with("mut") - && pat_snippet["mut".len()..].starts_with(Pattern_White_Space) + && pat_snippet["mut".len()..].starts_with(is_whitespace) { suggestion = pat_snippet["mut".len()..].trim_start(); to_remove = "&mut"; diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 5a5534922aa8a..32bf82c8bcde3 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -1,4 +1,4 @@ -use core::unicode::property::Pattern_White_Space; +use rustc_lexer::character_properties::is_whitespace; use rustc::hir; use rustc::hir::Node; use rustc::mir::{self, BindingForm, ClearCrossCrate, Local, Location, Body}; @@ -715,7 +715,7 @@ fn annotate_struct_field( fn suggest_ref_mut(tcx: TyCtxt<'_>, binding_span: Span) -> Option { let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).ok()?; if hi_src.starts_with("ref") - && hi_src["ref".len()..].starts_with(Pattern_White_Space) + && hi_src["ref".len()..].starts_with(is_whitespace) { let replacement = format!("ref mut{}", &hi_src["ref".len()..]); Some(replacement) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index dfa0db0d23b74..301946733dc55 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -33,6 +33,7 @@ extern crate rustc_interface; extern crate rustc_metadata; extern crate rustc_target; extern crate rustc_typeck; +extern crate rustc_lexer; extern crate serialize; extern crate syntax; extern crate syntax_pos; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index adcc9930b6c33..1105e47d74824 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -4,6 +4,7 @@ use rustc::hir; use rustc::hir::intravisit; use rustc::session::{self, config, DiagnosticOutput}; use rustc::util::common::ErrorReported; +use rustc_lexer::character_properties::{is_id_start, is_id_continue}; use syntax::ast; use syntax::with_globals; use syntax::source_map::SourceMap; @@ -763,8 +764,8 @@ impl Tester for Collector { // We use these headings as test names, so it's good if // they're valid identifiers. let name = name.chars().enumerate().map(|(i, c)| { - if (i == 0 && c.is_xid_start()) || - (i != 0 && c.is_xid_continue()) { + if (i == 0 && is_id_start(c)) || + (i != 0 && is_id_continue(c)) { c } else { '_' diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs index 1a26b17dac782..35feb6680f9cc 100644 --- a/src/libsyntax/ext/proc_macro_server.rs +++ b/src/libsyntax/ext/proc_macro_server.rs @@ -6,6 +6,7 @@ use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint} use errors::{Diagnostic, DiagnosticBuilder}; use rustc_data_structures::sync::Lrc; +use rustc_lexer::character_properties::{is_id_start, is_id_continue}; use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span}; use syntax_pos::symbol::{kw, sym, Symbol}; @@ -322,8 +323,7 @@ impl Ident { fn is_valid(string: &str) -> bool { let mut chars = string.chars(); if let Some(start) = chars.next() { - (start == '_' || start.is_xid_start()) - && chars.all(|cont| cont == '_' || cont.is_xid_continue()) + is_id_start(start) && chars.all(is_id_continue) } else { false } diff --git a/src/libsyntax_ext/Cargo.toml b/src/libsyntax_ext/Cargo.toml index 73310df305b32..791ee94b4fa77 100644 --- a/src/libsyntax_ext/Cargo.toml +++ b/src/libsyntax_ext/Cargo.toml @@ -18,3 +18,4 @@ rustc_target = { path = "../librustc_target" } smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } +rustc_lexer = { path = "../librustc_lexer" } From 78908f2e0963ceed461e9961020226d3e12c5978 Mon Sep 17 00:00:00 2001 From: Tim Vermeulen Date: Tue, 3 Sep 2019 11:56:08 +0200 Subject: [PATCH 460/618] Override `StepBy::{try_fold, try_rfold}` --- src/libcore/iter/adapters/mod.rs | 44 +++++++++++++++++++++++++++++++- src/libcore/tests/iter.rs | 35 +++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index f50781890ab22..7c9dde81a48fb 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -5,7 +5,7 @@ use crate::usize; use crate::intrinsics; use super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen}; -use super::LoopState; +use super::{LoopState, from_fn}; mod chain; mod flatten; @@ -541,6 +541,26 @@ impl Iterator for StepBy where I: Iterator { self.iter.nth(nth - 1); } } + + fn try_fold(&mut self, mut acc: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + #[inline] + fn nth(iter: &mut I, step: usize) -> impl FnMut() -> Option + '_ { + move || iter.nth(step) + } + + if self.first_take { + self.first_take = false; + match self.iter.next() { + None => return Try::from_ok(acc), + Some(x) => acc = f(acc, x)?, + } + } + from_fn(nth(&mut self.iter, self.step)).try_fold(acc, f) + } } impl StepBy where I: ExactSizeIterator { @@ -574,6 +594,28 @@ impl DoubleEndedIterator for StepBy where I: DoubleEndedIterator + ExactSi .saturating_add(self.next_back_index()); self.iter.nth_back(n) } + + fn try_rfold(&mut self, init: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + #[inline] + fn nth_back( + iter: &mut I, + step: usize, + ) -> impl FnMut() -> Option + '_ { + move || iter.nth_back(step) + } + + match self.next_back() { + None => Try::from_ok(init), + Some(x) => { + let acc = f(init, x)?; + from_fn(nth_back(&mut self.iter, self.step)).try_fold(acc, f) + } + } + } } // StepBy can only make the iterator shorter, so the len will still fit. diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 3a4f76852a0d7..f52899b500a3a 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -329,6 +329,23 @@ fn test_iterator_step_by_nth_overflow() { assert_eq!(it.0, (usize::MAX as Bigger) * 1); } +#[test] +fn test_iterator_step_by_nth_try_fold() { + let mut it = (0..).step_by(10); + assert_eq!(it.try_fold(0, i8::checked_add), None); + assert_eq!(it.next(), Some(60)); + assert_eq!(it.try_fold(0, i8::checked_add), None); + assert_eq!(it.next(), Some(90)); + + let mut it = (100..).step_by(10); + assert_eq!(it.try_fold(50, i8::checked_add), None); + assert_eq!(it.next(), Some(110)); + + let mut it = (100..=100).step_by(10); + assert_eq!(it.next(), Some(100)); + assert_eq!(it.try_fold(0, i8::checked_add), Some(0)); +} + #[test] fn test_iterator_step_by_nth_back() { let mut it = (0..16).step_by(5); @@ -354,6 +371,24 @@ fn test_iterator_step_by_nth_back() { assert_eq!(it().nth_back(42), None); } +#[test] +fn test_iterator_step_by_nth_try_rfold() { + let mut it = (0..100).step_by(10); + assert_eq!(it.try_rfold(0, i8::checked_add), None); + assert_eq!(it.next_back(), Some(70)); + assert_eq!(it.next(), Some(0)); + assert_eq!(it.try_rfold(0, i8::checked_add), None); + assert_eq!(it.next_back(), Some(30)); + + let mut it = (0..100).step_by(10); + assert_eq!(it.try_rfold(50, i8::checked_add), None); + assert_eq!(it.next_back(), Some(80)); + + let mut it = (100..=100).step_by(10); + assert_eq!(it.next_back(), Some(100)); + assert_eq!(it.try_fold(0, i8::checked_add), Some(0)); +} + #[test] #[should_panic] fn test_iterator_step_by_zero() { From 206fe8e1c37d55d0bf3a82baaa23eb5fb148880b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 4 Sep 2019 13:16:36 +0300 Subject: [PATCH 461/618] flatten rustc_lexer::character_properties module On the call site, `rustc_lexer::is_whitespace` reads much better than `character_properties::is_whitespace`. --- src/libfmt_macros/lib.rs | 5 +- src/librustc_lexer/src/lib.rs | 135 +++++++++--------- src/librustc_mir/borrow_check/move_errors.rs | 3 +- .../borrow_check/mutability_errors.rs | 3 +- src/librustdoc/test.rs | 5 +- src/libsyntax/ext/proc_macro_server.rs | 3 +- src/libsyntax/tests.rs | 14 +- 7 files changed, 82 insertions(+), 86 deletions(-) diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 98fa2bd061516..f9c1be20b8bc1 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -23,7 +23,6 @@ use std::string; use std::iter; use syntax_pos::{InnerSpan, Symbol}; -use rustc_lexer::character_properties::{is_id_start, is_id_continue}; #[derive(Copy, Clone)] struct InnerOffset(usize); @@ -602,7 +601,7 @@ impl<'a> Parser<'a> { /// Rust identifier, except that it can't start with `_` character. fn word(&mut self) -> &'a str { let start = match self.cur.peek() { - Some(&(pos, c)) if c != '_' && is_id_start(c) => { + Some(&(pos, c)) if c != '_' && rustc_lexer::is_id_start(c) => { self.cur.next(); pos } @@ -611,7 +610,7 @@ impl<'a> Parser<'a> { } }; while let Some(&(pos, c)) = self.cur.peek() { - if is_id_continue(c) { + if rustc_lexer::is_id_continue(c) { self.cur.next(); } else { return &self.input[start..pos]; diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs index 26e5e6fc8c4b1..30a5175d8cdb0 100644 --- a/src/librustc_lexer/src/lib.rs +++ b/src/librustc_lexer/src/lib.rs @@ -102,6 +102,62 @@ pub fn tokenize(mut input: &str) -> impl Iterator + '_ { }) } +// See [UAX #31](http://unicode.org/reports/tr31) for definitions of these +// classes. + +/// True if `c` is considered a whitespace according to Rust language definition. +pub fn is_whitespace(c: char) -> bool { + // This is Pattern_White_Space. + // + // Note that this set is stable (ie, it doesn't change with different + // Unicode versions), so it's ok to just hard-code the values. + + match c { + // Usual ASCII suspects + | '\u{0009}' // \t + | '\u{000A}' // \n + | '\u{000B}' // vertical tab + | '\u{000C}' // form feed + | '\u{000D}' // \r + | '\u{0020}' // space + + // NEXT LINE from latin1 + | '\u{0085}' + + // Bidi markers + | '\u{200E}' // LEFT-TO-RIGHT MARK + | '\u{200F}' // RIGHT-TO-LEFT MARK + + // Dedicated whitespace characters from Unicode + | '\u{2028}' // LINE SEPARATOR + | '\u{2029}' // PARAGRAPH SEPARATOR + => true, + _ => false, + } +} + +/// True if `c` is valid as a first character of an identifier. +pub fn is_id_start(c: char) -> bool { + // This is XID_Start OR '_' (which formally is not a XID_Start). + // We also add fast-path for ascii idents + ('a' <= c && c <= 'z') + || ('A' <= c && c <= 'Z') + || c == '_' + || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_start(c)) +} + +/// True if `c` is valid as a non-first character of an identifier. +pub fn is_id_continue(c: char) -> bool { + // This is exactly XID_Continue. + // We also add fast-path for ascii idents + ('a' <= c && c <= 'z') + || ('A' <= c && c <= 'Z') + || ('0' <= c && c <= '9') + || c == '_' + || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(c)) +} + + impl Cursor<'_> { fn advance_token(&mut self) -> Token { let first_char = self.bump().unwrap(); @@ -111,9 +167,9 @@ impl Cursor<'_> { '*' => self.block_comment(), _ => Slash, }, - c if character_properties::is_whitespace(c) => self.whitespace(), + c if is_whitespace(c) => self.whitespace(), 'r' => match (self.nth_char(0), self.nth_char(1)) { - ('#', c1) if character_properties::is_id_start(c1) => self.raw_ident(), + ('#', c1) if is_id_start(c1) => self.raw_ident(), ('#', _) | ('"', _) => { let (n_hashes, started, terminated) = self.raw_double_quoted_string(); let suffix_start = self.len_consumed(); @@ -158,7 +214,7 @@ impl Cursor<'_> { } _ => self.ident(), }, - c if character_properties::is_id_start(c) => self.ident(), + c if is_id_start(c) => self.ident(), c @ '0'..='9' => { let literal_kind = self.number(c); let suffix_start = self.len_consumed(); @@ -246,8 +302,8 @@ impl Cursor<'_> { } fn whitespace(&mut self) -> TokenKind { - debug_assert!(character_properties::is_whitespace(self.prev())); - while character_properties::is_whitespace(self.nth_char(0)) { + debug_assert!(is_whitespace(self.prev())); + while is_whitespace(self.nth_char(0)) { self.bump(); } Whitespace @@ -257,19 +313,19 @@ impl Cursor<'_> { debug_assert!( self.prev() == 'r' && self.nth_char(0) == '#' - && character_properties::is_id_start(self.nth_char(1)) + && is_id_start(self.nth_char(1)) ); self.bump(); self.bump(); - while character_properties::is_id_continue(self.nth_char(0)) { + while is_id_continue(self.nth_char(0)) { self.bump(); } RawIdent } fn ident(&mut self) -> TokenKind { - debug_assert!(character_properties::is_id_start(self.prev())); - while character_properties::is_id_continue(self.nth_char(0)) { + debug_assert!(is_id_start(self.prev())); + while is_id_continue(self.nth_char(0)) { self.bump(); } Ident @@ -314,7 +370,7 @@ impl Cursor<'_> { // integer literal followed by field/method access or a range pattern // (`0..2` and `12.foo()`) '.' if self.nth_char(1) != '.' - && !character_properties::is_id_start(self.nth_char(1)) => + && !is_id_start(self.nth_char(1)) => { // might have stuff after the ., and if it does, it needs to start // with a number @@ -344,7 +400,7 @@ impl Cursor<'_> { fn lifetime_or_char(&mut self) -> TokenKind { debug_assert!(self.prev() == '\''); let mut starts_with_number = false; - if (character_properties::is_id_start(self.nth_char(0)) + if (is_id_start(self.nth_char(0)) || self.nth_char(0).is_digit(10) && { starts_with_number = true; true @@ -352,7 +408,7 @@ impl Cursor<'_> { && self.nth_char(1) != '\'' { self.bump(); - while character_properties::is_id_continue(self.nth_char(0)) { + while is_id_continue(self.nth_char(0)) { self.bump(); } @@ -494,64 +550,13 @@ impl Cursor<'_> { } fn eat_literal_suffix(&mut self) { - if !character_properties::is_id_start(self.nth_char(0)) { + if !is_id_start(self.nth_char(0)) { return; } self.bump(); - while character_properties::is_id_continue(self.nth_char(0)) { + while is_id_continue(self.nth_char(0)) { self.bump(); } } } - -pub mod character_properties { - // See [UAX #31](http://unicode.org/reports/tr31) for definitions of these - // classes. - - // This is Pattern_White_Space. - // - // Note that this set is stable (ie, it doesn't change with different - // Unicode versions), so it's ok to just hard-code the values. - pub fn is_whitespace(c: char) -> bool { - match c { - // Usual ASCII suspects - | '\u{0009}' // \t - | '\u{000A}' // \n - | '\u{000B}' // vertical tab - | '\u{000C}' // form feed - | '\u{000D}' // \r - | '\u{0020}' // space - - // NEXT LINE from latin1 - | '\u{0085}' - - // Bidi markers - | '\u{200E}' // LEFT-TO-RIGHT MARK - | '\u{200F}' // RIGHT-TO-LEFT MARK - - // Dedicated whitespace characters from Unicode - | '\u{2028}' // LINE SEPARATOR - | '\u{2029}' // PARAGRAPH SEPARATOR - => true, - _ => false, - } - } - - // This is XID_Start OR '_' (which formally is not a XID_Start). - pub fn is_id_start(c: char) -> bool { - ('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z') - || c == '_' - || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_start(c)) - } - - // This is XID_Continue. - pub fn is_id_continue(c: char) -> bool { - ('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z') - || ('0' <= c && c <= '9') - || c == '_' - || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(c)) - } -} diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index abcb70b719741..0d13db2f5a413 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -1,7 +1,6 @@ use rustc::mir::*; use rustc::ty; use rustc_errors::{DiagnosticBuilder,Applicability}; -use rustc_lexer::character_properties::is_whitespace; use syntax_pos::Span; use crate::borrow_check::MirBorrowckCtxt; @@ -525,7 +524,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let suggestion; let to_remove; if pat_snippet.starts_with("mut") - && pat_snippet["mut".len()..].starts_with(is_whitespace) + && pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace) { suggestion = pat_snippet["mut".len()..].trim_start(); to_remove = "&mut"; diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 32bf82c8bcde3..8f2ce80aafa22 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -1,4 +1,3 @@ -use rustc_lexer::character_properties::is_whitespace; use rustc::hir; use rustc::hir::Node; use rustc::mir::{self, BindingForm, ClearCrossCrate, Local, Location, Body}; @@ -715,7 +714,7 @@ fn annotate_struct_field( fn suggest_ref_mut(tcx: TyCtxt<'_>, binding_span: Span) -> Option { let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).ok()?; if hi_src.starts_with("ref") - && hi_src["ref".len()..].starts_with(is_whitespace) + && hi_src["ref".len()..].starts_with(rustc_lexer::is_whitespace) { let replacement = format!("ref mut{}", &hi_src["ref".len()..]); Some(replacement) diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 1105e47d74824..000d2843adce3 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -4,7 +4,6 @@ use rustc::hir; use rustc::hir::intravisit; use rustc::session::{self, config, DiagnosticOutput}; use rustc::util::common::ErrorReported; -use rustc_lexer::character_properties::{is_id_start, is_id_continue}; use syntax::ast; use syntax::with_globals; use syntax::source_map::SourceMap; @@ -764,8 +763,8 @@ impl Tester for Collector { // We use these headings as test names, so it's good if // they're valid identifiers. let name = name.chars().enumerate().map(|(i, c)| { - if (i == 0 && is_id_start(c)) || - (i != 0 && is_id_continue(c)) { + if (i == 0 && rustc_lexer::is_id_start(c)) || + (i != 0 && rustc_lexer::is_id_continue(c)) { c } else { '_' diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs index 35feb6680f9cc..544ec789d80a9 100644 --- a/src/libsyntax/ext/proc_macro_server.rs +++ b/src/libsyntax/ext/proc_macro_server.rs @@ -6,7 +6,6 @@ use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint} use errors::{Diagnostic, DiagnosticBuilder}; use rustc_data_structures::sync::Lrc; -use rustc_lexer::character_properties::{is_id_start, is_id_continue}; use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span}; use syntax_pos::symbol::{kw, sym, Symbol}; @@ -323,7 +322,7 @@ impl Ident { fn is_valid(string: &str) -> bool { let mut chars = string.chars(); if let Some(start) = chars.next() { - is_id_start(start) && chars.all(is_id_continue) + rustc_lexer::is_id_start(start) && chars.all(rustc_lexer::is_id_continue) } else { false } diff --git a/src/libsyntax/tests.rs b/src/libsyntax/tests.rs index c472212bc2096..9b90b31f2d2a2 100644 --- a/src/libsyntax/tests.rs +++ b/src/libsyntax/tests.rs @@ -63,7 +63,7 @@ crate fn matches_codepattern(a : &str, b : &str) -> bool { (None, None) => return true, (None, _) => return false, (Some(&a), None) => { - if is_pattern_whitespace(a) { + if rustc_lexer::is_whitespace(a) { break // trailing whitespace check is out of loop for borrowck } else { return false @@ -72,11 +72,11 @@ crate fn matches_codepattern(a : &str, b : &str) -> bool { (Some(&a), Some(&b)) => (a, b) }; - if is_pattern_whitespace(a) && is_pattern_whitespace(b) { + if rustc_lexer::is_whitespace(a) && rustc_lexer::is_whitespace(b) { // skip whitespace for a and b scan_for_non_ws_or_end(&mut a_iter); scan_for_non_ws_or_end(&mut b_iter); - } else if is_pattern_whitespace(a) { + } else if rustc_lexer::is_whitespace(a) { // skip whitespace for a scan_for_non_ws_or_end(&mut a_iter); } else if a == b { @@ -88,20 +88,16 @@ crate fn matches_codepattern(a : &str, b : &str) -> bool { } // check if a has *only* trailing whitespace - a_iter.all(is_pattern_whitespace) + a_iter.all(rustc_lexer::is_whitespace) } /// Advances the given peekable `Iterator` until it reaches a non-whitespace character fn scan_for_non_ws_or_end>(iter: &mut Peekable) { - while iter.peek().copied().map(|c| is_pattern_whitespace(c)) == Some(true) { + while iter.peek().copied().map(|c| rustc_lexer::is_whitespace(c)) == Some(true) { iter.next(); } } -fn is_pattern_whitespace(c: char) -> bool { - rustc_lexer::character_properties::is_whitespace(c) -} - /// Identify a position in the text by the Nth occurrence of a string. struct Position { string: &'static str, From cb84aa4744c7a6120d8311806912240275d04960 Mon Sep 17 00:00:00 2001 From: Shiqing Date: Mon, 2 Sep 2019 21:03:35 +0800 Subject: [PATCH 462/618] Improve searching in rustdoc and add tests --- src/librustdoc/html/static/main.js | 16 ++---- src/test/rustdoc-js-std/vec-new.js | 1 + src/test/rustdoc-js/exact-match.js | 9 +++ src/test/rustdoc-js/exact-match.rs | 68 +++++++++++++++++++++++ src/test/rustdoc-js/module-substring.js | 9 +++ src/test/rustdoc-js/module-substring.rs | 68 +++++++++++++++++++++++ src/test/rustdoc-js/search-short-types.js | 2 + src/test/rustdoc-js/search-short-types.rs | 6 ++ 8 files changed, 169 insertions(+), 10 deletions(-) create mode 100644 src/test/rustdoc-js/exact-match.js create mode 100644 src/test/rustdoc-js/exact-match.rs create mode 100644 src/test/rustdoc-js/module-substring.js create mode 100644 src/test/rustdoc-js/module-substring.rs diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 637c6ef8e8e0b..5cb2456fefdb2 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -547,6 +547,11 @@ if (!DOMTokenList.prototype.remove) { results.sort(function(aaa, bbb) { var a, b; + // sort by exact match with regard to the last word (mismatch goes later) + a = (aaa.word !== val); + b = (bbb.word !== val); + if (a !== b) { return a - b; } + // Sort by non levenshtein results and then levenshtein results by the distance // (less changes required to match means higher rankings) a = (aaa.lev); @@ -558,11 +563,6 @@ if (!DOMTokenList.prototype.remove) { b = (bbb.item.crate !== window.currentCrate); if (a !== b) { return a - b; } - // sort by exact match (mismatch goes later) - a = (aaa.word !== valLower); - b = (bbb.word !== valLower); - if (a !== b) { return a - b; } - // sort by item name length (longer goes later) a = aaa.word.length; b = bbb.word.length; @@ -1028,7 +1028,7 @@ if (!DOMTokenList.prototype.remove) { if (lev > MAX_LEV_DISTANCE) { continue; } else if (lev > 0) { - lev_add = 1; + lev_add = lev / 10; } } @@ -1099,10 +1099,6 @@ if (!DOMTokenList.prototype.remove) { if (index !== -1 || lev <= MAX_LEV_DISTANCE) { if (index !== -1 && paths.length < 2) { lev = 0; - } else if (searchWords[j] === val) { - // Small trick to fix when you're looking for a one letter type - // and there are other short named types. - lev = -1; } if (results[fullId] === undefined) { results[fullId] = { diff --git a/src/test/rustdoc-js-std/vec-new.js b/src/test/rustdoc-js-std/vec-new.js index e4daa5065d233..e1a3256876bde 100644 --- a/src/test/rustdoc-js-std/vec-new.js +++ b/src/test/rustdoc-js-std/vec-new.js @@ -4,5 +4,6 @@ const EXPECTED = { 'others': [ { 'path': 'std::vec::Vec', 'name': 'new' }, { 'path': 'std::vec::Vec', 'name': 'ne' }, + { 'path': 'std::rc::Rc', 'name': 'ne' }, ], }; diff --git a/src/test/rustdoc-js/exact-match.js b/src/test/rustdoc-js/exact-match.js new file mode 100644 index 0000000000000..b0a411bee5829 --- /dev/null +++ b/src/test/rustdoc-js/exact-match.js @@ -0,0 +1,9 @@ +const QUERY = 'si::pc'; + +const EXPECTED = { + 'others': [ + { 'path': 'exact_match::Si', 'name': 'pc' }, + { 'path': 'exact_match::Psi', 'name': 'pc' }, + { 'path': 'exact_match::Si', 'name': 'pa' }, + ], +}; diff --git a/src/test/rustdoc-js/exact-match.rs b/src/test/rustdoc-js/exact-match.rs new file mode 100644 index 0000000000000..2eacc0a358284 --- /dev/null +++ b/src/test/rustdoc-js/exact-match.rs @@ -0,0 +1,68 @@ +macro_rules! imp { + ($name:ident) => { + pub struct $name { + pub op: usize, + } + impl $name { + pub fn op() {} + pub fn cmp() {} + pub fn map() {} + pub fn pop() {} + pub fn ptr() {} + pub fn rpo() {} + pub fn drop() {} + pub fn copy() {} + pub fn zip() {} + pub fn sup() {} + pub fn pa() {} + pub fn pb() {} + pub fn pc() {} + pub fn pd() {} + pub fn pe() {} + pub fn pf() {} + pub fn pg() {} + pub fn ph() {} + pub fn pi() {} + pub fn pj() {} + pub fn pk() {} + pub fn pl() {} + pub fn pm() {} + pub fn pn() {} + pub fn po() {} + } + }; + ($name:ident, $($names:ident),*) => { + imp!($name); + imp!($($names),*); + }; +} +macro_rules! en { + ($name:ident) => { + pub enum $name { + Ptr, + Rp, + Rpo, + Pt, + Drop, + Dr, + Dro, + Sup, + Op, + Cmp, + Map, + Mp, + } + }; + ($name:ident, $($names:ident),*) => { + en!($name); + en!($($names),*); + }; +} + +imp!(Ot, Foo, Cmp, Map, Loc, Lac, Toc, Si, Sig, Sip, Psy, Psi, Py, Pi, Pa, Pb, Pc, Pd); +imp!(Pe, Pf, Pg, Ph, Pj, Pk, Pl, Pm, Pn, Po, Pq, Pr, Ps, Pt, Pu, Pv, Pw, Px, Pz, Ap, Bp, Cp); +imp!(Dp, Ep, Fp, Gp, Hp, Ip, Jp, Kp, Lp, Mp, Np, Op, Pp, Qp, Rp, Sp, Tp, Up, Vp, Wp, Xp, Yp, Zp); + +en!(Place, Plac, Plae, Plce, Pace, Scalar, Scalr, Scaar, Sclar, Salar); + +pub struct P; diff --git a/src/test/rustdoc-js/module-substring.js b/src/test/rustdoc-js/module-substring.js new file mode 100644 index 0000000000000..a446c39ebad57 --- /dev/null +++ b/src/test/rustdoc-js/module-substring.js @@ -0,0 +1,9 @@ +const QUERY = 'ig::pc'; + +const EXPECTED = { + 'others': [ + { 'path': 'module_substring::Sig', 'name': 'pc' }, + { 'path': 'module_substring::Si', 'name': 'pc' }, + { 'path': 'module_substring::Si', 'name': 'pa' }, + ], +}; diff --git a/src/test/rustdoc-js/module-substring.rs b/src/test/rustdoc-js/module-substring.rs new file mode 100644 index 0000000000000..2eacc0a358284 --- /dev/null +++ b/src/test/rustdoc-js/module-substring.rs @@ -0,0 +1,68 @@ +macro_rules! imp { + ($name:ident) => { + pub struct $name { + pub op: usize, + } + impl $name { + pub fn op() {} + pub fn cmp() {} + pub fn map() {} + pub fn pop() {} + pub fn ptr() {} + pub fn rpo() {} + pub fn drop() {} + pub fn copy() {} + pub fn zip() {} + pub fn sup() {} + pub fn pa() {} + pub fn pb() {} + pub fn pc() {} + pub fn pd() {} + pub fn pe() {} + pub fn pf() {} + pub fn pg() {} + pub fn ph() {} + pub fn pi() {} + pub fn pj() {} + pub fn pk() {} + pub fn pl() {} + pub fn pm() {} + pub fn pn() {} + pub fn po() {} + } + }; + ($name:ident, $($names:ident),*) => { + imp!($name); + imp!($($names),*); + }; +} +macro_rules! en { + ($name:ident) => { + pub enum $name { + Ptr, + Rp, + Rpo, + Pt, + Drop, + Dr, + Dro, + Sup, + Op, + Cmp, + Map, + Mp, + } + }; + ($name:ident, $($names:ident),*) => { + en!($name); + en!($($names),*); + }; +} + +imp!(Ot, Foo, Cmp, Map, Loc, Lac, Toc, Si, Sig, Sip, Psy, Psi, Py, Pi, Pa, Pb, Pc, Pd); +imp!(Pe, Pf, Pg, Ph, Pj, Pk, Pl, Pm, Pn, Po, Pq, Pr, Ps, Pt, Pu, Pv, Pw, Px, Pz, Ap, Bp, Cp); +imp!(Dp, Ep, Fp, Gp, Hp, Ip, Jp, Kp, Lp, Mp, Np, Op, Pp, Qp, Rp, Sp, Tp, Up, Vp, Wp, Xp, Yp, Zp); + +en!(Place, Plac, Plae, Plce, Pace, Scalar, Scalr, Scaar, Sclar, Salar); + +pub struct P; diff --git a/src/test/rustdoc-js/search-short-types.js b/src/test/rustdoc-js/search-short-types.js index 0ebf4860cfa58..d14672af71fd6 100644 --- a/src/test/rustdoc-js/search-short-types.js +++ b/src/test/rustdoc-js/search-short-types.js @@ -3,6 +3,8 @@ const QUERY = 'P'; const EXPECTED = { 'others': [ { 'path': 'search_short_types', 'name': 'P' }, + { 'path': 'search_short_types::VeryLongTypeName', 'name': 'p' }, { 'path': 'search_short_types', 'name': 'Ap' }, + { 'path': 'search_short_types::VeryLongTypeName', 'name': 'ap' }, ], }; diff --git a/src/test/rustdoc-js/search-short-types.rs b/src/test/rustdoc-js/search-short-types.rs index 2eacc0a358284..a4083f9a76401 100644 --- a/src/test/rustdoc-js/search-short-types.rs +++ b/src/test/rustdoc-js/search-short-types.rs @@ -66,3 +66,9 @@ imp!(Dp, Ep, Fp, Gp, Hp, Ip, Jp, Kp, Lp, Mp, Np, Op, Pp, Qp, Rp, Sp, Tp, Up, Vp, en!(Place, Plac, Plae, Plce, Pace, Scalar, Scalr, Scaar, Sclar, Salar); pub struct P; + +pub struct VeryLongTypeName; +impl VeryLongTypeName { + pub fn p() {} + pub fn ap() {} +} From b6f9523dc662ebc23f72356999ae263de9616a2d Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 4 Sep 2019 13:52:28 +0000 Subject: [PATCH 463/618] Fix doc links in `std::cmp` module These links are rendered in `core::cmp` but not in `std::cmp`. --- src/libcore/cmp.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 607427a85d67a..7ec2295f97e36 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -9,14 +9,22 @@ //! * [`Ord`] and [`PartialOrd`] are traits that allow you to define total and //! partial orderings between values, respectively. Implementing them overloads //! the `<`, `<=`, `>`, and `>=` operators. -//! * [`Ordering`][cmp::Ordering] is an enum returned by the -//! main functions of [`Ord`] and [`PartialOrd`], and describes an ordering. -//! * [`Reverse`][cmp::Reverse] is a struct that allows you to easily reverse -//! an ordering. -//! * [`max`][cmp::max] and [`min`][cmp::min] are functions that build off of -//! [`Ord`] and allow you to find the maximum or minimum of two values. +//! * [`Ordering`] is an enum returned by the main functions of [`Ord`] and +//! [`PartialOrd`], and describes an ordering. +//! * [`Reverse`] is a struct that allows you to easily reverse an ordering. +//! * [`max`] and [`min`] are functions that build off of [`Ord`] and allow you +//! to find the maximum or minimum of two values. //! //! For more details, see the respective documentation of each item in the list. +//! +//! [`Eq`]: trait.Eq.html +//! [`PartialEq`]: trait.PartialEq.html +//! [`Ord`]: trait.Ord.html +//! [`PartialOrd`]: trait.PartialOrd.html +//! [`Ordering`]: enum.Ordering.html +//! [`Reverse`]: struct.Reverse.html +//! [`max`]: fn.max.html +//! [`min`]: fn.min.html #![stable(feature = "rust1", since = "1.0.0")] From 8e067243e450528c9c61f8f0e5f91e3fc7ec707d Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Wed, 4 Sep 2019 23:25:51 +0800 Subject: [PATCH 464/618] fix a few typos in comments --- src/librustc_llvm/build.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 40ddd65164290..62a3757757b80 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -54,7 +54,7 @@ fn main() { // LLVM are compiled the same way, but for us that's typically the case. // // We *want* detect this cross compiling situation by asking llvm-config - // what it's host-target is. If that's not the TARGET, then we're cross + // what its host-target is. If that's not the TARGET, then we're cross // compiling. Unfortunately `llvm-config` seems either be buggy, or we're // misconfiguring it, because the `i686-pc-windows-gnu` build of LLVM will // report itself with a `--host-target` of `x86_64-pc-windows-gnu`. This @@ -62,7 +62,7 @@ fn main() { // havoc ensues. // // In any case, if we're cross compiling, this generally just means that we - // can't trust all the output of llvm-config becaues it might be targeted + // can't trust all the output of llvm-config because it might be targeted // for the host rather than the target. As a result a bunch of blocks below // are gated on `if !is_crossed` let target = env::var("TARGET").expect("TARGET was not set"); @@ -166,7 +166,7 @@ fn main() { let (llvm_kind, llvm_link_arg) = detect_llvm_link(); - // Link in all LLVM libraries, if we're uwring the "wrong" llvm-config then + // Link in all LLVM libraries, if we're using the "wrong" llvm-config then // we don't pick up system libs because unfortunately they're for the host // of llvm-config, not the target that we're attempting to link. let mut cmd = Command::new(&llvm_config); From 74ccd08401f1350554272a1b7bdbcf6789166daa Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Sep 2019 08:35:52 -0700 Subject: [PATCH 465/618] Update cargo, books --- src/doc/embedded-book | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/tools/cargo | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/embedded-book b/src/doc/embedded-book index 432ca26686c11..5ca585c4a7552 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit 432ca26686c11d396eed6a59499f93ce1bf2433c +Subproject commit 5ca585c4a7552efb546e7681c3de0712f4ae4fdc diff --git a/src/doc/reference b/src/doc/reference index d191a0cdd3b92..090c015f79396 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit d191a0cdd3b92648e0f1e53b13140a14677cc65b +Subproject commit 090c015f7939665866432c334957bd536c811870 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 580839d90aacd..e76be6b2dc84c 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 580839d90aacd537f0293697096fa8355bc4e673 +Subproject commit e76be6b2dc84c6a992e186157efe29d625e29b94 diff --git a/src/tools/cargo b/src/tools/cargo index 22f7dd0495cd7..fe0e5a48b75da 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 22f7dd0495cd72ce2082d318d5a9b4dccb9c5b8c +Subproject commit fe0e5a48b75da2b405c8ce1ba2674e174ae11d5d From 4a2094c9f61836214d9e37fa042761948483c2d9 Mon Sep 17 00:00:00 2001 From: Dario Gonzalez Date: Tue, 27 Aug 2019 15:44:11 -0700 Subject: [PATCH 466/618] address rebase changes --- src/librustdoc/core.rs | 1 - src/librustdoc/markdown.rs | 3 ++- src/librustdoc/test.rs | 20 +++++++++++--------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 66a32c73e0f16..57b016a08c2fe 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -293,7 +293,6 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt } }).collect(); - let host_triple = TargetTriple::from_triple(config::host_triple()); let crate_types = if proc_macro_crate { vec![config::CrateType::ProcMacro] } else { diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 67faec6bd3d0c..b06b368469fc1 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -143,7 +143,8 @@ pub fn test(mut options: Options, diag: &errors::Handler) -> i32 { opts.no_crate_inject = true; opts.display_warnings = options.display_warnings; let mut collector = Collector::new(options.input.display().to_string(), options.clone(), - true, opts, None, Some(options.input)); + true, opts, None, Some(options.input), + options.enable_per_target_ignores); collector.set_position(DUMMY_SP); let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 840eeda9ad7ca..aefe4d3ea3f43 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -45,7 +45,7 @@ pub fn run(options: Options) -> i32 { vec![config::CrateType::Dylib] }; - let mut sessopts = config::Options { + let sessopts = config::Options { maybe_sysroot: options.maybe_sysroot.clone(), search_paths: options.libs.clone(), crate_types, @@ -84,6 +84,7 @@ pub fn run(options: Options) -> i32 { let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate()); opts.display_warnings |= options.display_warnings; + let enable_per_target_ignores = options.enable_per_target_ignores; let mut collector = Collector::new( compiler.crate_name()?.peek().to_string(), options, @@ -91,6 +92,7 @@ pub fn run(options: Options) -> i32 { opts, Some(compiler.source_map().clone()), None, + enable_per_target_ignores, ); let mut global_ctxt = compiler.global_ctxt()?.take(); @@ -275,6 +277,7 @@ fn run_test( if no_run { compiler.arg("--emit=metadata"); } + compiler.arg("--target").arg(target.to_string()); compiler.arg("-"); compiler.stdin(Stdio::piped()); @@ -616,6 +619,7 @@ pub struct Collector { options: Options, use_headers: bool, + enable_per_target_ignores: bool, cratename: String, opts: TestOptions, position: Span, @@ -625,12 +629,14 @@ pub struct Collector { impl Collector { pub fn new(cratename: String, options: Options, use_headers: bool, opts: TestOptions, - source_map: Option>, filename: Option,) -> Collector { + source_map: Option>, filename: Option, + enable_per_target_ignores: bool) -> Collector { Collector { tests: Vec::new(), names: Vec::new(), options, use_headers, + enable_per_target_ignores, cratename, opts, position: DUMMY_SP, @@ -674,13 +680,9 @@ impl Tester for Collector { let opts = self.opts.clone(); let edition = config.edition.unwrap_or(self.options.edition.clone()); let options = self.options.clone(); - let maybe_sysroot = self.maybe_sysroot.clone(); - let linker = self.linker.clone(); - let edition = config.edition.unwrap_or(self.edition); - let persist_doctests = self.persist_doctests.clone(); - let runtool = self.runtool.clone(); - let runtool_args = self.runtool_args.clone(); - let target = self.target.clone(); + let runtool = self.options.runtool.clone(); + let runtool_args = self.options.runtool_args.clone(); + let target = self.options.target.clone(); let target_str = target.to_string(); debug!("creating test {}: {}", name, test); From c86ea34639b0962858f053e900fe7c7de1008c5f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 2 Sep 2019 14:23:41 -0400 Subject: [PATCH 467/618] Ensure all warnings are emitted even on warnings=warn --- src/bootstrap/bin/rustc.rs | 13 +++++++------ src/bootstrap/bootstrap.py | 3 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 8cb48df14bfef..84415baa3a140 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -119,17 +119,18 @@ fn main() { cmd.arg(format!("-Cdebuginfo={}", debuginfo_level)); } - if env::var_os("RUSTC_DENY_WARNINGS").is_some() && - env::var_os("RUSTC_EXTERNAL_TOOL").is_none() { + if env::var_os("RUSTC_EXTERNAL_TOOL").is_none() { // When extending this list, add the new lints to the RUSTFLAGS of the // build_bootstrap function of src/bootstrap/bootstrap.py as well as // some code doesn't go through this `rustc` wrapper. - cmd.arg("-Dwarnings"); - cmd.arg("-Drust_2018_idioms"); - cmd.arg("-Dunused_lifetimes"); + cmd.arg("-Wrust_2018_idioms"); + cmd.arg("-Wunused_lifetimes"); if use_internal_lints(crate_name) { cmd.arg("-Zunstable-options"); - cmd.arg("-Drustc::internal"); + cmd.arg("-Wrustc::internal"); + } + if env::var_os("RUSTC_DENY_WARNINGS").is_some() { + cmd.arg("-Dwarnings"); } } diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 4162fe1df5086..03f02ea217ddf 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -631,8 +631,9 @@ def build_bootstrap(self): target_linker = self.get_toml("linker", build_section) if target_linker is not None: env["RUSTFLAGS"] += "-C linker=" + target_linker + " " + env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes " if self.get_toml("deny-warnings", "rust") != "false": - env["RUSTFLAGS"] += "-Dwarnings -Drust_2018_idioms -Dunused_lifetimes " + env["RUSTFLAGS"] += "-Dwarnings " env["PATH"] = os.path.join(self.bin_root(), "bin") + \ os.pathsep + env["PATH"] From fda251b966ec5a8d1c3c001242777861f15b95e2 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 2 Sep 2019 14:24:40 -0400 Subject: [PATCH 468/618] Rename --warnings=allow to --warnings=warn We never allowed the warnings, only made them not denied. --- src/bootstrap/flags.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 828865f10ffba..d9580b598155e 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -36,7 +36,7 @@ pub struct Flags { // This overrides the deny-warnings configuation option, // which passes -Dwarnings to the compiler invocations. // - // true => deny, false => allow + // true => deny, false => warn pub deny_warnings: Option, } @@ -556,10 +556,10 @@ fn split(s: &[String]) -> Vec { fn parse_deny_warnings(matches: &getopts::Matches) -> Option { match matches.opt_str("warnings").as_ref().map(|v| v.as_str()) { Some("deny") => Some(true), - Some("allow") => Some(false), + Some("warn") => Some(false), Some(value) => { eprintln!( - r#"invalid value for --warnings: {:?}, expected "allow" or "deny""#, + r#"invalid value for --warnings: {:?}, expected "warn" or "deny""#, value, ); process::exit(1); From 843fba3ed18b9aa9e3f6a2bfa030e1df8179503b Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Mon, 22 Jul 2019 00:54:42 +0300 Subject: [PATCH 469/618] Stabilize checked_duration_since for 1.39.0 Resolves #58402. --- src/libstd/lib.rs | 1 - src/libstd/time.rs | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c3882bacf87eb..71050b0dcd1f5 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -244,7 +244,6 @@ #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] #![feature(char_error_internals)] -#![feature(checked_duration_since)] #![feature(clamp)] #![feature(compiler_builtins_lib)] #![feature(concat_idents)] diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 98371b9ba3d7e..d59085cd44a6f 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -221,7 +221,6 @@ impl Instant { /// # Examples /// /// ```no_run - /// #![feature(checked_duration_since)] /// use std::time::{Duration, Instant}; /// use std::thread::sleep; /// @@ -231,7 +230,7 @@ impl Instant { /// println!("{:?}", new_now.checked_duration_since(now)); /// println!("{:?}", now.checked_duration_since(new_now)); // None /// ``` - #[unstable(feature = "checked_duration_since", issue = "58402")] + #[stable(feature = "checked_duration_since", since = "1.39.0")] pub fn checked_duration_since(&self, earlier: Instant) -> Option { self.0.checked_sub_instant(&earlier.0) } @@ -242,7 +241,6 @@ impl Instant { /// # Examples /// /// ```no_run - /// #![feature(checked_duration_since)] /// use std::time::{Duration, Instant}; /// use std::thread::sleep; /// @@ -252,7 +250,7 @@ impl Instant { /// println!("{:?}", new_now.saturating_duration_since(now)); /// println!("{:?}", now.saturating_duration_since(new_now)); // 0ns /// ``` - #[unstable(feature = "checked_duration_since", issue = "58402")] + #[stable(feature = "checked_duration_since", since = "1.39.0")] pub fn saturating_duration_since(&self, earlier: Instant) -> Duration { self.checked_duration_since(earlier).unwrap_or(Duration::new(0, 0)) } From 5545582a6f6111872cdda54d18f43a7da24661f4 Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Thu, 5 Sep 2019 01:25:07 +0300 Subject: [PATCH 470/618] Avoid feature name 'checked_duration_since' in a Tidy test --- src/tools/tidy/src/features/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/tidy/src/features/tests.rs b/src/tools/tidy/src/features/tests.rs index fa7a931ec865c..994523ac1abce 100644 --- a/src/tools/tidy/src/features/tests.rs +++ b/src/tools/tidy/src/features/tests.rs @@ -2,8 +2,8 @@ use super::*; #[test] fn test_find_attr_val() { - let s = r#"#[unstable(feature = "checked_duration_since", issue = "58402")]"#; - assert_eq!(find_attr_val(s, "feature"), Some("checked_duration_since")); + let s = r#"#[unstable(feature = "tidy_test_never_used_anywhere_else", issue = "58402")]"#; + assert_eq!(find_attr_val(s, "feature"), Some("tidy_test_never_used_anywhere_else")); assert_eq!(find_attr_val(s, "issue"), Some("58402")); assert_eq!(find_attr_val(s, "since"), None); } From 53fe76479aab03b1fbe5b7184f45484886f769b1 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 4 Sep 2019 16:02:31 -0700 Subject: [PATCH 471/618] Assume non-git LLVM is fresh if the stamp file exists Rustbuild usually writes the LLVM submodule commit in a stamp file, so we can avoid rebuilding it unnecessarily. However, for builds from a source tarball (non-git), we were assuming a rebuild is always needed. This can cause a lot of extra work if any environment like `CFLAGS` changed between steps like build and install, which are often separate in distro builds. Now we also write an empty stamp file if the git commit is unknown, and its presence is trusted to indicate that no rebuild is needed. An info message reports that this is happening, along with the stamp file path that can be deleted to force a rebuild anyway. --- src/bootstrap/native.rs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index f02def3e1b05d..7bf9ea2688f4c 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -81,26 +81,29 @@ impl Step for Llvm { (info, "src/llvm-project/llvm", builder.llvm_out(target), dir.join("bin")) }; - if !llvm_info.is_git() { - println!( - "git could not determine the LLVM submodule commit hash. \ - Assuming that an LLVM build is necessary.", - ); - } - let build_llvm_config = llvm_config_ret_dir .join(exe("llvm-config", &*builder.config.build)); let done_stamp = out_dir.join("llvm-finished-building"); - if let Some(llvm_commit) = llvm_info.sha() { - if done_stamp.exists() { + if done_stamp.exists() { + if let Some(llvm_commit) = llvm_info.sha() { let done_contents = t!(fs::read(&done_stamp)); // If LLVM was already built previously and the submodule's commit didn't change // from the previous build, then no action is required. if done_contents == llvm_commit.as_bytes() { - return build_llvm_config + return build_llvm_config; } + } else { + builder.info( + "Could not determine the LLVM submodule commit hash. \ + Assuming that an LLVM rebuild is not necessary.", + ); + builder.info(&format!( + "To force LLVM to rebuild, remove the file `{}`", + done_stamp.display() + )); + return build_llvm_config; } } @@ -303,9 +306,7 @@ impl Step for Llvm { cfg.build(); - if let Some(llvm_commit) = llvm_info.sha() { - t!(fs::write(&done_stamp, llvm_commit)); - } + t!(fs::write(&done_stamp, llvm_info.sha().unwrap_or(""))); build_llvm_config } From 290f5b22752f98071bbc25530fc10a7169e671a3 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Wed, 4 Sep 2019 12:14:34 -0700 Subject: [PATCH 472/618] Use backtrace formatting from the backtrace crate --- Cargo.lock | 4 +- src/libstd/Cargo.toml | 2 +- src/libstd/panicking.rs | 8 +- src/libstd/sys_common/backtrace.rs | 235 +++++++++++------------------ 4 files changed, 96 insertions(+), 153 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e0d30647809a9..db83aacc69e45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,9 +109,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.35" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1371048253fa3bac6704bfd6bbfc922ee9bdcee8881330d40f308b81cc5adc55" +checksum = "5180c5a20655b14a819b652fd2378fa5f1697b6c9ddad3e695c2f9cedf6df4e2" dependencies = [ "backtrace-sys", "cfg-if", diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 157faa0af9bca..02a54e9fa72c6 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -26,7 +26,7 @@ unwind = { path = "../libunwind" } hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] } [dependencies.backtrace] -version = "0.3.35" +version = "0.3.37" default-features = false # don't use coresymbolication on OSX features = [ "rustc-dep-of-std", # enable build support for integrating into libstd diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 952fd9ebfdf07..db4089c294812 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -158,7 +158,7 @@ pub fn take_hook() -> Box) + 'static + Sync + Send> { fn default_hook(info: &PanicInfo<'_>) { #[cfg(feature = "backtrace")] - use crate::sys_common::backtrace; + use crate::sys_common::{backtrace as backtrace_mod}; // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. @@ -167,9 +167,9 @@ fn default_hook(info: &PanicInfo<'_>) { let panics = update_panic_count(0); if panics >= 2 { - Some(backtrace::PrintFormat::Full) + Some(backtrace::PrintFmt::Full) } else { - backtrace::log_enabled() + backtrace_mod::log_enabled() } }; @@ -197,7 +197,7 @@ fn default_hook(info: &PanicInfo<'_>) { static FIRST_PANIC: AtomicBool = AtomicBool::new(true); if let Some(format) = log_backtrace { - let _ = backtrace::print(err, format); + let _ = backtrace_mod::print(err, format); } else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) { let _ = writeln!(err, "note: run with `RUST_BACKTRACE=1` \ environment variable to display a backtrace."); diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index bf37ff7ddbd3a..f434b62aced67 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -2,23 +2,20 @@ /// supported platforms. use crate::env; +use crate::fmt; use crate::io; use crate::io::prelude::*; -use crate::mem; use crate::path::{self, Path}; -use crate::ptr; use crate::sync::atomic::{self, Ordering}; use crate::sys::mutex::Mutex; -use backtrace::{BytesOrWideString, Frame, Symbol}; - -pub const HEX_WIDTH: usize = 2 + 2 * mem::size_of::(); +use backtrace::{BacktraceFmt, BytesOrWideString, PrintFmt}; /// Max number of frames to print. const MAX_NB_FRAMES: usize = 100; /// Prints the current backtrace. -pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> { +pub fn print(w: &mut dyn Write, format: PrintFmt) -> io::Result<()> { static LOCK: Mutex = Mutex::new(); // There are issues currently linking libbacktrace into tests, and in @@ -39,26 +36,66 @@ pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> { } } -fn _print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> { - writeln!(w, "stack backtrace:")?; +fn _print(w: &mut dyn Write, format: PrintFmt) -> io::Result<()> { + struct DisplayBacktrace { + format: PrintFmt, + } + impl fmt::Display for DisplayBacktrace { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + _print_fmt(fmt, self.format) + } + } + write!(w, "{}", DisplayBacktrace { format }) +} - let mut printer = Printer::new(format, w); +fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::Result { + let mut print_path = move |fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>| { + output_filename(fmt, bows, print_fmt) + }; + let mut bt_fmt = BacktraceFmt::new(fmt, print_fmt, &mut print_path); + bt_fmt.add_context()?; + let mut skipped = false; unsafe { + let mut idx = 0; + let mut res = Ok(()); backtrace::trace_unsynchronized(|frame| { + if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES { + skipped = true; + return false; + } + let mut hit = false; + let mut stop = false; backtrace::resolve_frame_unsynchronized(frame, |symbol| { hit = true; - printer.output(frame, Some(symbol)); + if print_fmt == PrintFmt::Short { + if let Some(sym) = symbol.name().and_then(|s| s.as_str()) { + if sym.contains("__rust_begin_short_backtrace") { + skipped = true; + stop = true; + return; + } + } + } + + res = bt_fmt.frame().symbol(frame, symbol); }); + if stop { + return false; + } if !hit { - printer.output(frame, None); + res = bt_fmt.frame().print_raw(frame.ip(), None, None, None); } - !printer.done + + idx += 1; + res.is_ok() }); + res?; } - if printer.skipped { + bt_fmt.finish()?; + if skipped { writeln!( - w, + fmt, "note: Some details are omitted, \ run with `RUST_BACKTRACE=full` for a verbose backtrace." )?; @@ -77,33 +114,24 @@ where f() } -/// Controls how the backtrace should be formatted. -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub enum PrintFormat { - /// Show only relevant data from the backtrace. - Short = 2, - /// Show all the frames with absolute path for files. - Full = 3, -} - // For now logging is turned off by default, and this function checks to see // whether the magical environment variable is present to see if it's turned on. -pub fn log_enabled() -> Option { +pub fn log_enabled() -> Option { static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0); match ENABLED.load(Ordering::SeqCst) { 0 => {} 1 => return None, - 2 => return Some(PrintFormat::Short), - _ => return Some(PrintFormat::Full), + 2 => return Some(PrintFmt::Short), + _ => return Some(PrintFmt::Full), } let val = env::var_os("RUST_BACKTRACE").and_then(|x| { if &x == "0" { None } else if &x == "full" { - Some(PrintFormat::Full) + Some(PrintFmt::Full) } else { - Some(PrintFormat::Short) + Some(PrintFmt::Short) } }); ENABLED.store( @@ -116,130 +144,45 @@ pub fn log_enabled() -> Option { val } -struct Printer<'a, 'b> { - format: PrintFormat, - done: bool, - skipped: bool, - idx: usize, - out: &'a mut (dyn Write + 'b), -} - -impl<'a, 'b> Printer<'a, 'b> { - fn new(format: PrintFormat, out: &'a mut (dyn Write + 'b)) -> Printer<'a, 'b> { - Printer { format, done: false, skipped: false, idx: 0, out } - } - - /// Prints the symbol of the backtrace frame. - /// - /// These output functions should now be used everywhere to ensure consistency. - /// You may want to also use `output_fileline`. - fn output(&mut self, frame: &Frame, symbol: Option<&Symbol>) { - if self.idx > MAX_NB_FRAMES { - self.done = true; - self.skipped = true; - return; - } - if self._output(frame, symbol).is_err() { - self.done = true; - } - self.idx += 1; - } - - fn _output(&mut self, frame: &Frame, symbol: Option<&Symbol>) -> io::Result<()> { - if self.format == PrintFormat::Short { - if let Some(sym) = symbol.and_then(|s| s.name()).and_then(|s| s.as_str()) { - if sym.contains("__rust_begin_short_backtrace") { - self.skipped = true; - self.done = true; - return Ok(()); - } - } - - // Remove the `17: 0x0 - ` line. - if self.format == PrintFormat::Short && frame.ip() == ptr::null_mut() { - self.skipped = true; - return Ok(()); - } - } - - match self.format { - PrintFormat::Full => { - write!(self.out, " {:2}: {:2$?} - ", self.idx, frame.ip(), HEX_WIDTH)? - } - PrintFormat::Short => write!(self.out, " {:2}: ", self.idx)?, - } - - match symbol.and_then(|s| s.name()) { - Some(symbol) => { - match self.format { - PrintFormat::Full => write!(self.out, "{}", symbol)?, - // Strip the trailing hash if short mode. - PrintFormat::Short => write!(self.out, "{:#}", symbol)?, - } - } - None => self.out.write_all(b"")?, +/// Prints the filename of the backtrace frame. +/// +/// See also `output`. +fn output_filename( + fmt: &mut fmt::Formatter<'_>, + bows: BytesOrWideString<'_>, + print_fmt: PrintFmt, +) -> fmt::Result { + #[cfg(windows)] + let path_buf; + let file = match bows { + #[cfg(unix)] + BytesOrWideString::Bytes(bytes) => { + use crate::os::unix::prelude::*; + Path::new(crate::ffi::OsStr::from_bytes(bytes)) } - self.out.write_all(b"\n")?; - if let Some(sym) = symbol { - self.output_fileline(sym)?; + #[cfg(not(unix))] + BytesOrWideString::Bytes(bytes) => { + Path::new(crate::str::from_utf8(bytes).unwrap_or("")) } - Ok(()) - } - - /// Prints the filename and line number of the backtrace frame. - /// - /// See also `output`. - fn output_fileline(&mut self, symbol: &Symbol) -> io::Result<()> { #[cfg(windows)] - let path_buf; - let file = match symbol.filename_raw() { - #[cfg(unix)] - Some(BytesOrWideString::Bytes(bytes)) => { - use crate::os::unix::prelude::*; - Path::new(crate::ffi::OsStr::from_bytes(bytes)) - } - #[cfg(not(unix))] - Some(BytesOrWideString::Bytes(bytes)) => { - Path::new(crate::str::from_utf8(bytes).unwrap_or("")) - } - #[cfg(windows)] - Some(BytesOrWideString::Wide(wide)) => { - use crate::os::windows::prelude::*; - path_buf = crate::ffi::OsString::from_wide(wide); - Path::new(&path_buf) - } - #[cfg(not(windows))] - Some(BytesOrWideString::Wide(_wide)) => { - Path::new("") - } - None => return Ok(()), - }; - let line = match symbol.lineno() { - Some(line) => line, - None => return Ok(()), - }; - // prior line: " ##: {:2$} - func" - self.out.write_all(b"")?; - match self.format { - PrintFormat::Full => write!(self.out, " {:1$}", "", HEX_WIDTH)?, - PrintFormat::Short => write!(self.out, " ")?, + BytesOrWideString::Wide(wide) => { + use crate::os::windows::prelude::*; + path_buf = crate::ffi::OsString::from_wide(wide); + Path::new(&path_buf) } - - let mut already_printed = false; - if self.format == PrintFormat::Short && file.is_absolute() { - if let Ok(cwd) = env::current_dir() { - if let Ok(stripped) = file.strip_prefix(&cwd) { - if let Some(s) = stripped.to_str() { - write!(self.out, " at .{}{}:{}", path::MAIN_SEPARATOR, s, line)?; - already_printed = true; - } + #[cfg(not(windows))] + BytesOrWideString::Wide(_wide) => { + Path::new("") + } + }; + if print_fmt == PrintFmt::Short && file.is_absolute() { + if let Ok(cwd) = env::current_dir() { + if let Ok(stripped) = file.strip_prefix(&cwd) { + if let Some(s) = stripped.to_str() { + return write!(fmt, ".{}{}", path::MAIN_SEPARATOR, s); } } } - if !already_printed { - write!(self.out, " at {}:{}", file.display(), line)?; - } - - self.out.write_all(b"\n") } + fmt::Display::fmt(&file.display(), fmt) } From 21e7e3f1e903f6d6f2e6eacbbe5848fcd894db9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 4 Sep 2019 19:04:26 -0700 Subject: [PATCH 473/618] Point at variant on pattern field count mismatch --- src/librustc_typeck/check/pat.rs | 2 ++ src/test/ui/error-codes/E0023.stderr | 9 +++++++++ src/test/ui/match/match-pattern-field-mismatch.stderr | 3 +++ src/test/ui/pattern/pat-tuple-overfield.stderr | 6 ++++++ src/test/ui/pattern/pattern-error-continue.stderr | 3 +++ 5 files changed, 23 insertions(+) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 4cf0df308fb4c..9a3f5e9e1b5d8 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -677,12 +677,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { let subpats_ending = if subpats.len() == 1 { "" } else { "s" }; let fields_ending = if variant.fields.len() == 1 { "" } else { "s" }; + let span = tcx.def_span(res.def_id()); struct_span_err!(tcx.sess, pat.span, E0023, "this pattern has {} field{}, but the corresponding {} has {} field{}", subpats.len(), subpats_ending, res.descr(), variant.fields.len(), fields_ending) .span_label(pat.span, format!("expected {} field{}, found {}", variant.fields.len(), fields_ending, subpats.len())) + .span_label(span, format!("{} defined here", res.descr())) .emit(); on_error(); return tcx.types.err; diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index 1bc90a995fe30..d04e494c2585c 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -1,18 +1,27 @@ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields --> $DIR/E0023.rs:10:9 | +LL | Apple(String, String), + | --------------------- tuple variant defined here +... LL | Fruit::Apple(a) => {}, | ^^^^^^^^^^^^^^^ expected 2 fields, found 1 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/E0023.rs:11:9 | +LL | Apple(String, String), + | --------------------- tuple variant defined here +... LL | Fruit::Apple(a, b, c) => {}, | ^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3 error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field --> $DIR/E0023.rs:12:9 | +LL | Pear(u32), + | --------- tuple variant defined here +... LL | Fruit::Pear(1, 2) => {}, | ^^^^^^^^^^^^^^^^^ expected 1 field, found 2 diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index 663cd2cd24d56..c2298d6fbbf02 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -1,6 +1,9 @@ error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields --> $DIR/match-pattern-field-mismatch.rs:10:11 | +LL | Rgb(usize, usize, usize), + | ------------------------ tuple variant defined here +... LL | Color::Rgb(_, _) => { } | ^^^^^^^^^^^^^^^^ expected 3 fields, found 2 diff --git a/src/test/ui/pattern/pat-tuple-overfield.stderr b/src/test/ui/pattern/pat-tuple-overfield.stderr index 0430897510b85..e64b6efb08da8 100644 --- a/src/test/ui/pattern/pat-tuple-overfield.stderr +++ b/src/test/ui/pattern/pat-tuple-overfield.stderr @@ -19,12 +19,18 @@ LL | (1, 2, .., 3, 4) => {} error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields --> $DIR/pat-tuple-overfield.rs:10:9 | +LL | struct S(u8, u8, u8); + | --------------------- tuple struct defined here +... LL | S(1, 2, 3, 4) => {} | ^^^^^^^^^^^^^ expected 3 fields, found 4 error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields --> $DIR/pat-tuple-overfield.rs:12:9 | +LL | struct S(u8, u8, u8); + | --------------------- tuple struct defined here +... LL | S(1, 2, .., 3, 4) => {} | ^^^^^^^^^^^^^^^^^ expected 3 fields, found 4 diff --git a/src/test/ui/pattern/pattern-error-continue.stderr b/src/test/ui/pattern/pattern-error-continue.stderr index a581f07496e6c..4fbc630644baa 100644 --- a/src/test/ui/pattern/pattern-error-continue.stderr +++ b/src/test/ui/pattern/pattern-error-continue.stderr @@ -15,6 +15,9 @@ LL | A::D(_) => (), error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/pattern-error-continue.rs:17:9 | +LL | B(isize, isize), + | --------------- tuple variant defined here +... LL | A::B(_, _, _) => (), | ^^^^^^^^^^^^^ expected 2 fields, found 3 From 9483db5052415464fcb59ab480479afdd35710a5 Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Thu, 5 Sep 2019 00:08:52 +0100 Subject: [PATCH 474/618] Opaque type locations in error message for clarity. --- src/librustc/infer/error_reporting/mod.rs | 11 +++++++++-- src/test/ui/suggestions/opaque-type-error.stderr | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 9be73cf3c6d16..fdadda92010a5 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1136,12 +1136,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Some((expected, found)) = expected_found { match (terr, is_simple_error, expected == found) { (&TypeError::Sorts(ref values), false, true) => { + let sort_string = | a_type: Ty<'tcx> | + if let ty::Opaque(def_id, _) = a_type.sty { + format!(" (opaque type at {})", self.tcx.sess.source_map() + .mk_substr_filename(self.tcx.def_span(def_id))) + } else { + format!(" ({})", a_type.sort_string(self.tcx)) + }; diag.note_expected_found_extra( &"type", expected, found, - &format!(" ({})", values.expected.sort_string(self.tcx)), - &format!(" ({})", values.found.sort_string(self.tcx)), + &sort_string(values.expected), + &sort_string(values.found), ); } (_, false, _) => { diff --git a/src/test/ui/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr index 3c9ea05aeceb2..450cbd4799fdc 100644 --- a/src/test/ui/suggestions/opaque-type-error.stderr +++ b/src/test/ui/suggestions/opaque-type-error.stderr @@ -10,8 +10,8 @@ LL | | thing_two() LL | | }.await | |_____- if and else have incompatible types | - = note: expected type `impl std::future::Future` (opaque type) - found type `impl std::future::Future` (opaque type) + = note: expected type `impl std::future::Future` (opaque type at <$DIR/opaque-type-error.rs:8:19>) + found type `impl std::future::Future` (opaque type at <$DIR/opaque-type-error.rs:12:19>) = note: distinct uses of `impl Trait` result in different opaque types = help: if both `Future`s have the same `Output` type, consider `.await`ing on both of them From af06bfb84c47add51a41153f6f71fc07d4c60a8d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 28 Aug 2019 07:20:54 +0200 Subject: [PATCH 475/618] resolve: extract `resolve_params`. --- src/librustc_resolve/late.rs | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index e15d02a9f7ec7..4595b1ff3f1cb 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -425,14 +425,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { self.label_ribs.push(Rib::new(rib_kind)); // Add each argument to the rib. - let mut bindings_list = FxHashMap::default(); - for argument in &declaration.inputs { - self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list); - - self.visit_ty(&argument.ty); + self.resolve_params(&declaration.inputs); - debug!("(resolving function) recorded argument"); - } visit::walk_fn_ret_ty(self, &declaration.output); // Resolve the function body, potentially inside the body of an async closure @@ -1135,6 +1129,15 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } } + fn resolve_params(&mut self, params: &[Arg]) { + let mut bindings_list = FxHashMap::default(); + for param in params { + self.resolve_pattern(¶m.pat, PatternSource::FnParam, &mut bindings_list); + self.visit_ty(¶m.ty); + debug!("(resolving function / closure) recorded parameter"); + } + } + fn resolve_local(&mut self, local: &Local) { // Resolve the type. walk_list!(self, visit_ty, &local.ty); @@ -1860,20 +1863,12 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { // `async |x| ...` gets desugared to `|x| future_from_generator(|| ...)`, so we need to // resolve the arguments within the proper scopes so that usages of them inside the // closure are detected as upvars rather than normal closure arg usages. - ExprKind::Closure( - _, IsAsync::Async { .. }, _, - ref fn_decl, ref body, _span, - ) => { - let rib_kind = NormalRibKind; - self.ribs[ValueNS].push(Rib::new(rib_kind)); + ExprKind::Closure(_, IsAsync::Async { .. }, _, ref fn_decl, ref body, _span) => { + self.ribs[ValueNS].push(Rib::new(NormalRibKind)); // Resolve arguments: - let mut bindings_list = FxHashMap::default(); - for argument in &fn_decl.inputs { - self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list); - self.visit_ty(&argument.ty); - } - // No need to resolve return type-- the outer closure return type is - // FunctionRetTy::Default + self.resolve_params(&fn_decl.inputs); + // No need to resolve return type -- + // the outer closure return type is `FunctionRetTy::Default`. // Now resolve the inner closure { From f8835eeaf898430dcf056791a210facfc60e9980 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 28 Aug 2019 08:48:10 +0200 Subject: [PATCH 476/618] resolve: cleanup using `with_rib`, etc. --- src/librustc_resolve/late.rs | 263 ++++++++++++++++------------------- 1 file changed, 118 insertions(+), 145 deletions(-) diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 4595b1ff3f1cb..5029d61d6e4e1 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -406,44 +406,32 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { visit::walk_foreign_item(this, foreign_item); }); } - fn visit_fn(&mut self, - function_kind: FnKind<'tcx>, - declaration: &'tcx FnDecl, - _: Span, - _: NodeId) - { + fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, _: Span, _: NodeId) { debug!("(resolving function) entering function"); - let rib_kind = match function_kind { + let rib_kind = match fn_kind { FnKind::ItemFn(..) => FnItemRibKind, FnKind::Method(..) | FnKind::Closure(_) => NormalRibKind, }; // Create a value rib for the function. - self.ribs[ValueNS].push(Rib::new(rib_kind)); - - // Create a label rib for the function. - self.label_ribs.push(Rib::new(rib_kind)); - - // Add each argument to the rib. - self.resolve_params(&declaration.inputs); - - visit::walk_fn_ret_ty(self, &declaration.output); - - // Resolve the function body, potentially inside the body of an async closure - match function_kind { - FnKind::ItemFn(.., body) | - FnKind::Method(.., body) => { - self.visit_block(body); - } - FnKind::Closure(body) => { - self.visit_expr(body); - } - }; - - debug!("(resolving function) leaving function"); - - self.label_ribs.pop(); - self.ribs[ValueNS].pop(); + self.with_rib(ValueNS, rib_kind, |this| { + // Create a label rib for the function. + this.with_label_rib(rib_kind, |this| { + // Add each argument to the rib. + this.resolve_params(&declaration.inputs); + + visit::walk_fn_ret_ty(this, &declaration.output); + + // Resolve the function body, potentially inside the body of an async closure + match fn_kind { + FnKind::ItemFn(.., body) | + FnKind::Method(.., body) => this.visit_block(body), + FnKind::Closure(body) => this.visit_expr(body), + }; + + debug!("(resolving function) leaving function"); + }) + }); } fn visit_generics(&mut self, generics: &'tcx Generics) { @@ -522,13 +510,14 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { // although it may be useful to track other components as well for diagnostics. let graph_root = resolver.graph_root; let parent_scope = ParentScope::module(graph_root); + let start_rib_kind = ModuleRibKind(graph_root); LateResolutionVisitor { r: resolver, parent_scope, ribs: PerNS { - value_ns: vec![Rib::new(ModuleRibKind(graph_root))], - type_ns: vec![Rib::new(ModuleRibKind(graph_root))], - macro_ns: vec![Rib::new(ModuleRibKind(graph_root))], + value_ns: vec![Rib::new(start_rib_kind)], + type_ns: vec![Rib::new(start_rib_kind)], + macro_ns: vec![Rib::new(start_rib_kind)], }, label_ribs: Vec::new(), current_trait_ref: None, @@ -582,23 +571,32 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { // generate a fake "implementation scope" containing all the // implementations thus found, for compatibility with old resolve pass. - fn with_scope(&mut self, id: NodeId, f: F) -> T - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T - { + /// Do some `work` within a new innermost rib of the given `kind` in the given namespace (`ns`). + fn with_rib( + &mut self, + ns: Namespace, + kind: RibKind<'a>, + work: impl FnOnce(&mut Self) -> T, + ) -> T { + self.ribs[ns].push(Rib::new(kind)); + let ret = work(self); + self.ribs[ns].pop(); + ret + } + + fn with_scope(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { let id = self.r.definitions.local_def_id(id); let module = self.r.module_map.get(&id).cloned(); // clones a reference if let Some(module) = module { // Move down in the graph. let orig_module = replace(&mut self.parent_scope.module, module); - self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module))); - self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module))); - - let ret = f(self); - - self.parent_scope.module = orig_module; - self.ribs[ValueNS].pop(); - self.ribs[TypeNS].pop(); - ret + self.with_rib(ValueNS, ModuleRibKind(module), |this| { + this.with_rib(TypeNS, ModuleRibKind(module), |this| { + let ret = f(this); + this.parent_scope.module = orig_module; + ret + }) + }) } else { f(self) } @@ -802,7 +800,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } fn with_generic_param_rib<'c, F>(&'c mut self, generic_params: GenericParameters<'a, 'c>, f: F) - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) + where F: FnOnce(&mut Self) { debug!("with_generic_param_rib"); match generic_params { @@ -888,38 +886,24 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } } - fn with_label_rib(&mut self, f: F) - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) - { - self.label_ribs.push(Rib::new(NormalRibKind)); + fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) { + self.label_ribs.push(Rib::new(kind)); f(self); self.label_ribs.pop(); } - fn with_item_rib(&mut self, f: F) - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) - { - self.ribs[ValueNS].push(Rib::new(ItemRibKind)); - self.ribs[TypeNS].push(Rib::new(ItemRibKind)); - f(self); - self.ribs[TypeNS].pop(); - self.ribs[ValueNS].pop(); + fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) { + self.with_rib(ValueNS, ItemRibKind, |this| this.with_rib(TypeNS, ItemRibKind, f)) } - fn with_constant_rib(&mut self, f: F) - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) - { + fn with_constant_rib(&mut self, f: impl FnOnce(&mut Self)) { debug!("with_constant_rib"); - self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind)); - self.label_ribs.push(Rib::new(ConstantItemRibKind)); - f(self); - self.label_ribs.pop(); - self.ribs[ValueNS].pop(); + self.with_rib(ValueNS, ConstantItemRibKind, |this| { + this.with_label_rib(ConstantItemRibKind, f); + }); } - fn with_current_self_type(&mut self, self_type: &Ty, f: F) -> T - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T - { + fn with_current_self_type(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T { // Handle nested impls (inside fn bodies) let previous_value = replace(&mut self.current_self_type, Some(self_type.clone())); let result = f(self); @@ -927,9 +911,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { result } - fn with_current_self_item(&mut self, self_item: &Item, f: F) -> T - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T - { + fn with_current_self_item(&mut self, self_item: &Item, f: impl FnOnce(&mut Self) -> T) -> T { let previous_value = replace(&mut self.current_self_item, Some(self_item.id)); let result = f(self); self.current_self_item = previous_value; @@ -937,9 +919,11 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } /// When evaluating a `trait` use its associated types' idents for suggestionsa in E0412. - fn with_trait_items(&mut self, trait_items: &Vec, f: F) -> T - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T - { + fn with_trait_items( + &mut self, + trait_items: &Vec, + f: impl FnOnce(&mut Self) -> T, + ) -> T { let trait_assoc_types = replace( &mut self.current_trait_assoc_types, trait_items.iter().filter_map(|item| match &item.node { @@ -953,9 +937,11 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`). - fn with_optional_trait_ref(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>, Option) -> T - { + fn with_optional_trait_ref( + &mut self, + opt_trait_ref: Option<&TraitRef>, + f: impl FnOnce(&mut Self, Option) -> T + ) -> T { let mut new_val = None; let mut new_id = None; if let Some(trait_ref) = opt_trait_ref { @@ -990,27 +976,18 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { result } - fn with_self_rib(&mut self, self_res: Res, f: F) - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) - { + fn with_self_rib_ns(&mut self, ns: Namespace, self_res: Res, f: impl FnOnce(&mut Self)) { let mut self_type_rib = Rib::new(NormalRibKind); // Plain insert (no renaming, since types are not currently hygienic) self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res); - self.ribs[TypeNS].push(self_type_rib); + self.ribs[ns].push(self_type_rib); f(self); - self.ribs[TypeNS].pop(); + self.ribs[ns].pop(); } - fn with_self_struct_ctor_rib(&mut self, impl_id: DefId, f: F) - where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) - { - let self_res = Res::SelfCtor(impl_id); - let mut self_type_rib = Rib::new(NormalRibKind); - self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res); - self.ribs[ValueNS].push(self_type_rib); - f(self); - self.ribs[ValueNS].pop(); + fn with_self_rib(&mut self, self_res: Res, f: impl FnOnce(&mut Self)) { + self.with_self_rib_ns(TypeNS, self_res, f) } fn resolve_implementation(&mut self, @@ -1038,8 +1015,8 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { this.visit_generics(generics); // Resolve the items within the impl. this.with_current_self_type(self_type, |this| { - this.with_self_struct_ctor_rib(item_def_id, |this| { - debug!("resolve_implementation with_self_struct_ctor_rib"); + this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| { + debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)"); for impl_item in impl_items { // We also need a new scope for the impl item type parameters. let generic_params = HasGenericParams(&impl_item.generics, @@ -1231,16 +1208,13 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } fn resolve_arm(&mut self, arm: &Arm) { - self.ribs[ValueNS].push(Rib::new(NormalRibKind)); - - self.resolve_pats(&arm.pats, PatternSource::Match); - - if let Some(ref expr) = arm.guard { - self.visit_expr(expr) - } - self.visit_expr(&arm.body); - - self.ribs[ValueNS].pop(); + self.with_rib(ValueNS, NormalRibKind, |this| { + this.resolve_pats(&arm.pats, PatternSource::Match); + if let Some(ref expr) = arm.guard { + this.visit_expr(expr) + } + this.visit_expr(&arm.body); + }); } /// Arising from `source`, resolve a sequence of patterns (top level or-patterns). @@ -1333,7 +1307,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { pat_src == PatternSource::Let => { // `Variant1(a) | Variant2(a)`, ok // Reuse definition from the first `a`. - res = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident]; + res = self.innermost_rib_bindings(ValueNS)[&ident]; } Some(..) => { span_bug!(ident.span, "two bindings with the same name from \ @@ -1343,7 +1317,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { // A completely fresh binding, add to the lists if it's valid. if ident.name != kw::Invalid { bindings.insert(ident, outer_pat_id); - self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident, res); + self.innermost_rib_bindings(ValueNS).insert(ident, res); } } } @@ -1351,6 +1325,10 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { res } + fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut FxHashMap { + &mut self.ribs[ns].last_mut().unwrap().bindings + } + fn resolve_pattern(&mut self, pat: &Pat, pat_src: PatternSource, @@ -1726,12 +1704,10 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { Some(result) } - fn with_resolved_label(&mut self, label: Option

\ \ {name}", id = id, @@ -3572,7 +3572,7 @@ fn item_enum(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, write!(w, ")")?; } } - write!(w, "")?; + write!(w, "
")?; document(w, cx, variant)?; document_non_exhaustive(w, variant)?; @@ -3583,7 +3583,7 @@ fn item_enum(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, let variant_id = cx.derive_id(format!("{}.{}.fields", ItemType::Variant, variant.name.as_ref().unwrap())); - write!(w, "", + write!(w, "
", id = variant_id)?; write!(w, "

Fields of {name}

", name = variant.name.as_ref().unwrap())?; @@ -3609,7 +3609,7 @@ fn item_enum(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, document(w, cx, field)?; } } - write!(w, "
")?; + write!(w, "
")?; } render_stability_since(w, variant, it)?; } From 0133941f47b039d652f5d9f2617b7d3884298515 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 25 Aug 2019 19:59:51 +0100 Subject: [PATCH 507/618] Add an ExpnKind for AST passes --- src/librustc/ich/impls_syntax.rs | 8 ++++++++ src/librustc/lint/mod.rs | 2 +- src/libsyntax_pos/hygiene.rs | 24 +++++++++++++++++++++++- src/libsyntax_pos/lib.rs | 1 + 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 05e2c7854b49c..532485b5d77bb 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -411,9 +411,17 @@ impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnData { impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnKind { Root, Macro(kind, descr), + AstPass(kind), Desugaring(kind) }); +impl_stable_hash_for!(enum ::syntax_pos::hygiene::AstPass { + StdImports, + TestHarness, + ProcMacroHarness, + PluginMacroDefs, +}); + impl_stable_hash_for!(enum ::syntax_pos::hygiene::DesugaringKind { CondTemporary, Async, diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 2b58627cdea56..1b133819a73bf 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -888,7 +888,7 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool { let expn_data = span.ctxt().outer_expn_data(); match expn_data.kind { ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false, - ExpnKind::Desugaring(_) => true, // well, it's "external" + ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external" ExpnKind::Macro(MacroKind::Bang, _) => { if expn_data.def_site.is_dummy() { // dummy span for the def_site means it's an external macro diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 733f6f0449065..237a02f2f667a 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -639,8 +639,9 @@ pub enum ExpnKind { /// No expansion, aka root expansion. Only `ExpnId::root()` has this kind. Root, /// Expansion produced by a macro. - /// FIXME: Some code injected by the compiler before HIR lowering also gets this kind. Macro(MacroKind, Symbol), + /// Transform done by the compiler on the AST. + AstPass(AstPass), /// Desugaring done by the compiler during HIR lowering. Desugaring(DesugaringKind) } @@ -650,6 +651,7 @@ impl ExpnKind { match *self { ExpnKind::Root => kw::PathRoot, ExpnKind::Macro(_, descr) => descr, + ExpnKind::AstPass(kind) => Symbol::intern(kind.descr()), ExpnKind::Desugaring(kind) => Symbol::intern(kind.descr()), } } @@ -683,6 +685,26 @@ impl MacroKind { } } +/// The kind of AST transform. +#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)] +pub enum AstPass { + StdImports, + TestHarness, + ProcMacroHarness, + PluginMacroDefs, +} + +impl AstPass { + fn descr(self) -> &'static str { + match self { + AstPass::StdImports => "standard library imports", + AstPass::TestHarness => "test harness", + AstPass::ProcMacroHarness => "proc macro harness", + AstPass::PluginMacroDefs => "plugin macro definitions", + } + } +} + /// The kind of compiler desugaring. #[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)] pub enum DesugaringKind { diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 3d8bfc77a8950..d800109cf8531 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -442,6 +442,7 @@ impl Span { let (pre, post) = match expn_data.kind { ExpnKind::Root => break, ExpnKind::Desugaring(..) => ("desugaring of ", ""), + ExpnKind::AstPass(..) => ("", ""), ExpnKind::Macro(macro_kind, _) => match macro_kind { MacroKind::Bang => ("", "!"), MacroKind::Attr => ("#[", "]"), From 4082cd95a8de6c8244e9b44908f9859e75acdeea Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 25 Aug 2019 20:58:03 +0100 Subject: [PATCH 508/618] Allow ast passes to create hygienic spans --- src/librustc_resolve/build_reduced_graph.rs | 3 +- src/librustc_resolve/lib.rs | 22 ++++++++++++ src/librustc_resolve/macros.rs | 39 ++++++++++++++++++++- src/libsyntax/ext/base.rs | 10 +++++- src/libsyntax_pos/hygiene.rs | 2 +- 5 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 9a794ade729c2..5a3b768301ce0 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -126,7 +126,8 @@ impl<'a> Resolver<'a> { crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> { let def_id = match self.macro_defs.get(&expn_id) { Some(def_id) => *def_id, - None => return self.graph_root, + None => return self.ast_transform_scopes.get(&expn_id) + .unwrap_or(&self.graph_root), }; if let Some(id) = self.definitions.as_local_node_id(def_id) { self.local_macro_def_scopes[&id] diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 875ae449d94e0..b12bf4521e098 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -879,6 +879,10 @@ pub struct Resolver<'a> { /// There will be an anonymous module created around `g` with the ID of the /// entry block for `f`. block_map: NodeMap>, + /// A fake module that contains no definition and no prelude. Used so that + /// some AST passes can generate identifiers that only resolve to local or + /// language items. + empty_module: Module<'a>, module_map: FxHashMap>, extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>, binding_parent_modules: FxHashMap>, Module<'a>>, @@ -913,6 +917,7 @@ pub struct Resolver<'a> { non_macro_attrs: [Lrc; 2], macro_defs: FxHashMap, local_macro_def_scopes: FxHashMap>, + ast_transform_scopes: FxHashMap>, unused_macros: NodeMap, proc_macro_stubs: NodeSet, /// Traces collected during macro resolution and validated when it's complete. @@ -1080,6 +1085,21 @@ impl<'a> Resolver<'a> { no_implicit_prelude: attr::contains_name(&krate.attrs, sym::no_implicit_prelude), ..ModuleData::new(None, root_module_kind, root_def_id, ExpnId::root(), krate.span) }); + let empty_module_kind = ModuleKind::Def( + DefKind::Mod, + root_def_id, + kw::Invalid, + ); + let empty_module = arenas.alloc_module(ModuleData { + no_implicit_prelude: true, + ..ModuleData::new( + Some(graph_root), + empty_module_kind, + root_def_id, + ExpnId::root(), + DUMMY_SP, + ) + }); let mut module_map = FxHashMap::default(); module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root); @@ -1139,10 +1159,12 @@ impl<'a> Resolver<'a> { label_res_map: Default::default(), export_map: FxHashMap::default(), trait_map: Default::default(), + empty_module, module_map, block_map: Default::default(), extern_module_map: FxHashMap::default(), binding_parent_modules: FxHashMap::default(), + ast_transform_scopes: FxHashMap::default(), glob_map: Default::default(), diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 719167eb057b2..fe7eae91945f7 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -8,6 +8,7 @@ use crate::{ModuleOrUniformRoot, KNOWN_TOOLS}; use crate::Namespace::*; use crate::resolve_imports::ImportResolver; use rustc::hir::def::{self, DefKind, NonMacroAttrKind}; +use rustc::hir::def_id; use rustc::middle::stability; use rustc::{ty, lint, span_bug}; use syntax::ast::{self, NodeId, Ident}; @@ -16,7 +17,7 @@ use syntax::edition::Edition; use syntax::ext::base::{self, Indeterminate, SpecialDerives}; use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; -use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind}; +use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind, Transparency}; use syntax::ext::tt::macro_rules; use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name}; use syntax::feature_gate::GateIssue; @@ -25,6 +26,7 @@ use syntax_pos::{Span, DUMMY_SP}; use std::{mem, ptr}; use rustc_data_structures::sync::Lrc; +use syntax_pos::hygiene::AstPass; type Res = def::Res; @@ -136,6 +138,41 @@ impl<'a> base::Resolver for Resolver<'a> { } } + // Create a Span with modern hygiene with a definition site of the provided + // module, or a fake empty `#[no_implicit_prelude]` module if no module is + // provided. + fn span_for_ast_pass( + &mut self, + base_span: Span, + pass: AstPass, + features: &[Symbol], + parent_module_id: Option, + ) -> Span { + let span = base_span.fresh_expansion_with_transparency( + ExpnData::allow_unstable( + ExpnKind::AstPass(pass), + base_span, + self.session.edition(), + features.into(), + ), + Transparency::Opaque, + ); + let expn_id = span.ctxt().outer_expn(); + let parent_scope = if let Some(module_id) = parent_module_id { + let parent_def_id = self.definitions.local_def_id(module_id); + self.definitions.add_parent_module_of_macro_def(expn_id, parent_def_id); + self.module_map[&parent_def_id] + } else { + self.definitions.add_parent_module_of_macro_def( + expn_id, + def_id::DefId::local(def_id::CRATE_DEF_INDEX), + ); + self.empty_module + }; + self.ast_transform_scopes.insert(expn_id, parent_scope); + span + } + fn resolve_imports(&mut self) { ImportResolver { r: self }.resolve_imports() } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index a63c4181d5e03..3d274af99083c 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -15,7 +15,7 @@ use crate::tokenstream::{self, TokenStream, TokenTree}; use errors::{DiagnosticBuilder, DiagnosticId}; use smallvec::{smallvec, SmallVec}; use syntax_pos::{FileName, Span, MultiSpan, DUMMY_SP}; -use syntax_pos::hygiene::{ExpnData, ExpnKind}; +use syntax_pos::hygiene::{AstPass, ExpnData, ExpnKind}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; @@ -660,6 +660,14 @@ pub trait Resolver { extra_placeholders: &[NodeId]); fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension); + fn span_for_ast_pass( + &mut self, + span: Span, + pass: AstPass, + features: &[Symbol], + parent_module_id: Option, + ) -> Span; + fn resolve_imports(&mut self); fn resolve_macro_invocation( diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 237a02f2f667a..99afe57ef5497 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -550,7 +550,7 @@ impl Span { /// The returned span belongs to the created expansion and has the new properties, /// but its location is inherited from the current span. pub fn fresh_expansion(self, expn_data: ExpnData) -> Span { - self.fresh_expansion_with_transparency(expn_data, Transparency::SemiTransparent) + self.fresh_expansion_with_transparency(expn_data, Transparency::Transparent) } pub fn fresh_expansion_with_transparency( From 6fcdb36ccb60cca5c26ac804770a47fc01e0c2dd Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 25 Aug 2019 21:03:24 +0100 Subject: [PATCH 509/618] Make use of hygiene in AST passes --- src/librustc_interface/passes.rs | 27 +-- src/librustc_resolve/macros.rs | 10 - src/libsyntax/ext/base.rs | 2 - src/libsyntax_ext/plugin_macro_defs.rs | 4 +- src/libsyntax_ext/proc_macro_harness.rs | 86 +++++---- src/libsyntax_ext/standard_library_imports.rs | 130 +++++++++---- src/libsyntax_ext/test.rs | 19 +- src/libsyntax_ext/test_harness.rs | 175 +++++------------- src/test/ui/hygiene/auxiliary/not-libstd.rs | 1 + src/test/ui/hygiene/prelude-import-hygiene.rs | 29 +++ src/test/ui/imports/gensymed.rs | 4 +- src/test/ui/inaccessible-test-modules.stderr | 21 --- src/test/ui/test-attrs/decl-macro-test.rs | 22 +++ .../inaccessible-test-modules.rs | 4 +- .../inaccessible-test-modules.stderr | 21 +++ 15 files changed, 298 insertions(+), 257 deletions(-) create mode 100644 src/test/ui/hygiene/auxiliary/not-libstd.rs create mode 100644 src/test/ui/hygiene/prelude-import-hygiene.rs delete mode 100644 src/test/ui/inaccessible-test-modules.stderr create mode 100644 src/test/ui/test-attrs/decl-macro-test.rs rename src/test/ui/{ => test-attrs}/inaccessible-test-modules.rs (56%) create mode 100644 src/test/ui/test-attrs/inaccessible-test-modules.stderr diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 8b0b5a5b7a2bd..649cc8a2fb515 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -233,7 +233,7 @@ pub fn register_plugins<'a>( syntax::attr::inject(krate, &sess.parse_sess, &sess.opts.debugging_opts.crate_attr) }); - let (mut krate, features) = syntax::config::features( + let (krate, features) = syntax::config::features( krate, &sess.parse_sess, sess.edition(), @@ -268,16 +268,6 @@ pub fn register_plugins<'a>( middle::recursion_limit::update_limits(sess, &krate); }); - krate = time(sess, "crate injection", || { - let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| &**s); - let (krate, name) = - syntax_ext::standard_library_imports::inject(krate, alt_std_name, sess.edition()); - if let Some(name) = name { - sess.parse_sess.injected_crate_name.set(name); - } - krate - }); - let registrars = time(sess, "plugin loading", || { plugin::load::load_plugins( sess, @@ -370,6 +360,21 @@ fn configure_and_expand_inner<'a>( &resolver_arenas, ); syntax_ext::register_builtin_macros(&mut resolver, sess.edition()); + + krate = time(sess, "crate injection", || { + let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s)); + let (krate, name) = syntax_ext::standard_library_imports::inject( + krate, + &mut resolver, + alt_std_name, + sess.edition(), + ); + if let Some(name) = name { + sess.parse_sess.injected_crate_name.set(name); + } + krate + }); + syntax_ext::plugin_macro_defs::inject( &mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition() ); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index fe7eae91945f7..20d281f1e997a 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -97,16 +97,6 @@ impl<'a> base::Resolver for Resolver<'a> { self.session.next_node_id() } - fn get_module_scope(&mut self, id: NodeId) -> ExpnId { - let expn_id = ExpnId::fresh(Some(ExpnData::default( - ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, self.session.edition() - ))); - let module = self.module_map[&self.definitions.local_def_id(id)]; - self.invocation_parent_scopes.insert(expn_id, ParentScope::module(module)); - self.definitions.set_invocation_parent(expn_id, module.def_id().unwrap().index); - expn_id - } - fn resolve_dollar_crates(&mut self) { hygiene::update_dollar_crate_names(|ctxt| { let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt)); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 3d274af99083c..962447e8cf07f 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -653,8 +653,6 @@ bitflags::bitflags! { pub trait Resolver { fn next_node_id(&mut self) -> NodeId; - fn get_module_scope(&mut self, id: NodeId) -> ExpnId; - fn resolve_dollar_crates(&mut self); fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment, extra_placeholders: &[NodeId]); diff --git a/src/libsyntax_ext/plugin_macro_defs.rs b/src/libsyntax_ext/plugin_macro_defs.rs index dbfd8fe98f389..ccdc5bd81a04b 100644 --- a/src/libsyntax_ext/plugin_macro_defs.rs +++ b/src/libsyntax_ext/plugin_macro_defs.rs @@ -11,7 +11,7 @@ use syntax::source_map::respan; use syntax::symbol::sym; use syntax::tokenstream::*; use syntax_pos::{Span, DUMMY_SP}; -use syntax_pos::hygiene::{ExpnData, ExpnKind, MacroKind}; +use syntax_pos::hygiene::{ExpnData, ExpnKind, AstPass}; use std::mem; @@ -44,7 +44,7 @@ pub fn inject( if !named_exts.is_empty() { let mut extra_items = Vec::new(); let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable( - ExpnKind::Macro(MacroKind::Attr, sym::plugin), DUMMY_SP, edition, + ExpnKind::AstPass(AstPass::PluginMacroDefs), DUMMY_SP, edition, [sym::rustc_attrs][..].into(), )); for (name, ext) in named_exts { diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs index e772eaf834964..1cdaa1190fae3 100644 --- a/src/libsyntax_ext/proc_macro_harness.rs +++ b/src/libsyntax_ext/proc_macro_harness.rs @@ -3,8 +3,7 @@ use std::mem; use smallvec::smallvec; use syntax::ast::{self, Ident}; use syntax::attr; -use syntax::source_map::{ExpnData, ExpnKind, respan}; -use syntax::ext::base::{ExtCtxt, MacroKind}; +use syntax::ext::base::ExtCtxt; use syntax::ext::expand::{AstFragment, ExpansionConfig}; use syntax::ext::proc_macro::is_proc_macro_attr; use syntax::parse::ParseSess; @@ -12,6 +11,7 @@ use syntax::ptr::P; use syntax::symbol::{kw, sym}; use syntax::visit::{self, Visitor}; use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::hygiene::AstPass; struct ProcMacroDerive { trait_name: ast::Name, @@ -308,8 +308,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { // Creates a new module which looks like: // -// #[doc(hidden)] -// mod $gensym { +// const _: () = { // extern crate proc_macro; // // use proc_macro::bridge::client::ProcMacro; @@ -327,32 +326,29 @@ fn mk_decls( custom_attrs: &[ProcMacroDef], custom_macros: &[ProcMacroDef], ) -> P { - let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable( - ExpnKind::Macro(MacroKind::Attr, sym::proc_macro), DUMMY_SP, cx.parse_sess.edition, - [sym::rustc_attrs, sym::proc_macro_internals][..].into(), - )); - - let hidden = cx.meta_list_item_word(span, sym::hidden); - let doc = cx.meta_list(span, sym::doc, vec![hidden]); - let doc_hidden = cx.attribute(doc); - - let proc_macro = Ident::with_dummy_span(sym::proc_macro); + let span = cx.resolver.span_for_ast_pass( + DUMMY_SP, + AstPass::ProcMacroHarness, + &[sym::rustc_attrs, sym::proc_macro_internals], + None, + ); + + let proc_macro = Ident::new(sym::proc_macro, span); let krate = cx.item(span, proc_macro, Vec::new(), ast::ItemKind::ExternCrate(None)); - let bridge = Ident::from_str("bridge"); - let client = Ident::from_str("client"); - let proc_macro_ty = Ident::from_str("ProcMacro"); - let custom_derive = Ident::from_str("custom_derive"); - let attr = Ident::from_str("attr"); - let bang = Ident::from_str("bang"); - let crate_kw = Ident::with_dummy_span(kw::Crate); + let bridge = Ident::from_str_and_span("bridge", span); + let client = Ident::from_str_and_span("client", span); + let proc_macro_ty = Ident::from_str_and_span("ProcMacro", span); + let custom_derive = Ident::from_str_and_span("custom_derive", span); + let attr = Ident::from_str_and_span("attr", span); + let bang = Ident::from_str_and_span("bang", span); let decls = { let local_path = |sp: Span, name| { - cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![crate_kw, name])) + cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![name])) }; let proc_macro_ty_method_path = |method| cx.expr_path(cx.path(span, vec![ proc_macro, bridge, client, proc_macro_ty, method, @@ -381,7 +377,7 @@ fn mk_decls( let decls_static = cx.item_static( span, - Ident::from_str("_DECLS"), + Ident::from_str_and_span("_DECLS", span), cx.ty_rptr(span, cx.ty(span, ast::TyKind::Slice( cx.ty_path(cx.path(span, @@ -392,22 +388,44 @@ fn mk_decls( ).map(|mut i| { let attr = cx.meta_word(span, sym::rustc_proc_macro_decls); i.attrs.push(cx.attribute(attr)); - i.vis = respan(span, ast::VisibilityKind::Public); i }); - let module = cx.item_mod( - span, + let block = P(ast::Expr { + id: ast::DUMMY_NODE_ID, + attrs: syntax::ThinVec::new(), + node: ast::ExprKind::Block(P(ast::Block { + id: ast::DUMMY_NODE_ID, + rules: ast::BlockCheckMode::Default, + stmts: vec![ + ast::Stmt { + id: ast::DUMMY_NODE_ID, + node: ast::StmtKind::Item(krate), + span, + }, + ast::Stmt { + id: ast::DUMMY_NODE_ID, + node: ast::StmtKind::Item(decls_static), + span, + } + ], + span, + }), None), span, - ast::Ident::from_str("decls").gensym(), - vec![doc_hidden], - vec![krate, decls_static], - ).map(|mut i| { - i.vis = respan(span, ast::VisibilityKind::Public); - i }); + let anon_constant = cx.item_const( + span, + ast::Ident::new(kw::Underscore, span), + P(ast::Ty { + id: ast::DUMMY_NODE_ID, + node: ast::TyKind::Tup(Vec::new()), + span, + }), + block, + ); + // Integrate the new module into existing module structures. - let module = AstFragment::Items(smallvec![module]); - cx.monotonic_expander().fully_expand_fragment(module).make_items().pop().unwrap() + let items = AstFragment::Items(smallvec![anon_constant]); + cx.monotonic_expander().fully_expand_fragment(items).make_items().pop().unwrap() } diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs index 8ca376341fcdb..61e423266fa05 100644 --- a/src/libsyntax_ext/standard_library_imports.rs +++ b/src/libsyntax_ext/standard_library_imports.rs @@ -1,52 +1,56 @@ use syntax::{ast, attr}; use syntax::edition::Edition; -use syntax::ext::hygiene::MacroKind; +use syntax::ext::hygiene::AstPass; +use syntax::ext::base::Resolver; use syntax::ptr::P; -use syntax::source_map::{ExpnData, ExpnKind, dummy_spanned, respan}; +use syntax::source_map::respan; use syntax::symbol::{Ident, Symbol, kw, sym}; use syntax_pos::DUMMY_SP; -use std::iter; - pub fn inject( - mut krate: ast::Crate, alt_std_name: Option<&str>, edition: Edition + mut krate: ast::Crate, + resolver: &mut dyn Resolver, + alt_std_name: Option, + edition: Edition, ) -> (ast::Crate, Option) { let rust_2018 = edition >= Edition::Edition2018; // the first name in this list is the crate name of the crate with the prelude - let names: &[&str] = if attr::contains_name(&krate.attrs, sym::no_core) { + let names: &[Symbol] = if attr::contains_name(&krate.attrs, sym::no_core) { return (krate, None); } else if attr::contains_name(&krate.attrs, sym::no_std) { if attr::contains_name(&krate.attrs, sym::compiler_builtins) { - &["core"] + &[sym::core] } else { - &["core", "compiler_builtins"] + &[sym::core, sym::compiler_builtins] } } else { - &["std"] + &[sym::std] }; + let span = resolver.span_for_ast_pass( + DUMMY_SP, + AstPass::StdImports, + &[sym::prelude_import], + None, + ); + // .rev() to preserve ordering above in combination with insert(0, ...) - let alt_std_name = alt_std_name.map(Symbol::intern); - for orig_name_str in names.iter().rev() { - // HACK(eddyb) gensym the injected crates on the Rust 2018 edition, - // so they don't accidentally interfere with the new import paths. - let orig_name_sym = Symbol::intern(orig_name_str); - let orig_name_ident = Ident::with_dummy_span(orig_name_sym); + for &orig_name_sym in names.iter().rev() { let (rename, orig_name) = if rust_2018 { - (orig_name_ident.gensym(), Some(orig_name_sym)) + (Ident::new(kw::Underscore, span), Some(orig_name_sym)) } else { - (orig_name_ident, None) + (Ident::with_dummy_span(orig_name_sym), None) }; krate.module.items.insert(0, P(ast::Item { attrs: vec![attr::mk_attr_outer( - attr::mk_word_item(ast::Ident::with_dummy_span(sym::macro_use)) + attr::mk_word_item(ast::Ident::new(sym::macro_use, span)) )], - vis: dummy_spanned(ast::VisibilityKind::Inherited), + vis: respan(span, ast::VisibilityKind::Inherited), node: ast::ItemKind::ExternCrate(alt_std_name.or(orig_name)), ident: rename, id: ast::DUMMY_NODE_ID, - span: DUMMY_SP, + span, tokens: None, })); } @@ -55,24 +59,22 @@ pub fn inject( // the prelude. let name = names[0]; - let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable( - ExpnKind::Macro(MacroKind::Attr, sym::std_inject), DUMMY_SP, edition, - [sym::prelude_import][..].into(), - )); + let segments = if rust_2018 { + [name, sym::prelude, sym::v1].iter() + .map(|symbol| ast::PathSegment::from_ident(ast::Ident::new(*symbol, span))) + .collect() + } else { + [kw::PathRoot, name, sym::prelude, sym::v1].iter() + .map(|symbol| ast::PathSegment::from_ident(ast::Ident::with_dummy_span(*symbol))) + .collect() + }; - krate.module.items.insert(0, P(ast::Item { + let use_item = P(ast::Item { attrs: vec![attr::mk_attr_outer( attr::mk_word_item(ast::Ident::new(sym::prelude_import, span)))], vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), node: ast::ItemKind::Use(P(ast::UseTree { - prefix: ast::Path { - segments: iter::once(ast::Ident::with_dummy_span(kw::PathRoot)) - .chain( - [name, "prelude", "v1"].iter().cloned() - .map(ast::Ident::from_str) - ).map(ast::PathSegment::from_ident).collect(), - span, - }, + prefix: ast::Path { segments, span }, kind: ast::UseTreeKind::Glob, span, })), @@ -80,7 +82,65 @@ pub fn inject( ident: ast::Ident::invalid(), span, tokens: None, - })); + }); + + let prelude_import_item = if rust_2018 { + let hygienic_extern_crate = P(ast::Item { + attrs: vec![], + vis: respan(span, ast::VisibilityKind::Inherited), + node: ast::ItemKind::ExternCrate(alt_std_name), + ident: ast::Ident::new(name, span), + id: ast::DUMMY_NODE_ID, + span, + tokens: None, + }); + + // Use an anonymous const to hide `extern crate std as hygienic_std` + // FIXME: Once inter-crate hygiene exists, this can just be `use_item`. + P(ast::Item { + attrs: Vec::new(), + vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), + node: ast::ItemKind::Const( + P(ast::Ty { + id: ast::DUMMY_NODE_ID, + node: ast::TyKind::Tup(Vec::new()), + span, + }), + P(ast::Expr { + id: ast::DUMMY_NODE_ID, + attrs: syntax::ThinVec::new(), + node: ast::ExprKind::Block(P(ast::Block { + id: ast::DUMMY_NODE_ID, + rules: ast::BlockCheckMode::Default, + stmts: vec![ + ast::Stmt { + id: ast::DUMMY_NODE_ID, + node: ast::StmtKind::Item(use_item), + span, + }, + ast::Stmt { + id: ast::DUMMY_NODE_ID, + node: ast::StmtKind::Item(hygienic_extern_crate), + span, + } + ], + span, + }), None), + span, + }) + ), + id: ast::DUMMY_NODE_ID, + ident: ast::Ident::new(kw::Underscore, span), + span, + tokens: None, + }) + } else { + // Have `extern crate std` at the root, so don't need to create a named + // extern crate item. + use_item + }; + + krate.module.items.insert(0, prelude_import_item); - (krate, Some(Symbol::intern(name))) + (krate, Some(name)) } diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index 5fd87d3a0e5c6..be5aca73f5cb1 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -28,11 +28,11 @@ pub fn expand_test_case( if !ecx.ecfg.should_test { return vec![]; } - let sp = ecx.with_legacy_ctxt(attr_sp); + let sp = ecx.with_def_site_ctxt(attr_sp); let mut item = anno_item.expect_item(); item = item.map(|mut item| { item.vis = respan(item.vis.span, ast::VisibilityKind::Public); - item.ident = item.ident.gensym(); + item.ident.span = item.ident.span.with_ctxt(sp.ctxt()); item.attrs.push( ecx.attribute(ecx.meta_word(sp, sym::rustc_test_marker)) ); @@ -92,10 +92,9 @@ pub fn expand_test_or_bench( return vec![Annotatable::Item(item)]; } - let (sp, attr_sp) = (cx.with_legacy_ctxt(item.span), cx.with_legacy_ctxt(attr_sp)); + let (sp, attr_sp) = (cx.with_def_site_ctxt(item.span), cx.with_def_site_ctxt(attr_sp)); - // Gensym "test" so we can extern crate without conflicting with any local names - let test_id = cx.ident_of("test").gensym(); + let test_id = ast::Ident::new(sym::test, attr_sp); // creates test::$name let test_path = |name| { @@ -112,7 +111,7 @@ pub fn expand_test_or_bench( let test_fn = if is_bench { // A simple ident for a lambda - let b = cx.ident_of("b"); + let b = ast::Ident::from_str_and_span("b", attr_sp); cx.expr_call(sp, cx.expr_path(test_path("StaticBenchFn")), vec![ // |b| self::test::assert_test_result( @@ -143,7 +142,7 @@ pub fn expand_test_or_bench( ]) }; - let mut test_const = cx.item(sp, ast::Ident::new(item.ident.name, sp).gensym(), + let mut test_const = cx.item(sp, ast::Ident::new(item.ident.name, sp), vec![ // #[cfg(test)] cx.attribute(cx.meta_list(attr_sp, sym::cfg, vec![ @@ -192,17 +191,17 @@ pub fn expand_test_or_bench( )); test_const = test_const.map(|mut tc| { tc.vis.node = ast::VisibilityKind::Public; tc}); - // extern crate test as test_gensym + // extern crate test let test_extern = cx.item(sp, test_id, vec![], - ast::ItemKind::ExternCrate(Some(sym::test)) + ast::ItemKind::ExternCrate(None) ); log::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const)); vec![ - // Access to libtest under a gensymed name + // Access to libtest under a hygienic name Annotatable::Item(test_extern), // The generated test case Annotatable::Item(test_const), diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs index 4a6ea0ebf85e5..6eb132979df8f 100644 --- a/src/libsyntax_ext/test_harness.rs +++ b/src/libsyntax_ext/test_harness.rs @@ -5,32 +5,29 @@ use smallvec::{smallvec, SmallVec}; use syntax::ast::{self, Ident}; use syntax::attr; use syntax::entry::{self, EntryPointType}; -use syntax::ext::base::{ExtCtxt, MacroKind, Resolver}; +use syntax::ext::base::{ExtCtxt, Resolver}; use syntax::ext::expand::{AstFragment, ExpansionConfig}; use syntax::feature_gate::Features; use syntax::mut_visit::{*, ExpectOne}; use syntax::parse::ParseSess; use syntax::ptr::P; -use syntax::source_map::{ExpnData, ExpnKind, dummy_spanned}; -use syntax::symbol::{kw, sym, Symbol}; +use syntax::source_map::respan; +use syntax::symbol::{sym, Symbol}; use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::hygiene::{AstPass, SyntaxContext, Transparency}; use std::{iter, mem}; struct Test { span: Span, - path: Vec, + ident: Ident, } struct TestCtxt<'a> { - span_diagnostic: &'a errors::Handler, - path: Vec, ext_cx: ExtCtxt<'a>, test_cases: Vec, reexport_test_harness_main: Option, test_runner: Option, - // top-level re-export submodule, filled out after folding is finished - toplevel_reexport: Option, } // Traverse the crate, collecting all the test functions, eliding any @@ -43,8 +40,8 @@ pub fn inject( span_diagnostic: &errors::Handler, features: &Features, ) { - // Check for #[reexport_test_harness_main = "some_name"] which - // creates a `use __test::main as some_name;`. This needs to be + // Check for #![reexport_test_harness_main = "some_name"] which gives the + // main test function the name `some_name` without hygiene. This needs to be // unconditional, so that the attribute is still marked as used in // non-test builds. let reexport_test_harness_main = @@ -56,16 +53,13 @@ pub fn inject( if should_test { generate_test_harness(sess, resolver, reexport_test_harness_main, - krate, span_diagnostic, features, test_runner) + krate, features, test_runner) } } struct TestHarnessGenerator<'a> { cx: TestCtxt<'a>, - tests: Vec, - - // submodule name, gensym'd identifier for re-exports - tested_submods: Vec<(Ident, Ident)>, + tests: Vec, } impl<'a> MutVisitor for TestHarnessGenerator<'a> { @@ -77,49 +71,46 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { } fn flat_map_item(&mut self, i: P) -> SmallVec<[P; 1]> { - let ident = i.ident; - if ident.name != kw::Invalid { - self.cx.path.push(ident); - } - debug!("current path: {}", path_name_i(&self.cx.path)); - let mut item = i.into_inner(); if is_test_case(&item) { debug!("this is a test item"); let test = Test { span: item.span, - path: self.cx.path.clone(), + ident: item.ident, }; - self.cx.test_cases.push(test); - self.tests.push(item.ident); + self.tests.push(test); } // We don't want to recurse into anything other than mods, since // mods or tests inside of functions will break things if let ast::ItemKind::Mod(mut module) = item.node { let tests = mem::take(&mut self.tests); - let tested_submods = mem::take(&mut self.tested_submods); noop_visit_mod(&mut module, self); - let tests = mem::replace(&mut self.tests, tests); - let tested_submods = mem::replace(&mut self.tested_submods, tested_submods); + let mut tests = mem::replace(&mut self.tests, tests); - if !tests.is_empty() || !tested_submods.is_empty() { - let (it, sym) = mk_reexport_mod(&mut self.cx, item.id, tests, tested_submods); - module.items.push(it); - - if !self.cx.path.is_empty() { - self.tested_submods.push((self.cx.path[self.cx.path.len()-1], sym)); + if !tests.is_empty() { + let parent = if item.id == ast::DUMMY_NODE_ID { + ast::CRATE_NODE_ID } else { - debug!("pushing nothing, sym: {:?}", sym); - self.cx.toplevel_reexport = Some(sym); + item.id + }; + // Create an identifier that will hygienically resolve the test + // case name, even in another module. + let sp = self.cx.ext_cx.resolver.span_for_ast_pass( + module.inner, + AstPass::TestHarness, + &[], + Some(parent), + ); + let expn = sp.ctxt().outer_expn(); + for test in &mut tests { + test.ident.span = test.ident.span.apply_mark(expn, Transparency::Opaque); } + self.cx.test_cases.extend(tests); } item.node = ast::ItemKind::Mod(module); } - if ident.name != kw::Invalid { - self.cx.path.pop(); - } smallvec![P(item)] } @@ -181,59 +172,11 @@ impl MutVisitor for EntryPointCleaner { } } -/// Creates an item (specifically a module) that "pub use"s the tests passed in. -/// Each tested submodule will contain a similar reexport module that we will export -/// under the name of the original module. That is, `submod::__test_reexports` is -/// reexported like so `pub use submod::__test_reexports as submod`. -fn mk_reexport_mod(cx: &mut TestCtxt<'_>, - parent: ast::NodeId, - tests: Vec, - tested_submods: Vec<(Ident, Ident)>) - -> (P, Ident) { - let super_ = Ident::with_dummy_span(kw::Super); - - let items = tests.into_iter().map(|r| { - cx.ext_cx.item_use_simple(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), - cx.ext_cx.path(DUMMY_SP, vec![super_, r])) - }).chain(tested_submods.into_iter().map(|(r, sym)| { - let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]); - cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), - Some(r), path) - })).collect(); - - let reexport_mod = ast::Mod { - inline: true, - inner: DUMMY_SP, - items, - }; - - let name = Ident::from_str("__test_reexports").gensym(); - let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent }; - cx.ext_cx.current_expansion.id = cx.ext_cx.resolver.get_module_scope(parent); - let module = P(ast::Item { - ident: name, - attrs: Vec::new(), - id: ast::DUMMY_NODE_ID, - node: ast::ItemKind::Mod(reexport_mod), - vis: dummy_spanned(ast::VisibilityKind::Public), - span: DUMMY_SP, - tokens: None, - }); - - // Integrate the new module into existing module structures. - let module = AstFragment::Items(smallvec![module]); - let module = - cx.ext_cx.monotonic_expander().fully_expand_fragment(module).make_items().pop().unwrap(); - - (module, name) -} - /// Crawl over the crate, inserting test reexports and the test main function fn generate_test_harness(sess: &ParseSess, resolver: &mut dyn Resolver, reexport_test_harness_main: Option, krate: &mut ast::Crate, - sd: &errors::Handler, features: &Features, test_runner: Option) { // Remove the entry points @@ -244,19 +187,15 @@ fn generate_test_harness(sess: &ParseSess, econfig.features = Some(features); let cx = TestCtxt { - span_diagnostic: sd, ext_cx: ExtCtxt::new(sess, econfig, resolver), - path: Vec::new(), test_cases: Vec::new(), reexport_test_harness_main, - toplevel_reexport: None, test_runner }; TestHarnessGenerator { cx, tests: Vec::new(), - tested_submods: Vec::new(), }.visit_crate(krate); } @@ -268,12 +207,14 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { // #![main] // test::test_main_static(&[..tests]); // } - let sp = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable( - ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, cx.ext_cx.parse_sess.edition, - [sym::main, sym::test, sym::rustc_attrs][..].into(), - )); + let sp = cx.ext_cx.resolver.span_for_ast_pass( + DUMMY_SP, + AstPass::TestHarness, + &[sym::main, sym::test, sym::rustc_attrs], + None, + ); let ecx = &cx.ext_cx; - let test_id = Ident::with_dummy_span(sym::test); + let test_id = Ident::new(sym::test, sp); // test::test_main_static(...) let mut test_runner = cx.test_runner.clone().unwrap_or( @@ -285,14 +226,14 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let test_main_path_expr = ecx.expr_path(test_runner); let call_test_main = ecx.expr_call(sp, test_main_path_expr, - vec![mk_tests_slice(cx)]); + vec![mk_tests_slice(cx, sp)]); let call_test_main = ecx.stmt_expr(call_test_main); // #![main] let main_meta = ecx.meta_word(sp, sym::main); let main_attr = ecx.attribute(main_meta); - // extern crate test as test_gensym + // extern crate test let test_extern_stmt = ecx.stmt_item(sp, ecx.item(sp, test_id, vec![], @@ -316,8 +257,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { // Honor the reexport_test_harness_main attribute let main_id = match cx.reexport_test_harness_main { - Some(sym) => Ident::new(sym, sp), - None => Ident::from_str_and_span("main", sp).gensym(), + Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())), + None => Ident::from_str_and_span("main", sp), }; let main = P(ast::Item { @@ -325,7 +266,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { attrs: vec![main_attr], id: ast::DUMMY_NODE_ID, node: main, - vis: dummy_spanned(ast::VisibilityKind::Public), + vis: respan(sp, ast::VisibilityKind::Public), span: sp, tokens: None, }); @@ -335,44 +276,20 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { cx.ext_cx.monotonic_expander().fully_expand_fragment(main).make_items().pop().unwrap() } -fn path_name_i(idents: &[Ident]) -> String { - let mut path_name = "".to_string(); - let mut idents_iter = idents.iter().peekable(); - while let Some(ident) = idents_iter.next() { - path_name.push_str(&ident.as_str()); - if idents_iter.peek().is_some() { - path_name.push_str("::") - } - } - path_name -} - /// Creates a slice containing every test like so: -/// &[path::to::test1, path::to::test2] -fn mk_tests_slice(cx: &TestCtxt<'_>) -> P { +/// &[test1, test2] +fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P { debug!("building test vector from {} tests", cx.test_cases.len()); let ref ecx = cx.ext_cx; - ecx.expr_vec_slice(DUMMY_SP, + + ecx.expr_vec_slice(sp, cx.test_cases.iter().map(|test| { ecx.expr_addr_of(test.span, - ecx.expr_path(ecx.path(test.span, visible_path(cx, &test.path)))) + ecx.expr_path(ecx.path(test.span, vec![test.ident]))) }).collect()) } -/// Creates a path from the top-level __test module to the test via __test_reexports -fn visible_path(cx: &TestCtxt<'_>, path: &[Ident]) -> Vec{ - let mut visible_path = vec![]; - match cx.toplevel_reexport { - Some(id) => visible_path.push(id), - None => { - cx.span_diagnostic.bug("expected to find top-level re-export name, but found None"); - } - } - visible_path.extend_from_slice(path); - visible_path -} - fn is_test_case(i: &ast::Item) -> bool { attr::contains_name(&i.attrs, sym::rustc_test_marker) } diff --git a/src/test/ui/hygiene/auxiliary/not-libstd.rs b/src/test/ui/hygiene/auxiliary/not-libstd.rs new file mode 100644 index 0000000000000..babba293d03bd --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/not-libstd.rs @@ -0,0 +1 @@ +pub fn not_in_lib_std() {} diff --git a/src/test/ui/hygiene/prelude-import-hygiene.rs b/src/test/ui/hygiene/prelude-import-hygiene.rs new file mode 100644 index 0000000000000..51e7bed6580b3 --- /dev/null +++ b/src/test/ui/hygiene/prelude-import-hygiene.rs @@ -0,0 +1,29 @@ +// Make sure that attribute used when injecting the prelude are resolved +// hygienically. + +// check-pass +// aux-build:not-libstd.rs + +//revisions: rust2015 rust2018 +//[rust2018] edition:2018 + +// The prelude import shouldn't see these as candidates for when it's trying to +// use the built-in macros. +extern crate core; +use core::prelude::v1::test as prelude_import; +use core::prelude::v1::test as macro_use; + +// Should not be used for the prelude import - not a concern in the 2015 edition +// because `std` is already declared in the crate root. +#[cfg(rust2018)] +extern crate not_libstd as std; + +#[cfg(rust2018)] +mod x { + // The extern crate item should override `std` in the extern prelude. + fn f() { + std::not_in_lib_std(); + } +} + +fn main() {} diff --git a/src/test/ui/imports/gensymed.rs b/src/test/ui/imports/gensymed.rs index 613ccc0b24234..7b53f0c536ad9 100644 --- a/src/test/ui/imports/gensymed.rs +++ b/src/test/ui/imports/gensymed.rs @@ -1,7 +1,9 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass // edition:2018 // aux-build:gensymed.rs extern crate gensymed; +use gensymed::*; + fn main() {} diff --git a/src/test/ui/inaccessible-test-modules.stderr b/src/test/ui/inaccessible-test-modules.stderr deleted file mode 100644 index b6a817e6b1d30..0000000000000 --- a/src/test/ui/inaccessible-test-modules.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0432]: unresolved import `__test` - --> $DIR/inaccessible-test-modules.rs:5:5 - | -LL | use __test as x; - | ------^^^^^ - | | - | no `__test` in the root - | help: a similar name exists in the module: `test` - -error[E0432]: unresolved import `__test_reexports` - --> $DIR/inaccessible-test-modules.rs:6:5 - | -LL | use __test_reexports as y; - | ----------------^^^^^ - | | - | no `__test_reexports` in the root - | help: a similar name exists in the module: `__test_reexports` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/test-attrs/decl-macro-test.rs b/src/test/ui/test-attrs/decl-macro-test.rs new file mode 100644 index 0000000000000..fcbe9f49e5564 --- /dev/null +++ b/src/test/ui/test-attrs/decl-macro-test.rs @@ -0,0 +1,22 @@ +// Check that declarative macros can declare tests + +// check-pass +// compile-flags: --test + +#![feature(decl_macro)] + +macro create_test() { + #[test] + fn test() {} +} + +macro create_module_test() { + mod x { + #[test] + fn test() {} + } +} + +create_test!(); +create_test!(); +create_module_test!(); diff --git a/src/test/ui/inaccessible-test-modules.rs b/src/test/ui/test-attrs/inaccessible-test-modules.rs similarity index 56% rename from src/test/ui/inaccessible-test-modules.rs rename to src/test/ui/test-attrs/inaccessible-test-modules.rs index 7095ec290f8f2..f5b3479379480 100644 --- a/src/test/ui/inaccessible-test-modules.rs +++ b/src/test/ui/test-attrs/inaccessible-test-modules.rs @@ -2,8 +2,8 @@ // the `--test` harness creates modules with these textual names, but // they should be inaccessible from normal code. -use __test as x; //~ ERROR unresolved import `__test` -use __test_reexports as y; //~ ERROR unresolved import `__test_reexports` +use main as x; //~ ERROR unresolved import `main` +use test as y; //~ ERROR unresolved import `test` #[test] fn baz() {} diff --git a/src/test/ui/test-attrs/inaccessible-test-modules.stderr b/src/test/ui/test-attrs/inaccessible-test-modules.stderr new file mode 100644 index 0000000000000..a94ea1e79bc51 --- /dev/null +++ b/src/test/ui/test-attrs/inaccessible-test-modules.stderr @@ -0,0 +1,21 @@ +error[E0432]: unresolved import `main` + --> $DIR/inaccessible-test-modules.rs:5:5 + | +LL | use main as x; + | ----^^^^^ + | | + | no `main` in the root + | help: a similar name exists in the module: `main` + +error[E0432]: unresolved import `test` + --> $DIR/inaccessible-test-modules.rs:6:5 + | +LL | use test as y; + | ----^^^^^ + | | + | no `test` in the root + | help: a similar name exists in the module: `test` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. From 2a82aec36ae86a1913473cb7e830a77b481641ea Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 25 Aug 2019 21:21:07 +0100 Subject: [PATCH 510/618] Move tests for unit tests to their own directory --- .../ui/{test-shadowing => test-attrs}/auxiliary/test_macro.rs | 0 src/test/ui/{ => test-attrs}/test-allow-fail-attr.rs | 0 .../ui/{ => test-attrs}/test-attr-non-associated-functions.rs | 0 .../ui/{ => test-attrs}/test-attr-non-associated-functions.stderr | 0 .../ui/{test-shadowing => test-attrs}/test-cant-be-shadowed.rs | 0 .../test-fn-signature-verification-for-explicit-return-type.rs | 0 src/test/ui/{ => test-attrs}/test-main-not-dead-attr.rs | 0 src/test/ui/{ => test-attrs}/test-main-not-dead.rs | 0 src/test/ui/{ => test-attrs}/test-on-macro.rs | 0 src/test/ui/{ => test-attrs}/test-on-macro.stderr | 0 src/test/ui/{ => test-attrs}/test-runner-hides-buried-main.rs | 0 src/test/ui/{ => test-attrs}/test-runner-hides-main.rs | 0 src/test/ui/{ => test-attrs}/test-runner-hides-start.rs | 0 src/test/ui/{ => test-attrs}/test-should-fail-good-message.rs | 0 src/test/ui/{ => test-attrs}/test-should-panic-attr.rs | 0 src/test/ui/{ => test-attrs}/test-should-panic-attr.stderr | 0 src/test/ui/{ => test-attrs}/test-vs-cfg-test.rs | 0 src/test/ui/{ => test-attrs}/test-warns-dead-code.rs | 0 src/test/ui/{ => test-attrs}/test-warns-dead-code.stderr | 0 19 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{test-shadowing => test-attrs}/auxiliary/test_macro.rs (100%) rename src/test/ui/{ => test-attrs}/test-allow-fail-attr.rs (100%) rename src/test/ui/{ => test-attrs}/test-attr-non-associated-functions.rs (100%) rename src/test/ui/{ => test-attrs}/test-attr-non-associated-functions.stderr (100%) rename src/test/ui/{test-shadowing => test-attrs}/test-cant-be-shadowed.rs (100%) rename src/test/ui/{ => test-attrs}/test-fn-signature-verification-for-explicit-return-type.rs (100%) rename src/test/ui/{ => test-attrs}/test-main-not-dead-attr.rs (100%) rename src/test/ui/{ => test-attrs}/test-main-not-dead.rs (100%) rename src/test/ui/{ => test-attrs}/test-on-macro.rs (100%) rename src/test/ui/{ => test-attrs}/test-on-macro.stderr (100%) rename src/test/ui/{ => test-attrs}/test-runner-hides-buried-main.rs (100%) rename src/test/ui/{ => test-attrs}/test-runner-hides-main.rs (100%) rename src/test/ui/{ => test-attrs}/test-runner-hides-start.rs (100%) rename src/test/ui/{ => test-attrs}/test-should-fail-good-message.rs (100%) rename src/test/ui/{ => test-attrs}/test-should-panic-attr.rs (100%) rename src/test/ui/{ => test-attrs}/test-should-panic-attr.stderr (100%) rename src/test/ui/{ => test-attrs}/test-vs-cfg-test.rs (100%) rename src/test/ui/{ => test-attrs}/test-warns-dead-code.rs (100%) rename src/test/ui/{ => test-attrs}/test-warns-dead-code.stderr (100%) diff --git a/src/test/ui/test-shadowing/auxiliary/test_macro.rs b/src/test/ui/test-attrs/auxiliary/test_macro.rs similarity index 100% rename from src/test/ui/test-shadowing/auxiliary/test_macro.rs rename to src/test/ui/test-attrs/auxiliary/test_macro.rs diff --git a/src/test/ui/test-allow-fail-attr.rs b/src/test/ui/test-attrs/test-allow-fail-attr.rs similarity index 100% rename from src/test/ui/test-allow-fail-attr.rs rename to src/test/ui/test-attrs/test-allow-fail-attr.rs diff --git a/src/test/ui/test-attr-non-associated-functions.rs b/src/test/ui/test-attrs/test-attr-non-associated-functions.rs similarity index 100% rename from src/test/ui/test-attr-non-associated-functions.rs rename to src/test/ui/test-attrs/test-attr-non-associated-functions.rs diff --git a/src/test/ui/test-attr-non-associated-functions.stderr b/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr similarity index 100% rename from src/test/ui/test-attr-non-associated-functions.stderr rename to src/test/ui/test-attrs/test-attr-non-associated-functions.stderr diff --git a/src/test/ui/test-shadowing/test-cant-be-shadowed.rs b/src/test/ui/test-attrs/test-cant-be-shadowed.rs similarity index 100% rename from src/test/ui/test-shadowing/test-cant-be-shadowed.rs rename to src/test/ui/test-attrs/test-cant-be-shadowed.rs diff --git a/src/test/ui/test-fn-signature-verification-for-explicit-return-type.rs b/src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs similarity index 100% rename from src/test/ui/test-fn-signature-verification-for-explicit-return-type.rs rename to src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs diff --git a/src/test/ui/test-main-not-dead-attr.rs b/src/test/ui/test-attrs/test-main-not-dead-attr.rs similarity index 100% rename from src/test/ui/test-main-not-dead-attr.rs rename to src/test/ui/test-attrs/test-main-not-dead-attr.rs diff --git a/src/test/ui/test-main-not-dead.rs b/src/test/ui/test-attrs/test-main-not-dead.rs similarity index 100% rename from src/test/ui/test-main-not-dead.rs rename to src/test/ui/test-attrs/test-main-not-dead.rs diff --git a/src/test/ui/test-on-macro.rs b/src/test/ui/test-attrs/test-on-macro.rs similarity index 100% rename from src/test/ui/test-on-macro.rs rename to src/test/ui/test-attrs/test-on-macro.rs diff --git a/src/test/ui/test-on-macro.stderr b/src/test/ui/test-attrs/test-on-macro.stderr similarity index 100% rename from src/test/ui/test-on-macro.stderr rename to src/test/ui/test-attrs/test-on-macro.stderr diff --git a/src/test/ui/test-runner-hides-buried-main.rs b/src/test/ui/test-attrs/test-runner-hides-buried-main.rs similarity index 100% rename from src/test/ui/test-runner-hides-buried-main.rs rename to src/test/ui/test-attrs/test-runner-hides-buried-main.rs diff --git a/src/test/ui/test-runner-hides-main.rs b/src/test/ui/test-attrs/test-runner-hides-main.rs similarity index 100% rename from src/test/ui/test-runner-hides-main.rs rename to src/test/ui/test-attrs/test-runner-hides-main.rs diff --git a/src/test/ui/test-runner-hides-start.rs b/src/test/ui/test-attrs/test-runner-hides-start.rs similarity index 100% rename from src/test/ui/test-runner-hides-start.rs rename to src/test/ui/test-attrs/test-runner-hides-start.rs diff --git a/src/test/ui/test-should-fail-good-message.rs b/src/test/ui/test-attrs/test-should-fail-good-message.rs similarity index 100% rename from src/test/ui/test-should-fail-good-message.rs rename to src/test/ui/test-attrs/test-should-fail-good-message.rs diff --git a/src/test/ui/test-should-panic-attr.rs b/src/test/ui/test-attrs/test-should-panic-attr.rs similarity index 100% rename from src/test/ui/test-should-panic-attr.rs rename to src/test/ui/test-attrs/test-should-panic-attr.rs diff --git a/src/test/ui/test-should-panic-attr.stderr b/src/test/ui/test-attrs/test-should-panic-attr.stderr similarity index 100% rename from src/test/ui/test-should-panic-attr.stderr rename to src/test/ui/test-attrs/test-should-panic-attr.stderr diff --git a/src/test/ui/test-vs-cfg-test.rs b/src/test/ui/test-attrs/test-vs-cfg-test.rs similarity index 100% rename from src/test/ui/test-vs-cfg-test.rs rename to src/test/ui/test-attrs/test-vs-cfg-test.rs diff --git a/src/test/ui/test-warns-dead-code.rs b/src/test/ui/test-attrs/test-warns-dead-code.rs similarity index 100% rename from src/test/ui/test-warns-dead-code.rs rename to src/test/ui/test-attrs/test-warns-dead-code.rs diff --git a/src/test/ui/test-warns-dead-code.stderr b/src/test/ui/test-attrs/test-warns-dead-code.stderr similarity index 100% rename from src/test/ui/test-warns-dead-code.stderr rename to src/test/ui/test-attrs/test-warns-dead-code.stderr From beb2f5b8ff89f3e973e085ce338a59e5203fecb0 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 25 Aug 2019 21:31:42 +0100 Subject: [PATCH 511/618] Remove `Ident::{gensym, is_gensymed}` `gensym_if_underscore` still exists. The symbol interner can still create arbitray gensyms, this is just not exposed publicly. --- src/librustc_resolve/resolve_imports.rs | 8 ++------ src/libsyntax_pos/symbol.rs | 27 +++++++++++-------------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index fd222a132a3f8..4e33ea018a074 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1307,12 +1307,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { None => continue, }; - // Filter away ambiguous and gensymed imports. Gensymed imports - // (e.g. implicitly injected `std`) cannot be properly encoded in metadata, - // so they can cause name conflict errors downstream. - let is_good_import = binding.is_import() && !binding.is_ambiguity() && - // Note that as_str() de-gensyms the Symbol - !(ident.is_gensymed() && ident.name.as_str() != "_"); + // Filter away ambiguous imports. + let is_good_import = binding.is_import() && !binding.is_ambiguity(); if is_good_import || binding.is_macro_def() { let res = binding.res(); if res != Res::Err { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 0b8f16bbc3b99..ce20e4407fe88 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -798,21 +798,15 @@ impl Ident { Ident::new(self.name, self.span.modern_and_legacy()) } - /// Transforms an identifier into one with the same name, but gensymed. - pub fn gensym(self) -> Ident { - let name = with_interner(|interner| interner.gensymed(self.name)); - Ident::new(name, self.span) - } - /// Transforms an underscore identifier into one with the same name, but /// gensymed. Leaves non-underscore identifiers unchanged. pub fn gensym_if_underscore(self) -> Ident { - if self.name == kw::Underscore { self.gensym() } else { self } - } - - // WARNING: this function is deprecated and will be removed in the future. - pub fn is_gensymed(self) -> bool { - with_interner(|interner| interner.is_gensymed(self.name)) + if self.name == kw::Underscore { + let name = with_interner(|interner| interner.gensymed(self.name)); + Ident::new(name, self.span) + } else { + self + } } pub fn as_str(self) -> LocalInternedString { @@ -865,9 +859,12 @@ impl UseSpecializedDecodable for Ident {} /// /// Examples: /// ``` -/// assert_eq!(Ident::from_str("x"), Ident::from_str("x")) -/// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x")) -/// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x").gensym()) +/// assert_eq!(Ident::from_str("_"), Ident::from_str("_")) +/// assert_ne!(Ident::from_str("_").gensym_if_underscore(), Ident::from_str("_")) +/// assert_ne!( +/// Ident::from_str("_").gensym_if_underscore(), +/// Ident::from_str("_").gensym_if_underscore(), +/// ) /// ``` /// Internally, a symbol is implemented as an index, and all operations /// (including hashing, equality, and ordering) operate on that index. The use From 846df20578189260ed3f4c9c824d324b6c9b7eac Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 25 Aug 2019 22:36:13 +0100 Subject: [PATCH 512/618] Fix 2018 edition expanded pretty printing --- src/libsyntax/print/pprust.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 4dc00af486013..c18c8c18ae1f9 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -128,10 +128,14 @@ pub fn print_crate<'a>(cm: &'a SourceMap, let fake_attr = attr::mk_attr_inner(list); s.print_attribute(&fake_attr); - // #![no_std] - let no_std_meta = attr::mk_word_item(ast::Ident::with_dummy_span(sym::no_std)); - let fake_attr = attr::mk_attr_inner(no_std_meta); - s.print_attribute(&fake_attr); + // Currently on Rust 2018 we don't have `extern crate std;` at the crate + // root, so this is not needed, and actually breaks things. + if sess.edition == syntax_pos::edition::Edition::Edition2015 { + // #![no_std] + let no_std_meta = attr::mk_word_item(ast::Ident::with_dummy_span(sym::no_std)); + let fake_attr = attr::mk_attr_inner(no_std_meta); + s.print_attribute(&fake_attr); + } } s.print_mod(&krate.module, &krate.attrs); From 0b86782058c27ba694ec81ebe7108dceb0968a2b Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 27 Aug 2019 21:13:20 +0100 Subject: [PATCH 513/618] Don't call `diag_span_note_once` for suppressed lints --- src/librustc/lint/mod.rs | 44 ++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 1b133819a73bf..fb7f14febf32e 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -666,6 +666,30 @@ pub fn struct_lint_level<'a>(sess: &'a Session, (Level::Forbid, None) => sess.struct_err(msg), }; + // Check for future incompatibility lints and issue a stronger warning. + let lints = sess.lint_store.borrow(); + let lint_id = LintId::of(lint); + let future_incompatible = lints.future_incompatible(lint_id); + + // If this code originates in a foreign macro, aka something that this crate + // did not itself author, then it's likely that there's nothing this crate + // can do about it. We probably want to skip the lint entirely. + if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { + // Any suggestions made here are likely to be incorrect, so anything we + // emit shouldn't be automatically fixed by rustfix. + err.allow_suggestions(false); + + // If this is a future incompatible lint it'll become a hard error, so + // we have to emit *something*. Also allow lints to whitelist themselves + // on a case-by-case basis for emission in a foreign macro. + if future_incompatible.is_none() && !lint.report_in_external_macro { + err.cancel(); + // Don't continue further, since we don't want to have + // `diag_span_note_once` called for a diagnostic that isn't emitted. + return err; + } + } + let name = lint.name_lower(); match src { LintSource::Default => { @@ -715,10 +739,6 @@ pub fn struct_lint_level<'a>(sess: &'a Session, err.code(DiagnosticId::Lint(name)); - // Check for future incompatibility lints and issue a stronger warning. - let lints = sess.lint_store.borrow(); - let lint_id = LintId::of(lint); - let future_incompatible = lints.future_incompatible(lint_id); if let Some(future_incompatible) = future_incompatible { const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \ @@ -743,22 +763,6 @@ pub fn struct_lint_level<'a>(sess: &'a Session, err.note(&citation); } - // If this code originates in a foreign macro, aka something that this crate - // did not itself author, then it's likely that there's nothing this crate - // can do about it. We probably want to skip the lint entirely. - if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { - // Any suggestions made here are likely to be incorrect, so anything we - // emit shouldn't be automatically fixed by rustfix. - err.allow_suggestions(false); - - // If this is a future incompatible lint it'll become a hard error, so - // we have to emit *something*. Also allow lints to whitelist themselves - // on a case-by-case basis for emission in a foreign macro. - if future_incompatible.is_none() && !lint.report_in_external_macro { - err.cancel() - } - } - return err } From c8cf9f5a025bb475804b5a90f54aca310b952526 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 28 Aug 2019 12:41:29 +0300 Subject: [PATCH 514/618] Add `with_{def_site,call_site,legacy}_ctxt,` methods to `Span` Use these to create call-site spans for AST passes when needed. --- src/librustc_resolve/macros.rs | 27 +++--- src/libsyntax/ext/base.rs | 14 +-- src/libsyntax_ext/proc_macro_harness.rs | 3 +- src/libsyntax_ext/standard_library_imports.rs | 8 +- src/libsyntax_ext/test_harness.rs | 10 +- src/libsyntax_pos/hygiene.rs | 2 +- src/libsyntax_pos/lib.rs | 19 ++++ .../dollar-crate-issue-57089.stdout | 32 +++---- .../dollar-crate-issue-62325.stdout | 44 ++++----- src/test/ui/proc-macro/dollar-crate.stdout | 96 +++++++++---------- 10 files changed, 138 insertions(+), 117 deletions(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 20d281f1e997a..02022c98c3502 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -17,7 +17,7 @@ use syntax::edition::Edition; use syntax::ext::base::{self, Indeterminate, SpecialDerives}; use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; -use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind, Transparency}; +use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind}; use syntax::ext::tt::macro_rules; use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name}; use syntax::feature_gate::GateIssue; @@ -131,23 +131,20 @@ impl<'a> base::Resolver for Resolver<'a> { // Create a Span with modern hygiene with a definition site of the provided // module, or a fake empty `#[no_implicit_prelude]` module if no module is // provided. - fn span_for_ast_pass( + fn expansion_for_ast_pass( &mut self, - base_span: Span, + call_site: Span, pass: AstPass, features: &[Symbol], parent_module_id: Option, - ) -> Span { - let span = base_span.fresh_expansion_with_transparency( - ExpnData::allow_unstable( - ExpnKind::AstPass(pass), - base_span, - self.session.edition(), - features.into(), - ), - Transparency::Opaque, - ); - let expn_id = span.ctxt().outer_expn(); + ) -> ExpnId { + let expn_id = ExpnId::fresh(Some(ExpnData::allow_unstable( + ExpnKind::AstPass(pass), + call_site, + self.session.edition(), + features.into(), + ))); + let parent_scope = if let Some(module_id) = parent_module_id { let parent_def_id = self.definitions.local_def_id(module_id); self.definitions.add_parent_module_of_macro_def(expn_id, parent_def_id); @@ -160,7 +157,7 @@ impl<'a> base::Resolver for Resolver<'a> { self.empty_module }; self.ast_transform_scopes.insert(expn_id, parent_scope); - span + expn_id } fn resolve_imports(&mut self) { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 962447e8cf07f..4c146611deab6 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -3,7 +3,7 @@ use crate::attr::{HasAttrs, Stability, Deprecation}; use crate::source_map::SourceMap; use crate::edition::Edition; use crate::ext::expand::{self, AstFragment, Invocation}; -use crate::ext::hygiene::{ExpnId, Transparency}; +use crate::ext::hygiene::ExpnId; use crate::mut_visit::{self, MutVisitor}; use crate::parse::{self, parser, DirectoryOwnership}; use crate::parse::token; @@ -658,13 +658,13 @@ pub trait Resolver { extra_placeholders: &[NodeId]); fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension); - fn span_for_ast_pass( + fn expansion_for_ast_pass( &mut self, - span: Span, + call_site: Span, pass: AstPass, features: &[Symbol], parent_module_id: Option, - ) -> Span; + ) -> ExpnId; fn resolve_imports(&mut self); @@ -750,20 +750,20 @@ impl<'a> ExtCtxt<'a> { /// Equivalent of `Span::def_site` from the proc macro API, /// except that the location is taken from the span passed as an argument. pub fn with_def_site_ctxt(&self, span: Span) -> Span { - span.with_ctxt_from_mark(self.current_expansion.id, Transparency::Opaque) + span.with_def_site_ctxt(self.current_expansion.id) } /// Equivalent of `Span::call_site` from the proc macro API, /// except that the location is taken from the span passed as an argument. pub fn with_call_site_ctxt(&self, span: Span) -> Span { - span.with_ctxt_from_mark(self.current_expansion.id, Transparency::Transparent) + span.with_call_site_ctxt(self.current_expansion.id) } /// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items). /// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably), /// or with `with_call_site_ctxt` (where necessary). pub fn with_legacy_ctxt(&self, span: Span) -> Span { - span.with_ctxt_from_mark(self.current_expansion.id, Transparency::SemiTransparent) + span.with_legacy_ctxt(self.current_expansion.id) } /// Returns span for the macro which originally caused the current expansion to happen. diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs index 1cdaa1190fae3..8a4b78a3efa31 100644 --- a/src/libsyntax_ext/proc_macro_harness.rs +++ b/src/libsyntax_ext/proc_macro_harness.rs @@ -326,12 +326,13 @@ fn mk_decls( custom_attrs: &[ProcMacroDef], custom_macros: &[ProcMacroDef], ) -> P { - let span = cx.resolver.span_for_ast_pass( + let expn_id = cx.resolver.expansion_for_ast_pass( DUMMY_SP, AstPass::ProcMacroHarness, &[sym::rustc_attrs, sym::proc_macro_internals], None, ); + let span = DUMMY_SP.with_def_site_ctxt(expn_id); let proc_macro = Ident::new(sym::proc_macro, span); let krate = cx.item(span, diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs index 61e423266fa05..e5dded9ea5319 100644 --- a/src/libsyntax_ext/standard_library_imports.rs +++ b/src/libsyntax_ext/standard_library_imports.rs @@ -28,19 +28,21 @@ pub fn inject( &[sym::std] }; - let span = resolver.span_for_ast_pass( + let expn_id = resolver.expansion_for_ast_pass( DUMMY_SP, AstPass::StdImports, &[sym::prelude_import], None, ); + let span = DUMMY_SP.with_def_site_ctxt(expn_id); + let call_site = DUMMY_SP.with_call_site_ctxt(expn_id); // .rev() to preserve ordering above in combination with insert(0, ...) for &orig_name_sym in names.iter().rev() { let (rename, orig_name) = if rust_2018 { (Ident::new(kw::Underscore, span), Some(orig_name_sym)) } else { - (Ident::with_dummy_span(orig_name_sym), None) + (Ident::new(orig_name_sym, call_site), None) }; krate.module.items.insert(0, P(ast::Item { attrs: vec![attr::mk_attr_outer( @@ -65,7 +67,7 @@ pub fn inject( .collect() } else { [kw::PathRoot, name, sym::prelude, sym::v1].iter() - .map(|symbol| ast::PathSegment::from_ident(ast::Ident::with_dummy_span(*symbol))) + .map(|symbol| ast::PathSegment::from_ident(ast::Ident::new(*symbol, call_site))) .collect() }; diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs index 6eb132979df8f..eedd7fbee3806 100644 --- a/src/libsyntax_ext/test_harness.rs +++ b/src/libsyntax_ext/test_harness.rs @@ -97,15 +97,16 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { }; // Create an identifier that will hygienically resolve the test // case name, even in another module. - let sp = self.cx.ext_cx.resolver.span_for_ast_pass( + let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass( module.inner, AstPass::TestHarness, &[], Some(parent), ); - let expn = sp.ctxt().outer_expn(); for test in &mut tests { - test.ident.span = test.ident.span.apply_mark(expn, Transparency::Opaque); + // See the comment on `mk_main` for why we're using + // `apply_mark` directly. + test.ident.span = test.ident.span.apply_mark(expn_id, Transparency::Opaque); } self.cx.test_cases.extend(tests); } @@ -207,12 +208,13 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { // #![main] // test::test_main_static(&[..tests]); // } - let sp = cx.ext_cx.resolver.span_for_ast_pass( + let expn_id = cx.ext_cx.resolver.expansion_for_ast_pass( DUMMY_SP, AstPass::TestHarness, &[sym::main, sym::test, sym::rustc_attrs], None, ); + let sp = DUMMY_SP.with_def_site_ctxt(expn_id); let ecx = &cx.ext_cx; let test_id = Ident::new(sym::test, sp); diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 99afe57ef5497..f0e7344c1b986 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -360,7 +360,7 @@ impl SyntaxContext { } /// Extend a syntax context with a given expansion and transparency. - pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext { + crate fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext { HygieneData::with(|data| data.apply_mark(self, expn_id, transparency)) } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index d800109cf8531..9a296f17aaf4a 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -514,6 +514,25 @@ impl Span { span.ctxt) } + /// Equivalent of `Span::def_site` from the proc macro API, + /// except that the location is taken from the `self` span. + pub fn with_def_site_ctxt(self, expn_id: ExpnId) -> Span { + self.with_ctxt_from_mark(expn_id, Transparency::Opaque) + } + + /// Equivalent of `Span::call_site` from the proc macro API, + /// except that the location is taken from the `self` span. + pub fn with_call_site_ctxt(&self, expn_id: ExpnId) -> Span { + self.with_ctxt_from_mark(expn_id, Transparency::Transparent) + } + + /// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items). + /// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably), + /// or with `with_call_site_ctxt` (where necessary). + pub fn with_legacy_ctxt(&self, expn_id: ExpnId) -> Span { + self.with_ctxt_from_mark(expn_id, Transparency::SemiTransparent) + } + /// Produces a span with the same location as `self` and context produced by a macro with the /// given ID and transparency, assuming that macro was defined directly and not produced by /// some other macro (which is the case for built-in and procedural macros). diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout index 0fe02a9a34d18..ea06f6c1acaf9 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout @@ -2,40 +2,40 @@ PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "M", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "S", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ] PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); @@ -43,39 +43,39 @@ PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "A", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "S", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ] diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout index a499e1362ec0b..7ee8078b2c5d2 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout @@ -3,55 +3,55 @@ PRINT-ATTR RE-COLLECTED (DISPLAY): struct A (identity ! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "A", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "identity", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: '!', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "S", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ] PRINT-ATTR INPUT (DISPLAY): struct B(identity!(::dollar_crate_external :: S)); @@ -59,54 +59,54 @@ PRINT-ATTR RE-COLLECTED (DISPLAY): struct B (identity ! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Ident { ident: "B", - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "identity", - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Punct { ch: '!', spacing: Alone, - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Ident { ident: "S", - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, ], - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, ], - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #7 bytes(LO..HI), + span: #8 bytes(LO..HI), }, ] diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout index da1d7549d0750..4f7e000265eb0 100644 --- a/src/test/ui/proc-macro/dollar-crate.stdout +++ b/src/test/ui/proc-macro/dollar-crate.stdout @@ -2,40 +2,40 @@ PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "M", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "S", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ] PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); @@ -43,40 +43,40 @@ PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "A", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "S", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ] PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S); @@ -84,80 +84,80 @@ PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "D", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Ident { ident: "S", - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ], - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #2 bytes(LO..HI), + span: #3 bytes(LO..HI), }, ] PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "M", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "S", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ], - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ] PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S); @@ -165,40 +165,40 @@ PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "A", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "S", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ], - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ] PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S); @@ -206,39 +206,39 @@ PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "D", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "$crate", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Joint, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ':', spacing: Alone, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Ident { ident: "S", - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ], - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, Punct { ch: ';', spacing: Alone, - span: #9 bytes(LO..HI), + span: #10 bytes(LO..HI), }, ] From e552840e79330f8a1f36fc676b71fa38b3123a50 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 28 Aug 2019 22:47:52 +0100 Subject: [PATCH 515/618] Document test harness generation Also ensure that we're consistently using the def-site span when appropriate. --- src/libsyntax_ext/test_harness.rs | 82 +++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs index eedd7fbee3806..b93c11fad3823 100644 --- a/src/libsyntax_ext/test_harness.rs +++ b/src/libsyntax_ext/test_harness.rs @@ -25,6 +25,7 @@ struct Test { struct TestCtxt<'a> { ext_cx: ExtCtxt<'a>, + def_site: Span, test_cases: Vec, reexport_test_harness_main: Option, test_runner: Option, @@ -125,6 +126,7 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { struct EntryPointCleaner { // Current depth in the ast depth: usize, + def_site: Span, } impl MutVisitor for EntryPointCleaner { @@ -141,8 +143,10 @@ impl MutVisitor for EntryPointCleaner { EntryPointType::MainAttr | EntryPointType::Start => item.map(|ast::Item {id, ident, attrs, node, vis, span, tokens}| { - let allow_ident = Ident::with_dummy_span(sym::allow); - let dc_nested = attr::mk_nested_word_item(Ident::from_str("dead_code")); + let allow_ident = Ident::new(sym::allow, self.def_site); + let dc_nested = attr::mk_nested_word_item( + Ident::from_str_and_span("dead_code", self.def_site), + ); let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]); let allow_dead_code = attr::mk_attr_outer(allow_dead_code_item); @@ -180,15 +184,26 @@ fn generate_test_harness(sess: &ParseSess, krate: &mut ast::Crate, features: &Features, test_runner: Option) { - // Remove the entry points - let mut cleaner = EntryPointCleaner { depth: 0 }; - cleaner.visit_crate(krate); - let mut econfig = ExpansionConfig::default("test".to_string()); econfig.features = Some(features); + let ext_cx = ExtCtxt::new(sess, econfig, resolver); + + let expn_id = ext_cx.resolver.expansion_for_ast_pass( + DUMMY_SP, + AstPass::TestHarness, + &[sym::main, sym::test, sym::rustc_attrs], + None, + ); + let def_site = DUMMY_SP.with_def_site_ctxt(expn_id); + + // Remove the entry points + let mut cleaner = EntryPointCleaner { depth: 0, def_site }; + cleaner.visit_crate(krate); + let cx = TestCtxt { - ext_cx: ExtCtxt::new(sess, econfig, resolver), + ext_cx, + def_site, test_cases: Vec::new(), reexport_test_harness_main, test_runner @@ -202,27 +217,40 @@ fn generate_test_harness(sess: &ParseSess, /// Creates a function item for use as the main function of a test build. /// This function will call the `test_runner` as specified by the crate attribute +/// +/// By default this expands to +/// +/// #[main] +/// pub fn main() { +/// extern crate test; +/// test::test_main_static(&[ +/// &test_const1, +/// &test_const2, +/// &test_const3, +/// ]); +/// } +/// +/// Most of the Ident have the usual def-site hygiene for the AST pass. The +/// exception is the `test_const`s. These have a syntax context that has two +/// opaque marks: one from the expansion of `test` or `test_case`, and one +/// generated in `TestHarnessGenerator::flat_map_item`. When resolving this +/// identifier after failing to find a matching identifier in the root module +/// we remove the outer mark, and try resolving at its def-site, which will +/// then resolve to `test_const`. +/// +/// The expansion here can be controlled by two attributes: +/// +/// `reexport_test_harness_main` provides a different name for the `main` +/// function and `test_runner` provides a path that replaces +/// `test::test_main_static`. fn mk_main(cx: &mut TestCtxt<'_>) -> P { - // Writing this out by hand: - // pub fn main() { - // #![main] - // test::test_main_static(&[..tests]); - // } - let expn_id = cx.ext_cx.resolver.expansion_for_ast_pass( - DUMMY_SP, - AstPass::TestHarness, - &[sym::main, sym::test, sym::rustc_attrs], - None, - ); - let sp = DUMMY_SP.with_def_site_ctxt(expn_id); + let sp = cx.def_site; let ecx = &cx.ext_cx; let test_id = Ident::new(sym::test, sp); // test::test_main_static(...) let mut test_runner = cx.test_runner.clone().unwrap_or( - ecx.path(sp, vec![ - test_id, ecx.ident_of("test_main_static") - ])); + ecx.path(sp, vec![test_id, Ident::from_str_and_span("test_main_static", sp)])); test_runner.span = sp; @@ -231,10 +259,6 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { vec![mk_tests_slice(cx, sp)]); let call_test_main = ecx.stmt_expr(call_test_main); - // #![main] - let main_meta = ecx.meta_word(sp, sym::main); - let main_attr = ecx.attribute(main_meta); - // extern crate test let test_extern_stmt = ecx.stmt_item(sp, ecx.item(sp, test_id, @@ -242,6 +266,10 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { ast::ItemKind::ExternCrate(None) )); + // #[main] + let main_meta = ecx.meta_word(sp, sym::main); + let main_attr = ecx.attribute(main_meta); + // pub fn main() { ... } let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![])); @@ -279,7 +307,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { } /// Creates a slice containing every test like so: -/// &[test1, test2] +/// &[&test1, &test2] fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P { debug!("building test vector from {} tests", cx.test_cases.len()); let ref ecx = cx.ext_cx; From 74563b41666228e46f892e795108e06306b2b514 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 3 Sep 2019 21:25:06 -0400 Subject: [PATCH 516/618] Restrict error code length to 80 columns The global restriction is 100, but since error codes are printed out via --explain we want to restrict them to just 80 columns. --- src/librustc/error_codes.rs | 18 +++++++++++------- src/librustc_metadata/error_codes.rs | 3 ++- src/librustc_typeck/error_codes.rs | 9 +++++---- src/libsyntax/error_codes.rs | 15 ++++++++++----- src/libsyntax/feature_gate/removed.rs | 5 +++++ src/libsyntax_ext/error_codes.rs | 7 ++++--- src/tools/tidy/src/style.rs | 26 ++++++++++++++++++++------ 7 files changed, 57 insertions(+), 26 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 937a9ea6c1bd4..bde0fdf3b8ee6 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1,7 +1,8 @@ // Error messages for EXXXX errors. -// Each message should start and end with a new line, and be wrapped to 80 characters. -// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable. -register_long_diagnostics! { +// Each message should start and end with a new line, and be wrapped to 80 +// characters. In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use +// `:set tw=0` to disable. +syntax::register_diagnostics! { E0038: r##" Trait objects like `Box` can only be constructed when certain requirements are satisfied by the trait in question. @@ -2206,7 +2207,8 @@ register_diagnostics! { // E0305, // expected constant E0311, // thing may not live long enough E0312, // lifetime of reference outlives lifetime of borrowed content - E0313, // lifetime of borrowed pointer outlives lifetime of captured variable + E0313, // lifetime of borrowed pointer outlives lifetime of captured + // variable E0314, // closure outlives stack frame E0315, // cannot invoke closure outside of its lifetime E0316, // nested quantification of lifetimes @@ -2223,12 +2225,13 @@ register_diagnostics! { E0483, // lifetime of operand does not outlive the operation E0484, // reference is not valid at the time of borrow E0485, // automatically reference is not valid at the time of borrow - E0486, // type of expression contains references that are not valid during... + E0486, // type of expression contains references that are not valid during.. E0487, // unsafe use of destructor: destructor might be called while... E0488, // lifetime of variable does not enclose its declaration E0489, // type/lifetime parameter not in scope here E0490, // a value of type `..` is borrowed for too long - E0495, // cannot infer an appropriate lifetime due to conflicting requirements + E0495, // cannot infer an appropriate lifetime due to conflicting + // requirements E0566, // conflicting representation hints E0623, // lifetime mismatch where both parameters are anonymous regions E0628, // generators cannot have explicit parameters @@ -2239,7 +2242,8 @@ register_diagnostics! { E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders E0697, // closures cannot be static E0707, // multiple elided lifetimes used in arguments of `async fn` - E0708, // `async` non-`move` closures with parameters are not currently supported + E0708, // `async` non-`move` closures with parameters are not currently + // supported E0709, // multiple different lifetimes used in arguments of `async fn` E0710, // an unknown tool name found in scoped lint E0711, // a feature has been declared with conflicting stability attributes diff --git a/src/librustc_metadata/error_codes.rs b/src/librustc_metadata/error_codes.rs index 0708a6243bf29..4d2c0291ad39b 100644 --- a/src/librustc_metadata/error_codes.rs +++ b/src/librustc_metadata/error_codes.rs @@ -97,5 +97,6 @@ register_diagnostics! { E0464, // multiple matching crates for `..` E0465, // multiple .. candidates for `..` found E0519, // local crate and dependency have same (crate-name, disambiguator) - E0523, // two dependencies have same (crate-name, disambiguator) but different SVH + // two dependencies have same (crate-name, disambiguator) but different SVH + E0523, } diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 093446d28533e..4d960b416fff0 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4930,7 +4930,8 @@ register_diagnostics! { // E0245, // not a trait // E0246, // invalid recursive type // E0247, -// E0248, // value used as a type, now reported earlier during resolution as E0412 +// E0248, // value used as a type, now reported earlier during resolution + // as E0412 // E0249, // E0319, // trait impls for defaulted traits allowed just for structs/enums // E0372, // coherence not object safe @@ -4938,7 +4939,7 @@ register_diagnostics! { // between structures with the same definition // E0558, // replaced with a generic attribute input check E0533, // `{}` does not name a unit variant, unit struct or a constant -// E0563, // cannot determine a type for this `impl Trait`: {} // removed in 6383de15 +// E0563, // cannot determine a type for this `impl Trait` removed in 6383de15 E0564, // only named lifetimes are allowed in `impl Trait`, // but `{}` was found in the type `{}` E0587, // type has conflicting packed and align representation hints @@ -4947,8 +4948,8 @@ register_diagnostics! { // E0612, // merged into E0609 // E0613, // Removed (merged with E0609) E0627, // yield statement outside of generator literal - E0632, // cannot provide explicit type parameters when `impl Trait` is used in - // argument position. + E0632, // cannot provide explicit type parameters when `impl Trait` is used + // in argument position. E0634, // type has conflicting packed representaton hints E0640, // infer outlives requirements E0641, // cannot cast to/from a pointer with an unknown kind diff --git a/src/libsyntax/error_codes.rs b/src/libsyntax/error_codes.rs index 1ba29011f75a4..76b2575bfd688 100644 --- a/src/libsyntax/error_codes.rs +++ b/src/libsyntax/error_codes.rs @@ -1,7 +1,8 @@ // Error messages for EXXXX errors. -// Each message should start and end with a new line, and be wrapped to 80 characters. -// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable. -register_long_diagnostics! { +// Each message should start and end with a new line, and be wrapped to 80 +// characters. In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use +// `:set tw=0` to disable. +register_diagnostics! { E0178: r##" In types, the `+` type operator has low precedence, so it is often necessary @@ -432,7 +433,9 @@ register_diagnostics! { E0546, // missing 'feature' E0547, // missing 'issue' // E0548, // replaced with a generic attribute input check - E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute + // rustc_deprecated attribute must be paired with either stable or unstable + // attribute + E0549, E0550, // multiple deprecated attributes E0551, // incorrect meta item E0553, // multiple rustc_const_unstable attributes @@ -440,7 +443,9 @@ register_diagnostics! { E0556, // malformed feature, expected just one word E0584, // file for module `..` found at both .. and .. E0629, // missing 'feature' (rustc_const_unstable) - E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute + // rustc_const_unstable attribute must be paired with stable/unstable + // attribute + E0630, E0693, // incorrect `repr(align)` attribute format E0694, // an unknown tool name found in scoped attributes E0703, // invalid ABI diff --git a/src/libsyntax/feature_gate/removed.rs b/src/libsyntax/feature_gate/removed.rs index ad7d69b3e7372..2c29e1ebf1493 100644 --- a/src/libsyntax/feature_gate/removed.rs +++ b/src/libsyntax/feature_gate/removed.rs @@ -94,6 +94,11 @@ declare_features! ( /// Allows defining `existential type`s. (removed, existential_type, "1.38.0", Some(63063), None, Some("removed in favor of `#![feature(type_alias_impl_trait)]`")), + /// Allows using the macros: + /// + `__diagnostic_used` + /// + `__register_diagnostic` + /// +`__build_diagnostic_array` + (removed, rustc_diagnostic_macros, "1.38.0", None, None, None), // ------------------------------------------------------------------------- // feature-group-end: removed features diff --git a/src/libsyntax_ext/error_codes.rs b/src/libsyntax_ext/error_codes.rs index 5982a4df226c2..49808fc0b60e2 100644 --- a/src/libsyntax_ext/error_codes.rs +++ b/src/libsyntax_ext/error_codes.rs @@ -1,9 +1,10 @@ use syntax::register_long_diagnostics; // Error messages for EXXXX errors. -// Each message should start and end with a new line, and be wrapped to 80 characters. -// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable. -register_long_diagnostics! { +// Each message should start and end with a new line, and be wrapped to 80 +// characters. In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use +// `:set tw=0` to disable. +syntax::register_diagnostics! { E0660: r##" The argument to the `asm` macro is not well-formed. diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 6a0d530e2362a..9302909968615 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -15,6 +15,7 @@ use std::path::Path; +const ERROR_CODE_COLS: usize = 80; const COLS: usize = 100; const LINES: usize = 3000; @@ -51,7 +52,13 @@ enum LIUState { /// Lines of this form are allowed to be overlength, because Markdown /// offers no way to split a line in the middle of a URL, and the lengths /// of URLs to external references are beyond our control. -fn line_is_url(line: &str) -> bool { +fn line_is_url(columns: usize, line: &str) -> bool { + // more basic check for error_codes.rs, to avoid complexity in implementing two state machines + if columns == ERROR_CODE_COLS { + return line.starts_with("[") && + line.contains("]:") && line.contains("http"); + } + use self::LIUState::*; let mut state: LIUState = EXP_COMMENT_START; let is_url = |w: &str| w.starts_with("http://") || w.starts_with("https://"); @@ -75,7 +82,7 @@ fn line_is_url(line: &str) -> bool { => state = EXP_END, (_, w) - if w.len() > COLS && is_url(w) + if w.len() > columns && is_url(w) => state = EXP_END, (_, _) => {} @@ -88,8 +95,8 @@ fn line_is_url(line: &str) -> bool { /// Returns `true` if `line` is allowed to be longer than the normal limit. /// Currently there is only one exception, for long URLs, but more /// may be added in the future. -fn long_line_is_ok(line: &str) -> bool { - if line_is_url(line) { +fn long_line_is_ok(max_columns: usize, line: &str) -> bool { + if line_is_url(max_columns, line) { return true; } @@ -144,6 +151,12 @@ pub fn check(path: &Path, bad: &mut bool) { tidy_error!(bad, "{}: empty file", file.display()); } + let max_columns = if filename == "error_codes.rs" { + ERROR_CODE_COLS + } else { + COLS + }; + let can_contain = contents.contains("// ignore-tidy-") || contents.contains("# ignore-tidy-"); let mut skip_cr = contains_ignore_directive(can_contain, &contents, "cr"); @@ -162,11 +175,12 @@ pub fn check(path: &Path, bad: &mut bool) { let mut err = |msg: &str| { tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg); }; - if line.chars().count() > COLS && !long_line_is_ok(line) { + if line.chars().count() > max_columns && + !long_line_is_ok(max_columns, line) { suppressible_tidy_err!( err, skip_line_length, - &format!("line longer than {} chars", COLS) + &format!("line longer than {} chars", max_columns) ); } if line.contains('\t') { From b437240ceefaad3cdf92ad7e9d1255b8da88dbb3 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 3 Sep 2019 21:15:18 -0400 Subject: [PATCH 517/618] Replace diagnostic plugins with macro_rules --- src/librustc/error_codes.rs | 6 +- src/librustc/lib.rs | 5 - src/librustc_codegen_llvm/error_codes.rs | 2 +- src/librustc_codegen_llvm/lib.rs | 4 +- src/librustc_codegen_ssa/error_codes.rs | 2 +- src/librustc_codegen_ssa/lib.rs | 4 - src/librustc_interface/passes.rs | 15 +- src/librustc_interface/util.rs | 18 +-- src/librustc_lint/error_codes.rs | 5 +- src/librustc_metadata/error_codes.rs | 9 +- src/librustc_metadata/lib.rs | 4 +- src/librustc_mir/error_codes.rs | 6 +- src/librustc_mir/lib.rs | 4 +- src/librustc_passes/error_codes.rs | 10 +- src/librustc_passes/lib.rs | 4 +- src/librustc_plugin/error_codes.rs | 11 +- src/librustc_plugin/lib.rs | 4 +- src/librustc_privacy/error_codes.rs | 5 +- src/librustc_privacy/lib.rs | 4 +- src/librustc_resolve/error_codes.rs | 9 +- src/librustc_resolve/late.rs | 24 +-- src/librustc_resolve/late/diagnostics.rs | 4 +- src/librustc_resolve/lib.rs | 6 +- src/librustc_typeck/error_codes.rs | 7 +- src/librustc_typeck/lib.rs | 6 +- src/librustc_typeck/structured_errors.rs | 4 +- src/libsyntax/diagnostics/macros.rs | 55 +++---- src/libsyntax/diagnostics/plugin.rs | 185 ----------------------- src/libsyntax/error_codes.rs | 5 +- src/libsyntax/lib.rs | 5 - src/libsyntax/parse/mod.rs | 4 - src/libsyntax_ext/error_codes.rs | 2 - 32 files changed, 87 insertions(+), 351 deletions(-) delete mode 100644 src/libsyntax/diagnostics/plugin.rs diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index bde0fdf3b8ee6..eee33846139e6 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2184,11 +2184,7 @@ Examples of erroneous code: static X: u32 = 42; ``` "##, - -} - - -register_diagnostics! { +; // E0006, // merged with E0005 // E0101, // replaced with E0282 // E0102, // replaced with E0282 diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 368f5bb64fe6c..c5d2b2d7e7f87 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -88,8 +88,6 @@ mod tests; #[macro_use] mod macros; -// N.B., this module needs to be declared first so diagnostics are -// registered before they are used. pub mod error_codes; #[macro_use] @@ -143,6 +141,3 @@ pub mod util { // Allows macros to refer to this crate as `::rustc` extern crate self as rustc; - -// Build the diagnostics array at the end so that the metadata includes error use sites. -__build_diagnostic_array! { librustc, DIAGNOSTICS } diff --git a/src/librustc_codegen_llvm/error_codes.rs b/src/librustc_codegen_llvm/error_codes.rs index c6b5dc03a6f0a..042e51ed2ba7a 100644 --- a/src/librustc_codegen_llvm/error_codes.rs +++ b/src/librustc_codegen_llvm/error_codes.rs @@ -1,4 +1,4 @@ -register_long_diagnostics! { +register_diagnostics! { E0511: r##" Invalid monomorphization of an intrinsic function was used. Erroneous code diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 2fd78885bd01e..f032d0ff0464c 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -256,7 +256,7 @@ impl CodegenBackend for LlvmCodegenBackend { } fn diagnostics(&self) -> &[(&'static str, &'static str)] { - &DIAGNOSTICS + &error_codes::DIAGNOSTICS } fn target_features(&self, sess: &Session) -> Vec { @@ -425,5 +425,3 @@ impl Drop for ModuleLlvm { } } } - -__build_diagnostic_array! { librustc_codegen_llvm, DIAGNOSTICS } diff --git a/src/librustc_codegen_ssa/error_codes.rs b/src/librustc_codegen_ssa/error_codes.rs index 8d46dcb7c09c3..8ff41c275a8f4 100644 --- a/src/librustc_codegen_ssa/error_codes.rs +++ b/src/librustc_codegen_ssa/error_codes.rs @@ -1,4 +1,4 @@ -register_long_diagnostics! { +syntax::register_diagnostics! { E0668: r##" Malformed inline assembly rejected by LLVM. diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index 68640abb0433e..0f98310722ee3 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -35,8 +35,6 @@ use rustc_data_structures::svh::Svh; use rustc::middle::cstore::{LibSource, CrateSource, NativeLibrary}; use syntax_pos::symbol::Symbol; -// N.B., this module needs to be declared first so diagnostics are -// registered before they are used. mod error_codes; pub mod common; @@ -158,5 +156,3 @@ pub struct CodegenResults { pub linker_info: back::linker::LinkerInfo, pub crate_info: CrateInfo, } - -__build_diagnostic_array! { librustc_codegen_ssa, DIAGNOSTICS } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 24b44964e4fd2..bd9b240e24efa 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -34,7 +34,7 @@ use rustc_privacy; use rustc_resolve::{Resolver, ResolverArenas}; use rustc_traits; use rustc_typeck as typeck; -use syntax::{self, ast, diagnostics, visit}; +use syntax::{self, ast, visit}; use syntax::early_buffered_lints::BufferedEarlyLint; use syntax::ext::base::{NamedSyntaxExtension, ExtCtxt}; use syntax::mut_visit::MutVisitor; @@ -292,18 +292,7 @@ pub fn register_plugins<'a>( time(sess, "plugin registration", || { if sess.features_untracked().rustc_diagnostic_macros { - registry.register_macro( - "__diagnostic_used", - diagnostics::plugin::expand_diagnostic_used, - ); - registry.register_macro( - "__register_diagnostic", - diagnostics::plugin::expand_register_diagnostic, - ); - registry.register_macro( - "__build_diagnostic_array", - diagnostics::plugin::expand_build_diagnostic_array, - ); + // FIXME: remove feature gate } for registrar in registrars { diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index f007a0cf2abee..9eaf7b77716f3 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -43,17 +43,17 @@ use std::{thread, panic}; pub fn diagnostics_registry() -> Registry { let mut all_errors = Vec::new(); - all_errors.extend_from_slice(&rustc::DIAGNOSTICS); - all_errors.extend_from_slice(&rustc_typeck::DIAGNOSTICS); - all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS); - all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_typeck::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_resolve::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_privacy::error_codes::DIAGNOSTICS); // FIXME: need to figure out a way to get these back in here // all_errors.extend_from_slice(get_codegen_backend(sess).diagnostics()); - all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS); - all_errors.extend_from_slice(&rustc_passes::DIAGNOSTICS); - all_errors.extend_from_slice(&rustc_plugin::DIAGNOSTICS); - all_errors.extend_from_slice(&rustc_mir::DIAGNOSTICS); - all_errors.extend_from_slice(&syntax::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_metadata::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_passes::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_plugin::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_mir::error_codes::DIAGNOSTICS); + all_errors.extend_from_slice(&syntax::error_codes::DIAGNOSTICS); Registry::new(&all_errors) } diff --git a/src/librustc_lint/error_codes.rs b/src/librustc_lint/error_codes.rs index d7c39b780bfdf..ea2e1d9ecc53f 100644 --- a/src/librustc_lint/error_codes.rs +++ b/src/librustc_lint/error_codes.rs @@ -1,5 +1,4 @@ -use syntax::register_diagnostics; - -register_diagnostics! { +syntax::register_diagnostics! { +; E0721, // `await` keyword } diff --git a/src/librustc_metadata/error_codes.rs b/src/librustc_metadata/error_codes.rs index 4d2c0291ad39b..cd8e95e6c3a11 100644 --- a/src/librustc_metadata/error_codes.rs +++ b/src/librustc_metadata/error_codes.rs @@ -1,6 +1,4 @@ -use syntax::{register_diagnostics, register_long_diagnostics}; - -register_long_diagnostics! { +syntax::register_diagnostics! { E0454: r##" A link name was given with an empty name. Erroneous code example: @@ -84,10 +82,7 @@ You need to link your code to the relevant crate in order to be able to use it (through Cargo or the `-L` option of rustc example). Plugins are crates as well, and you link to them the same way. "##, - -} - -register_diagnostics! { +; E0456, // plugin `..` is not available for triple `..` E0457, // plugin `..` only found in rlib format, but must be available... E0514, // metadata version mismatch diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index c96d02d9b37de..3ab7d372461b8 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -23,7 +23,7 @@ extern crate rustc; #[macro_use] extern crate rustc_data_structures; -mod error_codes; +pub mod error_codes; mod index; mod encoder; @@ -68,5 +68,3 @@ pub fn validate_crate_name( sess.unwrap().abort_if_errors(); } } - -__build_diagnostic_array! { librustc_metadata, DIAGNOSTICS } diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs index 86c263a447bb6..74b3eff0906ac 100644 --- a/src/librustc_mir/error_codes.rs +++ b/src/librustc_mir/error_codes.rs @@ -1,4 +1,4 @@ -register_long_diagnostics! { +syntax::register_diagnostics! { E0001: r##" @@ -2448,9 +2448,9 @@ information. There are some known bugs that trigger this message. "##, -} -register_diagnostics! { +; + // E0298, // cannot compare constants // E0299, // mismatched types between arms // E0471, // constant evaluation error (in pattern) diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index cccf7b9545bdb..7a5db4fc19d02 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -32,7 +32,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #[macro_use] extern crate rustc_data_structures; #[macro_use] extern crate syntax; -mod error_codes; +pub mod error_codes; mod borrow_check; mod build; @@ -62,5 +62,3 @@ pub fn provide(providers: &mut Providers<'_>) { }; providers.type_name = interpret::type_name; } - -__build_diagnostic_array! { librustc_mir, DIAGNOSTICS } diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs index a30cd8a627fe3..af07c790e2a87 100644 --- a/src/librustc_passes/error_codes.rs +++ b/src/librustc_passes/error_codes.rs @@ -1,6 +1,4 @@ -use syntax::{register_diagnostics, register_long_diagnostics}; - -register_long_diagnostics! { +syntax::register_diagnostics! { /* E0014: r##" Constants can only be initialized by a constant value or, in a future @@ -320,10 +318,8 @@ async fn foo() {} ``` Switch to the Rust 2018 edition to use `async fn`. -"## -} - -register_diagnostics! { +"##, +; E0226, // only a single explicit lifetime bound is permitted E0472, // asm! is unsupported on this target E0561, // patterns aren't allowed in function pointer types diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 5614b570b927a..2070f306112a1 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -18,7 +18,7 @@ extern crate rustc; use rustc::ty::query::Providers; -mod error_codes; +pub mod error_codes; pub mod ast_validation; pub mod rvalue_promotion; @@ -26,8 +26,6 @@ pub mod hir_stats; pub mod layout_test; pub mod loops; -__build_diagnostic_array! { librustc_passes, DIAGNOSTICS } - pub fn provide(providers: &mut Providers<'_>) { rvalue_promotion::provide(providers); loops::provide(providers); diff --git a/src/librustc_plugin/error_codes.rs b/src/librustc_plugin/error_codes.rs index b5f6a8d905d31..7b3f01c0ee111 100644 --- a/src/librustc_plugin/error_codes.rs +++ b/src/librustc_plugin/error_codes.rs @@ -1,9 +1,4 @@ -use syntax::{register_diagnostics, register_long_diagnostics}; - -register_long_diagnostics! { - -} - -register_diagnostics! { - E0498 // malformed plugin attribute +syntax::register_diagnostics! { +; + E0498, // malformed plugin attribute } diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 952bc9fff6a71..1cf01d481e468 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -60,9 +60,7 @@ pub use registry::Registry; -mod error_codes; +pub mod error_codes; pub mod registry; pub mod load; pub mod build; - -__build_diagnostic_array! { librustc_plugin, DIAGNOSTICS } diff --git a/src/librustc_privacy/error_codes.rs b/src/librustc_privacy/error_codes.rs index 70a799d426a07..67066466f1d22 100644 --- a/src/librustc_privacy/error_codes.rs +++ b/src/librustc_privacy/error_codes.rs @@ -1,4 +1,4 @@ -register_long_diagnostics! { +syntax::register_diagnostics! { E0445: r##" A private trait was used on a public type parameter bound. Erroneous code @@ -154,8 +154,5 @@ let f = Bar::Foo::new(); // ok! ``` "##, -} - -register_diagnostics! { // E0450, moved into resolve } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 146058963b69d..28ef3b794babd 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -31,7 +31,7 @@ use syntax_pos::Span; use std::{cmp, fmt, mem}; use std::marker::PhantomData; -mod error_codes; +pub mod error_codes; //////////////////////////////////////////////////////////////////////////////// /// Generic infrastructure used to implement specific visitors below. @@ -2035,5 +2035,3 @@ fn check_private_in_public(tcx: TyCtxt<'_>, krate: CrateNum) { }; krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); } - -__build_diagnostic_array! { librustc_privacy, DIAGNOSTICS } diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index 1faaf97e981c1..adbff67cc8dac 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1,9 +1,7 @@ -use syntax::{register_diagnostics, register_long_diagnostics}; - // Error messages for EXXXX errors. Each message should start and end with a // new line, and be wrapped to 80 characters. In vim you can `:set tw=80` and // use `gq` to wrap paragraphs. Use `:set tw=0` to disable. -register_long_diagnostics! { +syntax::register_diagnostics! { E0128: r##" Type parameter defaults can only use parameters that occur before them. @@ -1662,10 +1660,7 @@ fn const_id() -> T { // error: const parameter } ``` "##, - -} - -register_diagnostics! { +; // E0153, unused error code // E0157, unused error code // E0257, diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index e15d02a9f7ec7..4570bbbe33926 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -286,18 +286,18 @@ impl<'a> PathSource<'a> { } fn error_code(self, has_unexpected_resolution: bool) -> &'static str { - __diagnostic_used!(E0404); - __diagnostic_used!(E0405); - __diagnostic_used!(E0412); - __diagnostic_used!(E0422); - __diagnostic_used!(E0423); - __diagnostic_used!(E0425); - __diagnostic_used!(E0531); - __diagnostic_used!(E0532); - __diagnostic_used!(E0573); - __diagnostic_used!(E0574); - __diagnostic_used!(E0575); - __diagnostic_used!(E0576); + syntax::diagnostic_used!(E0404); + syntax::diagnostic_used!(E0405); + syntax::diagnostic_used!(E0412); + syntax::diagnostic_used!(E0422); + syntax::diagnostic_used!(E0423); + syntax::diagnostic_used!(E0425); + syntax::diagnostic_used!(E0531); + syntax::diagnostic_used!(E0532); + syntax::diagnostic_used!(E0573); + syntax::diagnostic_used!(E0574); + syntax::diagnostic_used!(E0575); + syntax::diagnostic_used!(E0576); match (self, has_unexpected_resolution) { (PathSource::Trait(_), true) => "E0404", (PathSource::Trait(_), false) => "E0405", diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index a822fa049ca1c..0c86d8494fde8 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -113,7 +113,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { // Emit special messages for unresolved `Self` and `self`. if is_self_type(path, ns) { - __diagnostic_used!(E0411); + syntax::diagnostic_used!(E0411); err.code(DiagnosticId::Error("E0411".into())); err.span_label(span, format!("`Self` is only available in impls, traits, \ and type definitions")); @@ -122,7 +122,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { if is_self_value(path, ns) { debug!("smart_resolve_path_fragment: E0424, source={:?}", source); - __diagnostic_used!(E0424); + syntax::diagnostic_used!(E0424); err.code(DiagnosticId::Error("E0424".into())); err.span_label(span, match source { PathSource::Pat => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 875ae449d94e0..6ba08ccef0307 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -67,9 +67,7 @@ use macros::{LegacyBinding, LegacyScope}; type Res = def::Res; -// N.B., this module needs to be declared first so diagnostics are -// registered before they are used. -mod error_codes; +pub mod error_codes; mod diagnostics; mod late; mod macros; @@ -2817,5 +2815,3 @@ impl CrateLint { } } } - -__build_diagnostic_array! { librustc_resolve, DIAGNOSTICS } diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 4d960b416fff0..e11dcfafb8f8b 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -1,6 +1,6 @@ // ignore-tidy-filelength -register_long_diagnostics! { +syntax::register_diagnostics! { E0023: r##" A pattern used to match against an enum variant must provide a sub-pattern for @@ -4870,10 +4870,7 @@ fn foo_recursive(n: usize) -> Pin>> { The `Box<...>` ensures that the result is of known size, and the pin is required to keep it in the same place in memory. "##, - -} // (end of detailed error messages) - -register_diagnostics! { +; // E0035, merged into E0087/E0089 // E0036, merged into E0087/E0089 // E0068, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9d9a9d9b559e4..91c7522280af2 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -78,9 +78,7 @@ This API is completely unstable and subject to change. #[macro_use] extern crate rustc; -// N.B., this module needs to be declared first so diagnostics are -// registered before they are used. -mod error_codes; +pub mod error_codes; mod astconv; mod check; @@ -389,5 +387,3 @@ pub fn hir_trait_to_predicates<'tcx>( bounds } - -__build_diagnostic_array! { librustc_typeck, DIAGNOSTICS } diff --git a/src/librustc_typeck/structured_errors.rs b/src/librustc_typeck/structured_errors.rs index 3e3eab8cf4cfb..273a36edc56ff 100644 --- a/src/librustc_typeck/structured_errors.rs +++ b/src/librustc_typeck/structured_errors.rs @@ -48,7 +48,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for VariadicError<'tcx> { fn session(&self) -> &Session { self.sess } fn code(&self) -> DiagnosticId { - __diagnostic_used!(E0617); + syntax::diagnostic_used!(E0617); DiagnosticId::Error("E0617".to_owned()) } @@ -104,7 +104,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCastError<'tcx> { fn session(&self) -> &Session { self.sess } fn code(&self) -> DiagnosticId { - __diagnostic_used!(E0607); + syntax::diagnostic_used!(E0607); DiagnosticId::Error("E0607".to_owned()) } diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index b754d0833761e..c95c5bd5d02d4 100644 --- a/src/libsyntax/diagnostics/macros.rs +++ b/src/libsyntax/diagnostics/macros.rs @@ -1,13 +1,14 @@ #[macro_export] -macro_rules! register_diagnostic { - ($code:tt, $description:tt) => (__register_diagnostic! { $code, $description }); - ($code:tt) => (__register_diagnostic! { $code }) +macro_rules! diagnostic_used { + ($code:ident) => ( + let _ = crate::error_codes::$code; + ) } #[macro_export] macro_rules! span_fatal { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.span_fatal_with_code( $span, &format!($($message)*), @@ -19,7 +20,7 @@ macro_rules! span_fatal { #[macro_export] macro_rules! span_err { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.span_err_with_code( $span, &format!($($message)*), @@ -31,7 +32,7 @@ macro_rules! span_err { #[macro_export] macro_rules! span_warn { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.span_warn_with_code( $span, &format!($($message)*), @@ -43,7 +44,7 @@ macro_rules! span_warn { #[macro_export] macro_rules! struct_err { ($session:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.struct_err_with_code( &format!($($message)*), $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()), @@ -54,7 +55,7 @@ macro_rules! struct_err { #[macro_export] macro_rules! span_err_or_warn { ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); if $is_warning { $session.span_warn_with_code( $span, @@ -74,7 +75,7 @@ macro_rules! span_err_or_warn { #[macro_export] macro_rules! struct_span_fatal { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.struct_span_fatal_with_code( $span, &format!($($message)*), @@ -86,7 +87,7 @@ macro_rules! struct_span_fatal { #[macro_export] macro_rules! struct_span_err { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.struct_span_err_with_code( $span, &format!($($message)*), @@ -98,7 +99,7 @@ macro_rules! struct_span_err { #[macro_export] macro_rules! stringify_error_code { ($code:ident) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()) }) } @@ -117,7 +118,7 @@ macro_rules! type_error_struct { #[macro_export] macro_rules! struct_span_warn { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); $session.struct_span_warn_with_code( $span, &format!($($message)*), @@ -129,7 +130,7 @@ macro_rules! struct_span_warn { #[macro_export] macro_rules! struct_span_err_or_warn { ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); + $crate::diagnostic_used!($code); if $is_warning { $session.struct_span_warn_with_code( $span, @@ -169,20 +170,22 @@ macro_rules! help { #[macro_export] macro_rules! register_diagnostics { - ($($code:tt),*) => ( - $($crate::register_diagnostic! { $code })* + ($($ecode:ident: $message:expr,)*) => ( + $crate::register_diagnostics!{$($ecode:$message,)* ;} ); - ($($code:tt),*,) => ( - $($crate::register_diagnostic! { $code })* - ) -} -#[macro_export] -macro_rules! register_long_diagnostics { - ($($code:tt: $description:tt),*) => ( - $($crate::register_diagnostic! { $code, $description })* - ); - ($($code:tt: $description:tt),*,) => ( - $($crate::register_diagnostic! { $code, $description })* + ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => ( + pub static DIAGNOSTICS: &[(&str, &str)] = &[ + $( (stringify!($ecode), $message), )* + ]; + + $( + #[deny(unused)] + pub(crate) const $ecode: &str = $message; + )* + $( + #[deny(unused)] + pub(crate) const $code: () = (); + )* ) } diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs deleted file mode 100644 index 5de39c8d14d17..0000000000000 --- a/src/libsyntax/diagnostics/plugin.rs +++ /dev/null @@ -1,185 +0,0 @@ -use std::collections::BTreeMap; - -use crate::ast::{self, Ident, Name}; -use crate::source_map; -use crate::ext::base::{ExtCtxt, MacEager, MacResult}; -use crate::parse::token::{self, Token}; -use crate::ptr::P; -use crate::symbol::kw; -use crate::tokenstream::{TokenTree, TokenStream}; - -use smallvec::smallvec; -use syntax_pos::Span; - -pub use errors::*; - -// Maximum width of any line in an extended error description (inclusive). -const MAX_DESCRIPTION_WIDTH: usize = 80; - -/// Error information type. -pub struct ErrorInfo { - pub description: Option, - pub use_site: Option -} - -/// Mapping from error codes to metadata. -pub type ErrorMap = BTreeMap; - -pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt<'_>, - span: Span, - tts: TokenStream) - -> Box { - assert_eq!(tts.len(), 1); - let code = match tts.into_trees().next() { - Some(TokenTree::Token(Token { kind: token::Ident(code, _), .. })) => code, - _ => unreachable!() - }; - - ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { - match diagnostics.get_mut(&code) { - // Previously used errors. - Some(&mut ErrorInfo { description: _, use_site: Some(previous_span) }) => { - ecx.struct_span_warn(span, &format!( - "diagnostic code {} already used", code - )).span_note(previous_span, "previous invocation") - .emit(); - } - // Newly used errors. - Some(ref mut info) => { - info.use_site = Some(span); - } - // Unregistered errors. - None => { - ecx.span_err(span, &format!( - "used diagnostic code {} not registered", code - )); - } - } - }); - MacEager::expr(ecx.expr_tuple(span, Vec::new())) -} - -pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt<'_>, - span: Span, - tts: TokenStream) - -> Box { - assert!(tts.len() == 1 || tts.len() == 3); - let mut cursor = tts.into_trees(); - let code = match cursor.next() { - Some(TokenTree::Token(Token { kind: token::Ident(code, _), .. })) => code, - _ => unreachable!() - }; - let description = match (cursor.next(), cursor.next()) { - (None, None) => None, - ( - Some(TokenTree::Token(Token { kind: token::Comma, .. })), - Some(TokenTree::Token(Token { kind: token::Literal(token::Lit { symbol, .. }), ..})) - ) => { - Some(symbol) - }, - _ => unreachable!() - }; - - // Check that the description starts and ends with a newline and doesn't - // overflow the maximum line width. - description.map(|raw_msg| { - let msg = raw_msg.as_str(); - if !msg.starts_with("\n") || !msg.ends_with("\n") { - ecx.span_err(span, &format!( - "description for error code {} doesn't start and end with a newline", - code - )); - } - - // URLs can be unavoidably longer than the line limit, so we allow them. - // Allowed format is: `[name]: https://www.rust-lang.org/` - let is_url = |l: &str| l.starts_with("[") && l.contains("]:") && l.contains("http"); - - if msg.lines().any(|line| line.len() > MAX_DESCRIPTION_WIDTH && !is_url(line)) { - ecx.span_err(span, &format!( - "description for error code {} contains a line longer than {} characters.\n\ - if you're inserting a long URL use the footnote style to bypass this check.", - code, MAX_DESCRIPTION_WIDTH - )); - } - }); - // Add the error to the map. - ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { - let info = ErrorInfo { - description, - use_site: None - }; - if diagnostics.insert(code, info).is_some() { - ecx.span_err(span, &format!( - "diagnostic code {} already registered", code - )); - } - }); - - MacEager::items(smallvec![]) -} - -pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt<'_>, - span: Span, - tts: TokenStream) - -> Box { - assert_eq!(tts.len(), 3); - let ident = match tts.into_trees().nth(2) { - // DIAGNOSTICS ident. - Some(TokenTree::Token(Token { kind: token::Ident(name, _), span })) - => Ident::new(name, span), - _ => unreachable!() - }; - - // Construct the output expression. - let (count, expr) = - ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { - let descriptions: Vec> = - diagnostics.iter().filter_map(|(&code, info)| { - info.description.map(|description| { - ecx.expr_tuple(span, vec![ - ecx.expr_str(span, code), - ecx.expr_str(span, description) - ]) - }) - }).collect(); - (descriptions.len(), ecx.expr_vec(span, descriptions)) - }); - - let static_ = ecx.lifetime(span, Ident::with_dummy_span(kw::StaticLifetime)); - let ty_str = ecx.ty_rptr( - span, - ecx.ty_ident(span, ecx.ident_of("str")), - Some(static_), - ast::Mutability::Immutable, - ); - - let ty = ecx.ty( - span, - ast::TyKind::Array( - ecx.ty( - span, - ast::TyKind::Tup(vec![ty_str.clone(), ty_str]) - ), - ast::AnonConst { - id: ast::DUMMY_NODE_ID, - value: ecx.expr_usize(span, count), - }, - ), - ); - - MacEager::items(smallvec![ - P(ast::Item { - ident, - attrs: Vec::new(), - id: ast::DUMMY_NODE_ID, - node: ast::ItemKind::Const( - ty, - expr, - ), - vis: source_map::respan(span.shrink_to_lo(), ast::VisibilityKind::Public), - span, - tokens: None, - }) - ]) -} diff --git a/src/libsyntax/error_codes.rs b/src/libsyntax/error_codes.rs index 76b2575bfd688..9925dd8ada0d5 100644 --- a/src/libsyntax/error_codes.rs +++ b/src/libsyntax/error_codes.rs @@ -421,9 +421,8 @@ Delete the offending feature attribute, or add it to the list of allowed features in the `-Z allow_features` flag. "##, -} +; -register_diagnostics! { E0539, // incorrect meta item E0540, // multiple rustc_deprecated attributes E0542, // missing 'since' @@ -447,7 +446,7 @@ register_diagnostics! { // attribute E0630, E0693, // incorrect `repr(align)` attribute format - E0694, // an unknown tool name found in scoped attributes +// E0694, // an unknown tool name found in scoped attributes E0703, // invalid ABI E0717, // rustc_promotable without stability attribute } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 1741932c1b80e..75ce306df800e 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -123,11 +123,8 @@ scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals); pub mod diagnostics { #[macro_use] pub mod macros; - pub mod plugin; } -// N.B., this module needs to be declared first so diagnostics are -// registered before they are used. pub mod error_codes; pub mod util { @@ -182,5 +179,3 @@ pub mod ext { } pub mod early_buffered_lints; - -__build_diagnostic_array! { libsyntax, DIAGNOSTICS } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index b1af4806e2d78..981f5f1f7b004 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -8,7 +8,6 @@ use crate::parse::parser::Parser; use crate::parse::parser::emit_unclosed_delims; use crate::parse::token::TokenKind; use crate::tokenstream::{TokenStream, TokenTree}; -use crate::diagnostics::plugin::ErrorMap; use crate::print::pprust; use crate::symbol::Symbol; @@ -64,8 +63,6 @@ pub struct ParseSess { pub missing_fragment_specifiers: Lock>, /// Places where raw identifiers were used. This is used for feature-gating raw identifiers. pub raw_identifier_spans: Lock>, - /// The registered diagnostics codes. - crate registered_diagnostics: Lock, /// Used to determine and report recursive module inclusions. included_mod_stack: Lock>, source_map: Lrc, @@ -95,7 +92,6 @@ impl ParseSess { config: FxHashSet::default(), missing_fragment_specifiers: Lock::new(FxHashSet::default()), raw_identifier_spans: Lock::new(Vec::new()), - registered_diagnostics: Lock::new(ErrorMap::new()), included_mod_stack: Lock::new(vec![]), source_map, buffered_lints: Lock::new(vec![]), diff --git a/src/libsyntax_ext/error_codes.rs b/src/libsyntax_ext/error_codes.rs index 49808fc0b60e2..2bc990574f7a8 100644 --- a/src/libsyntax_ext/error_codes.rs +++ b/src/libsyntax_ext/error_codes.rs @@ -1,5 +1,3 @@ -use syntax::register_long_diagnostics; - // Error messages for EXXXX errors. // Each message should start and end with a new line, and be wrapped to 80 // characters. In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use From 3f1dc326edee5528db80894eedd2036fdc05bca8 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 3 Sep 2019 21:50:01 -0400 Subject: [PATCH 518/618] Remove codegen dependencies Not doing this leads to building two copies of e.g. num_cpus in the sysroot and _llvm deps, leading to conflicts between the two when compiling librustc_codegen_llvm. It's not entirely clear why this is the case after the changes in this PR but likely has something to do with a subtle difference in ordering or similar. --- Cargo.lock | 4 ---- src/librustc_codegen_llvm/Cargo.toml | 4 ---- 2 files changed, 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 243a326646c38..e0b0640178b03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3129,11 +3129,7 @@ dependencies = [ name = "rustc_codegen_llvm" version = "0.0.0" dependencies = [ - "cc", - "memmap", - "num_cpus", "rustc_llvm", - "tempfile", ] [[package]] diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml index 5e1b0eafdec36..98efa6a5804bd 100644 --- a/src/librustc_codegen_llvm/Cargo.toml +++ b/src/librustc_codegen_llvm/Cargo.toml @@ -11,11 +11,7 @@ crate-type = ["dylib"] test = false [dependencies] -cc = "1.0.1" # Used to locate MSVC -num_cpus = "1.0" -tempfile = "3.0" rustc_llvm = { path = "../librustc_llvm" } -memmap = "0.6" [features] # This is used to convince Cargo to separately cache builds of `rustc_codegen_llvm` From 4de4f303e5cee3e40b8e91a381517a457af7b4cc Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 3 Sep 2019 22:04:01 -0400 Subject: [PATCH 519/618] Fix error index generator for new register_diagnostics API --- src/tools/error_index_generator/build.rs | 51 ++++++++++-------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/src/tools/error_index_generator/build.rs b/src/tools/error_index_generator/build.rs index 2ac7351fce469..832aa3b1c8dfd 100644 --- a/src/tools/error_index_generator/build.rs +++ b/src/tools/error_index_generator/build.rs @@ -14,9 +14,7 @@ fn main() { if entry.file_name() == "error_codes.rs" { println!("cargo:rerun-if-changed={}", entry.path().to_str().unwrap()); let file = fs::read_to_string(entry.path()).unwrap() - .replace("use syntax::{register_diagnostics, register_long_diagnostics};", "") - .replace("use syntax::register_diagnostics;", "") - .replace("use syntax::register_long_diagnostics;", ""); + .replace("syntax::register_diagnostics!", "register_diagnostics!"); let contents = format!("(|| {{\n{}\n}})();", file); fs::write(&out_dir.join(&format!("error_{}.rs", idx)), &contents).unwrap(); @@ -26,36 +24,31 @@ fn main() { } let mut all = String::new(); - all.push_str("fn register_all() -> Vec<(&'static str, Option<&'static str>)> {\n"); - all.push_str("let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new();\n"); - all.push_str(r#" -macro_rules! register_diagnostics { - ($($code:tt),*) => {{ - long_codes.extend([$( - stringify!($code), - )*].iter().cloned().map(|s| (s, None)).collect::>()); - }}; - ($($code:tt),*,) => {{ - long_codes.extend([$( - stringify!($code), - )*].iter().cloned().map(|s| (s, None))); - }} -} + all.push_str(r###" +fn register_all() -> Vec<(&'static str, Option<&'static str>)> { + let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new(); + macro_rules! register_diagnostics { + ($($ecode:ident: $message:expr,)*) => ( + register_diagnostics!{$($ecode:$message,)* ;} + ); -macro_rules! register_long_diagnostics { - ($($code:tt: $description:tt),*) => { - {long_codes.extend([$( - (stringify!($code), Some(stringify!($description))), - )*].iter());} - }; - ($($code:tt: $description:tt),*,) => { - {long_codes.extend([$( - (stringify!($code), Some(stringify!($description))), - )*].iter());} + ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => ( + $( + {long_codes.extend([ + (stringify!($ecode), Some(stringify!($message))), + ].iter());} + )* + $( + {long_codes.extend([ + stringify!($code), + ].iter().cloned().map(|s| (s, None)).collect::>());} + )* + ) } -}"#); +"###); for idx in 0..idx { all.push_str(&format!(r#"include!(concat!(env!("OUT_DIR"), "/error_{}.rs"));"#, idx)); + all.push_str("\n"); } all.push_str("\nlong_codes\n"); all.push_str("}\n"); From 41b39fce98fc141fef067cc22c1e9e9dc7b88b29 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 3 Sep 2019 22:10:12 -0400 Subject: [PATCH 520/618] Remove rustc_diagnostic_macros feature --- src/librustc/lib.rs | 1 - src/librustc_codegen_llvm/lib.rs | 1 - src/librustc_codegen_ssa/lib.rs | 1 - src/librustc_codegen_utils/lib.rs | 1 - src/librustc_driver/lib.rs | 1 - src/librustc_interface/passes.rs | 4 ---- src/librustc_lint/lib.rs | 1 - src/librustc_metadata/lib.rs | 1 - src/librustc_mir/lib.rs | 1 - src/librustc_passes/lib.rs | 1 - src/librustc_plugin/lib.rs | 1 - src/librustc_privacy/lib.rs | 1 - src/librustc_resolve/lib.rs | 1 - src/librustc_typeck/lib.rs | 1 - src/libsyntax/feature_gate/active.rs | 6 ------ src/libsyntax/lib.rs | 1 - src/libsyntax_ext/lib.rs | 1 - .../ui/feature-gate/allow-features-empty.rs | 2 -- .../feature-gate/allow-features-empty.stderr | 14 ++++--------- src/test/ui/feature-gate/allow-features.rs | 4 +--- .../ui/feature-gate/allow-features.stderr | 4 ++-- .../feature-gate-rustc-diagnostic-macros.rs | 13 ------------ ...eature-gate-rustc-diagnostic-macros.stderr | 20 ------------------- 23 files changed, 7 insertions(+), 75 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index c5d2b2d7e7f87..d25b954bbe306 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -45,7 +45,6 @@ #![feature(non_exhaustive)] #![feature(optin_builtin_traits)] #![feature(range_is_empty)] -#![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] #![feature(specialization)] #![feature(unboxed_closures)] diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index f032d0ff0464c..9f2c303145dc8 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -14,7 +14,6 @@ #![feature(in_band_lifetimes)] #![feature(libc)] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![feature(optin_builtin_traits)] #![feature(concat_idents)] #![feature(link_args)] diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index 0f98310722ee3..90bf964ceaa13 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -4,7 +4,6 @@ #![feature(box_syntax)] #![feature(core_intrinsics)] #![feature(libc)] -#![feature(rustc_diagnostic_macros)] #![feature(stmt_expr_attributes)] #![feature(try_blocks)] #![feature(in_band_lifetimes)] diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 4ea375b59b2c0..1201446afb531 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -10,7 +10,6 @@ #![feature(core_intrinsics)] #![feature(never_type)] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![feature(in_band_lifetimes)] #![recursion_limit="256"] diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 9a6a12e261c10..a912ea3c35821 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -9,7 +9,6 @@ #![feature(box_syntax)] #![cfg_attr(unix, feature(libc))] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![feature(set_stdio)] #![feature(no_debug)] #![feature(integer_atomics)] diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index bd9b240e24efa..af769a537a675 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -291,10 +291,6 @@ pub fn register_plugins<'a>( let mut registry = Registry::new(sess, krate.span); time(sess, "plugin registration", || { - if sess.features_untracked().rustc_diagnostic_macros { - // FIXME: remove feature gate - } - for registrar in registrars { registry.args_hidden = Some(registrar.args); (registrar.fun)(&mut registry); diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 27833161ef23d..4ee6551f78781 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -15,7 +15,6 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![recursion_limit="256"] diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 3ab7d372461b8..e6104e629e9fb 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -8,7 +8,6 @@ #![feature(nll)] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] -#![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(specialization)] diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 7a5db4fc19d02..f27db351b74db 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -14,7 +14,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(const_fn)] #![feature(decl_macro)] #![feature(exhaustive_patterns)] -#![feature(rustc_diagnostic_macros)] #![feature(never_type)] #![feature(specialization)] #![feature(try_trait)] diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 2070f306112a1..cf2da4ffa2af0 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -9,7 +9,6 @@ #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(bind_by_move_pattern_guards)] -#![feature(rustc_diagnostic_macros)] #![recursion_limit="256"] diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 1cf01d481e468..4e1a47c503e59 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -54,7 +54,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![recursion_limit="256"] diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 28ef3b794babd..1e61f78c357df 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -2,7 +2,6 @@ #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![recursion_limit="256"] diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6ba08ccef0307..7e93e12601376 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -13,7 +13,6 @@ #![feature(label_break_value)] #![feature(mem_take)] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![recursion_limit="256"] diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 91c7522280af2..959483e4439ff 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -65,7 +65,6 @@ This API is completely unstable and subject to change. #![feature(exhaustive_patterns)] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] #![feature(never_type)] #![feature(inner_deref)] diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index c947b09fdcb57..86979bdb1fb52 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -120,12 +120,6 @@ declare_features! ( /// macros disappear). (active, allow_internal_unsafe, "1.0.0", None, None), - /// Allows using the macros: - /// + `__diagnostic_used` - /// + `__register_diagnostic` - /// +`__build_diagnostic_array` - (active, rustc_diagnostic_macros, "1.0.0", None, None), - /// Allows using `#[rustc_const_unstable(feature = "foo", ..)]` which /// lets a function to be `const` when opted into with `#![feature(foo)]`. (active, rustc_const_unstable, "1.0.0", None, None), diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 75ce306df800e..49efbce482fa3 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -18,7 +18,6 @@ #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] -#![feature(rustc_diagnostic_macros)] #![feature(try_trait)] #![feature(unicode_internals)] diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 26ef80b2b06df..5bc6345d8118e 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -9,7 +9,6 @@ #![feature(nll)] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] -#![feature(rustc_diagnostic_macros)] extern crate proc_macro; diff --git a/src/test/ui/feature-gate/allow-features-empty.rs b/src/test/ui/feature-gate/allow-features-empty.rs index 784a1d2697d67..641e4b852e79f 100644 --- a/src/test/ui/feature-gate/allow-features-empty.rs +++ b/src/test/ui/feature-gate/allow-features-empty.rs @@ -1,8 +1,6 @@ // compile-flags: -Z allow_features= // Note: This test uses rustc internal flags because they will never stabilize. -#![feature(rustc_diagnostic_macros)] //~ ERROR - #![feature(rustc_const_unstable)] //~ ERROR #![feature(lang_items)] //~ ERROR diff --git a/src/test/ui/feature-gate/allow-features-empty.stderr b/src/test/ui/feature-gate/allow-features-empty.stderr index ab41422ed05b8..a87d105850327 100644 --- a/src/test/ui/feature-gate/allow-features-empty.stderr +++ b/src/test/ui/feature-gate/allow-features-empty.stderr @@ -1,27 +1,21 @@ -error[E0725]: the feature `rustc_diagnostic_macros` is not in the list of allowed features - --> $DIR/allow-features-empty.rs:4:12 - | -LL | #![feature(rustc_diagnostic_macros)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features - --> $DIR/allow-features-empty.rs:6:12 + --> $DIR/allow-features-empty.rs:4:12 | LL | #![feature(rustc_const_unstable)] | ^^^^^^^^^^^^^^^^^^^^ error[E0725]: the feature `lang_items` is not in the list of allowed features - --> $DIR/allow-features-empty.rs:8:12 + --> $DIR/allow-features-empty.rs:6:12 | LL | #![feature(lang_items)] | ^^^^^^^^^^ error[E0725]: the feature `unknown_stdlib_feature` is not in the list of allowed features - --> $DIR/allow-features-empty.rs:10:12 + --> $DIR/allow-features-empty.rs:8:12 | LL | #![feature(unknown_stdlib_feature)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0725`. diff --git a/src/test/ui/feature-gate/allow-features.rs b/src/test/ui/feature-gate/allow-features.rs index de3439a5b628f..de69e48a65fdf 100644 --- a/src/test/ui/feature-gate/allow-features.rs +++ b/src/test/ui/feature-gate/allow-features.rs @@ -1,8 +1,6 @@ -// compile-flags: -Z allow_features=rustc_diagnostic_macros,lang_items +// compile-flags: -Z allow_features=lang_items // Note: This test uses rustc internal flags because they will never stabilize. -#![feature(rustc_diagnostic_macros)] - #![feature(rustc_const_unstable)] //~ ERROR #![feature(lang_items)] diff --git a/src/test/ui/feature-gate/allow-features.stderr b/src/test/ui/feature-gate/allow-features.stderr index 5b39a6f053bde..157dddf06ad1d 100644 --- a/src/test/ui/feature-gate/allow-features.stderr +++ b/src/test/ui/feature-gate/allow-features.stderr @@ -1,11 +1,11 @@ error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features - --> $DIR/allow-features.rs:6:12 + --> $DIR/allow-features.rs:4:12 | LL | #![feature(rustc_const_unstable)] | ^^^^^^^^^^^^^^^^^^^^ error[E0725]: the feature `unknown_stdlib_feature` is not in the list of allowed features - --> $DIR/allow-features.rs:10:12 + --> $DIR/allow-features.rs:8:12 | LL | #![feature(unknown_stdlib_feature)] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs deleted file mode 100644 index 63c2c31fd30e6..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Test that diagnostic macros are gated by `rustc_diagnostic_macros` feature -// gate - -__register_diagnostic!(E0001); -//~^ ERROR cannot find macro `__register_diagnostic!` in this scope - -fn main() { - __diagnostic_used!(E0001); - //~^ ERROR cannot find macro `__diagnostic_used!` in this scope -} - -__build_diagnostic_array!(DIAGNOSTICS); -//~^ ERROR cannot find macro `__build_diagnostic_array!` in this scope diff --git a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr deleted file mode 100644 index 676b8b9f056c1..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: cannot find macro `__build_diagnostic_array!` in this scope - --> $DIR/feature-gate-rustc-diagnostic-macros.rs:12:1 - | -LL | __build_diagnostic_array!(DIAGNOSTICS); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: cannot find macro `__diagnostic_used!` in this scope - --> $DIR/feature-gate-rustc-diagnostic-macros.rs:8:5 - | -LL | __diagnostic_used!(E0001); - | ^^^^^^^^^^^^^^^^^ - -error: cannot find macro `__register_diagnostic!` in this scope - --> $DIR/feature-gate-rustc-diagnostic-macros.rs:4:1 - | -LL | __register_diagnostic!(E0001); - | ^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - From 0b7ba6ec54db24b676d376665692a49d0ecd603a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Sep 2019 19:32:44 -0700 Subject: [PATCH 521/618] std: Improve downstream codegen in `Command::env` This commit rejiggers the generics used in the implementation of `Command::env` with the purpose of reducing the amount of codegen that needs to happen in consumer crates, instead preferring to generate code into libstd. This was found when profiling the compile times of the `cc` crate where the binary rlib produced had a lot of `BTreeMap` code compiled into it but the crate doesn't actually use `BTreeMap`. It turns out that `Command::env` is generic enough to codegen the entire implementation in calling crates, but in this case there's no performance concern so it's fine to compile the code into the standard library. This change is done by removing the generic on the `CommandEnv` map which is intended to handle case-insensitive variables on Windows. Instead now a generic isn't used but rather a `use` statement defined per-platform is used. With this commit a debug build of `Command::new("foo").env("a", "b")` drops from 21k lines of LLVM IR to 10k. --- src/libstd/sys/cloudabi/shims/process.rs | 8 +-- src/libstd/sys/sgx/process.rs | 8 +-- src/libstd/sys/unix/process/mod.rs | 1 + src/libstd/sys/unix/process/process_common.rs | 8 +-- .../sys/vxworks/process/process_common.rs | 10 ++-- src/libstd/sys/wasi/process.rs | 8 +-- src/libstd/sys/wasm/process.rs | 8 +-- src/libstd/sys/windows/process.rs | 24 ++++----- src/libstd/sys_common/process.rs | 51 +++++-------------- 9 files changed, 56 insertions(+), 70 deletions(-) diff --git a/src/libstd/sys/cloudabi/shims/process.rs b/src/libstd/sys/cloudabi/shims/process.rs index e719b362cbf55..03a59d6d7c832 100644 --- a/src/libstd/sys/cloudabi/shims/process.rs +++ b/src/libstd/sys/cloudabi/shims/process.rs @@ -4,14 +4,16 @@ use crate::io; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys::{unsupported, Void}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; + +pub use crate::ffi::OsString as EnvKey; //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// pub struct Command { - env: CommandEnv, + env: CommandEnv, } // passed back to std::process with the pipes connected to the child, if any @@ -37,7 +39,7 @@ impl Command { pub fn arg(&mut self, _arg: &OsStr) {} - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } diff --git a/src/libstd/sys/sgx/process.rs b/src/libstd/sys/sgx/process.rs index a02e009d95356..edf933d10e074 100644 --- a/src/libstd/sys/sgx/process.rs +++ b/src/libstd/sys/sgx/process.rs @@ -4,14 +4,16 @@ use crate::io; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys::{unsupported, Void}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; + +pub use crate::ffi::OsString as EnvKey; //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// pub struct Command { - env: CommandEnv + env: CommandEnv, } // passed back to std::process with the pipes connected to the child, if any @@ -38,7 +40,7 @@ impl Command { pub fn arg(&mut self, _arg: &OsStr) { } - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } diff --git a/src/libstd/sys/unix/process/mod.rs b/src/libstd/sys/unix/process/mod.rs index bba4b21c46232..056a20345f404 100644 --- a/src/libstd/sys/unix/process/mod.rs +++ b/src/libstd/sys/unix/process/mod.rs @@ -1,5 +1,6 @@ pub use self::process_common::{Command, ExitStatus, ExitCode, Stdio, StdioPipes}; pub use self::process_inner::Process; +pub use crate::ffi::OsString as EnvKey; mod process_common; #[cfg(not(target_os = "fuchsia"))] diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 21fca23a8fe9e..72e66cc8e7240 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -7,7 +7,7 @@ use crate::ptr; use crate::sys::fd::FileDesc; use crate::sys::fs::{File, OpenOptions}; use crate::sys::pipe::{self, AnonPipe}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; use crate::collections::BTreeMap; use libc::{c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE}; @@ -69,7 +69,7 @@ pub struct Command { program: CString, args: Vec, argv: Argv, - env: CommandEnv, + env: CommandEnv, cwd: Option, uid: Option, @@ -201,7 +201,7 @@ impl Command { self.stderr = Some(stderr); } - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } @@ -271,7 +271,7 @@ impl CStringArray { } } -fn construct_envp(env: BTreeMap, saw_nul: &mut bool) -> CStringArray { +fn construct_envp(env: BTreeMap, saw_nul: &mut bool) -> CStringArray { let mut result = CStringArray::with_capacity(env.len()); for (k, v) in env { let mut k: OsString = k.into(); diff --git a/src/libstd/sys/vxworks/process/process_common.rs b/src/libstd/sys/vxworks/process/process_common.rs index ba797354a7380..509140229fd3a 100644 --- a/src/libstd/sys/vxworks/process/process_common.rs +++ b/src/libstd/sys/vxworks/process/process_common.rs @@ -7,11 +7,13 @@ use crate::ptr; use crate::sys::fd::FileDesc; use crate::sys::fs::{File, OpenOptions}; use crate::sys::pipe::{self, AnonPipe}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; use crate::collections::BTreeMap; use libc::{c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE}; +pub use crate::ffi::OsString as EnvKey; + //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// @@ -37,7 +39,7 @@ pub struct Command { program: CString, args: Vec, argv: Argv, - env: CommandEnv, + env: CommandEnv, cwd: Option, uid: Option, @@ -170,7 +172,7 @@ impl Command { self.stderr = Some(stderr); } - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } @@ -240,7 +242,7 @@ impl CStringArray { } } -fn construct_envp(env: BTreeMap, saw_nul: &mut bool) -> CStringArray { +fn construct_envp(env: BTreeMap, saw_nul: &mut bool) -> CStringArray { let mut result = CStringArray::with_capacity(env.len()); for (k, v) in env { let mut k: OsString = k.into(); diff --git a/src/libstd/sys/wasi/process.rs b/src/libstd/sys/wasi/process.rs index 788b829f4bac9..1c4d028b7618b 100644 --- a/src/libstd/sys/wasi/process.rs +++ b/src/libstd/sys/wasi/process.rs @@ -4,14 +4,16 @@ use crate::io; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys::{unsupported, Void}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; + +pub use crate::ffi::OsString as EnvKey; //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// pub struct Command { - env: CommandEnv + env: CommandEnv } // passed back to std::process with the pipes connected to the child, if any @@ -38,7 +40,7 @@ impl Command { pub fn arg(&mut self, _arg: &OsStr) { } - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/wasm/process.rs index a02e009d95356..edf933d10e074 100644 --- a/src/libstd/sys/wasm/process.rs +++ b/src/libstd/sys/wasm/process.rs @@ -4,14 +4,16 @@ use crate::io; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys::{unsupported, Void}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; + +pub use crate::ffi::OsString as EnvKey; //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// pub struct Command { - env: CommandEnv + env: CommandEnv, } // passed back to std::process with the pipes connected to the child, if any @@ -38,7 +40,7 @@ impl Command { pub fn arg(&mut self, _arg: &OsStr) { } - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 05e0ca6706453..8658deb854635 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -19,7 +19,7 @@ use crate::sys::pipe::{self, AnonPipe}; use crate::sys::stdio; use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; -use crate::sys_common::process::{CommandEnv, EnvKey}; +use crate::sys_common::process::CommandEnv; use crate::borrow::Borrow; use libc::{c_void, EXIT_SUCCESS, EXIT_FAILURE}; @@ -30,30 +30,28 @@ use libc::{c_void, EXIT_SUCCESS, EXIT_FAILURE}; #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] #[doc(hidden)] -pub struct WindowsEnvKey(OsString); +pub struct EnvKey(OsString); -impl From for WindowsEnvKey { +impl From for EnvKey { fn from(k: OsString) -> Self { let mut buf = k.into_inner().into_inner(); buf.make_ascii_uppercase(); - WindowsEnvKey(FromInner::from_inner(FromInner::from_inner(buf))) + EnvKey(FromInner::from_inner(FromInner::from_inner(buf))) } } -impl From for OsString { - fn from(k: WindowsEnvKey) -> Self { k.0 } +impl From for OsString { + fn from(k: EnvKey) -> Self { k.0 } } -impl Borrow for WindowsEnvKey { +impl Borrow for EnvKey { fn borrow(&self) -> &OsStr { &self.0 } } -impl AsRef for WindowsEnvKey { +impl AsRef for EnvKey { fn as_ref(&self) -> &OsStr { &self.0 } } -impl EnvKey for WindowsEnvKey {} - fn ensure_no_nuls>(str: T) -> io::Result { if str.as_ref().encode_wide().any(|b| b == 0) { @@ -66,7 +64,7 @@ fn ensure_no_nuls>(str: T) -> io::Result { pub struct Command { program: OsString, args: Vec, - env: CommandEnv, + env: CommandEnv, cwd: Option, flags: u32, detach: bool, // not currently exposed in std::process @@ -110,7 +108,7 @@ impl Command { pub fn arg(&mut self, arg: &OsStr) { self.args.push(arg.to_os_string()) } - pub fn env_mut(&mut self) -> &mut CommandEnv { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } pub fn cwd(&mut self, dir: &OsStr) { @@ -498,7 +496,7 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result> { } } -fn make_envp(maybe_env: Option>) +fn make_envp(maybe_env: Option>) -> io::Result<(*mut c_void, Vec)> { // On Windows we pass an "environment block" which is not a char**, but // rather a concatenation of null-terminated k=v\0 sequences, with a final diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs index 4d40dec97245a..bdf66fca35970 100644 --- a/src/libstd/sys_common/process.rs +++ b/src/libstd/sys_common/process.rs @@ -1,47 +1,20 @@ #![allow(dead_code)] #![unstable(feature = "process_internals", issue = "0")] -use crate::ffi::{OsStr, OsString}; -use crate::env; use crate::collections::BTreeMap; -use crate::borrow::Borrow; - -pub trait EnvKey: - From + Into + - Borrow + Borrow + AsRef + - Ord + Clone {} - -// Implement a case-sensitive environment variable key -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] -pub struct DefaultEnvKey(OsString); - -impl From for DefaultEnvKey { - fn from(k: OsString) -> Self { DefaultEnvKey(k) } -} - -impl From for OsString { - fn from(k: DefaultEnvKey) -> Self { k.0 } -} - -impl Borrow for DefaultEnvKey { - fn borrow(&self) -> &OsStr { &self.0 } -} - -impl AsRef for DefaultEnvKey { - fn as_ref(&self) -> &OsStr { &self.0 } -} - -impl EnvKey for DefaultEnvKey {} +use crate::env; +use crate::ffi::{OsStr, OsString}; +use crate::sys::process::EnvKey; // Stores a set of changes to an environment #[derive(Clone, Debug)] -pub struct CommandEnv { +pub struct CommandEnv { clear: bool, saw_path: bool, - vars: BTreeMap> + vars: BTreeMap> } -impl Default for CommandEnv { +impl Default for CommandEnv { fn default() -> Self { CommandEnv { clear: false, @@ -51,10 +24,10 @@ impl Default for CommandEnv { } } -impl CommandEnv { +impl CommandEnv { // Capture the current environment with these changes applied - pub fn capture(&self) -> BTreeMap { - let mut result = BTreeMap::::new(); + pub fn capture(&self) -> BTreeMap { + let mut result = BTreeMap::::new(); if !self.clear { for (k, v) in env::vars_os() { result.insert(k.into(), v); @@ -90,7 +63,7 @@ impl CommandEnv { !self.clear && self.vars.is_empty() } - pub fn capture_if_changed(&self) -> Option> { + pub fn capture_if_changed(&self) -> Option> { if self.is_unchanged() { None } else { @@ -103,6 +76,7 @@ impl CommandEnv { self.maybe_saw_path(&key); self.vars.insert(key.to_owned().into(), Some(value.to_owned())); } + pub fn remove(&mut self, key: &OsStr) { self.maybe_saw_path(&key); if self.clear { @@ -111,13 +85,16 @@ impl CommandEnv { self.vars.insert(key.to_owned().into(), None); } } + pub fn clear(&mut self) { self.clear = true; self.vars.clear(); } + pub fn have_changed_path(&self) -> bool { self.saw_path || self.clear } + fn maybe_saw_path(&mut self, key: &OsStr) { if !self.saw_path && key == "PATH" { self.saw_path = true; From 159d249705659ecb2ef41623105cab1c9f95b802 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 5 Sep 2019 21:31:12 +0200 Subject: [PATCH 522/618] annotate-snippet emitter: Deal with multispans from macros, too This moves the two methods from the `EmitterWriter` impl to trait default methods in the `Emitter` trait so that they can be re-used by the `AnnotateSnippetEmitterWriter`. Closes #61810 --- .../annotate_snippet_emitter_writer.rs | 12 +- src/librustc_errors/emitter.rs | 251 +++++++++--------- 2 files changed, 137 insertions(+), 126 deletions(-) diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index 3bed5d81dc514..60ee7507223e9 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -30,10 +30,14 @@ pub struct AnnotateSnippetEmitterWriter { impl Emitter for AnnotateSnippetEmitterWriter { /// The entry point for the diagnostics generation fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { - let children = db.children.clone(); - let (primary_span, suggestions) = self.primary_span_formatted(&db); - - // FIXME(#59346): Add `fix_multispans_in_std_macros` function from emitter.rs + let mut children = db.children.clone(); + let (mut primary_span, suggestions) = self.primary_span_formatted(&db); + + self.fix_multispans_in_std_macros(&self.source_map, + &mut primary_span, + &mut children, + &db.level, + db.handler.flags.external_macro_backtrace); self.emit_messages_default(&db.level, db.message(), diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index a298f9958f2d1..0ce69eecc6b1e 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -247,6 +247,133 @@ pub trait Emitter { (primary_span, &db.suggestions) } } + + // This does a small "fix" for multispans by looking to see if it can find any that + // point directly at <*macros>. Since these are often difficult to read, this + // will change the span to point at the use site. + fn fix_multispans_in_std_macros(&self, + source_map: &Option>, + span: &mut MultiSpan, + children: &mut Vec, + level: &Level, + backtrace: bool) { + let mut spans_updated = self.fix_multispan_in_std_macros(source_map, span, backtrace); + for child in children.iter_mut() { + spans_updated |= self.fix_multispan_in_std_macros( + source_map, + &mut child.span, + backtrace + ); + } + let msg = if level == &Error { + "this error originates in a macro outside of the current crate \ + (in Nightly builds, run with -Z external-macro-backtrace \ + for more info)".to_string() + } else { + "this warning originates in a macro outside of the current crate \ + (in Nightly builds, run with -Z external-macro-backtrace \ + for more info)".to_string() + }; + + if spans_updated { + children.push(SubDiagnostic { + level: Level::Note, + message: vec![ + (msg, + Style::NoStyle), + ], + span: MultiSpan::new(), + render_span: None, + }); + } + } + + // This "fixes" MultiSpans that contain Spans that are pointing to locations inside of + // <*macros>. Since these locations are often difficult to read, we move these Spans from + // <*macros> to their corresponding use site. + fn fix_multispan_in_std_macros(&self, + source_map: &Option>, + span: &mut MultiSpan, + always_backtrace: bool) -> bool { + let mut spans_updated = false; + + if let Some(ref sm) = source_map { + let mut before_after: Vec<(Span, Span)> = vec![]; + let mut new_labels: Vec<(Span, String)> = vec![]; + + // First, find all the spans in <*macros> and point instead at their use site + for sp in span.primary_spans() { + if sp.is_dummy() { + continue; + } + let call_sp = sm.call_span_if_macro(*sp); + if call_sp != *sp && !always_backtrace { + before_after.push((*sp, call_sp)); + } + let backtrace_len = sp.macro_backtrace().len(); + for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() { + // Only show macro locations that are local + // and display them like a span_note + if trace.def_site_span.is_dummy() { + continue; + } + if always_backtrace { + new_labels.push((trace.def_site_span, + format!("in this expansion of `{}`{}", + trace.macro_decl_name, + if backtrace_len > 2 { + // if backtrace_len == 1 it'll be pointed + // at by "in this macro invocation" + format!(" (#{})", i + 1) + } else { + String::new() + }))); + } + // Check to make sure we're not in any <*macros> + if !sm.span_to_filename(trace.def_site_span).is_macros() && + !trace.macro_decl_name.starts_with("desugaring of ") && + !trace.macro_decl_name.starts_with("#[") || + always_backtrace { + new_labels.push((trace.call_site, + format!("in this macro invocation{}", + if backtrace_len > 2 && always_backtrace { + // only specify order when the macro + // backtrace is multiple levels deep + format!(" (#{})", i + 1) + } else { + String::new() + }))); + if !always_backtrace { + break; + } + } + } + } + for (label_span, label_text) in new_labels { + span.push_span_label(label_span, label_text); + } + for sp_label in span.span_labels() { + if sp_label.span.is_dummy() { + continue; + } + if sm.span_to_filename(sp_label.span.clone()).is_macros() && + !always_backtrace + { + let v = sp_label.span.macro_backtrace(); + if let Some(use_site) = v.last() { + before_after.push((sp_label.span.clone(), use_site.call_site.clone())); + } + } + } + // After we have them, make sure we replace these 'bad' def sites with their use sites + for (before, after) in before_after { + span.replace(before, after); + spans_updated = true; + } + } + + spans_updated + } } impl Emitter for EmitterWriter { @@ -254,7 +381,8 @@ impl Emitter for EmitterWriter { let mut children = db.children.clone(); let (mut primary_span, suggestions) = self.primary_span_formatted(&db); - self.fix_multispans_in_std_macros(&mut primary_span, + self.fix_multispans_in_std_macros(&self.sm, + &mut primary_span, &mut children, &db.level, db.handler.flags.external_macro_backtrace); @@ -919,127 +1047,6 @@ impl EmitterWriter { max } - // This "fixes" MultiSpans that contain Spans that are pointing to locations inside of - // <*macros>. Since these locations are often difficult to read, we move these Spans from - // <*macros> to their corresponding use site. - fn fix_multispan_in_std_macros(&mut self, - span: &mut MultiSpan, - always_backtrace: bool) -> bool { - let mut spans_updated = false; - - if let Some(ref sm) = self.sm { - let mut before_after: Vec<(Span, Span)> = vec![]; - let mut new_labels: Vec<(Span, String)> = vec![]; - - // First, find all the spans in <*macros> and point instead at their use site - for sp in span.primary_spans() { - if sp.is_dummy() { - continue; - } - let call_sp = sm.call_span_if_macro(*sp); - if call_sp != *sp && !always_backtrace { - before_after.push((*sp, call_sp)); - } - let backtrace_len = sp.macro_backtrace().len(); - for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() { - // Only show macro locations that are local - // and display them like a span_note - if trace.def_site_span.is_dummy() { - continue; - } - if always_backtrace { - new_labels.push((trace.def_site_span, - format!("in this expansion of `{}`{}", - trace.macro_decl_name, - if backtrace_len > 2 { - // if backtrace_len == 1 it'll be pointed - // at by "in this macro invocation" - format!(" (#{})", i + 1) - } else { - String::new() - }))); - } - // Check to make sure we're not in any <*macros> - if !sm.span_to_filename(trace.def_site_span).is_macros() && - !trace.macro_decl_name.starts_with("desugaring of ") && - !trace.macro_decl_name.starts_with("#[") || - always_backtrace { - new_labels.push((trace.call_site, - format!("in this macro invocation{}", - if backtrace_len > 2 && always_backtrace { - // only specify order when the macro - // backtrace is multiple levels deep - format!(" (#{})", i + 1) - } else { - String::new() - }))); - if !always_backtrace { - break; - } - } - } - } - for (label_span, label_text) in new_labels { - span.push_span_label(label_span, label_text); - } - for sp_label in span.span_labels() { - if sp_label.span.is_dummy() { - continue; - } - if sm.span_to_filename(sp_label.span.clone()).is_macros() && - !always_backtrace - { - let v = sp_label.span.macro_backtrace(); - if let Some(use_site) = v.last() { - before_after.push((sp_label.span.clone(), use_site.call_site.clone())); - } - } - } - // After we have them, make sure we replace these 'bad' def sites with their use sites - for (before, after) in before_after { - span.replace(before, after); - spans_updated = true; - } - } - - spans_updated - } - - // This does a small "fix" for multispans by looking to see if it can find any that - // point directly at <*macros>. Since these are often difficult to read, this - // will change the span to point at the use site. - fn fix_multispans_in_std_macros(&mut self, - span: &mut MultiSpan, - children: &mut Vec, - level: &Level, - backtrace: bool) { - let mut spans_updated = self.fix_multispan_in_std_macros(span, backtrace); - for child in children.iter_mut() { - spans_updated |= self.fix_multispan_in_std_macros(&mut child.span, backtrace); - } - let msg = if level == &Error { - "this error originates in a macro outside of the current crate \ - (in Nightly builds, run with -Z external-macro-backtrace \ - for more info)".to_string() - } else { - "this warning originates in a macro outside of the current crate \ - (in Nightly builds, run with -Z external-macro-backtrace \ - for more info)".to_string() - }; - - if spans_updated { - children.push(SubDiagnostic { - level: Level::Note, - message: vec![ - (msg, - Style::NoStyle), - ], - span: MultiSpan::new(), - render_span: None, - }); - } - } - /// Adds a left margin to every line but the first, given a padding length and the label being /// displayed, keeping the provided highlighting. fn msg_to_buffer(&self, From 060fe88610ff8bad0e687a819bcb705fe988412a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 5 Sep 2019 23:03:50 +0300 Subject: [PATCH 523/618] fill metadata in rustc_lexer's Cargo.toml We publish this to crates.io, so having non-empty meta is useful --- src/librustc_lexer/Cargo.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc_lexer/Cargo.toml b/src/librustc_lexer/Cargo.toml index 675d3065c5b28..950771f0a6927 100644 --- a/src/librustc_lexer/Cargo.toml +++ b/src/librustc_lexer/Cargo.toml @@ -2,8 +2,14 @@ authors = ["The Rust Project Developers"] name = "rustc_lexer" version = "0.1.0" +license = "MIT OR Apache-2.0" edition = "2018" +repository = "https://github.com/rust-lang/rust/" +description = """ +Rust lexer used by rustc. No stability guarantees are provided. +""" + # Note: do not remove this blank `[lib]` section. # This will be used when publishing this crate as `rustc-ap-rustc_lexer`. [lib] From afcf9b262d450edd1a7d54754e62f62d50052d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 5 Sep 2019 13:15:42 -0700 Subject: [PATCH 524/618] Bail out when encountering likely missing turbofish in parser When encountering a likely intended turbofish without `::`, bubble up the diagnostic instead of emitting it to allow the parser to recover more gracefully and avoid uneccessary type errors that are likely to be wrong. --- src/libsyntax/parse/diagnostics.rs | 5 +- src/libsyntax/parse/parser/expr.rs | 2 +- src/test/ui/did_you_mean/issue-40396.rs | 11 --- src/test/ui/did_you_mean/issue-40396.stderr | 80 +------------------ .../require-parens-for-chained-comparison.rs | 3 +- ...quire-parens-for-chained-comparison.stderr | 15 +--- .../ui/parser/trait-object-lifetime-parens.rs | 1 - .../trait-object-lifetime-parens.stderr | 11 +-- 8 files changed, 12 insertions(+), 116 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index d4e661d1a38b7..d050d4f4ce705 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -544,7 +544,7 @@ impl<'a> Parser<'a> { /// Produce an error if comparison operators are chained (RFC #558). /// We only need to check lhs, not rhs, because all comparison ops /// have same precedence and are left-associative - crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) { + crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) -> PResult<'a, ()> { debug_assert!(outer_op.is_comparison(), "check_no_chained_comparison: {:?} is not comparison", outer_op); @@ -563,11 +563,14 @@ impl<'a> Parser<'a> { err.help( "use `::<...>` instead of `<...>` if you meant to specify type arguments"); err.help("or use `(...)` if you meant to specify fn arguments"); + // These cases cause too many knock-down errors, bail out (#61329). + return Err(err); } err.emit(); } _ => {} } + Ok(()) } crate fn maybe_report_ambiguous_plus( diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 5b9f0f1df6718..aeef216141299 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -231,7 +231,7 @@ impl<'a> Parser<'a> { self.bump(); if op.is_comparison() { - self.check_no_chained_comparison(&lhs, &op); + self.check_no_chained_comparison(&lhs, &op)?; } // Special cases: if op == AssocOp::As { diff --git a/src/test/ui/did_you_mean/issue-40396.rs b/src/test/ui/did_you_mean/issue-40396.rs index 63eec50c2d29f..6902779f33d23 100644 --- a/src/test/ui/did_you_mean/issue-40396.rs +++ b/src/test/ui/did_you_mean/issue-40396.rs @@ -1,27 +1,16 @@ fn foo() { (0..13).collect>(); //~^ ERROR chained comparison - //~| ERROR expected value, found struct `Vec` - //~| ERROR expected value, found builtin type `i32` - //~| ERROR attempted to take value of method `collect` } fn bar() { Vec::new(); //~^ ERROR chained comparison - //~| ERROR expected value, found struct `Vec` - //~| ERROR expected value, found builtin type `i32` - //~| ERROR cannot find function `new` in the crate root } fn qux() { (0..13).collect(); //~^ ERROR chained comparison - //~| ERROR chained comparison - //~| ERROR expected value, found struct `Vec` - //~| ERROR expected value, found builtin type `i32` - //~| ERROR attempted to take value of method `collect` - //~| ERROR mismatched types } fn main() {} diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index fe517ee34949d..7a08fda27e355 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -8,7 +8,7 @@ LL | (0..13).collect>(); = help: or use `(...)` if you meant to specify fn arguments error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:10:8 + --> $DIR/issue-40396.rs:7:8 | LL | Vec::new(); | ^^^^^^^ @@ -17,7 +17,7 @@ LL | Vec::new(); = help: or use `(...)` if you meant to specify fn arguments error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:18:20 + --> $DIR/issue-40396.rs:12:20 | LL | (0..13).collect(); | ^^^^^^^^ @@ -25,79 +25,5 @@ LL | (0..13).collect(); = help: use `::<...>` instead of `<...>` if you meant to specify type arguments = help: or use `(...)` if you meant to specify fn arguments -error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:18:24 - | -LL | (0..13).collect(); - | ^^^^^^ - | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments - -error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-40396.rs:2:21 - | -LL | (0..13).collect>(); - | ^^^ did you mean `Vec { /* fields */ }`? - -error[E0423]: expected value, found builtin type `i32` - --> $DIR/issue-40396.rs:2:25 - | -LL | (0..13).collect>(); - | ^^^ not a value - -error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-40396.rs:10:5 - | -LL | Vec::new(); - | ^^^ did you mean `Vec { /* fields */ }`? - -error[E0423]: expected value, found builtin type `i32` - --> $DIR/issue-40396.rs:10:9 - | -LL | Vec::new(); - | ^^^ not a value - -error[E0425]: cannot find function `new` in the crate root - --> $DIR/issue-40396.rs:10:15 - | -LL | Vec::new(); - | ^^^ not found in the crate root - -error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-40396.rs:18:21 - | -LL | (0..13).collect(); - | ^^^ did you mean `Vec { /* fields */ }`? - -error[E0423]: expected value, found builtin type `i32` - --> $DIR/issue-40396.rs:18:25 - | -LL | (0..13).collect(); - | ^^^ not a value - -error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>` - --> $DIR/issue-40396.rs:2:13 - | -LL | (0..13).collect>(); - | ^^^^^^^ help: use parentheses to call the method: `collect()` - -error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>` - --> $DIR/issue-40396.rs:18:13 - | -LL | (0..13).collect(); - | ^^^^^^^ help: use parentheses to call the method: `collect()` - -error[E0308]: mismatched types - --> $DIR/issue-40396.rs:18:29 - | -LL | (0..13).collect(); - | ^^ expected bool, found () - | - = note: expected type `bool` - found type `()` - -error: aborting due to 14 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0308, E0423, E0425, E0615. -For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index 525be5d20e27f..3dcc0c8f3d496 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -11,8 +11,7 @@ fn main() { //~| ERROR: mismatched types f(); - //~^ ERROR: chained comparison operators require parentheses - //~| ERROR: binary operation `<` cannot be applied to type `fn() {f::<_>}` + //~^ ERROR chained comparison operators require parentheses //~| HELP: use `::<...>` instead of `<...>` //~| HELP: or use `(...)` } diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index 76e548de045aa..e927f4c32484e 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -37,17 +37,6 @@ LL | false == 0 < 2; = note: expected type `bool` found type `{integer}` -error[E0369]: binary operation `<` cannot be applied to type `fn() {f::<_>}` - --> $DIR/require-parens-for-chained-comparison.rs:13:6 - | -LL | f(); - | -^- X - | | - | fn() {f::<_>} - | - = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() {f::<_>}` - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0308, E0369. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/trait-object-lifetime-parens.rs b/src/test/ui/parser/trait-object-lifetime-parens.rs index 5bbda4296ca7e..c8b0eb684f33d 100644 --- a/src/test/ui/parser/trait-object-lifetime-parens.rs +++ b/src/test/ui/parser/trait-object-lifetime-parens.rs @@ -9,7 +9,6 @@ fn check<'a>() { let _: Box<('a) + Trait>; //~^ ERROR expected type, found `'a` //~| ERROR expected `:`, found `)` - //~| ERROR chained comparison operators require parentheses } fn main() {} diff --git a/src/test/ui/parser/trait-object-lifetime-parens.stderr b/src/test/ui/parser/trait-object-lifetime-parens.stderr index 7ffc26e9edead..319a308c0137c 100644 --- a/src/test/ui/parser/trait-object-lifetime-parens.stderr +++ b/src/test/ui/parser/trait-object-lifetime-parens.stderr @@ -16,15 +16,6 @@ error: expected `:`, found `)` LL | let _: Box<('a) + Trait>; | ^ expected `:` -error: chained comparison operators require parentheses - --> $DIR/trait-object-lifetime-parens.rs:9:15 - | -LL | let _: Box<('a) + Trait>; - | ^^^^^^^^^^^^^^^ - | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments - error: expected type, found `'a` --> $DIR/trait-object-lifetime-parens.rs:9:17 | @@ -33,5 +24,5 @@ LL | let _: Box<('a) + Trait>; | | | while parsing the type for `_` -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors From bdc6cfc96a181653d6747762027902097e43bd3f Mon Sep 17 00:00:00 2001 From: Baoshan Pang Date: Thu, 5 Sep 2019 11:26:29 -0700 Subject: [PATCH 525/618] simplify is_vxworks_pure_dynamic --- src/tools/compiletest/src/runtest.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 84123cf326535..26fdfe9d1ef1b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1733,14 +1733,7 @@ impl<'test> TestCx<'test> { } fn is_vxworks_pure_dynamic(&self) -> bool { - if self.config.target.contains("vxworks") { - match env::var("RUST_VXWORKS_TEST_DYLINK") { - Ok(s) => s == "1", - _ => false - } - } else { - false - } + self.config.target.contains("vxworks") && !self.is_vxworks_pure_static() } fn compose_and_run_compiler(&self, mut rustc: Command, input: Option) -> ProcRes { From 3f3fc52bfa255e68d84ca40a497137f5c6bae4a8 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 5 Sep 2019 15:05:58 +0100 Subject: [PATCH 526/618] Simplify std lib injection --- src/librustc_interface/passes.rs | 2 +- src/librustc_resolve/diagnostics.rs | 8 ++ src/librustc_resolve/macros.rs | 5 +- src/librustc_resolve/resolve_imports.rs | 7 +- src/libsyntax_ext/proc_macro_harness.rs | 32 +---- src/libsyntax_ext/standard_library_imports.rs | 124 +++++------------- 6 files changed, 52 insertions(+), 126 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 649cc8a2fb515..48c3ddf39a22b 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -366,8 +366,8 @@ fn configure_and_expand_inner<'a>( let (krate, name) = syntax_ext::standard_library_imports::inject( krate, &mut resolver, + &sess.parse_sess, alt_std_name, - sess.edition(), ); if let Some(name) = name { sess.parse_sess.injected_crate_name.set(name); diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index b79e0c2bd3b26..c479912b4ef81 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -604,6 +604,14 @@ impl<'a> Resolver<'a> { if lookup_ident.span.rust_2018() { let extern_prelude_names = self.extern_prelude.clone(); for (ident, _) in extern_prelude_names.into_iter() { + if ident.span.from_expansion() { + // Idents are adjusted to the root context before being + // resolved in the extern prelude, so reporting this to the + // user is no help. This skips the injected + // `extern crate std` in the 2018 edition, which would + // otherwise cause duplicate suggestions. + continue; + } if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name, ident.span) { let crate_root = self.get_module(DefId { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 02022c98c3502..cf99663beaf48 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -128,9 +128,8 @@ impl<'a> base::Resolver for Resolver<'a> { } } - // Create a Span with modern hygiene with a definition site of the provided - // module, or a fake empty `#[no_implicit_prelude]` module if no module is - // provided. + // Create a new Expansion with a definition site of the provided module, or + // a fake empty `#[no_implicit_prelude]` module if no module is provided. fn expansion_for_ast_pass( &mut self, call_site: Span, diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 4e33ea018a074..ca189e71800b3 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1307,8 +1307,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> { None => continue, }; - // Filter away ambiguous imports. - let is_good_import = binding.is_import() && !binding.is_ambiguity(); + // Filter away ambiguous imports and anything that has def-site + // hygiene. + // FIXME: Implement actual cross-crate hygiene. + let is_good_import = binding.is_import() && !binding.is_ambiguity() + && !ident.span.modern().from_expansion(); if is_good_import || binding.is_macro_def() { let res = binding.res(); if res != Res::Err { diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs index 8a4b78a3efa31..31d32d23a645e 100644 --- a/src/libsyntax_ext/proc_macro_harness.rs +++ b/src/libsyntax_ext/proc_macro_harness.rs @@ -392,41 +392,19 @@ fn mk_decls( i }); - let block = P(ast::Expr { - id: ast::DUMMY_NODE_ID, - attrs: syntax::ThinVec::new(), - node: ast::ExprKind::Block(P(ast::Block { - id: ast::DUMMY_NODE_ID, - rules: ast::BlockCheckMode::Default, - stmts: vec![ - ast::Stmt { - id: ast::DUMMY_NODE_ID, - node: ast::StmtKind::Item(krate), - span, - }, - ast::Stmt { - id: ast::DUMMY_NODE_ID, - node: ast::StmtKind::Item(decls_static), - span, - } - ], - span, - }), None), + let block = cx.expr_block(cx.block( span, - }); + vec![cx.stmt_item(span, krate), cx.stmt_item(span, decls_static)], + )); let anon_constant = cx.item_const( span, ast::Ident::new(kw::Underscore, span), - P(ast::Ty { - id: ast::DUMMY_NODE_ID, - node: ast::TyKind::Tup(Vec::new()), - span, - }), + cx.ty(span, ast::TyKind::Tup(Vec::new())), block, ); - // Integrate the new module into existing module structures. + // Integrate the new item into existing module structures. let items = AstFragment::Items(smallvec![anon_constant]); cx.monotonic_expander().fully_expand_fragment(items).make_items().pop().unwrap() } diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs index e5dded9ea5319..c577b1e33cfeb 100644 --- a/src/libsyntax_ext/standard_library_imports.rs +++ b/src/libsyntax_ext/standard_library_imports.rs @@ -1,19 +1,20 @@ use syntax::{ast, attr}; use syntax::edition::Edition; +use syntax::ext::expand::ExpansionConfig; use syntax::ext::hygiene::AstPass; -use syntax::ext::base::Resolver; +use syntax::ext::base::{ExtCtxt, Resolver}; +use syntax::parse::ParseSess; use syntax::ptr::P; -use syntax::source_map::respan; use syntax::symbol::{Ident, Symbol, kw, sym}; use syntax_pos::DUMMY_SP; pub fn inject( mut krate: ast::Crate, resolver: &mut dyn Resolver, + sess: &ParseSess, alt_std_name: Option, - edition: Edition, ) -> (ast::Crate, Option) { - let rust_2018 = edition >= Edition::Edition2018; + let rust_2018 = sess.edition >= Edition::Edition2018; // the first name in this list is the crate name of the crate with the prelude let names: &[Symbol] = if attr::contains_name(&krate.attrs, sym::no_core) { @@ -37,112 +38,49 @@ pub fn inject( let span = DUMMY_SP.with_def_site_ctxt(expn_id); let call_site = DUMMY_SP.with_call_site_ctxt(expn_id); + let ecfg = ExpansionConfig::default("std_lib_injection".to_string()); + let cx = ExtCtxt::new(sess, ecfg, resolver); + + // .rev() to preserve ordering above in combination with insert(0, ...) - for &orig_name_sym in names.iter().rev() { - let (rename, orig_name) = if rust_2018 { - (Ident::new(kw::Underscore, span), Some(orig_name_sym)) + for &name in names.iter().rev() { + let ident = if rust_2018 { + Ident::new(name, span) } else { - (Ident::new(orig_name_sym, call_site), None) + Ident::new(name, call_site) }; - krate.module.items.insert(0, P(ast::Item { - attrs: vec![attr::mk_attr_outer( - attr::mk_word_item(ast::Ident::new(sym::macro_use, span)) - )], - vis: respan(span, ast::VisibilityKind::Inherited), - node: ast::ItemKind::ExternCrate(alt_std_name.or(orig_name)), - ident: rename, - id: ast::DUMMY_NODE_ID, + krate.module.items.insert(0, cx.item( span, - tokens: None, - })); + ident, + vec![cx.attribute(cx.meta_word(span, sym::macro_use))], + ast::ItemKind::ExternCrate(alt_std_name), + )); } - // the crates have been injected, the assumption is that the first one is the one with - // the prelude. + // The crates have been injected, the assumption is that the first one is + // the one with the prelude. let name = names[0]; - let segments = if rust_2018 { + let import_path = if rust_2018 { [name, sym::prelude, sym::v1].iter() - .map(|symbol| ast::PathSegment::from_ident(ast::Ident::new(*symbol, span))) - .collect() + .map(|symbol| ast::Ident::new(*symbol, span)).collect() } else { [kw::PathRoot, name, sym::prelude, sym::v1].iter() - .map(|symbol| ast::PathSegment::from_ident(ast::Ident::new(*symbol, call_site))) - .collect() + .map(|symbol| ast::Ident::new(*symbol, span)).collect() }; - let use_item = P(ast::Item { - attrs: vec![attr::mk_attr_outer( - attr::mk_word_item(ast::Ident::new(sym::prelude_import, span)))], - vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), - node: ast::ItemKind::Use(P(ast::UseTree { - prefix: ast::Path { segments, span }, + let use_item = cx.item( + span, + ast::Ident::invalid(), + vec![cx.attribute(cx.meta_word(span, sym::prelude_import))], + ast::ItemKind::Use(P(ast::UseTree { + prefix: cx.path(span, import_path), kind: ast::UseTreeKind::Glob, span, })), - id: ast::DUMMY_NODE_ID, - ident: ast::Ident::invalid(), - span, - tokens: None, - }); - - let prelude_import_item = if rust_2018 { - let hygienic_extern_crate = P(ast::Item { - attrs: vec![], - vis: respan(span, ast::VisibilityKind::Inherited), - node: ast::ItemKind::ExternCrate(alt_std_name), - ident: ast::Ident::new(name, span), - id: ast::DUMMY_NODE_ID, - span, - tokens: None, - }); - - // Use an anonymous const to hide `extern crate std as hygienic_std` - // FIXME: Once inter-crate hygiene exists, this can just be `use_item`. - P(ast::Item { - attrs: Vec::new(), - vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), - node: ast::ItemKind::Const( - P(ast::Ty { - id: ast::DUMMY_NODE_ID, - node: ast::TyKind::Tup(Vec::new()), - span, - }), - P(ast::Expr { - id: ast::DUMMY_NODE_ID, - attrs: syntax::ThinVec::new(), - node: ast::ExprKind::Block(P(ast::Block { - id: ast::DUMMY_NODE_ID, - rules: ast::BlockCheckMode::Default, - stmts: vec![ - ast::Stmt { - id: ast::DUMMY_NODE_ID, - node: ast::StmtKind::Item(use_item), - span, - }, - ast::Stmt { - id: ast::DUMMY_NODE_ID, - node: ast::StmtKind::Item(hygienic_extern_crate), - span, - } - ], - span, - }), None), - span, - }) - ), - id: ast::DUMMY_NODE_ID, - ident: ast::Ident::new(kw::Underscore, span), - span, - tokens: None, - }) - } else { - // Have `extern crate std` at the root, so don't need to create a named - // extern crate item. - use_item - }; + ); - krate.module.items.insert(0, prelude_import_item); + krate.module.items.insert(0, use_item); (krate, Some(name)) } From bad8147d01df374e3daa37fe36446781df2eac2d Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 5 Sep 2019 16:52:44 -0500 Subject: [PATCH 527/618] fix reviewer comments --- src/tools/rustbook/src/main.rs | 66 +++++++++++++++++----------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index b2111442310ef..d5dc9a79b5acb 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -8,6 +8,7 @@ use clap::{App, AppSettings, ArgMatches, SubCommand}; use mdbook::errors::Result as Result3; use mdbook::MDBook; +#[cfg(feature = "linkcheck")] use failure::Error; #[cfg(feature = "linkcheck")] use mdbook::renderer::RenderContext; @@ -52,36 +53,41 @@ fn main() { } } ("linkcheck", Some(sub_matches)) => { - if let Err(err) = linkcheck(sub_matches) { - eprintln!("Error: {}", err); - - // HACK: ignore timeouts - let actually_broken = { - #[cfg(feature = "linkcheck")] - { - err.downcast::() - .map(|broken_links| { - broken_links - .links() - .iter() - .inspect(|cause| eprintln!("\tCaused By: {}", cause)) - .any(|cause| !format!("{}", cause).contains("timed out")) - }) - .unwrap_or(false) - } - - #[cfg(not(feature = "linkcheck"))] - { - false + #[cfg(feature = "linkcheck")] + { + if let Err(err) = linkcheck(sub_matches) { + eprintln!("Error: {}", err); + + // HACK: ignore timeouts + let actually_broken = err + .downcast::() + .map(|broken_links| { + broken_links + .links() + .iter() + .inspect(|cause| eprintln!("\tCaused By: {}", cause)) + .fold(false, |already_broken, cause| { + already_broken || !format!("{}", cause).contains("timed out") + }) + }) + .unwrap_or(false); + + if actually_broken { + std::process::exit(101); + } else { + std::process::exit(0); } - }; - - if actually_broken { - std::process::exit(101); - } else { - std::process::exit(0); } } + + #[cfg(not(feature = "linkcheck"))] + { + // This avoids the `unused_binding` lint. + println!( + "mdbook-linkcheck is disabled, but arguments were passed: {:?}", + sub_matches + ); + } } (_, _) => unreachable!(), }; @@ -97,12 +103,6 @@ pub fn linkcheck(args: &ArgMatches<'_>) -> Result<(), Error> { mdbook_linkcheck::check_links(&render_ctx) } -#[cfg(not(feature = "linkcheck"))] -pub fn linkcheck(_args: &ArgMatches<'_>) -> Result<(), Error> { - println!("mdbook-linkcheck is disabled."); - Ok(()) -} - // Build command implementation pub fn build(args: &ArgMatches<'_>) -> Result3<()> { let book_dir = get_book_dir(args); From dc613c6d055c1b45f7e11e6ee03e4a3095d5b8a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 5 Sep 2019 15:29:31 -0700 Subject: [PATCH 528/618] Fix test --- src/test/ui-fulldeps/pprust-expr-roundtrip.rs | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs index 09f58521e5d5c..89c17cf4b3aa3 100644 --- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs @@ -32,13 +32,15 @@ use syntax::print::pprust; use syntax::ptr::P; -fn parse_expr(ps: &ParseSess, src: &str) -> P { +fn parse_expr(ps: &ParseSess, src: &str) -> Option> { let src_as_string = src.to_string(); - let mut p = parse::new_parser_from_source_str(ps, - FileName::Custom(src_as_string.clone()), - src_as_string); - p.parse_expr().unwrap() + let mut p = parse::new_parser_from_source_str( + ps, + FileName::Custom(src_as_string.clone()), + src_as_string, + ); + p.parse_expr().map_err(|mut e| e.cancel()).ok() } @@ -209,22 +211,23 @@ fn run() { let printed = pprust::expr_to_string(&e); println!("printed: {}", printed); - let mut parsed = parse_expr(&ps, &printed); - - // We want to know if `parsed` is structurally identical to `e`, ignoring trivial - // differences like placement of `Paren`s or the exact ranges of node spans. - // Unfortunately, there is no easy way to make this comparison. Instead, we add `Paren`s - // everywhere we can, then pretty-print. This should give an unambiguous representation of - // each `Expr`, and it bypasses nearly all of the parenthesization logic, so we aren't - // relying on the correctness of the very thing we're testing. - RemoveParens.visit_expr(&mut e); - AddParens.visit_expr(&mut e); - let text1 = pprust::expr_to_string(&e); - RemoveParens.visit_expr(&mut parsed); - AddParens.visit_expr(&mut parsed); - let text2 = pprust::expr_to_string(&parsed); - assert!(text1 == text2, - "exprs are not equal:\n e = {:?}\n parsed = {:?}", - text1, text2); + // Ignore expressions with chained comparisons that fail to parse + if let Some(mut parsed) = parse_expr(&ps, &printed) { + // We want to know if `parsed` is structurally identical to `e`, ignoring trivial + // differences like placement of `Paren`s or the exact ranges of node spans. + // Unfortunately, there is no easy way to make this comparison. Instead, we add `Paren`s + // everywhere we can, then pretty-print. This should give an unambiguous representation + // of each `Expr`, and it bypasses nearly all of the parenthesization logic, so we + // aren't relying on the correctness of the very thing we're testing. + RemoveParens.visit_expr(&mut e); + AddParens.visit_expr(&mut e); + let text1 = pprust::expr_to_string(&e); + RemoveParens.visit_expr(&mut parsed); + AddParens.visit_expr(&mut parsed); + let text2 = pprust::expr_to_string(&parsed); + assert!(text1 == text2, + "exprs are not equal:\n e = {:?}\n parsed = {:?}", + text1, text2); + } }); } From 5153db136e8419beb217340500a97db553ddabbe Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 5 Sep 2019 18:40:54 -0400 Subject: [PATCH 529/618] Explicitly create test tempdir --- src/bootstrap/test.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 97b28ed9e96c8..00d87f3841cff 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1327,7 +1327,10 @@ impl Step for Compiletest { cmd.env("RUSTC_PROFILER_SUPPORT", "1"); } - cmd.env("RUST_TEST_TMPDIR", builder.out.join("tmp")); + let tmp = builder.out.join("tmp"); + std::fs::create_dir_all(&tmp).unwrap(); + cmd.env("RUST_TEST_TMPDIR", tmp); + cmd.arg("--adb-path").arg("adb"); cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR); From bb1e42599d0062b9a43e83b5486d61eb1fcf0771 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Thu, 5 Sep 2019 16:44:22 -0700 Subject: [PATCH 530/618] Add Fuchsia to actually_monotonic Fuchsia provides a fully monotonic clock. --- src/libstd/sys/unix/time.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index 02f377d55c919..fd6796ad22c12 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -311,6 +311,7 @@ mod inner { pub fn actually_monotonic() -> bool { (cfg!(target_os = "linux") && cfg!(target_arch = "x86_64")) || (cfg!(target_os = "linux") && cfg!(target_arch = "x86")) || + cfg!(target_os = "fuchsia") || false // last clause, used so `||` is always trailing above } From 022d9c8eb56144c00980c88d4b68a5a1e487484a Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Sun, 1 Sep 2019 18:09:59 +0100 Subject: [PATCH 531/618] Fixed grammar/style in error messages and reblessed tests. --- src/librustc/mir/interpret/error.rs | 12 ++--- src/librustc/session/config.rs | 20 ++++---- src/librustc/traits/object_safety.rs | 7 +-- .../borrow_check/conflict_errors.rs | 2 +- src/librustc_mir/const_eval.rs | 4 +- src/librustc_mir/error_codes.rs | 2 +- src/librustc_mir/util/borrowck_errors.rs | 2 +- src/libsyntax/parse/parser/expr.rs | 2 +- src/libsyntax/parse/parser/stmt.rs | 2 +- src/test/ui/asm/asm-out-read-uninit.rs | 2 +- src/test/ui/asm/asm-out-read-uninit.stderr | 4 +- .../no-non-guaranteed-initialization.rs | 2 +- .../no-non-guaranteed-initialization.stderr | 4 +- .../partial-initialization-across-await.rs | 6 +-- ...partial-initialization-across-await.stderr | 12 ++--- .../ui/borrowck/assign_mutable_fields.stderr | 8 ++-- src/test/ui/borrowck/borrowck-and-init.rs | 2 +- src/test/ui/borrowck/borrowck-and-init.stderr | 4 +- src/test/ui/borrowck/borrowck-asm.rs | 2 +- src/test/ui/borrowck/borrowck-asm.stderr | 4 +- src/test/ui/borrowck/borrowck-block-unint.rs | 2 +- .../ui/borrowck/borrowck-block-unint.stderr | 4 +- .../ui/borrowck/borrowck-break-uninit-2.rs | 2 +- .../borrowck/borrowck-break-uninit-2.stderr | 4 +- src/test/ui/borrowck/borrowck-break-uninit.rs | 2 +- .../ui/borrowck/borrowck-break-uninit.stderr | 4 +- .../ui/borrowck/borrowck-field-sensitivity.rs | 6 +-- .../borrowck-field-sensitivity.stderr | 12 ++--- src/test/ui/borrowck/borrowck-if-no-else.rs | 2 +- .../ui/borrowck/borrowck-if-no-else.stderr | 4 +- src/test/ui/borrowck/borrowck-if-with-else.rs | 2 +- .../ui/borrowck/borrowck-if-with-else.stderr | 4 +- .../borrowck-init-in-called-fn-expr.rs | 2 +- .../borrowck-init-in-called-fn-expr.stderr | 4 +- .../ui/borrowck/borrowck-init-in-fn-expr.rs | 2 +- .../borrowck/borrowck-init-in-fn-expr.stderr | 4 +- src/test/ui/borrowck/borrowck-init-in-fru.rs | 2 +- .../ui/borrowck/borrowck-init-in-fru.stderr | 4 +- .../ui/borrowck/borrowck-init-op-equal.rs | 2 +- .../ui/borrowck/borrowck-init-op-equal.stderr | 4 +- .../ui/borrowck/borrowck-init-plus-equal.rs | 2 +- .../borrowck/borrowck-init-plus-equal.stderr | 4 +- src/test/ui/borrowck/borrowck-or-init.rs | 2 +- src/test/ui/borrowck/borrowck-or-init.stderr | 4 +- .../ui/borrowck/borrowck-partial-reinit-4.rs | 2 +- .../borrowck/borrowck-partial-reinit-4.stderr | 4 +- src/test/ui/borrowck/borrowck-return.rs | 2 +- src/test/ui/borrowck/borrowck-return.stderr | 4 +- .../ui/borrowck/borrowck-storage-dead.stderr | 4 +- .../ui/borrowck/borrowck-uninit-after-item.rs | 2 +- .../borrowck-uninit-after-item.stderr | 4 +- .../borrowck-uninit-field-access.stderr | 4 +- .../borrowck/borrowck-uninit-in-assignop.rs | 20 ++++---- .../borrowck-uninit-in-assignop.stderr | 40 ++++++++-------- .../ui/borrowck/borrowck-uninit-ref-chain.rs | 8 ++-- .../borrowck/borrowck-uninit-ref-chain.stderr | 28 +++++------ src/test/ui/borrowck/borrowck-uninit.rs | 2 +- src/test/ui/borrowck/borrowck-uninit.stderr | 4 +- .../borrowck/borrowck-union-uninitialized.rs | 4 +- .../borrowck-union-uninitialized.stderr | 8 ++-- .../borrowck-use-in-index-lvalue.stderr | 8 ++-- ...wck-use-uninitialized-in-cast-trait.stderr | 4 +- .../borrowck-use-uninitialized-in-cast.stderr | 4 +- src/test/ui/borrowck/borrowck-while-break.rs | 2 +- .../ui/borrowck/borrowck-while-break.stderr | 4 +- src/test/ui/borrowck/borrowck-while-cond.rs | 2 +- .../ui/borrowck/borrowck-while-cond.stderr | 4 +- src/test/ui/borrowck/borrowck-while.rs | 2 +- src/test/ui/borrowck/borrowck-while.stderr | 4 +- .../disallow-possibly-uninitialized.rs | 8 ++-- .../disallow-possibly-uninitialized.stderr | 16 +++---- ...-54499-field-mutation-marks-mut-as-used.rs | 6 +-- ...99-field-mutation-marks-mut-as-used.stderr | 12 ++--- ...ssue-54499-field-mutation-of-never-init.rs | 6 +-- ...-54499-field-mutation-of-never-init.stderr | 12 ++--- .../borrowck/issue-62107-match-arm-scopes.rs | 2 +- .../issue-62107-match-arm-scopes.stderr | 4 +- .../reassignment_immutable_fields.stderr | 8 ++-- ...gnment_immutable_fields_overlapping.stderr | 4 +- ...reassignment_immutable_fields_twice.stderr | 4 +- src/test/ui/borrowck/two-phase-across-loop.rs | 2 +- src/test/ui/consts/const-err4.stderr | 2 +- ...nst-pointer-values-in-various-types.stderr | 18 +++---- .../ui/consts/const-eval/double_check2.stderr | 2 +- .../consts/const-eval/ref_to_int_match.stderr | 2 +- .../consts/const-eval/transmute-const.stderr | 2 +- src/test/ui/consts/const-eval/ub-enum.stderr | 18 +++---- .../ui/consts/const-eval/ub-nonnull.stderr | 12 ++--- src/test/ui/consts/const-eval/ub-ref.stderr | 10 ++-- .../ui/consts/const-eval/ub-uninhabit.stderr | 6 +-- .../ui/consts/const-eval/ub-upvars.stderr | 2 +- .../ui/consts/const-eval/ub-wide-ptr.stderr | 36 +++++++------- .../const-eval/union-const-eval-field.stderr | 2 +- .../ui/consts/const-eval/union-ice.stderr | 6 +-- src/test/ui/consts/const-eval/union-ub.stderr | 2 +- src/test/ui/consts/const_let_refutable.rs | 4 +- src/test/ui/consts/const_let_refutable.stderr | 8 ++-- src/test/ui/consts/std/alloc.stderr | 2 +- .../ui/consts/validate_never_arrays.stderr | 2 +- src/test/ui/empty/empty-never-array.rs | 2 +- src/test/ui/empty/empty-never-array.stderr | 4 +- .../partial-initialization-across-yield.rs | 6 +-- ...partial-initialization-across-yield.stderr | 12 ++--- src/test/ui/issues/issue-15381.rs | 2 +- src/test/ui/issues/issue-15381.stderr | 4 +- src/test/ui/issues/issue-24267-flow-exit.rs | 4 +- .../ui/issues/issue-24267-flow-exit.stderr | 8 ++-- src/test/ui/loops/loop-proper-liveness.rs | 2 +- src/test/ui/loops/loop-proper-liveness.stderr | 4 +- .../missing/missing-semicolon-warning.stderr | 4 +- src/test/ui/moves/move-into-dead-array-1.rs | 2 +- .../ui/moves/move-into-dead-array-1.stderr | 4 +- ...ue-21232-partial-init-and-erroneous-use.rs | 8 ++-- ...1232-partial-init-and-erroneous-use.stderr | 16 +++---- .../nll/issue-21232-partial-init-and-use.rs | 24 +++++----- .../issue-21232-partial-init-and-use.stderr | 48 +++++++++---------- src/test/ui/nll/match-cfg-fake-edges.rs | 2 +- src/test/ui/nll/match-cfg-fake-edges.stderr | 4 +- src/test/ui/nll/match-on-borrowed.stderr | 4 +- src/test/ui/parser/do-catch-suggests-try.rs | 2 +- .../ui/parser/do-catch-suggests-try.stderr | 2 +- .../recursive-types-are-not-uninhabited.rs | 2 +- ...recursive-types-are-not-uninhabited.stderr | 4 +- src/test/ui/try-block/try-block-opt-init.rs | 2 +- .../ui/try-block/try-block-opt-init.stderr | 4 +- 125 files changed, 381 insertions(+), 380 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index ef0e205184871..589a021241d94 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -430,13 +430,13 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { match self { PointerOutOfBounds { ptr, msg, allocation_size } => { write!(f, "{} failed: pointer must be in-bounds at offset {}, \ - but is outside bounds of allocation {} which has size {}", + but is outside bounds of allocation {} which has size {}", msg, ptr.offset.bytes(), ptr.alloc_id, allocation_size.bytes()) }, ValidationFailure(ref err) => { write!(f, "type validation failed: {}", err) } - NoMirFor(ref func) => write!(f, "no mir for `{}`", func), + NoMirFor(ref func) => write!(f, "no MIR for `{}`", func), FunctionAbiMismatch(caller_abi, callee_abi) => write!(f, "tried to call a function with ABI {:?} using caller ABI {:?}", callee_abi, caller_abi), @@ -451,9 +451,9 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { FunctionArgCountMismatch => write!(f, "tried to call a function with incorrect number of arguments"), ReallocatedWrongMemoryKind(ref old, ref new) => - write!(f, "tried to reallocate memory from {} to {}", old, new), + write!(f, "tried to reallocate memory from `{}` to `{}`", old, new), DeallocatedWrongMemoryKind(ref old, ref new) => - write!(f, "tried to deallocate {} memory but gave {} as the kind", old, new), + write!(f, "tried to deallocate `{}` memory but gave `{}` as the kind", old, new), InvalidChar(c) => write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c), AlignmentCheckFailed { required, has } => @@ -462,7 +462,7 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { TypeNotPrimitive(ty) => write!(f, "expected primitive type, got {}", ty), PathNotFound(ref path) => - write!(f, "Cannot find path {:?}", path), + write!(f, "cannot find path {:?}", path), IncorrectAllocationInformation(size, size2, align, align2) => write!(f, "incorrect alloc info: expected size {} and align {}, \ got size {} and align {}", @@ -525,7 +525,7 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { InvalidBoolOp(_) => write!(f, "invalid boolean operation"), UnterminatedCString(_) => - write!(f, "attempted to get length of a null terminated string, but no null \ + write!(f, "attempted to get length of a null-terminated string, but no null \ found before end of allocation"), ReadUndefBytes(_) => write!(f, "attempted to read undefined bytes"), diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 740d9db7edcf7..296c6ad19c1cf 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1998,7 +1998,7 @@ pub fn parse_error_format( Some(arg) => early_error( ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)), &format!( - "argument for --error-format must be `human`, `json` or \ + "argument for `--error-format` must be `human`, `json` or \ `short` (instead was `{}`)", arg ), @@ -2037,7 +2037,7 @@ pub fn build_session_options_and_crate_config( early_error( ErrorOutputType::default(), &format!( - "argument for --edition must be one of: \ + "argument for `--edition` must be one of: \ {}. (instead was `{}`)", EDITION_NAME_LIST, arg @@ -2051,7 +2051,7 @@ pub fn build_session_options_and_crate_config( early_error( ErrorOutputType::default(), &format!( - "Edition {} is unstable and only \ + "edition {} is unstable and only \ available for nightly builds of rustc.", edition, ) @@ -2075,14 +2075,14 @@ pub fn build_session_options_and_crate_config( if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format { early_error( ErrorOutputType::Json { pretty: false, json_rendered }, - "--error-format=pretty-json is unstable", + "`--error-format=pretty-json` is unstable", ); } if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) = error_format { early_error( ErrorOutputType::Json { pretty: false, json_rendered }, - "--error-format=human-annotate-rs is unstable", + "`--error-format=human-annotate-rs` is unstable", ); } } @@ -2132,8 +2132,8 @@ pub fn build_session_options_and_crate_config( early_warn( error_format, &format!( - "--emit={} with -o incompatible with \ - -C codegen-units=N for N > 1", + "`--emit={}` with `-o` incompatible with \ + `-C codegen-units=N` for N > 1", ot ), ); @@ -2153,21 +2153,21 @@ pub fn build_session_options_and_crate_config( if debugging_opts.threads == Some(0) { early_error( error_format, - "Value for threads must be a positive nonzero integer", + "value for threads must be a positive non-zero integer", ); } if debugging_opts.threads.unwrap_or(1) > 1 && debugging_opts.fuel.is_some() { early_error( error_format, - "Optimization fuel is incompatible with multiple threads", + "optimization fuel is incompatible with multiple threads", ); } if codegen_units == Some(0) { early_error( error_format, - "Value for codegen units must be a positive nonzero integer", + "value for codegen units must be a positive non-zero integer", ); } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index f7f459cd27f68..c759981b8e8c9 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -368,7 +368,7 @@ impl<'tcx> TyCtxt<'tcx> { match self.layout_of(param_env.and(ty)) { Ok(layout) => &layout.abi, Err(err) => bug!( - "Error: {}\n while computing layout for type {:?}", err, ty + "error: {}\n while computing layout for type {:?}", err, ty ) } }; @@ -384,7 +384,7 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.delay_span_bug( self.def_span(method.def_id), &format!( - "Receiver when Self = () should have a Scalar ABI, found {:?}", + "receiver when `Self = ()` should have a Scalar ABI; found {:?}", abi ), ); @@ -406,7 +406,8 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.delay_span_bug( self.def_span(method.def_id), &format!( - "Receiver when Self = {} should have a ScalarPair ABI, found {:?}", + "receiver when `Self = {}` should have a ScalarPair ABI; \ + found {:?}", trait_object_ty, abi ), ); diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 247783c420e25..bfc7050ebf71c 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -98,7 +98,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &self.describe_place_with_options(moved_place, IncludingDowncast(true)) .unwrap_or_else(|| "_".to_owned()), ); - err.span_label(span, format!("use of possibly uninitialized {}", item_msg)); + err.span_label(span, format!("use of possibly-uninitialized {}", item_msg)); use_spans.var_span_label( &mut err, diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 5aa487d901663..db679024dc5a2 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -533,8 +533,8 @@ pub fn error_to_const_error<'mir, 'tcx>( pub fn note_on_undefined_behavior_error() -> &'static str { "The rules on what exactly is undefined behavior aren't clear, \ - so this check might be overzealous. Please open an issue on the rust compiler \ - repository if you believe it should not be considered undefined behavior" + so this check might be overzealous. Please open an issue on the rustc \ + repository if you believe it should not be considered undefined behavior." } fn validate_and_turn_into_const<'tcx>( diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs index 86c263a447bb6..22432db819020 100644 --- a/src/librustc_mir/error_codes.rs +++ b/src/librustc_mir/error_codes.rs @@ -748,7 +748,7 @@ It is not allowed to use or capture an uninitialized variable. For example: ```compile_fail,E0381 fn main() { let x: i32; - let y = x; // error, use of possibly uninitialized variable + let y = x; // error, use of possibly-uninitialized variable } ``` diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 3359d1b3bbfe1..cf9ef55c17b34 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -50,7 +50,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, span, E0381, - "{} of possibly uninitialized variable: `{}`", + "{} of possibly-uninitialized variable: `{}`", verb, desc, ) diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index e502a08f4b253..98c3562b3219f 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -982,7 +982,7 @@ impl<'a> Parser<'a> { } if self.is_do_catch_block() { let mut db = self.fatal("found removed `do catch` syntax"); - db.help("Following RFC #2388, the new non-placeholder syntax is `try`"); + db.help("following RFC #2388, the new non-placeholder syntax is `try`"); return Err(db); } if self.is_try_block() { diff --git a/src/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs index 651ebf6342e71..748c1a168b0b2 100644 --- a/src/libsyntax/parse/parser/stmt.rs +++ b/src/libsyntax/parse/parser/stmt.rs @@ -469,7 +469,7 @@ impl<'a> Parser<'a> { self.diagnostic().struct_span_warn(self.token.span, { &format!("expected `;`, found {}", self.this_token_descr()) }).note({ - "This was erroneously allowed and will become a hard error in a future release" + "this was erroneously allowed and will become a hard error in a future release" }).emit(); } } diff --git a/src/test/ui/asm/asm-out-read-uninit.rs b/src/test/ui/asm/asm-out-read-uninit.rs index 003f1fc5bb62b..78458ff60d4aa 100644 --- a/src/test/ui/asm/asm-out-read-uninit.rs +++ b/src/test/ui/asm/asm-out-read-uninit.rs @@ -20,7 +20,7 @@ pub fn main() { let x: isize; unsafe { asm!("mov $1, $0" : "=r"(x) : "r"(x)); - //~^ ERROR use of possibly uninitialized variable: `x` + //~^ ERROR use of possibly-uninitialized variable: `x` } foo(x); } diff --git a/src/test/ui/asm/asm-out-read-uninit.stderr b/src/test/ui/asm/asm-out-read-uninit.stderr index 6d0445d4b7a61..71aeda2ad4d2e 100644 --- a/src/test/ui/asm/asm-out-read-uninit.stderr +++ b/src/test/ui/asm/asm-out-read-uninit.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/asm-out-read-uninit.rs:22:43 | LL | asm!("mov $1, $0" : "=r"(x) : "r"(x)); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.rs b/src/test/ui/async-await/no-non-guaranteed-initialization.rs index 0afbf4cee1d3c..6a34209d55289 100644 --- a/src/test/ui/async-await/no-non-guaranteed-initialization.rs +++ b/src/test/ui/async-await/no-non-guaranteed-initialization.rs @@ -8,7 +8,7 @@ async fn no_non_guaranteed_initialization(x: usize) -> usize { y = echo(10).await; } y - //~^ use of possibly uninitialized variable: `y` + //~^ use of possibly-uninitialized variable: `y` } async fn echo(x: usize) -> usize { x + 1 } diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr index 91d7994654f37..b9aa9924bb815 100644 --- a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr +++ b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `y` +error[E0381]: use of possibly-uninitialized variable: `y` --> $DIR/no-non-guaranteed-initialization.rs:10:5 | LL | y - | ^ use of possibly uninitialized `y` + | ^ use of possibly-uninitialized `y` error: aborting due to previous error diff --git a/src/test/ui/async-await/partial-initialization-across-await.rs b/src/test/ui/async-await/partial-initialization-across-await.rs index 1785fb7f29947..8a98a4b0f6bb4 100644 --- a/src/test/ui/async-await/partial-initialization-across-await.rs +++ b/src/test/ui/async-await/partial-initialization-across-await.rs @@ -11,7 +11,7 @@ async fn noop() {} async fn test_tuple() { let mut t: (i32, i32); t.0 = 42; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] noop().await; t.1 = 88; let _ = t; @@ -20,7 +20,7 @@ async fn test_tuple() { async fn test_tuple_struct() { let mut t: T; t.0 = 42; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] noop().await; t.1 = 88; let _ = t; @@ -29,7 +29,7 @@ async fn test_tuple_struct() { async fn test_struct() { let mut t: S; t.x = 42; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] noop().await; t.y = 88; let _ = t; diff --git a/src/test/ui/async-await/partial-initialization-across-await.stderr b/src/test/ui/async-await/partial-initialization-across-await.stderr index d9a2db985e54d..9a510c22c4b1e 100644 --- a/src/test/ui/async-await/partial-initialization-across-await.stderr +++ b/src/test/ui/async-await/partial-initialization-across-await.stderr @@ -1,20 +1,20 @@ -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/partial-initialization-across-await.rs:13:5 | LL | t.0 = 42; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/partial-initialization-across-await.rs:22:5 | LL | t.0 = 42; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/partial-initialization-across-await.rs:31:5 | LL | t.x = 42; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/assign_mutable_fields.stderr b/src/test/ui/borrowck/assign_mutable_fields.stderr index 35101df4e0a6e..40f1aae092dc6 100644 --- a/src/test/ui/borrowck/assign_mutable_fields.stderr +++ b/src/test/ui/borrowck/assign_mutable_fields.stderr @@ -1,14 +1,14 @@ -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/assign_mutable_fields.rs:9:5 | LL | x.0 = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/assign_mutable_fields.rs:17:5 | LL | x.0 = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-and-init.rs b/src/test/ui/borrowck/borrowck-and-init.rs index 4427e25186103..f11d44e2217ba 100644 --- a/src/test/ui/borrowck/borrowck-and-init.rs +++ b/src/test/ui/borrowck/borrowck-and-init.rs @@ -2,5 +2,5 @@ fn main() { let i: isize; println!("{}", false && { i = 5; true }); - println!("{}", i); //~ ERROR borrow of possibly uninitialized variable: `i` + println!("{}", i); //~ ERROR borrow of possibly-uninitialized variable: `i` } diff --git a/src/test/ui/borrowck/borrowck-and-init.stderr b/src/test/ui/borrowck/borrowck-and-init.stderr index 2db075194810e..c7e357d4604f7 100644 --- a/src/test/ui/borrowck/borrowck-and-init.stderr +++ b/src/test/ui/borrowck/borrowck-and-init.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `i` +error[E0381]: borrow of possibly-uninitialized variable: `i` --> $DIR/borrowck-and-init.rs:5:20 | LL | println!("{}", i); - | ^ use of possibly uninitialized `i` + | ^ use of possibly-uninitialized `i` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-asm.rs b/src/test/ui/borrowck/borrowck-asm.rs index 9c9cc04baafee..c1b0f39f9366c 100644 --- a/src/test/ui/borrowck/borrowck-asm.rs +++ b/src/test/ui/borrowck/borrowck-asm.rs @@ -57,7 +57,7 @@ mod test_cases { fn indirect_is_not_init() { let x: i32; unsafe { - asm!("nop" : "=*r"(x)); //~ ERROR use of possibly uninitialized variable + asm!("nop" : "=*r"(x)); //~ ERROR use of possibly-uninitialized variable } } diff --git a/src/test/ui/borrowck/borrowck-asm.stderr b/src/test/ui/borrowck/borrowck-asm.stderr index c771373022ac4..f85b5983acced 100644 --- a/src/test/ui/borrowck/borrowck-asm.stderr +++ b/src/test/ui/borrowck/borrowck-asm.stderr @@ -46,11 +46,11 @@ LL | unsafe { LL | asm!("nop" : "+r"(x)); | ^ cannot assign twice to immutable variable -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-asm.rs:60:32 | LL | asm!("nop" : "=*r"(x)); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error[E0506]: cannot assign to `x` because it is borrowed --> $DIR/borrowck-asm.rs:68:31 diff --git a/src/test/ui/borrowck/borrowck-block-unint.rs b/src/test/ui/borrowck/borrowck-block-unint.rs index 1fed2d503bd35..1e7306acaee98 100644 --- a/src/test/ui/borrowck/borrowck-block-unint.rs +++ b/src/test/ui/borrowck/borrowck-block-unint.rs @@ -1,7 +1,7 @@ fn force(f: F) where F: FnOnce() { f(); } fn main() { let x: isize; - force(|| { //~ ERROR borrow of possibly uninitialized variable: `x` + force(|| { //~ ERROR borrow of possibly-uninitialized variable: `x` println!("{}", x); }); } diff --git a/src/test/ui/borrowck/borrowck-block-unint.stderr b/src/test/ui/borrowck/borrowck-block-unint.stderr index d2a49962bafca..578f89df46ce1 100644 --- a/src/test/ui/borrowck/borrowck-block-unint.stderr +++ b/src/test/ui/borrowck/borrowck-block-unint.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-block-unint.rs:4:11 | LL | force(|| { - | ^^ use of possibly uninitialized `x` + | ^^ use of possibly-uninitialized `x` LL | println!("{}", x); | - borrow occurs due to use in closure diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.rs b/src/test/ui/borrowck/borrowck-break-uninit-2.rs index dad5325cb8750..126d991a51c6e 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit-2.rs +++ b/src/test/ui/borrowck/borrowck-break-uninit-2.rs @@ -6,7 +6,7 @@ fn foo() -> isize { x = 0; } - println!("{}", x); //~ ERROR borrow of possibly uninitialized variable: `x` + println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x` return 17; } diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr index e40d8d9dfccb9..bc9b25c0221fc 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr +++ b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-break-uninit-2.rs:9:20 | LL | println!("{}", x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-break-uninit.rs b/src/test/ui/borrowck/borrowck-break-uninit.rs index 9af02b387d8b0..8ccb21ae8eebf 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit.rs +++ b/src/test/ui/borrowck/borrowck-break-uninit.rs @@ -6,7 +6,7 @@ fn foo() -> isize { x = 0; } - println!("{}", x); //~ ERROR borrow of possibly uninitialized variable: `x` + println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x` return 17; } diff --git a/src/test/ui/borrowck/borrowck-break-uninit.stderr b/src/test/ui/borrowck/borrowck-break-uninit.stderr index bbf9b9f1241a2..766d5cfd6348c 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit.stderr +++ b/src/test/ui/borrowck/borrowck-break-uninit.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-break-uninit.rs:9:20 | LL | println!("{}", x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.rs b/src/test/ui/borrowck/borrowck-field-sensitivity.rs index 88f74d1ed3300..ab607c2acbd4b 100644 --- a/src/test/ui/borrowck/borrowck-field-sensitivity.rs +++ b/src/test/ui/borrowck/borrowck-field-sensitivity.rs @@ -78,20 +78,20 @@ fn fu_move_after_fu_move() { fn copy_after_field_assign_after_uninit() { let mut x: A; - x.a = 1; //~ ERROR assign to part of possibly uninitialized variable: `x` + x.a = 1; //~ ERROR assign to part of possibly-uninitialized variable: `x` drop(x.a); } fn borrow_after_field_assign_after_uninit() { let mut x: A; - x.a = 1; //~ ERROR assign to part of possibly uninitialized variable: `x` + x.a = 1; //~ ERROR assign to part of possibly-uninitialized variable: `x` let p = &x.a; drop(*p); } fn move_after_field_assign_after_uninit() { let mut x: A; - x.b = box 1; //~ ERROR assign to part of possibly uninitialized variable: `x` + x.b = box 1; //~ ERROR assign to part of possibly-uninitialized variable: `x` drop(x.b); } diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr index 89523235481ad..158b2e42f2ddf 100644 --- a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr +++ b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr @@ -108,23 +108,23 @@ LL | let _z = A { a: 4, .. x }; | = note: move occurs because `x.b` has type `std::boxed::Box`, which does not implement the `Copy` trait -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/borrowck-field-sensitivity.rs:81:5 | LL | x.a = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/borrowck-field-sensitivity.rs:87:5 | LL | x.a = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/borrowck-field-sensitivity.rs:94:5 | LL | x.b = box 1; - | ^^^ use of possibly uninitialized `x` + | ^^^ use of possibly-uninitialized `x` error: aborting due to 14 previous errors diff --git a/src/test/ui/borrowck/borrowck-if-no-else.rs b/src/test/ui/borrowck/borrowck-if-no-else.rs index 044db99d54c1f..f59bcad6f61d7 100644 --- a/src/test/ui/borrowck/borrowck-if-no-else.rs +++ b/src/test/ui/borrowck/borrowck-if-no-else.rs @@ -2,5 +2,5 @@ fn foo(x: isize) { println!("{}", x); } fn main() { let x: isize; if 1 > 2 { x = 10; } - foo(x); //~ ERROR use of possibly uninitialized variable: `x` + foo(x); //~ ERROR use of possibly-uninitialized variable: `x` } diff --git a/src/test/ui/borrowck/borrowck-if-no-else.stderr b/src/test/ui/borrowck/borrowck-if-no-else.stderr index 1223e409d4df6..3e9d3d4f6d513 100644 --- a/src/test/ui/borrowck/borrowck-if-no-else.stderr +++ b/src/test/ui/borrowck/borrowck-if-no-else.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-if-no-else.rs:5:9 | LL | foo(x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-if-with-else.rs b/src/test/ui/borrowck/borrowck-if-with-else.rs index f632d61a6c3c1..c13318b16c2fa 100644 --- a/src/test/ui/borrowck/borrowck-if-with-else.rs +++ b/src/test/ui/borrowck/borrowck-if-with-else.rs @@ -7,5 +7,5 @@ fn main() { } else { x = 10; } - foo(x); //~ ERROR use of possibly uninitialized variable: `x` + foo(x); //~ ERROR use of possibly-uninitialized variable: `x` } diff --git a/src/test/ui/borrowck/borrowck-if-with-else.stderr b/src/test/ui/borrowck/borrowck-if-with-else.stderr index d11f29b05f565..53b8a6bba2c76 100644 --- a/src/test/ui/borrowck/borrowck-if-with-else.stderr +++ b/src/test/ui/borrowck/borrowck-if-with-else.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-if-with-else.rs:10:9 | LL | foo(x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs index f7457781adc3e..9905e420f948d 100644 --- a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs +++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs @@ -1,7 +1,7 @@ fn main() { let j = || -> isize { let i: isize; - i //~ ERROR use of possibly uninitialized variable: `i` + i //~ ERROR use of possibly-uninitialized variable: `i` }; j(); } diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr index 82a602c6359c1..2d1d9bc8fa41d 100644 --- a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `i` +error[E0381]: use of possibly-uninitialized variable: `i` --> $DIR/borrowck-init-in-called-fn-expr.rs:4:9 | LL | i - | ^ use of possibly uninitialized `i` + | ^ use of possibly-uninitialized `i` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs b/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs index 5055814625539..7dd3396c8c2cb 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs +++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs @@ -1,7 +1,7 @@ fn main() { let f = || -> isize { let i: isize; - i //~ ERROR use of possibly uninitialized variable: `i` + i //~ ERROR use of possibly-uninitialized variable: `i` }; println!("{}", f()); } diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr index 899739378524c..fd8b90eda6032 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `i` +error[E0381]: use of possibly-uninitialized variable: `i` --> $DIR/borrowck-init-in-fn-expr.rs:4:9 | LL | i - | ^ use of possibly uninitialized `i` + | ^ use of possibly-uninitialized `i` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.rs b/src/test/ui/borrowck/borrowck-init-in-fru.rs index 6da3098dc9336..d7ec2ed75c85c 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fru.rs +++ b/src/test/ui/borrowck/borrowck-init-in-fru.rs @@ -7,6 +7,6 @@ struct Point { fn main() { let mut origin: Point; origin = Point { x: 10, ..origin }; - //~^ ERROR use of possibly uninitialized variable: `origin` [E0381] + //~^ ERROR use of possibly-uninitialized variable: `origin` [E0381] origin.clone(); } diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.stderr index fe55bc2fd95c0..a4c042d1c125f 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fru.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-fru.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `origin` +error[E0381]: use of possibly-uninitialized variable: `origin` --> $DIR/borrowck-init-in-fru.rs:9:5 | LL | origin = Point { x: 10, ..origin }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly uninitialized `origin.y` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `origin.y` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.rs b/src/test/ui/borrowck/borrowck-init-op-equal.rs index d3fa852ac91ba..784eb8cf85b8a 100644 --- a/src/test/ui/borrowck/borrowck-init-op-equal.rs +++ b/src/test/ui/borrowck/borrowck-init-op-equal.rs @@ -1,6 +1,6 @@ fn test() { let v: isize; - v += 1; //~ ERROR use of possibly uninitialized variable: `v` + v += 1; //~ ERROR use of possibly-uninitialized variable: `v` v.clone(); } diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.stderr b/src/test/ui/borrowck/borrowck-init-op-equal.stderr index 9863ceb14240f..6c88778ae0e5a 100644 --- a/src/test/ui/borrowck/borrowck-init-op-equal.stderr +++ b/src/test/ui/borrowck/borrowck-init-op-equal.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `v` +error[E0381]: use of possibly-uninitialized variable: `v` --> $DIR/borrowck-init-op-equal.rs:3:5 | LL | v += 1; - | ^^^^^^ use of possibly uninitialized `v` + | ^^^^^^ use of possibly-uninitialized `v` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.rs b/src/test/ui/borrowck/borrowck-init-plus-equal.rs index d895a2e16b537..d9d20a2a9c148 100644 --- a/src/test/ui/borrowck/borrowck-init-plus-equal.rs +++ b/src/test/ui/borrowck/borrowck-init-plus-equal.rs @@ -1,6 +1,6 @@ fn test() { let mut v: isize; - v = v + 1; //~ ERROR use of possibly uninitialized variable: `v` + v = v + 1; //~ ERROR use of possibly-uninitialized variable: `v` v.clone(); } diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr index 80c4e0c80483d..fe09c8581df0e 100644 --- a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr +++ b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `v` +error[E0381]: use of possibly-uninitialized variable: `v` --> $DIR/borrowck-init-plus-equal.rs:3:9 | LL | v = v + 1; - | ^ use of possibly uninitialized `v` + | ^ use of possibly-uninitialized `v` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-or-init.rs b/src/test/ui/borrowck/borrowck-or-init.rs index c0d6c9c2739b2..81b0b80bf11b5 100644 --- a/src/test/ui/borrowck/borrowck-or-init.rs +++ b/src/test/ui/borrowck/borrowck-or-init.rs @@ -2,5 +2,5 @@ fn main() { let i: isize; println!("{}", false || { i = 5; true }); - println!("{}", i); //~ ERROR borrow of possibly uninitialized variable: `i` + println!("{}", i); //~ ERROR borrow of possibly-uninitialized variable: `i` } diff --git a/src/test/ui/borrowck/borrowck-or-init.stderr b/src/test/ui/borrowck/borrowck-or-init.stderr index 122f5192720cc..3fe8d9eededc5 100644 --- a/src/test/ui/borrowck/borrowck-or-init.stderr +++ b/src/test/ui/borrowck/borrowck-or-init.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `i` +error[E0381]: borrow of possibly-uninitialized variable: `i` --> $DIR/borrowck-or-init.rs:5:20 | LL | println!("{}", i); - | ^ use of possibly uninitialized `i` + | ^ use of possibly-uninitialized `i` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.rs b/src/test/ui/borrowck/borrowck-partial-reinit-4.rs index 0fb955d201d03..5e5a8cdf4232b 100644 --- a/src/test/ui/borrowck/borrowck-partial-reinit-4.rs +++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.rs @@ -15,7 +15,7 @@ impl Drop for Test2 { fn stuff() { let mut x : (Test2, Test2); (x.0).0 = Some(Test); - //~^ ERROR assign of possibly uninitialized variable: `x.0` + //~^ ERROR assign of possibly-uninitialized variable: `x.0` } fn main() { diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr index f0a9a7dd5e243..218c4f2de5bc7 100644 --- a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr +++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr @@ -1,8 +1,8 @@ -error[E0381]: assign of possibly uninitialized variable: `x.0` +error[E0381]: assign of possibly-uninitialized variable: `x.0` --> $DIR/borrowck-partial-reinit-4.rs:17:5 | LL | (x.0).0 = Some(Test); - | ^^^^^^^ use of possibly uninitialized `x.0` + | ^^^^^^^ use of possibly-uninitialized `x.0` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-return.rs b/src/test/ui/borrowck/borrowck-return.rs index e5bee2ca4bfeb..8c623356f6c6b 100644 --- a/src/test/ui/borrowck/borrowck-return.rs +++ b/src/test/ui/borrowck/borrowck-return.rs @@ -1,6 +1,6 @@ fn f() -> isize { let x: isize; - return x; //~ ERROR use of possibly uninitialized variable: `x` + return x; //~ ERROR use of possibly-uninitialized variable: `x` } fn main() { f(); } diff --git a/src/test/ui/borrowck/borrowck-return.stderr b/src/test/ui/borrowck/borrowck-return.stderr index a2b65af5dbfcd..bc74e8e343848 100644 --- a/src/test/ui/borrowck/borrowck-return.stderr +++ b/src/test/ui/borrowck/borrowck-return.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-return.rs:3:12 | LL | return x; - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-storage-dead.stderr b/src/test/ui/borrowck/borrowck-storage-dead.stderr index 5b9f49c2e7c92..8e4932142f0db 100644 --- a/src/test/ui/borrowck/borrowck-storage-dead.stderr +++ b/src/test/ui/borrowck/borrowck-storage-dead.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-storage-dead.rs:16:17 | LL | let _ = x + 1; - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.rs b/src/test/ui/borrowck/borrowck-uninit-after-item.rs index 83f3752a1a850..e9a389657c8fd 100644 --- a/src/test/ui/borrowck/borrowck-uninit-after-item.rs +++ b/src/test/ui/borrowck/borrowck-uninit-after-item.rs @@ -1,5 +1,5 @@ fn main() { let bar; fn baz(_x: isize) { } - baz(bar); //~ ERROR use of possibly uninitialized variable: `bar` + baz(bar); //~ ERROR use of possibly-uninitialized variable: `bar` } diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr index 2d0b21dd0d6fb..f7f069b81be02 100644 --- a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `bar` +error[E0381]: use of possibly-uninitialized variable: `bar` --> $DIR/borrowck-uninit-after-item.rs:4:9 | LL | baz(bar); - | ^^^ use of possibly uninitialized `bar` + | ^^^ use of possibly-uninitialized `bar` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr index aa214f9c2f590..9f35a4a8d83bd 100644 --- a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `a` +error[E0381]: use of possibly-uninitialized variable: `a` --> $DIR/borrowck-uninit-field-access.rs:21:13 | LL | let _ = a.x + 1; - | ^^^ use of possibly uninitialized `a.x` + | ^^^ use of possibly-uninitialized `a.x` error[E0382]: use of moved value: `line1.origin` --> $DIR/borrowck-uninit-field-access.rs:25:13 diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs b/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs index bfb0dd4301dd1..20350d61d5bb6 100644 --- a/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs +++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs @@ -3,32 +3,32 @@ pub fn main() { let x: isize; - x += 1; //~ ERROR use of possibly uninitialized variable: `x` + x += 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x -= 1; //~ ERROR use of possibly uninitialized variable: `x` + x -= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x *= 1; //~ ERROR use of possibly uninitialized variable: `x` + x *= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x /= 1; //~ ERROR use of possibly uninitialized variable: `x` + x /= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x %= 1; //~ ERROR use of possibly uninitialized variable: `x` + x %= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x ^= 1; //~ ERROR use of possibly uninitialized variable: `x` + x ^= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x &= 1; //~ ERROR use of possibly uninitialized variable: `x` + x &= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x |= 1; //~ ERROR use of possibly uninitialized variable: `x` + x |= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x <<= 1; //~ ERROR use of possibly uninitialized variable: `x` + x <<= 1; //~ ERROR use of possibly-uninitialized variable: `x` let x: isize; - x >>= 1; //~ ERROR use of possibly uninitialized variable: `x` + x >>= 1; //~ ERROR use of possibly-uninitialized variable: `x` } diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr index 163395e42d252..f2036df3ce92a 100644 --- a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr @@ -1,62 +1,62 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:6:5 | LL | x += 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:9:5 | LL | x -= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:12:5 | LL | x *= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:15:5 | LL | x /= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:18:5 | LL | x %= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:21:5 | LL | x ^= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:24:5 | LL | x &= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:27:5 | LL | x |= 1; - | ^^^^^^ use of possibly uninitialized `x` + | ^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:30:5 | LL | x <<= 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-in-assignop.rs:33:5 | LL | x >>= 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` error: aborting due to 10 previous errors diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs index fa9148f984077..0ccea49f329bb 100644 --- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs +++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs @@ -15,19 +15,19 @@ fn main() { let mut a: S; - a.x = 0; //~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] + a.x = 0; //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381] let _b = &a.x; let mut a: S<&&i32, &&i32>; - a.x = &&0; //~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] + a.x = &&0; //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381] let _b = &**a.x; let mut a: S; - a.x = 0; //~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] + a.x = 0; //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381] let _b = &a.y; let mut a: S<&&i32, &&i32>; - a.x = &&0; //~ assign to part of possibly uninitialized variable: `a` [E0381] + a.x = &&0; //~ assign to part of possibly-uninitialized variable: `a` [E0381] let _b = &**a.y; } diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr index d87621f04d653..d99a50df75b8c 100644 --- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr @@ -1,44 +1,44 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-ref-chain.rs:8:14 | LL | let _y = &**x; - | ^^^^ use of possibly uninitialized `**x` + | ^^^^ use of possibly-uninitialized `**x` -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-ref-chain.rs:11:14 | LL | let _y = &**x; - | ^^^^ use of possibly uninitialized `**x` + | ^^^^ use of possibly-uninitialized `**x` -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit-ref-chain.rs:14:14 | LL | let _y = &**x; - | ^^^^ use of possibly uninitialized `**x` + | ^^^^ use of possibly-uninitialized `**x` -error[E0381]: assign to part of possibly uninitialized variable: `a` +error[E0381]: assign to part of possibly-uninitialized variable: `a` --> $DIR/borrowck-uninit-ref-chain.rs:18:5 | LL | a.x = 0; - | ^^^^^^^ use of possibly uninitialized `a` + | ^^^^^^^ use of possibly-uninitialized `a` -error[E0381]: assign to part of possibly uninitialized variable: `a` +error[E0381]: assign to part of possibly-uninitialized variable: `a` --> $DIR/borrowck-uninit-ref-chain.rs:22:5 | LL | a.x = &&0; - | ^^^^^^^^^ use of possibly uninitialized `a` + | ^^^^^^^^^ use of possibly-uninitialized `a` -error[E0381]: assign to part of possibly uninitialized variable: `a` +error[E0381]: assign to part of possibly-uninitialized variable: `a` --> $DIR/borrowck-uninit-ref-chain.rs:27:5 | LL | a.x = 0; - | ^^^^^^^ use of possibly uninitialized `a` + | ^^^^^^^ use of possibly-uninitialized `a` -error[E0381]: assign to part of possibly uninitialized variable: `a` +error[E0381]: assign to part of possibly-uninitialized variable: `a` --> $DIR/borrowck-uninit-ref-chain.rs:31:5 | LL | a.x = &&0; - | ^^^^^^^^^ use of possibly uninitialized `a` + | ^^^^^^^^^ use of possibly-uninitialized `a` error: aborting due to 7 previous errors diff --git a/src/test/ui/borrowck/borrowck-uninit.rs b/src/test/ui/borrowck/borrowck-uninit.rs index 71c1f596fa21b..017b955a39535 100644 --- a/src/test/ui/borrowck/borrowck-uninit.rs +++ b/src/test/ui/borrowck/borrowck-uninit.rs @@ -2,5 +2,5 @@ fn foo(x: isize) { println!("{}", x); } fn main() { let x: isize; - foo(x); //~ ERROR use of possibly uninitialized variable: `x` + foo(x); //~ ERROR use of possibly-uninitialized variable: `x` } diff --git a/src/test/ui/borrowck/borrowck-uninit.stderr b/src/test/ui/borrowck/borrowck-uninit.stderr index 5db9c1b250cc2..effc209e81659 100644 --- a/src/test/ui/borrowck/borrowck-uninit.stderr +++ b/src/test/ui/borrowck/borrowck-uninit.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-uninit.rs:5:9 | LL | foo(x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.rs b/src/test/ui/borrowck/borrowck-union-uninitialized.rs index 9cab0b19202a0..3cc71e7cece0e 100644 --- a/src/test/ui/borrowck/borrowck-union-uninitialized.rs +++ b/src/test/ui/borrowck/borrowck-union-uninitialized.rs @@ -10,8 +10,8 @@ fn main() { unsafe { let mut s: S; let mut u: U; - s.a = 0; //~ ERROR assign to part of possibly uninitialized variable: `s` - u.a = 0; //~ ERROR assign to part of possibly uninitialized variable: `u` + s.a = 0; //~ ERROR assign to part of possibly-uninitialized variable: `s` + u.a = 0; //~ ERROR assign to part of possibly-uninitialized variable: `u` let sa = s.a; let ua = u.a; } diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.stderr b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr index 06c884e244667..bd9ec5e579ca9 100644 --- a/src/test/ui/borrowck/borrowck-union-uninitialized.stderr +++ b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr @@ -1,14 +1,14 @@ -error[E0381]: assign to part of possibly uninitialized variable: `s` +error[E0381]: assign to part of possibly-uninitialized variable: `s` --> $DIR/borrowck-union-uninitialized.rs:13:9 | LL | s.a = 0; - | ^^^^^^^ use of possibly uninitialized `s` + | ^^^^^^^ use of possibly-uninitialized `s` -error[E0381]: assign to part of possibly uninitialized variable: `u` +error[E0381]: assign to part of possibly-uninitialized variable: `u` --> $DIR/borrowck-union-uninitialized.rs:14:9 | LL | u.a = 0; - | ^^^^^^^ use of possibly uninitialized `u` + | ^^^^^^^ use of possibly-uninitialized `u` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr index c03ef759f570a..d1b396aba8257 100644 --- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr +++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr @@ -1,14 +1,14 @@ -error[E0381]: use of possibly uninitialized variable: `w` +error[E0381]: use of possibly-uninitialized variable: `w` --> $DIR/borrowck-use-in-index-lvalue.rs:3:5 | LL | w[5] = 0; - | ^^^^ use of possibly uninitialized `*w` + | ^^^^ use of possibly-uninitialized `*w` -error[E0381]: use of possibly uninitialized variable: `w` +error[E0381]: use of possibly-uninitialized variable: `w` --> $DIR/borrowck-use-in-index-lvalue.rs:6:5 | LL | w[5] = 0; - | ^^^^ use of possibly uninitialized `*w` + | ^^^^ use of possibly-uninitialized `*w` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr index 2b80140c6b376..ca5227c98c862 100644 --- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr +++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:9:13 | LL | let y = x as *const dyn Foo; - | ^ use of possibly uninitialized `*x` + | ^ use of possibly-uninitialized `*x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr index 84e717a4639cd..24897a0f2dc9c 100644 --- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr +++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/borrowck-use-uninitialized-in-cast.rs:7:13 | LL | let y = x as *const i32; - | ^ use of possibly uninitialized `*x` + | ^ use of possibly-uninitialized `*x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-while-break.rs b/src/test/ui/borrowck/borrowck-while-break.rs index e16bc58656d81..48e4221470221 100644 --- a/src/test/ui/borrowck/borrowck-while-break.rs +++ b/src/test/ui/borrowck/borrowck-while-break.rs @@ -4,7 +4,7 @@ fn test(cond: bool) { v = 3; break; } - println!("{}", v); //~ ERROR borrow of possibly uninitialized variable: `v` + println!("{}", v); //~ ERROR borrow of possibly-uninitialized variable: `v` } fn main() { diff --git a/src/test/ui/borrowck/borrowck-while-break.stderr b/src/test/ui/borrowck/borrowck-while-break.stderr index 0fe3cdc96a874..3eaaf8d7df08d 100644 --- a/src/test/ui/borrowck/borrowck-while-break.stderr +++ b/src/test/ui/borrowck/borrowck-while-break.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `v` +error[E0381]: borrow of possibly-uninitialized variable: `v` --> $DIR/borrowck-while-break.rs:7:20 | LL | println!("{}", v); - | ^ use of possibly uninitialized `v` + | ^ use of possibly-uninitialized `v` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-while-cond.rs b/src/test/ui/borrowck/borrowck-while-cond.rs index 28a5fb18a7f1d..b3ec20711c12b 100644 --- a/src/test/ui/borrowck/borrowck-while-cond.rs +++ b/src/test/ui/borrowck/borrowck-while-cond.rs @@ -1,4 +1,4 @@ fn main() { let x: bool; - while x { } //~ ERROR use of possibly uninitialized variable: `x` + while x { } //~ ERROR use of possibly-uninitialized variable: `x` } diff --git a/src/test/ui/borrowck/borrowck-while-cond.stderr b/src/test/ui/borrowck/borrowck-while-cond.stderr index 06deae345ab60..92937a9c5730e 100644 --- a/src/test/ui/borrowck/borrowck-while-cond.stderr +++ b/src/test/ui/borrowck/borrowck-while-cond.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-while-cond.rs:3:11 | LL | while x { } - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-while.rs b/src/test/ui/borrowck/borrowck-while.rs index 4274fa997a0ab..6b3220c7d8591 100644 --- a/src/test/ui/borrowck/borrowck-while.rs +++ b/src/test/ui/borrowck/borrowck-while.rs @@ -1,7 +1,7 @@ fn f() -> isize { let mut x: isize; while 1 == 1 { x = 10; } - return x; //~ ERROR use of possibly uninitialized variable: `x` + return x; //~ ERROR use of possibly-uninitialized variable: `x` } fn main() { f(); } diff --git a/src/test/ui/borrowck/borrowck-while.stderr b/src/test/ui/borrowck/borrowck-while.stderr index 60622d648dd23..a1f8f64725dcd 100644 --- a/src/test/ui/borrowck/borrowck-while.stderr +++ b/src/test/ui/borrowck/borrowck-while.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/borrowck-while.rs:4:12 | LL | return x; - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.rs b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs index a987c00b09191..7043cb3a164e7 100644 --- a/src/test/ui/borrowck/disallow-possibly-uninitialized.rs +++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs @@ -4,19 +4,19 @@ fn main() { let mut t: (u64, u64); t.0 = 1; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] t.1 = 1; let mut t: (u64, u64); t.1 = 1; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] t.0 = 1; let mut t: (u64, u64); t.0 = 1; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] let mut t: (u64,); t.0 = 1; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] } diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr index a32b17b165934..8d5b39341c109 100644 --- a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr +++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr @@ -1,26 +1,26 @@ -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/disallow-possibly-uninitialized.rs:6:5 | LL | t.0 = 1; - | ^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/disallow-possibly-uninitialized.rs:11:5 | LL | t.1 = 1; - | ^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/disallow-possibly-uninitialized.rs:16:5 | LL | t.0 = 1; - | ^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/disallow-possibly-uninitialized.rs:20:5 | LL | t.0 = 1; - | ^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^ use of possibly-uninitialized `t` error: aborting due to 4 previous errors diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs index 8d8ac279b23a8..f031a144443b3 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs +++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs @@ -10,7 +10,7 @@ fn main() { { let mut t: Tuple; t.0 = S(1); - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] t.1 = 2; println!("{:?} {:?}", t.0, t.1); } @@ -18,7 +18,7 @@ fn main() { { let mut u: Tpair; u.0 = S(1); - //~^ ERROR assign to part of possibly uninitialized variable: `u` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `u` [E0381] u.1 = 2; println!("{:?} {:?}", u.0, u.1); } @@ -26,7 +26,7 @@ fn main() { { let mut v: Spair; v.x = S(1); - //~^ ERROR assign to part of possibly uninitialized variable: `v` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `v` [E0381] v.y = 2; println!("{:?} {:?}", v.x, v.y); } diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr index 6f18ff161372a..22c6c3964edc1 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr +++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr @@ -1,20 +1,20 @@ -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:12:9 | LL | t.0 = S(1); - | ^^^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `u` +error[E0381]: assign to part of possibly-uninitialized variable: `u` --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:20:9 | LL | u.0 = S(1); - | ^^^^^^^^^^ use of possibly uninitialized `u` + | ^^^^^^^^^^ use of possibly-uninitialized `u` -error[E0381]: assign to part of possibly uninitialized variable: `v` +error[E0381]: assign to part of possibly-uninitialized variable: `v` --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:28:9 | LL | v.x = S(1); - | ^^^^^^^^^^ use of possibly uninitialized `v` + | ^^^^^^^^^^ use of possibly-uninitialized `v` error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs index 1a1b376bf9bcf..660d9e85ef54e 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs @@ -10,7 +10,7 @@ fn main() { { let t: Tuple; t.0 = S(1); - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] t.1 = 2; println!("{:?} {:?}", t.0, t.1); } @@ -18,7 +18,7 @@ fn main() { { let u: Tpair; u.0 = S(1); - //~^ ERROR assign to part of possibly uninitialized variable: `u` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `u` [E0381] u.1 = 2; println!("{:?} {:?}", u.0, u.1); } @@ -26,7 +26,7 @@ fn main() { { let v: Spair; v.x = S(1); - //~^ ERROR assign to part of possibly uninitialized variable: `v` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `v` [E0381] v.y = 2; println!("{:?} {:?}", v.x, v.y); } diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr index 68873ac5c02e2..5f9c978c342f6 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr @@ -1,20 +1,20 @@ -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/issue-54499-field-mutation-of-never-init.rs:12:9 | LL | t.0 = S(1); - | ^^^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `u` +error[E0381]: assign to part of possibly-uninitialized variable: `u` --> $DIR/issue-54499-field-mutation-of-never-init.rs:20:9 | LL | u.0 = S(1); - | ^^^^^^^^^^ use of possibly uninitialized `u` + | ^^^^^^^^^^ use of possibly-uninitialized `u` -error[E0381]: assign to part of possibly uninitialized variable: `v` +error[E0381]: assign to part of possibly-uninitialized variable: `v` --> $DIR/issue-54499-field-mutation-of-never-init.rs:28:9 | LL | v.x = S(1); - | ^^^^^^^^^^ use of possibly uninitialized `v` + | ^^^^^^^^^^ use of possibly-uninitialized `v` error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs b/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs index 220b2ecf04d38..f8efa8c891eb3 100644 --- a/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs +++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs @@ -1,7 +1,7 @@ fn main() { let e: i32; match e { - //~^ ERROR use of possibly uninitialized variable + //~^ ERROR use of possibly-uninitialized variable ref u if true => {} ref v if true => { let tx = 0; diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr index 9701343d2b1dd..0eca447b55159 100644 --- a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr +++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `e` +error[E0381]: use of possibly-uninitialized variable: `e` --> $DIR/issue-62107-match-arm-scopes.rs:3:11 | LL | match e { - | ^ use of possibly uninitialized `e` + | ^ use of possibly-uninitialized `e` error: aborting due to previous error diff --git a/src/test/ui/borrowck/reassignment_immutable_fields.stderr b/src/test/ui/borrowck/reassignment_immutable_fields.stderr index d455a8f078743..f09db378a75b4 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields.stderr @@ -1,14 +1,14 @@ -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/reassignment_immutable_fields.rs:7:5 | LL | x.0 = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/reassignment_immutable_fields.rs:15:5 | LL | x.0 = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr index 649c127dcc9d4..5f346708eb610 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr @@ -1,8 +1,8 @@ -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/reassignment_immutable_fields_overlapping.rs:12:5 | LL | x.a = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` error[E0594]: cannot assign to `x.b`, as `x` is not declared as mutable --> $DIR/reassignment_immutable_fields_overlapping.rs:13:5 diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr index 9a2824ccb3cd2..14f0fee84c9aa 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr @@ -7,11 +7,11 @@ LL | x = (22, 44); LL | x.0 = 1; | ^^^^^^^ cannot assign -error[E0381]: assign to part of possibly uninitialized variable: `x` +error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/reassignment_immutable_fields_twice.rs:12:5 | LL | x.0 = 1; - | ^^^^^^^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly-uninitialized `x` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/two-phase-across-loop.rs b/src/test/ui/borrowck/two-phase-across-loop.rs index 12222342c95a1..3fcea7d171349 100644 --- a/src/test/ui/borrowck/two-phase-across-loop.rs +++ b/src/test/ui/borrowck/two-phase-across-loop.rs @@ -1,4 +1,4 @@ -// Test that a borrow which starts as a 2-phase borrow and gets +// Test that a borrow which starts as a two-phase borrow and gets // carried around a loop winds up conflicting with itself. struct Foo { x: String } diff --git a/src/test/ui/consts/const-err4.stderr b/src/test/ui/consts/const-err4.stderr index 1feec3c21c0a5..081b09e33006f 100644 --- a/src/test/ui/consts/const-err4.stderr +++ b/src/test/ui/consts/const-err4.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | Boo = [unsafe { Foo { b: () }.a }; 4][3], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr index 3333ffac4c9b0..e0df787f80a44 100644 --- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:28:43 @@ -38,7 +38,7 @@ error[E0080]: it is undefined behavior to use this value LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:40:5 @@ -46,7 +46,7 @@ error[E0080]: it is undefined behavior to use this value LL | const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:43:43 @@ -78,7 +78,7 @@ error[E0080]: it is undefined behavior to use this value LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:55:5 @@ -86,7 +86,7 @@ error[E0080]: it is undefined behavior to use this value LL | const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:58:45 @@ -102,7 +102,7 @@ error[E0080]: it is undefined behavior to use this value LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:64:47 @@ -150,7 +150,7 @@ error[E0080]: it is undefined behavior to use this value LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:82:43 @@ -190,7 +190,7 @@ error[E0080]: it is undefined behavior to use this value LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:97:43 @@ -214,7 +214,7 @@ error[E0080]: it is undefined behavior to use this value LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:106:43 diff --git a/src/test/ui/consts/const-eval/double_check2.stderr b/src/test/ui/consts/const-eval/double_check2.stderr index 9c56f1995208f..28e0922ecafa6 100644 --- a/src/test/ui/consts/const-eval/double_check2.stderr +++ b/src/test/ui/consts/const-eval/double_check2.stderr @@ -7,7 +7,7 @@ LL | | Union { u8: &BAR }.bar, LL | | )}; | |___^ type validation failed: encountered 5 at .1., but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.stderr index 0be82e3434142..b72a5b80afa8d 100644 --- a/src/test/ui/consts/const-eval/ref_to_int_match.stderr +++ b/src/test/ui/consts/const-eval/ref_to_int_match.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: could not evaluate constant pattern --> $DIR/ref_to_int_match.rs:7:14 diff --git a/src/test/ui/consts/const-eval/transmute-const.stderr b/src/test/ui/consts/const-eval/transmute-const.stderr index cacf86364796f..47f89fccf7a81 100644 --- a/src/test/ui/consts/const-eval/transmute-const.stderr +++ b/src/test/ui/consts/const-eval/transmute-const.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | static FOO: bool = unsafe { mem::transmute(3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3, but expected something less or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index 30dd86592d469..8ebc9dbec8ab2 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:26:1 @@ -12,7 +12,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:29:1 @@ -20,7 +20,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { TransmuteEnum { in1: &1 }.out2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 0 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:48:1 @@ -28,7 +28,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:50:1 @@ -36,7 +36,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:52:1 @@ -44,7 +44,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { TransmuteEnum2 { in2: &0 }.out2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 2 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:56:1 @@ -52,7 +52,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:60:1 @@ -60,7 +60,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }.out3 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:71:1 @@ -68,7 +68,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected something less or equal to 1114111 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to 9 previous errors diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr index de20c3d0b8cfe..80d80a986751e 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error --> $DIR/ub-nonnull.rs:18:29 @@ -30,7 +30,7 @@ error[E0080]: it is undefined behavior to use this value LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:24:1 @@ -38,7 +38,7 @@ error[E0080]: it is undefined behavior to use this value LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:32:1 @@ -46,7 +46,7 @@ error[E0080]: it is undefined behavior to use this value LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:40:1 @@ -54,7 +54,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:46:1 @@ -62,7 +62,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to 7 previous errors diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr index cd3cc38467c36..01bde413c0d9c 100644 --- a/src/test/ui/consts/const-eval/ub-ref.stderr +++ b/src/test/ui/consts/const-eval/ub-ref.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned reference (required 2 byte alignment but found 1) | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:11:1 @@ -12,7 +12,7 @@ error[E0080]: it is undefined behavior to use this value LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:17:1 @@ -20,7 +20,7 @@ error[E0080]: it is undefined behavior to use this value LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:20:1 @@ -28,7 +28,7 @@ error[E0080]: it is undefined behavior to use this value LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:23:1 @@ -36,7 +36,7 @@ error[E0080]: it is undefined behavior to use this value LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (created from integer) | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to 5 previous errors diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr index 43d91483797bf..3877f3cab6d44 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:18:1 @@ -12,7 +12,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at . | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:21:1 @@ -20,7 +20,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/const-eval/ub-upvars.stderr b/src/test/ui/consts/const-eval/ub-upvars.stderr index f8273ba902a88..ea6ab3ae5b5ba 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.stderr +++ b/src/test/ui/consts/const-eval/ub-upvars.stderr @@ -8,7 +8,7 @@ LL | | move || { let _ = bad_ref; let _ = another_var; } LL | | }; | |__^ type validation failed: encountered 0 at ..., but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index aadabc323fbd4..9134ef5a31ad9 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:90:1 @@ -12,7 +12,7 @@ error[E0080]: it is undefined behavior to use this value LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:93:1 @@ -20,7 +20,7 @@ error[E0080]: it is undefined behavior to use this value LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:97:1 @@ -28,7 +28,7 @@ error[E0080]: it is undefined behavior to use this value LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:100:1 @@ -36,7 +36,7 @@ error[E0080]: it is undefined behavior to use this value LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:107:1 @@ -44,7 +44,7 @@ error[E0080]: it is undefined behavior to use this value LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:110:1 @@ -52,7 +52,7 @@ error[E0080]: it is undefined behavior to use this value LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:113:1 @@ -60,7 +60,7 @@ error[E0080]: it is undefined behavior to use this value LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:117:1 @@ -68,7 +68,7 @@ error[E0080]: it is undefined behavior to use this value LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected something less or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:123:1 @@ -76,7 +76,7 @@ error[E0080]: it is undefined behavior to use this value LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected something less or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:126:1 @@ -84,7 +84,7 @@ error[E0080]: it is undefined behavior to use this value LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected something less or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:133:1 @@ -92,7 +92,7 @@ error[E0080]: it is undefined behavior to use this value LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:138:1 @@ -100,7 +100,7 @@ error[E0080]: it is undefined behavior to use this value LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:141:1 @@ -108,7 +108,7 @@ error[E0080]: it is undefined behavior to use this value LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:144:1 @@ -116,7 +116,7 @@ error[E0080]: it is undefined behavior to use this value LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:148:1 @@ -124,7 +124,7 @@ error[E0080]: it is undefined behavior to use this value LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:152:1 @@ -132,7 +132,7 @@ error[E0080]: it is undefined behavior to use this value LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:154:1 @@ -140,7 +140,7 @@ error[E0080]: it is undefined behavior to use this value LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to 18 previous errors diff --git a/src/test/ui/consts/const-eval/union-const-eval-field.stderr b/src/test/ui/consts/const-eval/union-const-eval-field.stderr index 4d008a0e02ad7..9193bd9dea189 100644 --- a/src/test/ui/consts/const-eval/union-const-eval-field.stderr +++ b/src/test/ui/consts/const-eval/union-const-eval-field.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const FIELD3: Field3 = unsafe { UNION.field3 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/union-ice.stderr b/src/test/ui/consts/const-eval/union-ice.stderr index 8d950e86d27fc..476f3651740ab 100644 --- a/src/test/ui/consts/const-eval/union-ice.stderr +++ b/src/test/ui/consts/const-eval/union-ice.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const FIELD3: Field3 = unsafe { UNION.field3 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/union-ice.rs:16:1 @@ -15,7 +15,7 @@ LL | | b: unsafe { UNION.field3 }, LL | | }; | |__^ type validation failed: encountered uninitialized bytes at .b, but expected initialized plain (non-pointer) bytes | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/union-ice.rs:26:1 @@ -29,7 +29,7 @@ LL | | a: 42, LL | | }; | |__^ type validation failed: encountered undefined bytes at .b[1] | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/const-eval/union-ub.stderr b/src/test/ui/consts/const-eval/union-ub.stderr index 6a3a397585c89..fa67bc0d8e7b5 100644 --- a/src/test/ui/consts/const-eval/union-ub.stderr +++ b/src/test/ui/consts/const-eval/union-ub.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something less or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/const_let_refutable.rs b/src/test/ui/consts/const_let_refutable.rs index 7b3a591223025..d48d5945e7da9 100644 --- a/src/test/ui/consts/const_let_refutable.rs +++ b/src/test/ui/consts/const_let_refutable.rs @@ -2,6 +2,6 @@ fn main() {} const fn slice([a, b]: &[i32]) -> i32 { //~ ERROR refutable pattern in function argument a + b //~ ERROR can only call other `const fn` within a `const fn` - //~^ ERROR use of possibly uninitialized variable: `a` - //~| ERROR use of possibly uninitialized variable: `b` + //~^ ERROR use of possibly-uninitialized variable: `a` + //~| ERROR use of possibly-uninitialized variable: `b` } diff --git a/src/test/ui/consts/const_let_refutable.stderr b/src/test/ui/consts/const_let_refutable.stderr index a61c9b0c9fef9..31a3098a26376 100644 --- a/src/test/ui/consts/const_let_refutable.stderr +++ b/src/test/ui/consts/const_let_refutable.stderr @@ -13,17 +13,17 @@ LL | a + b = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 = help: add `#![feature(const_fn)]` to the crate attributes to enable -error[E0381]: use of possibly uninitialized variable: `a` +error[E0381]: use of possibly-uninitialized variable: `a` --> $DIR/const_let_refutable.rs:4:5 | LL | a + b - | ^ use of possibly uninitialized `a` + | ^ use of possibly-uninitialized `a` -error[E0381]: use of possibly uninitialized variable: `b` +error[E0381]: use of possibly-uninitialized variable: `b` --> $DIR/const_let_refutable.rs:4:9 | LL | a + b - | ^ use of possibly uninitialized `b` + | ^ use of possibly-uninitialized `b` error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/std/alloc.stderr b/src/test/ui/consts/std/alloc.stderr index 74a8f3daf6aaa..26b7a24ebfa6f 100644 --- a/src/test/ui/consts/std/alloc.stderr +++ b/src/test/ui/consts/std/alloc.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const LAYOUT_INVALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0 at .align_, but expected something greater or equal to 1 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/consts/validate_never_arrays.stderr b/src/test/ui/consts/validate_never_arrays.stderr index 7a7d816873350..c4c7a33718279 100644 --- a/src/test/ui/consts/validate_never_arrays.stderr +++ b/src/test/ui/consts/validate_never_arrays.stderr @@ -4,7 +4,7 @@ error[E0080]: it is undefined behavior to use this value LL | const FOO: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at . | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: aborting due to previous error diff --git a/src/test/ui/empty/empty-never-array.rs b/src/test/ui/empty/empty-never-array.rs index ffd2545b291e2..f0ecea42f39c8 100644 --- a/src/test/ui/empty/empty-never-array.rs +++ b/src/test/ui/empty/empty-never-array.rs @@ -10,7 +10,7 @@ fn transmute(t: T) -> U { let Helper::U(u) = Helper::T(t, []); //~^ ERROR refutable pattern in local binding: `T(_, _)` not covered u - //~^ ERROR use of possibly uninitialized variable: `u` + //~^ ERROR use of possibly-uninitialized variable: `u` } fn main() { diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr index 01ee1c3a4d7fa..a7f7cfa289e00 100644 --- a/src/test/ui/empty/empty-never-array.stderr +++ b/src/test/ui/empty/empty-never-array.stderr @@ -11,11 +11,11 @@ LL | | } LL | let Helper::U(u) = Helper::T(t, []); | ^^^^^^^^^^^^ pattern `T(_, _)` not covered -error[E0381]: use of possibly uninitialized variable: `u` +error[E0381]: use of possibly-uninitialized variable: `u` --> $DIR/empty-never-array.rs:12:5 | LL | u - | ^ use of possibly uninitialized `u` + | ^ use of possibly-uninitialized `u` error: aborting due to 2 previous errors diff --git a/src/test/ui/generator/partial-initialization-across-yield.rs b/src/test/ui/generator/partial-initialization-across-yield.rs index 1e4593002cb9a..8b75721420351 100644 --- a/src/test/ui/generator/partial-initialization-across-yield.rs +++ b/src/test/ui/generator/partial-initialization-across-yield.rs @@ -10,7 +10,7 @@ fn test_tuple() { let _ = || { let mut t: (i32, i32); t.0 = 42; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] yield; t.1 = 88; let _ = t; @@ -21,7 +21,7 @@ fn test_tuple_struct() { let _ = || { let mut t: T; t.0 = 42; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] yield; t.1 = 88; let _ = t; @@ -32,7 +32,7 @@ fn test_struct() { let _ = || { let mut t: S; t.x = 42; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] yield; t.y = 88; let _ = t; diff --git a/src/test/ui/generator/partial-initialization-across-yield.stderr b/src/test/ui/generator/partial-initialization-across-yield.stderr index 8bf0037e07009..66b86488eaec7 100644 --- a/src/test/ui/generator/partial-initialization-across-yield.stderr +++ b/src/test/ui/generator/partial-initialization-across-yield.stderr @@ -1,20 +1,20 @@ -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/partial-initialization-across-yield.rs:12:9 | LL | t.0 = 42; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/partial-initialization-across-yield.rs:23:9 | LL | t.0 = 42; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/partial-initialization-across-yield.rs:34:9 | LL | t.x = 42; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-15381.rs b/src/test/ui/issues/issue-15381.rs index d21c321b09399..4c8e1b41beefc 100644 --- a/src/test/ui/issues/issue-15381.rs +++ b/src/test/ui/issues/issue-15381.rs @@ -4,6 +4,6 @@ fn main() { for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { //~^ ERROR refutable pattern in `for` loop binding: `&[]` not covered println!("y={}", y); - //~^ ERROR borrow of possibly uninitialized variable: `y` + //~^ ERROR borrow of possibly-uninitialized variable: `y` } } diff --git a/src/test/ui/issues/issue-15381.stderr b/src/test/ui/issues/issue-15381.stderr index a8495846b3610..e8106059052da 100644 --- a/src/test/ui/issues/issue-15381.stderr +++ b/src/test/ui/issues/issue-15381.stderr @@ -4,11 +4,11 @@ error[E0005]: refutable pattern in `for` loop binding: `&[]` not covered LL | for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { | ^^^^^^^^ pattern `&[]` not covered -error[E0381]: borrow of possibly uninitialized variable: `y` +error[E0381]: borrow of possibly-uninitialized variable: `y` --> $DIR/issue-15381.rs:6:26 | LL | println!("y={}", y); - | ^ use of possibly uninitialized `y` + | ^ use of possibly-uninitialized `y` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-24267-flow-exit.rs b/src/test/ui/issues/issue-24267-flow-exit.rs index a1b4d75d4048f..d6809ee4143b0 100644 --- a/src/test/ui/issues/issue-24267-flow-exit.rs +++ b/src/test/ui/issues/issue-24267-flow-exit.rs @@ -9,11 +9,11 @@ pub fn main() { pub fn foo1() { let x: i32; loop { x = break; } - println!("{}", x); //~ ERROR borrow of possibly uninitialized variable: `x` + println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x` } pub fn foo2() { let x: i32; for _ in 0..10 { x = continue; } - println!("{}", x); //~ ERROR borrow of possibly uninitialized variable: `x` + println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x` } diff --git a/src/test/ui/issues/issue-24267-flow-exit.stderr b/src/test/ui/issues/issue-24267-flow-exit.stderr index 3b4f27621f696..4eb41ca24ddfe 100644 --- a/src/test/ui/issues/issue-24267-flow-exit.stderr +++ b/src/test/ui/issues/issue-24267-flow-exit.stderr @@ -1,14 +1,14 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/issue-24267-flow-exit.rs:12:20 | LL | println!("{}", x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/issue-24267-flow-exit.rs:18:20 | LL | println!("{}", x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to 2 previous errors diff --git a/src/test/ui/loops/loop-proper-liveness.rs b/src/test/ui/loops/loop-proper-liveness.rs index b8f76fbe57ba3..b242ec4296d66 100644 --- a/src/test/ui/loops/loop-proper-liveness.rs +++ b/src/test/ui/loops/loop-proper-liveness.rs @@ -6,7 +6,7 @@ fn test1() { 'a: loop { x = loop { break 'a }; } - println!("{:?}", x); //~ ERROR borrow of possibly uninitialized variable + println!("{:?}", x); //~ ERROR borrow of possibly-uninitialized variable } // test2 and test3 should not fail. diff --git a/src/test/ui/loops/loop-proper-liveness.stderr b/src/test/ui/loops/loop-proper-liveness.stderr index c87720659fd78..d55f9ff31e3ee 100644 --- a/src/test/ui/loops/loop-proper-liveness.stderr +++ b/src/test/ui/loops/loop-proper-liveness.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `x` +error[E0381]: borrow of possibly-uninitialized variable: `x` --> $DIR/loop-proper-liveness.rs:9:22 | LL | println!("{:?}", x); - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to previous error diff --git a/src/test/ui/missing/missing-semicolon-warning.stderr b/src/test/ui/missing/missing-semicolon-warning.stderr index b3f3ebc855daa..b4001aba2882c 100644 --- a/src/test/ui/missing/missing-semicolon-warning.stderr +++ b/src/test/ui/missing/missing-semicolon-warning.stderr @@ -7,7 +7,7 @@ LL | $( let x = $e1 )*; LL | fn main() { m!(0, 0; 0, 0); } | --------------- in this macro invocation | - = note: This was erroneously allowed and will become a hard error in a future release + = note: this was erroneously allowed and will become a hard error in a future release warning: expected `;`, found `println` --> $DIR/missing-semicolon-warning.rs:7:12 @@ -18,5 +18,5 @@ LL | $( println!("{}", $e2) )*; LL | fn main() { m!(0, 0; 0, 0); } | --------------- in this macro invocation | - = note: This was erroneously allowed and will become a hard error in a future release + = note: this was erroneously allowed and will become a hard error in a future release diff --git a/src/test/ui/moves/move-into-dead-array-1.rs b/src/test/ui/moves/move-into-dead-array-1.rs index 16a18da4a44a3..2d0ff58526393 100644 --- a/src/test/ui/moves/move-into-dead-array-1.rs +++ b/src/test/ui/moves/move-into-dead-array-1.rs @@ -11,5 +11,5 @@ fn main() { fn foo(i: usize) { let mut a: [D; 4]; - a[i] = d(); //~ ERROR use of possibly uninitialized variable: `a` + a[i] = d(); //~ ERROR use of possibly-uninitialized variable: `a` } diff --git a/src/test/ui/moves/move-into-dead-array-1.stderr b/src/test/ui/moves/move-into-dead-array-1.stderr index 33da0e54a1e4c..5f20ccfeddf48 100644 --- a/src/test/ui/moves/move-into-dead-array-1.stderr +++ b/src/test/ui/moves/move-into-dead-array-1.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `a` +error[E0381]: use of possibly-uninitialized variable: `a` --> $DIR/move-into-dead-array-1.rs:14:5 | LL | a[i] = d(); - | ^^^^ use of possibly uninitialized `a` + | ^^^^ use of possibly-uninitialized `a` error: aborting due to previous error diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs index 906ea32b9c42d..1983e13db0afd 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs +++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs @@ -26,13 +26,13 @@ impl Drop for D { fn cannot_partially_init_adt_with_drop() { let d: D; d.x = 10; - //~^ ERROR assign of possibly uninitialized variable: `d` [E0381] + //~^ ERROR assign of possibly-uninitialized variable: `d` [E0381] } fn cannot_partially_init_mutable_adt_with_drop() { let mut d: D; d.x = 10; - //~^ ERROR assign of possibly uninitialized variable: `d` [E0381] + //~^ ERROR assign of possibly-uninitialized variable: `d` [E0381] } fn cannot_partially_reinit_adt_with_drop() { @@ -45,13 +45,13 @@ fn cannot_partially_reinit_adt_with_drop() { fn cannot_partially_init_inner_adt_via_outer_with_drop() { let d: D; d.s.y = 20; - //~^ ERROR assign to part of possibly uninitialized variable: `d` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `d` [E0381] } fn cannot_partially_init_inner_adt_via_mutable_outer_with_drop() { let mut d: D; d.s.y = 20; - //~^ ERROR assign to part of possibly uninitialized variable: `d` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `d` [E0381] } fn cannot_partially_reinit_inner_adt_via_outer_with_drop() { diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr index 153d9bdf3215d..1b66e034d3785 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr +++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr @@ -1,14 +1,14 @@ -error[E0381]: assign of possibly uninitialized variable: `d` +error[E0381]: assign of possibly-uninitialized variable: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:28:5 | LL | d.x = 10; - | ^^^^^^^^ use of possibly uninitialized `d` + | ^^^^^^^^ use of possibly-uninitialized `d` -error[E0381]: assign of possibly uninitialized variable: `d` +error[E0381]: assign of possibly-uninitialized variable: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:34:5 | LL | d.x = 10; - | ^^^^^^^^ use of possibly uninitialized `d` + | ^^^^^^^^ use of possibly-uninitialized `d` error[E0382]: assign of moved value: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:41:5 @@ -20,17 +20,17 @@ LL | drop(d); LL | d.x = 10; | ^^^^^^^^ value assigned here after move -error[E0381]: assign to part of possibly uninitialized variable: `d` +error[E0381]: assign to part of possibly-uninitialized variable: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:47:5 | LL | d.s.y = 20; - | ^^^^^^^^^^ use of possibly uninitialized `d.s` + | ^^^^^^^^^^ use of possibly-uninitialized `d.s` -error[E0381]: assign to part of possibly uninitialized variable: `d` +error[E0381]: assign to part of possibly-uninitialized variable: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:53:5 | LL | d.s.y = 20; - | ^^^^^^^^^^ use of possibly uninitialized `d.s` + | ^^^^^^^^^^ use of possibly-uninitialized `d.s` error[E0382]: assign to part of moved value: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:60:5 diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-use.rs index 633cbdba2d40e..7da47c85f5450 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-use.rs +++ b/src/test/ui/nll/issue-21232-partial-init-and-use.rs @@ -97,14 +97,14 @@ macro_rules! use_part { fn test_0000_local_fully_init_and_use_struct() { let s: S; s.x = 10; s.y = Box::new(20); - //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381] use_fully!(struct s); } fn test_0001_local_fully_init_and_use_tuple() { let t: T; t.0 = 10; t.1 = Box::new(20); - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] use_fully!(tuple t); } @@ -125,14 +125,14 @@ fn test_0011_local_fully_reinit_and_use_tuple() { fn test_0100_local_partial_init_and_use_struct() { let s: S; s.x = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381] use_part!(struct s); } fn test_0101_local_partial_init_and_use_tuple() { let t: T; t.0 = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] use_part!(tuple t); } @@ -153,14 +153,14 @@ fn test_0111_local_partial_reinit_and_use_tuple() { fn test_0200_local_void_init_and_use_struct() { let s: S; s.x = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381] use_part!(struct s); } fn test_0201_local_void_init_and_use_tuple() { let t: Tvoid; t.0 = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] use_part!(tuple t); } @@ -176,14 +176,14 @@ fn test_0201_local_void_init_and_use_tuple() { fn test_1000_field_fully_init_and_use_struct() { let q: Q>; q.r.f.x = 10; q.r.f.y = Box::new(20); - //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] use_fully!(struct q.r.f); } fn test_1001_field_fully_init_and_use_tuple() { let q: Q; q.r.f.0 = 10; q.r.f.1 = Box::new(20); - //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] use_fully!(tuple q.r.f); } @@ -204,14 +204,14 @@ fn test_1011_field_fully_reinit_and_use_tuple() { fn test_1100_field_partial_init_and_use_struct() { let q: Q>; q.r.f.x = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] use_part!(struct q.r.f); } fn test_1101_field_partial_init_and_use_tuple() { let q: Q; q.r.f.0 = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] use_part!(tuple q.r.f); } @@ -232,14 +232,14 @@ fn test_1111_field_partial_reinit_and_use_tuple() { fn test_1200_field_void_init_and_use_struct() { let mut q: Q>; q.r.f.x = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] use_part!(struct q.r.f); } fn test_1201_field_void_init_and_use_tuple() { let mut q: Q; q.r.f.0 = 10; - //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] use_part!(tuple q.r.f); } diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr index 1cdf728a5e604..32147898320c0 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr +++ b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr @@ -1,14 +1,14 @@ -error[E0381]: assign to part of possibly uninitialized variable: `s` +error[E0381]: assign to part of possibly-uninitialized variable: `s` --> $DIR/issue-21232-partial-init-and-use.rs:99:5 | LL | s.x = 10; s.y = Box::new(20); - | ^^^^^^^^ use of possibly uninitialized `s` + | ^^^^^^^^ use of possibly-uninitialized `s` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/issue-21232-partial-init-and-use.rs:106:5 | LL | t.0 = 10; t.1 = Box::new(20); - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` error[E0382]: assign to part of moved value: `s` --> $DIR/issue-21232-partial-init-and-use.rs:113:5 @@ -30,17 +30,17 @@ LL | let mut t: T = (0, Box::new(0)); drop(t); LL | t.0 = 10; t.1 = Box::new(20); | ^^^^^^^^ value partially assigned here after move -error[E0381]: assign to part of possibly uninitialized variable: `s` +error[E0381]: assign to part of possibly-uninitialized variable: `s` --> $DIR/issue-21232-partial-init-and-use.rs:127:5 | LL | s.x = 10; - | ^^^^^^^^ use of possibly uninitialized `s` + | ^^^^^^^^ use of possibly-uninitialized `s` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/issue-21232-partial-init-and-use.rs:134:5 | LL | t.0 = 10; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` error[E0382]: assign to part of moved value: `s` --> $DIR/issue-21232-partial-init-and-use.rs:141:5 @@ -62,29 +62,29 @@ LL | let mut t: T = (0, Box::new(0)); drop(t); LL | t.0 = 10; | ^^^^^^^^ value partially assigned here after move -error[E0381]: assign to part of possibly uninitialized variable: `s` +error[E0381]: assign to part of possibly-uninitialized variable: `s` --> $DIR/issue-21232-partial-init-and-use.rs:155:5 | LL | s.x = 10; - | ^^^^^^^^ use of possibly uninitialized `s` + | ^^^^^^^^ use of possibly-uninitialized `s` -error[E0381]: assign to part of possibly uninitialized variable: `t` +error[E0381]: assign to part of possibly-uninitialized variable: `t` --> $DIR/issue-21232-partial-init-and-use.rs:162:5 | LL | t.0 = 10; - | ^^^^^^^^ use of possibly uninitialized `t` + | ^^^^^^^^ use of possibly-uninitialized `t` -error[E0381]: assign to part of possibly uninitialized variable: `q` +error[E0381]: assign to part of possibly-uninitialized variable: `q` --> $DIR/issue-21232-partial-init-and-use.rs:178:5 | LL | q.r.f.x = 10; q.r.f.y = Box::new(20); - | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` -error[E0381]: assign to part of possibly uninitialized variable: `q` +error[E0381]: assign to part of possibly-uninitialized variable: `q` --> $DIR/issue-21232-partial-init-and-use.rs:185:5 | LL | q.r.f.0 = 10; q.r.f.1 = Box::new(20); - | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` error[E0382]: assign to part of moved value: `q.r` --> $DIR/issue-21232-partial-init-and-use.rs:192:5 @@ -106,17 +106,17 @@ LL | q.r.f.0 = 10; q.r.f.1 = Box::new(20); | = note: move occurs because `q.r` has type `R<(u32, std::boxed::Box)>`, which does not implement the `Copy` trait -error[E0381]: assign to part of possibly uninitialized variable: `q` +error[E0381]: assign to part of possibly-uninitialized variable: `q` --> $DIR/issue-21232-partial-init-and-use.rs:206:5 | LL | q.r.f.x = 10; - | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` -error[E0381]: assign to part of possibly uninitialized variable: `q` +error[E0381]: assign to part of possibly-uninitialized variable: `q` --> $DIR/issue-21232-partial-init-and-use.rs:213:5 | LL | q.r.f.0 = 10; - | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` error[E0382]: assign to part of moved value: `q.r` --> $DIR/issue-21232-partial-init-and-use.rs:220:5 @@ -138,17 +138,17 @@ LL | q.r.f.0 = 10; | = note: move occurs because `q.r` has type `R<(u32, std::boxed::Box)>`, which does not implement the `Copy` trait -error[E0381]: assign to part of possibly uninitialized variable: `q` +error[E0381]: assign to part of possibly-uninitialized variable: `q` --> $DIR/issue-21232-partial-init-and-use.rs:234:5 | LL | q.r.f.x = 10; - | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` -error[E0381]: assign to part of possibly uninitialized variable: `q` +error[E0381]: assign to part of possibly-uninitialized variable: `q` --> $DIR/issue-21232-partial-init-and-use.rs:241:5 | LL | q.r.f.0 = 10; - | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` error[E0382]: assign to part of moved value: `c` --> $DIR/issue-21232-partial-init-and-use.rs:259:13 diff --git a/src/test/ui/nll/match-cfg-fake-edges.rs b/src/test/ui/nll/match-cfg-fake-edges.rs index 94e4a763866f6..5fc9966cdf807 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.rs +++ b/src/test/ui/nll/match-cfg-fake-edges.rs @@ -20,7 +20,7 @@ fn guard_may_be_skipped(y: i32) { match y { _ if { x = 2; true } => 1, _ if { - x; //~ ERROR use of possibly uninitialized variable: `x` + x; //~ ERROR use of possibly-uninitialized variable: `x` false } => 2, _ => 3, diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr index b1e0fa739769a..3d9037bbe7bf8 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.stderr +++ b/src/test/ui/nll/match-cfg-fake-edges.stderr @@ -1,8 +1,8 @@ -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/match-cfg-fake-edges.rs:23:13 | LL | x; - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error[E0382]: use of moved value: `x` --> $DIR/match-cfg-fake-edges.rs:37:13 diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr index 9f804dfb3d7be..284a910a01b8a 100644 --- a/src/test/ui/nll/match-on-borrowed.stderr +++ b/src/test/ui/nll/match-on-borrowed.stderr @@ -34,11 +34,11 @@ LL | true => (), LL | x; | - borrow later used here -error[E0381]: use of possibly uninitialized variable: `n` +error[E0381]: use of possibly-uninitialized variable: `n` --> $DIR/match-on-borrowed.rs:92:11 | LL | match n {} - | ^ use of possibly uninitialized `n` + | ^ use of possibly-uninitialized `n` error: aborting due to 4 previous errors diff --git a/src/test/ui/parser/do-catch-suggests-try.rs b/src/test/ui/parser/do-catch-suggests-try.rs index 61fae721ffbde..d805ab75882dd 100644 --- a/src/test/ui/parser/do-catch-suggests-try.rs +++ b/src/test/ui/parser/do-catch-suggests-try.rs @@ -1,5 +1,5 @@ fn main() { let _: Option<()> = do catch {}; //~^ ERROR found removed `do catch` syntax - //~^^ HELP Following RFC #2388, the new non-placeholder syntax is `try` + //~^^ HELP following RFC #2388, the new non-placeholder syntax is `try` } diff --git a/src/test/ui/parser/do-catch-suggests-try.stderr b/src/test/ui/parser/do-catch-suggests-try.stderr index 6d13b0f1cc872..e151d4cf8a6aa 100644 --- a/src/test/ui/parser/do-catch-suggests-try.stderr +++ b/src/test/ui/parser/do-catch-suggests-try.stderr @@ -4,7 +4,7 @@ error: found removed `do catch` syntax LL | let _: Option<()> = do catch {}; | ^^ | - = help: Following RFC #2388, the new non-placeholder syntax is `try` + = help: following RFC #2388, the new non-placeholder syntax is `try` error: aborting due to previous error diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs index 45910c3c3a8c6..f6b317886bfad 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs @@ -6,7 +6,7 @@ fn foo(res: Result) -> u32 { let Ok(x) = res; //~^ ERROR refutable pattern x - //~^ ERROR use of possibly uninitialized variable: `x` + //~^ ERROR use of possibly-uninitialized variable: `x` } fn main() { diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr index eee331d95b9bc..b9385952fafa3 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -4,11 +4,11 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered LL | let Ok(x) = res; | ^^^^^ pattern `Err(_)` not covered -error[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/recursive-types-are-not-uninhabited.rs:8:5 | LL | x - | ^ use of possibly uninitialized `x` + | ^ use of possibly-uninitialized `x` error: aborting due to 2 previous errors diff --git a/src/test/ui/try-block/try-block-opt-init.rs b/src/test/ui/try-block/try-block-opt-init.rs index 2387db8de4d6a..ef10b47fd1305 100644 --- a/src/test/ui/try-block/try-block-opt-init.rs +++ b/src/test/ui/try-block/try-block-opt-init.rs @@ -12,5 +12,5 @@ pub fn main() { Ok::<(), ()>(())?; use_val(cfg_res); }; - assert_eq!(cfg_res, 5); //~ ERROR borrow of possibly uninitialized variable: `cfg_res` + assert_eq!(cfg_res, 5); //~ ERROR borrow of possibly-uninitialized variable: `cfg_res` } diff --git a/src/test/ui/try-block/try-block-opt-init.stderr b/src/test/ui/try-block/try-block-opt-init.stderr index ec0128dbdf0fc..308906477d914 100644 --- a/src/test/ui/try-block/try-block-opt-init.stderr +++ b/src/test/ui/try-block/try-block-opt-init.stderr @@ -1,8 +1,8 @@ -error[E0381]: borrow of possibly uninitialized variable: `cfg_res` +error[E0381]: borrow of possibly-uninitialized variable: `cfg_res` --> $DIR/try-block-opt-init.rs:15:5 | LL | assert_eq!(cfg_res, 5); - | ^^^^^^^^^^^^^^^^^^^^^^^ use of possibly uninitialized `cfg_res` + | ^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `cfg_res` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) From 0ca645ac5f88fcaed9c7b8246af1462a90fea5a1 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 6 Sep 2019 07:34:55 +0200 Subject: [PATCH 532/618] annotate-snippet emitter: Update issue number The tracking issue has been replaced by one with mentoring instructions. --- src/librustc_errors/annotate_snippet_emitter_writer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index 3bed5d81dc514..50841236bb498 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -105,7 +105,7 @@ impl<'a> DiagnosticConverter<'a> { annotated_files: Vec, primary_lo: Loc ) -> Vec { - // FIXME(#59346): Provide a test case where `annotated_files` is > 1 + // FIXME(#64205): Provide a test case where `annotated_files` is > 1 annotated_files.iter().flat_map(|annotated_file| { annotated_file.lines.iter().map(|line| { let line_source = Self::source_string(annotated_file.file.clone(), &line); From ba7d1b80d051f8004fa6a294e8331dcb33b85f6d Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Fri, 6 Sep 2019 15:14:25 +0800 Subject: [PATCH 533/618] it's more pythonic to use 'is not None' in python files --- src/bootstrap/bootstrap.py | 2 +- src/libcore/unicode/printable.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 4162fe1df5086..179cd488be732 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -668,7 +668,7 @@ def check_submodule(self, module, slow_submodules): def update_submodule(self, module, checked_out, recorded_submodules): module_path = os.path.join(self.rust_root, module) - if checked_out != None: + if checked_out is not None: default_encoding = sys.getdefaultencoding() checked_out = checked_out.communicate()[0].decode(default_encoding).strip() if recorded_submodules[module] == checked_out: diff --git a/src/libcore/unicode/printable.py b/src/libcore/unicode/printable.py index 748917f1d3420..4e8b4ecad0200 100644 --- a/src/libcore/unicode/printable.py +++ b/src/libcore/unicode/printable.py @@ -60,7 +60,7 @@ def get_codepoints(f): yield Codepoint(codepoint, class_) prev_codepoint = codepoint - if class_first != None: + if class_first is not None: raise ValueError("Missing Last after First") for c in range(prev_codepoint + 1, NUM_CODEPOINTS): From 2d168fa74174b6dd02b718b90289bd79c6edf3ff Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 6 Sep 2019 10:35:14 +0200 Subject: [PATCH 534/618] mir borrowck: drive-by cleanup. --- src/librustc_mir/borrow_check/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 8ded539e7205a..5c397ff3019db 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -164,8 +164,8 @@ fn do_mir_borrowck<'a, 'tcx>( }; let mdpe = MoveDataParamEnv { - move_data: move_data, - param_env: param_env, + move_data, + param_env, }; let dead_unwinds = BitSet::new_empty(body.basic_blocks().len()); From 055409538d601e905d72a08dd6c28256587fba3d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 6 Sep 2019 10:39:38 +0200 Subject: [PATCH 535/618] Refuse to downgrade NLL errors on Rust >= 2018. --- src/librustc_mir/borrow_check/mod.rs | 5 ++++- .../borrowck/borrowck-migrate-to-nll.edition.stderr | 13 ++++++------- src/test/ui/borrowck/borrowck-migrate-to-nll.rs | 4 +++- .../borrowck/borrowck-migrate-to-nll.zflag.stderr | 4 ++-- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 5c397ff3019db..9ad7cbc478bb0 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -259,7 +259,10 @@ fn do_mir_borrowck<'a, 'tcx>( move_error_reported: BTreeMap::new(), uninitialized_error_reported: Default::default(), errors_buffer, - disable_error_downgrading: false, + // Only downgrade errors on Rust 2015 and refuse to do so on Rust 2018. + // FIXME(Centril): In Rust 1.40.0, refuse doing so on 2015 as well and + // proceed to throwing out the migration infrastructure. + disable_error_downgrading: body.span.rust_2018(), nonlexical_regioncx: regioncx, used_mut: Default::default(), used_mut_upvars: SmallVec::new(), diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr index a33a1d00a5786..58f2cadcc6573 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr @@ -1,15 +1,14 @@ -warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-migrate-to-nll.rs:28:21 +error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-migrate-to-nll.rs:29:21 | LL | let x = &mut block; | ---------- mutable borrow occurs here LL | let p: &'a u8 = &*block.current; | ^^^^^^^^^^^^^^^ immutable borrow occurs here -LL | // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes) +... LL | drop(x); | - mutable borrow later used here - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs index 6dda317e57efe..98fd5682277b3 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs @@ -4,6 +4,8 @@ // // Therefore, for backwards-compatiblity, under borrowck=migrate the // NLL checks will be emitted as *warnings*. +// +// In Rust 2018, no errors will be downgraded to warnings. // NLL mode makes this compile-fail; we cannot currently encode a // test that is run-pass or compile-fail based on compare-mode. So @@ -16,7 +18,6 @@ //[zflag]compile-flags: -Z borrowck=migrate //[edition]edition:2018 //[zflag] run-pass -//[edition] run-pass pub struct Block<'a> { current: &'a u8, @@ -26,6 +27,7 @@ pub struct Block<'a> { fn bump<'a>(mut block: &mut Block<'a>) { let x = &mut block; let p: &'a u8 = &*block.current; + //[edition]~^ ERROR cannot borrow `*block.current` as immutable // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes) drop(x); drop(p); diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr index a33a1d00a5786..ace336a3bf32a 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr @@ -1,11 +1,11 @@ warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-migrate-to-nll.rs:28:21 + --> $DIR/borrowck-migrate-to-nll.rs:29:21 | LL | let x = &mut block; | ---------- mutable borrow occurs here LL | let p: &'a u8 = &*block.current; | ^^^^^^^^^^^^^^^ immutable borrow occurs here -LL | // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes) +... LL | drop(x); | - mutable borrow later used here | From 39bfb3626c04fe03d50864e13a6baeed1c0378f4 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 6 Sep 2019 11:10:53 +0200 Subject: [PATCH 536/618] Fix miri --- src/librustc/mir/interpret/allocation.rs | 28 ++++++++++++++++++++++++ src/tools/miri | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index df1d9a987011d..13552a61acb0e 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -130,6 +130,34 @@ impl Allocation { } } +impl Allocation<()> { + /// Add Tag and Extra fields + pub fn retag( + self, + mut tagger: impl FnMut(AllocId) -> T, + extra: E, + ) -> Allocation { + Allocation { + bytes: self.bytes, + size: self.size, + relocations: Relocations::from_presorted( + self.relocations.iter() + // The allocations in the relocations (pointers stored *inside* this allocation) + // all get the base pointer tag. + .map(|&(offset, ((), alloc))| { + let tag = tagger(alloc); + (offset, (tag, alloc)) + }) + .collect() + ), + undef_mask: self.undef_mask, + align: self.align, + mutability: self.mutability, + extra, + } + } +} + /// Raw accessors. Provide access to otherwise private bytes. impl Allocation { pub fn len(&self) -> usize { diff --git a/src/tools/miri b/src/tools/miri index 69268fb75fdb4..e479ab26406ed 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 69268fb75fdb452296caa9bc4aaeff1674279de2 +Subproject commit e479ab26406ed8a473987e5f4a1f3be3e978e5d2 From 32101ad3b38d29291a5150840e88aeef2fb911a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Thu, 22 Aug 2019 12:28:03 +0200 Subject: [PATCH 537/618] Upgrade rand to 0.7 --- Cargo.lock | 13 +++++++------ src/librustc_incremental/Cargo.toml | 2 +- src/libstd/Cargo.toml | 2 +- src/libstd/fs.rs | 2 +- src/libstd/tests/env.rs | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 313fef1c086a8..43eb28168086a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1151,12 +1151,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.8" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34f33de6f0ae7c9cb5e574502a562e2b512799e32abb801cd1e79ad952b62b49" +checksum = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" dependencies = [ "cfg-if", "libc", + "wasi", ] [[package]] @@ -1583,9 +1584,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" -version = "0.2.61" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c665266eb592905e8503ba3403020f4b8794d26263f412ca33171600eca9a6fa" +checksum = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" dependencies = [ "rustc-std-workspace-core", ] @@ -3248,7 +3249,7 @@ version = "0.0.0" dependencies = [ "graphviz", "log", - "rand 0.6.1", + "rand 0.7.0", "rustc", "rustc_data_structures", "rustc_fs_util", @@ -3864,7 +3865,7 @@ dependencies = [ "panic_abort", "panic_unwind", "profiler_builtins", - "rand 0.6.1", + "rand 0.7.0", "rustc_asan", "rustc_lsan", "rustc_msan", diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml index a931ad3b66e21..659c4c89fe33c 100644 --- a/src/librustc_incremental/Cargo.toml +++ b/src/librustc_incremental/Cargo.toml @@ -12,7 +12,7 @@ doctest = false [dependencies] graphviz = { path = "../libgraphviz" } log = "0.4" -rand = "0.6" +rand = "0.7" rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_serialize = { path = "../libserialize", package = "serialize" } diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 18a46cf0b5257..a34ab598aed94 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -38,7 +38,7 @@ features = [ optional = true [dev-dependencies] -rand = "0.6.1" +rand = "0.7" [target.x86_64-apple-darwin.dependencies] rustc_asan = { path = "../librustc_asan" } diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 5f76875bd66c4..b14e02a2cb478 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -2144,7 +2144,7 @@ mod tests { use crate::sys_common::io::test::{TempDir, tmpdir}; use crate::thread; - use rand::{rngs::StdRng, FromEntropy, RngCore}; + use rand::{rngs::StdRng, RngCore, SeedableRng}; #[cfg(windows)] use crate::os::windows::fs::{symlink_dir, symlink_file}; diff --git a/src/libstd/tests/env.rs b/src/libstd/tests/env.rs index 06fb5533afdd8..f8014cb2ad9af 100644 --- a/src/libstd/tests/env.rs +++ b/src/libstd/tests/env.rs @@ -5,7 +5,7 @@ use rand::{thread_rng, Rng}; use rand::distributions::Alphanumeric; fn make_rand_name() -> OsString { - let mut rng = thread_rng(); + let rng = thread_rng(); let n = format!("TEST{}", rng.sample_iter(&Alphanumeric).take(10) .collect::()); let n = OsString::from(n); From 58ba1f51efab249411a932880e3c10d36355b166 Mon Sep 17 00:00:00 2001 From: Tim Vermeulen Date: Fri, 28 Jun 2019 14:43:32 +0200 Subject: [PATCH 538/618] Add Iterator comparison methods that take a comparison function --- src/libcore/iter/traits/iterator.rs | 109 ++++++++++++++++++++++++++-- src/libcore/tests/iter.rs | 56 ++++++++++++++ src/libcore/tests/lib.rs | 1 + 3 files changed, 160 insertions(+), 6 deletions(-) diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 8fd5fe0653eed..c09df3f7f22cb 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -2557,10 +2557,40 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().cmp([1].iter()), Ordering::Greater); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] - fn cmp(mut self, other: I) -> Ordering where + fn cmp(self, other: I) -> Ordering + where I: IntoIterator, Self::Item: Ord, Self: Sized, + { + self.cmp_by(other, |x, y| x.cmp(&y)) + } + + /// Lexicographically compares the elements of this `Iterator` with those + /// of another with respect to the specified comparison function. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_order_by)] + /// + /// use std::cmp::Ordering; + /// + /// let xs = [1, 2, 3, 4]; + /// let ys = [1, 4, 9, 16]; + /// + /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| x.cmp(&y)), Ordering::Less); + /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (x * x).cmp(&y)), Ordering::Equal); + /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater); + /// ``` + #[unstable(feature = "iter_order_by", issue = "0")] + fn cmp_by(mut self, other: I, mut cmp: F) -> Ordering + where + Self: Sized, + I: IntoIterator, + F: FnMut(Self::Item, I::Item) -> Ordering, { let mut other = other.into_iter(); @@ -2579,7 +2609,7 @@ pub trait Iterator { Some(val) => val, }; - match x.cmp(&y) { + match cmp(x, y) { Ordering::Equal => (), non_eq => return non_eq, } @@ -2601,10 +2631,49 @@ pub trait Iterator { /// assert_eq!([std::f64::NAN].iter().partial_cmp([1.].iter()), None); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] - fn partial_cmp(mut self, other: I) -> Option where + fn partial_cmp(self, other: I) -> Option + where I: IntoIterator, Self::Item: PartialOrd, Self: Sized, + { + self.partial_cmp_by(other, |x, y| x.partial_cmp(&y)) + } + + /// Lexicographically compares the elements of this `Iterator` with those + /// of another with respect to the specified comparison function. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_order_by)] + /// + /// use std::cmp::Ordering; + /// + /// let xs = [1.0, 2.0, 3.0, 4.0]; + /// let ys = [1.0, 4.0, 9.0, 16.0]; + /// + /// assert_eq!( + /// xs.iter().partial_cmp_by(&ys, |&x, &y| x.partial_cmp(&y)), + /// Some(Ordering::Less) + /// ); + /// assert_eq!( + /// xs.iter().partial_cmp_by(&ys, |&x, &y| (x * x).partial_cmp(&y)), + /// Some(Ordering::Equal) + /// ); + /// assert_eq!( + /// xs.iter().partial_cmp_by(&ys, |&x, &y| (2.0 * x).partial_cmp(&y)), + /// Some(Ordering::Greater) + /// ); + /// ``` + #[unstable(feature = "iter_order_by", issue = "0")] + fn partial_cmp_by(mut self, other: I, mut partial_cmp: F) -> Option + where + Self: Sized, + I: IntoIterator, + F: FnMut(Self::Item, I::Item) -> Option, { let mut other = other.into_iter(); @@ -2623,7 +2692,7 @@ pub trait Iterator { Some(val) => val, }; - match x.partial_cmp(&y) { + match partial_cmp(x, y) { Some(Ordering::Equal) => (), non_eq => return non_eq, } @@ -2640,10 +2709,36 @@ pub trait Iterator { /// assert_eq!([1].iter().eq([1, 2].iter()), false); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] - fn eq(mut self, other: I) -> bool where + fn eq(self, other: I) -> bool + where I: IntoIterator, Self::Item: PartialEq, Self: Sized, + { + self.eq_by(other, |x, y| x == y) + } + + /// Determines if the elements of this `Iterator` are equal to those of + /// another with respect to the specified equality function. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_order_by)] + /// + /// let xs = [1, 2, 3, 4]; + /// let ys = [1, 4, 9, 16]; + /// + /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y)); + /// ``` + #[unstable(feature = "iter_order_by", issue = "0")] + fn eq_by(mut self, other: I, mut eq: F) -> bool + where + Self: Sized, + I: IntoIterator, + F: FnMut(Self::Item, I::Item) -> bool, { let mut other = other.into_iter(); @@ -2658,7 +2753,9 @@ pub trait Iterator { Some(val) => val, }; - if x != y { return false } + if !eq(x, y) { + return false; + } } } diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 8e0658d87c1fb..d7088cf891f77 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -57,6 +57,62 @@ fn test_multi_iter() { assert!(xs.iter().lt(xs.iter().skip(2))); } +#[test] +fn test_cmp_by() { + use core::cmp::Ordering; + + let f = |x: i32, y: i32| (x * x).cmp(&y); + let xs = || [1, 2, 3, 4].iter().copied(); + let ys = || [1, 4, 16].iter().copied(); + + assert_eq!(xs().cmp_by(ys(), f), Ordering::Less); + assert_eq!(ys().cmp_by(xs(), f), Ordering::Greater); + assert_eq!(xs().cmp_by(xs().map(|x| x * x), f), Ordering::Equal); + assert_eq!(xs().rev().cmp_by(ys().rev(), f), Ordering::Greater); + assert_eq!(xs().cmp_by(ys().rev(), f), Ordering::Less); + assert_eq!(xs().cmp_by(ys().take(2), f), Ordering::Greater); +} + +#[test] +fn test_partial_cmp_by() { + use core::cmp::Ordering; + use core::f64; + + let f = |x: i32, y: i32| (x * x).partial_cmp(&y); + let xs = || [1, 2, 3, 4].iter().copied(); + let ys = || [1, 4, 16].iter().copied(); + + assert_eq!(xs().partial_cmp_by(ys(), f), Some(Ordering::Less)); + assert_eq!(ys().partial_cmp_by(xs(), f), Some(Ordering::Greater)); + assert_eq!(xs().partial_cmp_by(xs().map(|x| x * x), f), Some(Ordering::Equal)); + assert_eq!(xs().rev().partial_cmp_by(ys().rev(), f), Some(Ordering::Greater)); + assert_eq!(xs().partial_cmp_by(xs().rev(), f), Some(Ordering::Less)); + assert_eq!(xs().partial_cmp_by(ys().take(2), f), Some(Ordering::Greater)); + + let f = |x: f64, y: f64| (x * x).partial_cmp(&y); + let xs = || [1.0, 2.0, 3.0, 4.0].iter().copied(); + let ys = || [1.0, 4.0, f64::NAN, 16.0].iter().copied(); + + assert_eq!(xs().partial_cmp_by(ys(), f), None); + assert_eq!(ys().partial_cmp_by(xs(), f), Some(Ordering::Greater)); +} + +#[test] +fn test_eq_by() { + let f = |x: i32, y: i32| x * x == y; + let xs = || [1, 2, 3, 4].iter().copied(); + let ys = || [1, 4, 9, 16].iter().copied(); + + assert!(xs().eq_by(ys(), f)); + assert!(!ys().eq_by(xs(), f)); + assert!(!xs().eq_by(xs(), f)); + assert!(!ys().eq_by(ys(), f)); + + assert!(!xs().take(3).eq_by(ys(), f)); + assert!(!xs().eq_by(ys().take(3), f)); + assert!(xs().take(3).eq_by(ys().take(3), f)); +} + #[test] fn test_counter_from_iter() { let it = (0..).step_by(5).take(10); diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index a3b108b2e9cea..3b4e47438e10a 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -32,6 +32,7 @@ #![feature(const_fn)] #![feature(iter_partition_in_place)] #![feature(iter_is_partitioned)] +#![feature(iter_order_by)] extern crate test; From eedf555d0c041caa0a9e7c8cd4394716e637feaf Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 4 Sep 2019 15:21:46 +0300 Subject: [PATCH 539/618] rustc_codegen_llvm: give names to non-alloca variable values. --- src/librustc_codegen_llvm/debuginfo/mod.rs | 35 ++++++++++++++++++-- src/librustc_codegen_llvm/llvm/ffi.rs | 2 ++ src/librustc_codegen_ssa/mir/mod.rs | 16 ++++----- src/librustc_codegen_ssa/mir/statement.rs | 16 ++++++++- src/librustc_codegen_ssa/traits/debuginfo.rs | 2 +- src/test/codegen/var-names.rs | 15 +++++++++ 6 files changed, 73 insertions(+), 13 deletions(-) create mode 100644 src/test/codegen/var-names.rs diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index cad2bcdc05fc9..6dedf10f0ab83 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -32,7 +32,7 @@ use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, MirDebugScope, Variable use libc::c_uint; use std::cell::RefCell; -use std::ffi::CString; +use std::ffi::{CStr, CString}; use syntax_pos::{self, Span, Pos}; use syntax::ast; @@ -224,8 +224,37 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { gdb::insert_reference_to_gdb_debug_scripts_section_global(self) } - fn set_value_name(&mut self, value: &'ll Value, name: &str) { - let cname = SmallCStr::new(name); + fn set_var_name(&mut self, value: &'ll Value, name: impl ToString) { + // Avoid wasting time if LLVM value names aren't even enabled. + if self.sess().fewer_names() { + return; + } + + // Only function parameters and instructions are local to a function, + // don't change the name of anything else (e.g. globals). + let param_or_inst = unsafe { + llvm::LLVMIsAArgument(value).is_some() || + llvm::LLVMIsAInstruction(value).is_some() + }; + if !param_or_inst { + return; + } + + let old_name = unsafe { + CStr::from_ptr(llvm::LLVMGetValueName(value)) + }; + match old_name.to_str() { + Ok("") => {} + Ok(_) => { + // Avoid replacing the name if it already exists. + // While we could combine the names somehow, it'd + // get noisy quick, and the usefulness is dubious. + return; + } + Err(_) => return, + } + + let cname = CString::new(name.to_string()).unwrap(); unsafe { llvm::LLVMSetValueName(value, cname.as_ptr()); } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 9f9410560e373..b07214fdc03f3 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -806,6 +806,7 @@ extern "C" { pub fn LLVMRustRemoveFunctionAttributes(Fn: &Value, index: c_uint, attr: Attribute); // Operations on parameters + pub fn LLVMIsAArgument(Val: &Value) -> Option<&Value>; pub fn LLVMCountParams(Fn: &Value) -> c_uint; pub fn LLVMGetParam(Fn: &Value, Index: c_uint) -> &Value; @@ -818,6 +819,7 @@ extern "C" { pub fn LLVMDeleteBasicBlock(BB: &BasicBlock); // Operations on instructions + pub fn LLVMIsAInstruction(Val: &Value) -> Option<&Value>; pub fn LLVMGetFirstBasicBlock(Fn: &Value) -> &BasicBlock; // Operations on call sites diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 8acb3ba06267e..00e9ca01f4dd2 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -518,19 +518,19 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( PassMode::Ignore(IgnoreMode::CVarArgs) => {} PassMode::Direct(_) => { let llarg = bx.get_param(llarg_idx); - bx.set_value_name(llarg, &name); + bx.set_var_name(llarg, &name); llarg_idx += 1; return local( OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout)); } PassMode::Pair(..) => { - let a = bx.get_param(llarg_idx); - bx.set_value_name(a, &(name.clone() + ".0")); - llarg_idx += 1; + let (a, b) = (bx.get_param(llarg_idx), bx.get_param(llarg_idx + 1)); + llarg_idx += 2; - let b = bx.get_param(llarg_idx); - bx.set_value_name(b, &(name + ".1")); - llarg_idx += 1; + // FIXME(eddyb) these are scalar components, + // maybe extract the high-level fields? + bx.set_var_name(a, format_args!("{}.0", name)); + bx.set_var_name(b, format_args!("{}.1", name)); return local(OperandRef { val: OperandValue::Pair(a, b), @@ -546,7 +546,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // already put it in a temporary alloca and gave it up. // FIXME: lifetimes let llarg = bx.get_param(llarg_idx); - bx.set_value_name(llarg, &name); + bx.set_var_name(llarg, &name); llarg_idx += 1; PlaceRef::new_sized(llarg, arg.layout) } else if arg.is_unsized_indirect() { diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs index 3617f3afaae41..594f45c833758 100644 --- a/src/librustc_codegen_ssa/mir/statement.rs +++ b/src/librustc_codegen_ssa/mir/statement.rs @@ -29,7 +29,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_rvalue_unsized(bx, cg_indirect_dest, rvalue) } LocalRef::Operand(None) => { - let (bx, operand) = self.codegen_rvalue_operand(bx, rvalue); + let (mut bx, operand) = self.codegen_rvalue_operand(bx, rvalue); + if let Some(name) = self.mir.local_decls[index].name { + match operand.val { + OperandValue::Ref(x, ..) | + OperandValue::Immediate(x) => { + bx.set_var_name(x, name); + } + OperandValue::Pair(a, b) => { + // FIXME(eddyb) these are scalar components, + // maybe extract the high-level fields? + bx.set_var_name(a, format_args!("{}.0", name)); + bx.set_var_name(b, format_args!("{}.1", name)); + } + } + } self.locals[index] = LocalRef::Operand(Some(operand)); bx } diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs index be2fa7279aa7c..9c16b864ef21d 100644 --- a/src/librustc_codegen_ssa/traits/debuginfo.rs +++ b/src/librustc_codegen_ssa/traits/debuginfo.rs @@ -57,5 +57,5 @@ pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes { span: Span, ); fn insert_reference_to_gdb_debug_scripts_section_global(&mut self); - fn set_value_name(&mut self, value: Self::Value, name: &str); + fn set_var_name(&mut self, value: Self::Value, name: impl ToString); } diff --git a/src/test/codegen/var-names.rs b/src/test/codegen/var-names.rs new file mode 100644 index 0000000000000..3140a7c6b6cc2 --- /dev/null +++ b/src/test/codegen/var-names.rs @@ -0,0 +1,15 @@ +// compile-flags: -O -C no-prepopulate-passes + +#![crate_type = "lib"] + +// CHECK-LABEL: define i32 @test(i32 %a, i32 %b) +#[no_mangle] +pub fn test(a: u32, b: u32) -> u32 { + let c = a + b; + // CHECK: %c = add i32 %a, %b + let d = c; + let e = d * a; + // CHECK-NEXT: %e = mul i32 %c, %a + e + // CHECK-NEXT: ret i32 %e +} From e1d27eb73cc2f318157f744d8175e1ef0340ff52 Mon Sep 17 00:00:00 2001 From: Shiqing Date: Sat, 7 Sep 2019 00:16:11 +0800 Subject: [PATCH 540/618] Reduce span to function name in unreachable calls --- src/librustc_typeck/check/expr.rs | 4 ++++ src/test/ui/never-assign-dead-code.stderr | 4 ++-- src/test/ui/reachable/expr_call.stderr | 4 ++-- src/test/ui/reachable/expr_method.stderr | 6 +++--- src/test/ui/unreachable/unreachable-in-call.rs | 2 +- src/test/ui/unreachable/unreachable-in-call.stderr | 8 +++----- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 9644815f805d9..da72dfd155182 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -161,6 +161,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Warn for non-block expressions with diverging children. match expr.node { ExprKind::Block(..) | ExprKind::Loop(..) | ExprKind::Match(..) => {}, + ExprKind::Call(ref callee, _) => + self.warn_if_unreachable(expr.hir_id, callee.span, "call"), + ExprKind::MethodCall(_, ref span, _) => + self.warn_if_unreachable(expr.hir_id, *span, "call"), _ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"), } diff --git a/src/test/ui/never-assign-dead-code.stderr b/src/test/ui/never-assign-dead-code.stderr index 779780a90a81d..b1b5bf03fe52a 100644 --- a/src/test/ui/never-assign-dead-code.stderr +++ b/src/test/ui/never-assign-dead-code.stderr @@ -11,11 +11,11 @@ LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]` -warning: unreachable expression +warning: unreachable call --> $DIR/never-assign-dead-code.rs:10:5 | LL | drop(x); - | ^^^^^^^ + | ^^^^ warning: unused variable: `x` --> $DIR/never-assign-dead-code.rs:9:9 diff --git a/src/test/ui/reachable/expr_call.stderr b/src/test/ui/reachable/expr_call.stderr index df5cff16f9a46..f2db17e4dfe8e 100644 --- a/src/test/ui/reachable/expr_call.stderr +++ b/src/test/ui/reachable/expr_call.stderr @@ -10,11 +10,11 @@ note: lint level defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: unreachable expression +error: unreachable call --> $DIR/expr_call.rs:18:5 | LL | bar(return); - | ^^^^^^^^^^^ + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_method.stderr b/src/test/ui/reachable/expr_method.stderr index bbfa2ef529add..947ea0fee889c 100644 --- a/src/test/ui/reachable/expr_method.stderr +++ b/src/test/ui/reachable/expr_method.stderr @@ -10,11 +10,11 @@ note: lint level defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: unreachable expression - --> $DIR/expr_method.rs:21:5 +error: unreachable call + --> $DIR/expr_method.rs:21:9 | LL | Foo.bar(return); - | ^^^^^^^^^^^^^^^ + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/unreachable/unreachable-in-call.rs b/src/test/ui/unreachable/unreachable-in-call.rs index 25f849d7a0a91..dd94e79f4d84c 100644 --- a/src/test/ui/unreachable/unreachable-in-call.rs +++ b/src/test/ui/unreachable/unreachable-in-call.rs @@ -14,7 +14,7 @@ fn diverge_first() { get_u8()); //~ ERROR unreachable expression } fn diverge_second() { - call( //~ ERROR unreachable expression + call( //~ ERROR unreachable call get_u8(), diverge()); } diff --git a/src/test/ui/unreachable/unreachable-in-call.stderr b/src/test/ui/unreachable/unreachable-in-call.stderr index f8dd54590f6ae..c740011c4a125 100644 --- a/src/test/ui/unreachable/unreachable-in-call.stderr +++ b/src/test/ui/unreachable/unreachable-in-call.stderr @@ -10,13 +10,11 @@ note: lint level defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: unreachable expression +error: unreachable call --> $DIR/unreachable-in-call.rs:17:5 | -LL | / call( -LL | | get_u8(), -LL | | diverge()); - | |__________________^ +LL | call( + | ^^^^ error: aborting due to 2 previous errors From 10f46b69bc32bd1cb5f013ce904957aeb28603bb Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 6 Sep 2019 18:02:12 +0100 Subject: [PATCH 541/618] Move the HIR cfg to `rustc_ast_borrowck` No new code should be using it. --- src/librustc/lib.rs | 1 - src/librustc_ast_borrowck/borrowck/mod.rs | 2 +- .../borrowck/move_data.rs | 2 +- .../cfg/construct.rs | 12 +++---- .../cfg/graphviz.rs | 11 +++---- .../cfg/mod.rs | 31 ++++++++----------- src/librustc_ast_borrowck/dataflow.rs | 5 ++- src/librustc_ast_borrowck/graphviz.rs | 7 ++--- src/librustc_ast_borrowck/lib.rs | 1 + src/librustc_driver/pretty.rs | 3 +- 10 files changed, 32 insertions(+), 43 deletions(-) rename src/{librustc => librustc_ast_borrowck}/cfg/construct.rs (98%) rename src/{librustc => librustc_ast_borrowck}/cfg/graphviz.rs (94%) rename src/{librustc => librustc_ast_borrowck}/cfg/mod.rs (51%) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 368f5bb64fe6c..bf4330a29a7df 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -97,7 +97,6 @@ pub mod query; #[macro_use] pub mod arena; -pub mod cfg; pub mod dep_graph; pub mod hir; pub mod ich; diff --git a/src/librustc_ast_borrowck/borrowck/mod.rs b/src/librustc_ast_borrowck/borrowck/mod.rs index 3bbd7ae5c352f..23d5480c60562 100644 --- a/src/librustc_ast_borrowck/borrowck/mod.rs +++ b/src/librustc_ast_borrowck/borrowck/mod.rs @@ -9,7 +9,6 @@ use InteriorKind::*; use rustc::hir::HirId; use rustc::hir::Node; -use rustc::cfg; use rustc::middle::borrowck::{BorrowCheckResult, SignalledError}; use rustc::hir::def_id::{DefId, LocalDefId}; use rustc::middle::mem_categorization as mc; @@ -28,6 +27,7 @@ use log::debug; use rustc::hir; +use crate::cfg; use crate::dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom}; pub mod check_loans; diff --git a/src/librustc_ast_borrowck/borrowck/move_data.rs b/src/librustc_ast_borrowck/borrowck/move_data.rs index 887a0e2f20e16..67d818161b1b5 100644 --- a/src/librustc_ast_borrowck/borrowck/move_data.rs +++ b/src/librustc_ast_borrowck/borrowck/move_data.rs @@ -4,7 +4,7 @@ use crate::dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom}; use crate::borrowck::*; -use rustc::cfg; +use crate::cfg; use rustc::ty::{self, TyCtxt}; use rustc::util::nodemap::FxHashMap; diff --git a/src/librustc/cfg/construct.rs b/src/librustc_ast_borrowck/cfg/construct.rs similarity index 98% rename from src/librustc/cfg/construct.rs rename to src/librustc_ast_borrowck/cfg/construct.rs index 0dad2dda837b5..339d92145c64f 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc_ast_borrowck/cfg/construct.rs @@ -1,11 +1,11 @@ use crate::cfg::*; -use crate::middle::region; use rustc_data_structures::graph::implementation as graph; -use crate::ty::{self, TyCtxt}; +use rustc::middle::region; +use rustc::ty::{self, TyCtxt}; -use crate::hir::{self, PatKind}; -use crate::hir::def_id::DefId; -use crate::hir::ptr::P; +use rustc::hir::{self, PatKind}; +use rustc::hir::def_id::DefId; +use rustc::hir::ptr::P; struct CFGBuilder<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -30,7 +30,7 @@ struct LoopScope { break_index: CFGIndex, // where to go on a `break` } -pub fn construct(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG { +pub(super) fn construct(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG { let mut graph = graph::Graph::new(); let entry = graph.add_node(CFGNodeData::Entry); diff --git a/src/librustc/cfg/graphviz.rs b/src/librustc_ast_borrowck/cfg/graphviz.rs similarity index 94% rename from src/librustc/cfg/graphviz.rs rename to src/librustc_ast_borrowck/cfg/graphviz.rs index 918120057d4d3..46409f1a1cebf 100644 --- a/src/librustc/cfg/graphviz.rs +++ b/src/librustc_ast_borrowck/cfg/graphviz.rs @@ -1,15 +1,12 @@ /// This module provides linkage between rustc::middle::graph and /// libgraphviz traits. -// For clarity, rename the graphviz crate locally to dot. -use graphviz as dot; - use crate::cfg; -use crate::hir; -use crate::ty::TyCtxt; +use rustc::hir; +use rustc::ty::TyCtxt; -pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode); -pub type Edge<'a> = &'a cfg::CFGEdge; +pub(crate) type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode); +pub(crate) type Edge<'a> = &'a cfg::CFGEdge; pub struct LabelledCFG<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, diff --git a/src/librustc/cfg/mod.rs b/src/librustc_ast_borrowck/cfg/mod.rs similarity index 51% rename from src/librustc/cfg/mod.rs rename to src/librustc_ast_borrowck/cfg/mod.rs index 88fc7fbfad51f..981199c91d513 100644 --- a/src/librustc/cfg/mod.rs +++ b/src/librustc_ast_borrowck/cfg/mod.rs @@ -2,18 +2,18 @@ //! Uses `Graph` as the underlying representation. use rustc_data_structures::graph::implementation as graph; -use crate::ty::TyCtxt; -use crate::hir; -use crate::hir::def_id::DefId; +use rustc::ty::TyCtxt; +use rustc::hir; +use rustc::hir::def_id::DefId; mod construct; pub mod graphviz; pub struct CFG { - pub owner_def_id: DefId, - pub graph: CFGGraph, - pub entry: CFGIndex, - pub exit: CFGIndex, + owner_def_id: DefId, + pub(crate) graph: CFGGraph, + pub(crate) entry: CFGIndex, + exit: CFGIndex, } #[derive(Copy, Clone, Debug, PartialEq)] @@ -26,7 +26,7 @@ pub enum CFGNodeData { } impl CFGNodeData { - pub fn id(&self) -> hir::ItemLocalId { + pub(crate) fn id(&self) -> hir::ItemLocalId { if let CFGNodeData::AST(id) = *self { id } else { @@ -37,24 +37,19 @@ impl CFGNodeData { #[derive(Debug)] pub struct CFGEdgeData { - pub exiting_scopes: Vec + pub(crate) exiting_scopes: Vec } -pub type CFGIndex = graph::NodeIndex; +pub(crate) type CFGIndex = graph::NodeIndex; -pub type CFGGraph = graph::Graph; +pub(crate) type CFGGraph = graph::Graph; -pub type CFGNode = graph::Node; +pub(crate) type CFGNode = graph::Node; -pub type CFGEdge = graph::Edge; +pub(crate) type CFGEdge = graph::Edge; impl CFG { pub fn new(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG { construct::construct(tcx, body) } - - pub fn node_is_reachable(&self, id: hir::ItemLocalId) -> bool { - self.graph.depth_traverse(self.entry, graph::OUTGOING) - .any(|idx| self.graph.node_data(idx).id() == id) - } } diff --git a/src/librustc_ast_borrowck/dataflow.rs b/src/librustc_ast_borrowck/dataflow.rs index 3a4c8c924764e..a8562901d99c5 100644 --- a/src/librustc_ast_borrowck/dataflow.rs +++ b/src/librustc_ast_borrowck/dataflow.rs @@ -3,9 +3,7 @@ //! and thus uses bitvectors. Your job is simply to specify the so-called //! GEN and KILL bits for each expression. -use rustc::cfg; -use rustc::cfg::CFGIndex; -use rustc::ty::TyCtxt; +use crate::cfg::{self, CFGIndex}; use std::mem; use std::usize; use log::debug; @@ -16,6 +14,7 @@ use rustc::util::nodemap::FxHashMap; use rustc::hir; use rustc::hir::intravisit; use rustc::hir::print as pprust; +use rustc::ty::TyCtxt; #[derive(Copy, Clone, Debug)] pub enum EntryOrExit { diff --git a/src/librustc_ast_borrowck/graphviz.rs b/src/librustc_ast_borrowck/graphviz.rs index 7a8a23ca76afc..c077dc828aba2 100644 --- a/src/librustc_ast_borrowck/graphviz.rs +++ b/src/librustc_ast_borrowck/graphviz.rs @@ -4,13 +4,12 @@ pub use Variant::*; -pub use rustc::cfg::graphviz::{Node, Edge}; -use rustc::cfg::graphviz as cfg_dot; - +pub(crate) use crate::cfg::graphviz::{Node, Edge}; +use crate::cfg::graphviz as cfg_dot; +use crate::cfg::CFGIndex; use crate::borrowck::{self, BorrowckCtxt, LoanPath}; use crate::dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit}; use log::debug; -use rustc::cfg::CFGIndex; use std::rc::Rc; #[derive(Debug, Copy, Clone)] diff --git a/src/librustc_ast_borrowck/lib.rs b/src/librustc_ast_borrowck/lib.rs index dc818278a4b74..aea97fea1a9fd 100644 --- a/src/librustc_ast_borrowck/lib.rs +++ b/src/librustc_ast_borrowck/lib.rs @@ -18,5 +18,6 @@ mod borrowck; pub mod graphviz; mod dataflow; +pub mod cfg; pub use borrowck::provide; diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index cb17401f6247b..c4d3ad946f9f6 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -1,7 +1,5 @@ //! The various pretty-printing routines. -use rustc::cfg; -use rustc::cfg::graphviz::LabelledCFG; use rustc::hir; use rustc::hir::map as hir_map; use rustc::hir::map::blocks; @@ -14,6 +12,7 @@ use rustc::util::common::ErrorReported; use rustc_interface::util::ReplaceBodyWithLoop; use rustc_ast_borrowck as borrowck; use rustc_ast_borrowck::graphviz as borrowck_dot; +use rustc_ast_borrowck::cfg::{self, graphviz::LabelledCFG}; use rustc_mir::util::{write_mir_pretty, write_mir_graphviz}; use syntax::ast; From 8ddbe7660fa6297193fe81e50f5d342a16cb06b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Thu, 29 Aug 2019 13:22:21 +0200 Subject: [PATCH 542/618] Upgrade env_logger to 0.6 --- Cargo.lock | 36 +++++++++++--------------------- src/librustc_driver/Cargo.toml | 2 +- src/tools/compiletest/Cargo.toml | 2 +- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 313fef1c086a8..c9f2092eb5236 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -277,7 +277,7 @@ dependencies = [ "crypto-hash", "curl", "curl-sys", - "env_logger 0.6.0", + "env_logger", "failure", "filetime", "flate2", @@ -507,7 +507,7 @@ name = "compiletest" version = "0.0.0" dependencies = [ "diff", - "env_logger 0.5.13", + "env_logger", "getopts", "lazy_static 1.3.0", "libc", @@ -909,21 +909,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" -dependencies = [ - "atty", - "humantime", - "log", - "termcolor", -] - -[[package]] -name = "env_logger" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" +checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" dependencies = [ "atty", "humantime", @@ -1774,7 +1762,7 @@ dependencies = [ "chrono", "clap", "elasticlunr-rs", - "env_logger 0.6.0", + "env_logger", "error-chain", "handlebars", "itertools 0.8.0", @@ -1799,7 +1787,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77d1f0ba4d1e6b86fa18e8853d026d7d76a97eb7eb5eb052ed80901e43b7fc10" dependencies = [ - "env_logger 0.6.0", + "env_logger", "failure", "log", "mdbook", @@ -1992,7 +1980,7 @@ dependencies = [ "colored", "compiletest_rs", "directories", - "env_logger 0.6.0", + "env_logger", "getrandom", "hex", "log", @@ -2363,7 +2351,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" dependencies = [ "chrono", - "env_logger 0.6.0", + "env_logger", "log", ] @@ -2440,7 +2428,7 @@ dependencies = [ "bitflags", "clap", "derive_more", - "env_logger 0.6.0", + "env_logger", "humantime", "lazy_static 1.3.0", "log", @@ -2734,7 +2722,7 @@ dependencies = [ "clippy_lints", "crossbeam-channel", "difference", - "env_logger 0.6.0", + "env_logger", "failure", "futures", "heck", @@ -3203,7 +3191,7 @@ dependencies = [ name = "rustc_driver" version = "0.0.0" dependencies = [ - "env_logger 0.5.13", + "env_logger", "graphviz", "log", "rustc", @@ -3590,7 +3578,7 @@ dependencies = [ "derive-new", "diff", "dirs", - "env_logger 0.6.0", + "env_logger", "failure", "getopts", "ignore", diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index b030517e28ec2..a839ee56b2b6e 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["dylib"] [dependencies] graphviz = { path = "../libgraphviz" } log = "0.4" -env_logger = { version = "0.5", default-features = false } +env_logger = { version = "0.6", default-features = false } rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } rustc_ast_borrowck = { path = "../librustc_ast_borrowck" } diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index e759ad1f35dde..745233c151cd6 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] diff = "0.1.10" -env_logger = { version = "0.5", default-features = false } +env_logger = { version = "0.6", default-features = false } getopts = "0.2" log = "0.4" regex = "1.0" From f6481ed1c31d2a3c43fab73e58901f7c25360fcb Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 6 Sep 2019 19:21:20 +0100 Subject: [PATCH 543/618] Correct pluralisation of various diagnostic messages --- src/librustc/ty/error.rs | 4 +++- src/librustc_typeck/check/pat.rs | 33 +++++++++++++++++++++--------- src/libsyntax/ext/tt/transcribe.rs | 9 ++++++-- src/libsyntax_ext/format.rs | 2 +- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index fe8f94ab1d314..f67526ea4a1d9 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -200,7 +200,9 @@ impl<'tcx> ty::TyS<'tcx> { ty::Array(_, n) => { let n = tcx.lift_to_global(&n).unwrap(); match n.try_eval_usize(tcx, ty::ParamEnv::empty()) { - Some(n) => format!("array of {} elements", n).into(), + Some(n) => { + format!("array of {} element{}", n, if n != 1 { "s" } else { "" }).into() + } None => "array".into(), } } diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 24d0659391b04..8502b89de1469 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1098,22 +1098,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) { struct_span_err!( - self.tcx.sess, span, E0527, - "pattern requires {} elements but array has {}", - min_len, size + self.tcx.sess, + span, + E0527, + "pattern requires {} element{} but array has {}", + min_len, + if min_len != 1 { "s" } else { "" }, + size, ) - .span_label(span, format!("expected {} elements", size)) + .span_label(span, format!("expected {} element{}", size, if size != 1 { "s" } else { "" })) .emit(); } fn error_scrutinee_with_rest_inconsistent_length(&self, span: Span, min_len: u64, size: u64) { struct_span_err!( - self.tcx.sess, span, E0528, - "pattern requires at least {} elements but array has {}", - min_len, size - ) - .span_label(span, format!("pattern cannot match array of {} elements", size)) - .emit(); + self.tcx.sess, + span, + E0528, + "pattern requires at least {} element{} but array has {}", + min_len, + if min_len != 1 { "s" } else { "" }, + size, + ).span_label( + span, + format!( + "pattern cannot match array of {} element{}", + size, + if size != 1 { "s" } else { "" }, + ), + ).emit(); } fn error_scrutinee_unfixed_length(&self, span: Span) { diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 30d5df13dcedb..23735727fe8cf 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -345,8 +345,13 @@ impl LockstepIterSize { LockstepIterSize::Constraint(r_len, _) if l_len == r_len => self, LockstepIterSize::Constraint(r_len, r_id) => { let msg = format!( - "meta-variable `{}` repeats {} times, but `{}` repeats {} times", - l_id, l_len, r_id, r_len + "meta-variable `{}` repeats {} time{}, but `{}` repeats {} time{}", + l_id, + l_len, + if l_len != 1 { "s" } else { "" }, + r_id, + r_len, + if r_len != 1 { "s" } else { "" }, ); LockstepIterSize::Contradiction(msg) } diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index e29f12c50c526..dec84c8286292 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -291,7 +291,7 @@ impl<'a, 'b> Context<'a, 'b> { &format!( "{} positional argument{} in format string, but {}", count, - if count > 1 { "s" } else { "" }, + if count != 1 { "s" } else { "" }, self.describe_num_args(), ), ); From 0b97726e6c524d2cc0de4c2f5b1284eca010a7b2 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 6 Sep 2019 19:21:26 +0100 Subject: [PATCH 544/618] Update ui tests --- src/test/ui/coercion/coercion-slice.rs | 2 +- src/test/ui/coercion/coercion-slice.stderr | 2 +- src/test/ui/issues/issue-15783.rs | 8 ++++---- src/test/ui/issues/issue-15783.stderr | 2 +- src/test/ui/match/match-vec-mismatch.stderr | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/ui/coercion/coercion-slice.rs b/src/test/ui/coercion/coercion-slice.rs index 312b634c9fd0b..b69edcf260637 100644 --- a/src/test/ui/coercion/coercion-slice.rs +++ b/src/test/ui/coercion/coercion-slice.rs @@ -4,5 +4,5 @@ fn main() { let _: &[i32] = [0]; //~^ ERROR mismatched types //~| expected type `&[i32]` - //~| expected &[i32], found array of 1 elements + //~| expected &[i32], found array of 1 element } diff --git a/src/test/ui/coercion/coercion-slice.stderr b/src/test/ui/coercion/coercion-slice.stderr index 6fa712371178b..ccd776e987938 100644 --- a/src/test/ui/coercion/coercion-slice.stderr +++ b/src/test/ui/coercion/coercion-slice.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let _: &[i32] = [0]; | ^^^ | | - | expected &[i32], found array of 1 elements + | expected &[i32], found array of 1 element | help: consider borrowing here: `&[0]` | = note: expected type `&[i32]` diff --git a/src/test/ui/issues/issue-15783.rs b/src/test/ui/issues/issue-15783.rs index 77eae914fa1ca..5189f550cfbd6 100644 --- a/src/test/ui/issues/issue-15783.rs +++ b/src/test/ui/issues/issue-15783.rs @@ -6,9 +6,9 @@ fn main() { let name = "Foo"; let x = Some(&[name]); let msg = foo(x); -//~^ ERROR mismatched types -//~| expected type `std::option::Option<&[&str]>` -//~| found type `std::option::Option<&[&str; 1]>` -//~| expected slice, found array of 1 elements + //~^ ERROR mismatched types + //~| expected type `std::option::Option<&[&str]>` + //~| found type `std::option::Option<&[&str; 1]>` + //~| expected slice, found array of 1 element assert_eq!(msg, 3); } diff --git a/src/test/ui/issues/issue-15783.stderr b/src/test/ui/issues/issue-15783.stderr index 595fe4025ad48..1d54b2830d6c5 100644 --- a/src/test/ui/issues/issue-15783.stderr +++ b/src/test/ui/issues/issue-15783.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-15783.rs:8:19 | LL | let msg = foo(x); - | ^ expected slice, found array of 1 elements + | ^ expected slice, found array of 1 element | = note: expected type `std::option::Option<&[&str]>` found type `std::option::Option<&[&str; 1]>` diff --git a/src/test/ui/match/match-vec-mismatch.stderr b/src/test/ui/match/match-vec-mismatch.stderr index 2f1bbb7621659..a3523bb689e6b 100644 --- a/src/test/ui/match/match-vec-mismatch.stderr +++ b/src/test/ui/match/match-vec-mismatch.stderr @@ -10,7 +10,7 @@ error[E0529]: expected an array or slice, found `std::string::String` LL | ['f', 'o', ..] => {} | ^^^^^^^^^^^^^^ pattern cannot match with input type `std::string::String` -error[E0527]: pattern requires 1 elements but array has 3 +error[E0527]: pattern requires 1 element but array has 3 --> $DIR/match-vec-mismatch.rs:20:9 | LL | [0] => {}, From 055d3798d40ca0eefa52fa152bf3c913240281af Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 31 Aug 2019 16:03:54 +0300 Subject: [PATCH 545/618] reduce visibility --- src/libsyntax/parse/parser.rs | 22 +++++++++++----------- src/libsyntax/util/parser.rs | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 49b05551bae86..ab5462baaf721 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -132,7 +132,7 @@ pub struct Parser<'a> { /// into modules, and sub-parsers have new values for this name. pub root_module_name: Option, crate expected_tokens: Vec, - crate token_cursor: TokenCursor, + token_cursor: TokenCursor, desugar_doc_comments: bool, /// `true` we should configure out of line modules as we parse. pub cfg_mods: bool, @@ -161,19 +161,19 @@ impl<'a> Drop for Parser<'a> { } #[derive(Clone)] -crate struct TokenCursor { - crate frame: TokenCursorFrame, - crate stack: Vec, +struct TokenCursor { + frame: TokenCursorFrame, + stack: Vec, } #[derive(Clone)] -crate struct TokenCursorFrame { - crate delim: token::DelimToken, - crate span: DelimSpan, - crate open_delim: bool, - crate tree_cursor: tokenstream::Cursor, - crate close_delim: bool, - crate last_token: LastToken, +struct TokenCursorFrame { + delim: token::DelimToken, + span: DelimSpan, + open_delim: bool, + tree_cursor: tokenstream::Cursor, + close_delim: bool, + last_token: LastToken, } /// This is used in `TokenCursorFrame` above to track tokens that are consumed diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index a501541c95909..fceaed360cdb4 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -69,7 +69,7 @@ pub enum Fixity { impl AssocOp { /// Creates a new AssocOP from a token - pub fn from_token(t: &Token) -> Option { + crate fn from_token(t: &Token) -> Option { use AssocOp::*; match t.kind { token::BinOpEq(k) => Some(AssignOp(k)), From a26ee8586c150e786ffaa47fba06ebcc671373d1 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Fri, 6 Sep 2019 12:41:54 -0700 Subject: [PATCH 546/618] Include compiler-rt in the source tarball In #60981 we switched to using src/llvm-project/compiler-rt inside compiler-builtins rather than a separate copy of it. In order to have the "c" feature turn on in builds from the source tarball, we need to include that path in its creation. fixes #64239 --- src/bootstrap/dist.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 0f4ac63651ca9..500d5766a899e 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -808,6 +808,7 @@ fn copy_src_dirs(builder: &Builder<'_>, src_dirs: &[&str], exclude_dirs: &[&str] "llvm-project/lld", "llvm-project\\lld", "llvm-project/lldb", "llvm-project\\lldb", "llvm-project/llvm", "llvm-project\\llvm", + "llvm-project/compiler-rt", "llvm-project\\compiler-rt", ]; if spath.contains("llvm-project") && !spath.ends_with("llvm-project") && !LLVM_PROJECTS.iter().any(|path| spath.contains(path)) From 7dd5c661081b12de72e5a869b9c80131f7a6b464 Mon Sep 17 00:00:00 2001 From: Aditya Atluri Date: Fri, 6 Sep 2019 12:54:42 -0700 Subject: [PATCH 547/618] Added more prereqs and note about default directory --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 724bc36ecc6fb..4c2e4eef6552f 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ or reading the [rustc guide][rustcguidebuild]. * `cmake` 3.4.3 or later * `curl` * `git` + * `ssl` which comes in `libssl-dev` or `openssl-devel` 2. Clone the [source] with `git`: @@ -56,6 +57,8 @@ or reading the [rustc guide][rustcguidebuild]. an installation (using `./x.py install`) that you set the `prefix` value in the `[install]` section to a directory that you have write permissions. + Create install directory if you are not installing in default directory + 4. Build and install: ```sh From 3dde650efa3a8910cccaef38e89fe74272d67c91 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 6 Sep 2019 23:41:54 +0300 Subject: [PATCH 548/618] Move injection of attributes from command line to `libsyntax_ext` --- src/librustc_interface/passes.rs | 4 +- src/libsyntax/attr/mod.rs | 59 +++++++----------------------- src/libsyntax/parse/attr.rs | 2 +- src/libsyntax_ext/cmdline_attrs.rs | 30 +++++++++++++++ src/libsyntax_ext/lib.rs | 1 + 5 files changed, 48 insertions(+), 48 deletions(-) create mode 100644 src/libsyntax_ext/cmdline_attrs.rs diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 24b44964e4fd2..08ae3360eb94f 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -230,7 +230,9 @@ pub fn register_plugins<'a>( crate_name: &str, ) -> Result<(ast::Crate, PluginInfo)> { krate = time(sess, "attributes injection", || { - syntax::attr::inject(krate, &sess.parse_sess, &sess.opts.debugging_opts.crate_attr) + syntax_ext::cmdline_attrs::inject( + krate, &sess.parse_sess, &sess.opts.debugging_opts.crate_attr + ) }); let (mut krate, features) = syntax::config::features( diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 0e5cfa73a9e3a..69de3150354e7 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -16,7 +16,7 @@ use crate::mut_visit::visit_clobber; use crate::source_map::{BytePos, Spanned, DUMMY_SP}; use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use crate::parse::parser::Parser; -use crate::parse::{self, ParseSess, PResult}; +use crate::parse::{ParseSess, PResult}; use crate::parse::token::{self, Token}; use crate::ptr::P; use crate::symbol::{sym, Symbol}; @@ -25,7 +25,7 @@ use crate::tokenstream::{TokenStream, TokenTree, DelimSpan}; use crate::GLOBALS; use log::debug; -use syntax_pos::{FileName, Span}; +use syntax_pos::Span; use std::iter; use std::ops::DerefMut; @@ -381,28 +381,25 @@ crate fn mk_attr_id() -> AttrId { AttrId(id) } -/// Returns an inner attribute with the given value and span. -pub fn mk_attr_inner(item: MetaItem) -> Attribute { +pub fn mk_attr(style: AttrStyle, path: Path, tokens: TokenStream, span: Span) -> Attribute { Attribute { id: mk_attr_id(), - style: ast::AttrStyle::Inner, - path: item.path, - tokens: item.node.tokens(item.span), + style, + path, + tokens, is_sugared_doc: false, - span: item.span, + span, } } +/// Returns an inner attribute with the given value and span. +pub fn mk_attr_inner(item: MetaItem) -> Attribute { + mk_attr(AttrStyle::Inner, item.path, item.node.tokens(item.span), item.span) +} + /// Returns an outer attribute with the given value and span. pub fn mk_attr_outer(item: MetaItem) -> Attribute { - Attribute { - id: mk_attr_id(), - style: ast::AttrStyle::Outer, - path: item.path, - tokens: item.node.tokens(item.span), - is_sugared_doc: false, - span: item.span, - } + mk_attr(AttrStyle::Outer, item.path, item.node.tokens(item.span), item.span) } pub fn mk_sugared_doc_attr(text: Symbol, span: Span) -> Attribute { @@ -716,33 +713,3 @@ derive_has_attrs! { Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm, ast::Field, ast::FieldPat, ast::Variant, ast::Param } - -pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate { - for raw_attr in attrs { - let mut parser = parse::new_parser_from_source_str( - parse_sess, - FileName::cli_crate_attr_source_code(&raw_attr), - raw_attr.clone(), - ); - - let start_span = parser.token.span; - let (path, tokens) = panictry!(parser.parse_meta_item_unrestricted()); - let end_span = parser.token.span; - if parser.token != token::Eof { - parse_sess.span_diagnostic - .span_err(start_span.to(end_span), "invalid crate attribute"); - continue; - } - - krate.attrs.push(Attribute { - id: mk_attr_id(), - style: AttrStyle::Inner, - path, - tokens, - is_sugared_doc: false, - span: start_span.to(end_span), - }); - } - - krate -} diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 671178223f503..d9c4baad49ded 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -176,7 +176,7 @@ impl<'a> Parser<'a> { /// PATH /// PATH `=` TOKEN_TREE /// The delimiters or `=` are still put into the resulting token stream. - crate fn parse_meta_item_unrestricted(&mut self) -> PResult<'a, (ast::Path, TokenStream)> { + pub fn parse_meta_item_unrestricted(&mut self) -> PResult<'a, (ast::Path, TokenStream)> { let meta = match self.token.kind { token::Interpolated(ref nt) => match **nt { Nonterminal::NtMeta(ref meta) => Some(meta.clone()), diff --git a/src/libsyntax_ext/cmdline_attrs.rs b/src/libsyntax_ext/cmdline_attrs.rs new file mode 100644 index 0000000000000..bb8e3df3db921 --- /dev/null +++ b/src/libsyntax_ext/cmdline_attrs.rs @@ -0,0 +1,30 @@ +//! Attributes injected into the crate root from command line using `-Z crate-attr`. + +use syntax::ast::{self, AttrStyle}; +use syntax::attr::mk_attr; +use syntax::panictry; +use syntax::parse::{self, token, ParseSess}; +use syntax_pos::FileName; + +pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate { + for raw_attr in attrs { + let mut parser = parse::new_parser_from_source_str( + parse_sess, + FileName::cli_crate_attr_source_code(&raw_attr), + raw_attr.clone(), + ); + + let start_span = parser.token.span; + let (path, tokens) = panictry!(parser.parse_meta_item_unrestricted()); + let end_span = parser.token.span; + if parser.token != token::Eof { + parse_sess.span_diagnostic + .span_err(start_span.to(end_span), "invalid crate attribute"); + continue; + } + + krate.attrs.push(mk_attr(AttrStyle::Inner, path, tokens, start_span.to(end_span))); + } + + krate +} diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 26ef80b2b06df..5c0a63ebbe7cb 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -40,6 +40,7 @@ mod source_util; mod test; mod trace_macros; +pub mod cmdline_attrs; pub mod plugin_macro_defs; pub mod proc_macro_harness; pub mod standard_library_imports; From f0386a10e0112acef6ea0447e6e5a3ac1c7cb118 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 7 Sep 2019 13:16:18 +0100 Subject: [PATCH 549/618] Add "bool" lang item --- src/libcore/bool/mod.rs | 7 +++++++ src/libcore/lib.rs | 1 + src/librustc/middle/lang_items.rs | 1 + src/librustc_typeck/check/method/probe.rs | 4 ++++ src/librustc_typeck/coherence/inherent_impls.rs | 8 ++++++++ src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/passes/collect_intra_doc_links.rs | 1 + src/librustdoc/passes/collect_trait_impls.rs | 1 + 8 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/libcore/bool/mod.rs diff --git a/src/libcore/bool/mod.rs b/src/libcore/bool/mod.rs new file mode 100644 index 0000000000000..ddca07b27a53f --- /dev/null +++ b/src/libcore/bool/mod.rs @@ -0,0 +1,7 @@ +//! impl bool {} + +#![stable(feature = "core_bool", since = "1.39.0")] + +#[cfg(not(boostrap_stdarch_ignore_this))] +#[lang = "bool"] +impl bool {} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index c168d5c8a2eac..03b6aa68d3c27 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -198,6 +198,7 @@ pub mod borrow; pub mod any; pub mod array; pub mod ascii; +pub mod bool; pub mod sync; pub mod cell; pub mod char; diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 6b04600eb75f8..0aa708033c1a7 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -246,6 +246,7 @@ pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems { language_item_table! { // Variant name, Name, Method name, Target; + BoolImplItem, "bool", bool_impl, Target::Impl; CharImplItem, "char", char_impl, Target::Impl; StrImplItem, "str", str_impl, Target::Impl; SliceImplItem, "slice", slice_impl, Target::Impl; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 1c01c8408be6c..c8838311e8dbf 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -578,6 +578,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ty::Param(p) => { self.assemble_inherent_candidates_from_param(p); } + ty::Bool => { + let lang_def_id = lang_items.bool_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } ty::Char => { let lang_def_id = lang_items.char_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index fb79a85ea25bf..e7c2126cfd727 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -67,6 +67,14 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => { self.check_def_id(item, data.principal_def_id().unwrap()); } + ty::Bool => { + self.check_primitive_impl(def_id, + lang_items.bool_impl(), + None, + "bool", + "bool", + item.span); + } ty::Char => { self.check_primitive_impl(def_id, lang_items.char_impl(), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4971155113263..38eff43bad2be 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3977,7 +3977,7 @@ fn build_deref_target_impls(cx: &DocContext<'_>, F32 => tcx.lang_items().f32_impl(), F64 => tcx.lang_items().f64_impl(), Char => tcx.lang_items().char_impl(), - Bool => None, + Bool => tcx.lang_items().bool_impl(), Str => tcx.lang_items().str_impl(), Slice => tcx.lang_items().slice_impl(), Array => tcx.lang_items().slice_impl(), diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 2951b2ccb2af9..d6073cdc1e11d 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -679,6 +679,7 @@ fn primitive_impl(cx: &DocContext<'_>, path_str: &str) -> Option { "f32" => tcx.lang_items().f32_impl(), "f64" => tcx.lang_items().f64_impl(), "str" => tcx.lang_items().str_impl(), + "bool" => tcx.lang_items().bool_impl(), "char" => tcx.lang_items().char_impl(), _ => None, } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 86e4e9fd95637..28c64d0b9638e 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -53,6 +53,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { lang_items.f64_impl(), lang_items.f32_runtime_impl(), lang_items.f64_runtime_impl(), + lang_items.bool_impl(), lang_items.char_impl(), lang_items.str_impl(), lang_items.slice_impl(), From 0d084670d726d17505c03f71a258a42229680e7e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 5 Sep 2019 18:04:58 +0300 Subject: [PATCH 550/618] resolve: Do not afraid to set current module to enums and traits --- src/librustc_resolve/build_reduced_graph.rs | 11 ++++------- src/librustc_resolve/lib.rs | 6 +++++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 81bd687e26321..333509e18504d 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -728,9 +728,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { expansion, item.span); self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); + self.parent_scope.module = module; for variant in &(*enum_definition).variants { - self.build_reduced_graph_for_variant(variant, module, vis); + self.build_reduced_graph_for_variant(variant, vis); } } @@ -818,10 +819,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // Constructs the reduced graph for one variant. Variants exist in the // type and value namespaces. - fn build_reduced_graph_for_variant(&mut self, - variant: &Variant, - parent: Module<'a>, - vis: ty::Visibility) { + fn build_reduced_graph_for_variant(&mut self, variant: &Variant, vis: ty::Visibility) { + let parent = self.parent_scope.module; let expn_id = self.parent_scope.expansion; let ident = variant.ident; @@ -1253,9 +1252,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { let expansion = self.parent_scope.expansion; self.r.define(parent, item.ident, ns, (res, vis, item.span, expansion)); - self.parent_scope.module = parent.parent.unwrap(); // nearest normal ancestor visit::walk_trait_item(self, item); - self.parent_scope.module = parent; } fn visit_token(&mut self, t: Token) { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 7f65e5dfaa2bf..29676f96ce7a8 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -538,7 +538,11 @@ impl<'a> ModuleData<'a> { } fn nearest_item_scope(&'a self) -> Module<'a> { - if self.is_trait() { self.parent.unwrap() } else { self } + match self.kind { + ModuleKind::Def(DefKind::Enum, ..) | ModuleKind::Def(DefKind::Trait, ..) => + self.parent.expect("enum or trait module without a parent"), + _ => self, + } } fn is_ancestor_of(&self, mut other: &Self) -> bool { From 56f635304b7a2689cfe5e98577428d67f059b413 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 7 Sep 2019 17:33:50 +0300 Subject: [PATCH 551/618] resolve: Adjust `hygienic_lexical_parent` to account for enum and trait modules --- src/librustc_resolve/lib.rs | 2 +- src/test/ui/resolve/block-with-trait-parent.rs | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/resolve/block-with-trait-parent.rs diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 29676f96ce7a8..efb64c9341f13 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1644,7 +1644,7 @@ impl<'a> Resolver<'a> { } if let ModuleKind::Block(..) = module.kind { - return Some(module.parent.unwrap()); + return Some(module.parent.unwrap().nearest_item_scope()); } None diff --git a/src/test/ui/resolve/block-with-trait-parent.rs b/src/test/ui/resolve/block-with-trait-parent.rs new file mode 100644 index 0000000000000..bc86f94e921cb --- /dev/null +++ b/src/test/ui/resolve/block-with-trait-parent.rs @@ -0,0 +1,14 @@ +// check-pass + +trait Trait { + fn method(&self) { + // Items inside a block turn it into a module internally. + struct S; + impl Trait for S {} + + // OK, `Trait` is in scope here from method resolution point of view. + S.method(); + } +} + +fn main() {} From b73e32c795ec438a4b2e1901abc4e2a281e1a18a Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 7 Sep 2019 15:49:27 +0100 Subject: [PATCH 552/618] Add `bool::then` and `bool::then_with` --- src/libcore/bool/mod.rs | 42 ++++++++++++++++++++++++++++++++++++++- src/libcore/tests/bool.rs | 7 +++++++ src/libcore/tests/lib.rs | 2 ++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/libcore/tests/bool.rs diff --git a/src/libcore/bool/mod.rs b/src/libcore/bool/mod.rs index ddca07b27a53f..0fbd3b8c2bbce 100644 --- a/src/libcore/bool/mod.rs +++ b/src/libcore/bool/mod.rs @@ -4,4 +4,44 @@ #[cfg(not(boostrap_stdarch_ignore_this))] #[lang = "bool"] -impl bool {} +impl bool { + /// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(bool_to_option)] + /// + /// assert_eq!(false.then(0), None); + /// assert_eq!(true.then(0), Some(0)); + /// ``` + #[unstable(feature = "bool_to_option", issue = "0")] + #[inline] + pub fn then(self, t: T) -> Option { + if self { + Some(t) + } else { + None + } + } + + /// Returns `Some(f())` if the `bool` is `true`, or `None` otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(bool_to_option)] + /// + /// assert_eq!(false.then_with(|| 0), None); + /// assert_eq!(true.then_with(|| 0), Some(0)); + /// ``` + #[unstable(feature = "bool_to_option", issue = "0")] + #[inline] + pub fn then_with T>(self, f: F) -> Option { + if self { + Some(f()) + } else { + None + } + } +} diff --git a/src/libcore/tests/bool.rs b/src/libcore/tests/bool.rs new file mode 100644 index 0000000000000..0f1e6e89451e9 --- /dev/null +++ b/src/libcore/tests/bool.rs @@ -0,0 +1,7 @@ +#[test] +fn test_bool_to_option() { + assert_eq!(false.then(0), None); + assert_eq!(true.then(0), Some(0)); + assert_eq!(false.then_with(|| 0), None); + assert_eq!(true.then_with(|| 0), Some(0)); +} diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index a3b108b2e9cea..b2c29aa269265 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -1,3 +1,4 @@ +#![feature(bool_to_option)] #![feature(bound_cloned)] #![feature(box_syntax)] #![feature(cell_update)] @@ -40,6 +41,7 @@ mod any; mod array; mod ascii; mod atomic; +mod bool; mod cell; mod char; mod clone; From c1d29ee3c754c63fc6c8c3a522b7a71a5a19616a Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Fri, 6 Sep 2019 03:57:44 +0100 Subject: [PATCH 553/618] Aggregation of cosmetic changes made during work on REPL PRs: librustc --- src/librustc/arena.rs | 2 +- src/librustc/hir/check_attr.rs | 7 +- src/librustc/hir/def.rs | 22 +- src/librustc/hir/def_id.rs | 7 +- src/librustc/hir/intravisit.rs | 20 +- src/librustc/hir/itemlikevisit.rs | 21 +- src/librustc/hir/lowering.rs | 18 +- src/librustc/hir/lowering/item.rs | 4 +- src/librustc/hir/map/collector.rs | 2 +- src/librustc/hir/map/definitions.rs | 77 +++--- src/librustc/hir/map/mod.rs | 41 ++-- src/librustc/hir/mod.rs | 53 +++-- src/librustc/hir/print.rs | 25 +- src/librustc/ich/hcx.rs | 54 ++--- src/librustc/ich/impls_hir.rs | 18 +- src/librustc/ich/impls_ty.rs | 6 +- src/librustc/infer/mod.rs | 8 +- src/librustc/lint/context.rs | 20 +- src/librustc/lint/mod.rs | 6 +- src/librustc/middle/entry.rs | 18 +- src/librustc/middle/expr_use_visitor.rs | 2 +- src/librustc/middle/lang_items.rs | 18 +- src/librustc/middle/region.rs | 82 ++++--- src/librustc/mir/cache.rs | 2 +- src/librustc/mir/interpret/allocation.rs | 109 +++++---- src/librustc/mir/interpret/error.rs | 16 +- src/librustc/mir/interpret/mod.rs | 110 ++++----- src/librustc/mir/interpret/pointer.rs | 9 +- src/librustc/mir/interpret/value.rs | 10 +- src/librustc/mir/mod.rs | 170 +++++++------- src/librustc/query/mod.rs | 5 +- src/librustc/session/config.rs | 137 ++++++----- src/librustc/session/mod.rs | 61 ++--- src/librustc/traits/object_safety.rs | 22 +- .../traits/query/evaluate_obligation.rs | 5 +- src/librustc/traits/query/method_autoderef.rs | 10 +- src/librustc/traits/util.rs | 6 +- src/librustc/ty/codec.rs | 21 +- src/librustc/ty/context.rs | 165 +++++++------ src/librustc/ty/fold.rs | 4 +- .../ty/inhabitedness/def_id_forest.rs | 18 +- src/librustc/ty/inhabitedness/mod.rs | 35 +-- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/print/mod.rs | 7 +- src/librustc/ty/print/pretty.rs | 79 ++++--- src/librustc/ty/query/on_disk_cache.rs | 219 +++++++++--------- src/librustc/ty/query/plumbing.rs | 106 +++++---- src/librustc/ty/sty.rs | 8 +- src/librustc_ast_borrowck/cfg/construct.rs | 146 ++++++------ src/librustc_ast_borrowck/cfg/graphviz.rs | 11 +- 50 files changed, 1028 insertions(+), 996 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index b3a561ef74be7..d4fc1b12830a1 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -187,7 +187,7 @@ impl ArenaAllocatable for T {} unsafe trait ArenaField<'tcx>: Sized { /// Returns a specific arena to allocate from. - /// If None is returned, the DropArena will be used. + /// If `None` is returned, the `DropArena` will be used. fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a TypedArena>; } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index eae956c978a8e..1df09429e519f 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -4,13 +4,12 @@ //! conflicts between multiple such attributes attached to the same //! item. - -use crate::ty::TyCtxt; -use crate::ty::query::Providers; - use crate::hir; use crate::hir::def_id::DefId; use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use crate::ty::TyCtxt; +use crate::ty::query::Providers; + use std::fmt::{self, Display}; use syntax::symbol::sym; use syntax_pos::Span; diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index f83fbcdc263b0..f7d31ca06ee56 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -1,15 +1,17 @@ +use self::Namespace::*; + use crate::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use crate::hir; +use crate::ty; use crate::util::nodemap::DefIdMap; + use syntax::ast; use syntax::ext::base::MacroKind; use syntax::ast::NodeId; use syntax_pos::Span; use rustc_macros::HashStable; -use crate::hir; -use crate::ty; -use std::fmt::Debug; -use self::Namespace::*; +use std::fmt::Debug; /// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct. #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] @@ -115,7 +117,7 @@ impl DefKind { } } - /// An English article for the def. + /// Gets an English article for the definition. pub fn article(&self) -> &'static str { match *self { DefKind::AssocTy @@ -134,18 +136,22 @@ pub enum Res { Def(DefKind, DefId), // Type namespace + PrimTy(hir::PrimTy), SelfTy(Option /* trait */, Option /* impl */), ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]` // Value namespace + SelfCtor(DefId /* impl */), // `DefId` refers to the impl Local(Id), // Macro namespace + NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]` // All namespaces + Err, } @@ -330,7 +336,7 @@ impl NonMacroAttrKind { } impl Res { - /// Return the `DefId` of this `Def` if it has an id, else panic. + /// Return the `DefId` of this `Def` if it has an ID, else panic. pub fn def_id(&self) -> DefId where Id: Debug, @@ -340,7 +346,7 @@ impl Res { }) } - /// Return `Some(..)` with the `DefId` of this `Res` if it has a id, else `None`. + /// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`. pub fn opt_def_id(&self) -> Option { match *self { Res::Def(_, id) => Some(id), @@ -379,7 +385,7 @@ impl Res { } } - /// An English article for the res. + /// Gets an English article for the `Res`. pub fn article(&self) -> &'static str { match *self { Res::Def(kind, _) => kind.article(), diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index c91ad7858d0bb..d0bdc14913183 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -11,7 +11,7 @@ newtype_index! { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum CrateNum { - /// A special CrateNum that we use for the tcx.rcache when decoding from + /// A special `CrateNum` that we use for the `tcx.rcache` when decoding from /// the incr. comp. cache. ReservedForIncrCompCache, Index(CrateId), @@ -26,11 +26,10 @@ impl ::std::fmt::Debug for CrateNum { } } -/// Item definitions in the currently-compiled crate would have the CrateNum -/// LOCAL_CRATE in their DefId. +/// Item definitions in the currently-compiled crate would have the `CrateNum` +/// `LOCAL_CRATE` in their `DefId`. pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32_const(0)); - impl Idx for CrateNum { #[inline] fn new(value: usize) -> Self { diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index bbde3510e29f9..1f125de967216 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -31,11 +31,13 @@ //! This order consistency is required in a few places in rustc, for //! example generator inference, and possibly also HIR borrowck. -use syntax::ast::{Ident, Name, Attribute}; -use syntax_pos::Span; +use super::itemlikevisit::DeepVisitor; + use crate::hir::*; use crate::hir::map::Map; -use super::itemlikevisit::DeepVisitor; + +use syntax::ast::{Ident, Name, Attribute}; +use syntax_pos::Span; #[derive(Copy, Clone)] pub enum FnKind<'a> { @@ -139,7 +141,7 @@ impl<'this, 'tcx> NestedVisitorMap<'this, 'tcx> { /// explicitly, you need to override each method. (And you also need /// to monitor future changes to `Visitor` in case a new method with a /// new default implementation gets introduced.) -pub trait Visitor<'v> : Sized { +pub trait Visitor<'v>: Sized { /////////////////////////////////////////////////////////////////////////// // Nested items. @@ -162,8 +164,8 @@ pub trait Visitor<'v> : Sized { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v>; /// Invoked when a nested item is encountered. By default does - /// nothing unless you override `nested_visit_map` to return - /// `Some(_)`, in which case it will walk the item. **You probably + /// nothing unless you override `nested_visit_map` to return other than + /// `None`, in which case it will walk the item. **You probably /// don't want to override this method** -- instead, override /// `nested_visit_map` or use the "shallow" or "deep" visit /// patterns described on `itemlikevisit::ItemLikeVisitor`. The only @@ -201,8 +203,8 @@ pub trait Visitor<'v> : Sized { /// Invoked to visit the body of a function, method or closure. Like /// visit_nested_item, does nothing by default unless you override - /// `nested_visit_map` to return `Some(_)`, in which case it will walk the - /// body. + /// `nested_visit_map` to return other htan `None`, in which case it will walk + /// the body. fn visit_nested_body(&mut self, id: BodyId) { let opt_body = self.nested_visit_map().intra().map(|map| map.body(id)); if let Some(body) = opt_body { @@ -603,7 +605,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { visitor.visit_lifetime(lifetime); visitor.visit_ty(&mutable_type.ty) } - TyKind::Never => {}, + TyKind::Never => {} TyKind::Tup(ref tuple_element_types) => { walk_list!(visitor, visit_ty, tuple_element_types); } diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs index 35b181245837f..39dd46c2d2903 100644 --- a/src/librustc/hir/itemlikevisit.rs +++ b/src/librustc/hir/itemlikevisit.rs @@ -1,7 +1,7 @@ use super::{Item, ImplItem, TraitItem}; use super::intravisit::Visitor; -/// The "item-like visitor" visitor defines only the top-level methods +/// The "item-like visitor" defines only the top-level methods /// that can be invoked by `Crate::visit_all_item_likes()`. Whether /// this trait is the right one to implement will depend on the /// overall pattern you need. Here are the three available patterns, @@ -18,11 +18,11 @@ use super::intravisit::Visitor; /// an item, but don't care about how item-like things are nested /// within one another. /// - Example: Examine each expression to look for its type and do some check or other. -/// - How: Implement `intravisit::Visitor` and use -/// `tcx.hir().krate().visit_all_item_likes(visitor.as_deep_visitor())`. Within -/// your `intravisit::Visitor` impl, implement methods like -/// `visit_expr()`; don't forget to invoke -/// `intravisit::walk_visit_expr()` to keep walking the subparts. +/// - How: Implement `intravisit::Visitor` and override the `nested_visit_map()` method +/// to return `NestedVisitorMap::OnlyBodies` and use +/// `tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor())`. Within +/// your `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget +/// to invoke `intravisit::walk_expr()` to keep walking the subparts). /// - Pro: Visitor methods for any kind of HIR node, not just item-like things. /// - Pro: Integrates well into dependency tracking. /// - Con: Don't get information about nesting between items @@ -30,10 +30,9 @@ use super::intravisit::Visitor; /// item-like things. /// - Example: Lifetime resolution, which wants to bring lifetimes declared on the /// impl into scope while visiting the impl-items, and then back out again. -/// - How: Implement `intravisit::Visitor` and override the -/// `nested_visit_map()` methods to return -/// `NestedVisitorMap::All`. Walk your crate with -/// `intravisit::walk_crate()` invoked on `tcx.hir().krate()`. +/// - How: Implement `intravisit::Visitor` and override the `nested_visit_map()` method +/// to return `NestedVisitorMap::All`. Walk your crate with `intravisit::walk_crate()` +/// invoked on `tcx.hir().krate()`. /// - Pro: Visitor methods for any kind of HIR node, not just item-like things. /// - Pro: Preserves nesting information /// - Con: Does not integrate well into dependency tracking. @@ -79,7 +78,7 @@ impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V> } } -/// A parallel variant of ItemLikeVisitor +/// A parallel variant of `ItemLikeVisitor`. pub trait ParItemLikeVisitor<'hir> { fn visit_item(&self, item: &'hir Item); fn visit_trait_item(&self, trait_item: &'hir TraitItem); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 190b50b10b281..fd6445ea3c4d4 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -79,7 +79,7 @@ const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; pub struct LoweringContext<'a> { crate_root: Option, - /// Used to assign ids to HIR nodes that do not directly correspond to an AST node. + /// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes. sess: &'a Session, cstore: &'a dyn CrateStore, @@ -126,7 +126,7 @@ pub struct LoweringContext<'a> { /// lifetime definitions in the corresponding impl or function generics. lifetimes_to_define: Vec<(Span, ParamName)>, - /// Whether or not in-band lifetimes are being collected. This is used to + /// `true` ifs in-band lifetimes are being collected. This is used to /// indicate whether or not we're in a place where new lifetimes will result /// in in-band lifetime definitions, such a function or an impl header, /// including implicit lifetimes from `impl_header_lifetime_elision`. @@ -154,13 +154,13 @@ pub struct LoweringContext<'a> { } pub trait Resolver { - /// Obtain resolution for a `NodeId` with a single resolution. + /// Obtains resolution for a `NodeId` with a single resolution. fn get_partial_res(&mut self, id: NodeId) -> Option; - /// Obtain per-namespace resolutions for `use` statement with the given `NoedId`. + /// Obtains per-namespace resolutions for `use` statement with the given `NodeId`. fn get_import_res(&mut self, id: NodeId) -> PerNS>>; - /// Obtain resolution for a label with the given `NodeId`. + /// Obtains resolution for a label with the given `NodeId`. fn get_label_res(&mut self, id: NodeId) -> Option; /// We must keep the set of definitions up to date as we add nodes that weren't in the AST. @@ -699,7 +699,7 @@ impl<'a> LoweringContext<'a> { fn lower_res(&mut self, res: Res) -> Res { res.map_id(|id| { self.lower_node_id_generic(id, |_| { - panic!("expected node_id to be lowered already for res {:#?}", res) + panic!("expected `NodeId` to be lowered already for res {:#?}", res); }) }) } @@ -1364,7 +1364,7 @@ impl<'a> LoweringContext<'a> { } } } - TyKind::Mac(_) => bug!("`TyMac` should have been expanded by now."), + TyKind::Mac(_) => bug!("`TyMac` should have been expanded by now"), TyKind::CVarArgs => { // Create the implicit lifetime of the "spoofed" `VaListImpl`. let span = self.sess.source_map().next_point(t.span.shrink_to_lo()); @@ -2999,7 +2999,7 @@ impl<'a> LoweringContext<'a> { } StmtKind::Expr(ref e) => hir::StmtKind::Expr(P(self.lower_expr(e))), StmtKind::Semi(ref e) => hir::StmtKind::Semi(P(self.lower_expr(e))), - StmtKind::Mac(..) => panic!("Shouldn't exist here"), + StmtKind::Mac(..) => panic!("shouldn't exist here"), }; smallvec![hir::Stmt { hir_id: self.lower_node_id(s.id), @@ -3187,7 +3187,7 @@ impl<'a> LoweringContext<'a> { hir::Path { span, - res: res.map_id(|_| panic!("unexpected node_id")), + res: res.map_id(|_| panic!("unexpected `NodeId`")), segments: segments.into(), } } diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 4e432f4981d23..5f82e42abb308 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -718,7 +718,7 @@ impl LoweringContext<'_> { AnonymousLifetimeMode::PassThrough, |this, _| { ( - // Disallow impl Trait in foreign items + // Disallow `impl Trait` in foreign items. this.lower_fn_decl(fdec, None, false, None), this.lower_fn_params_to_names(fdec), ) @@ -732,7 +732,7 @@ impl LoweringContext<'_> { self.lower_ty(t, ImplTraitContext::disallowed()), self.lower_mutability(m)) } ForeignItemKind::Ty => hir::ForeignItemKind::Type, - ForeignItemKind::Macro(_) => panic!("shouldn't exist here"), + ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"), }, vis: self.lower_visibility(&i.vis, None), span: i.span, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index b8bd1d73fc28b..4179cf2ff807f 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -340,7 +340,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { /// their outer items. fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> { - panic!("visit_nested_xxx must be manually implemented in this visitor") + panic!("`visit_nested_xxx` must be manually implemented in this visitor"); } fn visit_nested_item(&mut self, item: ItemId) { diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 6dc3c7038f569..651fe8449ac93 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -7,10 +7,12 @@ use crate::hir; use crate::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, CRATE_DEF_INDEX}; use crate::ich::Fingerprint; +use crate::session::CrateDisambiguator; +use crate::util::nodemap::NodeMap; + use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::{IndexVec}; use rustc_data_structures::stable_hasher::StableHasher; -use crate::session::CrateDisambiguator; use std::borrow::Borrow; use std::fmt::Write; use std::hash::Hash; @@ -18,12 +20,11 @@ use syntax::ast; use syntax::ext::hygiene::ExpnId; use syntax::symbol::{Symbol, sym, InternedString}; use syntax_pos::{Span, DUMMY_SP}; -use crate::util::nodemap::NodeMap; -/// The DefPathTable maps DefIndexes to DefKeys and vice versa. -/// Internally the DefPathTable holds a tree of DefKeys, where each DefKey -/// stores the DefIndex of its parent. -/// There is one DefPathTable for each crate. +/// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa. +/// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey` +/// stores the `DefIndex` of its parent. +/// There is one `DefPathTable` for each crate. #[derive(Clone, Default, RustcDecodable, RustcEncodable)] pub struct DefPathTable { index_to_key: Vec, @@ -121,7 +122,7 @@ impl DefKey { fn compute_stable_hash(&self, parent_hash: DefPathHash) -> DefPathHash { let mut hasher = StableHasher::new(); - // We hash a 0u8 here to disambiguate between regular DefPath hashes, + // We hash a `0u8` here to disambiguate between regular `DefPath` hashes, // and the special "root_parent" below. 0u8.hash(&mut hasher); parent_hash.hash(&mut hasher); @@ -145,8 +146,7 @@ impl DefKey { crate_disambiguator: CrateDisambiguator) -> DefPathHash { let mut hasher = StableHasher::new(); - // Disambiguate this from a regular DefPath hash, - // see compute_stable_hash() above. + // Disambiguate this from a regular `DefPath` hash; see `compute_stable_hash()` above. 1u8.hash(&mut hasher); crate_name.hash(&mut hasher); crate_disambiguator.hash(&mut hasher); @@ -155,10 +155,10 @@ impl DefKey { } /// A pair of `DefPathData` and an integer disambiguator. The integer is -/// normally 0, but in the event that there are multiple defs with the +/// normally `0`, but in the event that there are multiple defs with the /// same `parent` and `data`, we use this field to disambiguate /// between them. This introduces some artificial ordering dependency -/// but means that if you have (e.g.) two impls for the same type in +/// but means that if you have, e.g., two impls for the same type in /// the same module, they do get distinct `DefId`s. #[derive(Clone, PartialEq, Debug, Hash, RustcEncodable, RustcDecodable)] pub struct DisambiguatedDefPathData { @@ -277,29 +277,34 @@ impl DefPath { pub enum DefPathData { // Root: these should only be used for the root nodes, because // they are treated specially by the `def_path` function. - /// The crate root (marker) + + /// The crate root (marker). CrateRoot, - // Catch-all for random DefId things like `DUMMY_NODE_ID` + // Catch-all for random `DefId` things like `DUMMY_NODE_ID`. Misc, + // Different kinds of items and item-like things: - /// An impl + + /// An impl. Impl, - /// Something in the type NS + /// Something in the type namespace. TypeNs(InternedString), - /// Something in the value NS + /// Something in the value namespace. ValueNs(InternedString), - /// Something in the macro NS + /// Something in the macro namespace. MacroNs(InternedString), - /// Something in the lifetime NS + /// Something in the lifetime namespace. LifetimeNs(InternedString), - /// A closure expression + /// A closure expression. ClosureExpr, - // Subportions of items - /// Implicit ctor for a unit or tuple-like struct or enum variant. + + // Subportions of items: + + /// Implicit constructor for a unit or tuple-like struct or enum variant. Ctor, - /// A constant expression (see {ast,hir}::AnonConst). + /// A constant expression (see `{ast,hir}::AnonConst`). AnonConst, - /// An `impl Trait` type node + /// An `impl Trait` type node. ImplTrait, /// Identifies a piece of crate metadata that is global to a whole crate /// (as opposed to just one item). `GlobalMetaData` components are only @@ -435,7 +440,7 @@ impl Definitions { self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index); self.set_invocation_parent(ExpnId::root(), root_index); - // Allocate some other DefIndices that always must exist. + // Allocate some other `DefIndex`es that always must exist. GlobalMetaDataKind::allocate_def_indices(self); root_index @@ -458,7 +463,7 @@ impl Definitions { data, self.table.def_key(self.node_to_def_index[&node_id])); - // The root node must be created with create_root_def() + // The root node must be created with `create_root_def()`. assert!(data != DefPathData::CrateRoot); // Find the next free disambiguator for this key. @@ -486,9 +491,9 @@ impl Definitions { assert_eq!(index.index(), self.def_index_to_node.len()); self.def_index_to_node.push(node_id); - // Some things for which we allocate DefIndices don't correspond to - // anything in the AST, so they don't have a NodeId. For these cases - // we don't need a mapping from NodeId to DefIndex. + // Some things for which we allocate `DefIndex`es don't correspond to + // anything in the AST, so they don't have a `NodeId`. For these cases + // we don't need a mapping from `NodeId` to `DefIndex`. if node_id != ast::DUMMY_NODE_ID { debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id); self.node_to_def_index.insert(node_id, index); @@ -498,7 +503,7 @@ impl Definitions { self.expansions_that_defined.insert(index, expn_id); } - // The span is added if it isn't dummy + // The span is added if it isn't dummy. if !span.is_dummy() { self.def_index_to_span.insert(index, span); } @@ -506,12 +511,12 @@ impl Definitions { index } - /// Initialize the `ast::NodeId` to `HirId` mapping once it has been generated during + /// Initializes the `ast::NodeId` to `HirId` mapping once it has been generated during /// AST to HIR lowering. pub fn init_node_id_to_hir_id_mapping(&mut self, mapping: IndexVec) { assert!(self.node_to_hir_id.is_empty(), - "Trying initialize NodeId -> HirId mapping twice"); + "trying to initialize `NodeId` -> `HirId` mapping twice"); self.node_to_hir_id = mapping; } @@ -533,7 +538,7 @@ impl Definitions { pub fn set_invocation_parent(&mut self, invoc_id: ExpnId, parent: DefIndex) { let old_parent = self.invocation_parents.insert(invoc_id, parent); - assert!(old_parent.is_none(), "parent def-index is reset for an invocation"); + assert!(old_parent.is_none(), "parent `DefIndex` is reset for an invocation"); } } @@ -585,9 +590,9 @@ impl DefPathData { } } -// We define the GlobalMetaDataKind enum with this macro because we want to +// We define the `GlobalMetaDataKind` enum with this macro because we want to // make sure that we exhaustively iterate over all variants when registering -// the corresponding DefIndices in the DefTable. +// the corresponding `DefIndex`es in the `DefTable`. macro_rules! define_global_metadata_kind { (pub enum GlobalMetaDataKind { $($variant:ident),* @@ -609,7 +614,7 @@ macro_rules! define_global_metadata_kind { DUMMY_SP ); - // Make sure calling def_index does not crash. + // Make sure calling `def_index` does not crash. instance.def_index(&definitions.table); })* } @@ -623,7 +628,7 @@ macro_rules! define_global_metadata_kind { } }; - // These DefKeys are all right after the root, + // These `DefKey`s are all right after the root, // so a linear search is fine. let index = def_path_table.index_to_key .iter() diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index eb8be6e6e3cbc..5cec8a593f12a 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -5,10 +5,15 @@ pub use self::definitions::{ }; use crate::dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex}; - +use crate::hir::*; +use crate::hir::DefKind; use crate::hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId}; - +use crate::hir::itemlikevisit::ItemLikeVisitor; +use crate::hir::print::Nested; use crate::middle::cstore::CrateStoreDyn; +use crate::ty::query::Providers; +use crate::util::nodemap::FxHashMap; +use crate::util::common::time; use rustc_target::spec::abi::Abi; use rustc_data_structures::svh::Svh; @@ -18,15 +23,7 @@ use syntax::source_map::Spanned; use syntax::ext::base::MacroKind; use syntax_pos::{Span, DUMMY_SP}; -use crate::hir::*; -use crate::hir::DefKind; -use crate::hir::itemlikevisit::ItemLikeVisitor; -use crate::hir::print::Nested; -use crate::util::nodemap::FxHashMap; -use crate::util::common::time; - use std::result::Result::Err; -use crate::ty::query::Providers; pub mod blocks; mod collector; @@ -627,7 +624,7 @@ impl<'hir> Map<'hir> { .unwrap_or(hir_id) } - /// Check if the node is an argument. An argument is a local variable whose + /// Checks if the node is an argument. An argument is a local variable whose /// immediate parent is an item or a closure. pub fn is_argument(&self, id: HirId) -> bool { match self.find(id) { @@ -733,7 +730,7 @@ impl<'hir> Map<'hir> { /// ``` /// fn foo(x: usize) -> bool { /// if x == 1 { - /// true // `get_return_block` gets passed the `id` corresponding + /// true // If `get_return_block` gets passed the `id` corresponding /// } else { // to this, it will return `foo`'s `HirId`. /// false /// } @@ -743,7 +740,7 @@ impl<'hir> Map<'hir> { /// ``` /// fn foo(x: usize) -> bool { /// loop { - /// true // `get_return_block` gets passed the `id` corresponding + /// true // If `get_return_block` gets passed the `id` corresponding /// } // to this, it will return `None`. /// false /// } @@ -994,9 +991,9 @@ impl<'hir> Map<'hir> { self.map.iter().enumerate().filter_map(|(i, local_map)| { local_map.as_ref().map(|m| (i, m)) }).flat_map(move |(array_index, local_map)| { - // Iterate over each valid entry in the local map + // Iterate over each valid entry in the local map. local_map.iter_enumerated().filter_map(move |(i, entry)| entry.map(move |_| { - // Reconstruct the HirId based on the 3 indices we used to find it + // Reconstruct the `HirId` based on the 3 indices we used to find it. HirId { owner: DefIndex::from(array_index), local_id: i, @@ -1207,7 +1204,7 @@ pub fn map_crate<'hir>(sess: &crate::session::Session, definitions, }; - time(sess, "validate hir map", || { + time(sess, "validate HIR map", || { hir_id_validator::check_crate(&map); }); @@ -1247,9 +1244,9 @@ impl<'a> print::State<'a> { Node::Pat(a) => self.print_pat(&a), Node::Arm(a) => self.print_arm(&a), Node::Block(a) => { - // containing cbox, will be closed by print-block at } + // Containing cbox, will be closed by print-block at `}`. self.cbox(print::INDENT_UNIT); - // head-ibox, will be closed by print-block after { + // Head-ibox, will be closed by print-block after `{`. self.ibox(0); self.print_block(&a) } @@ -1257,8 +1254,8 @@ impl<'a> print::State<'a> { Node::Visibility(a) => self.print_visibility(&a), Node::GenericParam(_) => bug!("cannot print Node::GenericParam"), Node::Field(_) => bug!("cannot print StructField"), - // these cases do not carry enough information in the - // hir_map to reconstruct their full structure for pretty + // These cases do not carry enough information in the + // `hir_map` to reconstruct their full structure for pretty // printing. Node::Ctor(..) => bug!("cannot print isolated Ctor"), Node::Local(a) => self.print_local_decl(&a), @@ -1273,8 +1270,8 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { let id_str = if include_id { &id_str[..] } else { "" }; let path_str = || { - // This functionality is used for debugging, try to use TyCtxt to get - // the user-friendly path, otherwise fall back to stringifying DefPath. + // This functionality is used for debugging, try to use `TyCtxt` to get + // the user-friendly path, otherwise fall back to stringifying `DefPath`. crate::ty::tls::with_opt(|tcx| { if let Some(tcx) = tcx { let def_id = map.local_def_id(id); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d2c45a5af8598..f5e644625729b 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -13,26 +13,24 @@ pub use self::UnsafeSource::*; use crate::hir::def::{Res, DefKind}; use crate::hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX}; use crate::hir::ptr::P; -use crate::util::nodemap::{NodeMap, FxHashSet}; use crate::mir::mono::Linkage; +use crate::ty::AdtKind; +use crate::ty::query::Providers; +use crate::util::nodemap::{NodeMap, FxHashSet}; use errors::FatalError; use syntax_pos::{Span, DUMMY_SP, symbol::InternedString, MultiSpan}; use syntax::source_map::Spanned; -use rustc_target::spec::abi::Abi; use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect}; use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy}; use syntax::attr::{InlineAttr, OptimizeAttr}; use syntax::symbol::{Symbol, kw}; use syntax::tokenstream::TokenStream; use syntax::util::parser::ExprPrecedence; -use crate::ty::AdtKind; -use crate::ty::query::Providers; - +use rustc_target::spec::abi::Abi; use rustc_data_structures::sync::{par_for_each_in, Send, Sync}; use rustc_data_structures::thin_vec::ThinVec; use rustc_macros::HashStable; - use rustc_serialize::{self, Encoder, Encodable, Decoder, Decodable}; use std::collections::{BTreeSet, BTreeMap}; use std::fmt; @@ -99,7 +97,8 @@ impl rustc_serialize::UseSpecializedEncodable for HirId { } = *self; owner.encode(s)?; - local_id.encode(s) + local_id.encode(s)?; + Ok(()) } } @@ -121,7 +120,7 @@ impl fmt::Display for HirId { } } -// Hack to ensure that we don't try to access the private parts of `ItemLocalId` in this module +// Hack to ensure that we don't try to access the private parts of `ItemLocalId` in this module. mod item_local_id_inner { use rustc_data_structures::indexed_vec::Idx; use rustc_macros::HashStable; @@ -746,7 +745,7 @@ pub struct Crate { // Attributes from non-exported macros, kept only for collecting the library feature list. pub non_exported_macro_attrs: HirVec, - // N.B., we use a BTreeMap here so that `visit_all_items` iterates + // N.B., we use a `BTreeMap` here so that `visit_all_items` iterates // over the ids in increasing order. In principle it should not // matter what order we visit things in, but in *practice* it // does, because it can affect the order in which errors are @@ -1403,13 +1402,13 @@ pub struct AnonConst { pub body: BodyId, } -/// An expression +/// An expression. #[derive(RustcEncodable, RustcDecodable)] pub struct Expr { - pub span: Span, + pub hir_id: HirId, pub node: ExprKind, pub attrs: ThinVec, - pub hir_id: HirId, + pub span: Span, } // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. @@ -2422,37 +2421,37 @@ pub enum ItemKind { /// /// or just /// - /// `use foo::bar::baz;` (with `as baz` implicitly on the right) + /// `use foo::bar::baz;` (with `as baz` implicitly on the right). Use(P, UseKind), - /// A `static` item + /// A `static` item. Static(P, Mutability, BodyId), - /// A `const` item + /// A `const` item. Const(P, BodyId), - /// A function declaration + /// A function declaration. Fn(P, FnHeader, Generics, BodyId), - /// A module + /// A module. Mod(Mod), - /// An external module + /// An external module. ForeignMod(ForeignMod), - /// Module-level inline assembly (from global_asm!) + /// Module-level inline assembly (from `global_asm!`). GlobalAsm(P), - /// A type alias, e.g., `type Foo = Bar` + /// A type alias, e.g., `type Foo = Bar`. TyAlias(P, Generics), - /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;` + /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`. OpaqueTy(OpaqueTy), - /// An enum definition, e.g., `enum Foo {C, D}` + /// An enum definition, e.g., `enum Foo {C, D}`. Enum(EnumDef, Generics), - /// A struct definition, e.g., `struct Foo {x: A}` + /// A struct definition, e.g., `struct Foo {x: A}`. Struct(VariantData, Generics), - /// A union definition, e.g., `union Foo {x: A, y: B}` + /// A union definition, e.g., `union Foo {x: A, y: B}`. Union(VariantData, Generics), - /// A trait definition + /// A trait definition. Trait(IsAuto, Unsafety, Generics, GenericBounds, HirVec), - /// A trait alias + /// A trait alias. TraitAlias(Generics, GenericBounds), - /// An implementation, eg `impl Trait for Foo { .. }` + /// An implementation, e.g., `impl Trait for Foo { .. }`. Impl(Unsafety, ImplPolarity, Defaultness, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 21cc72efee4a3..cfbfb5eceb550 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1293,11 +1293,11 @@ impl<'a> State<'a> { self.print_closure_params(&decl, body); self.s.space(); - // this is a bare expression + // This is a bare expression. self.ann.nested(self, Nested::Body(body)); self.end(); // need to close a box - // a box will be closed by print_expr, but we didn't want an overall + // A box will be closed by `print_expr`, but we didn't want an overall // wrapper so we closed the corresponding opening. so create an // empty box to satisfy the close. self.ibox(0); @@ -1307,9 +1307,9 @@ impl<'a> State<'a> { self.print_ident(label.ident); self.word_space(":"); } - // containing cbox, will be closed by print-block at } + // containing cbox, will be closed by print-block at `}` self.cbox(INDENT_UNIT); - // head-box, will be closed by print-block after { + // head-box, will be closed by print-block after `{` self.ibox(0); self.print_block(&blk); } @@ -1759,7 +1759,7 @@ impl<'a> State<'a> { self.word_space(","); } if let PatKind::Wild = p.node { - // Print nothing + // Print nothing. } else { self.print_pat(&p); } @@ -1891,7 +1891,7 @@ impl<'a> State<'a> { i += 1; if let hir::TyKind::Infer = ty.node { - // Print nothing + // Print nothing. } else { s.s.word(":"); s.s.space(); @@ -2221,7 +2221,6 @@ impl<'a> State<'a> { } } -// Dup'ed from parse::classify, but adapted for the HIR. /// Does this expression require a semicolon to be treated /// as a statement? The negation of this: 'can this expression /// be used as a statement without a semicolon' -- is used @@ -2229,6 +2228,8 @@ impl<'a> State<'a> { /// if true {...} else {...} /// |x| 5 /// isn't parsed as (if true {...} else {...} | x) | 5 +// +// Duplicated from `parse::classify`, but adapted for the HIR. fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool { match e.node { hir::ExprKind::Match(..) | @@ -2238,7 +2239,7 @@ fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool { } } -/// this statement requires a semicolon after it. +/// This statement requires a semicolon after it. /// note that in one case (stmt_semi), we've already /// seen the semicolon, and thus don't need another. fn stmt_ends_with_semi(stmt: &hir::StmtKind) -> bool { @@ -2277,7 +2278,7 @@ fn bin_op_to_assoc_op(op: hir::BinOpKind) -> AssocOp { } } -/// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any +/// Expressions that syntactically contain an "exterior" struct literal, i.e., not surrounded by any /// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not. fn contains_exterior_struct_lit(value: &hir::Expr) -> bool { @@ -2287,7 +2288,7 @@ fn contains_exterior_struct_lit(value: &hir::Expr) -> bool { hir::ExprKind::Assign(ref lhs, ref rhs) | hir::ExprKind::AssignOp(_, ref lhs, ref rhs) | hir::ExprKind::Binary(_, ref lhs, ref rhs) => { - // X { y: 1 } + X { y: 2 } + // `X { y: 1 } + X { y: 2 }` contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs) } hir::ExprKind::Unary(_, ref x) | @@ -2295,12 +2296,12 @@ fn contains_exterior_struct_lit(value: &hir::Expr) -> bool { hir::ExprKind::Type(ref x, _) | hir::ExprKind::Field(ref x, _) | hir::ExprKind::Index(ref x, _) => { - // &X { y: 1 }, X { y: 1 }.y + // `&X { y: 1 }, X { y: 1 }.y` contains_exterior_struct_lit(&x) } hir::ExprKind::MethodCall(.., ref exprs) => { - // X { y: 1 }.bar(...) + // `X { y: 1 }.bar(...)` contains_exterior_struct_lit(&exprs[0]) } diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index e77faea1e4c58..182a9ade8c36e 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -12,7 +12,6 @@ use std::hash as std_hash; use std::cell::RefCell; use syntax::ast; - use syntax::source_map::SourceMap; use syntax::ext::hygiene::SyntaxContext; use syntax::symbol::Symbol; @@ -20,9 +19,9 @@ use syntax::tokenstream::DelimSpan; use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::hygiene; -use rustc_data_structures::stable_hasher::{HashStable, - StableHasher, StableHasherResult, - ToStableHashKey}; +use rustc_data_structures::stable_hasher::{ + HashStable, StableHasher, StableHasherResult, ToStableHashKey, +}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use smallvec::SmallVec; @@ -32,9 +31,9 @@ fn compute_ignored_attr_names() -> FxHashSet { } /// This is the context state available during incr. comp. hashing. It contains -/// enough information to transform DefIds and HirIds into stable DefPaths (i.e. -/// a reference to the TyCtxt) and it holds a few caches for speeding up various -/// things (e.g., each DefId/DefPath is only hashed once). +/// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e., +/// a reference to the `TyCtxt`) and it holds a few caches for speeding up various +/// things (e.g., each `DefId`/`DefPath` is only hashed once). #[derive(Clone)] pub struct StableHashingContext<'a> { sess: &'a Session, @@ -46,7 +45,7 @@ pub struct StableHashingContext<'a> { node_id_hashing_mode: NodeIdHashingMode, // Very often, we are hashing something that does not need the - // CachingSourceMapView, so we initialize it lazily. + // `CachingSourceMapView`, so we initialize it lazily. raw_source_map: &'a SourceMap, caching_source_map: Option>, } @@ -57,24 +56,24 @@ pub enum NodeIdHashingMode { HashDefPath, } -/// The BodyResolver allows to map a BodyId to the corresponding hir::Body. -/// We could also just store a plain reference to the hir::Crate but we want +/// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`. +/// We could also just store a plain reference to the `hir::Crate` but we want /// to avoid that the crate is used to get untracked access to all of the HIR. #[derive(Clone, Copy)] struct BodyResolver<'tcx>(&'tcx hir::Crate); impl<'tcx> BodyResolver<'tcx> { - // Return a reference to the hir::Body with the given BodyId. - // DOES NOT DO ANY TRACKING, use carefully. + /// Returns a reference to the `hir::Body` with the given `BodyId`. + /// **Does not do any tracking**; use carefully. fn body(self, id: hir::BodyId) -> &'tcx hir::Body { self.0.body(id) } } impl<'a> StableHashingContext<'a> { - // The `krate` here is only used for mapping BodyIds to Bodies. - // Don't use it for anything else or you'll run the risk of - // leaking data out of the tracking system. + /// The `krate` here is only used for mapping `BodyId`s to `Body`s. + /// Don't use it for anything else or you'll run the risk of + /// leaking data out of the tracking system. #[inline] pub fn new(sess: &'a Session, krate: &'a hir::Crate, @@ -217,9 +216,7 @@ impl<'a> StableHashingContextProvider<'a> for StableHashingContext<'a> { } } -impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> { -} - +impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> {} impl<'a> HashStable> for hir::BodyId { fn hash_stable(&self, @@ -292,16 +289,15 @@ impl<'a> ToStableHashKey> for ast::NodeId { } impl<'a> HashStable> for Span { - - // Hash a span in a stable way. We can't directly hash the span's BytePos - // fields (that would be similar to hashing pointers, since those are just - // offsets into the SourceMap). Instead, we hash the (file name, line, column) - // triple, which stays the same even if the containing SourceFile has moved - // within the SourceMap. - // Also note that we are hashing byte offsets for the column, not unicode - // codepoint offsets. For the purpose of the hash that's sufficient. - // Also, hashing filenames is expensive so we avoid doing it twice when the - // span starts and ends in the same file, which is almost always the case. + /// Hashes a span in a stable way. We can't directly hash the span's `BytePos` + /// fields (that would be similar to hashing pointers, since those are just + /// offsets into the `SourceMap`). Instead, we hash the (file name, line, column) + /// triple, which stays the same even if the containing `SourceFile` has moved + /// within the `SourceMap`. + /// Also note that we are hashing byte offsets for the column, not unicode + /// codepoint offsets. For the purpose of the hash that's sufficient. + /// Also, hashing filenames is expensive so we avoid doing it twice when the + /// span starts and ends in the same file, which is almost always the case. fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { @@ -340,7 +336,7 @@ impl<'a> HashStable> for Span { } std_hash::Hash::hash(&TAG_VALID_SPAN, hasher); - // We truncate the stable_id hash and line and col numbers. The chances + // We truncate the stable ID hash and line and column numbers. The chances // of causing a collision this way should be minimal. std_hash::Hash::hash(&(file_lo.name_hash as u64), hasher); diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index fb981d961129f..6e6492d0426f2 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -5,8 +5,10 @@ use crate::hir; use crate::hir::map::DefPathHash; use crate::hir::def_id::{DefId, LocalDefId, CrateNum, CRATE_DEF_INDEX}; use crate::ich::{StableHashingContext, NodeIdHashingMode, Fingerprint}; -use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, - StableHasher, StableHasherResult}; + +use rustc_data_structures::stable_hasher::{ + HashStable, ToStableHashKey, StableHasher, StableHasherResult, +}; use smallvec::SmallVec; use std::mem; use syntax::ast; @@ -82,9 +84,9 @@ for hir::ItemLocalId { } } -// The following implementations of HashStable for ItemId, TraitItemId, and -// ImplItemId deserve special attention. Normally we do not hash NodeIds within -// the HIR, since they just signify a HIR nodes own path. But ItemId et al +// The following implementations of HashStable for `ItemId`, `TraitItemId`, and +// `ImplItemId` deserve special attention. Normally we do not hash `NodeId`s within +// the HIR, since they just signify a HIR nodes own path. But `ItemId` et al // are used when another item in the HIR is *referenced* and we certainly // want to pick up on a reference changing its target, so we hash the NodeIds // in "DefPath Mode". @@ -131,7 +133,6 @@ impl<'a> HashStable> for hir::ImplItemId { } } - impl_stable_hash_for!(struct ast::Label { ident }); @@ -241,7 +242,7 @@ impl<'a> HashStable> for hir::ImplItem { } } -impl_stable_hash_for!(enum ::syntax::ast::CrateSugar { +impl_stable_hash_for!(enum ast::CrateSugar { JustCrate, PubCrate, }); @@ -365,8 +366,7 @@ impl<'a> HashStable> for hir::def_id::DefIndex { } } -impl<'a> ToStableHashKey> -for hir::def_id::DefIndex { +impl<'a> ToStableHashKey> for hir::def_id::DefIndex { type KeyType = DefPathHash; #[inline] diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index be7669fcad875..f230c53728748 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -204,7 +204,7 @@ impl<'a> HashStable> for ty::TyVid { fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { - // TyVid values are confined to an inference context and hence + // `TyVid` values are confined to an inference context and hence // should not be hashed. bug!("ty::TyKind::hash_stable() - can't hash a TyVid {:?}.", *self) } @@ -214,7 +214,7 @@ impl<'a> HashStable> for ty::IntVid { fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { - // IntVid values are confined to an inference context and hence + // `IntVid` values are confined to an inference context and hence // should not be hashed. bug!("ty::TyKind::hash_stable() - can't hash an IntVid {:?}.", *self) } @@ -224,7 +224,7 @@ impl<'a> HashStable> for ty::FloatVid { fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { - // FloatVid values are confined to an inference context and hence + // `FloatVid` values are confined to an inference context and hence // should not be hashed. bug!("ty::TyKind::hash_stable() - can't hash a FloatVid {:?}.", *self) } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index cc28567e2fc9e..8638f42976f04 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1321,13 +1321,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { T: TypeFoldable<'tcx>, { if !value.needs_infer() { - return value.clone(); // avoid duplicated subst-folding + return value.clone(); // Avoid duplicated subst-folding. } let mut r = resolve::OpportunisticVarResolver::new(self); value.fold_with(&mut r) } - /// Returns first unresolved variable contained in `T`. In the + /// Returns the first unresolved variable contained in `T`. In the /// process of visiting `T`, this will resolve (where possible) /// type variables in `T`, but it never constructs the final, /// resolved type, so it's more efficient than @@ -1462,7 +1462,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None); - // this can get called from typeck (by euv), and moves_by_default + // This can get called from typeck (by euv), and `moves_by_default` // rightly refuses to work with inference variables, but // moves_by_default has a cache, which we want to use in other // cases. @@ -1482,7 +1482,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { closure_kind_ty.to_opt_closure_kind() } - /// Obtain the signature of a closure. For closures, unlike + /// Obtains the signature of a closure. For closures, unlike /// `tcx.fn_sig(def_id)`, this method will work during the /// type-checking of the enclosing function and return the closure /// signature in its partially inferred state. diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 77df93080cd16..c658120b95df3 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -16,32 +16,32 @@ use self::TargetLint::*; -use std::slice; -use rustc_data_structures::sync::{ReadGuard, Lock, ParallelIterator, join, par_iter}; +use crate::hir; +use crate::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use crate::hir::intravisit as hir_visit; +use crate::hir::intravisit::Visitor; +use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData}; use crate::lint::{EarlyLintPass, LateLintPass, EarlyLintPassObject, LateLintPassObject}; use crate::lint::{LintArray, Level, Lint, LintId, LintPass, LintBuffer}; use crate::lint::builtin::BuiltinLintDiagnostics; use crate::lint::levels::{LintLevelSets, LintLevelsBuilder}; use crate::middle::privacy::AccessLevels; -use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use crate::session::{config, early_error, Session}; use crate::ty::{self, print::Printer, subst::Kind, TyCtxt, Ty}; use crate::ty::layout::{LayoutError, LayoutOf, TyLayout}; use crate::util::nodemap::FxHashMap; use crate::util::common::time; +use errors::DiagnosticBuilder; +use std::slice; use std::default::Default as StdDefault; +use rustc_data_structures::sync::{ReadGuard, Lock, ParallelIterator, join, par_iter}; +use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use syntax::ast; use syntax::edition; -use syntax_pos::{MultiSpan, Span, symbol::Symbol}; -use errors::DiagnosticBuilder; -use crate::hir; -use crate::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use crate::hir::intravisit as hir_visit; -use crate::hir::intravisit::Visitor; -use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData}; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit as ast_visit; +use syntax_pos::{MultiSpan, Span, symbol::Symbol}; /// Information about the registered lints. /// diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index e33f8e27871b2..5b490b701267d 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -875,12 +875,12 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool { ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external" ExpnKind::Macro(MacroKind::Bang, _) => { if expn_data.def_site.is_dummy() { - // dummy span for the def_site means it's an external macro + // Dummy span for the `def_site` means it's an external macro. return true; } match sess.source_map().span_to_snippet(expn_data.def_site) { Ok(code) => !code.starts_with("macro_rules"), - // no snippet = external macro or compiler-builtin expansion + // No snippet means external macro or compiler-builtin expansion. Err(_) => true, } } @@ -888,7 +888,7 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool { } } -/// Returns whether `span` originates in a derive macro's expansion +/// Returns `true` if `span` originates in a derive-macro's expansion. pub fn in_derive_expansion(span: Span) -> bool { if let ExpnKind::Macro(MacroKind::Derive, _) = span.ctxt().outer_expn_data().kind { return true; diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 53c099c0b4339..93bb301f0951a 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -16,17 +16,17 @@ struct EntryContext<'a, 'tcx> { map: &'a hir_map::Map<'tcx>, - // The top-level function called 'main' + /// The top-level function called 'main'. main_fn: Option<(HirId, Span)>, - // The function that has attribute named 'main' + /// The function that has attribute named 'main'. attr_main_fn: Option<(HirId, Span)>, - // The function that has the attribute 'start' on it + /// The function that has the attribute 'start' on it. start_fn: Option<(HirId, Span)>, - // The functions that one might think are 'main' but aren't, e.g. - // main functions not defined at the top level. For diagnostics. + /// The functions that one might think are 'main' but aren't, e.g. + /// main functions not defined at the top level. For diagnostics. non_main_fns: Vec<(HirId, Span)> , } @@ -39,11 +39,11 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { } fn visit_trait_item(&mut self, _trait_item: &'tcx TraitItem) { - // entry fn is never a trait item + // Entry fn is never a trait item. } fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem) { - // entry fn is never an impl item + // Entry fn is never a trait item. } } @@ -54,7 +54,7 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> { *ty == config::CrateType::Executable }); if !any_exe { - // No need to find a main function + // No need to find a main function. return None; } @@ -148,7 +148,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De } else if let Some((hir_id, _)) = visitor.main_fn { Some((tcx.hir().local_def_id(hir_id), EntryFnType::Main)) } else { - // No main function + // There is no main function. let mut err = struct_err!(tcx.sess, E0601, "`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE)); if !visitor.non_main_fns.is_empty() { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 222c2a405d65b..de6dadabcbf56 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -596,7 +596,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } hir::StmtKind::Item(_) => { - // we don't visit nested items in this visitor, + // We don't visit nested items in this visitor, // only the fn body we were given. } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 6b04600eb75f8..6dfd7a7f94378 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -3,10 +3,8 @@ //! Language items are items that represent concepts intrinsic to the language //! itself. Examples are: //! -//! * Traits that specify "kinds"; e.g., "Sync", "Send". -//! -//! * Traits that represent operators; e.g., "Add", "Sub", "Index". -//! +//! * Traits that specify "kinds"; e.g., `Sync`, `Send`. +//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`. //! * Functions called by the compiler itself. pub use self::LangItem::*; @@ -151,11 +149,11 @@ impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> { } fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { - // at present, lang items are always items, not trait items + // At present, lang items are always items, not trait items. } fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { - // at present, lang items are always items, not impl items + // At present, lang items are always items, not impl items. } } @@ -204,7 +202,7 @@ impl LanguageItemCollector<'tcx> { } } -/// Extract the first `lang = "$name"` out of a list of attributes. +/// Extracts the first `lang = "$name"` out of a list of attributes. /// The attributes `#[panic_handler]` and `#[alloc_error_handler]` /// are also extracted out when found. pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { @@ -216,7 +214,7 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { })) } -/// Traverse and collect all the lang items in all crates. +/// Traverses and collects all the lang items in all crates. pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems { // Initialize the collector. let mut collector = LanguageItemCollector::new(tcx); @@ -367,7 +365,7 @@ language_item_table! { MaybeUninitLangItem, "maybe_uninit", maybe_uninit, Target::Union; - // Align offset for stride != 1, must not panic. + // Align offset for stride != 1; must not panic. AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn; TerminationTraitLangItem, "termination", termination, Target::Trait; @@ -378,7 +376,7 @@ language_item_table! { impl<'tcx> TyCtxt<'tcx> { /// Returns the `DefId` for a given `LangItem`. - /// If not found, fatally abort compilation. + /// If not found, fatally aborts compilation. pub fn require_lang_item(&self, lang_item: LangItem, span: Option) -> DefId { self.lang_items().require(lang_item).unwrap_or_else(|msg| { if let Some(span) = span { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 28aa86ef9afb2..b9d8a4ec68fad 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -6,29 +6,27 @@ //! //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html +use crate::hir; +use crate::hir::Node; +use crate::hir::def_id::DefId; +use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use crate::hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local}; use crate::ich::{StableHashingContext, NodeIdHashingMode}; use crate::util::nodemap::{FxHashMap, FxHashSet}; -use crate::ty; +use crate::ty::{self, DefIdTree, TyCtxt}; +use crate::ty::query::Providers; -use std::mem; -use std::fmt; +use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use rustc_macros::HashStable; use syntax::source_map; use syntax_pos::{Span, DUMMY_SP}; -use crate::ty::{DefIdTree, TyCtxt}; -use crate::ty::query::Providers; -use crate::hir; -use crate::hir::Node; -use crate::hir::def_id::DefId; -use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use crate::hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local}; -use rustc_data_structures::indexed_vec::Idx; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, - StableHasherResult}; +use std::fmt; +use std::mem; -/// Scope represents a statically-describable scope that can be -/// used to bound the lifetime/region for values. +/// Represents a statically-describable scope that can be used to +/// bound the lifetime/region for values. /// /// `Node(node_id)`: Any AST node that has any scope at all has the /// `Node(node_id)` scope. Other variants represent special cases not @@ -225,7 +223,7 @@ pub struct ScopeTree { /// have lifetime parameters free in this body. root_parent: Option, - /// `parent_map` maps from a scope ID to the enclosing scope id; + /// Maps from a scope ID to the enclosing scope id; /// this is usually corresponding to the lexical nesting, though /// in the case of closures the parent scope is the innermost /// conditional expression or repeating block. (Note that the @@ -233,17 +231,17 @@ pub struct ScopeTree { /// the closure itself.) parent_map: FxHashMap, - /// `var_map` maps from a variable or binding ID to the block in - /// which that variable is declared. + /// Maps from a variable or binding ID to the block in which that + /// variable is declared. var_map: FxHashMap, - /// maps from a `NodeId` to the associated destruction scope (if any) + /// Maps from a `NodeId` to the associated destruction scope (if any). destruction_scopes: FxHashMap, - /// `rvalue_scopes` includes entries for those expressions whose cleanup scope is - /// larger than the default. The map goes from the expression id - /// to the cleanup scope id. For rvalues not present in this - /// table, the appropriate cleanup scope is the innermost + /// `rvalue_scopes` includes entries for those expressions whose + /// cleanup scope is larger than the default. The map goes from the + /// expression ID to the cleanup scope id. For rvalues not present in + /// this table, the appropriate cleanup scope is the innermost /// enclosing statement, conditional expression, or repeating /// block (see `terminating_scopes`). /// In constants, None is used to indicate that certain expressions @@ -318,7 +316,7 @@ pub struct ScopeTree { /// 4. By `2.` and `3.`, `D` is *statically* storage-dead at `U`, /// QED. /// - /// I don't think this property relies on `3.` in an essential way - it + /// This property ought to not on (3) in an essential way -- it /// is probably still correct even if we have "unrestricted" terminating /// scopes. However, why use the complicated proof when a simple one /// works? @@ -341,20 +339,20 @@ pub struct ScopeTree { #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)] pub struct YieldData { - /// `Span` of the yield. + /// The `Span` of the yield. pub span: Span, - /// The number of expressions and patterns appearing before the `yield` in the body + 1. + /// The number of expressions and patterns appearing before the `yield` in the body plus one. pub expr_and_pat_count: usize, pub source: hir::YieldSource, } #[derive(Debug, Copy, Clone)] pub struct Context { - /// the root of the current region tree. This is typically the id + /// The root of the current region tree. This is typically the id /// of the innermost fn body. Each fn forms its own disjoint tree /// in the region hierarchy. These fn bodies are themselves /// arranged into a tree. See the "Modeling closures" section of - /// the README in infer::region_constraints for more + /// the README in `infer::region_constraints` for more /// details. root_id: Option, @@ -369,15 +367,15 @@ pub struct Context { struct RegionResolutionVisitor<'tcx> { tcx: TyCtxt<'tcx>, - // The number of expressions and patterns visited in the current body + // The number of expressions and patterns visited in the current body. expr_and_pat_count: usize, // When this is `true`, we record the `Scopes` we encounter // when processing a Yield expression. This allows us to fix // up their indices. pessimistic_yield: bool, - // Stores scopes when pessimistic_yield is true. + // Stores scopes when `pessimistic_yield` is `true`. fixup_scopes: Vec, - // Generated scope tree: + // The generated scope tree. scope_tree: ScopeTree, cx: Context, @@ -411,7 +409,7 @@ struct ExprLocatorVisitor { expr_and_pat_count: usize, } -// This visitor has to have the same visit_expr calls as RegionResolutionVisitor +// This visitor has to have the same `visit_expr` calls as `RegionResolutionVisitor` // since `expr_count` is compared against the results there. impl<'tcx> Visitor<'tcx> for ExprLocatorVisitor { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { @@ -456,7 +454,7 @@ impl<'tcx> ScopeTree { assert!(prev.is_none()); } - // record the destruction scopes for later so we can query them + // Record the destruction scopes for later so we can query them. if let ScopeData::Destruction = child.data { self.destruction_scopes.insert(child.item_local_id(), child); } @@ -478,7 +476,7 @@ impl<'tcx> ScopeTree { self.destruction_scopes.get(&n).cloned() } - /// Records that `sub_closure` is defined within `sup_closure`. These ids + /// Records that `sub_closure` is defined within `sup_closure`. These IDs /// should be the ID of the block that is the fn body, which is /// also the root of the region hierarchy for that fn. fn record_closure_parent(&mut self, @@ -505,14 +503,14 @@ impl<'tcx> ScopeTree { self.rvalue_scopes.insert(var, lifetime); } + /// Returns the narrowest scope that encloses `id`, if any. pub fn opt_encl_scope(&self, id: Scope) -> Option { - //! Returns the narrowest scope that encloses `id`, if any. self.parent_map.get(&id).cloned().map(|(p, _)| p) } + /// Returns the narrowest scope that encloses `id`, if any. #[allow(dead_code)] // used in cfg pub fn encl_scope(&self, id: Scope) -> Scope { - //! Returns the narrowest scope that encloses `id`, if any. self.opt_encl_scope(id).unwrap() } @@ -522,16 +520,15 @@ impl<'tcx> ScopeTree { bug!("no enclosing scope for id {:?}", var_id)) } + /// Returns the scope when the temp created by `expr_id` will be cleaned up. pub fn temporary_scope(&self, expr_id: hir::ItemLocalId) -> Option { - //! Returns the scope when temp created by expr_id will be cleaned up - - // check for a designated rvalue scope + // Check for a designated rvalue scope. if let Some(&s) = self.rvalue_scopes.get(&expr_id) { debug!("temporary_scope({:?}) = {:?} [custom]", expr_id, s); return s; } - // else, locate the innermost terminating scope + // Otherwise, locate the innermost terminating scope // if there's one. Static items, for instance, won't // have an enclosing scope, hence no scope will be // returned. @@ -552,9 +549,8 @@ impl<'tcx> ScopeTree { return None; } + /// Returns the lifetime of the variable `id`. pub fn var_region(&self, id: hir::ItemLocalId) -> ty::RegionKind { - //! Returns the lifetime of the variable `id`. - let scope = ty::ReScope(self.var_scope(id)); debug!("var_region({:?}) = {:?}", id, scope); scope @@ -589,7 +585,7 @@ impl<'tcx> ScopeTree { return true; } - /// Returns the ID of the innermost containing body + /// Returns the ID of the innermost containing body. pub fn containing_body(&self, mut scope: Scope) -> Option { loop { if let ScopeData::CallSite = scope.data { diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 3d33e249536c7..1f604877841a7 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -27,7 +27,7 @@ impl<'a> HashStable> for Cache { fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { - // do nothing + // Do nothing. } } diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 13552a61acb0e..e81096c3066f1 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -13,7 +13,7 @@ use rustc_data_structures::sorted_map::SortedMap; use rustc_target::abi::HasDataLayout; use std::borrow::Cow; -// NOTE: When adding new fields, make sure to adjust the Snapshot impl in +// NOTE: When adding new fields, make sure to adjust the `Snapshot` impl in // `src/librustc_mir/interpret/snapshot.rs`. #[derive( Clone, @@ -27,7 +27,7 @@ use std::borrow::Cow; RustcDecodable, HashStable, )] -pub struct Allocation { +pub struct Allocation { /// The actual bytes of the allocation. /// Note that the bytes of a pointer represent the offset of the pointer. bytes: Vec, @@ -42,7 +42,7 @@ pub struct Allocation { pub size: Size, /// The alignment of the allocation to detect unaligned reads. pub align: Align, - /// Whether the allocation is mutable. + /// `true` if the allocation is mutable. /// Also used by codegen to determine if a static should be put into mutable memory, /// which happens for `static mut` and `static` with interior mutability. pub mutability: Mutability, @@ -50,7 +50,6 @@ pub struct Allocation { pub extra: Extra, } - pub trait AllocationExtra: ::std::fmt::Debug + Clone { // There is no constructor in here because the constructor's type depends // on `MemoryKind`, and making things sufficiently generic leads to painful @@ -92,7 +91,7 @@ pub trait AllocationExtra: ::std::fmt::Debug + Clone { } } -// For Tag=() and no extra state, we have is a trivial implementation. +// For `Tag = ()` and no extra state, we have a trivial implementation. impl AllocationExtra<()> for () { } // The constructors are all without extra; the extra gets added by a machine hook later. @@ -185,7 +184,7 @@ impl Allocation { impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Allocation {} -/// Byte accessors +/// Byte accessors. impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Just a small local helper function to avoid a bit of code repetition. /// Returns the range of this allocation that was meant. @@ -195,7 +194,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { offset: Size, size: Size ) -> Range { - let end = offset + size; // this does overflow checking + let end = offset + size; // This does overflow checking. assert_eq!( end.bytes() as usize as u64, end.bytes(), "cannot handle this access on this host architecture" @@ -232,7 +231,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { self.check_defined(ptr, size)?; self.check_relocations(cx, ptr, size)?; } else { - // We still don't want relocations on the *edges* + // We still don't want relocations on the *edges*. self.check_relocation_edges(cx, ptr, size)?; } @@ -241,7 +240,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(&self.bytes[range]) } - /// Check that these bytes are initialized and not pointer bytes, and then return them + /// Checks that these bytes are initialized and not pointer bytes, and then return them /// as a slice. /// /// It is the caller's responsibility to check bounds and alignment beforehand. @@ -293,7 +292,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } } -/// Reading and writing +/// Reading and writing. impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Reads bytes until a `0` is encountered. Will error if the end of the allocation is reached /// before a `0` is found. @@ -329,9 +328,9 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { allow_ptr_and_undef: bool, ) -> InterpResult<'tcx> { - // Check bounds and relocations on the edges + // Check bounds and relocations on the edges. self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; - // Check undef and ptr + // Check undef and ptr. if !allow_ptr_and_undef { self.check_defined(ptr, size)?; self.check_relocations(cx, ptr, size)?; @@ -372,12 +371,12 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(()) } - /// Read a *non-ZST* scalar + /// Reads a *non-ZST* scalar. /// - /// zsts can't be read out of two reasons: - /// * byteorder cannot work with zero element buffers - /// * in order to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers - /// being valid for ZSTs + /// ZSTs can't be read for two reasons: + /// * byte-order cannot work with zero-element buffers; + /// * in order to obtain a `Pointer`, we need to check for ZSTness anyway due to integer + /// pointers being valid for ZSTs. /// /// It is the caller's responsibility to check bounds and alignment beforehand. pub fn read_scalar( @@ -387,20 +386,20 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { size: Size ) -> InterpResult<'tcx, ScalarMaybeUndef> { - // get_bytes_unchecked tests relocation edges + // `get_bytes_unchecked` tests relocation edges. let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; // Undef check happens *after* we established that the alignment is correct. - // We must not return Ok() for unaligned pointers! + // We must not return `Ok()` for unaligned pointers! if self.check_defined(ptr, size).is_err() { - // this inflates undefined bytes to the entire scalar, even if only a few - // bytes are undefined + // This inflates undefined bytes to the entire scalar, even if only a few + // bytes are undefined. return Ok(ScalarMaybeUndef::Undef); } - // Now we do the actual reading + // Now we do the actual reading. let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap(); - // See if we got a pointer + // See if we got a pointer. if size != cx.data_layout().pointer_size { - // *Now* better make sure that the inside also is free of relocations. + // *Now*, we better make sure that the inside is free of relocations too. self.check_relocations(cx, ptr, size)?; } else { match self.relocations.get(&ptr.offset) { @@ -415,7 +414,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size))) } - /// Read a pointer-sized scalar. + /// Reads a pointer-sized scalar. /// /// It is the caller's responsibility to check bounds and alignment beforehand. pub fn read_ptr_sized( @@ -427,12 +426,12 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { self.read_scalar(cx, ptr, cx.data_layout().pointer_size) } - /// Write a *non-ZST* scalar + /// Writes a *non-ZST* scalar. /// - /// zsts can't be read out of two reasons: - /// * byteorder cannot work with zero element buffers - /// * in oder to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers - /// being valid for ZSTs + /// ZSTs can't be read for two reasons: + /// * byte-order cannot work with zero-element buffers; + /// * in order to obtain a `Pointer`, we need to check for ZSTness anyway due to integer + /// pointers being valid for ZSTs. /// /// It is the caller's responsibility to check bounds and alignment beforehand. pub fn write_scalar( @@ -460,7 +459,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { let dst = self.get_bytes_mut(cx, ptr, type_size)?; write_target_uint(endian, dst, bytes).unwrap(); - // See if we have to also write a relocation + // See if we have to also write a relocation. match val { Scalar::Ptr(val) => { self.relocations.insert( @@ -474,7 +473,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(()) } - /// Write a pointer-sized scalar. + /// Writes a pointer-sized scalar. /// /// It is the caller's responsibility to check bounds and alignment beforehand. pub fn write_ptr_sized( @@ -489,9 +488,9 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } } -/// Relocations +/// Relocations. impl<'tcx, Tag: Copy, Extra> Allocation { - /// Returns all relocations overlapping with the given ptr-offset pair. + /// Returns all relocations overlapping with the given pointer-offset pair. pub fn get_relocations( &self, cx: &impl HasDataLayout, @@ -501,7 +500,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // We have to go back `pointer_size - 1` bytes, as that one would still overlap with // the beginning of this range. let start = ptr.offset.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1); - let end = ptr.offset + size; // this does overflow checking + let end = ptr.offset + size; // This does overflow checking. self.relocations.range(Size::from_bytes(start)..end) } @@ -561,7 +560,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { Ok(()) } - /// Error if there are relocations overlapping with the edges of the + /// Errors if there are relocations overlapping with the edges of the /// given memory range. #[inline] fn check_relocation_edges( @@ -577,7 +576,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { } -/// Undefined bytes +/// Undefined bytes. impl<'tcx, Tag, Extra> Allocation { /// Checks that a range of bytes is defined. If not, returns the `ReadUndefBytes` /// error which will report the first byte which is undefined. @@ -618,7 +617,7 @@ pub struct AllocationDefinedness { /// Transferring the definedness mask to other allocations. impl Allocation { - /// Creates a run-length encoding of the undef_mask. + /// Creates a run-length encoding of the undef mask. pub fn compress_undef_range( &self, src: Pointer, @@ -631,10 +630,10 @@ impl Allocation { // Therefor we precompute a compressed version of the undef mask of the source value and // then write it back `repeat` times without computing any more information from the source. - // a precomputed cache for ranges of defined/undefined bits + // A precomputed cache for ranges of defined/undefined bits // 0000010010001110 will become - // [5, 1, 2, 1, 3, 3, 1] - // where each element toggles the state + // `[5, 1, 2, 1, 3, 3, 1]`, + // where each element toggles the state. let mut ranges = smallvec::SmallVec::<[u64; 1]>::new(); let initial = self.undef_mask.get(src.offset); @@ -642,7 +641,7 @@ impl Allocation { let mut cur = initial; for i in 1..size.bytes() { - // FIXME: optimize to bitshift the current undef block's bits and read the top bit + // FIXME: optimize to bitshift the current undef block's bits and read the top bit. if self.undef_mask.get(src.offset + Size::from_bytes(i)) == cur { cur_len += 1; } else { @@ -657,7 +656,7 @@ impl Allocation { AllocationDefinedness { ranges, initial, } } - /// Apply multiple instances of the run-length encoding to the undef_mask. + /// Applies multiple instances of the run-length encoding to the undef mask. pub fn mark_compressed_undef_range( &mut self, defined: &AllocationDefinedness, @@ -665,7 +664,7 @@ impl Allocation { size: Size, repeat: u64, ) { - // an optimization where we can just overwrite an entire range of definedness bits if + // An optimization where we can just overwrite an entire range of definedness bits if // they are going to be uniformly `1` or `0`. if defined.ranges.len() <= 1 { self.undef_mask.set_range_inbounds( @@ -694,9 +693,9 @@ impl Allocation { } } -/// Relocations +/// Relocations. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] -pub struct Relocations(SortedMap); +pub struct Relocations(SortedMap); impl Relocations { pub fn new() -> Self { @@ -838,8 +837,8 @@ impl UndefMask { let (blocka, bita) = bit_index(start); let (blockb, bitb) = bit_index(end); if blocka == blockb { - // first set all bits but the first `bita` - // then unset the last `64 - bitb` bits + // First set all bits except the first `bita`, + // then unset the last `64 - bitb` bits. let range = if bitb == 0 { u64::max_value() << bita } else { @@ -854,24 +853,24 @@ impl UndefMask { } // across block boundaries if new_state { - // set bita..64 to 1 + // Set `bita..64` to `1`. self.blocks[blocka] |= u64::max_value() << bita; - // set 0..bitb to 1 + // Set `0..bitb` to `1`. if bitb != 0 { self.blocks[blockb] |= u64::max_value() >> (64 - bitb); } - // fill in all the other blocks (much faster than one bit at a time) + // Fill in all the other blocks (much faster than one bit at a time). for block in (blocka + 1) .. blockb { self.blocks[block] = u64::max_value(); } } else { - // set bita..64 to 0 + // Set `bita..64` to `0`. self.blocks[blocka] &= !(u64::max_value() << bita); - // set 0..bitb to 0 + // Set `0..bitb` to `0`. if bitb != 0 { self.blocks[blockb] &= !(u64::max_value() >> (64 - bitb)); } - // fill in all the other blocks (much faster than one bit at a time) + // Fill in all the other blocks (much faster than one bit at a time). for block in (blocka + 1) .. blockb { self.blocks[block] = 0; } @@ -908,7 +907,7 @@ impl UndefMask { let additional_blocks = amount.bytes() / Self::BLOCK_SIZE + 1; assert_eq!(additional_blocks as usize as u64, additional_blocks); self.blocks.extend( - // FIXME(oli-obk): optimize this by repeating `new_state as Block` + // FIXME(oli-obk): optimize this by repeating `new_state as Block`. iter::repeat(0).take(additional_blocks as usize), ); } diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 589a021241d94..09c822f7508a0 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -1,23 +1,21 @@ -use std::{fmt, env}; +use super::{RawConst, Pointer, CheckInAllocMsg, ScalarMaybeUndef}; use crate::hir; use crate::hir::map::definitions::DefPathData; use crate::mir; use crate::ty::{self, Ty, layout}; use crate::ty::layout::{Size, Align, LayoutError}; -use rustc_target::spec::abi::Abi; -use rustc_macros::HashStable; - -use super::{RawConst, Pointer, CheckInAllocMsg, ScalarMaybeUndef}; +use crate::ty::query::TyCtxtAt; use backtrace::Backtrace; - -use crate::ty::query::TyCtxtAt; use errors::DiagnosticBuilder; - +use rustc_macros::HashStable; +use rustc_target::spec::abi::Abi; use syntax_pos::{Pos, Span}; use syntax::symbol::Symbol; +use std::{fmt, env}; + #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)] pub enum ErrorHandled { /// Already reported a lint or an error for this evaluation. @@ -582,7 +580,7 @@ pub type InterpResult<'tcx, T = ()> = Result>; impl fmt::Display for InterpError<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Forward `Display` to `Debug` + // Forward `Display` to `Debug`. write!(f, "{:?}", self) } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 1ec95c29a4a6f..6f7e11877d5fb 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -1,4 +1,4 @@ -//! An interpreter for MIR used in CTFE and by miri +//! An interpreter for MIR used in CTFE and by miri. #[macro_export] macro_rules! err_unsup { @@ -107,21 +107,21 @@ pub use self::allocation::{Allocation, AllocationExtra, Relocations, UndefMask}; pub use self::pointer::{Pointer, PointerArithmetic, CheckInAllocMsg}; -use std::fmt; use crate::mir; use crate::hir::def_id::DefId; use crate::ty::{self, TyCtxt, Instance, subst::UnpackedKind}; +use crate::ty::codec::TyDecoder; use crate::ty::layout::{self, Size}; use std::io; +use std::fmt; +use std::num::NonZeroU32; +use std::sync::atomic::{AtomicU32, Ordering}; use rustc_serialize::{Encoder, Decodable, Encodable}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::{Lock as Mutex, HashMapExt}; +use rustc_data_structures::sync::{Lock, HashMapExt}; use rustc_data_structures::tiny_list::TinyList; use rustc_macros::HashStable; use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian, BigEndian}; -use crate::ty::codec::TyDecoder; -use std::sync::atomic::{AtomicU32, Ordering}; -use std::num::NonZeroU32; /// Uniquely identifies a specific constant or static. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable, HashStable)] @@ -152,8 +152,8 @@ pub fn specialized_encode_alloc_id<'tcx, E: Encoder>( tcx: TyCtxt<'tcx>, alloc_id: AllocId, ) -> Result<(), E::Error> { - let alloc: GlobalAlloc<'tcx> = - tcx.alloc_map.lock().get(alloc_id).expect("no value for AllocId"); + let alloc: GlobalAlloc<'tcx> = tcx.alloc_map.lock().get(alloc_id) + .expect("no value for given alloc ID"); match alloc { GlobalAlloc::Memory(alloc) => { trace!("encoding {:?} with {:#?}", alloc_id, alloc); @@ -166,8 +166,8 @@ pub fn specialized_encode_alloc_id<'tcx, E: Encoder>( fn_instance.encode(encoder)?; } GlobalAlloc::Static(did) => { - // referring to statics doesn't need to know about their allocations, - // just about its DefId + // References to statics doesn't need to know about their allocations, + // just about its `DefId`. AllocDiscriminant::Static.encode(encoder)?; did.encode(encoder)?; } @@ -187,19 +187,18 @@ enum State { } pub struct AllocDecodingState { - // For each AllocId we keep track of which decoding state it's currently in. - decoding_state: Vec>, + // For each `AllocId`, we keep track of which decoding state it's currently in. + decoding_state: Vec>, // The offsets of each allocation in the data stream. data_offsets: Vec, } impl AllocDecodingState { - pub fn new_decoding_session(&self) -> AllocDecodingSession<'_> { static DECODER_SESSION_ID: AtomicU32 = AtomicU32::new(0); let counter = DECODER_SESSION_ID.fetch_add(1, Ordering::SeqCst); - // Make sure this is never zero + // Make sure this is never zero. let session_id = DecodingSessionId::new((counter & 0x7FFFFFFF) + 1).unwrap(); AllocDecodingSession { @@ -208,10 +207,10 @@ impl AllocDecodingState { } } - pub fn new(data_offsets: Vec) -> AllocDecodingState { - let decoding_state = vec![Mutex::new(State::Empty); data_offsets.len()]; + pub fn new(data_offsets: Vec) -> Self { + let decoding_state = vec![Lock::new(State::Empty); data_offsets.len()]; - AllocDecodingState { + Self { decoding_state, data_offsets, } @@ -225,23 +224,23 @@ pub struct AllocDecodingSession<'s> { } impl<'s> AllocDecodingSession<'s> { - // Decodes an AllocId in a thread-safe way. + /// Decodes an `AllocId` in a thread-safe way. pub fn decode_alloc_id(&self, decoder: &mut D) -> Result where D: TyDecoder<'tcx>, { - // Read the index of the allocation + // Read the index of the allocation. let idx = decoder.read_u32()? as usize; let pos = self.state.data_offsets[idx] as usize; - // Decode the AllocDiscriminant now so that we know if we have to reserve an - // AllocId. + // Decode the `AllocDiscriminant` now so that we know if we have to reserve an + // `AllocId`. let (alloc_kind, pos) = decoder.with_position(pos, |decoder| { let alloc_kind = AllocDiscriminant::decode(decoder)?; Ok((alloc_kind, decoder.position())) })?; - // Check the decoding state, see if it's already decoded or if we should + // Check the decoding state to see if it's already decoded or if we should // decode it here. let alloc_id = { let mut entry = self.state.decoding_state[idx].lock(); @@ -251,11 +250,11 @@ impl<'s> AllocDecodingSession<'s> { return Ok(alloc_id); } ref mut entry @ State::Empty => { - // We are allowed to decode + // We are allowed to decode. match alloc_kind { AllocDiscriminant::Alloc => { // If this is an allocation, we need to reserve an - // AllocId so we can decode cyclic graphs. + // `AllocId` so we can decode cyclic graphs. let alloc_id = decoder.tcx().alloc_map.lock().reserve(); *entry = State::InProgress( TinyList::new_single(self.session_id), @@ -263,8 +262,8 @@ impl<'s> AllocDecodingSession<'s> { Some(alloc_id) }, AllocDiscriminant::Fn | AllocDiscriminant::Static => { - // Fns and statics cannot be cyclic and their AllocId - // is determined later by interning + // Fns and statics cannot be cyclic, and their `AllocId` + // is determined later by interning. *entry = State::InProgressNonAlloc( TinyList::new_single(self.session_id)); None @@ -273,9 +272,9 @@ impl<'s> AllocDecodingSession<'s> { } State::InProgressNonAlloc(ref mut sessions) => { if sessions.contains(&self.session_id) { - bug!("This should be unreachable") + bug!("this should be unreachable"); } else { - // Start decoding concurrently + // Start decoding concurrently. sessions.insert(self.session_id); None } @@ -285,7 +284,7 @@ impl<'s> AllocDecodingSession<'s> { // Don't recurse. return Ok(alloc_id) } else { - // Start decoding concurrently + // Start decoding concurrently. sessions.insert(self.session_id); Some(alloc_id) } @@ -293,20 +292,20 @@ impl<'s> AllocDecodingSession<'s> { } }; - // Now decode the actual data + // Now decode the actual data. let alloc_id = decoder.with_position(pos, |decoder| { match alloc_kind { AllocDiscriminant::Alloc => { - let allocation = <&'tcx Allocation as Decodable>::decode(decoder)?; - // We already have a reserved AllocId. + let alloc = <&'tcx Allocation as Decodable>::decode(decoder)?; + // We already have a reserved `AllocId`. let alloc_id = alloc_id.unwrap(); - trace!("decoded alloc {:?} {:#?}", alloc_id, allocation); - decoder.tcx().alloc_map.lock().set_alloc_id_same_memory(alloc_id, allocation); + trace!("decoded alloc {:?}: {:#?}", alloc_id, alloc); + decoder.tcx().alloc_map.lock().set_alloc_id_same_memory(alloc_id, alloc); Ok(alloc_id) }, AllocDiscriminant::Fn => { assert!(alloc_id.is_none()); - trace!("creating fn alloc id"); + trace!("creating fn alloc ID"); let instance = ty::Instance::decode(decoder)?; trace!("decoded fn alloc instance: {:?}", instance); let alloc_id = decoder.tcx().alloc_map.lock().create_fn_alloc(instance); @@ -314,8 +313,9 @@ impl<'s> AllocDecodingSession<'s> { }, AllocDiscriminant::Static => { assert!(alloc_id.is_none()); - trace!("creating extern static alloc id at"); + trace!("creating extern static alloc ID"); let did = DefId::decode(decoder)?; + trace!("decoded static def-ID: {:?}", did); let alloc_id = decoder.tcx().alloc_map.lock().create_static_alloc(did); Ok(alloc_id) } @@ -340,7 +340,7 @@ impl fmt::Display for AllocId { /// a static, or a "real" allocation with some data in it. #[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable, HashStable)] pub enum GlobalAlloc<'tcx> { - /// The alloc ID is used as a function pointer + /// The alloc ID is used as a function pointer. Function(Instance<'tcx>), /// The alloc ID points to a "lazy" static variable that did not get computed (yet). /// This is also used to break the cycle in recursive statics. @@ -349,17 +349,19 @@ pub enum GlobalAlloc<'tcx> { Memory(&'tcx Allocation), } +#[derive(Clone)] pub struct AllocMap<'tcx> { - /// Lets you know what an `AllocId` refers to. + /// Maps `AllocId`s to their corresponding allocations. alloc_map: FxHashMap>, /// Used to ensure that statics and functions only get one associated `AllocId`. /// Should never contain a `GlobalAlloc::Memory`! - /// FIXME: Should we just have two separate dedup maps for statics and functions each? + // + // FIXME: Should we just have two separate dedup maps for statics and functions each? dedup: FxHashMap, AllocId>, /// The `AllocId` to assign to the next requested ID. - /// Always incremented, never gets smaller. + /// Always incremented; never gets smaller. next_id: AllocId, } @@ -389,7 +391,7 @@ impl<'tcx> AllocMap<'tcx> { next } - /// Reserve a new ID *if* this allocation has not been dedup-reserved before. + /// Reserves a new ID *if* this allocation has not been dedup-reserved before. /// Should only be used for function pointers and statics, we don't want /// to dedup IDs for "real" memory! fn reserve_and_set_dedup(&mut self, alloc: GlobalAlloc<'tcx>) -> AllocId { @@ -430,17 +432,17 @@ impl<'tcx> AllocMap<'tcx> { } }); if is_generic { - // Get a fresh ID + // Get a fresh ID. let id = self.reserve(); self.alloc_map.insert(id, GlobalAlloc::Function(instance)); id } else { - // Deduplicate + // Deduplicate. self.reserve_and_set_dedup(GlobalAlloc::Function(instance)) } } - /// Intern the `Allocation` and return a new `AllocId`, even if there's already an identical + /// Interns the `Allocation` and return a new `AllocId`, even if there's already an identical /// `Allocation` with a different `AllocId`. /// Statics with identical content will still point to the same `Allocation`, i.e., /// their data will be deduplicated through `Allocation` interning -- but they @@ -465,19 +467,19 @@ impl<'tcx> AllocMap<'tcx> { pub fn unwrap_memory(&self, id: AllocId) -> &'tcx Allocation { match self.get(id) { Some(GlobalAlloc::Memory(mem)) => mem, - _ => bug!("expected allocation id {} to point to memory", id), + _ => bug!("expected allocation ID {} to point to memory", id), } } - /// Freeze an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to + /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to /// call this function twice, even with the same `Allocation` will ICE the compiler. pub fn set_alloc_id_memory(&mut self, id: AllocId, mem: &'tcx Allocation) { if let Some(old) = self.alloc_map.insert(id, GlobalAlloc::Memory(mem)) { - bug!("tried to set allocation id {}, but it was already existing as {:#?}", id, old); + bug!("tried to set allocation ID {}, but it was already existing as {:#?}", id, old); } } - /// Freeze an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called + /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called /// twice for the same `(AllocId, Allocation)` pair. fn set_alloc_id_same_memory(&mut self, id: AllocId, mem: &'tcx Allocation) { self.alloc_map.insert_same(id, GlobalAlloc::Memory(mem)); @@ -513,7 +515,7 @@ pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result // Methods to facilitate working with signed integers stored in a u128 //////////////////////////////////////////////////////////////////////////////// -/// Truncate `value` to `size` bits and then sign-extend it to 128 bits +/// Truncates `value` to `size` bits and then sign-extend it to 128 bits /// (i.e., if it is negative, fill with 1's on the left). #[inline] pub fn sign_extend(value: u128, size: Size) -> u128 { @@ -522,14 +524,14 @@ pub fn sign_extend(value: u128, size: Size) -> u128 { // Truncated until nothing is left. return 0; } - // sign extend + // Sign-extend it. let shift = 128 - size; - // shift the unsigned value to the left - // and back to the right as signed (essentially fills with FF on the left) + // Shift the unsigned value to the left, then shift back to the right as signed + // (essentially fills with FF on the left). (((value << shift) as i128) >> shift) as u128 } -/// Truncate `value` to `size` bits. +/// Truncates `value` to `size` bits. #[inline] pub fn truncate(value: u128, size: Size) -> u128 { let size = size.bits(); @@ -538,6 +540,6 @@ pub fn truncate(value: u128, size: Size) -> u128 { return 0; } let shift = 128 - size; - // truncate (shift left to drop out leftover values, shift right to fill with zeroes) + // Truncate (shift left to drop out leftover values, shift right to fill with zeroes). (value << shift) >> shift } diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index b55e6bc54bc5f..1bb4d9ea4d6d9 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -86,18 +86,17 @@ pub trait PointerArithmetic: layout::HasDataLayout { impl PointerArithmetic for T {} - -/// Pointer is generic over the type that represents a reference to Allocations, +/// `Pointer` is generic over the type that represents a reference to `Allocation`s, /// thus making it possible for the most convenient representation to be used in /// each context. /// -/// Defaults to the index based and loosely coupled AllocId. +/// Defaults to the index based and loosely coupled `AllocId`. /// /// Pointer is also generic over the `Tag` associated with each pointer, /// which is used to do provenance tracking during execution. #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash, HashStable)] -pub struct Pointer { +pub struct Pointer { pub alloc_id: Id, pub offset: Size, pub tag: Tag, @@ -117,7 +116,7 @@ impl fmt::Debug for Pointer<(), Id> { } } -/// Produces a `Pointer` which points to the beginning of the Allocation +/// Produces a `Pointer` which points to the beginning of the `Allocation`. impl From for Pointer { #[inline(always)] fn from(alloc_id: AllocId) -> Self { diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 3da5a65c37932..d72d879059369 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -91,7 +91,7 @@ impl<'tcx> ConstValue<'tcx> { /// of a simple value or a pointer into another `Allocation` #[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash, HashStable)] -pub enum Scalar { +pub enum Scalar { /// The raw bytes of a simple value. Raw { /// The first `size` bytes of `data` are the value. @@ -359,7 +359,7 @@ impl<'tcx, Tag> Scalar { #[inline(always)] pub fn assert_bits(self, target_size: Size) -> u128 { - self.to_bits(target_size).expect("Expected Raw bits but got a Pointer") + self.to_bits(target_size).expect("expected Raw bits but got a Pointer") } /// Do not call this method! Use either `assert_ptr` or `force_ptr`. @@ -374,7 +374,7 @@ impl<'tcx, Tag> Scalar { #[inline(always)] pub fn assert_ptr(self) -> Pointer { - self.to_ptr().expect("Expected a Pointer but got Raw bits") + self.to_ptr().expect("expected a Pointer but got Raw bits") } /// Do not call this method! Dispatch based on the type instead. @@ -482,8 +482,8 @@ impl From> for Scalar { } } -#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)] -pub enum ScalarMaybeUndef { +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, RustcEncodable, RustcDecodable)] +pub enum ScalarMaybeUndef { Scalar(Scalar), Undef, } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 8956cbb2baefc..da2faeb4e1ebf 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -18,6 +18,7 @@ use crate::ty::{ self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt, UserTypeAnnotationIndex, }; + use polonius_engine::Atom; use rustc_data_structures::bit_set::BitMatrix; use rustc_data_structures::fx::FxHashSet; @@ -70,7 +71,7 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> { /// The various "big phases" that MIR goes through. /// -/// Warning: ordering of variants is significant +/// Warning: ordering of variants is significant. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum MirPhase { Build = 0, @@ -80,16 +81,16 @@ pub enum MirPhase { } impl MirPhase { - /// Gets the index of the current MirPhase within the set of all MirPhases. + /// Gets the index of the current MirPhase within the set of all `MirPhase`s. pub fn phase_index(&self) -> usize { *self as usize } } -/// Lowered representation of a single function. +/// The lowered representation of a single function. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Body<'tcx> { - /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock` + /// A list of basic blocks. References to basic block use a newtyped index type `BasicBlock` /// that indexes into this vector. basic_blocks: IndexVec>, @@ -100,7 +101,7 @@ pub struct Body<'tcx> { /// us to see the difference and forego optimization on the inlined promoted items. pub phase: MirPhase, - /// List of source scopes; these are referenced by statements + /// A list of source scopes; these are referenced by statements /// and used for debuginfo. Indexed by a `SourceScope`. pub source_scopes: IndexVec, @@ -108,10 +109,10 @@ pub struct Body<'tcx> { /// needn't) be tracked across crates. pub source_scope_local_data: ClearCrossCrate>, - /// Yields type of the function, if it is a generator. + /// The yield type of the function, if it is a generator. pub yield_ty: Option>, - /// Generator drop glue + /// Generator drop glue. pub generator_drop: Option>>, /// The layout of a generator. Produced by the state transformation. @@ -124,10 +125,10 @@ pub struct Body<'tcx> { /// variables and temporaries. pub local_decls: LocalDecls<'tcx>, - /// User type annotations + /// User type annotations. pub user_type_annotations: CanonicalUserTypeAnnotations<'tcx>, - /// Number of arguments this function takes. + /// The number of arguments this function takes. /// /// Starting at local 1, `arg_count` locals will be provided by the caller /// and can be assumed to be initialized. @@ -143,10 +144,11 @@ pub struct Body<'tcx> { /// Names and capture modes of all the closure upvars, assuming /// the first argument is either the closure or a reference to it. + // // NOTE(eddyb) This is *strictly* a temporary hack for codegen // debuginfo generation, and will be removed at some point. - // Do **NOT** use it for anything else, upvar information should not be - // in the MIR, please rely on local crate HIR or other side-channels. + // Do **NOT** use it for anything else; upvar information should not be + // in the MIR, so please rely on local crate HIR or other side-channels. pub __upvar_debuginfo_codegen_only_do_not_use: Vec, /// Mark this MIR of a const context other than const functions as having converted a `&&` or @@ -157,10 +159,10 @@ pub struct Body<'tcx> { /// List of places where control flow was destroyed. Used for error reporting. pub control_flow_destroyed: Vec<(Span, String)>, - /// A span representing this MIR, for error reporting + /// A span representing this MIR, for error reporting. pub span: Span, - /// A cache for various calculations + /// A cache for various calculations. cache: cache::Cache, } @@ -177,7 +179,7 @@ impl<'tcx> Body<'tcx> { span: Span, control_flow_destroyed: Vec<(Span, String)>, ) -> Self { - // We need `arg_count` locals, and one for the return place + // We need `arg_count` locals, and one for the return place. assert!( local_decls.len() >= arg_count + 1, "expected at least {} locals, got {}", @@ -384,12 +386,12 @@ impl<'tcx> Body<'tcx> { true } - /// Returns the return type, it always return first element from `local_decls` array + /// Returns the return type; it always return first element from `local_decls` array. pub fn return_ty(&self) -> Ty<'tcx> { self.local_decls[RETURN_PLACE].ty } - /// Gets the location of the terminator for the given block + /// Gets the location of the terminator for the given block. pub fn terminator_loc(&self, bb: BasicBlock) -> Location { Location { block: bb, statement_index: self[bb].statements.len() } } @@ -463,7 +465,7 @@ impl rustc_serialize::UseSpecializedDecodable for ClearCrossCrate< /// Most passes can work with it as a whole, within a single function. #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, HashStable)] pub struct SourceInfo { - /// Source span for the AST pertaining to this MIR entity. + /// The source span for the AST pertaining to this MIR entity. pub span: Span, /// The source scope, keeping track of which bindings can be @@ -591,18 +593,20 @@ impl Atom for Local { /// Classifies locals into categories. See `Body::local_kind`. #[derive(PartialEq, Eq, Debug, HashStable)] pub enum LocalKind { - /// User-declared variable binding + /// User-declared variable binding. Var, - /// Compiler-introduced temporary + /// Compiler-introduced temporary. Temp, - /// Function argument + /// Function argument. Arg, - /// Location of function's return value + /// Location of function's return value. ReturnPointer, } #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct VarBindingForm<'tcx> { + /// The `HirId` of the variable. + pub var_id: hir::HirId, /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`? pub binding_mode: ty::BindingMode, /// If an explicit type was provided for this variable binding, @@ -619,7 +623,7 @@ pub struct VarBindingForm<'tcx> { /// (b) it gives a way to separate this case from the remaining cases /// for diagnostics. pub opt_match_place: Option<(Option>, Span)>, - /// Span of the pattern in which this variable was bound. + /// The span of the pattern in which this variable was bound. pub pat_span: Span, } @@ -652,6 +656,7 @@ pub enum ImplicitSelfKind { CloneTypeFoldableAndLiftImpls! { BindingForm<'tcx>, } impl_stable_hash_for!(struct self::VarBindingForm<'tcx> { + var_id, binding_mode, opt_ty_info, opt_match_place, @@ -721,12 +726,12 @@ impl_stable_hash_for!(struct BlockTailInfo { tail_result_is_ignored }); /// argument, or the return place. #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct LocalDecl<'tcx> { - /// `let mut x` vs `let x`. + /// Whether this is a mutable minding (i.e., `let x` or `let mut x`). /// /// Temporaries and the return place are always mutable. pub mutability: Mutability, - /// Some(binding_mode) if this corresponds to a user-declared local variable. + /// `Some(binding_mode)` if this corresponds to a user-declared local variable. /// /// This is solely used for local diagnostics when generating /// warnings/errors when compiling the current crate, and @@ -760,7 +765,7 @@ pub struct LocalDecl<'tcx> { /// intervening statement context). pub is_block_tail: Option, - /// Type of this local. + /// The type of this local. pub ty: Ty<'tcx>, /// If the user manually ascribed a type to this variable, @@ -769,7 +774,7 @@ pub struct LocalDecl<'tcx> { /// region inference. pub user_ty: UserTypeProjections, - /// Name of the local, used in debuginfo and pretty-printing. + /// The name of the local, used in debuginfo and pretty-printing. /// /// Note that function arguments can also have this set to `Some(_)` /// to generate better debuginfo. @@ -837,8 +842,8 @@ pub struct LocalDecl<'tcx> { /// ROOT SCOPE /// │{ argument x: &str } /// │ - /// │ │{ #[allow(unused_mut)] } // this is actually split into 2 scopes - /// │ │ // in practice because I'm lazy. + /// │ │{ #[allow(unused_mut)] } // This is actually split into 2 scopes + /// │ │ // in practice because I'm lazy. /// │ │ /// │ │↠x.source_info.scope /// │ │↠`x.parse().unwrap()` @@ -852,7 +857,7 @@ pub struct LocalDecl<'tcx> { /// │ /// │ │{ let x: u32 } /// │ │↠x.visibility_scope - /// │ │↠`drop(x)` // this accesses `x: u32` + /// │ │↠`drop(x)` // This accesses `x: u32`. /// ``` pub source_info: SourceInfo, @@ -872,9 +877,7 @@ impl<'tcx> LocalDecl<'tcx> { match self.is_user_variable { Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { binding_mode: ty::BindingMode::BindByValue(_), - opt_ty_info: _, - opt_match_place: _, - pat_span: _, + .. }))) => true, Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(ImplicitSelfKind::Imm))) => true, @@ -890,9 +893,7 @@ impl<'tcx> LocalDecl<'tcx> { match self.is_user_variable { Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { binding_mode: ty::BindingMode::BindByValue(_), - opt_ty_info: _, - opt_match_place: _, - pat_span: _, + .. }))) => true, Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_))) => true, @@ -1038,16 +1039,16 @@ pub struct Terminator<'tcx> { #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum TerminatorKind<'tcx> { - /// block should have one successor in the graph; we jump there + /// Block should have one successor in the graph; we jump there. Goto { target: BasicBlock }, - /// operand evaluates to an integer; jump depending on its value - /// to one of the targets, and otherwise fallback to `otherwise` + /// Operand evaluates to an integer; jump depending on its value + /// to one of the targets, and otherwise fallback to `otherwise`. SwitchInt { - /// discriminant value being tested + /// The discriminant value being tested. discr: Operand<'tcx>, - /// type of value being tested + /// The type of value being tested. switch_ty: Ty<'tcx>, /// Possible values. The locations to branch to in each case @@ -1057,6 +1058,7 @@ pub enum TerminatorKind<'tcx> { /// Possible branch sites. The last element of this vector is used /// for the otherwise branch, so targets.len() == values.len() + 1 /// should hold. + // // This invariant is quite non-obvious and also could be improved. // One way to make this invariant is to have something like this instead: // @@ -1069,7 +1071,7 @@ pub enum TerminatorKind<'tcx> { }, /// Indicates that the landing pad is finished and unwinding should - /// continue. Emitted by build::scope::diverge_cleanup. + /// continue. Emitted by `build::scope::diverge_cleanup`. Resume, /// Indicates that the landing pad is finished and that the process @@ -1083,10 +1085,10 @@ pub enum TerminatorKind<'tcx> { /// Indicates a terminator that can never be reached. Unreachable, - /// Drop the Place + /// Drop the `Place`. Drop { location: Place<'tcx>, target: BasicBlock, unwind: Option }, - /// Drop the Place and assign the new value over it. This ensures + /// Drop the `Place` and assign the new value over it. This ensures /// that the assignment to `P` occurs *even if* the destructor for /// place unwinds. Its semantics are best explained by the /// elaboration: @@ -1119,9 +1121,9 @@ pub enum TerminatorKind<'tcx> { unwind: Option, }, - /// Block ends with a call of a converging function + /// Block ends with a call of a converging function. Call { - /// The function that’s being called + /// The function that’s being called. func: Operand<'tcx>, /// Arguments the function is called with. /// These are owned by the callee, which is free to modify them. @@ -1132,7 +1134,7 @@ pub enum TerminatorKind<'tcx> { destination: Option<(Place<'tcx>, BasicBlock)>, /// Cleanups to be done if the call unwinds. cleanup: Option, - /// Whether this is from a call in HIR, rather than from an overloaded + /// `true` if this is from a call in HIR rather than from an overloaded /// operator. True for overloaded function call. from_hir_call: bool, }, @@ -1147,40 +1149,40 @@ pub enum TerminatorKind<'tcx> { cleanup: Option, }, - /// A suspend point + /// A suspend point. Yield { - /// The value to return + /// The value to return. value: Operand<'tcx>, - /// Where to resume to + /// Where to resume to. resume: BasicBlock, - /// Cleanup to be done if the generator is dropped at this suspend point + /// Cleanup to be done if the generator is dropped at this suspend point. drop: Option, }, - /// Indicates the end of the dropping of a generator + /// Indicates the end of the dropping of a generator. GeneratorDrop, /// A block where control flow only ever takes one real path, but borrowck /// needs to be more conservative. FalseEdges { - /// The target normal control flow will take + /// The target normal control flow will take. real_target: BasicBlock, /// A block control flow could conceptually jump to, but won't in - /// practice + /// practice. imaginary_target: BasicBlock, }, /// A terminator for blocks that only take one path in reality, but where we /// reserve the right to unwind in borrowck, even if it won't happen in practice. /// This can arise in infinite loops with no function calls for example. FalseUnwind { - /// The target normal control flow will take + /// The target normal control flow will take. real_target: BasicBlock, /// The imaginary cleanup block link. This particular path will never be taken /// in practice, but in order to avoid fragility we want to always /// consider it in borrowck. We don't want to accept programs which - /// pass borrowck only when panic=abort or some assertions are disabled - /// due to release vs. debug mode builds. This needs to be an Option because - /// of the remove_noop_landing_pads and no_landing_pads passes + /// pass borrowck only when `panic=abort` or some assertions are disabled + /// due to release vs. debug mode builds. This needs to be an `Option` because + /// of the `remove_noop_landing_pads` and `no_landing_pads` passes. unwind: Option, }, } @@ -1445,7 +1447,7 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { } impl<'tcx> TerminatorKind<'tcx> { - /// Write the "head" part of the terminator; that is, its name and the data it uses to pick the + /// Writes the "head" part of the terminator; that is, its name and the data it uses to pick the /// successor basic block, if any. The only information not included is the list of possible /// successors, which may be rendered differently between the text and the graphviz format. pub fn fmt_head(&self, fmt: &mut W) -> fmt::Result { @@ -1615,20 +1617,20 @@ pub enum StatementKind<'tcx> { Nop, } -/// `RetagKind` describes what kind of retag is to be performed. +/// Describes what kind of retag is to be performed. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, HashStable)] pub enum RetagKind { - /// The initial retag when entering a function + /// The initial retag when entering a function. FnEntry, - /// Retag preparing for a two-phase borrow + /// Retag preparing for a two-phase borrow. TwoPhase, - /// Retagging raw pointers + /// Retagging raw pointers. Raw, - /// A "normal" retag + /// A "normal" retag. Default, } -/// The `FakeReadCause` describes the type of pattern why a `FakeRead` statement exists. +/// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum FakeReadCause { /// Inject a fake read of the borrowed input at the end of each guards @@ -2171,7 +2173,7 @@ pub struct SourceScopeData { #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct SourceScopeLocalData { - /// A HirId with lint levels equivalent to this scope's lint levels. + /// An `HirId` with lint levels equivalent to this scope's lint levels. pub lint_root: hir::HirId, /// The unsafe block that contains this node. pub safety: Safety, @@ -2760,11 +2762,12 @@ impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> { #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)] pub struct Location { - /// the location is within this block + /// The block that the location is within. pub block: BasicBlock, - /// the location is the start of the statement; or, if `statement_index` - /// == num-statements, then the start of the terminator. + /// The location is the position of the start of the statement; or, if + /// `statement_index` equals the number of statements, then the start of the + /// terminator. pub statement_index: usize, } @@ -2827,7 +2830,7 @@ impl Location { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub enum UnsafetyViolationKind { General, - /// Permitted in const fn and regular fns. + /// Permitted in const fns and regular fns. GeneralAndConstFn, ExternStatic(hir::HirId), BorrowPacked(hir::HirId), @@ -2843,9 +2846,9 @@ pub struct UnsafetyViolation { #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct UnsafetyCheckResult { - /// Violations that are propagated *upwards* from this function + /// Violations that are propagated *upwards* from this function. pub violations: Lrc<[UnsafetyViolation]>, - /// unsafe blocks in this function, along with whether they are used. This is + /// Unsafe blocks in this function, along with whether they are used. This is /// used for the "unused_unsafe" lint. pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>, } @@ -2857,7 +2860,7 @@ newtype_index! { } } -/// The layout of generator state +/// The layout of generator state. #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct GeneratorLayout<'tcx> { /// The type of every local stored inside the generator. @@ -2873,10 +2876,11 @@ pub struct GeneratorLayout<'tcx> { pub storage_conflicts: BitMatrix, /// Names and scopes of all the stored generator locals. - /// NOTE(tmandry) This is *strictly* a temporary hack for codegen - /// debuginfo generation, and will be removed at some point. - /// Do **NOT** use it for anything else, local information should not be - /// in the MIR, please rely on local crate HIR or other side-channels. + // + // NOTE(tmandry) This is *strictly* a temporary hack for codegen + // debuginfo generation, and will be removed at some point. + // Do **NOT** use it for anything else, local information should not be + // in the MIR, please rely on local crate HIR or other side-channels. pub __local_debuginfo_codegen_only_do_not_use: IndexVec>, } @@ -2934,7 +2938,7 @@ pub struct BorrowCheckResult<'tcx> { /// instances assigned one of these same indices. Those regions will /// be substituted away by the creator. We use `ReClosureBound` in /// that case because the regions must be allocated in the global -/// TyCtxt, and hence we cannot use `ReVar` (which is what we use +/// `TyCtxt`, and hence we cannot use `ReVar` (which is what we use /// internally within the rest of the NLL code). #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct ClosureRegionRequirements<'tcx> { @@ -2950,8 +2954,8 @@ pub struct ClosureRegionRequirements<'tcx> { pub outlives_requirements: Vec>, } -/// Indicates an outlives constraint between a type or between two -/// free-regions declared on the closure. +/// Indicates an outlives-constraint between a type or between two +/// free regions declared on the closure. #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct ClosureOutlivesRequirement<'tcx> { // This region or type ... @@ -2967,11 +2971,11 @@ pub struct ClosureOutlivesRequirement<'tcx> { pub category: ConstraintCategory, } -/// Outlives constraints can be categorized to determine whether and why they +/// Outlives-constraints can be categorized to determine whether and why they /// are interesting (for error reporting). Order of variants indicates sort /// order of the category, thereby influencing diagnostic output. /// -/// See also [rustc_mir::borrow_check::nll::constraints] +/// See also [rustc_mir::borrow_check::nll::constraints]. #[derive( Copy, Clone, @@ -3019,7 +3023,7 @@ pub enum ConstraintCategory { Internal, } -/// The subject of a ClosureOutlivesRequirement -- that is, the thing +/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing /// that must outlive some region. #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub enum ClosureOutlivesSubject<'tcx> { @@ -3037,7 +3041,7 @@ pub enum ClosureOutlivesSubject<'tcx> { } /* - * TypeFoldable implementations for MIR types + * `TypeFoldable` implementations for MIR types */ CloneTypeFoldableAndLiftImpls! { diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index ef838114f6c36..4ebc2e72490d4 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -17,7 +17,6 @@ use crate::traits::query::{ use std::borrow::Cow; use syntax_pos::symbol::InternedString; - // Each of these queries corresponds to a function pointer field in the // `Providers` struct for requesting a value of that type, and a method // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way @@ -854,7 +853,7 @@ rustc_queries! { desc { "calculating the lang items map" } } - /// Returns all diagnostic items defined in all crates + /// Returns all diagnostic items defined in all crates. query all_diagnostic_items(_: CrateNum) -> &'tcx FxHashMap { eval_always desc { "calculating the diagnostic items map" } @@ -865,7 +864,7 @@ rustc_queries! { desc { "calculating the lang items defined in a crate" } } - /// Returns the diagnostic items defined in a crate + /// Returns the diagnostic items defined in a crate. query diagnostic_items(_: CrateNum) -> &'tcx FxHashMap { desc { "calculating the diagnostic items map in a crate" } } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 296c6ad19c1cf..27a33ced119df 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1,36 +1,36 @@ //! Contains infrastructure for configuring the compiler, including parsing -//! command line options. - -use std::str::FromStr; +//! command-line options. +use crate::lint; +use crate::middle::cstore; use crate::session::{early_error, early_warn, Session}; use crate::session::search_paths::SearchPath; +use rustc_data_structures::fx::FxHashSet; + use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel}; use rustc_target::spec::{Target, TargetTriple}; -use crate::lint; -use crate::middle::cstore; use syntax; use syntax::ast::{self, IntTy, UintTy, MetaItemKind}; use syntax::source_map::{FileName, FilePathMapping}; use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION}; +use syntax::parse::{ParseSess, new_parser_from_source_str}; use syntax::parse::token; -use syntax::parse; use syntax::symbol::{sym, Symbol}; use syntax::feature_gate::UnstableFeatures; -use errors::emitter::HumanReadableErrorType; +use errors::emitter::HumanReadableErrorType; use errors::{ColorConfig, FatalError, Handler}; use getopts; -use std::collections::{BTreeMap, BTreeSet}; -use std::collections::btree_map::Iter as BTreeMapIter; -use std::collections::btree_map::Keys as BTreeMapKeysIter; -use std::collections::btree_map::Values as BTreeMapValuesIter; -use rustc_data_structures::fx::FxHashSet; -use std::{fmt, str}; +use std::collections::{BTreeMap, BTreeSet}; +use std::collections::btree_map::{ + Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter, +}; +use std::fmt; +use std::str::{self, FromStr}; use std::hash::Hasher; use std::collections::hash_map::DefaultHasher; use std::iter::FromIterator; @@ -241,14 +241,14 @@ pub enum ErrorOutputType { } impl Default for ErrorOutputType { - fn default() -> ErrorOutputType { - ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto)) + fn default() -> Self { + Self::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto)) } } -// Use tree-based collections to cheaply get a deterministic Hash implementation. -// DO NOT switch BTreeMap out for an unsorted container type! That would break -// dependency tracking for command-line arguments. +/// Use tree-based collections to cheaply get a deterministic `Hash` implementation. +/// *Do not* switch `BTreeMap` out for an unsorted container type! That would break +/// dependency tracking for command-line arguments. #[derive(Clone, Hash)] pub struct OutputTypes(BTreeMap>); @@ -281,7 +281,7 @@ impl OutputTypes { self.0.len() } - // True if any of the output types require codegen or linking. + // Returns `true` if any of the output types require codegen or linking. pub fn should_codegen(&self) -> bool { self.0.keys().any(|k| match *k { OutputType::Bitcode @@ -295,9 +295,9 @@ impl OutputTypes { } } -// Use tree-based collections to cheaply get a deterministic Hash implementation. -// DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That -// would break dependency tracking for command-line arguments. +/// Use tree-based collections to cheaply get a deterministic `Hash` implementation. +/// *Do not* switch `BTreeMap` or `BTreeSet` out for an unsorted container type! That +/// would break dependency tracking for command-line arguments. #[derive(Clone, Hash)] pub struct Externs(BTreeMap); @@ -327,7 +327,7 @@ macro_rules! hash_option { ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => ({ if $sub_hashes.insert(stringify!($opt_name), $opt_expr as &dyn dep_tracking::DepTrackingHash).is_some() { - bug!("Duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name)) + bug!("duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name)) } }); } @@ -362,7 +362,7 @@ macro_rules! top_level_options { ); } -// The top-level command-line options struct +// The top-level command-line options struct. // // For each option, one has to specify how it behaves with regard to the // dependency tracking system of incremental compilation. This is done via the @@ -376,16 +376,16 @@ macro_rules! top_level_options { // Incremental compilation is not influenced by this option. // // If you add a new option to this struct or one of the sub-structs like -// CodegenOptions, think about how it influences incremental compilation. If in +// `CodegenOptions`, think about how it influences incremental compilation. If in // doubt, specify [TRACKED], which is always "correct" but might lead to // unnecessary re-compilation. top_level_options!( pub struct Options { // The crate config requested for the session, which may be combined - // with additional crate configurations during the compile process + // with additional crate configurations during the compile process. crate_types: Vec [TRACKED], optimize: OptLevel [TRACKED], - // Include the debug_assertions flag into dependency tracking, since it + // Include the `debug_assertions` flag in dependency tracking, since it // can influence whether overflow checks are done or not. debug_assertions: bool [TRACKED], debuginfo: DebugInfo [TRACKED], @@ -402,8 +402,8 @@ top_level_options!( test: bool [TRACKED], error_format: ErrorOutputType [UNTRACKED], - // if Some, enable incremental compilation, using the given - // directory to store intermediate results + // If `Some`, enable incremental compilation, using the given + // directory to store intermediate results. incremental: Option [UNTRACKED], debugging_opts: DebuggingOptions [TRACKED], @@ -418,7 +418,7 @@ top_level_options!( // written `extern crate name as std`. Defaults to `std`. Used by // out-of-tree drivers. alt_std_name: Option [TRACKED], - // Indicates how the compiler should treat unstable features + // Indicates how the compiler should treat unstable features. unstable_features: UnstableFeatures [TRACKED], // Indicates whether this run of the compiler is actually rustdoc. This @@ -434,12 +434,12 @@ top_level_options!( cli_forced_codegen_units: Option [UNTRACKED], cli_forced_thinlto_off: bool [UNTRACKED], - // Remap source path prefixes in all output (messages, object files, debug, etc) + // Remap source path prefixes in all output (messages, object files, debug, etc.). remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED], edition: Edition [TRACKED], - // Whether or not we're emitting JSON blobs about each artifact produced + // `true` if we're emitting JSON blobs about each artifact produced // by the compiler. json_artifact_notifications: bool [TRACKED], } @@ -468,7 +468,7 @@ pub enum BorrowckMode { } impl BorrowckMode { - /// Should we run the MIR-based borrow check, but also fall back + /// Returns whether we should run the MIR-based borrow check, but also fall back /// on the AST borrow check if the MIR-based one errors. pub fn migrate(self) -> bool { match self { @@ -477,7 +477,7 @@ impl BorrowckMode { } } - /// Should we emit the AST-based borrow checker errors? + /// Returns whether we should emit the AST-based borrow checker errors. pub fn use_ast(self) -> bool { match self { BorrowckMode::Mir => false, @@ -487,12 +487,13 @@ impl BorrowckMode { } pub enum Input { - /// Loads source from file + /// Load source code from a file. File(PathBuf), + /// Load source code from a string. Str { - /// String that is shown in place of a filename + /// A string that is shown in place of a filename. name: FileName, - /// Anonymous source string + /// An anonymous string containing the source code. input: String, }, } @@ -651,7 +652,7 @@ impl Options { FilePathMapping::new(self.remap_path_prefix.clone()) } - /// Returns `true` if there will be an output file generated + /// Returns `true` if there will be an output file generated. pub fn will_create_output_file(&self) -> bool { !self.debugging_opts.parse_only && // The file is just being parsed !self.debugging_opts.ls // The file is just being queried @@ -709,16 +710,14 @@ impl Passes { } } -/// Declare a macro that will define all CodegenOptions/DebuggingOptions fields and parsers all -/// at once. The goal of this macro is to define an interface that can be -/// programmatically used by the option parser in order to initialize the struct -/// without hardcoding field names all over the place. +/// Defines all `CodegenOptions`/`DebuggingOptions` fields and parsers all at once. The goal of this +/// macro is to define an interface that can be programmatically used by the option parser in order +/// to initialize the struct without hardcoding field names all over the place. /// -/// The goal is to invoke this macro once with the correct fields, and then this -/// macro generates all necessary code. The main gotcha of this macro is the -/// cgsetters module which is a bunch of generated code to parse an option into -/// its respective field in the struct. There are a few hand-written parsers for -/// parsing specific types of values in this module. +/// The goal is to invoke this macro once with the correct fields, and then this macro generates all +/// necessary code. The main gotcha of this macro is the cgsetters module which is a bunch of +/// generated code to parse an option into its respective field in the struct. There are a few +/// hand-written parsers for parsing specific types of values in this module. macro_rules! options { ($struct_name:ident, $setter_name:ident, $defaultfn:ident, $buildfn:ident, $prefix:expr, $outputname:expr, @@ -1539,7 +1538,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { ret } -/// Converts the crate cfg! configuration from String to Symbol. +/// Converts the crate `cfg!` configuration from `String` to `Symbol`. /// `rustc_interface::interface::Config` accepts this in the compiler configuration, /// but the symbol interner is not yet set up then, so we must convert it later. pub fn to_crate_config(cfg: FxHashSet<(String, Option)>) -> ast::CrateConfig { @@ -1550,9 +1549,9 @@ pub fn to_crate_config(cfg: FxHashSet<(String, Option)>) -> ast::CrateCo pub fn build_configuration(sess: &Session, mut user_cfg: ast::CrateConfig) -> ast::CrateConfig { // Combine the configuration requested by the session (command line) with - // some default and generated configuration items + // some default and generated configuration items. let default_cfg = default_configuration(sess); - // If the user wants a test runner, then add the test cfg + // If the user wants a test runner, then add the test cfg. if sess.opts.test { user_cfg.insert((sym::test, None)); } @@ -1851,13 +1850,13 @@ pub fn rustc_optgroups() -> Vec { opts } -// Convert strings provided as --cfg [cfgspec] into a crate_cfg +// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`. pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option)> { syntax::with_default_globals(move || { let cfg = cfgspecs.into_iter().map(|s| { - let sess = parse::ParseSess::new(FilePathMapping::empty()); + let sess = ParseSess::new(FilePathMapping::empty()); let filename = FileName::cfg_spec_source_code(&s); - let mut parser = parse::new_parser_from_source_str(&sess, filename, s.to_string()); + let mut parser = new_parser_from_source_str(&sess, filename, s.to_string()); macro_rules! error {($reason: expr) => { early_error(ErrorOutputType::default(), @@ -1917,7 +1916,7 @@ pub fn get_cmd_lint_options(matches: &getopts::Matches, (lint_opts, describe_lints, lint_cap) } -/// Parse the `--color` flag +/// Parses the `--color` flag. pub fn parse_color(matches: &getopts::Matches) -> ColorConfig { match matches.opt_str("color").as_ref().map(|s| &s[..]) { Some("auto") => ColorConfig::Auto, @@ -1929,7 +1928,7 @@ pub fn parse_color(matches: &getopts::Matches) -> ColorConfig { Some(arg) => early_error( ErrorOutputType::default(), &format!( - "argument for --color must be auto, \ + "argument for `--color` must be auto, \ always or never (instead was `{}`)", arg ), @@ -1974,16 +1973,16 @@ pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool) (json_rendered(json_color), json_artifact_notifications) } -/// Parse the `--error-format` flag +/// Parses the `--error-format` flag. pub fn parse_error_format( matches: &getopts::Matches, color: ColorConfig, json_rendered: HumanReadableErrorType, ) -> ErrorOutputType { - // We need the opts_present check because the driver will send us Matches + // We need the `opts_present` check because the driver will send us Matches // with only stable options if no unstable options are used. Since error-format - // is unstable, it will not be present. We have to use opts_present not - // opt_present because the latter will panic. + // is unstable, it will not be present. We have to use `opts_present` not + // `opt_present` because the latter will panic. let error_format = if matches.opts_present(&["error-format".to_owned()]) { match matches.opt_str("error-format").as_ref().map(|s| &s[..]) { None | @@ -2116,7 +2115,7 @@ pub fn build_session_options_and_crate_config( let mut codegen_units = cg.codegen_units; let mut disable_thinlto = false; - // Issue #30063: if user requests llvm-related output to one + // Issue #30063: if user requests LLVM-related output to one // particular path, disable codegen-units. let incompatible: Vec<_> = output_types .iter() @@ -2414,10 +2413,10 @@ pub fn build_session_options_and_crate_config( ) } - // We start out with a Vec<(Option, bool)>>, - // and later convert it into a BTreeSet<(Option, bool)> + // We start out with a `Vec<(Option, bool)>>`, + // and later convert it into a `BTreeSet<(Option, bool)>` // This allows to modify entries in-place to set their correct - // 'public' value + // 'public' value. let mut externs: BTreeMap = BTreeMap::new(); for (arg, private) in matches.opt_strs("extern").into_iter().map(|v| (v, false)) .chain(matches.opt_strs("extern-private").into_iter().map(|v| (v, true))) { @@ -2616,15 +2615,15 @@ impl fmt::Display for CrateType { /// The values of all command-line arguments that are relevant for dependency /// tracking are hashed into a single value that determines whether the /// incremental compilation cache can be re-used or not. This hashing is done -/// via the DepTrackingHash trait defined below, since the standard Hash -/// implementation might not be suitable (e.g., arguments are stored in a Vec, +/// via the `DepTrackingHash` trait defined below, since the standard `Hash` +/// implementation might not be suitable (e.g., arguments are stored in a `Vec`, /// the hash of which is order dependent, but we might not want the order of /// arguments to make a difference for the hash). /// -/// However, since the value provided by Hash::hash often *is* suitable, +/// However, since the value provided by `Hash::hash` often *is* suitable, /// especially for primitive types, there is the -/// impl_dep_tracking_hash_via_hash!() macro that allows to simply reuse the -/// Hash implementation for DepTrackingHash. It's important though that +/// `impl_dep_tracking_hash_via_hash!()` macro that allows to simply reuse the +/// `Hash` implementation for `DepTrackingHash`. It's important though that /// we have an opt-in scheme here, so one is hopefully forced to think about /// how the hash should be calculated when adding a new command-line argument. mod dep_tracking { @@ -2637,9 +2636,9 @@ mod dep_tracking { use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes, Passes, Sanitizer, LtoCli, LinkerPluginLto, SwitchWithOptPath, SymbolManglingVersion}; - use syntax::feature_gate::UnstableFeatures; use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel, TargetTriple}; use syntax::edition::Edition; + use syntax::feature_gate::UnstableFeatures; pub trait DepTrackingHash { fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index f01883d9634cd..8656ebb2e6d72 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -79,12 +79,12 @@ pub struct Session { /// if the value stored here has been affected by path remapping. pub working_dir: (PathBuf, bool), - // FIXME: lint_store and buffered_lints are not thread-safe, - // but are only used in a single thread + // FIXME: `lint_store` and `buffered_lints` are not thread-safe, + // but are only used in a single thread. pub lint_store: RwLock, pub buffered_lints: Lock>, - /// Set of (DiagnosticId, Option, message) tuples tracking + /// Set of `(DiagnosticId, Option, message)` tuples tracking /// (sub)diagnostics that have been set once, but should not be set again, /// in order to avoid redundantly verbose output (Issue #24690, #44953). pub one_time_diagnostics: Lock, String)>>, @@ -92,11 +92,11 @@ pub struct Session { pub plugin_attributes: Lock>, pub crate_types: Once>, pub dependency_formats: Once, - /// The crate_disambiguator is constructed out of all the `-C metadata` + /// The `crate_disambiguator` is constructed out of all the `-C metadata` /// arguments passed to the compiler. Its value together with the crate-name /// forms a unique global identifier for the crate. It is used to allow /// multiple crates with the same name to coexist. See the - /// rustc_codegen_llvm::back::symbol_names module for more information. + /// `rustc_codegen_llvm::back::symbol_names` module for more information. pub crate_disambiguator: Once, features: Once, @@ -111,7 +111,7 @@ pub struct Session { /// The maximum number of stackframes allowed in const eval. pub const_eval_stack_frame_limit: usize, - /// The metadata::creader module may inject an allocator/panic_runtime + /// The `metadata::creader` module may inject an allocator/`panic_runtime` /// dependency if it didn't already find one, and this tracks what was /// injected. pub allocator_kind: Once>, @@ -130,7 +130,7 @@ pub struct Session { /// Used by `-Z profile-queries` in `util::common`. pub profile_channel: Lock>>, - /// Used by -Z self-profile + /// Used by `-Z self-profile`. pub self_profiling: Option>, /// Some measurements that are being gathered during compilation. @@ -187,16 +187,16 @@ pub struct PerfStats { pub normalize_projection_ty: AtomicUsize, } -/// Enum to support dispatch of one-time diagnostics (in Session.diag_once) +/// Enum to support dispatch of one-time diagnostics (in `Session.diag_once`). enum DiagnosticBuilderMethod { Note, SpanNote, SpanSuggestion(String), // suggestion - // add more variants as needed to support one-time diagnostics + // Add more variants as needed to support one-time diagnostics. } -/// Diagnostic message ID—used by `Session.one_time_diagnostics` to avoid -/// emitting the same message more than once +/// Diagnostic message ID, used by `Session.one_time_diagnostics` to avoid +/// emitting the same message more than once. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum DiagnosticMessageId { ErrorId(u16), // EXXXX error code as integer @@ -408,7 +408,7 @@ impl Session { Some(next) => { self.next_node_id.set(ast::NodeId::from_usize(next)); } - None => bug!("Input too large, ran out of node ids!"), + None => bug!("input too large; ran out of node-IDs!"), } id @@ -440,11 +440,11 @@ impl Session { diag_builder.note(message); } DiagnosticBuilderMethod::SpanNote => { - let span = span_maybe.expect("span_note needs a span"); + let span = span_maybe.expect("`span_note` needs a span"); diag_builder.span_note(span, message); } DiagnosticBuilderMethod::SpanSuggestion(suggestion) => { - let span = span_maybe.expect("span_suggestion_* needs a span"); + let span = span_maybe.expect("`span_suggestion_*` needs a span"); diag_builder.span_suggestion( span, message, @@ -688,7 +688,7 @@ impl Session { pub fn must_not_eliminate_frame_pointers(&self) -> bool { // "mcount" function relies on stack pointer. - // See https://sourceware.org/binutils/docs/gprof/Implementation.html + // See . if self.instrument_mcount() { true } else if let Some(x) = self.opts.cg.force_frame_pointers { @@ -699,7 +699,7 @@ impl Session { } /// Returns the symbol name for the registrar function, - /// given the crate Svh and the function DefIndex. + /// given the crate `Svh` and the function `DefIndex`. pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator) -> String { format!( "__rustc_plugin_registrar_{}__", @@ -719,7 +719,7 @@ impl Session { &self.sysroot, self.opts.target_triple.triple(), &self.opts.search_paths, - // target_tlib_path==None means it's the same as host_tlib_path. + // `target_tlib_path == None` means it's the same as `host_tlib_path`. self.target_tlib_path.as_ref().unwrap_or(&self.host_tlib_path), kind, ) @@ -779,12 +779,12 @@ impl Session { if let IncrCompSession::Active { .. } = *incr_comp_session { } else { bug!( - "Trying to finalize IncrCompSession `{:?}`", + "trying to finalize `IncrCompSession` `{:?}`", *incr_comp_session - ) + ); } - // Note: This will also drop the lock file, thus unlocking the directory + // Note: this will also drop the lock file, thus unlocking the directory. *incr_comp_session = IncrCompSession::Finalized { session_directory: new_directory_path, }; @@ -800,13 +800,15 @@ impl Session { } => session_directory.clone(), IncrCompSession::InvalidBecauseOfErrors { .. } => return, _ => bug!( - "Trying to invalidate IncrCompSession `{:?}`", + "trying to invalidate `IncrCompSession` `{:?}`", *incr_comp_session ), }; - // Note: This will also drop the lock file, thus unlocking the directory - *incr_comp_session = IncrCompSession::InvalidBecauseOfErrors { session_directory }; + // Note: this will also drop the lock file, thus unlocking the directory. + *incr_comp_session = IncrCompSession::InvalidBecauseOfErrors { + session_directory, + }; } pub fn incr_comp_session_dir(&self) -> cell::Ref<'_, PathBuf> { @@ -815,8 +817,8 @@ impl Session { incr_comp_session, |incr_comp_session| match *incr_comp_session { IncrCompSession::NotInitialized => bug!( - "Trying to get session directory from IncrCompSession `{:?}`", - *incr_comp_session + "trying to get session directory from `IncrCompSession`: {:?}", + *incr_comp_session, ), IncrCompSession::Active { ref session_directory, @@ -1185,7 +1187,10 @@ fn build_session_( ); let target_cfg = config::build_target_config(&sopts, &span_diagnostic); - let p_s = parse::ParseSess::with_span_handler(span_diagnostic, source_map); + let parse_sess = parse::ParseSess::with_span_handler( + span_diagnostic, + source_map, + ); let sysroot = match &sopts.maybe_sysroot { Some(sysroot) => sysroot.clone(), None => filesearch::get_or_default_sysroot(), @@ -1214,7 +1219,7 @@ fn build_session_( let print_fuel = AtomicU64::new(0); let working_dir = env::current_dir().unwrap_or_else(|e| - p_s.span_diagnostic + parse_sess.span_diagnostic .fatal(&format!("Current directory is invalid: {}", e)) .raise() ); @@ -1232,7 +1237,7 @@ fn build_session_( opts: sopts, host_tlib_path, target_tlib_path, - parse_sess: p_s, + parse_sess, sysroot, local_crate_source_file, working_dir, diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index c759981b8e8c9..a7990c4af69fd 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -130,13 +130,13 @@ impl<'tcx> TyCtxt<'tcx> { } /// We say a method is *vtable safe* if it can be invoked on a trait - /// object. Note that object-safe traits can have some - /// non-vtable-safe methods, so long as they require `Self:Sized` or - /// otherwise ensure that they cannot be used when `Self=Trait`. + /// object. Note that object-safe traits can have some + /// non-vtable-safe methods, so long as they require `Self: Sized` or + /// otherwise ensure that they cannot be used when `Self = Trait`. pub fn is_vtable_safe_method(self, trait_def_id: DefId, method: &ty::AssocItem) -> bool { debug_assert!(self.generics_of(trait_def_id).has_self); debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method); - // Any method that has a `Self : Sized` requisite can't be called. + // Any method that has a `Self: Sized` bound cannot be called. if self.generics_require_sized_self(method.def_id) { return false; } @@ -350,15 +350,15 @@ impl<'tcx> TyCtxt<'tcx> { &sig.map_bound(|sig| sig.inputs()[0]), ); - // until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on. + // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on. // However, this is already considered object-safe. We allow it as a special case here. // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows - // `Receiver: Unsize dyn Trait]>` + // `Receiver: Unsize dyn Trait]>`. if receiver_ty != self.types.self_param { if !self.receiver_is_dispatchable(method, receiver_ty) { return Some(MethodViolationCode::UndispatchableReceiver); } else { - // sanity check to make sure the receiver actually has the layout of a pointer + // Do sanity check to make sure the receiver actually has the layout of a pointer. use crate::ty::layout::Abi; @@ -373,7 +373,7 @@ impl<'tcx> TyCtxt<'tcx> { } }; - // e.g., Rc<()> + // e.g., `Rc<()>` let unit_receiver_ty = self.receiver_for_self_ty( receiver_ty, self.mk_unit(), method.def_id ); @@ -395,7 +395,7 @@ impl<'tcx> TyCtxt<'tcx> { trait_def_id, self.mk_region(ty::ReStatic) ); - // e.g., Rc + // e.g., `Rc` let trait_object_receiver = self.receiver_for_self_ty( receiver_ty, trait_object_ty, method.def_id ); @@ -419,8 +419,8 @@ impl<'tcx> TyCtxt<'tcx> { None } - /// Performs a type substitution to produce the version of receiver_ty when `Self = self_ty` - /// e.g., for receiver_ty = `Rc` and self_ty = `Foo`, returns `Rc`. + /// Performs a type substitution to produce the version of `receiver_ty` when `Self = self_ty`. + /// For example, for `receiver_ty = Rc` and `self_ty = Foo`, returns `Rc`. fn receiver_for_self_ty( self, receiver_ty: Ty<'tcx>, diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs index 2ee63647aaded..b9557ceaa6d9f 100644 --- a/src/librustc/traits/query/evaluate_obligation.rs +++ b/src/librustc/traits/query/evaluate_obligation.rs @@ -1,7 +1,8 @@ use crate::infer::InferCtxt; use crate::infer::canonical::OriginalQueryValues; -use crate::traits::{EvaluationResult, PredicateObligation, SelectionContext, - TraitQueryMode, OverflowError}; +use crate::traits::{ + EvaluationResult, PredicateObligation, SelectionContext, TraitQueryMode, OverflowError, +}; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// Evaluates whether the predicate can be satisfied (by any means) diff --git a/src/librustc/traits/query/method_autoderef.rs b/src/librustc/traits/query/method_autoderef.rs index 6b9bdfd63f4d0..039dea1ffcd16 100644 --- a/src/librustc/traits/query/method_autoderef.rs +++ b/src/librustc/traits/query/method_autoderef.rs @@ -6,11 +6,11 @@ use crate::ty::Ty; pub struct CandidateStep<'tcx> { pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, pub autoderefs: usize, - // true if the type results from a dereference of a raw pointer. - // when assembling candidates, we include these steps, but not when - // picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods - // `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then - // `foo.by_raw_ptr()` will work and `foo.by_ref()` won't. + /// `true` if the type results from a dereference of a raw pointer. + /// when assembling candidates, we include these steps, but not when + /// picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods + /// `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then + /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't. pub from_unsafe_deref: bool, pub unsize: bool, } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 07d6f633143a2..7f3c62ec99470 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -512,7 +512,7 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>( (impl_trait_ref, impl_obligations) } -/// See `super::obligations_for_generics` +/// See [`super::obligations_for_generics`]. pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, recursion_depth: usize, param_env: ty::ParamEnv<'tcx>, @@ -562,7 +562,7 @@ impl<'tcx> TyCtxt<'tcx> { predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth) } - /// Cast a trait reference into a reference to one of its super + /// Casts a trait reference into a reference to one of its super /// traits; returns `None` if `target_trait_def_id` is not a /// supertrait. pub fn upcast_choices(self, @@ -571,7 +571,7 @@ impl<'tcx> TyCtxt<'tcx> { -> Vec> { if source_trait_ref.def_id() == target_trait_def_id { - return vec![source_trait_ref]; // shorcut the most common case + return vec![source_trait_ref]; // Shorcut the most common case. } supertraits(self, source_trait_ref) diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index 1ddc6780aca89..1aa21501129c8 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -284,9 +284,11 @@ where #[macro_export] macro_rules! __impl_decoder_methods { ($($name:ident -> $ty:ty;)*) => { - $(fn $name(&mut self) -> Result<$ty, Self::Error> { - self.opaque.$name() - })* + $( + fn $name(&mut self) -> Result<$ty, Self::Error> { + self.opaque.$name() + } + )* } } @@ -327,14 +329,17 @@ macro_rules! impl_arena_allocatable_decoders { macro_rules! implement_ty_decoder { ($DecoderName:ident <$($typaram:tt),*>) => { mod __ty_decoder_impl { - use super::$DecoderName; + use std::borrow::Cow; + + use rustc_serialize::{Decoder, SpecializedDecoder}; + use $crate::infer::canonical::CanonicalVarInfos; use $crate::ty; use $crate::ty::codec::*; use $crate::ty::subst::SubstsRef; use $crate::hir::def_id::{CrateNum}; - use rustc_serialize::{Decoder, SpecializedDecoder}; - use std::borrow::Cow; + + use super::$DecoderName; impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> { type Error = String; @@ -368,8 +373,8 @@ macro_rules! implement_ty_decoder { } } - // FIXME(#36588) These impls are horribly unsound as they allow - // the caller to pick any lifetime for 'tcx, including 'static, + // FIXME(#36588): These impls are horribly unsound as they allow + // the caller to pick any lifetime for `'tcx`, including `'static`, // by using the unspecialized proxies to them. arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 17c9e520bcea2..6867230f4ec43 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1,3 +1,5 @@ +// ignore-tidy-filelength + //! Type context book-keeping. use crate::arena::Arena; @@ -7,7 +9,7 @@ use crate::session::Session; use crate::session::config::{BorrowckMode, OutputFilenames}; use crate::session::config::CrateType; use crate::middle; -use crate::hir::{TraitCandidate, HirId, ItemKind, ItemLocalId, Node}; +use crate::hir::{self, TraitCandidate, HirId, ItemKind, ItemLocalId, Node}; use crate::hir::def::{Res, DefKind, Export}; use crate::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use crate::hir::map as hir_map; @@ -45,15 +47,16 @@ use crate::ty::CanonicalPolyFnSig; use crate::util::common::ErrorReported; use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet}; use crate::util::nodemap::{FxHashMap, FxHashSet}; + use errors::DiagnosticBuilder; -use smallvec::SmallVec; -use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap, - StableHasher, StableHasherResult, - StableVec}; use arena::SyncDroplessArena; +use smallvec::SmallVec; +use rustc_data_structures::stable_hasher::{ + HashStable, StableHasher, StableHasherResult, StableVec, hash_stable_hashmap, +}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; -use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal}; use rustc_data_structures::sharded::ShardedHashMap; +use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal}; use std::any::Any; use std::borrow::Borrow; use std::cmp::Ordering; @@ -74,8 +77,6 @@ use syntax::feature_gate; use syntax::symbol::{Symbol, InternedString, kw, sym}; use syntax_pos::Span; -use crate::hir; - pub struct AllArenas { pub interner: SyncDroplessArena, } @@ -91,10 +92,10 @@ impl AllArenas { type InternedSet<'tcx, T> = ShardedHashMap, ()>; pub struct CtxtInterners<'tcx> { - /// The arena that types, regions, etc are allocated from + /// The arena that types, regions, etc. are allocated from. arena: &'tcx SyncDroplessArena, - /// Specifically use a speedy hash algorithm for these hash sets, + /// Specifically use a speedy hash algorithm for these hash sets, since /// they're accessed quite often. type_: InternedSet<'tcx, TyS<'tcx>>, type_list: InternedSet<'tcx, List>>, @@ -129,7 +130,7 @@ impl<'tcx> CtxtInterners<'tcx> { } } - /// Intern a type + /// Interns a type. #[allow(rustc::usage_of_ty_tykind)] #[inline(never)] fn intern_ty(&self, @@ -144,7 +145,6 @@ impl<'tcx> CtxtInterners<'tcx> { outer_exclusive_binder: flags.outer_exclusive_binder, }; - Interned(self.arena.alloc(ty_struct)) }).0 } @@ -1025,7 +1025,7 @@ pub struct GlobalCtxt<'tcx> { hir_map: hir_map::Map<'tcx>, - /// A map from DefPathHash -> DefId. Includes DefIds from the local crate + /// A map from `DefPathHash` -> `DefId`. Includes `DefId`s from the local crate /// as well as all upstream crates. Only populated in incremental mode. pub def_path_hash_to_def_id: Option>, @@ -1124,9 +1124,9 @@ impl<'tcx> TyCtxt<'tcx> { }) } - /// Allocates a byte or string literal for `mir::interpret`, read-only + /// Allocates a read-only byte or string literal for `mir::interpret`. pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId { - // create an allocation that just contains these bytes + // Create an allocation that just contains these bytes. let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes); let alloc = self.intern_const_alloc(alloc); self.alloc_map.lock().create_memory_alloc(alloc) @@ -1346,7 +1346,7 @@ impl<'tcx> TyCtxt<'tcx> { } /// Converts a `DefId` into its fully expanded `DefPath` (every - /// `DefId` is really just an interned def-path). + /// `DefId` is really just an interned `DefPath`). /// /// Note that if `id` is not local to this crate, the result will /// be a non-local `DefPath`. @@ -1402,6 +1402,10 @@ impl<'tcx> TyCtxt<'tcx> { self.cstore.metadata_encoding_version().to_vec() } + pub fn encode_metadata(self)-> EncodedMetadata { + self.cstore.encode_metadata(self) + } + // Note that this is *untracked* and should only be used within the query // system if the result is otherwise tracked through queries pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Lrc { @@ -1446,25 +1450,25 @@ impl<'tcx> TyCtxt<'tcx> { self.queries.on_disk_cache.serialize(self.global_tcx(), encoder) } - /// If true, we should use the AST-based borrowck (we may *also* use + /// If `true`, we should use the AST-based borrowck (we may *also* use /// the MIR-based borrowck). pub fn use_ast_borrowck(self) -> bool { self.borrowck_mode().use_ast() } - /// If true, we should use the MIR-based borrow check, but also - /// fall back on the AST borrow check if the MIR-based one errors. + /// If `true`, we should use the MIR-based borrowck, but also + /// fall back on the AST borrowck if the MIR-based one errors. pub fn migrate_borrowck(self) -> bool { self.borrowck_mode().migrate() } - /// If true, make MIR codegen for `match` emit a temp that holds a + /// If `true`, make MIR codegen for `match` emit a temp that holds a /// borrow of the input to the match expression. pub fn generate_borrow_of_any_match_input(&self) -> bool { self.emit_read_for_match() } - /// If true, make MIR codegen for `match` emit FakeRead + /// If `true`, make MIR codegen for `match` emit FakeRead /// statements (which simulate the maximal effect of executing the /// patterns in a match arm). pub fn emit_read_for_match(&self) -> bool { @@ -1517,7 +1521,7 @@ impl<'tcx> TyCtxt<'tcx> { }) } - // This method returns the DefId and the BoundRegion corresponding to the given region. + // Returns the `DefId` and the `BoundRegion` corresponding to the given region. pub fn is_suitable_region(&self, region: Region<'tcx>) -> Option { let (suitable_region_binding_scope, bound_region) = match *region { ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region), @@ -1550,18 +1554,18 @@ impl<'tcx> TyCtxt<'tcx> { &self, scope_def_id: DefId, ) -> Option> { - // HACK: `type_of_def_id()` will fail on these (#55796), so return None + // HACK: `type_of_def_id()` will fail on these (#55796), so return `None`. let hir_id = self.hir().as_local_hir_id(scope_def_id).unwrap(); match self.hir().get(hir_id) { Node::Item(item) => { match item.node { - ItemKind::Fn(..) => { /* type_of_def_id() will work */ } + ItemKind::Fn(..) => { /* `type_of_def_id()` will work */ } _ => { return None; } } } - _ => { /* type_of_def_id() will work or panic */ } + _ => { /* `type_of_def_id()` will work or panic */ } } let ret_ty = self.type_of(scope_def_id); @@ -1579,7 +1583,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - // Here we check if the bound region is in Impl Item. + // Checks if the bound region is in Impl Item. pub fn is_bound_region_in_impl_item( &self, suitable_region_binding_scope: DefId, @@ -1599,23 +1603,15 @@ impl<'tcx> TyCtxt<'tcx> { false } - /// Determine whether identifiers in the assembly have strict naming rules. + /// Determines whether identifiers in the assembly have strict naming rules. /// Currently, only NVPTX* targets need it. pub fn has_strict_asm_symbol_naming(&self) -> bool { - self.gcx.sess.target.target.arch.contains("nvptx") - } -} - -impl<'tcx> TyCtxt<'tcx> { - pub fn encode_metadata(self) - -> EncodedMetadata - { - self.cstore.encode_metadata(self) + self.sess.target.target.arch.contains("nvptx") } } impl<'tcx> GlobalCtxt<'tcx> { - /// Call the closure with a local `TyCtxt` using the given arena. + /// Calls the closure with a local `TyCtxt` using the given arena. /// `interners` is a slot passed so we can create a CtxtInterners /// with the same lifetime as `arena`. pub fn enter_local(&'tcx self, f: F) -> R @@ -1651,7 +1647,7 @@ impl<'tcx> GlobalCtxt<'tcx> { /// It would be more efficient if `TypedArena` provided a way to /// determine whether the address is in the allocated range. /// -/// None is returned if the value or one of the components is not part +/// `None` is returned if the value or one of the components is not part /// of the provided context. /// For `Ty`, `None` can be returned if either the type interner doesn't /// contain the `TyKind` key or if the address of the interned @@ -1662,7 +1658,6 @@ pub trait Lift<'tcx>: fmt::Debug { fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option; } - macro_rules! nop_lift { ($ty:ty => $lifted:ty) => { impl<'a, 'tcx> Lift<'tcx> for $ty { @@ -1709,7 +1704,7 @@ nop_list_lift!{Predicate<'a> => Predicate<'tcx>} nop_list_lift!{CanonicalVarInfo => CanonicalVarInfo} nop_list_lift!{ProjectionKind => ProjectionKind} -// this is the impl for `&'a InternalSubsts<'a>` +// This is the impl for `&'a InternalSubsts<'a>`. nop_list_lift!{Kind<'a> => Kind<'tcx>} pub mod tls { @@ -1732,43 +1727,43 @@ pub mod tls { use rustc_rayon_core as rayon_core; /// This is the implicit state of rustc. It contains the current - /// TyCtxt and query. It is updated when creating a local interner or - /// executing a new query. Whenever there's a TyCtxt value available - /// you should also have access to an ImplicitCtxt through the functions + /// `TyCtxt` and query. It is updated when creating a local interner or + /// executing a new query. Whenever there's a `TyCtxt` value available + /// you should also have access to an `ImplicitCtxt` through the functions /// in this module. #[derive(Clone)] pub struct ImplicitCtxt<'a, 'tcx> { - /// The current TyCtxt. Initially created by `enter_global` and updated - /// by `enter_local` with a new local interner + /// The current `TyCtxt`. Initially created by `enter_global` and updated + /// by `enter_local` with a new local interner. pub tcx: TyCtxt<'tcx>, - /// The current query job, if any. This is updated by JobOwner::start in - /// ty::query::plumbing when executing a query + /// The current query job, if any. This is updated by `JobOwner::start` in + /// `ty::query::plumbing` when executing a query. pub query: Option>>, /// Where to store diagnostics for the current query job, if any. - /// This is updated by JobOwner::start in ty::query::plumbing when executing a query + /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query. pub diagnostics: Option<&'a Lock>>, /// Used to prevent layout from recursing too deeply. pub layout_depth: usize, /// The current dep graph task. This is used to add dependencies to queries - /// when executing them + /// when executing them. pub task_deps: Option<&'a Lock>, } - /// Sets Rayon's thread local variable which is preserved for Rayon jobs + /// Sets Rayon's thread local variablem, which is preserved for Rayon jobs /// to `value` during the call to `f`. It is restored to its previous value after. - /// This is used to set the pointer to the new ImplicitCtxt. + /// This is used to set the pointer to the new `ImplicitCtxt`. #[cfg(parallel_compiler)] #[inline] fn set_tlv R, R>(value: usize, f: F) -> R { rayon_core::tlv::with(value, f) } - /// Gets Rayon's thread local variable which is preserved for Rayon jobs. - /// This is used to get the pointer to the current ImplicitCtxt. + /// Gets Rayon's thread local variable, which is preserved for Rayon jobs. + /// This is used to get the pointer to the current `ImplicitCtxt`. #[cfg(parallel_compiler)] #[inline] fn get_tlv() -> usize { @@ -1777,13 +1772,13 @@ pub mod tls { #[cfg(not(parallel_compiler))] thread_local! { - /// A thread local variable which stores a pointer to the current ImplicitCtxt. + /// A thread local variable that stores a pointer to the current `ImplicitCtxt`. static TLV: Cell = Cell::new(0); } /// Sets TLV to `value` during the call to `f`. /// It is restored to its previous value after. - /// This is used to set the pointer to the new ImplicitCtxt. + /// This is used to set the pointer to the new `ImplicitCtxt`. #[cfg(not(parallel_compiler))] #[inline] fn set_tlv R, R>(value: usize, f: F) -> R { @@ -1793,14 +1788,14 @@ pub mod tls { f() } - /// This is used to get the pointer to the current ImplicitCtxt. + /// Gets the pointer to the current `ImplicitCtxt`. #[cfg(not(parallel_compiler))] fn get_tlv() -> usize { TLV.with(|tlv| tlv.get()) } /// This is a callback from libsyntax as it cannot access the implicit state - /// in librustc otherwise + /// in librustc otherwise. fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_opt(|tcx| { if let Some(tcx) = tcx { @@ -1825,7 +1820,7 @@ pub mod tls { }) } - /// Sets up the callbacks from libsyntax on the current thread + /// Sets up the callbacks from libsyntax on the current thread. pub fn with_thread_locals(f: F) -> R where F: FnOnce() -> R { @@ -1850,7 +1845,7 @@ pub mod tls { }) } - /// Sets `context` as the new current ImplicitCtxt for the duration of the function `f` + /// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`. #[inline] pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) -> R where @@ -1861,19 +1856,19 @@ pub mod tls { }) } - /// Enters GlobalCtxt by setting up libsyntax callbacks and - /// creating a initial TyCtxt and ImplicitCtxt. - /// This happens once per rustc session and TyCtxts only exists + /// Enters `GlobalCtxt` by setting up libsyntax callbacks and + /// creating a initial `TyCtxt` and `ImplicitCtxt`. + /// This happens once per rustc session and `TyCtxt`s only exists /// inside the `f` function. pub fn enter_global<'tcx, F, R>(gcx: &'tcx GlobalCtxt<'tcx>, f: F) -> R where F: FnOnce(TyCtxt<'tcx>) -> R, { - // Update GCX_PTR to indicate there's a GlobalCtxt available + // Update `GCX_PTR` to indicate there's a `GlobalCtxt` available. GCX_PTR.with(|lock| { *lock.lock() = gcx as *const _ as usize; }); - // Set GCX_PTR back to 0 when we exit + // Set `GCX_PTR` back to 0 when we exit. let _on_drop = OnDrop(move || { GCX_PTR.with(|lock| *lock.lock() = 0); }); @@ -1894,12 +1889,12 @@ pub mod tls { } scoped_thread_local! { - /// Stores a pointer to the GlobalCtxt if one is available. - /// This is used to access the GlobalCtxt in the deadlock handler given to Rayon. + /// Stores a pointer to the `GlobalCtxt` if one is available. + /// This is used to access the `GlobalCtxt` in the deadlock handler given to Rayon. pub static GCX_PTR: Lock } - /// Creates a TyCtxt and ImplicitCtxt based on the GCX_PTR thread local. + /// Creates a `TyCtxt` and `ImplicitCtxt` based on the `GCX_PTR` thread local. /// This is used in the deadlock handler. pub unsafe fn with_global(f: F) -> R where @@ -1921,7 +1916,7 @@ pub mod tls { enter_context(&icx, |_| f(tcx)) } - /// Allows access to the current ImplicitCtxt in a closure if one is available + /// Allows access to the current `ImplicitCtxt` in a closure if one is available. #[inline] pub fn with_context_opt(f: F) -> R where @@ -1931,16 +1926,16 @@ pub mod tls { if context == 0 { f(None) } else { - // We could get a ImplicitCtxt pointer from another thread. - // Ensure that ImplicitCtxt is Sync + // We could get a `ImplicitCtxt` pointer from another thread. + // Ensure that `ImplicitCtxt` is `Sync`. sync::assert_sync::>(); unsafe { f(Some(&*(context as *const ImplicitCtxt<'_, '_>))) } } } - /// Allows access to the current ImplicitCtxt. - /// Panics if there is no ImplicitCtxt available + /// Allows access to the current `ImplicitCtxt`. + /// Panics if there is no `ImplicitCtxt` available. #[inline] pub fn with_context(f: F) -> R where @@ -1949,11 +1944,11 @@ pub mod tls { with_context_opt(|opt_context| f(opt_context.expect("no ImplicitCtxt stored in tls"))) } - /// Allows access to the current ImplicitCtxt whose tcx field has the same global - /// interner as the tcx argument passed in. This means the closure is given an ImplicitCtxt - /// with the same 'tcx lifetime as the TyCtxt passed in. - /// This will panic if you pass it a TyCtxt which has a different global interner from - /// the current ImplicitCtxt's tcx field. + /// Allows access to the current `ImplicitCtxt` whose tcx field has the same global + /// interner as the tcx argument passed in. This means the closure is given an `ImplicitCtxt` + /// with the same `'tcx` lifetime as the `TyCtxt` passed in. + /// This will panic if you pass it a `TyCtxt` which has a different global interner from + /// the current `ImplicitCtxt`'s `tcx` field. #[inline] pub fn with_related_context<'tcx, F, R>(tcx: TyCtxt<'tcx>, f: F) -> R where @@ -1968,8 +1963,8 @@ pub mod tls { }) } - /// Allows access to the TyCtxt in the current ImplicitCtxt. - /// Panics if there is no ImplicitCtxt available + /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`. + /// Panics if there is no `ImplicitCtxt` available. #[inline] pub fn with(f: F) -> R where @@ -1978,8 +1973,8 @@ pub mod tls { with_context(|context| f(context.tcx)) } - /// Allows access to the TyCtxt in the current ImplicitCtxt. - /// The closure is passed None if there is no ImplicitCtxt available + /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`. + /// The closure is passed None if there is no `ImplicitCtxt` available. #[inline] pub fn with_opt(f: F) -> R where @@ -1991,7 +1986,7 @@ pub mod tls { macro_rules! sty_debug_print { ($ctxt: expr, $($variant: ident),*) => {{ - // curious inner module to allow variant names to be used as + // Curious inner module to allow variant names to be used as // variable names. #[allow(non_snake_case)] mod inner { @@ -2265,9 +2260,9 @@ slice_interners!( projs: _intern_projs(ProjectionKind) ); -// This isn't a perfect fit: CanonicalVarInfo slices are always +// This isn't a perfect fit: `CanonicalVarInfo` slices are always // allocated in the global arena, so this `intern_method!` macro is -// overly general. But we just return false for the code that checks +// overly general. However, we just return `false` for the code that checks // whether they belong in the thread-local arena, so no harm done, and // seems better than open-coding the rest. intern_method! { @@ -2366,7 +2361,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_adt(self, def: &'tcx AdtDef, substs: SubstsRef<'tcx>) -> Ty<'tcx> { - // take a copy of substs so that we own the vectors inside + // Take a copy of substs so that we own the vectors inside. self.mk_ty(Adt(def, substs)) } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 4b30412b41954..1e08ae45951d1 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -39,8 +39,8 @@ use std::collections::BTreeMap; use std::fmt; use crate::util::nodemap::FxHashSet; -/// The TypeFoldable trait is implemented for every type that can be folded. -/// Basically, every type that has a corresponding method in TypeFolder. +/// This trait is implemented for every type that can be folded. +/// Basically, every type that has a corresponding method in `TypeFolder`. /// /// To implement this conveniently, use the /// `BraceStructTypeFoldableImpl` etc macros found in `macros.rs`. diff --git a/src/librustc/ty/inhabitedness/def_id_forest.rs b/src/librustc/ty/inhabitedness/def_id_forest.rs index 4453624fa4502..63cc60d80aada 100644 --- a/src/librustc/ty/inhabitedness/def_id_forest.rs +++ b/src/librustc/ty/inhabitedness/def_id_forest.rs @@ -4,20 +4,20 @@ use rustc::hir::CRATE_HIR_ID; use crate::ty::context::TyCtxt; use crate::ty::{DefId, DefIdTree}; -/// Represents a forest of DefIds closed under the ancestor relation. That is, -/// if a DefId representing a module is contained in the forest then all -/// DefIds defined in that module or submodules are also implicitly contained +/// Represents a forest of `DefId`s closed under the ancestor relation. That is, +/// if a `DefId` representing a module is contained in the forest then all +/// `DefId`s defined in that module or submodules are also implicitly contained /// in the forest. /// /// This is used to represent a set of modules in which a type is visibly /// uninhabited. #[derive(Clone)] pub struct DefIdForest { - /// The minimal set of DefIds required to represent the whole set. - /// If A and B are DefIds in the DefIdForest, and A is a descendant - /// of B, then only B will be in root_ids. - /// We use a SmallVec here because (for its use for caching inhabitedness) - /// its rare that this will contain even two ids. + /// The minimal set of `DefId`s required to represent the whole set. + /// If A and B are DefIds in the `DefIdForest`, and A is a descendant + /// of B, then only B will be in `root_ids`. + /// We use a `SmallVec` here because (for its use for caching inhabitedness) + /// its rare that this will contain even two IDs. root_ids: SmallVec<[DefId; 1]>, } @@ -37,7 +37,7 @@ impl<'tcx> DefIdForest { DefIdForest::from_id(crate_id) } - /// Creates a forest containing a DefId and all its descendants. + /// Creates a forest containing a `DefId` and all its descendants. pub fn from_id(id: DefId) -> DefIdForest { let mut root_ids = SmallVec::new(); root_ids.push(id); diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 2b3291656653f..1a0e351733877 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -1,3 +1,5 @@ +pub use self::def_id_forest::DefIdForest; + use crate::ty::context::TyCtxt; use crate::ty::{AdtDef, VariantDef, FieldDef, Ty, TyS}; use crate::ty::{DefId, SubstsRef}; @@ -5,12 +7,10 @@ use crate::ty::{AdtKind, Visibility}; use crate::ty::TyKind::*; use crate::ty; -pub use self::def_id_forest::DefIdForest; - mod def_id_forest; -// The methods in this module calculate DefIdForests of modules in which a -// AdtDef/VariantDef/FieldDef is visibly uninhabited. +// The methods in this module calculate `DefIdForest`s of modules in which a +// `AdtDef`/`VariantDef`/`FieldDef` is visibly uninhabited. // // # Example // ```rust @@ -36,24 +36,25 @@ mod def_id_forest; // y: c::AlsoSecretlyUninhabited, // } // ``` -// In this code, the type Foo will only be visibly uninhabited inside the -// modules b, c and d. Calling uninhabited_from on Foo or its AdtDef will -// return the forest of modules {b, c->d} (represented in a DefIdForest by the -// set {b, c}) +// In this code, the type `Foo` will only be visibly uninhabited inside the +// modules `b`, `c` and `d`. Calling `uninhabited_from` on `Foo` or its `AdtDef` will +// return the forest of modules {`b`, `c`->`d`} (represented in a `DefIdForest` by the +// set {`b`, `c`}). // -// We need this information for pattern-matching on Foo or types that contain -// Foo. +// We need this information for pattern-matching on `Foo` or types that contain +// `Foo`. // // # Example // ```rust // let foo_result: Result = ... ; // let Ok(t) = foo_result; // ``` -// This code should only compile in modules where the uninhabitedness of Foo is +// This code should only compile in modules where the uninhabitedness of `Foo` is // visible. impl<'tcx> TyCtxt<'tcx> { /// Checks whether a type is visibly uninhabited from a particular module. + /// /// # Example /// ```rust /// enum Void {} @@ -91,7 +92,7 @@ impl<'tcx> TyCtxt<'tcx> { /// visible. pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool { // To check whether this type is uninhabited at all (not just from the - // given node) you could check whether the forest is empty. + // given node), you could check whether the forest is empty. // ``` // forest.is_empty() // ``` @@ -108,7 +109,7 @@ impl<'tcx> TyCtxt<'tcx> { } impl<'tcx> AdtDef { - /// Calculate the forest of DefIds from which this adt is visibly uninhabited. + /// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited. fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>) -> DefIdForest { // Non-exhaustive ADTs from other crates are always considered inhabited. if self.is_variant_list_non_exhaustive() && !self.did.is_local() { @@ -122,7 +123,7 @@ impl<'tcx> AdtDef { } impl<'tcx> VariantDef { - /// Calculate the forest of DefIds from which this variant is visibly uninhabited. + /// Calculates the forest of `DefId`s from which this variant is visibly uninhabited. pub fn uninhabited_from( &self, tcx: TyCtxt<'tcx>, @@ -148,7 +149,7 @@ impl<'tcx> VariantDef { } impl<'tcx> FieldDef { - /// Calculate the forest of DefIds from which this field is visibly uninhabited. + /// Calculates the forest of `DefId`s from which this field is visibly uninhabited. fn uninhabited_from( &self, tcx: TyCtxt<'tcx>, @@ -159,7 +160,7 @@ impl<'tcx> FieldDef { self.ty(tcx, substs).uninhabited_from(tcx) }; // FIXME(canndrew): Currently enum fields are (incorrectly) stored with - // Visibility::Invisible so we need to override self.vis if we're + // `Visibility::Invisible` so we need to override `self.vis` if we're // dealing with an enum. if is_enum { data_uninhabitedness() @@ -178,7 +179,7 @@ impl<'tcx> FieldDef { } impl<'tcx> TyS<'tcx> { - /// Calculate the forest of DefIds from which this type is visibly uninhabited. + /// Calculates the forest of `DefId`s from which this type is visibly uninhabited. fn uninhabited_from(&self, tcx: TyCtxt<'tcx>) -> DefIdForest { match self.sty { Adt(def, substs) => def.uninhabited_from(tcx, substs), diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2da50f37409ae..41e4295caecce 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -590,7 +590,7 @@ impl<'tcx> rustc_serialize::UseSpecializedDecodable for Ty<'tcx> {} pub type CanonicalTy<'tcx> = Canonical<'tcx, Ty<'tcx>>; extern { - /// A dummy type used to force List to by unsized without requiring fat pointers + /// A dummy type used to force `List` to by unsized without requiring fat pointers. type OpaqueListContents; } diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 092e7c6f3fffb..50789bf6213b6 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -27,7 +27,8 @@ pub trait Print<'tcx, P> { /// which the associated types allow passing through the methods. /// /// For pretty-printing/formatting in particular, see `PrettyPrinter`. -// FIXME(eddyb) find a better name, this is more general than "printing". +// +// FIXME(eddyb) find a better name; this is more general than "printing". pub trait Printer<'tcx>: Sized { type Error; @@ -46,6 +47,7 @@ pub trait Printer<'tcx>: Sized { ) -> Result { self.default_print_def_path(def_id, substs) } + fn print_impl_path( self, impl_def_id: DefId, @@ -80,6 +82,7 @@ pub trait Printer<'tcx>: Sized { self, cnum: CrateNum, ) -> Result; + fn path_qualified( self, self_ty: Ty<'tcx>, @@ -93,11 +96,13 @@ pub trait Printer<'tcx>: Sized { self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result; + fn path_append( self, print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, ) -> Result; + fn path_generic_args( self, print_prefix: impl FnOnce(Self) -> Result, diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index a72ecdb5745bb..419a815074b5e 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -8,10 +8,11 @@ use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable}; use crate::ty::subst::{Kind, Subst, UnpackedKind}; use crate::ty::layout::{Integer, IntegerExt, Size}; use crate::mir::interpret::{ConstValue, sign_extend, Scalar, truncate}; -use syntax::ast; + use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; use rustc_target::spec::abi::Abi; +use syntax::ast; use syntax::attr::{SignedInt, UnsignedInt}; use syntax::symbol::{kw, InternedString}; @@ -194,7 +195,7 @@ pub trait PrettyPrinter<'tcx>: value.skip_binder().print(self) } - /// Print comma-separated elements. + /// Prints comma-separated elements. fn comma_sep(mut self, mut elems: impl Iterator) -> Result where T: Print<'tcx, Self, Output = Self, Error = Self::Error>, @@ -209,14 +210,14 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } - /// Print `<...>` around what `f` prints. + /// Prints `<...>` around what `f` prints. fn generic_delimiters( self, f: impl FnOnce(Self) -> Result, ) -> Result; - /// Return `true` if the region should be printed in - /// optional positions, e.g. `&'a T` or `dyn Tr + 'b`. + /// Returns `true` if the region should be printed in + /// optional positions, e.g., `&'a T` or `dyn Tr + 'b`. /// This is typically the case for all non-`'_` regions. fn region_should_not_be_omitted( &self, @@ -226,7 +227,7 @@ pub trait PrettyPrinter<'tcx>: // Defaults (should not be overriden): /// If possible, this returns a global path resolving to `def_id` that is visible - /// from at least one local module and returns true. If the crate defining `def_id` is + /// from at least one local module, and returns `true`. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. fn try_print_visible_def_path( self, @@ -267,11 +268,11 @@ pub trait PrettyPrinter<'tcx>: // In local mode, when we encounter a crate other than // LOCAL_CRATE, execution proceeds in one of two ways: // - // 1. for a direct dependency, where user added an + // 1. For a direct dependency, where user added an // `extern crate` manually, we put the `extern // crate` as the parent. So you wind up with // something relative to the current crate. - // 2. for an extern inferred from a path or an indirect crate, + // 2. For an extern inferred from a path or an indirect crate, // where there is no explicit `extern crate`, we just prepend // the crate name. match self.tcx().extern_crate(def_id) { @@ -304,13 +305,13 @@ pub trait PrettyPrinter<'tcx>: let mut cur_def_key = self.tcx().def_key(def_id); debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key); - // For a constructor we want the name of its parent rather than . + // For a constructor, we want the name of its parent rather than . match cur_def_key.disambiguated_data.data { DefPathData::Ctor => { let parent = DefId { krate: def_id.krate, index: cur_def_key.parent - .expect("DefPathData::Ctor/VariantData missing a parent"), + .expect("`DefPathData::Ctor` / `VariantData` missing a parent"), }; cur_def_key = self.tcx().def_key(parent); @@ -630,7 +631,7 @@ pub trait PrettyPrinter<'tcx>: sep = ", "; } } else { - // cross-crate closure types should only be + // Cross-crate closure types should only be // visible in codegen bug reports, I imagine. p!(write("@{:?}", did)); let mut sep = " "; @@ -673,7 +674,7 @@ pub trait PrettyPrinter<'tcx>: sep = ", "; } } else { - // cross-crate closure types should only be + // Cross-crate closure types should only be // visible in codegen bug reports, I imagine. p!(write("@{:?}", did)); let mut sep = " "; @@ -1092,35 +1093,38 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { } let key = self.tcx.def_key(def_id); - if let DefPathData::Impl = key.disambiguated_data.data { - // Always use types for non-local impls, where types are always - // available, and filename/line-number is mostly uninteresting. - let use_types = - !def_id.is_local() || { - // Otherwise, use filename/line-number if forced. - let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); - !force_no_types - }; + match key.disambiguated_data.data { + DefPathData::Impl => { + // Always use types for non-local impls, where types are always + // available, and filename/line-number is mostly uninteresting. + let use_types = + !def_id.is_local() || { + // Otherwise, use filename/line-number if forced. + let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); + !force_no_types + }; - if !use_types { - // If no type info is available, fall back to - // pretty printing some span information. This should - // only occur very early in the compiler pipeline. - let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; - let span = self.tcx.def_span(def_id); + if !use_types { + // If no type info is available, fall back to + // pretty-printing some span information. This should + // only occur very early in the compiler pipeline. + let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; + let span = self.tcx.def_span(def_id); - self = self.print_def_path(parent_def_id, &[])?; + self = self.print_def_path(parent_def_id, &[])?; - // HACK(eddyb) copy of `path_append` to avoid - // constructing a `DisambiguatedDefPathData`. - if !self.empty_path { - write!(self, "::")?; - } - write!(self, "", span)?; - self.empty_path = false; + // HACK(eddyb) copy of `path_append` to avoid + // constructing a `DisambiguatedDefPathData`. + if !self.empty_path { + write!(self, "::")?; + } + write!(self, "", span)?; + self.empty_path = false; - return Ok(self); + return Ok(self); + } } + _ => {} } self.default_print_def_path(def_id, substs) @@ -1173,6 +1177,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { } Ok(self) } + fn path_qualified( mut self, self_ty: Ty<'tcx>, @@ -1201,6 +1206,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { self.empty_path = false; Ok(self) } + fn path_append( mut self, print_prefix: impl FnOnce(Self) -> Result, @@ -1238,6 +1244,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { Ok(self) } + fn path_generic_args( mut self, print_prefix: impl FnOnce(Self) -> Result, diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 674f8944f261a..d24143ced5be2 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -5,9 +5,6 @@ use crate::hir::map::definitions::DefPathHash; use crate::ich::{CachingSourceMapView, Fingerprint}; use crate::mir::{self, interpret}; use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState}; -use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque, - SpecializedDecoder, SpecializedEncoder, - UseSpecializedDecodable, UseSpecializedEncodable}; use crate::session::{CrateDisambiguator, Session}; use crate::ty::{self, Ty}; use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder}; @@ -19,6 +16,10 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::sync::{Lrc, Lock, HashMapExt, Once}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use rustc_serialize::{ + Decodable, Decoder, Encodable, Encoder, SpecializedDecoder, SpecializedEncoder, + UseSpecializedDecodable, UseSpecializedEncodable, opaque, +}; use std::mem; use syntax::ast::{Ident, NodeId}; use syntax::source_map::{SourceMap, StableSourceFileId}; @@ -37,17 +38,16 @@ const TAG_EXPN_DATA_INLINE: u8 = 2; const TAG_VALID_SPAN: u8 = 0; const TAG_INVALID_SPAN: u8 = 1; -/// `OnDiskCache` provides an interface to incr. comp. data cached from the +/// Provides an interface to incremental compilation data cached from the /// previous compilation session. This data will eventually include the results /// of a few selected queries (like `typeck_tables_of` and `mir_optimized`) and /// any diagnostics that have been emitted during a query. pub struct OnDiskCache<'sess> { - // The complete cache data in serialized form. serialized_data: Vec, - // This field collects all Diagnostics emitted during the current - // compilation session. + // Collects all `Diagnostic`s emitted during the current compilation + // session. current_diagnostics: Lock>>, prev_cnums: Vec<(u32, String, CrateDisambiguator)>, @@ -56,7 +56,7 @@ pub struct OnDiskCache<'sess> { source_map: &'sess SourceMap, file_index_to_stable_id: FxHashMap, - // These two fields caches that are populated lazily during decoding. + // Caches that are populated lazily during decoding. file_index_to_file: Lock>>, synthetic_syntax_contexts: Lock>, @@ -78,7 +78,7 @@ struct Footer { prev_cnums: Vec<(u32, String, CrateDisambiguator)>, query_result_index: EncodedQueryResultIndex, diagnostics_index: EncodedQueryResultIndex, - // the location of all allocations + // The location of all allocations. interpret_alloc_index: Vec, } @@ -104,28 +104,28 @@ impl AbsoluteBytePos { } impl<'sess> OnDiskCache<'sess> { - /// Creates a new OnDiskCache instance from the serialized data in `data`. - pub fn new(sess: &'sess Session, data: Vec, start_pos: usize) -> OnDiskCache<'sess> { + /// Creates a new `OnDiskCache` instance from the serialized data in `data`. + pub fn new(sess: &'sess Session, data: Vec, start_pos: usize) -> Self { debug_assert!(sess.opts.incremental.is_some()); - // Wrapping in a scope so we can borrow `data` + // Wrap in a scope so we can borrow `data`. let footer: Footer = { let mut decoder = opaque::Decoder::new(&data[..], start_pos); - // Decode the *position* of the footer which can be found in the + // Decode the *position* of the footer, which can be found in the // last 8 bytes of the file. decoder.set_position(data.len() - IntEncodedWithFixedSize::ENCODED_SIZE); - let query_result_index_pos = IntEncodedWithFixedSize::decode(&mut decoder) - .expect("Error while trying to decode query result index position.") + let footer_pos = IntEncodedWithFixedSize::decode(&mut decoder) + .expect("error while trying to decode footer position") .0 as usize; - // Decoder the file footer which contains all the lookup tables, etc. - decoder.set_position(query_result_index_pos); + // Decode the file footer, which contains all the lookup tables, etc. + decoder.set_position(footer_pos); decode_tagged(&mut decoder, TAG_FILE_FOOTER) - .expect("Error while trying to decode query result index position.") + .expect("error while trying to decode footer position") }; - OnDiskCache { + Self { serialized_data: data, file_index_to_stable_id: footer.file_index_to_stable_id, file_index_to_file: Default::default(), @@ -140,8 +140,8 @@ impl<'sess> OnDiskCache<'sess> { } } - pub fn new_empty(source_map: &'sess SourceMap) -> OnDiskCache<'sess> { - OnDiskCache { + pub fn new_empty(source_map: &'sess SourceMap) -> Self { + Self { serialized_data: Vec::new(), file_index_to_stable_id: Default::default(), file_index_to_file: Default::default(), @@ -158,11 +158,11 @@ impl<'sess> OnDiskCache<'sess> { pub fn serialize<'tcx, E>(&self, tcx: TyCtxt<'tcx>, encoder: &mut E) -> Result<(), E::Error> where - E: ty_codec::TyEncoder, + E: TyEncoder, { - // Serializing the DepGraph should not modify it: + // Serializing the `DepGraph` should not modify it. tcx.dep_graph.with_ignore(|| { - // Allocate SourceFileIndices + // Allocate `SourceFileIndex`es. let (file_to_file_index, file_index_to_stable_id) = { let files = tcx.sess.source_map().files(); let mut file_to_file_index = FxHashMap::with_capacity_and_hasher( @@ -197,7 +197,7 @@ impl<'sess> OnDiskCache<'sess> { // be in memory, so this should be a cheap operation. tcx.dep_graph.exec_cache_promotions(tcx); - // Encode query results + // Encode query results. let mut query_result_index = EncodedQueryResultIndex::new(); time(tcx.sess, "encode query results", || { @@ -221,29 +221,28 @@ impl<'sess> OnDiskCache<'sess> { Ok(()) })?; - // Encode diagnostics + // Encode diagnostics. let diagnostics_index: EncodedDiagnosticsIndex = self.current_diagnostics.borrow() .iter() - .map(|(dep_node_index, diagnostics)| - { - let pos = AbsoluteBytePos::new(encoder.position()); - // Let's make sure we get the expected type here: - let diagnostics: &EncodedDiagnostics = diagnostics; - let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index()); - encoder.encode_tagged(dep_node_index, diagnostics)?; - - Ok((dep_node_index, pos)) - }) - .collect::>()?; + .map(|(dep_node_index, diagnostics)| { + let pos = AbsoluteBytePos::new(encoder.position()); + // Let's make sure we get the expected type here. + let diagnostics: &EncodedDiagnostics = diagnostics; + let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index()); + encoder.encode_tagged(dep_node_index, diagnostics)?; + + Ok((dep_node_index, pos)) + }) + .collect::>()?; let interpret_alloc_index = { let mut interpret_alloc_index = Vec::new(); let mut n = 0; loop { let new_n = encoder.interpret_allocs_inverse.len(); - // if we have found new ids, serialize those, too + // If we have found new IDs, serialize those too. if n == new_n { - // otherwise, abort + // Otherwise, abort. break; } interpret_alloc_index.reserve(new_n - n); @@ -263,13 +262,15 @@ impl<'sess> OnDiskCache<'sess> { }; let sorted_cnums = sorted_cnums_including_local_crate(tcx); - let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| { - let crate_name = tcx.original_crate_name(cnum).as_str().to_string(); - let crate_disambiguator = tcx.crate_disambiguator(cnum); - (cnum.as_u32(), crate_name, crate_disambiguator) - }).collect(); - - // Encode the file footer + let prev_cnums: Vec<_> = sorted_cnums.iter() + .map(|&cnum| { + let crate_name = tcx.original_crate_name(cnum).as_str().to_string(); + let crate_disambiguator = tcx.crate_disambiguator(cnum); + (cnum.as_u32(), crate_name, crate_disambiguator) + }) + .collect(); + + // Encode the file footer. let footer_pos = encoder.position() as u64; encoder.encode_tagged(TAG_FILE_FOOTER, &Footer { file_index_to_stable_id, @@ -371,7 +372,7 @@ impl<'sess> OnDiskCache<'sess> { { let pos = index.get(&dep_node_index).cloned()?; - // Initialize the cnum_map using the value from the thread which finishes the closure first + // Initialize `cnum_map` using the value from the thread that finishes the closure first. self.cnum_map.init_nonlocking_same(|| { Self::compute_cnum_map(tcx, &self.prev_cnums[..]) }); @@ -381,25 +382,21 @@ impl<'sess> OnDiskCache<'sess> { opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()), source_map: self.source_map, cnum_map: self.cnum_map.get(), + synthetic_syntax_contexts: &self.synthetic_syntax_contexts, file_index_to_file: &self.file_index_to_file, file_index_to_stable_id: &self.file_index_to_stable_id, - synthetic_syntax_contexts: &self.synthetic_syntax_contexts, alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(), }; match decode_tagged(&mut decoder, dep_node_index) { - Ok(value) => { - Some(value) - } - Err(e) => { - bug!("Could not decode cached {}: {}", debug_tag, e) - } + Ok(v) => Some(v), + Err(e) => bug!("could not decode cached {}: {}", debug_tag, e), } } - // This function builds mapping from previous-session-CrateNum to - // current-session-CrateNum. There might be CrateNums from the previous - // Session that don't occur in the current one. For these, the mapping + // This function builds mapping from previous-session-`CrateNum` to + // current-session-`CrateNum`. There might be `CrateNum`s from the previous + // `Session` that don't occur in the current one. For these, the mapping // maps to None. fn compute_cnum_map( tcx: TyCtxt<'_>, @@ -432,9 +429,9 @@ impl<'sess> OnDiskCache<'sess> { //- DECODING ------------------------------------------------------------------- -/// A decoder that can read the incr. comp. cache. It is similar to the one -/// we use for crate metadata decoding in that it can rebase spans and -/// eventually will also handle things that contain `Ty` instances. +/// A decoder that can read fro the incr. comp. cache. It is similar to the onem +/// we use for crate metadata decoding in that it can rebase spans and eventually +/// will also handle things that contain `Ty` instances. struct CacheDecoder<'a, 'tcx> { tcx: TyCtxt<'tcx>, opaque: opaque::Decoder<'a>, @@ -458,30 +455,32 @@ impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { file_index_to_file.borrow_mut().entry(index).or_insert_with(|| { let stable_id = file_index_to_stable_id[&index]; source_map.source_file_by_stable_id(stable_id) - .expect("Failed to lookup SourceFile in new context.") + .expect("failed to lookup `SourceFile` in new context") }).clone() } } -trait DecoderWithPosition: Decoder { +pub trait DecoderWithPosition: Decoder { fn position(&self) -> usize; } impl<'a> DecoderWithPosition for opaque::Decoder<'a> { + #[inline] fn position(&self) -> usize { self.position() } } impl<'a, 'tcx> DecoderWithPosition for CacheDecoder<'a, 'tcx> { + #[inline] fn position(&self) -> usize { self.opaque.position() } } -// Decode something that was encoded with encode_tagged() and verify that the +// Decodes something that was encoded with `encode_tagged()` and verify that the // tag matches and the correct amount of bytes was read. -fn decode_tagged(decoder: &mut D, expected_tag: T) -> Result +pub fn decode_tagged(decoder: &mut D, expected_tag: T) -> Result where T: Decodable + Eq + ::std::fmt::Debug, V: Decodable, @@ -500,7 +499,7 @@ where Ok(value) } -impl<'a, 'tcx> ty_codec::TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { +impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { self.tcx @@ -534,7 +533,7 @@ impl<'a, 'tcx> ty_codec::TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { } let ty = or_insert_with(self)?; - // This may overwrite the entry, but it should overwrite with the same value + // This may overwrite the entry, but it should overwrite with the same value. tcx.rcache.borrow_mut().insert_same(cache_key, ty); Ok(ty) } @@ -553,7 +552,7 @@ impl<'a, 'tcx> ty_codec::TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum { self.cnum_map[cnum].unwrap_or_else(|| { - bug!("Could not find new CrateNum for {:?}", cnum) + bug!("could not find new `CrateNum` for {:?}", cnum) }) } } @@ -635,25 +634,25 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { } // This impl makes sure that we get a runtime error when we try decode a -// DefIndex that is not contained in a DefId. Such a case would be problematic -// because we would not know how to transform the DefIndex to the current +// `DefIndex` that is not contained in a `DefId`. Such a case would be problematic +// because we would not know how to transform the `DefIndex` to the current // context. impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { fn specialized_decode(&mut self) -> Result { - bug!("Trying to decode DefIndex outside the context of a DefId") + bug!("trying to decode `DefIndex` outside the context of a `DefId`") } } -// Both the CrateNum and the DefIndex of a DefId can change in between two -// compilation sessions. We use the DefPathHash, which is stable across -// sessions, to map the old DefId to the new one. +// Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two +// compilation sessions. We use the `DefPathHash`, which is stable across +// sessions, to map the old DefId`` to the new one. impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { #[inline] fn specialized_decode(&mut self) -> Result { - // Load the DefPathHash which is was we encoded the DefId as. + // Load the `DefPathHash` which is was we encoded the `DefId` as. let def_path_hash = DefPathHash::decode(self)?; - // Using the DefPathHash, we can lookup the new DefId + // Using the `DefPathHash`, we can lookup the new `DefId`. Ok(self.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash]) } } @@ -667,10 +666,10 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { fn specialized_decode(&mut self) -> Result { - // Load the DefPathHash which is was we encoded the DefIndex as. + // Load the `DefPathHash` which is what we encoded the `DefIndex` as. let def_path_hash = DefPathHash::decode(self)?; - // Use the DefPathHash to map to the current DefId. + // Use the `DefPathHash` to map to the current `DefId`. let def_id = self.tcx() .def_path_hash_to_def_id .as_ref() @@ -678,10 +677,10 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { debug_assert!(def_id.is_local()); - // The ItemLocalId needs no remapping. + // The `ItemLocalId` needs no remapping. let local_id = hir::ItemLocalId::decode(self)?; - // Reconstruct the HirId and look up the corresponding NodeId in the + // Reconstruct the `HirId` and look up the corresponding `NodeId` in the // context of the current session. Ok(hir::HirId { owner: def_id.index, @@ -690,8 +689,8 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { } } -// NodeIds are not stable across compilation sessions, so we store them in their -// HirId representation. This allows use to map them to the current NodeId. +// `NodeId`s are not stable across compilation sessions, so we store them in their +// `HirId` representation. This allows use to map them to the current `NodeId`. impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { #[inline] fn specialized_decode(&mut self) -> Result { @@ -701,6 +700,7 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { } impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { + #[inline] fn specialized_decode(&mut self) -> Result { Fingerprint::decode_opaque(&mut self.opaque) } @@ -728,6 +728,7 @@ impl<'a, 'tcx, T: Decodable> SpecializedDecoder> //- ENCODING ------------------------------------------------------------------- +/// An encoder that can write the incr. comp. cache. struct CacheEncoder<'a, 'tcx, E: ty_codec::TyEncoder> { tcx: TyCtxt<'tcx>, encoder: &'a mut E, @@ -742,7 +743,7 @@ struct CacheEncoder<'a, 'tcx, E: ty_codec::TyEncoder> { impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { fn source_file_index(&mut self, source_file: Lrc) -> SourceFileIndex { self.file_to_file_index[&(&*source_file as *const SourceFile)] @@ -753,11 +754,11 @@ where /// encode the specified tag, then the given value, then the number of /// bytes taken up by tag and value. On decoding, we can then verify that /// we get the expected tag and read the expected number of bytes. - fn encode_tagged(&mut self, - tag: T, - value: &V) - -> Result<(), E::Error> - { + pub fn encode_tagged( + &mut self, + tag: T, + value: &V + ) -> Result<(), E::Error> { let start_pos = self.position(); tag.encode(self)?; @@ -770,7 +771,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> { use std::collections::hash_map::Entry; @@ -790,10 +791,9 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> { - if *span == DUMMY_SP { return TAG_INVALID_SPAN.encode(self); } @@ -849,14 +849,14 @@ where // We don't currently encode enough information to ensure hygiene works // with incremental, so panic rather than risk incremental bugs. - // FIXME: Handle hygiene in incremental - bug!("Trying to encode Ident for incremental") + // FIXME: handle hygiene in incremental. + bug!("trying to encode `Ident` for incremental"); } } impl<'a, 'tcx, E> ty_codec::TyEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn position(&self) -> usize { @@ -866,7 +866,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> { @@ -876,7 +876,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder> for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> { @@ -887,7 +887,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder> for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, @@ -900,7 +900,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, id: &hir::HirId) -> Result<(), Self::Error> { @@ -918,7 +918,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, id: &DefId) -> Result<(), Self::Error> { @@ -929,7 +929,7 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, id: &LocalDefId) -> Result<(), Self::Error> { @@ -939,18 +939,18 @@ where impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { fn specialized_encode(&mut self, _: &DefIndex) -> Result<(), Self::Error> { - bug!("Encoding DefIndex without context.") + bug!("encoding `DefIndex` without context"); } } -// NodeIds are not stable across compilation sessions, so we store them in their -// HirId representation. This allows use to map them to the current NodeId. +// `NodeId`s are not stable across compilation sessions, so we store them in their +// `HirId` representation. This allows use to map them to the current `NodeId`. impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, node_id: &NodeId) -> Result<(), Self::Error> { @@ -960,6 +960,7 @@ where } impl<'a, 'tcx> SpecializedEncoder for CacheEncoder<'a, 'tcx, opaque::Encoder> { + #[inline] fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> { f.encode_opaque(&mut self.encoder) } @@ -967,7 +968,7 @@ impl<'a, 'tcx> SpecializedEncoder for CacheEncoder<'a, 'tcx, opaque impl<'a, 'tcx, E, T> SpecializedEncoder> for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, T: Encodable, { #[inline] @@ -996,7 +997,7 @@ macro_rules! encoder_methods { impl<'a, 'tcx, E> Encoder for CacheEncoder<'a, 'tcx, E> where - E: 'a + ty_codec::TyEncoder, + E: 'a + TyEncoder, { type Error = E::Error; @@ -1040,7 +1041,7 @@ impl UseSpecializedDecodable for IntEncodedWithFixedSize {} impl SpecializedEncoder for opaque::Encoder { fn specialized_encode(&mut self, x: &IntEncodedWithFixedSize) -> Result<(), Self::Error> { let start_pos = self.position(); - for i in 0 .. IntEncodedWithFixedSize::ENCODED_SIZE { + for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE { ((x.0 >> i * 8) as u8).encode(self)?; } let end_pos = self.position(); @@ -1085,10 +1086,10 @@ where if Q::cache_on_disk(tcx, key.clone(), Some(&entry.value)) { let dep_node = SerializedDepNodeIndex::new(entry.index.index()); - // Record position of the cache entry + // Record position of the cache entry. query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position()))); - // Encode the type check tables with the SerializedDepNodeIndex + // Encode the type check tables with the `SerializedDepNodeIndex` // as tag. encoder.encode_tagged(dep_node, &entry.value)?; } diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 4dce55f589233..d199a26475be7 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -61,7 +61,7 @@ impl<'tcx, M: QueryConfig<'tcx>> Default for QueryCache<'tcx, M> { } } -// If enabled, send a message to the profile-queries thread +// If enabled, sends a message to the profile-queries thread. macro_rules! profq_msg { ($tcx:expr, $msg:expr) => { if cfg!(debug_assertions) { @@ -72,7 +72,7 @@ macro_rules! profq_msg { } } -// If enabled, format a key using its debug string, which can be +// If enabled, formats a key using its debug string, which can be // expensive to compute (in terms of time). macro_rules! profq_query_msg { ($query:expr, $tcx:expr, $key:expr) => {{ @@ -98,7 +98,7 @@ pub(super) struct JobOwner<'a, 'tcx, Q: QueryDescription<'tcx>> { impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { /// Either gets a `JobOwner` corresponding the query, allowing us to - /// start executing the query, or it returns with the result of the query. + /// start executing the query, or returns with the result of the query. /// If the query is executing elsewhere, this will wait for it. /// If the query panicked, this will silently panic. /// @@ -215,30 +215,30 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> { #[inline(never)] #[cold] fn drop(&mut self) { - // Poison the query so jobs waiting on it panic + // Poison the query so jobs waiting on it panic. let shard = self.cache.get_shard_by_value(&self.key); shard.lock().active.insert(self.key.clone(), QueryResult::Poisoned); // Also signal the completion of the job, so waiters - // will continue execution + // will continue execution. self.job.signal_complete(); } } #[derive(Clone)] pub struct CycleError<'tcx> { - /// The query and related span which uses the cycle + /// The query and related span that uses the cycle. pub(super) usage: Option<(Span, Query<'tcx>)>, pub(super) cycle: Vec>, } -/// The result of `try_get_lock` +/// The result of `try_get_lock`. pub(super) enum TryGetJob<'a, 'tcx, D: QueryDescription<'tcx>> { /// The query is not yet started. Contains a guard to the cache eventually used to start it. NotYetStarted(JobOwner<'a, 'tcx, D>), /// The query was already completed. - /// Returns the result of the query and its dep node index - /// if it succeeded or a cycle error if it failed + /// Returns the result of the query and its dep-node index + /// if it succeeded or a cycle error if it failed. JobCompleted((D::Value, DepNodeIndex)), /// Trying to execute the query resulted in a cycle. @@ -246,7 +246,7 @@ pub(super) enum TryGetJob<'a, 'tcx, D: QueryDescription<'tcx>> { } impl<'tcx> TyCtxt<'tcx> { - /// Executes a job by changing the ImplicitCtxt to point to the + /// Executes a job by changing the `ImplicitCtxt` to point to the /// new query job while it executes. It returns the diagnostics /// captured during execution and the actual result. #[inline(always)] @@ -259,11 +259,11 @@ impl<'tcx> TyCtxt<'tcx> { where F: FnOnce(TyCtxt<'tcx>) -> R, { - // The TyCtxt stored in TLS has the same global interner lifetime + // The `TyCtxt` stored in TLS has the same global interner lifetime // as `self`, so we use `with_related_context` to relate the 'tcx lifetimes - // when accessing the ImplicitCtxt + // when accessing the `ImplicitCtxt`. tls::with_related_context(self, move |current_icx| { - // Update the ImplicitCtxt to point to our new query job + // Update the `ImplicitCtxt` to point to our new query job. let new_icx = tls::ImplicitCtxt { tcx: self.global_tcx(), query: Some(job), @@ -272,7 +272,7 @@ impl<'tcx> TyCtxt<'tcx> { task_deps: current_icx.task_deps, }; - // Use the ImplicitCtxt while we execute the query + // Use the `ImplicitCtxt` while we execute the query. tls::enter_context(&new_icx, |_| { compute(self.global_tcx()) }) @@ -372,7 +372,7 @@ impl<'tcx> TyCtxt<'tcx> { }; // Fast path for when incr. comp. is off. `to_dep_node` is - // expensive for some DepKinds. + // expensive for some `DepKind`s. if !self.dep_graph.is_fully_enabled() { let null_dep_node = DepNode::new_no_params(crate::dep_graph::DepKind::Null); return self.force_query_with_job::(key, job, null_dep_node).0; @@ -410,7 +410,7 @@ impl<'tcx> TyCtxt<'tcx> { if !Q::EVAL_ALWAYS { // The diagnostics for this query will be // promoted to the current session during - // try_mark_green(), so we can ignore them here. + // `try_mark_green()`, so we can ignore them here. let loaded = self.start_query(job.job.clone(), None, |tcx| { let marked = tcx.dep_graph.try_mark_green_and_read(tcx, &dep_node); marked.map(|(prev_dep_node_index, dep_node_index)| { @@ -441,11 +441,11 @@ impl<'tcx> TyCtxt<'tcx> { dep_node: &DepNode, ) -> Q::Value { // Note this function can be called concurrently from the same query - // We must ensure that this is handled correctly + // We must ensure that this is handled correctly. debug_assert!(self.dep_graph.is_green(dep_node)); - // First we try to load the result from the on-disk cache + // First we try to load the result from the on-disk cache. let result = if Q::cache_on_disk(self.global_tcx(), key.clone(), None) && self.sess.opts.debugging_opts.incremental_queries { self.sess.profiler(|p| p.incremental_load_result_start(Q::NAME)); @@ -453,10 +453,10 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.profiler(|p| p.incremental_load_result_end(Q::NAME)); // We always expect to find a cached result for things that - // can be forced from DepNode. + // can be forced from `DepNode`. debug_assert!(!dep_node.kind.can_reconstruct_query_key() || result.is_some(), - "Missing on-disk cache entry for {:?}", + "missing on-disk cache entry for {:?}", dep_node); result } else { @@ -475,8 +475,7 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.profiler(|p| p.start_query(Q::NAME)); - // The dep-graph for this computation is already in - // place + // The dep-graph for this computation is already in-place. let result = self.dep_graph.with_ignore(|| { Q::compute(self, key) }); @@ -485,7 +484,7 @@ impl<'tcx> TyCtxt<'tcx> { result }; - // If -Zincremental-verify-ich is specified, re-hash results from + // If `-Zincremental-verify-ich` is specified, re-hash results from // the cache and make sure that they have the expected fingerprint. if unlikely!(self.sess.opts.debugging_opts.incremental_verify_ich) { self.incremental_verify_ich::(&result, dep_node, dep_node_index); @@ -508,10 +507,12 @@ impl<'tcx> TyCtxt<'tcx> { ) { use crate::ich::Fingerprint; - assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) == + assert!( + Some(self.dep_graph.fingerprint_of(dep_node_index)) == self.dep_graph.prev_fingerprint_of(dep_node), - "Fingerprint for green query instance not loaded \ - from cache: {:?}", dep_node); + "fingerprint for green query instance not loaded from cache: {:?}", + dep_node, + ); debug!("BEGIN verify_ich({:?})", dep_node); let mut hcx = self.create_stable_hashing_context(); @@ -521,8 +522,11 @@ impl<'tcx> TyCtxt<'tcx> { let old_hash = self.dep_graph.fingerprint_of(dep_node_index); - assert!(new_hash == old_hash, "Found unstable fingerprints \ - for {:?}", dep_node); + assert!( + new_hash == old_hash, + "found unstable fingerprints for {:?}", + dep_node, + ); } #[inline(always)] @@ -534,11 +538,11 @@ impl<'tcx> TyCtxt<'tcx> { ) -> (Q::Value, DepNodeIndex) { // If the following assertion triggers, it can have two reasons: // 1. Something is wrong with DepNode creation, either here or - // in DepGraph::try_mark_green() - // 2. Two distinct query keys get mapped to the same DepNode - // (see for example #48923) + // in `DepGraph::try_mark_green()`. + // 2. Two distinct query keys get mapped to the same `DepNode` + // (see for example #48923). assert!(!self.dep_graph.dep_node_exists(&dep_node), - "Forcing query with already existing DepNode.\n\ + "forcing query with already existing `DepNode`\n\ - query-key: {:?}\n\ - dep-node: {:?}", key, dep_node); @@ -584,7 +588,7 @@ impl<'tcx> TyCtxt<'tcx> { } /// Ensure that either this query has all green inputs or been executed. - /// Executing query::ensure(D) is considered a read of the dep-node D. + /// Executing `query::ensure(D)` is considered a read of the dep-node `D`. /// /// This function is particularly useful when executing passes for their /// side-effects -- e.g., in order to report errors for erroneous programs. @@ -899,13 +903,13 @@ macro_rules! define_queries_inner { } } - // FIXME(eddyb) Get more valid Span's on queries. + // FIXME(eddyb) Get more valid `Span`s on queries. pub fn default_span(&self, tcx: TyCtxt<$tcx>, span: Span) -> Span { if !span.is_dummy() { return span; } - // The def_span query is used to calculate default_span, - // so exit to avoid infinite recursion + // The `def_span` query is used to calculate `default_span`, + // so exit to avoid infinite recursion. if let Query::def_span(..) = *self { return span } @@ -1116,7 +1120,7 @@ macro_rules! define_provider_struct { impl<$tcx> Default for Providers<$tcx> { fn default() -> Self { $(fn $name<$tcx>(_: TyCtxt<$tcx>, key: $K) -> $R { - bug!("tcx.{}({:?}) unsupported by its crate", + bug!("`tcx.{}({:?})` unsupported by its crate", stringify!($name), key); })* Providers { $($name),* } @@ -1128,26 +1132,26 @@ macro_rules! define_provider_struct { /// The red/green evaluation system will try to mark a specific DepNode in the /// dependency graph as green by recursively trying to mark the dependencies of -/// that DepNode as green. While doing so, it will sometimes encounter a DepNode +/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode` /// where we don't know if it is red or green and we therefore actually have /// to recompute its value in order to find out. Since the only piece of -/// information that we have at that point is the DepNode we are trying to +/// information that we have at that point is the `DepNode` we are trying to /// re-evaluate, we need some way to re-run a query from just that. This is what /// `force_from_dep_node()` implements. /// -/// In the general case, a DepNode consists of a DepKind and an opaque +/// In the general case, a `DepNode` consists of a `DepKind` and an opaque /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint /// is usually constructed by computing a stable hash of the query-key that the -/// DepNode corresponds to. Consequently, it is not in general possible to go +/// `DepNode` corresponds to. Consequently, it is not in general possible to go /// back from hash to query-key (since hash functions are not reversible). For /// this reason `force_from_dep_node()` is expected to fail from time to time -/// because we just cannot find out, from the DepNode alone, what the +/// because we just cannot find out, from the `DepNode` alone, what the /// corresponding query-key is and therefore cannot re-run the query. /// /// The system deals with this case letting `try_mark_green` fail which forces /// the root query to be re-evaluated. /// -/// Now, if force_from_dep_node() would always fail, it would be pretty useless. +/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless. /// Fortunately, we can use some contextual information that will allow us to /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a @@ -1171,9 +1175,9 @@ macro_rules! define_provider_struct { pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { use crate::dep_graph::RecoverKey; - // We must avoid ever having to call force_from_dep_node() for a - // DepNode::codegen_unit: - // Since we cannot reconstruct the query key of a DepNode::codegen_unit, we + // We must avoid ever having to call `force_from_dep_node()` for a + // `DepNode::codegen_unit`: + // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we // would always end up having to evaluate the first caller of the // `codegen_unit` query that *is* reconstructible. This might very well be // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just @@ -1196,7 +1200,7 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { if let Some(def_id) = dep_node.extract_def_id(tcx) { def_id } else { - // return from the whole function + // Return from the whole function. return false } } @@ -1224,20 +1228,20 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { rustc_dep_node_force!([dep_node, tcx] // These are inputs that are expected to be pre-allocated and that - // should therefore always be red or green already + // should therefore always be red or green already. DepKind::AllLocalTraitImpls | DepKind::Krate | DepKind::CrateMetadata | DepKind::HirBody | DepKind::Hir | - // This are anonymous nodes + // These are anonymous nodes. DepKind::TraitSelect | // We don't have enough information to reconstruct the query key of - // these + // these. DepKind::CompileCodegenUnit => { - bug!("force_from_dep_node() - Encountered {:?}", dep_node) + bug!("force_from_dep_node: encountered {:?}", dep_node) } DepKind::Analysis => { force!(analysis, krate!()); } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index d2edf6fb1ee80..e73a51e6f78e5 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -644,7 +644,7 @@ impl<'tcx> Binder> { impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List> {} impl<'tcx> List> { - /// Returns the "principal def id" of this set of existential predicates. + /// Returns the "principal `DefId`" of this set of existential predicates. /// /// A Rust trait object type consists (in addition to a lifetime bound) /// of a set of trait bounds, which are separated into any number @@ -1052,7 +1052,7 @@ impl<'tcx> PolyGenSig<'tcx> { } } -/// Signature of a function type, which I have arbitrarily +/// Signature of a function type, which we have arbitrarily /// decided to use to refer to the input/output types. /// /// - `inputs`: is the list of arguments and their modes. @@ -1076,7 +1076,8 @@ impl<'tcx> FnSig<'tcx> { self.inputs_and_output[self.inputs_and_output.len() - 1] } - // Create a minimal `FnSig` to be used when encountering a `TyKind::Error` in a fallible method + // Creates a minimal `FnSig` to be used when encountering a `TyKind::Error` in a fallible + // method. fn fake() -> FnSig<'tcx> { FnSig { inputs_and_output: List::empty(), @@ -1118,7 +1119,6 @@ impl<'tcx> PolyFnSig<'tcx> { pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder>>; - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct ParamTy { diff --git a/src/librustc_ast_borrowck/cfg/construct.rs b/src/librustc_ast_borrowck/cfg/construct.rs index 339d92145c64f..0dc999083a91a 100644 --- a/src/librustc_ast_borrowck/cfg/construct.rs +++ b/src/librustc_ast_borrowck/cfg/construct.rs @@ -1,11 +1,12 @@ use crate::cfg::*; -use rustc_data_structures::graph::implementation as graph; -use rustc::middle::region; -use rustc::ty::{self, TyCtxt}; use rustc::hir::{self, PatKind}; use rustc::hir::def_id::DefId; use rustc::hir::ptr::P; +use rustc::middle::region; +use rustc::ty::{self, TyCtxt}; + +use rustc_data_structures::graph::implementation as graph; struct CFGBuilder<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -19,15 +20,15 @@ struct CFGBuilder<'a, 'tcx> { #[derive(Copy, Clone)] struct BlockScope { - block_expr_id: hir::ItemLocalId, // id of breakable block expr node + block_expr_id: hir::ItemLocalId, // ID of breakable block expr node break_index: CFGIndex, // where to go on `break` } #[derive(Copy, Clone)] struct LoopScope { - loop_id: hir::ItemLocalId, // id of loop/while node + loop_id: hir::ItemLocalId, // ID of `loop`/`while` node continue_index: CFGIndex, // where to go on a `loop` - break_index: CFGIndex, // where to go on a `break` + break_index: CFGIndex, // where to go on a `break` } pub(super) fn construct(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG { @@ -103,9 +104,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { let init_exit = self.opt_expr(&local.init, pred); self.pat(&local.pat, init_exit) } - hir::StmtKind::Item(_) => { - pred - } + hir::StmtKind::Item(_) => pred, hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { self.expr(&expr, pred) @@ -154,12 +153,12 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } } - fn pats_all<'b, I: Iterator>>( + /// Handles case where all of the patterns must match. + fn pats_all<'b, I: Iterator>>( &mut self, pats: I, - pred: CFGIndex + pred: CFGIndex, ) -> CFGIndex { - //! Handles case where all of the patterns must match. pats.fold(pred, |pred, pat| self.pat(&pat, pred)) } @@ -185,15 +184,15 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // Note that `break` and `loop` statements // may cause additional edges. - let loopback = self.add_dummy_node(&[pred]); // 1 - let expr_exit = self.add_ast_node(expr.hir_id.local_id, &[]); // 2 + let loopback = self.add_dummy_node(&[pred]); // 1 + let expr_exit = self.add_ast_node(expr.hir_id.local_id, &[]); // 2 self.loop_scopes.push(LoopScope { loop_id: expr.hir_id.local_id, continue_index: loopback, break_index: expr_exit, }); - let body_exit = self.block(&body, loopback); // 3 - self.add_contained_edge(body_exit, loopback); // 4 + let body_exit = self.block(&body, loopback); // 3 + self.add_contained_edge(body_exit, loopback); // 4 self.loop_scopes.pop(); expr_exit } @@ -217,9 +216,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // v 3 v 4 // [..exit..] // - let l_exit = self.expr(&l, pred); // 1 - let r_exit = self.expr(&r, l_exit); // 2 - self.add_ast_node(expr.hir_id.local_id, &[l_exit, r_exit]) // 3,4 + let l_exit = self.expr(&l, pred); // 1 + let r_exit = self.expr(&r, l_exit); // 2 + self.add_ast_node(expr.hir_id.local_id, &[l_exit, r_exit]) // 3,4 } hir::ExprKind::Ret(ref v) => { @@ -313,11 +312,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } } - fn call<'b, I: Iterator>(&mut self, - call_expr: &hir::Expr, - pred: CFGIndex, - func_or_rcvr: &hir::Expr, - args: I) -> CFGIndex { + fn call<'b, I: Iterator>( + &mut self, + call_expr: &hir::Expr, + pred: CFGIndex, + func_or_rcvr: &hir::Expr, + args: I, + ) -> CFGIndex { let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); let ret = self.straightline(call_expr, func_or_rcvr_exit, args); let m = self.tcx.hir().get_module_parent(call_expr.hir_id); @@ -328,33 +329,38 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } } - fn exprs<'b, I: Iterator>(&mut self, - exprs: I, - pred: CFGIndex) -> CFGIndex { - //! Constructs graph for `exprs` evaluated in order + /// Constructs graph for `exprs` evaluated in order. + fn exprs<'b, I: Iterator>( + &mut self, + exprs: I, + pred: CFGIndex, + ) -> CFGIndex { exprs.fold(pred, |p, e| self.expr(e, p)) } - fn opt_expr(&mut self, - opt_expr: &Option>, - pred: CFGIndex) -> CFGIndex { - //! Constructs graph for `opt_expr` evaluated, if Some + /// Constructs graph for `opt_expr` evaluated, if `Some`. + fn opt_expr( + &mut self, + opt_expr: &Option>, + pred: CFGIndex, + ) -> CFGIndex { opt_expr.iter().fold(pred, |p, e| self.expr(&e, p)) } - fn straightline<'b, I: Iterator>(&mut self, - expr: &hir::Expr, - pred: CFGIndex, - subexprs: I) -> CFGIndex { - //! Handles case of an expression that evaluates `subexprs` in order - + /// Handles case of an expression that evaluates `subexprs` in order. + fn straightline<'b, I: Iterator>( + &mut self, + expr: &hir::Expr, + pred: CFGIndex, + subexprs: I, + ) -> CFGIndex { let subexprs_exit = self.exprs(subexprs, pred); self.add_ast_node(expr.hir_id.local_id, &[subexprs_exit]) } fn match_(&mut self, id: hir::ItemLocalId, discr: &hir::Expr, arms: &[hir::Arm], pred: CFGIndex) -> CFGIndex { - // The CFG for match expression is quite complex, so no ASCII + // The CFG for match expressions is quite complex, so no ASCII // art for it (yet). // // The CFG generated below matches roughly what MIR contains. @@ -369,13 +375,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // // What is going on is explained in further comments. - // Visit the discriminant expression + // Visit the discriminant expression. let discr_exit = self.expr(discr, pred); // Add a node for the exit of the match expression as a whole. let expr_exit = self.add_ast_node(id, &[]); - // Keep track of the previous guard expressions + // Keep track of the previous guard expressions. let mut prev_guard = None; let match_scope = region::Scope { id, data: region::ScopeData::Node }; @@ -388,12 +394,12 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // Visit the pattern, coming from the discriminant exit let mut pat_exit = self.pat(&pat, discr_exit); - // If there is a guard expression, handle it here + // If there is a guard expression, handle it here. if let Some(ref guard) = arm.guard { // Add a dummy node for the previous guard - // expression to target + // expression to target. let guard_start = self.add_dummy_node(&[pat_exit]); - // Visit the guard expression + // Visit the guard expression. let guard_exit = match guard { hir::Guard::If(ref e) => (&**e, self.expr(e, guard_start)), }; @@ -407,24 +413,23 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.add_exiting_edge(prev_guard, prev_index, match_scope, guard_start); } - // Push the guard onto the list of previous guards + // Push the guard onto the list of previous guards. prev_guard = Some(guard_exit); - // Update the exit node for the pattern + // Update the exit node for the pattern. pat_exit = guard_exit.1; } - // Add an edge from the exit of this pattern to the - // exit of the arm + // Add an edge from the exit of this pattern to the exit of the arm. self.add_contained_edge(pat_exit, bindings_exit); } - // Visit the body of this arm + // Visit the body of this arm. let body_exit = self.expr(&arm.body, bindings_exit); let arm_exit = self.add_ast_node(arm.hir_id.local_id, &[body_exit]); - // Link the body to the exit of the expression + // Link the body to the exit of the expression. self.add_contained_edge(arm_exit, expr_exit); } @@ -451,18 +456,22 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { node } - fn add_contained_edge(&mut self, - source: CFGIndex, - target: CFGIndex) { + fn add_contained_edge( + &mut self, + source: CFGIndex, + target: CFGIndex, + ) { let data = CFGEdgeData {exiting_scopes: vec![] }; self.graph.add_edge(source, target, data); } - fn add_exiting_edge(&mut self, - from_expr: &hir::Expr, - from_index: CFGIndex, - target_scope: region::Scope, - to_index: CFGIndex) { + fn add_exiting_edge( + &mut self, + from_expr: &hir::Expr, + from_index: CFGIndex, + target_scope: region::Scope, + to_index: CFGIndex, + ) { let mut data = CFGEdgeData { exiting_scopes: vec![] }; let mut scope = region::Scope { id: from_expr.hir_id.local_id, @@ -476,9 +485,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.graph.add_edge(from_index, to_index, data); } - fn add_returning_edge(&mut self, - _from_expr: &hir::Expr, - from_index: CFGIndex) { + fn add_returning_edge( + &mut self, + _from_expr: &hir::Expr, + from_index: CFGIndex, + ) { let data = CFGEdgeData { exiting_scopes: self.loop_scopes.iter() .rev() @@ -488,11 +499,12 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.graph.add_edge(from_index, self.fn_exit, data); } - fn find_scope_edge(&self, - expr: &hir::Expr, - destination: hir::Destination, - scope_cf_kind: ScopeCfKind) -> (region::Scope, CFGIndex) { - + fn find_scope_edge( + &self, + expr: &hir::Expr, + destination: hir::Destination, + scope_cf_kind: ScopeCfKind, + ) -> (region::Scope, CFGIndex) { match destination.target_id { Ok(loop_id) => { for b in &self.breakable_block_scopes { @@ -519,7 +531,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { }); } } - span_bug!(expr.span, "no scope for id {}", loop_id); + span_bug!(expr.span, "no scope for ID {}", loop_id); } Err(err) => span_bug!(expr.span, "scope error: {}", err), } diff --git a/src/librustc_ast_borrowck/cfg/graphviz.rs b/src/librustc_ast_borrowck/cfg/graphviz.rs index 46409f1a1cebf..99c6b49cad5d9 100644 --- a/src/librustc_ast_borrowck/cfg/graphviz.rs +++ b/src/librustc_ast_borrowck/cfg/graphviz.rs @@ -1,4 +1,4 @@ -/// This module provides linkage between rustc::middle::graph and +/// This module provides linkage between `rustc::middle::graph` and /// libgraphviz traits. use crate::cfg; @@ -12,7 +12,7 @@ pub struct LabelledCFG<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, pub cfg: &'a cfg::CFG, pub name: String, - /// `labelled_edges` controls whether we emit labels on the edges + /// `labelled_edges` controls whether we emit labels on the edges. pub labelled_edges: bool, } @@ -25,12 +25,12 @@ impl<'a, 'tcx> LabelledCFG<'a, 'tcx> { }; let s = self.tcx.hir().node_to_string(hir_id); - // Replacing newlines with \\l causes each line to be left-aligned, + // Replacing newlines with `\\l` causes each line to be left-aligned, // improving presentation of (long) pretty-printed expressions. if s.contains("\n") { let mut s = s.replace("\n", "\\l"); // Apparently left-alignment applies to the line that precedes - // \l, not the line that follows; so, add \l at end of string + // `\l`, not the line that follows; so, add `\l` at end of string // if not already present, ensuring last line gets left-aligned // as well. let mut last_two: Vec<_> = @@ -109,8 +109,7 @@ impl<'a> dot::GraphWalk<'a> for &'a cfg::CFG { } } -impl<'a, 'hir> dot::GraphWalk<'a> for LabelledCFG<'a, 'hir> -{ +impl<'a, 'hir> dot::GraphWalk<'a> for LabelledCFG<'a, 'hir> { type Node = Node<'a>; type Edge = Edge<'a>; fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { self.cfg.nodes() } From fd48ca20d366cff016cb0f9cfd8e98c44a91da10 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Fri, 6 Sep 2019 21:05:37 +0100 Subject: [PATCH 554/618] Apply suggestions from code review Co-Authored-By: Mazdak Farrokhzad --- src/librustc/hir/lowering.rs | 2 +- src/librustc/mir/interpret/allocation.rs | 9 +++-- src/librustc/mir/interpret/mod.rs | 1 - src/librustc/mir/mod.rs | 27 +++++++------ src/librustc/session/config.rs | 4 +- src/librustc/traits/util.rs | 2 +- src/librustc/ty/context.rs | 6 +-- src/librustc/ty/print/pretty.rs | 51 +++++++++++------------- src/librustc/ty/query/on_disk_cache.rs | 12 ++---- 9 files changed, 54 insertions(+), 60 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index fd6445ea3c4d4..b50cfa00f09ef 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -126,7 +126,7 @@ pub struct LoweringContext<'a> { /// lifetime definitions in the corresponding impl or function generics. lifetimes_to_define: Vec<(Span, ParamName)>, - /// `true` ifs in-band lifetimes are being collected. This is used to + /// `true` if in-band lifetimes are being collected. This is used to /// indicate whether or not we're in a place where new lifetimes will result /// in in-band lifetime definitions, such a function or an impl header, /// including implicit lifetimes from `impl_header_lifetime_elision`. diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index e81096c3066f1..755cda792ba79 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -4,13 +4,14 @@ use super::{ Pointer, InterpResult, AllocId, ScalarMaybeUndef, write_target_uint, read_target_uint, Scalar, }; +use crate::mir; use crate::ty::layout::{Size, Align}; + +use rustc_data_structures::sorted_map::SortedMap; +use rustc_target::abi::HasDataLayout; use syntax::ast::Mutability; use std::iter; -use crate::mir; use std::ops::{Range, Deref, DerefMut}; -use rustc_data_structures::sorted_map::SortedMap; -use rustc_target::abi::HasDataLayout; use std::borrow::Cow; // NOTE: When adding new fields, make sure to adjust the `Snapshot` impl in @@ -765,7 +766,7 @@ impl Allocation { } } - /// Apply a relocation copy. + /// Applies a relocation copy. /// The affected range, as defined in the parameters to `prepare_relocation_copy` is expected /// to be clear of relocations. pub fn mark_relocation_range( diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 6f7e11877d5fb..23433c2e8834d 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -349,7 +349,6 @@ pub enum GlobalAlloc<'tcx> { Memory(&'tcx Allocation), } -#[derive(Clone)] pub struct AllocMap<'tcx> { /// Maps `AllocId`s to their corresponding allocations. alloc_map: FxHashMap>, diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index da2faeb4e1ebf..18a5142208d2d 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -605,8 +605,6 @@ pub enum LocalKind { #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct VarBindingForm<'tcx> { - /// The `HirId` of the variable. - pub var_id: hir::HirId, /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`? pub binding_mode: ty::BindingMode, /// If an explicit type was provided for this variable binding, @@ -656,7 +654,6 @@ pub enum ImplicitSelfKind { CloneTypeFoldableAndLiftImpls! { BindingForm<'tcx>, } impl_stable_hash_for!(struct self::VarBindingForm<'tcx> { - var_id, binding_mode, opt_ty_info, opt_match_place, @@ -877,7 +874,9 @@ impl<'tcx> LocalDecl<'tcx> { match self.is_user_variable { Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { binding_mode: ty::BindingMode::BindByValue(_), - .. + opt_ty_info: _, + opt_match_place: _, + pat_span: _, }))) => true, Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(ImplicitSelfKind::Imm))) => true, @@ -893,7 +892,9 @@ impl<'tcx> LocalDecl<'tcx> { match self.is_user_variable { Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { binding_mode: ty::BindingMode::BindByValue(_), - .. + opt_ty_info: _, + opt_match_place: _, + pat_span: _, }))) => true, Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_))) => true, @@ -2830,7 +2831,7 @@ impl Location { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub enum UnsafetyViolationKind { General, - /// Permitted in const fns and regular fns. + /// Permitted both in `const fn`s and regular `fn`s. GeneralAndConstFn, ExternStatic(hir::HirId), BorrowPacked(hir::HirId), @@ -2848,7 +2849,7 @@ pub struct UnsafetyViolation { pub struct UnsafetyCheckResult { /// Violations that are propagated *upwards* from this function. pub violations: Lrc<[UnsafetyViolation]>, - /// Unsafe blocks in this function, along with whether they are used. This is + /// `unsafe` blocks in this function, along with whether they are used. This is /// used for the "unused_unsafe" lint. pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>, } @@ -2875,12 +2876,14 @@ pub struct GeneratorLayout<'tcx> { /// layout. pub storage_conflicts: BitMatrix, - /// Names and scopes of all the stored generator locals. + /// The names and scopes of all the stored generator locals. + /// + /// N.B., this is *strictly* a temporary hack for codegen + /// debuginfo generation, and will be removed at some point. + /// Do **NOT** use it for anything else, local information should not be + /// in the MIR, please rely on local crate HIR or other side-channels. // - // NOTE(tmandry) This is *strictly* a temporary hack for codegen - // debuginfo generation, and will be removed at some point. - // Do **NOT** use it for anything else, local information should not be - // in the MIR, please rely on local crate HIR or other side-channels. + // FIXME(tmandry): see above. pub __local_debuginfo_codegen_only_do_not_use: IndexVec>, } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 27a33ced119df..c74b2fee41d6c 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -711,11 +711,11 @@ impl Passes { } /// Defines all `CodegenOptions`/`DebuggingOptions` fields and parsers all at once. The goal of this -/// macro is to define an interface that can be programmatically used by the option parser in order +/// macro is to define an interface that can be programmatically used by the option parser /// to initialize the struct without hardcoding field names all over the place. /// /// The goal is to invoke this macro once with the correct fields, and then this macro generates all -/// necessary code. The main gotcha of this macro is the cgsetters module which is a bunch of +/// necessary code. The main gotcha of this macro is the `cgsetters` module which is a bunch of /// generated code to parse an option into its respective field in the struct. There are a few /// hand-written parsers for parsing specific types of values in this module. macro_rules! options { diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 7f3c62ec99470..3d36790c94b8c 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -571,7 +571,7 @@ impl<'tcx> TyCtxt<'tcx> { -> Vec> { if source_trait_ref.def_id() == target_trait_def_id { - return vec![source_trait_ref]; // Shorcut the most common case. + return vec![source_trait_ref]; // Shortcut the most common case. } supertraits(self, source_trait_ref) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 6867230f4ec43..8e8472a5aacc9 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1,5 +1,3 @@ -// ignore-tidy-filelength - //! Type context book-keeping. use crate::arena::Arena; @@ -1753,7 +1751,7 @@ pub mod tls { pub task_deps: Option<&'a Lock>, } - /// Sets Rayon's thread local variablem, which is preserved for Rayon jobs + /// Sets Rayon's thread-local variable, which is preserved for Rayon jobs /// to `value` during the call to `f`. It is restored to its previous value after. /// This is used to set the pointer to the new `ImplicitCtxt`. #[cfg(parallel_compiler)] @@ -1762,7 +1760,7 @@ pub mod tls { rayon_core::tlv::with(value, f) } - /// Gets Rayon's thread local variable, which is preserved for Rayon jobs. + /// Gets Rayon's thread-local variable, which is preserved for Rayon jobs. /// This is used to get the pointer to the current `ImplicitCtxt`. #[cfg(parallel_compiler)] #[inline] diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 419a815074b5e..d99580116e4ae 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1093,38 +1093,35 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { } let key = self.tcx.def_key(def_id); - match key.disambiguated_data.data { - DefPathData::Impl => { - // Always use types for non-local impls, where types are always - // available, and filename/line-number is mostly uninteresting. - let use_types = - !def_id.is_local() || { - // Otherwise, use filename/line-number if forced. - let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); - !force_no_types - }; - - if !use_types { - // If no type info is available, fall back to - // pretty-printing some span information. This should - // only occur very early in the compiler pipeline. - let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; - let span = self.tcx.def_span(def_id); + if let DefPathData::Impl = key.disambiguated_data.data { + // Always use types for non-local impls, where types are always + // available, and filename/line-number is mostly uninteresting. + let use_types = + !def_id.is_local() || { + // Otherwise, use filename/line-number if forced. + let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); + !force_no_types + }; - self = self.print_def_path(parent_def_id, &[])?; + if !use_types { + // If no type info is available, fall back to + // pretty printing some span information. This should + // only occur very early in the compiler pipeline. + let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; + let span = self.tcx.def_span(def_id); - // HACK(eddyb) copy of `path_append` to avoid - // constructing a `DisambiguatedDefPathData`. - if !self.empty_path { - write!(self, "::")?; - } - write!(self, "", span)?; - self.empty_path = false; + self = self.print_def_path(parent_def_id, &[])?; - return Ok(self); + // HACK(eddyb) copy of `path_append` to avoid + // constructing a `DisambiguatedDefPathData`. + if !self.empty_path { + write!(self, "::")?; } + write!(self, "", span)?; + self.empty_path = false; + + return Ok(self); } - _ => {} } self.default_print_def_path(def_id, substs) diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index d24143ced5be2..4cef6a09925ad 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -429,7 +429,7 @@ impl<'sess> OnDiskCache<'sess> { //- DECODING ------------------------------------------------------------------- -/// A decoder that can read fro the incr. comp. cache. It is similar to the onem +/// A decoder that can read fro the incr. comp. cache. It is similar to the one /// we use for crate metadata decoding in that it can rebase spans and eventually /// will also handle things that contain `Ty` instances. struct CacheDecoder<'a, 'tcx> { @@ -460,19 +460,17 @@ impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { } } -pub trait DecoderWithPosition: Decoder { +trait DecoderWithPosition: Decoder { fn position(&self) -> usize; } impl<'a> DecoderWithPosition for opaque::Decoder<'a> { - #[inline] fn position(&self) -> usize { self.position() } } impl<'a, 'tcx> DecoderWithPosition for CacheDecoder<'a, 'tcx> { - #[inline] fn position(&self) -> usize { self.opaque.position() } @@ -480,7 +478,7 @@ impl<'a, 'tcx> DecoderWithPosition for CacheDecoder<'a, 'tcx> { // Decodes something that was encoded with `encode_tagged()` and verify that the // tag matches and the correct amount of bytes was read. -pub fn decode_tagged(decoder: &mut D, expected_tag: T) -> Result +fn decode_tagged(decoder: &mut D, expected_tag: T) -> Result where T: Decodable + Eq + ::std::fmt::Debug, V: Decodable, @@ -700,7 +698,6 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { } impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { - #[inline] fn specialized_decode(&mut self) -> Result { Fingerprint::decode_opaque(&mut self.opaque) } @@ -754,7 +751,7 @@ where /// encode the specified tag, then the given value, then the number of /// bytes taken up by tag and value. On decoding, we can then verify that /// we get the expected tag and read the expected number of bytes. - pub fn encode_tagged( + fn encode_tagged( &mut self, tag: T, value: &V @@ -960,7 +957,6 @@ where } impl<'a, 'tcx> SpecializedEncoder for CacheEncoder<'a, 'tcx, opaque::Encoder> { - #[inline] fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> { f.encode_opaque(&mut self.encoder) } From 49d2fd1725510fd3bf6f2937e178b1aa055ddb02 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Fri, 6 Sep 2019 03:56:45 +0100 Subject: [PATCH 555/618] Aggregation of cosmetic changes made during work on REPL PRs: libsyntax --- src/libsyntax/ast.rs | 52 ++++---- src/libsyntax/attr/mod.rs | 43 +++--- src/libsyntax/ext/base.rs | 2 +- src/libsyntax/feature_gate/active.rs | 18 +-- src/libsyntax/feature_gate/builtin_attrs.rs | 2 +- src/libsyntax/feature_gate/check.rs | 4 +- src/libsyntax/mut_visit.rs | 28 ++-- src/libsyntax/mut_visit/tests.rs | 10 +- src/libsyntax/parse/attr.rs | 38 +++--- src/libsyntax/parse/diagnostics.rs | 76 +++++------ src/libsyntax/parse/lexer/tests.rs | 17 +-- src/libsyntax/parse/mod.rs | 53 ++++---- src/libsyntax/parse/parser.rs | 50 +++---- src/libsyntax/parse/parser/expr.rs | 141 ++++++++++---------- src/libsyntax/parse/parser/item.rs | 115 ++++++++-------- src/libsyntax/parse/parser/module.rs | 6 +- src/libsyntax/parse/parser/pat.rs | 4 +- src/libsyntax/parse/parser/stmt.rs | 64 ++++----- src/libsyntax/parse/tests.rs | 8 +- src/libsyntax/print/pprust.rs | 52 ++++---- src/libsyntax/print/pprust/tests.rs | 5 +- src/libsyntax/source_map.rs | 128 +++++++++--------- src/libsyntax/source_map/tests.rs | 98 ++++++++------ src/libsyntax/tests.rs | 18 +-- src/libsyntax/tokenstream.rs | 7 +- src/libsyntax/visit.rs | 23 ++-- 26 files changed, 538 insertions(+), 524 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index c93e6d11ce711..bfb2db9596363 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -413,11 +413,11 @@ impl WherePredicate { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereBoundPredicate { pub span: Span, - /// Any generics from a `for` binding + /// Any generics from a `for` binding. pub bound_generic_params: Vec, - /// The type being bounded + /// The type being bounded. pub bounded_ty: P, - /// Trait and lifetime bounds (`Clone+Send+'static`) + /// Trait and lifetime bounds (`Clone + Send + 'static`). pub bounds: GenericBounds, } @@ -495,15 +495,15 @@ pub enum MetaItemKind { NameValue(Lit), } -/// A Block (`{ .. }`). +/// A block (`{ .. }`). /// /// E.g., `{ .. }` as in `fn foo() { .. }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Block { - /// Statements in a block + /// The statements in the block. pub stmts: Vec, pub id: NodeId, - /// Distinguishes between `unsafe { ... }` and `{ ... }` + /// Distinguishes between `unsafe { ... }` and `{ ... }`. pub rules: BlockCheckMode, pub span: Span, } @@ -908,11 +908,11 @@ pub enum MacStmtStyle { /// Local represents a `let` statement, e.g., `let : = ;`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Local { + pub id: NodeId, pub pat: P, pub ty: Option>, /// Initializer expression to set the value, if any. pub init: Option>, - pub id: NodeId, pub span: Span, pub attrs: ThinVec, } @@ -970,7 +970,7 @@ pub struct AnonConst { pub value: P, } -/// An expression +/// An expression. #[derive(Clone, RustcEncodable, RustcDecodable)] pub struct Expr { pub id: NodeId, @@ -984,26 +984,26 @@ pub struct Expr { static_assert_size!(Expr, 96); impl Expr { - /// Whether this expression would be valid somewhere that expects a value; for example, an `if` - /// condition. + /// Returns `true` if this expression would be valid somewhere that expects a value; + /// for example, an `if` condition. pub fn returns(&self) -> bool { if let ExprKind::Block(ref block, _) = self.node { match block.stmts.last().map(|last_stmt| &last_stmt.node) { - // implicit return + // Implicit return Some(&StmtKind::Expr(_)) => true, Some(&StmtKind::Semi(ref expr)) => { if let ExprKind::Ret(_) = expr.node { - // last statement is explicit return + // Last statement is explicit return. true } else { false } } - // This is a block that doesn't end in either an implicit or explicit return + // This is a block that doesn't end in either an implicit or explicit return. _ => false, } } else { - // This is not a block, it is a value + // This is not a block, it is a value. true } } @@ -2307,37 +2307,37 @@ impl Default for FnHeader { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ItemKind { - /// An `extern crate` item, with optional *original* crate name if the crate was renamed. + /// An `extern crate` item, with the optional *original* crate name if the crate was renamed. /// /// E.g., `extern crate foo` or `extern crate foo_bar as foo`. ExternCrate(Option), - /// A use declaration (`use` or `pub use`) item. + /// A use declaration item (`use`). /// /// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`. Use(P), - /// A static item (`static` or `pub static`). + /// A static item (`static`). /// /// E.g., `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`. Static(P, Mutability, P), - /// A constant item (`const` or `pub const`). + /// A constant item (`const`). /// /// E.g., `const FOO: i32 = 42;`. Const(P, P), - /// A function declaration (`fn` or `pub fn`). + /// A function declaration (`fn`). /// /// E.g., `fn foo(bar: usize) -> usize { .. }`. Fn(P, FnHeader, Generics, P), - /// A module declaration (`mod` or `pub mod`). + /// A module declaration (`mod`). /// /// E.g., `mod foo;` or `mod foo { .. }`. Mod(Mod), - /// An external module (`extern` or `pub extern`). + /// An external module (`extern`). /// /// E.g., `extern {}` or `extern "C" {}`. ForeignMod(ForeignMod), /// Module-level inline assembly (from `global_asm!()`). GlobalAsm(P), - /// A type alias (`type` or `pub type`). + /// A type alias (`type`). /// /// E.g., `type Foo = Bar;`. TyAlias(P, Generics), @@ -2345,19 +2345,19 @@ pub enum ItemKind { /// /// E.g., `type Foo = impl Bar + Boo;`. OpaqueTy(GenericBounds, Generics), - /// An enum definition (`enum` or `pub enum`). + /// An enum definition (`enum`). /// /// E.g., `enum Foo { C, D }`. Enum(EnumDef, Generics), - /// A struct definition (`struct` or `pub struct`). + /// A struct definition (`struct`). /// /// E.g., `struct Foo { x: A }`. Struct(VariantData, Generics), - /// A union definition (`union` or `pub union`). + /// A union definition (`union`). /// /// E.g., `union Foo { x: A, y: B }`. Union(VariantData, Generics), - /// A Trait declaration (`trait` or `pub trait`). + /// A trait declaration (`trait`). /// /// E.g., `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}`. Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec), diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 69de3150354e7..1f954064944dc 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -1,4 +1,4 @@ -//! Functions dealing with attributes and meta items +//! Functions dealing with attributes and meta items. mod builtin; @@ -61,7 +61,7 @@ pub fn is_known_lint_tool(m_item: Ident) -> bool { } impl NestedMetaItem { - /// Returns the MetaItem if self is a NestedMetaItem::MetaItem. + /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`. pub fn meta_item(&self) -> Option<&MetaItem> { match *self { NestedMetaItem::MetaItem(ref item) => Some(item), @@ -69,7 +69,7 @@ impl NestedMetaItem { } } - /// Returns the Lit if self is a NestedMetaItem::Literal. + /// Returns the `Lit` if `self` is a `NestedMetaItem::Literal`s. pub fn literal(&self) -> Option<&Lit> { match *self { NestedMetaItem::Literal(ref lit) => Some(lit), @@ -82,7 +82,7 @@ impl NestedMetaItem { self.meta_item().map_or(false, |meta_item| meta_item.check_name(name)) } - /// For a single-segment meta-item returns its name, otherwise returns `None`. + /// For a single-segment meta item, returns its name; otherwise, returns `None`. pub fn ident(&self) -> Option { self.meta_item().and_then(|meta_item| meta_item.ident()) } @@ -90,13 +90,13 @@ impl NestedMetaItem { self.ident().unwrap_or(Ident::invalid()).name } - /// Gets the string value if self is a MetaItem and the MetaItem is a - /// MetaItemKind::NameValue variant containing a string, otherwise None. + /// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a + /// `MetaItemKind::NameValue` variant containing a string, otherwise `None`. pub fn value_str(&self) -> Option { self.meta_item().and_then(|meta_item| meta_item.value_str()) } - /// Returns a name and single literal value tuple of the MetaItem. + /// Returns a name and single literal value tuple of the `MetaItem`. pub fn name_value_literal(&self) -> Option<(Name, &Lit)> { self.meta_item().and_then( |meta_item| meta_item.meta_item_list().and_then( @@ -112,32 +112,32 @@ impl NestedMetaItem { })) } - /// Gets a list of inner meta items from a list MetaItem type. + /// Gets a list of inner meta items from a list `MetaItem` type. pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> { self.meta_item().and_then(|meta_item| meta_item.meta_item_list()) } - /// Returns `true` if the variant is MetaItem. + /// Returns `true` if the variant is `MetaItem`. pub fn is_meta_item(&self) -> bool { self.meta_item().is_some() } - /// Returns `true` if the variant is Literal. + /// Returns `true` if the variant is `Literal`. pub fn is_literal(&self) -> bool { self.literal().is_some() } - /// Returns `true` if self is a MetaItem and the meta item is a word. + /// Returns `true` if `self` is a `MetaItem` and the meta item is a word. pub fn is_word(&self) -> bool { self.meta_item().map_or(false, |meta_item| meta_item.is_word()) } - /// Returns `true` if self is a MetaItem and the meta item is a ValueString. + /// Returns `true` if `self` is a `MetaItem` and the meta item is a `ValueString`. pub fn is_value_str(&self) -> bool { self.value_str().is_some() } - /// Returns `true` if self is a MetaItem and the meta item is a list. + /// Returns `true` if `self` is a `MetaItem` and the meta item is a list. pub fn is_meta_item_list(&self) -> bool { self.meta_item_list().is_some() } @@ -156,7 +156,7 @@ impl Attribute { matches } - /// For a single-segment attribute returns its name, otherwise returns `None`. + /// For a single-segment attribute, returns its name; otherwise, returns `None`. pub fn ident(&self) -> Option { if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) @@ -187,14 +187,14 @@ impl Attribute { self.meta_item_list().is_some() } - /// Indicates if the attribute is a Value String. + /// Indicates if the attribute is a `ValueString`. pub fn is_value_str(&self) -> bool { self.value_str().is_some() } } impl MetaItem { - /// For a single-segment meta-item returns its name, otherwise returns `None`. + /// For a single-segment meta item, returns its name; otherwise, returns `None`. pub fn ident(&self) -> Option { if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) @@ -206,8 +206,9 @@ impl MetaItem { self.ident().unwrap_or(Ident::invalid()).name } - // #[attribute(name = "value")] - // ^^^^^^^^^^^^^^ + // Example: + // #[attribute(name = "value")] + // ^^^^^^^^^^^^^^ pub fn name_value_literal(&self) -> Option<&Lit> { match &self.node { MetaItemKind::NameValue(v) => Some(v), @@ -255,7 +256,7 @@ impl MetaItem { } impl Attribute { - /// Extracts the MetaItem from inside this Attribute. + /// Extracts the `MetaItem` from inside this `Attribute`. pub fn meta(&self) -> Option { let mut tokens = self.tokens.trees().peekable(); Some(MetaItem { @@ -318,8 +319,8 @@ impl Attribute { }) } - /// Converts self to a normal #[doc="foo"] comment, if it is a - /// comment like `///` or `/** */`. (Returns self unchanged for + /// Converts `self` to a normal `#[doc="foo"]` comment, if it is a + /// comment like `///` or `/** */`. (Returns `self` unchanged for /// non-sugared doc attributes.) pub fn with_desugared_doc(&self, f: F) -> T where F: FnOnce(&Attribute) -> T, diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 5b2515d20cbab..c4569b3fba1be 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -958,7 +958,7 @@ impl<'a> ExtCtxt<'a> { self.resolver.check_unused_macros(); } - /// Resolve a path mentioned inside Rust code. + /// Resolves a path mentioned inside Rust code. /// /// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths. /// diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index c947b09fdcb57..a15fc050141a3 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -1,9 +1,11 @@ //! List of the active feature gates. +use super::{State, Feature}; + use crate::edition::Edition; use crate::symbol::{Symbol, sym}; + use syntax_pos::Span; -use super::{State, Feature}; macro_rules! set { ($field: ident) => {{ @@ -37,9 +39,9 @@ macro_rules! declare_features { /// A set of features to be used by later passes. #[derive(Clone)] pub struct Features { - /// `#![feature]` attrs for language features, for error reporting + /// `#![feature]` attrs for language features, for error reporting. pub declared_lang_features: Vec<(Symbol, Span, Option)>, - /// `#![feature]` attrs for non-language (library) features + /// `#![feature]` attrs for non-language (library) features. pub declared_lib_features: Vec<(Symbol, Span)>, $( $(#[doc = $doc])* @@ -66,11 +68,11 @@ macro_rules! declare_features { } impl Feature { - /// Set this feature in `Features`. Panics if called on a non-active feature. + /// Sets this feature in `Features`. Panics if called on a non-active feature. pub fn set(&self, features: &mut Features, span: Span) { match self.state { State::Active { set } => set(features, span), - _ => panic!("Called `set` on feature `{}` which is not `active`", self.name) + _ => panic!("called `set` on feature `{}` which is not `active`", self.name) } } } @@ -478,7 +480,7 @@ declare_features! ( (active, precise_pointer_size_matching, "1.32.0", Some(56354), None), /// Allows relaxing the coherence rules such that - /// `impl ForeignTrait for ForeignType is permitted. + /// `impl ForeignTrait for ForeignType` is permitted. (active, re_rebalance_coherence, "1.32.0", Some(55437), None), /// Allows using `#[ffi_returns_twice]` on foreign functions. @@ -520,7 +522,7 @@ declare_features! ( /// Allows `async || body` closures. (active, async_closure, "1.37.0", Some(62290), None), - /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests + /// Allows the use of `#[cfg(doctest)]`; set when rustdoc is collecting doctests. (active, cfg_doctest, "1.37.0", Some(62210), None), /// Allows `[x; N]` where `x` is a constant (RFC 2203). @@ -529,7 +531,7 @@ declare_features! ( /// Allows `impl Trait` to be used inside type aliases (RFC 2515). (active, type_alias_impl_trait, "1.38.0", Some(63063), None), - /// Allows the use of or-patterns, e.g. `0 | 1`. + /// Allows the use of or-patterns (e.g., `0 | 1`). (active, or_patterns, "1.38.0", Some(54883), None), // ------------------------------------------------------------------------- diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index ee7ac3b15d955..763c3ffd782df 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -169,7 +169,7 @@ const INTERAL_UNSTABLE: &str = "this is an internal attribute that will never be pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate); -/// Attributes that have a special meaning to rustc or rustdoc +/// Attributes that have a special meaning to rustc or rustdoc. pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== // Stable attributes: diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index f3a9d135125ae..5711b269ff092 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -920,9 +920,9 @@ pub enum UnstableFeatures { impl UnstableFeatures { pub fn from_environment() -> UnstableFeatures { - // Whether this is a feature-staged build, i.e., on the beta or stable channel + // `true` if this is a feature-staged build, i.e., on the beta or stable channel. let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some(); - // Whether we should enable unstable features for bootstrapping + // `true` if we should enable unstable features for bootstrapping. let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok(); match (disable_unstable_features, bootstrap) { (_, true) => UnstableFeatures::Cheat, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 6023c5149d05b..1c35688666836 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1,10 +1,10 @@ -//! A MutVisitor represents an AST modification; it accepts an AST piece and -//! and mutates it in place. So, for instance, macro expansion is a MutVisitor +//! A `MutVisitor` represents an AST modification; it accepts an AST piece and +//! and mutates it in place. So, for instance, macro expansion is a `MutVisitor` //! that walks over an AST and modifies it. //! -//! Note: using a MutVisitor (other than the MacroExpander MutVisitor) on +//! Note: using a `MutVisitor` (other than the `MacroExpander` `MutVisitor`) on //! an AST before macro expansion is probably a bad idea. For instance, -//! a MutVisitor renaming item names in a module will miss all of those +//! a `MutVisitor` renaming item names in a module will miss all of those //! that are created by the expansion of a macro. use crate::ast::*; @@ -614,7 +614,7 @@ pub fn noop_visit_tts(TokenStream(tts): &mut TokenStream, vis: &m }) } -// Apply ident visitor if it's an ident, apply other visits to interpolated nodes. +// Applies ident visitor if it's an ident; applies other visits to interpolated nodes. // In practice the ident part is not actually used by specific visitors right now, // but there's a test below checking that it works. pub fn noop_visit_token(t: &mut Token, vis: &mut T) { @@ -625,7 +625,7 @@ pub fn noop_visit_token(t: &mut Token, vis: &mut T) { vis.visit_ident(&mut ident); *name = ident.name; *span = ident.span; - return; // avoid visiting the span for the second time + return; // Avoid visiting the span for the second time. } token::Interpolated(nt) => { let mut nt = Lrc::make_mut(nt); @@ -636,28 +636,28 @@ pub fn noop_visit_token(t: &mut Token, vis: &mut T) { vis.visit_span(span); } -/// Apply visitor to elements of interpolated nodes. +/// Applies the visitor to elements of interpolated nodes. // // N.B., this can occur only when applying a visitor to partially expanded // code, where parsed pieces have gotten implanted ito *other* macro // invocations. This is relevant for macro hygiene, but possibly not elsewhere. // // One problem here occurs because the types for flat_map_item, flat_map_stmt, -// etc. allow the visitor to return *multiple* items; this is a problem for the +// etc., allow the visitor to return *multiple* items; this is a problem for the // nodes here, because they insist on having exactly one piece. One solution // would be to mangle the MutVisitor trait to include one-to-many and // one-to-one versions of these entry points, but that would probably confuse a // lot of people and help very few. Instead, I'm just going to put in dynamic // checks. I think the performance impact of this will be pretty much -// nonexistent. The danger is that someone will apply a MutVisitor to a +// nonexistent. The danger is that someone will apply a `MutVisitor` to a // partially expanded node, and will be confused by the fact that their -// "flat_map_item" or "flat_map_stmt" isn't getting called on NtItem or NtStmt +// `flat_map_item` or `flat_map_stmt` isn't getting called on `NtItem` or `NtStmt` // nodes. Hopefully they'll wind up reading this comment, and doing something // appropriate. // -// BTW, design choice: I considered just changing the type of, e.g., NtItem to +// BTW, design choice: I considered just changing the type of, e.g., `NtItem` to // contain multiple items, but decided against it when I looked at -// parse_item_or_view_item and tried to figure out what I would do with +// `parse_item_or_view_item` and tried to figure out what I would do with // multiple items there.... pub fn noop_visit_interpolated(nt: &mut token::Nonterminal, vis: &mut T) { match nt { @@ -1014,7 +1014,7 @@ pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { }); } -// Mutate one item into possibly many items. +// Mutates one item into possibly many items. pub fn noop_flat_map_item(mut item: P, visitor: &mut T) -> SmallVec<[P; 1]> { let Item { ident, attrs, id, node, vis, span, tokens: _ } = item.deref_mut(); @@ -1224,7 +1224,7 @@ pub fn noop_visit_expr(Expr { node, id, span, attrs }: &mut Expr, ExprKind::Paren(expr) => { vis.visit_expr(expr); - // Nodes that are equal modulo `Paren` sugar no-ops should have the same ids. + // Nodes that are equal modulo `Paren` sugar no-ops should have the same IDs. *id = expr.id; vis.visit_span(span); visit_thin_attrs(attrs, vis); diff --git a/src/libsyntax/mut_visit/tests.rs b/src/libsyntax/mut_visit/tests.rs index 6868736976b25..f779e0d0a6014 100644 --- a/src/libsyntax/mut_visit/tests.rs +++ b/src/libsyntax/mut_visit/tests.rs @@ -6,13 +6,13 @@ use crate::print::pprust; use crate::mut_visit; use crate::with_default_globals; -// this version doesn't care about getting comments or docstrings in. +// This version doesn't care about getting comments or doc-strings in. fn fake_print_crate(s: &mut pprust::State<'_>, krate: &ast::Crate) { s.print_mod(&krate.module, &krate.attrs) } -// change every identifier to "zz" +// Change every identifier to "zz". struct ToZzIdentMutVisitor; impl MutVisitor for ToZzIdentMutVisitor { @@ -24,7 +24,7 @@ impl MutVisitor for ToZzIdentMutVisitor { } } -// maybe add to expand.rs... +// Maybe add to `expand.rs`. macro_rules! assert_pred { ($pred:expr, $predname:expr, $a:expr , $b:expr) => ( { @@ -39,7 +39,7 @@ macro_rules! assert_pred { ) } -// make sure idents get transformed everywhere +// Make sure idents get transformed everywhere. #[test] fn ident_transformation () { with_default_globals(|| { let mut zz_visitor = ToZzIdentMutVisitor; @@ -54,7 +54,7 @@ macro_rules! assert_pred { }) } -// even inside macro defs.... +// Make sure idents get transformed even inside macro defs. #[test] fn ident_transformation_in_defs () { with_default_globals(|| { let mut zz_visitor = ToZzIdentMutVisitor; diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index d9c4baad49ded..9aa1ec0b14fe9 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -26,7 +26,7 @@ impl<'a> Parser<'a> { Ok(attrs) } - /// Parse attributes that appear before an item + /// Parses attributes that appear before an item. crate fn parse_outer_attributes(&mut self) -> PResult<'a, Vec> { let mut attrs: Vec = Vec::new(); let mut just_parsed_doc_comment = false; @@ -69,10 +69,10 @@ impl<'a> Parser<'a> { Ok(attrs) } - /// Matches `attribute = # ! [ meta_item ]` + /// Matches `attribute = # ! [ meta_item ]`. /// - /// If permit_inner is true, then a leading `!` indicates an inner - /// attribute + /// If `permit_inner` is `true`, then a leading `!` indicates an inner + /// attribute. pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> { debug!("parse_attribute: permit_inner={:?} self.token={:?}", permit_inner, @@ -167,14 +167,14 @@ impl<'a> Parser<'a> { }) } - /// Parse an inner part of attribute - path and following tokens. + /// Parses an inner part of an attribute (the path and following tokens). /// The tokens must be either a delimited token stream, or empty token stream, /// or the "legacy" key-value form. - /// PATH `(` TOKEN_STREAM `)` - /// PATH `[` TOKEN_STREAM `]` - /// PATH `{` TOKEN_STREAM `}` - /// PATH - /// PATH `=` TOKEN_TREE + /// PATH `(` TOKEN_STREAM `)` + /// PATH `[` TOKEN_STREAM `]` + /// PATH `{` TOKEN_STREAM `}` + /// PATH + /// PATH `=` TOKEN_TREE /// The delimiters or `=` are still put into the resulting token stream. pub fn parse_meta_item_unrestricted(&mut self) -> PResult<'a, (ast::Path, TokenStream)> { let meta = match self.token.kind { @@ -217,11 +217,11 @@ impl<'a> Parser<'a> { }) } - /// Parse attributes that appear after the opening of an item. These should + /// Parses attributes that appear after the opening of an item. These should /// be preceded by an exclamation mark, but we accept and warn about one /// terminated by a semicolon. - - /// matches inner_attrs* + /// + /// Matches `inner_attrs*`. crate fn parse_inner_attributes(&mut self) -> PResult<'a, Vec> { let mut attrs: Vec = vec![]; loop { @@ -237,7 +237,7 @@ impl<'a> Parser<'a> { attrs.push(attr); } token::DocComment(s) => { - // we need to get the position of this token before we bump. + // We need to get the position of this token before we bump. let attr = attr::mk_sugared_doc_attr(s, self.token.span); if attr.style == ast::AttrStyle::Inner { attrs.push(attr); @@ -268,10 +268,10 @@ impl<'a> Parser<'a> { Ok(lit) } - /// Per RFC#1559, matches the following grammar: + /// Matches the following grammar (per RFC 1559). /// - /// meta_item : IDENT ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ; - /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ; + /// meta_item : IDENT ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ; + /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ; pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> { let nt_meta = match self.token.kind { token::Interpolated(ref nt) => match **nt { @@ -303,7 +303,7 @@ impl<'a> Parser<'a> { }) } - /// matches meta_item_inner : (meta_item | UNSUFFIXED_LIT) ; + /// Matches `meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;`. fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> { match self.parse_unsuffixed_lit() { Ok(lit) => { @@ -324,7 +324,7 @@ impl<'a> Parser<'a> { Err(self.diagnostic().struct_span_err(self.token.span, &msg)) } - /// matches meta_seq = ( COMMASEP(meta_item_inner) ) + /// Matches `meta_seq = ( COMMASEP(meta_item_inner) )`. fn parse_meta_seq(&mut self) -> PResult<'a, Vec> { self.parse_seq_to_end(&token::CloseDelim(token::Paren), SeqSep::trailing_allowed(token::Comma), diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index d050d4f4ce705..2890a8e721e65 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -240,7 +240,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, bool /* recovered */> { fn tokens_to_string(tokens: &[TokenType]) -> String { let mut i = tokens.iter(); - // This might be a sign we need a connect method on Iterator. + // This might be a sign we need a connect method on `Iterator`. let b = i.next() .map_or(String::new(), |t| t.to_string()); i.enumerate().fold(b, |mut b, (i, a)| { @@ -301,7 +301,7 @@ impl<'a> Parser<'a> { ); } let sp = if self.token == token::Eof { - // This is EOF, don't want to point at the following char, but rather the last token + // This is EOF; don't want to point at the following char, but rather the last token. self.prev_span } else { label_sp @@ -317,9 +317,9 @@ impl<'a> Parser<'a> { } let is_semi_suggestable = expected.iter().any(|t| match t { - TokenType::Token(token::Semi) => true, // we expect a `;` here + TokenType::Token(token::Semi) => true, // We expect a `;` here. _ => false, - }) && ( // a `;` would be expected before the current keyword + }) && ( // A `;` would be expected before the current keyword. self.token.is_keyword(kw::Break) || self.token.is_keyword(kw::Continue) || self.token.is_keyword(kw::For) || @@ -541,16 +541,16 @@ impl<'a> Parser<'a> { } } - /// Produce an error if comparison operators are chained (RFC #558). - /// We only need to check lhs, not rhs, because all comparison ops - /// have same precedence and are left-associative + /// Produces an error if comparison operators are chained (RFC #558). + /// We only need to check the LHS, not the RHS, because all comparison ops + /// have same precedence and are left-associative. crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) -> PResult<'a, ()> { debug_assert!(outer_op.is_comparison(), "check_no_chained_comparison: {:?} is not comparison", outer_op); match lhs.node { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { - // respan to include both operators + // Respan to include both operators. let op_span = op.span.to(self.token.span); let mut err = self.struct_span_err( op_span, @@ -691,9 +691,9 @@ impl<'a> Parser<'a> { Ok(()) } - /// Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`. - /// Attempt to convert the base expression/pattern/type into a type, parse the `::AssocItem` - /// tail, and combine them into a `::AssocItem` expression/pattern/type. + /// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`. + /// Attempts to convert the base expression/pattern/type into a type, parses the `::AssocItem` + /// tail, and combines them into a `::AssocItem` expression/pattern/type. crate fn maybe_recover_from_bad_qpath( &mut self, base: P, @@ -708,8 +708,8 @@ impl<'a> Parser<'a> { Ok(base) } - /// Given an already parsed `Ty` parse the `::AssocItem` tail and - /// combine them into a `::AssocItem` expression/pattern/type. + /// Given an already parsed `Ty`, parses the `::AssocItem` tail and + /// combines them into a `::AssocItem` expression/pattern/type. crate fn maybe_recover_from_bad_qpath_stage_2( &mut self, ty_span: Span, @@ -730,7 +730,7 @@ impl<'a> Parser<'a> { self.diagnostic() .struct_span_err(path.span, "missing angle brackets in associated item path") .span_suggestion( - // this is a best-effort recovery + // This is a best-effort recovery. path.span, "try", format!("<{}>::{}", ty_str, path), @@ -738,7 +738,7 @@ impl<'a> Parser<'a> { ) .emit(); - let path_span = ty_span.shrink_to_hi(); // use an empty path since `position` == 0 + let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`. Ok(P(T::recovered( Some(QSelf { ty, @@ -761,8 +761,8 @@ impl<'a> Parser<'a> { if !items.is_empty() { let previous_item = &items[items.len() - 1]; let previous_item_kind_name = match previous_item.node { - // say "braced struct" because tuple-structs and - // braceless-empty-struct declarations do take a semicolon + // Say "braced struct" because tuple-structs and + // braceless-empty-struct declarations do take a semicolon. ItemKind::Struct(..) => Some("braced struct"), ItemKind::Enum(..) => Some("enum"), ItemKind::Trait(..) => Some("trait"), @@ -783,7 +783,7 @@ impl<'a> Parser<'a> { } } - /// Create a `DiagnosticBuilder` for an unexpected token `t` and try to recover if it is a + /// Creates a `DiagnosticBuilder` for an unexpected token `t` and tries to recover if it is a /// closing delimiter. pub fn unexpected_try_recover( &mut self, @@ -841,7 +841,7 @@ impl<'a> Parser<'a> { extern_sp: Span, ) -> PResult<'a, ()> { if self.token != token::Semi { - // this might be an incorrect fn definition (#62109) + // This might be an incorrect fn definition (#62109). let parser_snapshot = self.clone(); match self.parse_inner_attrs_and_block() { Ok((_, body)) => { @@ -871,7 +871,7 @@ impl<'a> Parser<'a> { Ok(()) } - /// Consume alternative await syntaxes like `await!()`, `await `, + /// Consumes alternative await syntaxes like `await!()`, `await `, /// `await? `, `await()`, and `await { }`. crate fn parse_incorrect_await_syntax( &mut self, @@ -924,7 +924,7 @@ impl<'a> Parser<'a> { sp } - /// If encountering `future.await()`, consume and emit error. + /// If encountering `future.await()`, consumes and emits an error. crate fn recover_from_await_method_call(&mut self) { if self.token == token::OpenDelim(token::Paren) && self.look_ahead(1, |t| t == &token::CloseDelim(token::Paren)) @@ -944,7 +944,7 @@ impl<'a> Parser<'a> { } } - /// Recover a situation like `for ( $pat in $expr )` + /// Recovers a situation like `for ( $pat in $expr )` /// and suggest writing `for $pat in $expr` instead. /// /// This should be called before parsing the `$block`. @@ -1010,7 +1010,7 @@ impl<'a> Parser<'a> { Ok(x) => x, Err(mut err) => { err.emit(); - // recover from parse error + // Recover from parse error. self.consume_block(delim); self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new()) } @@ -1023,7 +1023,7 @@ impl<'a> Parser<'a> { mut err: DiagnosticBuilder<'a>, ) -> PResult<'a, bool> { let mut pos = None; - // we want to use the last closing delim that would apply + // We want to use the last closing delim that would apply. for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() { if tokens.contains(&token::CloseDelim(unmatched.expected_delim)) && Some(self.token.span) > unmatched.unclosed_span @@ -1041,7 +1041,7 @@ impl<'a> Parser<'a> { let unmatched = self.unclosed_delims.remove(pos); let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim)); - // We want to suggest the inclusion of the closing delimiter where it makes + // We want to suggest the inclusion of the closing delimiter where it makes // the most sense, which is immediately after the last token: // // {foo(bar {}} @@ -1067,7 +1067,7 @@ impl<'a> Parser<'a> { } } - /// Recover from `pub` keyword in places where it seems _reasonable_ but isn't valid. + /// Recovers from `pub` keyword in places where it seems _reasonable_ but isn't valid. crate fn eat_bad_pub(&mut self) { if self.token.is_keyword(kw::Pub) { match self.parse_visibility(false) { @@ -1082,21 +1082,21 @@ impl<'a> Parser<'a> { } } - // Eat tokens until we can be relatively sure we reached the end of the - // statement. This is something of a best-effort heuristic. - // - // We terminate when we find an unmatched `}` (without consuming it). - crate fn recover_stmt(&mut self) { + /// Eats tokens until we can be relatively sure we reached the end of the + /// statement. This is something of a best-effort heuristic. + /// + /// We terminate when we find an unmatched `}` (without consuming it). + pub fn recover_stmt(&mut self) { self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore) } - // If `break_on_semi` is `Break`, then we will stop consuming tokens after - // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is - // approximate - it can mean we break too early due to macros, but that - // should only lead to sub-optimal recovery, not inaccurate parsing). - // - // If `break_on_block` is `Break`, then we will stop consuming tokens - // after finding (and consuming) a brace-delimited block. + /// If `break_on_semi` is `Break`, then we will stop consuming tokens after + /// finding (and consuming) a `;` outside of `{}` or `[]` (note that this is + /// approximate -- it can mean we break too early due to macros, but that + /// should only lead to sub-optimal recovery, not inaccurate parsing). + /// + /// If `break_on_block` is `Break`, then we will stop consuming tokens + /// after finding (and consuming) a brace-delimited block. crate fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) { let mut brace_depth = 0; let mut bracket_depth = 0; diff --git a/src/libsyntax/parse/lexer/tests.rs b/src/libsyntax/parse/lexer/tests.rs index 652ae95c85349..d965bf28ee7df 100644 --- a/src/libsyntax/parse/lexer/tests.rs +++ b/src/libsyntax/parse/lexer/tests.rs @@ -4,9 +4,10 @@ use crate::symbol::Symbol; use crate::source_map::{SourceMap, FilePathMapping}; use crate::parse::token; use crate::with_default_globals; + +use errors::{Handler, emitter::EmitterWriter}; use std::io; use std::path::PathBuf; -use errors::{Handler, emitter::EmitterWriter}; use syntax_pos::{BytePos, Span}; fn mk_sess(sm: Lrc) -> ParseSess { @@ -21,7 +22,7 @@ fn mk_sess(sm: Lrc) -> ParseSess { ParseSess::with_span_handler(Handler::with_emitter(true, None, Box::new(emitter)), sm) } -// open a string reader for the given string +// Creates a string reader for the given string. fn setup<'a>(sm: &SourceMap, sess: &'a ParseSess, teststr: String) @@ -38,7 +39,7 @@ fn t1() { let mut string_reader = setup( &sm, &sh, - "/* my source file */ fn main() { println!(\"zebra\"); }\n".to_string(), + "/* my source file */ fn main() { println!(\"zebra\"); }\n".to_owned(), ); assert_eq!(string_reader.next_token(), token::Comment); assert_eq!(string_reader.next_token(), token::Whitespace); @@ -50,7 +51,7 @@ fn t1() { assert_eq!(tok1.kind, tok2.kind); assert_eq!(tok1.span, tok2.span); assert_eq!(string_reader.next_token(), token::Whitespace); - // read another token: + // Read another token. let tok3 = string_reader.next_token(); assert_eq!(string_reader.pos.clone(), BytePos(28)); let tok4 = Token::new( @@ -65,15 +66,15 @@ fn t1() { }) } -// check that the given reader produces the desired stream -// of tokens (stop checking after exhausting the expected vec) +// Checks that the given reader produces the desired stream +// of tokens (stop checking after exhausting `expected`). fn check_tokenization(mut string_reader: StringReader<'_>, expected: Vec) { for expected_tok in &expected { assert_eq!(&string_reader.next_token(), expected_tok); } } -// make the identifier by looking up the string in the interner +// Makes the identifier by looking up the string in the interner. fn mk_ident(id: &str) -> TokenKind { token::Ident(Symbol::intern(id), false) } @@ -201,7 +202,7 @@ fn literal_suffixes() { setup(&sm, &sh, format!("{}suffix", $input)).next_token(), mk_lit(token::$tok_type, $tok_contents, Some("suffix")), ); - // with a whitespace separator: + // with a whitespace separator assert_eq!( setup(&sm, &sh, format!("{} suffix", $input)).next_token(), mk_lit(token::$tok_type, $tok_contents, None), diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index b1af4806e2d78..aa57c3954e352 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -13,12 +13,12 @@ use crate::print::pprust; use crate::symbol::Symbol; use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; +use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_data_structures::sync::{Lrc, Lock, Once}; use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; use syntax_pos::edition::Edition; use syntax_pos::hygiene::ExpnId; -use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use std::borrow::Cow; use std::path::{Path, PathBuf}; use std::str; @@ -81,25 +81,27 @@ pub struct ParseSess { impl ParseSess { pub fn new(file_path_mapping: FilePathMapping) -> Self { let cm = Lrc::new(SourceMap::new(file_path_mapping)); - let handler = Handler::with_tty_emitter(ColorConfig::Auto, - true, - None, - Some(cm.clone())); + let handler = Handler::with_tty_emitter( + ColorConfig::Auto, + true, + None, + Some(cm.clone()), + ); ParseSess::with_span_handler(handler, cm) } - pub fn with_span_handler(handler: Handler, source_map: Lrc) -> ParseSess { - ParseSess { + pub fn with_span_handler(handler: Handler, source_map: Lrc) -> Self { + Self { span_diagnostic: handler, unstable_features: UnstableFeatures::from_environment(), config: FxHashSet::default(), + edition: ExpnId::root().expn_data().edition, missing_fragment_specifiers: Lock::new(FxHashSet::default()), raw_identifier_spans: Lock::new(Vec::new()), registered_diagnostics: Lock::new(ErrorMap::new()), included_mod_stack: Lock::new(vec![]), source_map, buffered_lints: Lock::new(vec![]), - edition: ExpnId::root().expn_data().edition, ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), injected_crate_name: Once::new(), gated_spans: GatedSpans::default(), @@ -155,17 +157,17 @@ pub struct Directory<'a> { #[derive(Copy, Clone)] pub enum DirectoryOwnership { Owned { - // None if `mod.rs`, `Some("foo")` if we're in `foo.rs` + // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`. relative: Option, }, UnownedViaBlock, UnownedViaMod(bool /* legacy warnings? */), } -// a bunch of utility functions of the form parse__from_ +// A bunch of utility functions of the form `parse__from_` // where includes crate, expr, item, stmt, tts, and one that // uses a HOF to parse anything, and includes file and -// source_str. +// `source_str`. pub fn parse_crate_from_file<'a>(input: &Path, sess: &'a ParseSess) -> PResult<'a, ast::Crate> { let mut parser = new_parser_from_file(sess, input); @@ -219,14 +221,13 @@ pub fn maybe_new_parser_from_source_str(sess: &ParseSess, name: FileName, source Ok(parser) } -/// Creates a new parser, handling errors as appropriate -/// if the file doesn't exist +/// Creates a new parser, handling errors as appropriate if the file doesn't exist. pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a> { source_file_to_parser(sess, file_to_source_file(sess, path, None)) } -/// Creates a new parser, returning buffered diagnostics if the file doesn't -/// exist or from lexing the initial token stream. +/// Creates a new parser, returning buffered diagnostics if the file doesn't exist, +/// or from lexing the initial token stream. pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Result, Vec> { let file = try_file_to_source_file(sess, path, None).map_err(|db| vec![db])?; @@ -234,8 +235,8 @@ pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) } /// Given a session, a crate config, a path, and a span, add -/// the file at the given path to the source_map, and return a parser. -/// On an error, use the given span as the source of the problem. +/// the file at the given path to the `source_map`, and returns a parser. +/// On an error, uses the given span as the source of the problem. pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess, path: &Path, directory_ownership: DirectoryOwnership, @@ -247,13 +248,13 @@ pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess, p } -/// Given a source_file and config, return a parser +/// Given a `source_file` and config, returns a parser. fn source_file_to_parser(sess: &ParseSess, source_file: Lrc) -> Parser<'_> { panictry_buffer!(&sess.span_diagnostic, maybe_source_file_to_parser(sess, source_file)) } -/// Given a source_file and config, return a parser. Returns any buffered errors from lexing the +/// Given a `source_file` and config, return a parser. Returns any buffered errors from lexing the /// initial token stream. fn maybe_source_file_to_parser( sess: &ParseSess, @@ -270,14 +271,14 @@ fn maybe_source_file_to_parser( Ok(parser) } -// must preserve old name for now, because quote! from the *existing* -// compiler expands into it +// Must preserve old name for now, because `quote!` from the *existing* +// compiler expands into it. pub fn new_parser_from_tts(sess: &ParseSess, tts: Vec) -> Parser<'_> { stream_to_parser(sess, tts.into_iter().collect(), crate::MACRO_ARGUMENTS) } -// base abstractions +// Base abstractions /// Given a session and a path and an optional span (for error reporting), /// add the path to the session's source_map and return the new source_file or @@ -296,7 +297,7 @@ fn try_file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option) } /// Given a session and a path and an optional span (for error reporting), -/// add the path to the session's `source_map` and return the new `source_file`. +/// adds the path to the session's `source_map` and returns the new `source_file`. fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option) -> Lrc { match try_file_to_source_file(sess, path, spanopt) { @@ -308,7 +309,7 @@ fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option) } } -/// Given a source_file, produces a sequence of token trees. +/// Given a `source_file`, produces a sequence of token trees. pub fn source_file_to_stream( sess: &ParseSess, source_file: Lrc, @@ -352,7 +353,7 @@ pub fn maybe_file_to_stream( } } -/// Given stream and the `ParseSess`, produces a parser. +/// Given a stream and the `ParseSess`, produces a parser. pub fn stream_to_parser<'a>( sess: &'a ParseSess, stream: TokenStream, @@ -361,7 +362,7 @@ pub fn stream_to_parser<'a>( Parser::new(sess, stream, None, true, false, subparser_name) } -/// Given stream, the `ParseSess` and the base directory, produces a parser. +/// Given a stream, the `ParseSess` and the base directory, produces a parser. /// /// Use this function when you are creating a parser from the token stream /// and also care about the current working directory of the parser (e.g., diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ab5462baaf721..fcaf5065dac78 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -10,22 +10,22 @@ pub use path::PathStyle; mod stmt; mod generics; -use crate::ast::{self, AttrStyle, Attribute, Param, BindingMode, StrStyle, SelfKind}; -use crate::ast::{FnDecl, Ident, IsAsync, MacDelimiter, Mutability, TyKind}; -use crate::ast::{Visibility, VisibilityKind, Unsafety, CrateSugar}; -use crate::source_map::{self, respan}; -use crate::parse::{SeqSep, literal, token}; +use crate::ast::{ + self, DUMMY_NODE_ID, AttrStyle, Attribute, BindingMode, CrateSugar, FnDecl, Ident, + IsAsync, MacDelimiter, Mutability, Param, StrStyle, SelfKind, TyKind, Visibility, + VisibilityKind, Unsafety, +}; +use crate::parse::{ParseSess, PResult, Directory, DirectoryOwnership, SeqSep, literal, token}; +use crate::parse::diagnostics::{Error, dummy_arg}; use crate::parse::lexer::UnmatchedBrace; use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use crate::parse::token::{Token, TokenKind, DelimToken}; -use crate::parse::{ParseSess, Directory, DirectoryOwnership}; use crate::print::pprust; use crate::ptr::P; -use crate::parse::PResult; -use crate::ThinVec; -use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; +use crate::source_map::{self, respan}; use crate::symbol::{kw, sym, Symbol}; -use crate::parse::diagnostics::{Error, dummy_arg}; +use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; +use crate::ThinVec; use errors::{Applicability, DiagnosticId, FatalError}; use rustc_target::spec::abi::{self, Abi}; @@ -56,7 +56,7 @@ crate enum BlockMode { Ignore, } -/// As maybe_whole_expr, but for things other than expressions +/// Like `maybe_whole_expr`, but for things other than expressions. #[macro_export] macro_rules! maybe_whole { ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { @@ -116,11 +116,11 @@ pub struct Parser<'a> { /// with non-interpolated identifier and lifetime tokens they refer to. /// Perhaps the normalized / non-normalized setup can be simplified somehow. pub token: Token, - /// Span of the current non-normalized token. + /// The span of the current non-normalized token. meta_var_span: Option, - /// Span of the previous non-normalized token. + /// The span of the previous non-normalized token. pub prev_span: Span, - /// Kind of the previous normalized token (in simplified form). + /// The kind of the previous normalized token (in simplified form). prev_token_kind: PrevTokenKind, restrictions: Restrictions, /// Used to determine the path to externally loaded source files. @@ -143,7 +143,7 @@ pub struct Parser<'a> { /// See the comments in the `parse_path_segment` function for more details. crate unmatched_angle_bracket_count: u32, crate max_angle_bracket_count: u32, - /// List of all unclosed delimiters found by the lexer. If an entry is used for error recovery + /// A list of all unclosed delimiters found by the lexer. If an entry is used for error recovery /// it gets removed from here. Every entry left at the end gets emitted as an independent /// error. crate unclosed_delims: Vec, @@ -799,14 +799,14 @@ impl<'a> Parser<'a> { break; } Err(mut e) => { - // Attempt to keep parsing if it was a similar separator + // Attempt to keep parsing if it was a similar separator. if let Some(ref tokens) = t.similar_tokens() { if tokens.contains(&self.token.kind) { self.bump(); } } e.emit(); - // Attempt to keep parsing if it was an omitted separator + // Attempt to keep parsing if it was an omitted separator. match f(self) { Ok(t) => { v.push(t); @@ -871,7 +871,7 @@ impl<'a> Parser<'a> { self.parse_delim_comma_seq(token::Paren, f) } - /// Advance the parser by one token + /// Advance the parser by one token. pub fn bump(&mut self) { if self.prev_token_kind == PrevTokenKind::Eof { // Bumping after EOF is a bad sign, usually an infinite loop. @@ -894,17 +894,17 @@ impl<'a> Parser<'a> { self.token = self.next_tok(); self.expected_tokens.clear(); - // check after each token + // Check after each token. self.process_potential_macro_variable(); } - /// Advance the parser using provided token as a next one. Use this when + /// Advances the parser using provided token as a next one. Use this when /// consuming a part of a token. For example a single `<` from `<<`. fn bump_with(&mut self, next: TokenKind, span: Span) { self.prev_span = self.token.span.with_hi(span.lo()); // It would be incorrect to record the kind of the current token, but // fortunately for tokens currently using `bump_with`, the - // prev_token_kind will be of no use anyway. + // `prev_token_kind` will be of no use anyway. self.prev_token_kind = PrevTokenKind::Other; self.token = Token::new(next, span); self.expected_tokens.clear(); @@ -937,8 +937,8 @@ impl<'a> Parser<'a> { fn parse_asyncness(&mut self) -> IsAsync { if self.eat_keyword(kw::Async) { IsAsync::Async { - closure_id: ast::DUMMY_NODE_ID, - return_impl_trait_id: ast::DUMMY_NODE_ID, + closure_id: DUMMY_NODE_ID, + return_impl_trait_id: DUMMY_NODE_ID, } } else { IsAsync::NotAsync @@ -1040,7 +1040,7 @@ impl<'a> Parser<'a> { let span = lo.to(self.token.span); - Ok(Param { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, span, ty }) + Ok(Param { attrs: attrs.into(), id: DUMMY_NODE_ID, pat, span, ty }) } /// Parses mutability (`mut` or nothing). @@ -1497,7 +1497,7 @@ impl<'a> Parser<'a> { format!("in {}", path), Applicability::MachineApplicable, ) - .emit(); // emit diagnostic, but continue with public visibility + .emit(); // Emit diagnostic, but continue with public visibility. } } diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index e8c8e199fd06b..f70c607198fa9 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1,26 +1,26 @@ -use super::{Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle}; -use super::{BlockMode, SemiColonMode}; -use super::{SeqSep, TokenExpectType}; +use super::{ + Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle, BlockMode, SemiColonMode, + SeqSep, TokenExpectType, +}; use super::pat::{GateOr, PARAM_EXPECTED}; +use crate::ast::{ + self, DUMMY_NODE_ID, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode, + Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm, Ty, TyKind, + FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst, Field, +}; use crate::maybe_recover_from_interpolated_ty_qpath; -use crate::ptr::P; -use crate::ast::{self, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode}; -use crate::ast::{Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm}; -use crate::ast::{Ty, TyKind, FunctionRetTy, Param, FnDecl}; -use crate::ast::{BinOpKind, BinOp, UnOp}; -use crate::ast::{Mac, AnonConst, Field}; - use crate::parse::classify; use crate::parse::token::{self, Token}; -use crate::parse::diagnostics::{Error}; +use crate::parse::diagnostics::Error; use crate::print::pprust; +use crate::ptr::P; use crate::source_map::{self, Span}; use crate::symbol::{kw, sym}; use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par}; -use std::mem; use errors::Applicability; +use std::mem; use rustc_data_structures::thin_vec::ThinVec; /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression @@ -51,7 +51,7 @@ macro_rules! maybe_whole_expr { $p.token.span, ExprKind::Block(block, None), ThinVec::new() )); } - // N.B: `NtIdent(ident)` is normalized to `Ident` in `fn bump`. + // N.B., `NtIdent(ident)` is normalized to `Ident` in `fn bump`. _ => {}, }; } @@ -340,7 +340,7 @@ impl<'a> Parser<'a> { fn is_at_start_of_range_notation_rhs(&self) -> bool { if self.token.can_begin_expr() { - // parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`. + // 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::NO_STRUCT_LITERAL); } @@ -350,12 +350,12 @@ impl<'a> Parser<'a> { } } - /// Parse prefix-forms of range notation: `..expr`, `..`, `..=expr` + /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`. fn parse_prefix_range_expr( &mut self, already_parsed_attrs: Option> ) -> PResult<'a, P> { - // Check for deprecated `...` syntax + // Check for deprecated `...` syntax. if self.token == token::DotDotDot { self.err_dotdotdot_syntax(self.token.span); } @@ -389,7 +389,7 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(lo.to(hi), r, attrs)) } - /// Parse a prefix-unary-operator expr + /// Parses a prefix-unary-operator expr. fn parse_prefix_expr( &mut self, already_parsed_attrs: Option> @@ -549,7 +549,7 @@ impl<'a> Parser<'a> { let expr = mk_expr(self, P(Ty { span: path.span, node: TyKind::Path(None, path), - id: ast::DUMMY_NODE_ID + id: DUMMY_NODE_ID, })); let expr_str = self.span_to_snippet(expr.span) @@ -565,7 +565,7 @@ impl<'a> Parser<'a> { expr.span, &format!("try {} the cast value", op_verb), format!("({})", expr_str), - Applicability::MachineApplicable + Applicability::MachineApplicable, ) .emit(); @@ -741,7 +741,6 @@ impl<'a> Parser<'a> { }) } - /// At the bottom (top?) of the precedence hierarchy, /// Parses things like parenthesized exprs, macros, `return`, etc. /// @@ -755,7 +754,7 @@ impl<'a> Parser<'a> { // added to the return value after the fact. // // Therefore, prevent sub-parser from parsing - // attributes by giving them a empty "already parsed" list. + // attributes by giving them a empty "already-parsed" list. let mut attrs = ThinVec::new(); let lo = self.token.span; @@ -778,7 +777,7 @@ impl<'a> Parser<'a> { } } - // Note: when adding new syntax here, don't forget to adjust TokenKind::can_begin_expr(). + // Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`. match self.token.kind { // This match arm is a special-case of the `_` match arm below and // could be removed without changing functionality, but it's faster @@ -791,8 +790,8 @@ impl<'a> Parser<'a> { attrs.extend(self.parse_inner_attributes()?); - // (e) is parenthesized e - // (e,) is a tuple with only one field, e + // `(e)` is parenthesized `e`. + // `(e,)` is a tuple with only one field, `e`. let mut es = vec![]; let mut trailing_comma = false; let mut recovered = false; @@ -800,7 +799,7 @@ impl<'a> Parser<'a> { es.push(match self.parse_expr() { Ok(es) => es, Err(mut err) => { - // recover from parse error in tuple list + // Recover from parse error in tuple list. match self.token.kind { token::Ident(name, false) if name == kw::Underscore && self.look_ahead(1, |t| { @@ -844,7 +843,7 @@ impl<'a> Parser<'a> { return self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs); } token::BinOp(token::Or) | token::OrOr => { - return self.parse_lambda_expr(attrs); + return self.parse_closure(attrs); } token::OpenDelim(token::Bracket) => { self.bump(); @@ -852,21 +851,21 @@ impl<'a> Parser<'a> { attrs.extend(self.parse_inner_attributes()?); if self.eat(&token::CloseDelim(token::Bracket)) { - // Empty vector. + // Empty vector ex = ExprKind::Array(Vec::new()); } else { - // Nonempty vector. + // Non-empty vector let first_expr = self.parse_expr()?; if self.eat(&token::Semi) { - // Repeating array syntax: [ 0; 512 ] + // Repeating array syntax: `[ 0; 512 ]` let count = AnonConst { - id: ast::DUMMY_NODE_ID, + id: DUMMY_NODE_ID, value: self.parse_expr()?, }; self.expect(&token::CloseDelim(token::Bracket))?; ex = ExprKind::Repeat(first_expr, count); } else if self.eat(&token::Comma) { - // Vector with two or more elements. + // Vector with two or more elements let remaining_exprs = self.parse_seq_to_end( &token::CloseDelim(token::Bracket), SeqSep::trailing_allowed(token::Comma), @@ -876,7 +875,7 @@ impl<'a> Parser<'a> { exprs.extend(remaining_exprs); ex = ExprKind::Array(exprs); } else { - // Vector with one element. + // Vector with one element self.expect(&token::CloseDelim(token::Bracket))?; ex = ExprKind::Array(vec![first_expr]); } @@ -892,7 +891,7 @@ impl<'a> Parser<'a> { if self.token.is_path_start() { let path = self.parse_path(PathStyle::Expr)?; - // `!`, as an operator, is prefix, so we know this isn't that + // `!`, as an operator, is prefix, so we know this isn't that. if self.eat(&token::Not) { // MACRO INVOCATION expression let (delim, tts) = self.expect_delimited_token_tree()?; @@ -920,7 +919,7 @@ impl<'a> Parser<'a> { return self.maybe_recover_from_bad_qpath(expr, true); } if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) { - return self.parse_lambda_expr(attrs); + return self.parse_closure(attrs); } if self.eat_keyword(kw::If) { return self.parse_if_expr(attrs); @@ -991,13 +990,13 @@ impl<'a> Parser<'a> { return self.parse_try_block(lo, attrs); } - // Span::rust_2018() is somewhat expensive; don't get it repeatedly. + // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly. let is_span_rust_2018 = self.token.span.rust_2018(); if is_span_rust_2018 && self.check_keyword(kw::Async) { - return if self.is_async_block() { // check for `async {` and `async move {` + return if self.is_async_block() { // Check for `async {` and `async move {`. self.parse_async_block(attrs) } else { - self.parse_lambda_expr(attrs) + self.parse_closure(attrs) }; } if self.eat_keyword(kw::Return) { @@ -1043,13 +1042,12 @@ impl<'a> Parser<'a> { // recovery in order to keep the error count down. Fixing the // delimiters will possibly also fix the bare semicolon found in // expression context. For example, silence the following error: - // ``` - // error: expected expression, found `;` - // --> file.rs:2:13 - // | - // 2 | foo(bar(; - // | ^ expected expression - // ``` + // + // error: expected expression, found `;` + // --> file.rs:2:13 + // | + // 2 | foo(bar(; + // | ^ expected expression self.bump(); return Ok(self.mk_expr(self.token.span, ExprKind::Err, ThinVec::new())); } @@ -1096,11 +1094,11 @@ impl<'a> Parser<'a> { attrs.extend(self.parse_inner_attributes()?); let blk = self.parse_block_tail(lo, blk_mode)?; - return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs)); + Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs)) } - /// Parses `move |args| expr`. - fn parse_lambda_expr(&mut self, attrs: ThinVec) -> PResult<'a, P> { + /// Parses a closure (e.g., `move |args| expr`). + fn parse_closure(&mut self, attrs: ThinVec) -> PResult<'a, P> { let lo = self.token.span; let movability = if self.eat_keyword(kw::Static) { @@ -1115,7 +1113,7 @@ impl<'a> Parser<'a> { IsAsync::NotAsync }; if asyncness.is_async() { - // Feature gate `async ||` closures. + // Feature-gate `async ||` closures. self.sess.gated_spans.async_closure.borrow_mut().push(self.prev_span); } @@ -1128,8 +1126,7 @@ impl<'a> Parser<'a> { self.parse_expr_res(restrictions, None)? }, _ => { - // If an explicit return type is given, require a - // block to appear (RFC 968). + // If an explicit return type is given, require a block to appear (RFC 968). let body_lo = self.token.span; self.parse_block_expr(None, body_lo, BlockCheckMode::Default, ThinVec::new())? } @@ -1141,7 +1138,7 @@ impl<'a> Parser<'a> { attrs)) } - /// Parse an optional `move` prefix to a closure lke construct. + /// Parses an optional `move` prefix to a closure lke construct. fn parse_capture_clause(&mut self) -> CaptureBy { if self.eat_keyword(kw::Move) { CaptureBy::Value @@ -1176,7 +1173,7 @@ impl<'a> Parser<'a> { })) } - /// Parses a parameter in a lambda header (e.g., `|arg, arg|`). + /// Parses a parameter in a closure header (e.g., `|arg, arg|`). fn parse_fn_block_param(&mut self) -> PResult<'a, Param> { let lo = self.token.span; let attrs = self.parse_param_attributes()?; @@ -1185,7 +1182,7 @@ impl<'a> Parser<'a> { self.parse_ty()? } else { P(Ty { - id: ast::DUMMY_NODE_ID, + id: DUMMY_NODE_ID, node: TyKind::Infer, span: self.prev_span, }) @@ -1196,7 +1193,7 @@ impl<'a> Parser<'a> { ty: t, pat, span, - id: ast::DUMMY_NODE_ID + id: DUMMY_NODE_ID }) } @@ -1233,7 +1230,7 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(lo.to(hi), ExprKind::If(cond, thn, els), attrs)) } - /// Parse the condition of a `if`- or `while`-expression + /// Parses the condition of a `if` or `while` expression. fn parse_cond_expr(&mut self) -> PResult<'a, P> { let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; @@ -1261,7 +1258,7 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(span, ExprKind::Let(pat, expr), attrs)) } - /// `else` token already eaten + /// Parses an `else { ... }` expression (`else` token already eaten). fn parse_else_expr(&mut self) -> PResult<'a, P> { if self.eat_keyword(kw::If) { return self.parse_if_expr(ThinVec::new()); @@ -1271,7 +1268,7 @@ impl<'a> Parser<'a> { } } - /// Parse a 'for' .. 'in' expression ('for' token already eaten) + /// Parses a `for ... in` expression (`for` token already eaten). fn parse_for_expr( &mut self, opt_label: Option
")?; + write!(buffer, "
"); if it.is_crate() { - write!(fmt, "

See all {}'s items

", - it.name.as_ref().expect("crates always have a name"))?; + write!(buffer, "

See all {}'s items

", + it.name.as_ref().expect("crates always have a name")); } match it.inner { - clean::StructItem(ref s) => sidebar_struct(fmt, it, s)?, - clean::TraitItem(ref t) => sidebar_trait(fmt, it, t)?, - clean::PrimitiveItem(ref p) => sidebar_primitive(fmt, it, p)?, - clean::UnionItem(ref u) => sidebar_union(fmt, it, u)?, - clean::EnumItem(ref e) => sidebar_enum(fmt, it, e)?, - clean::TypedefItem(ref t, _) => sidebar_typedef(fmt, it, t)?, - clean::ModuleItem(ref m) => sidebar_module(fmt, it, &m.items)?, - clean::ForeignTypeItem => sidebar_foreign_type(fmt, it)?, + clean::StructItem(ref s) => sidebar_struct(buffer, it, s), + clean::TraitItem(ref t) => sidebar_trait(buffer, it, t), + clean::PrimitiveItem(ref p) => sidebar_primitive(buffer, it, p), + clean::UnionItem(ref u) => sidebar_union(buffer, it, u), + clean::EnumItem(ref e) => sidebar_enum(buffer, it, e), + clean::TypedefItem(ref t, _) => sidebar_typedef(buffer, it, t), + clean::ModuleItem(ref m) => sidebar_module(buffer, it, &m.items), + clean::ForeignTypeItem => sidebar_foreign_type(buffer, it), _ => (), } @@ -4328,20 +4328,20 @@ impl<'a> fmt::Display for Sidebar<'a> { // as much HTML as possible in order to allow non-JS-enabled browsers // to navigate the documentation (though slightly inefficiently). - write!(fmt, "

")?; + write!(buffer, "

"); for (i, name) in cx.current.iter().take(parentlen).enumerate() { if i > 0 { - write!(fmt, "::")?; + write!(buffer, "::"); } - write!(fmt, "{}", + write!(buffer, "{}", &cx.root_path()[..(cx.current.len() - i - 1) * 3], - *name)?; + *name); } - write!(fmt, "

")?; + write!(buffer, "

"); // Sidebar refers to the enclosing module, not this module. let relpath = if it.is_mod() { "../" } else { "" }; - write!(fmt, + write!(buffer, "", name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""), ty = it.type_().css_class(), - path = relpath)?; + path = relpath); if parentlen == 0 { // There is no sidebar-items.js beyond the crate root path // FIXME maybe dynamic crate loading can be merged here } else { - write!(fmt, "", - path = relpath)?; + write!(buffer, "", + path = relpath); } // Closes sidebar-elems div. - write!(fmt, "
")?; - - Ok(()) + write!(buffer, "
"); } } @@ -4534,8 +4532,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { out } -fn sidebar_struct(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - s: &clean::Struct) -> fmt::Result { +fn sidebar_struct(buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) { let mut sidebar = String::new(); let fields = get_struct_fields_name(&s.fields); @@ -4549,9 +4546,8 @@ fn sidebar_struct(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, sidebar.push_str(&sidebar_assoc_items(it)); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } fn get_id_for_impl_on_foreign_type(for_: &clean::Type, trait_: &clean::Type) -> String { @@ -4575,8 +4571,7 @@ fn is_negative_impl(i: &clean::Impl) -> bool { i.polarity == Some(clean::ImplPolarity::Negative) } -fn sidebar_trait(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - t: &clean::Trait) -> fmt::Result { +fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) { let mut sidebar = String::new(); let types = t.items @@ -4684,27 +4679,23 @@ fn sidebar_trait(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, sidebar.push_str(&sidebar_assoc_items(it)); - write!(fmt, "
{}
", sidebar) + write!(buf, "
{}
", sidebar) } -fn sidebar_primitive(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - _p: &clean::PrimitiveType) -> fmt::Result { +fn sidebar_primitive(buf: &mut Buffer, it: &clean::Item, _p: &clean::PrimitiveType) { let sidebar = sidebar_assoc_items(it); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } -fn sidebar_typedef(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - _t: &clean::Typedef) -> fmt::Result { +fn sidebar_typedef(buf: &mut Buffer, it: &clean::Item, _t: &clean::Typedef) { let sidebar = sidebar_assoc_items(it); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } fn get_struct_fields_name(fields: &[clean::Item]) -> String { @@ -4722,8 +4713,7 @@ fn get_struct_fields_name(fields: &[clean::Item]) -> String { .collect() } -fn sidebar_union(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - u: &clean::Union) -> fmt::Result { +fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) { let mut sidebar = String::new(); let fields = get_struct_fields_name(&u.fields); @@ -4735,13 +4725,11 @@ fn sidebar_union(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, sidebar.push_str(&sidebar_assoc_items(it)); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } -fn sidebar_enum(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - e: &clean::Enum) -> fmt::Result { +fn sidebar_enum(buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) { let mut sidebar = String::new(); let variants = e.variants.iter() @@ -4759,9 +4747,8 @@ fn sidebar_enum(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, sidebar.push_str(&sidebar_assoc_items(it)); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) { @@ -4795,8 +4782,7 @@ fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) { } } -fn sidebar_module(fmt: &mut fmt::Formatter<'_>, _it: &clean::Item, - items: &[clean::Item]) -> fmt::Result { +fn sidebar_module(buf: &mut Buffer, _it: &clean::Item, items: &[clean::Item]) { let mut sidebar = String::new(); if items.iter().any(|it| it.type_() == ItemType::ExternCrate || @@ -4823,17 +4809,15 @@ fn sidebar_module(fmt: &mut fmt::Formatter<'_>, _it: &clean::Item, } if !sidebar.is_empty() { - write!(fmt, "
    {}
", sidebar)?; + write!(buf, "
    {}
", sidebar); } - Ok(()) } -fn sidebar_foreign_type(fmt: &mut fmt::Formatter<'_>, it: &clean::Item) -> fmt::Result { +fn sidebar_foreign_type(buf: &mut Buffer, it: &clean::Item) { let sidebar = sidebar_assoc_items(it); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } fn item_macro(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, From f4a15ae3b248bf91f10f6e5d031ca84dc1942e19 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 11:22:51 -0400 Subject: [PATCH 576/618] Implement Print for FnOnce(&mut Buffer) This means that callers can pass in a closure like `|buf| some_function(..., &mut buf)` and pass in arbitrary arguments to that function without complicating the trait definition. We also keep the impl for str and String, since it's useful to be able to just pass in "" or format!("{}"...) results in some cases. This changes Print's definition to take self, instead of &self, because otherwise FnOnce cannot be called directly. We could instead take FnMut or even Fn, but that seems like it'd merely complicate matters -- most of the time, the FnOnce does not constrain us at all anyway. If it does, a custom Print impl for &'_ SomeStruct is not all that painful. --- src/librustdoc/html/format.rs | 20 +++++++++++--------- src/librustdoc/html/layout.rs | 2 +- src/librustdoc/html/render.rs | 10 +++++----- src/librustdoc/html/sources.rs | 2 +- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 99ddbcd7170d7..5d86f0566111f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -19,23 +19,25 @@ use crate::html::item_type::ItemType; use crate::html::render::{self, cache, CURRENT_DEPTH}; pub trait Print { - fn print(&self, buffer: &mut Buffer); + fn print(self, buffer: &mut Buffer); } -impl Print for &'_ T { - fn print(&self, buffer: &mut Buffer) { - (&**self).print(buffer) +impl Print for F + where F: FnOnce(&mut Buffer), +{ + fn print(self, buffer: &mut Buffer) { + (self)(buffer) } } impl Print for String { - fn print(&self, buffer: &mut Buffer) { - buffer.write_str(self); + fn print(self, buffer: &mut Buffer) { + buffer.write_str(&self); } } -impl Print for str { - fn print(&self, buffer: &mut Buffer) { +impl Print for &'_ str { + fn print(self, buffer: &mut Buffer) { buffer.write_str(self); } } @@ -92,7 +94,7 @@ impl Buffer { self.buffer.write_fmt(v).unwrap(); } - crate fn to_display(mut self, t: &T) -> String { + crate fn to_display(mut self, t: T) -> String { t.print(&mut self); self.into_inner() } diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 38dcfbfcec49c..1202f411f912c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -34,7 +34,7 @@ pub struct Page<'a> { pub fn render( layout: &Layout, page: &Page<'_>, - sidebar: &S, + sidebar: S, t: &T, themes: &[PathBuf], ) -> String { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 40e7081c57c72..fc7038f8bda96 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1174,7 +1174,7 @@ themePicker.onblur = handleThemeButtonsBlur; }) .collect::()); let v = layout::render(&cx.shared.layout, - &page, &(""), &content, + &page, "", &content, &cx.shared.themes); cx.shared.fs.write(&dst, v.as_bytes())?; } @@ -1921,7 +1921,7 @@ impl Context { String::new() }; let v = layout::render(&self.shared.layout, - &page, &sidebar, &all, + &page, sidebar, &all, &self.shared.themes); self.shared.fs.write(&final_file, v.as_bytes())?; @@ -1937,7 +1937,7 @@ impl Context { themes.push(PathBuf::from("settings.css")); let v = layout::render( &self.shared.layout, - &page, &sidebar, &settings, + &page, sidebar, &settings, &themes); self.shared.fs.write(&settings_file, v.as_bytes())?; @@ -1994,7 +1994,7 @@ impl Context { if !self.render_redirect_pages { layout::render(&self.shared.layout, &page, - &Sidebar{ cx: self, item: it }, + Sidebar{ cx: self, item: it }, &Item{ cx: self, item: it }, &self.shared.themes) } else { @@ -4267,7 +4267,7 @@ fn item_foreign_type(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item) } impl Print for Sidebar<'_> { - fn print(&self, buffer: &mut Buffer) { + fn print(self, buffer: &mut Buffer) { let cx = self.cx; let it = self.item; let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 018db3f9363cb..94ae14226097f 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -120,7 +120,7 @@ impl<'a> SourceCollector<'a> { static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)], }; let v = layout::render(&self.scx.layout, - &page, &(""), &Source(contents), + &page, "", &Source(contents), &self.scx.themes); self.scx.fs.write(&cur, v.as_bytes())?; self.scx.local_sources.insert(p.clone(), href); From eefaee1af4cc3df09d2588638c2bb250fe6a30e6 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 11:32:47 -0400 Subject: [PATCH 577/618] Delete Sidebar struct in favor of FnOnce impl --- src/librustdoc/html/render.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index fc7038f8bda96..3dec5c2a20e8e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -387,8 +387,6 @@ struct Item<'a> { item: &'a clean::Item, } -struct Sidebar<'a> { cx: &'a Context, item: &'a clean::Item, } - /// Struct representing one entry in the JS search index. These are all emitted /// by hand to a large JS file at the end of cache-creation. #[derive(Debug)] @@ -1994,7 +1992,7 @@ impl Context { if !self.render_redirect_pages { layout::render(&self.shared.layout, &page, - Sidebar{ cx: self, item: it }, + |buf: &mut _| print_sidebar(self, it, buf), &Item{ cx: self, item: it }, &self.shared.themes) } else { @@ -4266,10 +4264,7 @@ fn item_foreign_type(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item) render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } -impl Print for Sidebar<'_> { - fn print(self, buffer: &mut Buffer) { - let cx = self.cx; - let it = self.item; + fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) { let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union() @@ -4360,7 +4355,6 @@ impl Print for Sidebar<'_> { // Closes sidebar-elems div. write!(buffer, "
"); } -} fn get_next_url(used_links: &mut FxHashSet, url: String) -> String { if used_links.insert(url.clone()) { From d5f147086bbc70eb248804d3a16c643979fd1f2b Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 11:34:37 -0400 Subject: [PATCH 578/618] De-indent all fmt::Display impls for later replacement to functions --- src/librustdoc/html/format.rs | 10 +- src/librustdoc/html/render.rs | 466 ++++++++++++++++----------------- src/librustdoc/html/sources.rs | 34 +-- 3 files changed, 255 insertions(+), 255 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 5d86f0566111f..f3c40c8568bb6 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -290,11 +290,11 @@ impl<'a> fmt::Display for WhereClause<'a> { } &clean::WherePredicate::RegionPredicate { ref lifetime, ref bounds } => { clause.push_str(&format!("{}: {}", - lifetime, - bounds.iter() - .map(|b| b.to_string()) - .collect::>() - .join(" + "))); + lifetime, + bounds.iter() + .map(|b| b.to_string()) + .collect::>() + .join(" + "))); } &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => { if f.alternate() { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3dec5c2a20e8e..1d1e54fc9eaba 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1772,33 +1772,33 @@ fn print_entries(f: &mut fmt::Formatter<'_>, e: &FxHashSet, title: &s } impl fmt::Display for AllTypes { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, +fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "

\ - \ - \ - \ - []\ - \ - - - List of all items\ + \ + \ + \ + []\ + \ + + + List of all items\

")?; - print_entries(f, &self.structs, "Structs", "structs")?; - print_entries(f, &self.enums, "Enums", "enums")?; - print_entries(f, &self.unions, "Unions", "unions")?; - print_entries(f, &self.primitives, "Primitives", "primitives")?; - print_entries(f, &self.traits, "Traits", "traits")?; - print_entries(f, &self.macros, "Macros", "macros")?; - print_entries(f, &self.attributes, "Attribute Macros", "attributes")?; - print_entries(f, &self.derives, "Derive Macros", "derives")?; - print_entries(f, &self.functions, "Functions", "functions")?; - print_entries(f, &self.typedefs, "Typedefs", "typedefs")?; - print_entries(f, &self.trait_aliases, "Trait Aliases", "trait-aliases")?; - print_entries(f, &self.opaque_tys, "Opaque Types", "opaque-types")?; - print_entries(f, &self.statics, "Statics", "statics")?; - print_entries(f, &self.constants, "Constants", "constants") - } + print_entries(f, &self.structs, "Structs", "structs")?; + print_entries(f, &self.enums, "Enums", "enums")?; + print_entries(f, &self.unions, "Unions", "unions")?; + print_entries(f, &self.primitives, "Primitives", "primitives")?; + print_entries(f, &self.traits, "Traits", "traits")?; + print_entries(f, &self.macros, "Macros", "macros")?; + print_entries(f, &self.attributes, "Attribute Macros", "attributes")?; + print_entries(f, &self.derives, "Derive Macros", "derives")?; + print_entries(f, &self.functions, "Functions", "functions")?; + print_entries(f, &self.typedefs, "Typedefs", "typedefs")?; + print_entries(f, &self.trait_aliases, "Trait Aliases", "trait-aliases")?; + print_entries(f, &self.opaque_tys, "Opaque Types", "opaque-types")?; + print_entries(f, &self.statics, "Statics", "statics")?; + print_entries(f, &self.constants, "Constants", "constants") +} } #[derive(Debug)] @@ -1829,27 +1829,27 @@ impl<'a> Settings<'a> { } impl<'a> fmt::Display for Settings<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, +fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "

\ - Rustdoc settings\ + Rustdoc settings\

\
{}
\ ", - self.settings.iter() - .map(|(id, text, enabled)| { - format!("
\ - \ -
{}
\ -
", id, if *enabled { " checked" } else { "" }, text) - }) - .collect::(), - self.root_path, - self.suffix) - } + self.settings.iter() + .map(|(id, text, enabled)| { + format!("
\ + \ +
{}
\ +
", id, if *enabled { " checked" } else { "" }, text) + }) + .collect::(), + self.root_path, + self.suffix) +} } impl Context { @@ -2205,108 +2205,108 @@ where F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result { } impl<'a> fmt::Display for Item<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - debug_assert!(!self.item.is_stripped()); - // Write the breadcrumb trail header for the top - write!(fmt, "

")?; - if let Some(version) = self.item.stable_since() { - write!(fmt, "{0}", - version)?; - } - write!(fmt, - "\ - \ - []\ - \ - ")?; - - // Write `src` tag - // - // When this item is part of a `pub use` in a downstream crate, the - // [src] link in the downstream documentation will actually come back to - // this page, and this link will be auto-clicked. The `id` attribute is - // used to find the link to auto-click. - if self.cx.shared.include_sources && !self.item.is_primitive() { - if let Some(l) = self.src_href() { - write!(fmt, "[src]", - l, "goto source code")?; - } - } - - write!(fmt, "")?; // out-of-band - write!(fmt, "")?; - match self.item.inner { - clean::ModuleItem(ref m) => if m.is_crate { - write!(fmt, "Crate ")?; - } else { - write!(fmt, "Module ")?; - }, - clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => write!(fmt, "Function ")?, - clean::TraitItem(..) => write!(fmt, "Trait ")?, - clean::StructItem(..) => write!(fmt, "Struct ")?, - clean::UnionItem(..) => write!(fmt, "Union ")?, - clean::EnumItem(..) => write!(fmt, "Enum ")?, - clean::TypedefItem(..) => write!(fmt, "Type Definition ")?, - clean::MacroItem(..) => write!(fmt, "Macro ")?, - clean::ProcMacroItem(ref mac) => match mac.kind { - MacroKind::Bang => write!(fmt, "Macro ")?, - MacroKind::Attr => write!(fmt, "Attribute Macro ")?, - MacroKind::Derive => write!(fmt, "Derive Macro ")?, - } - clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?, - clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?, - clean::ConstantItem(..) => write!(fmt, "Constant ")?, - clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?, - clean::KeywordItem(..) => write!(fmt, "Keyword ")?, - clean::OpaqueTyItem(..) => write!(fmt, "Opaque Type ")?, - clean::TraitAliasItem(..) => write!(fmt, "Trait Alias ")?, - _ => { - // We don't generate pages for any other type. - unreachable!(); - } - } - if !self.item.is_primitive() && !self.item.is_keyword() { - let cur = &self.cx.current; - let amt = if self.item.is_mod() { cur.len() - 1 } else { cur.len() }; - for (i, component) in cur.iter().enumerate().take(amt) { - write!(fmt, "{}::", - "../".repeat(cur.len() - i - 1), - component)?; - } - } - write!(fmt, "{}", - self.item.type_(), self.item.name.as_ref().unwrap())?; - - write!(fmt, "

")?; // in-band - - match self.item.inner { - clean::ModuleItem(ref m) => - item_module(fmt, self.cx, self.item, &m.items), - clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => - item_function(fmt, self.cx, self.item, f), - clean::TraitItem(ref t) => item_trait(fmt, self.cx, self.item, t), - clean::StructItem(ref s) => item_struct(fmt, self.cx, self.item, s), - clean::UnionItem(ref s) => item_union(fmt, self.cx, self.item, s), - clean::EnumItem(ref e) => item_enum(fmt, self.cx, self.item, e), - clean::TypedefItem(ref t, _) => item_typedef(fmt, self.cx, self.item, t), - clean::MacroItem(ref m) => item_macro(fmt, self.cx, self.item, m), - clean::ProcMacroItem(ref m) => item_proc_macro(fmt, self.cx, self.item, m), - clean::PrimitiveItem(ref p) => item_primitive(fmt, self.cx, self.item, p), - clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => - item_static(fmt, self.cx, self.item, i), - clean::ConstantItem(ref c) => item_constant(fmt, self.cx, self.item, c), - clean::ForeignTypeItem => item_foreign_type(fmt, self.cx, self.item), - clean::KeywordItem(ref k) => item_keyword(fmt, self.cx, self.item, k), - clean::OpaqueTyItem(ref e, _) => item_opaque_ty(fmt, self.cx, self.item, e), - clean::TraitAliasItem(ref ta) => item_trait_alias(fmt, self.cx, self.item, ta), - _ => { - // We don't generate pages for any other type. - unreachable!(); - } +fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + debug_assert!(!self.item.is_stripped()); + // Write the breadcrumb trail header for the top + write!(fmt, "

")?; + if let Some(version) = self.item.stable_since() { + write!(fmt, "{0}", + version)?; + } + write!(fmt, + "\ + \ + []\ + \ + ")?; + + // Write `src` tag + // + // When this item is part of a `pub use` in a downstream crate, the + // [src] link in the downstream documentation will actually come back to + // this page, and this link will be auto-clicked. The `id` attribute is + // used to find the link to auto-click. + if self.cx.shared.include_sources && !self.item.is_primitive() { + if let Some(l) = self.src_href() { + write!(fmt, "[src]", + l, "goto source code")?; + } + } + + write!(fmt, "")?; // out-of-band + write!(fmt, "")?; + match self.item.inner { + clean::ModuleItem(ref m) => if m.is_crate { + write!(fmt, "Crate ")?; + } else { + write!(fmt, "Module ")?; + }, + clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => write!(fmt, "Function ")?, + clean::TraitItem(..) => write!(fmt, "Trait ")?, + clean::StructItem(..) => write!(fmt, "Struct ")?, + clean::UnionItem(..) => write!(fmt, "Union ")?, + clean::EnumItem(..) => write!(fmt, "Enum ")?, + clean::TypedefItem(..) => write!(fmt, "Type Definition ")?, + clean::MacroItem(..) => write!(fmt, "Macro ")?, + clean::ProcMacroItem(ref mac) => match mac.kind { + MacroKind::Bang => write!(fmt, "Macro ")?, + MacroKind::Attr => write!(fmt, "Attribute Macro ")?, + MacroKind::Derive => write!(fmt, "Derive Macro ")?, + } + clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?, + clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?, + clean::ConstantItem(..) => write!(fmt, "Constant ")?, + clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?, + clean::KeywordItem(..) => write!(fmt, "Keyword ")?, + clean::OpaqueTyItem(..) => write!(fmt, "Opaque Type ")?, + clean::TraitAliasItem(..) => write!(fmt, "Trait Alias ")?, + _ => { + // We don't generate pages for any other type. + unreachable!(); + } + } + if !self.item.is_primitive() && !self.item.is_keyword() { + let cur = &self.cx.current; + let amt = if self.item.is_mod() { cur.len() - 1 } else { cur.len() }; + for (i, component) in cur.iter().enumerate().take(amt) { + write!(fmt, "{}::", + "../".repeat(cur.len() - i - 1), + component)?; + } + } + write!(fmt, "{}", + self.item.type_(), self.item.name.as_ref().unwrap())?; + + write!(fmt, "

")?; // in-band + + match self.item.inner { + clean::ModuleItem(ref m) => + item_module(fmt, self.cx, self.item, &m.items), + clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => + item_function(fmt, self.cx, self.item, f), + clean::TraitItem(ref t) => item_trait(fmt, self.cx, self.item, t), + clean::StructItem(ref s) => item_struct(fmt, self.cx, self.item, s), + clean::UnionItem(ref s) => item_union(fmt, self.cx, self.item, s), + clean::EnumItem(ref e) => item_enum(fmt, self.cx, self.item, e), + clean::TypedefItem(ref t, _) => item_typedef(fmt, self.cx, self.item, t), + clean::MacroItem(ref m) => item_macro(fmt, self.cx, self.item, m), + clean::ProcMacroItem(ref m) => item_proc_macro(fmt, self.cx, self.item, m), + clean::PrimitiveItem(ref p) => item_primitive(fmt, self.cx, self.item, p), + clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => + item_static(fmt, self.cx, self.item, i), + clean::ConstantItem(ref c) => item_constant(fmt, self.cx, self.item, c), + clean::ForeignTypeItem => item_foreign_type(fmt, self.cx, self.item), + clean::KeywordItem(ref k) => item_keyword(fmt, self.cx, self.item, k), + clean::OpaqueTyItem(ref e, _) => item_opaque_ty(fmt, self.cx, self.item, e), + clean::TraitAliasItem(ref ta) => item_trait_alias(fmt, self.cx, self.item, ta), + _ => { + // We don't generate pages for any other type. + unreachable!(); } } } +} fn item_path(ty: ItemType, name: &str) -> String { match ty { @@ -3834,9 +3834,9 @@ fn render_assoc_items(w: &mut fmt::Formatter<'_>, struct RendererStruct<'a, 'b, 'c>(&'a Context, Vec<&'b &'b Impl>, &'c clean::Item); impl<'a, 'b, 'c> fmt::Display for RendererStruct<'a, 'b, 'c> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - render_impls(self.0, fmt, &self.1, self.2) - } + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + render_impls(self.0, fmt, &self.1, self.2) + } } let impls = RendererStruct(cx, concrete, containing_item).to_string(); @@ -4264,97 +4264,97 @@ fn item_foreign_type(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item) render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } - fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) { - let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; - - if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union() - || it.is_enum() || it.is_mod() || it.is_typedef() { - write!(buffer, "

{}{}

", - match it.inner { - clean::StructItem(..) => "Struct ", - clean::TraitItem(..) => "Trait ", - clean::PrimitiveItem(..) => "Primitive Type ", - clean::UnionItem(..) => "Union ", - clean::EnumItem(..) => "Enum ", - clean::TypedefItem(..) => "Type Definition ", - clean::ForeignTypeItem => "Foreign Type ", - clean::ModuleItem(..) => if it.is_crate() { - "Crate " - } else { - "Module " - }, - _ => "", +fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) { + let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; + + if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union() + || it.is_enum() || it.is_mod() || it.is_typedef() { + write!(buffer, "

{}{}

", + match it.inner { + clean::StructItem(..) => "Struct ", + clean::TraitItem(..) => "Trait ", + clean::PrimitiveItem(..) => "Primitive Type ", + clean::UnionItem(..) => "Union ", + clean::EnumItem(..) => "Enum ", + clean::TypedefItem(..) => "Type Definition ", + clean::ForeignTypeItem => "Foreign Type ", + clean::ModuleItem(..) => if it.is_crate() { + "Crate " + } else { + "Module " }, - it.name.as_ref().unwrap()); - } - - if it.is_crate() { - if let Some(ref version) = cache().crate_version { - write!(buffer, - "
\ -

Version {}

\ -
", - version); - } - } - - write!(buffer, "
"); - if it.is_crate() { - write!(buffer, "

See all {}'s items

", - it.name.as_ref().expect("crates always have a name")); - } - match it.inner { - clean::StructItem(ref s) => sidebar_struct(buffer, it, s), - clean::TraitItem(ref t) => sidebar_trait(buffer, it, t), - clean::PrimitiveItem(ref p) => sidebar_primitive(buffer, it, p), - clean::UnionItem(ref u) => sidebar_union(buffer, it, u), - clean::EnumItem(ref e) => sidebar_enum(buffer, it, e), - clean::TypedefItem(ref t, _) => sidebar_typedef(buffer, it, t), - clean::ModuleItem(ref m) => sidebar_module(buffer, it, &m.items), - clean::ForeignTypeItem => sidebar_foreign_type(buffer, it), - _ => (), - } - - // The sidebar is designed to display sibling functions, modules and - // other miscellaneous information. since there are lots of sibling - // items (and that causes quadratic growth in large modules), - // we refactor common parts into a shared JavaScript file per module. - // still, we don't move everything into JS because we want to preserve - // as much HTML as possible in order to allow non-JS-enabled browsers - // to navigate the documentation (though slightly inefficiently). - - write!(buffer, "

"); - for (i, name) in cx.current.iter().take(parentlen).enumerate() { - if i > 0 { - write!(buffer, "::"); - } - write!(buffer, "{}", - &cx.root_path()[..(cx.current.len() - i - 1) * 3], - *name); - } - write!(buffer, "

"); - - // Sidebar refers to the enclosing module, not this module. - let relpath = if it.is_mod() { "../" } else { "" }; - write!(buffer, - "", - name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""), - ty = it.type_().css_class(), - path = relpath); - if parentlen == 0 { - // There is no sidebar-items.js beyond the crate root path - // FIXME maybe dynamic crate loading can be merged here - } else { - write!(buffer, "", - path = relpath); - } - // Closes sidebar-elems div. - write!(buffer, "
"); + _ => "", + }, + it.name.as_ref().unwrap()); + } + + if it.is_crate() { + if let Some(ref version) = cache().crate_version { + write!(buffer, + "
\ +

Version {}

\ +
", + version); + } + } + + write!(buffer, "
"); + if it.is_crate() { + write!(buffer, "

See all {}'s items

", + it.name.as_ref().expect("crates always have a name")); + } + match it.inner { + clean::StructItem(ref s) => sidebar_struct(buffer, it, s), + clean::TraitItem(ref t) => sidebar_trait(buffer, it, t), + clean::PrimitiveItem(ref p) => sidebar_primitive(buffer, it, p), + clean::UnionItem(ref u) => sidebar_union(buffer, it, u), + clean::EnumItem(ref e) => sidebar_enum(buffer, it, e), + clean::TypedefItem(ref t, _) => sidebar_typedef(buffer, it, t), + clean::ModuleItem(ref m) => sidebar_module(buffer, it, &m.items), + clean::ForeignTypeItem => sidebar_foreign_type(buffer, it), + _ => (), + } + + // The sidebar is designed to display sibling functions, modules and + // other miscellaneous information. since there are lots of sibling + // items (and that causes quadratic growth in large modules), + // we refactor common parts into a shared JavaScript file per module. + // still, we don't move everything into JS because we want to preserve + // as much HTML as possible in order to allow non-JS-enabled browsers + // to navigate the documentation (though slightly inefficiently). + + write!(buffer, "

"); + for (i, name) in cx.current.iter().take(parentlen).enumerate() { + if i > 0 { + write!(buffer, "::"); + } + write!(buffer, "{}", + &cx.root_path()[..(cx.current.len() - i - 1) * 3], + *name); + } + write!(buffer, "

"); + + // Sidebar refers to the enclosing module, not this module. + let relpath = if it.is_mod() { "../" } else { "" }; + write!(buffer, + "", + name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""), + ty = it.type_().css_class(), + path = relpath); + if parentlen == 0 { + // There is no sidebar-items.js beyond the crate root path + // FIXME maybe dynamic crate loading can be merged here + } else { + write!(buffer, "", + path = relpath); } + // Closes sidebar-elems div. + write!(buffer, "
"); +} fn get_next_url(used_links: &mut FxHashSet, url: String) -> String { if used_links.insert(url.clone()) { diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 94ae14226097f..6dccfdadf0fb8 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -160,22 +160,22 @@ where struct Source<'a>(&'a str); impl<'a> fmt::Display for Source<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let Source(s) = *self; - let lines = s.lines().count(); - let mut cols = 0; - let mut tmp = lines; - while tmp > 0 { - cols += 1; - tmp /= 10; - } - write!(fmt, "
")?;
-        for i in 1..=lines {
-            write!(fmt, "{0:1$}\n", i, cols)?;
-        }
-        write!(fmt, "
")?; - write!(fmt, "{}", - highlight::render_with_highlighting(s, None, None, None))?; - Ok(()) +fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let Source(s) = *self; + let lines = s.lines().count(); + let mut cols = 0; + let mut tmp = lines; + while tmp > 0 { + cols += 1; + tmp /= 10; } + write!(fmt, "
")?;
+    for i in 1..=lines {
+        write!(fmt, "{0:1$}\n", i, cols)?;
+    }
+    write!(fmt, "
")?; + write!(fmt, "{}", + highlight::render_with_highlighting(s, None, None, None))?; + Ok(()) +} } From 3f0e77f19c16eb3cd46390ab0082ad749cb1c5b5 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 12:18:25 -0400 Subject: [PATCH 579/618] layout::render takes Print instead of fmt::Display --- src/librustdoc/html/format.rs | 6 +++++- src/librustdoc/html/layout.rs | 7 +++---- src/librustdoc/html/render.rs | 10 +++++----- src/librustdoc/html/sources.rs | 3 ++- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index f3c40c8568bb6..80f34fb17d2e8 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -99,7 +99,11 @@ impl Buffer { self.into_inner() } - crate fn display(&mut self, t: T) { + crate fn with_formatter) -> fmt::Result>(&mut self, t: T) { + self.from_display(display_fn(move |f| (t)(f))); + } + + crate fn from_display(&mut self, t: T) { if self.for_html { write!(self, "{}", t); } else { diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 1202f411f912c..56074f4ab1192 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -1,4 +1,3 @@ -use std::fmt; use std::path::PathBuf; use crate::externalfiles::ExternalHtml; @@ -31,11 +30,11 @@ pub struct Page<'a> { pub static_extra_scripts: &'a [&'a str], } -pub fn render( +pub fn render( layout: &Layout, page: &Page<'_>, sidebar: S, - t: &T, + t: T, themes: &[PathBuf], ) -> String { let static_root_path = page.static_root_path.unwrap_or(page.root_path); @@ -175,7 +174,7 @@ pub fn render( } else { String::new() }, - content = *t, + content = Buffer::html().to_display(t), static_root_path = static_root_path, root_path = page.root_path, css_class = page.css_class, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 1d1e54fc9eaba..4514a540f543a 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -65,7 +65,7 @@ use crate::docfs::{DocFS, ErrorStorage, PathError}; use crate::doctree; use crate::fold::DocFolder; use crate::html::escape::Escape; -use crate::html::format::{Print, Buffer, AsyncSpace, ConstnessSpace}; +use crate::html::format::{Buffer, AsyncSpace, ConstnessSpace}; use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace, DefaultSpace}; use crate::html::format::{VisSpace, Function, UnsafetySpace, MutableSpace}; use crate::html::format::fmt_impl_for_trait_page; @@ -1172,7 +1172,7 @@ themePicker.onblur = handleThemeButtonsBlur; }) .collect::()); let v = layout::render(&cx.shared.layout, - &page, "", &content, + &page, "", content, &cx.shared.themes); cx.shared.fs.write(&dst, v.as_bytes())?; } @@ -1919,7 +1919,7 @@ impl Context { String::new() }; let v = layout::render(&self.shared.layout, - &page, sidebar, &all, + &page, sidebar, |buf: &mut Buffer| buf.from_display(all), &self.shared.themes); self.shared.fs.write(&final_file, v.as_bytes())?; @@ -1935,7 +1935,7 @@ impl Context { themes.push(PathBuf::from("settings.css")); let v = layout::render( &self.shared.layout, - &page, sidebar, &settings, + &page, sidebar, |buf: &mut Buffer| buf.from_display(settings), &themes); self.shared.fs.write(&settings_file, v.as_bytes())?; @@ -1993,7 +1993,7 @@ impl Context { if !self.render_redirect_pages { layout::render(&self.shared.layout, &page, |buf: &mut _| print_sidebar(self, it, buf), - &Item{ cx: self, item: it }, + |buf: &mut Buffer| buf.from_display(Item { cx: self, item: it }), &self.shared.themes) } else { let mut url = self.root_path(); diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 6dccfdadf0fb8..e94ae1d968ef5 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -4,6 +4,7 @@ use crate::fold::DocFolder; use crate::html::layout; use crate::html::render::{Error, SharedContext, BASIC_KEYWORDS}; use crate::html::highlight; +use crate::html::format::Buffer; use std::ffi::OsStr; use std::fs; use std::path::{Component, Path, PathBuf}; @@ -120,7 +121,7 @@ impl<'a> SourceCollector<'a> { static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)], }; let v = layout::render(&self.scx.layout, - &page, "", &Source(contents), + &page, "", |buf: &mut Buffer| buf.from_display(Source(&contents)), &self.scx.themes); self.scx.fs.write(&cur, v.as_bytes())?; self.scx.local_sources.insert(p.clone(), href); From bb40d5fa498603f041dcf1092099c0b93928e442 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 12:20:56 -0400 Subject: [PATCH 580/618] Move Source to Buffer --- src/librustdoc/html/sources.rs | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index e94ae1d968ef5..d840683a7af87 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -8,7 +8,6 @@ use crate::html::format::Buffer; use std::ffi::OsStr; use std::fs; use std::path::{Component, Path, PathBuf}; -use std::fmt; use syntax::source_map::FileName; crate fn render(dst: &Path, scx: &mut SharedContext, @@ -121,7 +120,7 @@ impl<'a> SourceCollector<'a> { static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)], }; let v = layout::render(&self.scx.layout, - &page, "", |buf: &mut Buffer| buf.from_display(Source(&contents)), + &page, "", |buf: &mut _| print_src(buf, &contents), &self.scx.themes); self.scx.fs.write(&cur, v.as_bytes())?; self.scx.local_sources.insert(p.clone(), href); @@ -158,11 +157,7 @@ where /// Wrapper struct to render the source code of a file. This will do things like /// adding line numbers to the left-hand side. -struct Source<'a>(&'a str); - -impl<'a> fmt::Display for Source<'a> { -fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let Source(s) = *self; +fn print_src(buf: &mut Buffer, s: &str) { let lines = s.lines().count(); let mut cols = 0; let mut tmp = lines; @@ -170,13 +165,11 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { cols += 1; tmp /= 10; } - write!(fmt, "
")?;
+    write!(buf, "
");
     for i in 1..=lines {
-        write!(fmt, "{0:1$}\n", i, cols)?;
+        write!(buf, "{0:1$}\n", i, cols);
     }
-    write!(fmt, "
")?; - write!(fmt, "{}", - highlight::render_with_highlighting(s, None, None, None))?; - Ok(()) -} + write!(buf, "
"); + write!(buf, "{}", + highlight::render_with_highlighting(s, None, None, None)); } From 17bef30d0b1cc3851fb76fdd84b4d15bb629dc39 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 12:27:27 -0400 Subject: [PATCH 581/618] Settings to function --- src/librustdoc/html/render.rs | 55 ++++++++++++----------------------- 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4514a540f543a..2eb2ba4e2b201 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1801,42 +1801,25 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } -#[derive(Debug)] -struct Settings<'a> { +fn settings(root_path: &str, suffix: &str) -> String { // (id, explanation, default value) - settings: Vec<(&'static str, &'static str, bool)>, - root_path: &'a str, - suffix: &'a str, -} - -impl<'a> Settings<'a> { - pub fn new(root_path: &'a str, suffix: &'a str) -> Settings<'a> { - Settings { - settings: vec![ - ("item-declarations", "Auto-hide item declarations.", true), - ("item-attributes", "Auto-hide item attributes.", true), - ("trait-implementations", "Auto-hide trait implementations documentation", - true), - ("method-docs", "Auto-hide item methods' documentation", false), - ("go-to-only-result", "Directly go to item in search if there is only one result", - false), - ("line-numbers", "Show line numbers on code examples", false), - ], - root_path, - suffix, - } - } -} - -impl<'a> fmt::Display for Settings<'a> { -fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, + let settings = [ + ("item-declarations", "Auto-hide item declarations.", true), + ("item-attributes", "Auto-hide item attributes.", true), + ("trait-implementations", "Auto-hide trait implementations documentation", + true), + ("method-docs", "Auto-hide item methods' documentation", false), + ("go-to-only-result", "Directly go to item in search if there is only one result", + false), + ("line-numbers", "Show line numbers on code examples", false), + ]; + format!( "

\ Rustdoc settings\

\
{}
\ ", - self.settings.iter() + settings.iter() .map(|(id, text, enabled)| { format!("
\
", id, if *enabled { " checked" } else { "" }, text) }) .collect::(), - self.root_path, - self.suffix) -} + root_path, + suffix) } impl Context { @@ -1924,8 +1906,6 @@ impl Context { self.shared.fs.write(&final_file, v.as_bytes())?; // Generating settings page. - let settings = Settings::new(self.shared.static_root_path.as_deref().unwrap_or("./"), - &self.shared.resource_suffix); page.title = "Rustdoc settings"; page.description = "Settings of Rustdoc"; page.root_path = "./"; @@ -1935,7 +1915,10 @@ impl Context { themes.push(PathBuf::from("settings.css")); let v = layout::render( &self.shared.layout, - &page, sidebar, |buf: &mut Buffer| buf.from_display(settings), + &page, sidebar, settings( + self.shared.static_root_path.as_deref().unwrap_or("./"), + &self.shared.resource_suffix + ), &themes); self.shared.fs.write(&settings_file, v.as_bytes())?; From a502e856034bcd4bc38152b3bd74cad792b62c63 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 12:31:55 -0400 Subject: [PATCH 582/618] AllTypes to function --- src/librustdoc/html/render.rs | 62 +++++++++++++++++------------------ 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 2eb2ba4e2b201..ee7981aba013a 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1757,8 +1757,7 @@ impl AllTypes { } } -fn print_entries(f: &mut fmt::Formatter<'_>, e: &FxHashSet, title: &str, - class: &str) -> fmt::Result { +fn print_entries(f: &mut Buffer, e: &FxHashSet, title: &str, class: &str) { if !e.is_empty() { let mut e: Vec<&ItemEntry> = e.iter().collect(); e.sort(); @@ -1766,39 +1765,38 @@ fn print_entries(f: &mut fmt::Formatter<'_>, e: &FxHashSet, title: &s title, Escape(title), class, - e.iter().map(|s| format!("
  • {}
  • ", s)).collect::())?; + e.iter().map(|s| format!("
  • {}
  • ", s)).collect::()); } - Ok(()) } -impl fmt::Display for AllTypes { -fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, -"

    \ - \ - \ - \ - []\ - \ +impl AllTypes { + fn print(self, f: &mut Buffer) { + write!(f, + "

    \ + \ + \ + \ + []\ + \ + - - List of all items\ -

    ")?; - print_entries(f, &self.structs, "Structs", "structs")?; - print_entries(f, &self.enums, "Enums", "enums")?; - print_entries(f, &self.unions, "Unions", "unions")?; - print_entries(f, &self.primitives, "Primitives", "primitives")?; - print_entries(f, &self.traits, "Traits", "traits")?; - print_entries(f, &self.macros, "Macros", "macros")?; - print_entries(f, &self.attributes, "Attribute Macros", "attributes")?; - print_entries(f, &self.derives, "Derive Macros", "derives")?; - print_entries(f, &self.functions, "Functions", "functions")?; - print_entries(f, &self.typedefs, "Typedefs", "typedefs")?; - print_entries(f, &self.trait_aliases, "Trait Aliases", "trait-aliases")?; - print_entries(f, &self.opaque_tys, "Opaque Types", "opaque-types")?; - print_entries(f, &self.statics, "Statics", "statics")?; - print_entries(f, &self.constants, "Constants", "constants") -} + List of all items\ +

    "); + print_entries(f, &self.structs, "Structs", "structs"); + print_entries(f, &self.enums, "Enums", "enums"); + print_entries(f, &self.unions, "Unions", "unions"); + print_entries(f, &self.primitives, "Primitives", "primitives"); + print_entries(f, &self.traits, "Traits", "traits"); + print_entries(f, &self.macros, "Macros", "macros"); + print_entries(f, &self.attributes, "Attribute Macros", "attributes"); + print_entries(f, &self.derives, "Derive Macros", "derives"); + print_entries(f, &self.functions, "Functions", "functions"); + print_entries(f, &self.typedefs, "Typedefs", "typedefs"); + print_entries(f, &self.trait_aliases, "Trait Aliases", "trait-aliases"); + print_entries(f, &self.opaque_tys, "Opaque Types", "opaque-types"); + print_entries(f, &self.statics, "Statics", "statics"); + print_entries(f, &self.constants, "Constants", "constants") + } } fn settings(root_path: &str, suffix: &str) -> String { @@ -1901,7 +1899,7 @@ impl Context { String::new() }; let v = layout::render(&self.shared.layout, - &page, sidebar, |buf: &mut Buffer| buf.from_display(all), + &page, sidebar, |buf: &mut Buffer| all.print(buf), &self.shared.themes); self.shared.fs.write(&final_file, v.as_bytes())?; From c1c1e86d5a03796ec4442372b185fb1e20d81124 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 13:29:31 -0400 Subject: [PATCH 583/618] Item to function --- src/librustdoc/html/render.rs | 163 ++++++++++++++++------------------ 1 file changed, 79 insertions(+), 84 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index ee7981aba013a..fc23ffe2b8ca7 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -381,12 +381,6 @@ pub struct RenderInfo { // Helper structs for rendering items/sidebars and carrying along contextual // information -#[derive(Copy, Clone)] -struct Item<'a> { - cx: &'a Context, - item: &'a clean::Item, -} - /// Struct representing one entry in the JS search index. These are all emitted /// by hand to a large JS file at the end of cache-creation. #[derive(Debug)] @@ -1974,7 +1968,7 @@ impl Context { if !self.render_redirect_pages { layout::render(&self.shared.layout, &page, |buf: &mut _| print_sidebar(self, it, buf), - |buf: &mut Buffer| buf.from_display(Item { cx: self, item: it }), + |buf: &mut _| print_item(self, it, buf), &self.shared.themes) } else { let mut url = self.root_path(); @@ -2115,7 +2109,7 @@ impl Context { } } -impl<'a> Item<'a> { +impl Context { /// Generates a url appropriate for an `href` attribute back to the source of /// this item. /// @@ -2125,26 +2119,26 @@ impl<'a> Item<'a> { /// If `None` is returned, then a source link couldn't be generated. This /// may happen, for example, with externally inlined items where the source /// of their crate documentation isn't known. - fn src_href(&self) -> Option { - let mut root = self.cx.root_path(); + fn src_href(&self, item: &clean::Item) -> Option { + let mut root = self.root_path(); let cache = cache(); let mut path = String::new(); // We can safely ignore macros from other libraries - let file = match self.item.source.filename { + let file = match item.source.filename { FileName::Real(ref path) => path, _ => return None, }; - let (krate, path) = if self.item.def_id.is_local() { - if let Some(path) = self.cx.shared.local_sources.get(file) { - (&self.cx.shared.layout.krate, path) + let (krate, path) = if item.def_id.is_local() { + if let Some(path) = self.shared.local_sources.get(file) { + (&self.shared.layout.krate, path) } else { return None; } } else { - let (krate, src_root) = match *cache.extern_locations.get(&self.item.def_id.krate)? { + let (krate, src_root) = match *cache.extern_locations.get(&item.def_id.krate)? { (ref name, ref src, Local) => (name, src), (ref name, ref src, Remote(ref s)) => { root = s.to_string(); @@ -2164,10 +2158,10 @@ impl<'a> Item<'a> { (krate, &path) }; - let lines = if self.item.source.loline == self.item.source.hiline { - self.item.source.loline.to_string() + let lines = if item.source.loline == item.source.hiline { + item.source.loline.to_string() } else { - format!("{}-{}", self.item.source.loline, self.item.source.hiline) + format!("{}-{}", item.source.loline, item.source.hiline) }; Some(format!("{root}src/{krate}/{path}#{lines}", root = Escape(&root), @@ -2185,22 +2179,21 @@ where F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result { write!(w, "") } -impl<'a> fmt::Display for Item<'a> { -fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - debug_assert!(!self.item.is_stripped()); +fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) { + debug_assert!(!item.is_stripped()); // Write the breadcrumb trail header for the top - write!(fmt, "

    ")?; - if let Some(version) = self.item.stable_since() { - write!(fmt, "{0}", - version)?; + write!(buf, "

    "); + if let Some(version) = item.stable_since() { + write!(buf, "{0}", + version); } - write!(fmt, + write!(buf, "\ \ []\ \ - ")?; + "); // Write `src` tag // @@ -2208,85 +2201,87 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { // [src] link in the downstream documentation will actually come back to // this page, and this link will be auto-clicked. The `id` attribute is // used to find the link to auto-click. - if self.cx.shared.include_sources && !self.item.is_primitive() { - if let Some(l) = self.src_href() { - write!(fmt, "[src]", - l, "goto source code")?; + if cx.shared.include_sources && !item.is_primitive() { + if let Some(l) = cx.src_href(item) { + write!(buf, "[src]", + l, "goto source code"); } } - write!(fmt, "")?; // out-of-band - write!(fmt, "")?; - match self.item.inner { + write!(buf, ""); // out-of-band + write!(buf, ""); + let name = match item.inner { clean::ModuleItem(ref m) => if m.is_crate { - write!(fmt, "Crate ")?; + "Crate " } else { - write!(fmt, "Module ")?; + "Module " }, - clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => write!(fmt, "Function ")?, - clean::TraitItem(..) => write!(fmt, "Trait ")?, - clean::StructItem(..) => write!(fmt, "Struct ")?, - clean::UnionItem(..) => write!(fmt, "Union ")?, - clean::EnumItem(..) => write!(fmt, "Enum ")?, - clean::TypedefItem(..) => write!(fmt, "Type Definition ")?, - clean::MacroItem(..) => write!(fmt, "Macro ")?, + clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => "Function ", + clean::TraitItem(..) => "Trait ", + clean::StructItem(..) => "Struct ", + clean::UnionItem(..) => "Union ", + clean::EnumItem(..) => "Enum ", + clean::TypedefItem(..) => "Type Definition ", + clean::MacroItem(..) => "Macro ", clean::ProcMacroItem(ref mac) => match mac.kind { - MacroKind::Bang => write!(fmt, "Macro ")?, - MacroKind::Attr => write!(fmt, "Attribute Macro ")?, - MacroKind::Derive => write!(fmt, "Derive Macro ")?, - } - clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?, - clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?, - clean::ConstantItem(..) => write!(fmt, "Constant ")?, - clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?, - clean::KeywordItem(..) => write!(fmt, "Keyword ")?, - clean::OpaqueTyItem(..) => write!(fmt, "Opaque Type ")?, - clean::TraitAliasItem(..) => write!(fmt, "Trait Alias ")?, + MacroKind::Bang => "Macro ", + MacroKind::Attr => "Attribute Macro ", + MacroKind::Derive => "Derive Macro ", + } + clean::PrimitiveItem(..) => "Primitive Type ", + clean::StaticItem(..) | clean::ForeignStaticItem(..) => "Static ", + clean::ConstantItem(..) => "Constant ", + clean::ForeignTypeItem => "Foreign Type ", + clean::KeywordItem(..) => "Keyword ", + clean::OpaqueTyItem(..) => "Opaque Type ", + clean::TraitAliasItem(..) => "Trait Alias ", _ => { // We don't generate pages for any other type. unreachable!(); } - } - if !self.item.is_primitive() && !self.item.is_keyword() { - let cur = &self.cx.current; - let amt = if self.item.is_mod() { cur.len() - 1 } else { cur.len() }; + }; + buf.write_str(name); + if !item.is_primitive() && !item.is_keyword() { + let cur = &cx.current; + let amt = if item.is_mod() { cur.len() - 1 } else { cur.len() }; for (i, component) in cur.iter().enumerate().take(amt) { - write!(fmt, "{}::", + write!(buf, "{}::", "../".repeat(cur.len() - i - 1), - component)?; + component); } } - write!(fmt, "{}", - self.item.type_(), self.item.name.as_ref().unwrap())?; + write!(buf, "{}", + item.type_(), item.name.as_ref().unwrap()); - write!(fmt, "

    ")?; // in-band + write!(buf, "

    "); // in-band - match self.item.inner { + buf.with_formatter(|fmt| { + match item.inner { clean::ModuleItem(ref m) => - item_module(fmt, self.cx, self.item, &m.items), + item_module(fmt, cx, item, &m.items), clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => - item_function(fmt, self.cx, self.item, f), - clean::TraitItem(ref t) => item_trait(fmt, self.cx, self.item, t), - clean::StructItem(ref s) => item_struct(fmt, self.cx, self.item, s), - clean::UnionItem(ref s) => item_union(fmt, self.cx, self.item, s), - clean::EnumItem(ref e) => item_enum(fmt, self.cx, self.item, e), - clean::TypedefItem(ref t, _) => item_typedef(fmt, self.cx, self.item, t), - clean::MacroItem(ref m) => item_macro(fmt, self.cx, self.item, m), - clean::ProcMacroItem(ref m) => item_proc_macro(fmt, self.cx, self.item, m), - clean::PrimitiveItem(ref p) => item_primitive(fmt, self.cx, self.item, p), + item_function(fmt, cx, item, f), + clean::TraitItem(ref t) => item_trait(fmt, cx, item, t), + clean::StructItem(ref s) => item_struct(fmt, cx, item, s), + clean::UnionItem(ref s) => item_union(fmt, cx, item, s), + clean::EnumItem(ref e) => item_enum(fmt, cx, item, e), + clean::TypedefItem(ref t, _) => item_typedef(fmt, cx, item, t), + clean::MacroItem(ref m) => item_macro(fmt, cx, item, m), + clean::ProcMacroItem(ref m) => item_proc_macro(fmt, cx, item, m), + clean::PrimitiveItem(ref p) => item_primitive(fmt, cx, item, p), clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => - item_static(fmt, self.cx, self.item, i), - clean::ConstantItem(ref c) => item_constant(fmt, self.cx, self.item, c), - clean::ForeignTypeItem => item_foreign_type(fmt, self.cx, self.item), - clean::KeywordItem(ref k) => item_keyword(fmt, self.cx, self.item, k), - clean::OpaqueTyItem(ref e, _) => item_opaque_ty(fmt, self.cx, self.item, e), - clean::TraitAliasItem(ref ta) => item_trait_alias(fmt, self.cx, self.item, ta), + item_static(fmt, cx, item, i), + clean::ConstantItem(ref c) => item_constant(fmt, cx, item, c), + clean::ForeignTypeItem => item_foreign_type(fmt, cx, item), + clean::KeywordItem(ref k) => item_keyword(fmt, cx, item, k), + clean::OpaqueTyItem(ref e, _) => item_opaque_ty(fmt, cx, item, e), + clean::TraitAliasItem(ref ta) => item_trait_alias(fmt, cx, item, ta), _ => { // We don't generate pages for any other type. unreachable!(); } } -} + }) } fn item_path(ty: ItemType, name: &str) -> String { @@ -4004,7 +3999,7 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt write!(w, "", id)?; let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]); render_stability_since_raw(w, since, outer_version)?; - if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() { + if let Some(l) = cx.src_href(&i.impl_item) { write!(w, "[src]", l, "goto source code")?; } @@ -4050,7 +4045,7 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt render_assoc_item(w, item, link.anchor(&id), ItemType::Impl)?; write!(w, "")?; render_stability_since_raw(w, item.stable_since(), outer_version)?; - if let Some(l) = (Item { cx, item }).src_href() { + if let Some(l) = cx.src_href(item) { write!(w, "[src]", l, "goto source code")?; } @@ -4073,7 +4068,7 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt assoc_const(w, item, ty, default.as_ref(), link.anchor(&id), "")?; write!(w, "")?; render_stability_since_raw(w, item.stable_since(), outer_version)?; - if let Some(l) = (Item { cx, item }).src_href() { + if let Some(l) = cx.src_href(item) { write!(w, "[src]", l, "goto source code")?; } From 02c5c5cb597c873dd152f3ec8a6b74b5f28ccf36 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 15:47:55 -0400 Subject: [PATCH 584/618] Move to buffers throughout print_item --- src/librustdoc/html/format.rs | 6 +- src/librustdoc/html/render.rs | 797 ++++++++++++++++------------------ 2 files changed, 375 insertions(+), 428 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 80f34fb17d2e8..dcd32192ff384 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -872,9 +872,9 @@ impl fmt::Display for clean::Impl { // The difference from above is that trait is not hyperlinked. pub fn fmt_impl_for_trait_page(i: &clean::Impl, - f: &mut fmt::Formatter<'_>, - use_absolute: bool) -> fmt::Result { - fmt_impl(i, f, false, use_absolute) + f: &mut Buffer, + use_absolute: bool) { + f.with_formatter(|f| fmt_impl(i, f, false, use_absolute)) } impl fmt::Display for clean::Arguments { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index fc23ffe2b8ca7..9846073cad4bc 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1233,9 +1233,9 @@ themePicker.onblur = handleThemeButtonsBlur; // identically even with rustdoc running in parallel. all_implementors.sort(); - let mut v = String::from("(function() {var implementors = {}};\n"); + let mut v = String::from("(function() {var implementors = {};\n"); for implementor in &all_implementors { - v.push_str(&format!("{}", *implementor)); + writeln!(v, "{}", *implementor).unwrap(); } v.push_str(r" if (window.register_implementors) { @@ -1243,7 +1243,7 @@ themePicker.onblur = handleThemeButtonsBlur; } else { window.pending_implementors = implementors; } - \n"); + "); v.push_str("})()"); cx.shared.fs.write(&mydst, &v)?; } @@ -2171,11 +2171,11 @@ impl Context { } } -fn wrap_into_docblock(w: &mut fmt::Formatter<'_>, - f: F) -> fmt::Result -where F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result { - write!(w, "
    ")?; - f(w)?; +fn wrap_into_docblock(w: &mut Buffer, f: F) + where F: FnOnce(&mut Buffer) +{ + write!(w, "
    "); + f(w); write!(w, "
    ") } @@ -2255,33 +2255,31 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) { write!(buf, ""); // in-band - buf.with_formatter(|fmt| { match item.inner { clean::ModuleItem(ref m) => - item_module(fmt, cx, item, &m.items), + item_module(buf, cx, item, &m.items), clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => - item_function(fmt, cx, item, f), - clean::TraitItem(ref t) => item_trait(fmt, cx, item, t), - clean::StructItem(ref s) => item_struct(fmt, cx, item, s), - clean::UnionItem(ref s) => item_union(fmt, cx, item, s), - clean::EnumItem(ref e) => item_enum(fmt, cx, item, e), - clean::TypedefItem(ref t, _) => item_typedef(fmt, cx, item, t), - clean::MacroItem(ref m) => item_macro(fmt, cx, item, m), - clean::ProcMacroItem(ref m) => item_proc_macro(fmt, cx, item, m), - clean::PrimitiveItem(ref p) => item_primitive(fmt, cx, item, p), + item_function(buf, cx, item, f), + clean::TraitItem(ref t) => item_trait(buf, cx, item, t), + clean::StructItem(ref s) => item_struct(buf, cx, item, s), + clean::UnionItem(ref s) => item_union(buf, cx, item, s), + clean::EnumItem(ref e) => item_enum(buf, cx, item, e), + clean::TypedefItem(ref t, _) => item_typedef(buf, cx, item, t), + clean::MacroItem(ref m) => item_macro(buf, cx, item, m), + clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m), + clean::PrimitiveItem(ref p) => item_primitive(buf, cx, item, p), clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => - item_static(fmt, cx, item, i), - clean::ConstantItem(ref c) => item_constant(fmt, cx, item, c), - clean::ForeignTypeItem => item_foreign_type(fmt, cx, item), - clean::KeywordItem(ref k) => item_keyword(fmt, cx, item, k), - clean::OpaqueTyItem(ref e, _) => item_opaque_ty(fmt, cx, item, e), - clean::TraitAliasItem(ref ta) => item_trait_alias(fmt, cx, item, ta), + item_static(buf, cx, item, i), + clean::ConstantItem(ref c) => item_constant(buf, cx, item, c), + clean::ForeignTypeItem => item_foreign_type(buf, cx, item), + clean::KeywordItem(ref k) => item_keyword(buf, cx, item, k), + clean::OpaqueTyItem(ref e, _) => item_opaque_ty(buf, cx, item, e), + clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta), _ => { // We don't generate pages for any other type. unreachable!(); } } - }) } fn item_path(ty: ItemType, name: &str) -> String { @@ -2333,24 +2331,23 @@ fn shorten(s: String) -> String { } } -fn document(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item) -> fmt::Result { +fn document(w: &mut Buffer, cx: &Context, item: &clean::Item) { if let Some(ref name) = item.name { info!("Documenting {}", name); } - document_stability(w, cx, item, false)?; - document_full(w, item, cx, "", false)?; - Ok(()) + document_stability(w, cx, item, false); + document_full(w, item, cx, "", false); } /// Render md_text as markdown. fn render_markdown( - w: &mut fmt::Formatter<'_>, + w: &mut Buffer, cx: &Context, md_text: &str, links: Vec<(String, String)>, prefix: &str, is_hidden: bool, -) -> fmt::Result { +) { let mut ids = cx.id_map.borrow_mut(); write!(w, "
    {}{}
    ", if is_hidden { " hidden" } else { "" }, @@ -2360,13 +2357,13 @@ fn render_markdown( } fn document_short( - w: &mut fmt::Formatter<'_>, + w: &mut Buffer, cx: &Context, item: &clean::Item, link: AssocItemLink<'_>, prefix: &str, is_hidden: bool, -) -> fmt::Result { +) { if let Some(s) = item.doc_value() { let markdown = if s.contains('\n') { format!("{} [Read more]({})", @@ -2374,46 +2371,41 @@ fn document_short( } else { plain_summary_line(Some(s)) }; - render_markdown(w, cx, &markdown, item.links(), prefix, is_hidden)?; + render_markdown(w, cx, &markdown, item.links(), prefix, is_hidden); } else if !prefix.is_empty() { write!(w, "
    {}
    ", if is_hidden { " hidden" } else { "" }, - prefix)?; + prefix); } - Ok(()) } -fn document_full(w: &mut fmt::Formatter<'_>, item: &clean::Item, - cx: &Context, prefix: &str, is_hidden: bool) -> fmt::Result { +fn document_full(w: &mut Buffer, item: &clean::Item, cx: &Context, prefix: &str, is_hidden: bool) { if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) { debug!("Doc block: =====\n{}\n=====", s); - render_markdown(w, cx, &*s, item.links(), prefix, is_hidden)?; + render_markdown(w, cx, &*s, item.links(), prefix, is_hidden); } else if !prefix.is_empty() { write!(w, "
    {}
    ", if is_hidden { " hidden" } else { "" }, - prefix)?; + prefix); } - Ok(()) } -fn document_stability(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item, - is_hidden: bool) -> fmt::Result { +fn document_stability(w: &mut Buffer, cx: &Context, item: &clean::Item, is_hidden: bool) { let stabilities = short_stability(item, cx); if !stabilities.is_empty() { - write!(w, "
    ", if is_hidden { " hidden" } else { "" })?; + write!(w, "
    ", if is_hidden { " hidden" } else { "" }); for stability in stabilities { - write!(w, "{}", stability)?; + write!(w, "{}", stability); } - write!(w, "
    ")?; + write!(w, "
    "); } - Ok(()) } fn document_non_exhaustive_header(item: &clean::Item) -> &str { if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" } } -fn document_non_exhaustive(w: &mut fmt::Formatter<'_>, item: &clean::Item) -> fmt::Result { +fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { if item.is_non_exhaustive() { write!(w, "
    ", { if item.is_struct() { @@ -2425,31 +2417,29 @@ fn document_non_exhaustive(w: &mut fmt::Formatter<'_>, item: &clean::Item) -> fm } else { "type" } - })?; + }); if item.is_struct() { write!(w, "Non-exhaustive structs could have additional fields added in future. \ Therefore, non-exhaustive structs cannot be constructed in external crates \ using the traditional Struct {{ .. }} syntax; cannot be \ matched against without a wildcard ..; and \ - struct update syntax will not work.")?; + struct update syntax will not work."); } else if item.is_enum() { write!(w, "Non-exhaustive enums could have additional variants added in future. \ Therefore, when matching against variants of non-exhaustive enums, an \ - extra wildcard arm must be added to account for any future variants.")?; + extra wildcard arm must be added to account for any future variants."); } else if item.is_variant() { write!(w, "Non-exhaustive enum variants could have additional fields added in future. \ Therefore, non-exhaustive enum variants cannot be constructed in external \ - crates and cannot be matched against.")?; + crates and cannot be matched against."); } else { write!(w, "This type will require a wildcard arm in any match statements or \ - constructors.")?; + constructors."); } - write!(w, "
    ")?; + write!(w, "
    "); } - - Ok(()) } fn name_key(name: &str) -> (&str, u64, usize) { @@ -2473,9 +2463,8 @@ fn name_key(name: &str) -> (&str, u64, usize) { } } -fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context, - item: &clean::Item, items: &[clean::Item]) -> fmt::Result { - document(w, cx, item)?; +fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean::Item]) { + document(w, cx, item); let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::>(); @@ -2566,13 +2555,13 @@ fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context, curty = myty; } else if myty != curty { if curty.is_some() { - write!(w, "")?; + write!(w, ""); } curty = myty; let (short, name) = item_ty_to_strs(&myty.unwrap()); write!(w, "

    \ {name}

    \n", - id = cx.derive_id(short.to_owned()), name = name)?; + id = cx.derive_id(short.to_owned()), name = name); } match myitem.inner { @@ -2584,20 +2573,20 @@ fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context, write!(w, "")?; + write!(w, ""); } clean::ImportItem(ref import) => { write!(w, "", - VisSpace(&myitem.visibility), *import)?; + VisSpace(&myitem.visibility), *import); } _ => { @@ -2642,15 +2631,14 @@ fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context, }) .collect::>() .join(" "), - )?; + ); } } } if curty.is_some() { - write!(w, "
    {}extern crate {} as {};", VisSpace(&myitem.visibility), anchor(myitem.def_id, src), - name)? + name) } None => { write!(w, "
    {}extern crate {};", VisSpace(&myitem.visibility), - anchor(myitem.def_id, name))? + anchor(myitem.def_id, name)) } } - write!(w, "
    {}{}
    ")?; + write!(w, ""); } - Ok(()) } /// Render the stability and deprecation tags that are displayed in the item's summary at the @@ -2799,33 +2787,30 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { stability } -fn item_constant(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, - c: &clean::Constant) -> fmt::Result { - write!(w, "
    ")?;
    -    render_attributes(w, it, false)?;
    +fn item_constant(w: &mut Buffer, cx: &Context, it: &clean::Item, c: &clean::Constant) {
    +    write!(w, "
    ");
    +    render_attributes(w, it, false);
         write!(w, "{vis}const \
                    {name}: {typ}
    ", vis = VisSpace(&it.visibility), name = it.name.as_ref().unwrap(), - typ = c.type_)?; + typ = c.type_); document(w, cx, it) } -fn item_static(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, - s: &clean::Static) -> fmt::Result { - write!(w, "
    ")?;
    -    render_attributes(w, it, false)?;
    +fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static) {
    +    write!(w, "
    ");
    +    render_attributes(w, it, false);
         write!(w, "{vis}static {mutability}\
                    {name}: {typ}
    ", vis = VisSpace(&it.visibility), mutability = MutableSpace(s.mutability), name = it.name.as_ref().unwrap(), - typ = s.type_)?; + typ = s.type_); document(w, cx, it) } -fn item_function(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, - f: &clean::Function) -> fmt::Result { +fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Function) { let header_len = format!( "{}{}{}{}{:#}fn {}{:#}", VisSpace(&it.visibility), @@ -2836,8 +2821,8 @@ fn item_function(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, it.name.as_ref().unwrap(), f.generics ).len(); - write!(w, "{}
    ", render_spotlight_traits(it)?)?;
    -    render_attributes(w, it, false)?;
    +    write!(w, "{}
    ", render_spotlight_traits(it));
    +    render_attributes(w, it, false);
         write!(w,
                "{vis}{constness}{unsafety}{asyncness}{abi}fn \
                {name}{generics}{decl}{where_clause}
    ", @@ -2854,12 +2839,12 @@ fn item_function(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, header_len, indent: 0, asyncness: f.header.asyncness, - })?; + }); document(w, cx, it) } -fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter<'_>, - implementor_dups: &FxHashMap<&str, (DefId, bool)>) -> fmt::Result { +fn render_implementor(cx: &Context, implementor: &Impl, w: &mut Buffer, + implementor_dups: &FxHashMap<&str, (DefId, bool)>) { // If there's already another implementor that has the same abbridged name, use the // full path, for example in `std::iter::ExactSizeIterator` let use_absolute = match implementor.inner_impl().for_ { @@ -2871,20 +2856,18 @@ fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter<' _ => false, }; render_impl(w, cx, implementor, AssocItemLink::Anchor(None), RenderMode::Normal, - implementor.impl_item.stable_since(), false, Some(use_absolute), false, false)?; - Ok(()) + implementor.impl_item.stable_since(), false, Some(use_absolute), false, false); } -fn render_impls(cx: &Context, w: &mut fmt::Formatter<'_>, +fn render_impls(cx: &Context, w: &mut Buffer, traits: &[&&Impl], - containing_item: &clean::Item) -> fmt::Result { + containing_item: &clean::Item) { for i in traits { let did = i.trait_did().unwrap(); let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods); render_impl(w, cx, i, assoc_link, - RenderMode::Normal, containing_item.stable_since(), true, None, false, true)?; + RenderMode::Normal, containing_item.stable_since(), true, None, false, true); } - Ok(()) } fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool) -> String { @@ -2912,11 +2895,11 @@ fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl) -> Ordering { } fn item_trait( - w: &mut fmt::Formatter<'_>, + w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait, -) -> fmt::Result { +) { let bounds = bounds(&t.bounds, false); let types = t.items.iter().filter(|m| m.is_associated_type()).collect::>(); let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::>(); @@ -2925,146 +2908,144 @@ fn item_trait( // Output the trait definition wrap_into_docblock(w, |w| { - write!(w, "
    ")?;
    -        render_attributes(w, it, true)?;
    +        write!(w, "
    ");
    +        render_attributes(w, it, true);
             write!(w, "{}{}{}trait {}{}{}",
                    VisSpace(&it.visibility),
                    UnsafetySpace(t.unsafety),
                    if t.is_auto { "auto " } else { "" },
                    it.name.as_ref().unwrap(),
                    t.generics,
    -               bounds)?;
    +               bounds);
     
             if !t.generics.where_predicates.is_empty() {
    -            write!(w, "{}", WhereClause { gens: &t.generics, indent: 0, end_newline: true })?;
    +            write!(w, "{}", WhereClause { gens: &t.generics, indent: 0, end_newline: true });
             } else {
    -            write!(w, " ")?;
    +            write!(w, " ");
             }
     
             if t.items.is_empty() {
    -            write!(w, "{{ }}")?;
    +            write!(w, "{{ }}");
             } else {
                 // FIXME: we should be using a derived_id for the Anchors here
    -            write!(w, "{{\n")?;
    +            write!(w, "{{\n");
                 for t in &types {
    -                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
    -                write!(w, ";\n")?;
    +                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait);
    +                write!(w, ";\n");
                 }
                 if !types.is_empty() && !consts.is_empty() {
    -                w.write_str("\n")?;
    +                w.write_str("\n");
                 }
                 for t in &consts {
    -                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
    -                write!(w, ";\n")?;
    +                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait);
    +                write!(w, ";\n");
                 }
                 if !consts.is_empty() && !required.is_empty() {
    -                w.write_str("\n")?;
    +                w.write_str("\n");
                 }
                 for (pos, m) in required.iter().enumerate() {
    -                render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?;
    -                write!(w, ";\n")?;
    +                render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait);
    +                write!(w, ";\n");
     
                     if pos < required.len() - 1 {
    -                   write!(w, "
    ")?; + write!(w, "
    "); } } if !required.is_empty() && !provided.is_empty() { - w.write_str("\n")?; + w.write_str("\n"); } for (pos, m) in provided.iter().enumerate() { - render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?; + render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait); match m.inner { clean::MethodItem(ref inner) if !inner.generics.where_predicates.is_empty() => { - write!(w, ",\n {{ ... }}\n")?; + write!(w, ",\n {{ ... }}\n"); }, _ => { - write!(w, " {{ ... }}\n")?; + write!(w, " {{ ... }}\n"); }, } if pos < provided.len() - 1 { - write!(w, "
    ")?; + write!(w, "
    "); } } - write!(w, "}}")?; + write!(w, "}}"); } write!(w, "
    ") - })?; + }); // Trait documentation - document(w, cx, it)?; + document(w, cx, it); fn write_small_section_header( - w: &mut fmt::Formatter<'_>, + w: &mut Buffer, id: &str, title: &str, extra_content: &str, - ) -> fmt::Result { + ) { write!(w, "

    \ {1}\

    {2}", id, title, extra_content) } - fn write_loading_content(w: &mut fmt::Formatter<'_>, extra_content: &str) -> fmt::Result { + fn write_loading_content(w: &mut Buffer, extra_content: &str) { write!(w, "{}Loading content...", extra_content) } - fn trait_item(w: &mut fmt::Formatter<'_>, cx: &Context, m: &clean::Item, t: &clean::Item) - -> fmt::Result { + fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) { let name = m.name.as_ref().unwrap(); let item_type = m.type_(); let id = cx.derive_id(format!("{}.{}", item_type, name)); let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

    {extra}", - extra = render_spotlight_traits(m)?, + extra = render_spotlight_traits(m), id = id, - ns_id = ns_id)?; - render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl)?; - write!(w, "")?; - render_stability_since(w, m, t)?; - write!(w, "

    ")?; - document(w, cx, m)?; - Ok(()) + ns_id = ns_id); + render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl); + write!(w, ""); + render_stability_since(w, m, t); + write!(w, ""); + document(w, cx, m); } if !types.is_empty() { write_small_section_header(w, "associated-types", "Associated Types", - "
    ")?; + "
    "); for t in &types { - trait_item(w, cx, *t, it)?; + trait_item(w, cx, *t, it); } - write_loading_content(w, "
    ")?; + write_loading_content(w, "
    "); } if !consts.is_empty() { write_small_section_header(w, "associated-const", "Associated Constants", - "
    ")?; + "
    "); for t in &consts { - trait_item(w, cx, *t, it)?; + trait_item(w, cx, *t, it); } - write_loading_content(w, "
    ")?; + write_loading_content(w, "
    "); } // Output the documentation for each function individually if !required.is_empty() { write_small_section_header(w, "required-methods", "Required methods", - "
    ")?; + "
    "); for m in &required { - trait_item(w, cx, *m, it)?; + trait_item(w, cx, *m, it); } - write_loading_content(w, "
    ")?; + write_loading_content(w, "
    "); } if !provided.is_empty() { write_small_section_header(w, "provided-methods", "Provided methods", - "
    ")?; + "
    "); for m in &provided { - trait_item(w, cx, *m, it)?; + trait_item(w, cx, *m, it); } - write_loading_content(w, "
    ")?; + write_loading_content(w, "
    "); } // If there are methods directly on this trait object, render them here. - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)?; + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All); let cache = cache(); @@ -3103,7 +3084,7 @@ fn item_trait( concrete.sort_by(compare_impl); if !foreign.is_empty() { - write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "")?; + write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", ""); for implementor in foreign { let assoc_link = AssocItemLink::GotoSource( @@ -3112,44 +3093,44 @@ fn item_trait( ); render_impl(w, cx, &implementor, assoc_link, RenderMode::Normal, implementor.impl_item.stable_since(), false, - None, true, false)?; + None, true, false); } - write_loading_content(w, "")?; + write_loading_content(w, ""); } write_small_section_header(w, "implementors", "Implementors", - "
    ")?; + "
    "); for implementor in concrete { - render_implementor(cx, implementor, w, &implementor_dups)?; + render_implementor(cx, implementor, w, &implementor_dups); } - write_loading_content(w, "
    ")?; + write_loading_content(w, "
    "); if t.auto { write_small_section_header(w, "synthetic-implementors", "Auto implementors", - "
    ")?; + "
    "); for implementor in synthetic { synthetic_types.extend( collect_paths_for_type(implementor.inner_impl().for_.clone()) ); - render_implementor(cx, implementor, w, &implementor_dups)?; + render_implementor(cx, implementor, w, &implementor_dups); } - write_loading_content(w, "
    ")?; + write_loading_content(w, "
    "); } } else { // even without any implementations to write in, we still want the heading and list, so the // implementors javascript file pulled in below has somewhere to write the impls into write_small_section_header(w, "implementors", "Implementors", - "
    ")?; - write_loading_content(w, "
    ")?; + "
    "); + write_loading_content(w, "
    "); if t.auto { write_small_section_header(w, "synthetic-implementors", "Auto implementors", - "
    ")?; - write_loading_content(w, "
    ")?; + "
    "); + write_loading_content(w, "
    "); } } write!(w, r#""#, - as_json(&synthetic_types))?; + as_json(&synthetic_types)); write!(w, r#"