From 48d1be4f46225350bb59f87a46bf2f6cba041013 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 6 May 2019 17:06:59 -0400 Subject: [PATCH 01/17] Test interaction of unions with non-zero/niche-filling optimization Notably this nails down part of the behavior that MaybeUninit assumes, e.g. that a Option> does not take advantage of non-zero optimization, and thus is a safe construct. --- src/test/run-pass/union/union-nonzero.rs | 30 +++++++++++++++++++ src/test/ui/print_type_sizes/niche-filling.rs | 17 +++++++++++ .../ui/print_type_sizes/niche-filling.stdout | 26 ++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 src/test/run-pass/union/union-nonzero.rs diff --git a/src/test/run-pass/union/union-nonzero.rs b/src/test/run-pass/union/union-nonzero.rs new file mode 100644 index 0000000000000..614aa9ec0ce17 --- /dev/null +++ b/src/test/run-pass/union/union-nonzero.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(dead_code)] + +use std::mem::{size_of, transmute}; + +union U1 { + a: A, +} + +union U2 { + a: A, + b: B, +} + +fn main() { + // Unions do not participate in niche-filling/non-zero optimization... + assert!(size_of::>>() > size_of::>()); + assert!(size_of::>>() > size_of::>()); + + // ...even when theoretically possible: + assert!(size_of::>>() > size_of::>()); + assert!(size_of::>>() > size_of::>()); + + // The unused bits of the () variant can have any value. + let zeroed: U2<&u8, ()> = unsafe { transmute(std::ptr::null::()) }; + + if let None = Some(zeroed) { + panic!() + } +} diff --git a/src/test/ui/print_type_sizes/niche-filling.rs b/src/test/ui/print_type_sizes/niche-filling.rs index bed1e32a60158..0127261b2b7d0 100644 --- a/src/test/ui/print_type_sizes/niche-filling.rs +++ b/src/test/ui/print_type_sizes/niche-filling.rs @@ -57,6 +57,15 @@ pub enum Enum4 { Four(D) } +pub union Union1 { + a: A, +} + +pub union Union2 { + a: A, + b: B, +} + #[start] fn start(_: isize, _: *const *const u8) -> isize { let _x: MyOption = Default::default(); @@ -69,5 +78,13 @@ fn start(_: isize, _: *const *const u8) -> isize { let _e: Enum4<(), char, (), ()> = Enum4::One(()); let _f: Enum4<(), (), bool, ()> = Enum4::One(()); let _g: Enum4<(), (), (), MyOption> = Enum4::One(()); + + // Unions do not currently participate in niche filling. + let _h: MyOption> = Default::default(); + + // ...even when theoretically possible. + let _i: MyOption> = Default::default(); + let _j: MyOption> = Default::default(); + 0 } diff --git a/src/test/ui/print_type_sizes/niche-filling.stdout b/src/test/ui/print_type_sizes/niche-filling.stdout index 9cdb2ae4f57e0..301edc0d086b1 100644 --- a/src/test/ui/print_type_sizes/niche-filling.stdout +++ b/src/test/ui/print_type_sizes/niche-filling.stdout @@ -14,6 +14,21 @@ print-type-size field `.post`: 2 bytes print-type-size field `.pre`: 1 bytes print-type-size variant `None`: 0 bytes print-type-size end padding: 1 bytes +print-type-size type: `MyOption>`: 8 bytes, alignment: 4 bytes +print-type-size discriminant: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `MyOption>`: 8 bytes, alignment: 4 bytes +print-type-size discriminant: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `MyOption>`: 8 bytes, alignment: 4 bytes +print-type-size discriminant: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes print-type-size field `.val`: 4 bytes print-type-size field `.post`: 2 bytes @@ -36,6 +51,17 @@ print-type-size type: `MyOption`: 4 bytes, alignment: 4 by print-type-size variant `Some`: 4 bytes print-type-size field `.0`: 4 bytes print-type-size variant `None`: 0 bytes +print-type-size type: `Union1`: 4 bytes, alignment: 4 bytes +print-type-size variant `Union1`: 4 bytes +print-type-size field `.a`: 4 bytes +print-type-size type: `Union2`: 4 bytes, alignment: 4 bytes +print-type-size variant `Union2`: 4 bytes +print-type-size field `.a`: 4 bytes +print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes +print-type-size type: `Union2`: 4 bytes, alignment: 4 bytes +print-type-size variant `Union2`: 4 bytes +print-type-size field `.a`: 4 bytes +print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes print-type-size field `.0`: 4 bytes print-type-size type: `Enum4<(), (), (), MyOption>`: 2 bytes, alignment: 1 bytes From 76c52290214c49a9ba0cf506ac7e636543e087ff Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Tue, 7 May 2019 12:16:33 -0400 Subject: [PATCH 02/17] Document purpose of union-nonzero test --- src/test/run-pass/union/union-nonzero.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/run-pass/union/union-nonzero.rs b/src/test/run-pass/union/union-nonzero.rs index 614aa9ec0ce17..07a58aa7746d1 100644 --- a/src/test/run-pass/union/union-nonzero.rs +++ b/src/test/run-pass/union/union-nonzero.rs @@ -1,6 +1,18 @@ // run-pass #![allow(dead_code)] +// Tests that unions aren't subject to unsafe non-zero/niche-filling optimizations. +// +// For example, if a union `U` can contain both a `&T` and a `*const T`, there's definitely no +// bit-value that an `Option` could reuse as `None`; this test makes sure that isn't done. +// +// Secondly, this tests the status quo to not apply such optimizations to types containing unions +// even if they're theoretically possible. (discussion: https://github.com/rust-lang/rust/issues/36394) +// +// Notably this nails down part of the behavior that `MaybeUninit` assumes: that a +// `Option>` does not take advantage of non-zero optimization, and thus is a safe +// construct. + use std::mem::{size_of, transmute}; union U1 { From aa1db2476a7b6e3155bf40cc48f6bc897575c622 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Tue, 7 May 2019 12:17:28 -0400 Subject: [PATCH 03/17] Add non-non-zero test to union-nonzero test --- src/test/run-pass/union/union-nonzero.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/run-pass/union/union-nonzero.rs b/src/test/run-pass/union/union-nonzero.rs index 07a58aa7746d1..2108cc3a4ea78 100644 --- a/src/test/run-pass/union/union-nonzero.rs +++ b/src/test/run-pass/union/union-nonzero.rs @@ -24,10 +24,18 @@ union U2 { b: B, } +// Option uses a value other than 0 and 1 as None +#[derive(Clone,Copy)] +enum E { + A = 0, + B = 1, +} + fn main() { // Unions do not participate in niche-filling/non-zero optimization... assert!(size_of::>>() > size_of::>()); assert!(size_of::>>() > size_of::>()); + assert!(size_of::>>() > size_of::>()); // ...even when theoretically possible: assert!(size_of::>>() > size_of::>()); From b5febe72bbe10e3a327fa983b06d64354a0954e0 Mon Sep 17 00:00:00 2001 From: chandde Date: Tue, 14 May 2019 17:00:48 -0700 Subject: [PATCH 04/17] Update lib.rs --- src/libtest/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 26612964c308f..765ee12a1d673 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -37,12 +37,12 @@ extern crate libc; use term; // FIXME(#54291): rustc and/or LLVM don't yet support building with panic-unwind -// on aarch64-pc-windows-msvc, so we don't link libtest against +// on aarch64-pc-windows-msvc, or thumbv7a-pc-windows-msvc, so we don't link libtest against // libunwind (for the time being), even though it means that -// libtest won't be fully functional on this platform. +// libtest won't be fully functional on these platforms. // // See also: https://github.com/rust-lang/rust/issues/54190#issuecomment-422904437 -#[cfg(not(all(windows, target_arch = "aarch64")))] +#[cfg(not(any(all(windows, target_arch = "aarch64"), all(windows, target_arch = "arm"))))] extern crate panic_unwind; pub use self::ColorConfig::*; From ba3785ec0a959b074450686dca7bb16182cf8d1a Mon Sep 17 00:00:00 2001 From: Chandler Deng Date: Thu, 16 May 2019 15:05:56 -0700 Subject: [PATCH 05/17] add targetarch for CodegenContext --- src/librustc_codegen_llvm/back/write.rs | 4 ++-- src/librustc_codegen_ssa/back/write.rs | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index cb59cf41a3ca5..66ba95810a625 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -795,10 +795,10 @@ fn create_msvc_imps( return } // The x86 ABI seems to require that leading underscores are added to symbol - // names, so we need an extra underscore on 32-bit. There's also a leading + // names, so we need an extra underscore on x86. There's also a leading // '\x01' here which disables LLVM's symbol mangling (e.g., no extra // underscores added in front). - let prefix = if cgcx.target_pointer_width == "32" { + let prefix = if cgcx.target_arch == "x86" { "\x01__imp__" } else { "\x01__imp_" diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 6320d8a671ddb..1c793996c83db 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -248,6 +248,7 @@ pub struct CodegenContext { pub tm_factory: TargetMachineFactory, pub msvc_imps_needed: bool, pub target_pointer_width: String, + pub target_arch: String, pub debuginfo: config::DebugInfo, // Number of cgus excluding the allocator/metadata modules @@ -1103,6 +1104,7 @@ fn start_executing_work( total_cgus, msvc_imps_needed: msvc_imps_needed(tcx), target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(), + target_arch: tcx.sess.target.target.arch.clone(), debuginfo: tcx.sess.opts.debuginfo, assembler_cmd, }; From 70f78b3f8cd1a1cc7324bbae6b559315e423b2af Mon Sep 17 00:00:00 2001 From: chandde Date: Fri, 17 May 2019 20:45:25 -0700 Subject: [PATCH 06/17] optimize the arm64 OR arm32 check --- src/libtest/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 765ee12a1d673..b64973573c018 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -42,7 +42,7 @@ use term; // libtest won't be fully functional on these platforms. // // See also: https://github.com/rust-lang/rust/issues/54190#issuecomment-422904437 -#[cfg(not(any(all(windows, target_arch = "aarch64"), all(windows, target_arch = "arm"))))] +#[cfg(not(all(windows, any(target_arch = "aarch64", target_arch = "arm"))))] extern crate panic_unwind; pub use self::ColorConfig::*; From 759921e2a0ec87211a0a54ab628f5ba5fbe6e578 Mon Sep 17 00:00:00 2001 From: chandde Date: Sat, 18 May 2019 00:49:54 -0700 Subject: [PATCH 07/17] fix line length --- src/libtest/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index b64973573c018..6c57581a6c250 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -37,9 +37,10 @@ extern crate libc; use term; // FIXME(#54291): rustc and/or LLVM don't yet support building with panic-unwind -// on aarch64-pc-windows-msvc, or thumbv7a-pc-windows-msvc, so we don't link libtest against -// libunwind (for the time being), even though it means that -// libtest won't be fully functional on these platforms. +// on aarch64-pc-windows-msvc, or thumbv7a-pc-windows-msvc +// so we don't link libtest against libunwind (for the time being) +// even though it means that libtest won't be fully functional on +// these platforms. // // See also: https://github.com/rust-lang/rust/issues/54190#issuecomment-422904437 #[cfg(not(all(windows, any(target_arch = "aarch64", target_arch = "arm"))))] From b5d4bd2a07218a6cd61bace73d7910a3f1a117c4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 16 May 2019 18:31:53 +0200 Subject: [PATCH 08/17] Fix lints handling in rustdoc --- src/librustc/lint/mod.rs | 3 ++ src/librustdoc/clean/mod.rs | 7 ++++ .../passes/collect_intra_doc_links.rs | 34 +++++++++++----- src/librustdoc/passes/mod.rs | 19 +++++---- .../lint-missing-doc-code-example.rs | 39 +++++++++++++++++++ .../lint-missing-doc-code-example.stderr | 0 6 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 src/test/rustdoc-ui/lint-missing-doc-code-example.rs create mode 100644 src/test/rustdoc-ui/lint-missing-doc-code-example.stderr diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 68b65f9b4a1cc..9c4683e094634 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -778,6 +778,9 @@ fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) let push = builder.levels.push(&krate.attrs); builder.levels.register_id(hir::CRATE_HIR_ID); + for macro_def in &krate.exported_macros { + builder.levels.register_id(macro_def.hir_id); + } intravisit::walk_crate(&mut builder, krate); builder.levels.pop(push); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e9ccc61280b10..7fe3aecca10c5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3405,6 +3405,7 @@ pub struct Span { pub locol: usize, pub hiline: usize, pub hicol: usize, + pub original: syntax_pos::Span, } impl Span { @@ -3413,8 +3414,13 @@ impl Span { filename: FileName::Anon(0), loline: 0, locol: 0, hiline: 0, hicol: 0, + original: syntax_pos::DUMMY_SP, } } + + pub fn span(&self) -> syntax_pos::Span { + self.original + } } impl Clean for syntax_pos::Span { @@ -3433,6 +3439,7 @@ impl Clean for syntax_pos::Span { locol: lo.col.to_usize(), hiline: hi.line, hicol: hi.col.to_usize(), + original: *self, } } } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 9e108e605c8bb..2c382a1c17596 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -321,7 +321,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { if let Ok(res) = self.resolve(path_str, ns, ¤t_item, parent_node) { res } else { - resolution_failure(cx, &item.attrs, path_str, &dox, link_range); + resolution_failure(cx, &item, path_str, &dox, link_range); // This could just be a normal link or a broken link // we could potentially check if something is // "intra-doc-link-like" and warn in that case. @@ -332,7 +332,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { if let Ok(res) = self.resolve(path_str, ns, ¤t_item, parent_node) { res } else { - resolution_failure(cx, &item.attrs, path_str, &dox, link_range); + resolution_failure(cx, &item, path_str, &dox, link_range); // This could just be a normal link. continue; } @@ -357,7 +357,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { }; if candidates.is_empty() { - resolution_failure(cx, &item.attrs, path_str, &dox, link_range); + resolution_failure(cx, &item, path_str, &dox, link_range); // this could just be a normal link continue; } @@ -368,7 +368,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } else { ambiguity_error( cx, - &item.attrs, + &item, path_str, &dox, link_range, @@ -381,7 +381,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { if let Some(res) = macro_resolve(cx, path_str) { (res, None) } else { - resolution_failure(cx, &item.attrs, path_str, &dox, link_range); + resolution_failure(cx, &item, path_str, &dox, link_range); continue } } @@ -452,16 +452,24 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option { /// line containing the failure as a note as well. fn resolution_failure( cx: &DocContext<'_>, - attrs: &Attributes, + item: &Item, path_str: &str, dox: &str, link_range: Option>, ) { + let hir_id = match cx.as_local_hir_id(item.def_id) { + Some(hir_id) => hir_id, + None => { + // If non-local, no need to check anything. + return; + } + }; + let attrs = &item.attrs; let sp = span_of_attrs(attrs); let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, - hir::CRATE_HIR_ID, + hir_id, sp, &format!("`[{}]` cannot be resolved, ignoring it...", path_str), ); @@ -495,12 +503,20 @@ fn resolution_failure( fn ambiguity_error( cx: &DocContext<'_>, - attrs: &Attributes, + item: &Item, path_str: &str, dox: &str, link_range: Option>, candidates: PerNS>, ) { + let hir_id = match cx.as_local_hir_id(item.def_id) { + Some(hir_id) => hir_id, + None => { + // If non-local, no need to check anything. + return; + } + }; + let attrs = &item.attrs; let sp = span_of_attrs(attrs); let mut msg = format!("`{}` is ", path_str); @@ -532,7 +548,7 @@ fn ambiguity_error( let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, - hir::CRATE_HIR_ID, + hir_id, sp, &msg, ); diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 99aca0634710f..d9af33ac5b622 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -1,7 +1,6 @@ //! Contains information about "passes", used to modify crate information during the documentation //! process. -use rustc::hir; use rustc::hir::def_id::DefId; use rustc::lint as lint; use rustc::middle::privacy::AccessLevels; @@ -314,10 +313,13 @@ pub fn look_for_tests<'tcx>( item: &Item, check_missing_code: bool, ) { - if cx.as_local_hir_id(item.def_id).is_none() { - // If non-local, no need to check anything. - return; - } + let hir_id = match cx.as_local_hir_id(item.def_id) { + Some(hir_id) => hir_id, + None => { + // If non-local, no need to check anything. + return; + } + }; struct Tests { found_tests: usize, @@ -336,10 +338,11 @@ 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 mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::MISSING_DOC_CODE_EXAMPLES, - hir::CRATE_HIR_ID, - span_of_attrs(&item.attrs), + hir_id, + sp, "Missing code example in this documentation"); diag.emit(); } else if check_missing_code == false && @@ -347,7 +350,7 @@ pub fn look_for_tests<'tcx>( !cx.renderinfo.borrow().access_levels.is_doc_reachable(item.def_id) { let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::PRIVATE_DOC_TESTS, - hir::CRATE_HIR_ID, + hir_id, span_of_attrs(&item.attrs), "Documentation test in private item"); diag.emit(); diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.rs b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs new file mode 100644 index 0000000000000..3bb1a2b7bef0b --- /dev/null +++ b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs @@ -0,0 +1,39 @@ +#![deny(missing_docs)] +#![deny(missing_doc_code_examples)] + +//! crate level doc +//! ``` +//! println!("hello"): +//! ``` + + +/// doc +/// +/// ``` +/// println!("hello"); +/// ``` +fn test() { +} + +#[allow(missing_docs)] +mod module1 { +} + +#[allow(missing_doc_code_examples)] +/// doc +mod module2 { + + /// doc + pub fn test() {} +} + +/// doc +/// +/// ``` +/// println!("hello"); +/// ``` +pub mod module3 { + + /// doc + pub fn test() {} +} diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr new file mode 100644 index 0000000000000..e69de29bb2d1d From c78af2bc60fe8611c063c13bea1295c784403234 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 17 May 2019 13:39:20 +0200 Subject: [PATCH 09/17] Update rustdoc-ui tests --- src/test/rustdoc-ui/doc-without-codeblock.rs | 4 +--- .../rustdoc-ui/doc-without-codeblock.stderr | 18 ++++++++++++---- .../lint-missing-doc-code-example.rs | 3 ++- .../lint-missing-doc-code-example.stderr | 21 +++++++++++++++++++ 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/test/rustdoc-ui/doc-without-codeblock.rs b/src/test/rustdoc-ui/doc-without-codeblock.rs index aa3f539ba32a3..4b2a91e9c8127 100644 --- a/src/test/rustdoc-ui/doc-without-codeblock.rs +++ b/src/test/rustdoc-ui/doc-without-codeblock.rs @@ -1,6 +1,4 @@ -//~ ERROR Missing code example in this documentation - -#![deny(missing_doc_code_examples)] +#![deny(missing_doc_code_examples)] //~ ERROR Missing code example in this documentation /// Some docs. //~^ ERROR Missing code example in this documentation diff --git a/src/test/rustdoc-ui/doc-without-codeblock.stderr b/src/test/rustdoc-ui/doc-without-codeblock.stderr index 208bdedf24ddb..23c07c4d32d64 100644 --- a/src/test/rustdoc-ui/doc-without-codeblock.stderr +++ b/src/test/rustdoc-ui/doc-without-codeblock.stderr @@ -1,25 +1,35 @@ error: Missing code example in this documentation + --> $DIR/doc-without-codeblock.rs:1:1 + | +LL | / #![deny(missing_doc_code_examples)] +LL | | +LL | | /// Some docs. +LL | | +... | +LL | | pub fn bar() {} +LL | | } + | |_^ | note: lint level defined here - --> $DIR/doc-without-codeblock.rs:3:9 + --> $DIR/doc-without-codeblock.rs:1:9 | LL | #![deny(missing_doc_code_examples)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: Missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:5:1 + --> $DIR/doc-without-codeblock.rs:3:1 | LL | /// Some docs. | ^^^^^^^^^^^^^^ error: Missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:9:1 + --> $DIR/doc-without-codeblock.rs:7:1 | LL | /// And then, the princess died. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:12:5 + --> $DIR/doc-without-codeblock.rs:10:5 | LL | /// Or maybe not because she saved herself! | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.rs b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs index 3bb1a2b7bef0b..ffe0ddcd8c9b2 100644 --- a/src/test/rustdoc-ui/lint-missing-doc-code-example.rs +++ b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs @@ -16,7 +16,7 @@ fn test() { } #[allow(missing_docs)] -mod module1 { +mod module1 { //~ ERROR } #[allow(missing_doc_code_examples)] @@ -35,5 +35,6 @@ mod module2 { pub mod module3 { /// doc + //~^ ERROR pub fn test() {} } diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr index e69de29bb2d1d..97a52a13e3f65 100644 --- a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr +++ b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr @@ -0,0 +1,21 @@ +error: Missing code example in this documentation + --> $DIR/lint-missing-doc-code-example.rs:19:1 + | +LL | / mod module1 { +LL | | } + | |_^ + | +note: lint level defined here + --> $DIR/lint-missing-doc-code-example.rs:2:9 + | +LL | #![deny(missing_doc_code_examples)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Missing code example in this documentation + --> $DIR/lint-missing-doc-code-example.rs:37:3 + | +LL | /// doc + | ^^^^^^^ + +error: aborting due to 2 previous errors + From 606377740b6022664299b47c8dd8d3e65017021d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 18 May 2019 12:42:13 +0200 Subject: [PATCH 10/17] Fix tests not running locally --- src/bootstrap/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 7826ac9471806..be0af8be7b272 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -683,7 +683,7 @@ impl Step for RustdocUi { target: self.target, mode: "ui", suite: "rustdoc-ui", - path: None, + path: Some("src/test/rustdoc-ui"), compare_mode: None, }) } From a91ad60158647c1f6a89b9c01915279ce9314a65 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Sat, 18 May 2019 22:27:33 -0400 Subject: [PATCH 11/17] =?UTF-8?q?Make=20clear=20that=20status=20quo=20?= =?UTF-8?q?=E2=89=A0=20guarantee?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/run-pass/union/union-nonzero.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/run-pass/union/union-nonzero.rs b/src/test/run-pass/union/union-nonzero.rs index 2108cc3a4ea78..bd84b46bf3d23 100644 --- a/src/test/run-pass/union/union-nonzero.rs +++ b/src/test/run-pass/union/union-nonzero.rs @@ -6,8 +6,9 @@ // For example, if a union `U` can contain both a `&T` and a `*const T`, there's definitely no // bit-value that an `Option` could reuse as `None`; this test makes sure that isn't done. // -// Secondly, this tests the status quo to not apply such optimizations to types containing unions -// even if they're theoretically possible. (discussion: https://github.com/rust-lang/rust/issues/36394) +// Secondly, this tests the status quo (not a guarantee; subject to change!) to not apply such +// optimizations to types containing unions even if they're theoretically possible. (discussion: +// https://github.com/rust-lang/rust/issues/36394) // // Notably this nails down part of the behavior that `MaybeUninit` assumes: that a // `Option>` does not take advantage of non-zero optimization, and thus is a safe From 6bb3980e7a7b6ecf891e2309cc858fe167d1a651 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 19 May 2019 13:00:28 +0100 Subject: [PATCH 12/17] Stop using gensyms in HIR lowering These names aren't ever handled by resolve, so there's no reason to make them gensyms. --- src/librustc/hir/lowering.rs | 37 +++++++++++++++--------------------- src/libsyntax_pos/symbol.rs | 7 +++++++ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 970f6ba017735..3ec4d4e8cc8f6 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -855,10 +855,6 @@ impl<'a> LoweringContext<'a> { self.sess.diagnostic() } - fn str_to_ident(&self, s: &'static str) -> Ident { - Ident::with_empty_ctxt(Symbol::gensym(s)) - } - fn with_anonymous_lifetime_mode( &mut self, anonymous_lifetime_mode: AnonymousLifetimeMode, @@ -4621,18 +4617,18 @@ impl<'a> LoweringContext<'a> { ); head.span = desugared_span; - let iter = self.str_to_ident("iter"); + let iter = Ident::with_empty_ctxt(sym::iter); - let next_ident = self.str_to_ident("__next"); + let next_ident = Ident::with_empty_ctxt(sym::__next); let (next_pat, next_pat_hid) = self.pat_ident_binding_mode( desugared_span, next_ident, hir::BindingAnnotation::Mutable, ); - // `::std::option::Option::Some(val) => next = val` + // `::std::option::Option::Some(val) => __next = val` let pat_arm = { - let val_ident = self.str_to_ident("val"); + let val_ident = Ident::with_empty_ctxt(sym::val); let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident); let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid)); let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid)); @@ -4771,17 +4767,13 @@ impl<'a> LoweringContext<'a> { let unstable_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::QuestionMark, e.span, - Some(vec![ - Symbol::intern("try_trait") - ].into()), + Some(vec![sym::try_trait].into()), ); let try_span = self.sess.source_map().end_point(e.span); let try_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::QuestionMark, try_span, - Some(vec![ - Symbol::intern("try_trait") - ].into()), + Some(vec![sym::try_trait].into()), ); // `Try::into_result()` @@ -4802,7 +4794,8 @@ impl<'a> LoweringContext<'a> { // `allow(unreachable_code)` let allow = { let allow_ident = Ident::with_empty_ctxt(sym::allow).with_span_pos(e.span); - let uc_ident = Ident::from_str("unreachable_code").with_span_pos(e.span); + let uc_ident = Ident::with_empty_ctxt(sym::unreachable_code) + .with_span_pos(e.span); let uc_nested = attr::mk_nested_word_item(uc_ident); attr::mk_list_item(e.span, allow_ident, vec![uc_nested]) }; @@ -4812,7 +4805,7 @@ impl<'a> LoweringContext<'a> { // `Ok(val) => #[allow(unreachable_code)] val,` let ok_arm = { - let val_ident = self.str_to_ident("val"); + let val_ident = Ident::with_empty_ctxt(sym::val); let (val_pat, val_pat_nid) = self.pat_ident(e.span, val_ident); let val_expr = P(self.expr_ident_with_attrs( e.span, @@ -4828,7 +4821,7 @@ impl<'a> LoweringContext<'a> { // `Err(err) => #[allow(unreachable_code)] // return Try::from_error(From::from(err)),` let err_arm = { - let err_ident = self.str_to_ident("err"); + let err_ident = Ident::with_empty_ctxt(sym::err); let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident); let from_expr = { let from_path = &[sym::convert, sym::From, sym::from]; @@ -5552,7 +5545,7 @@ impl<'a> LoweringContext<'a> { // match ::std::future::poll_with_tls_context(unsafe { // ::std::pin::Pin::new_unchecked(&mut pinned) // }) { - // ::std::task::Poll::Ready(x) => break x, + // ::std::task::Poll::Ready(result) => break result, // ::std::task::Poll::Pending => {}, // } // yield (); @@ -5580,12 +5573,12 @@ impl<'a> LoweringContext<'a> { let gen_future_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::Await, await_span, - Some(vec![Symbol::intern("gen_future")].into()), + Some(vec![sym::gen_future].into()), ); // let mut pinned = ; let expr = P(self.lower_expr(expr)); - let pinned_ident = self.str_to_ident("pinned"); + let pinned_ident = Ident::with_empty_ctxt(sym::pinned); let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode( span, pinned_ident, @@ -5621,11 +5614,11 @@ impl<'a> LoweringContext<'a> { )) }; - // `::std::task::Poll::Ready(x) => break x` + // `::std::task::Poll::Ready(result) => break result` let loop_node_id = self.sess.next_node_id(); let loop_hir_id = self.lower_node_id(loop_node_id); let ready_arm = { - let x_ident = self.str_to_ident("x"); + let x_ident = Ident::with_empty_ctxt(sym::result); let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident); let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid)); let ready_pat = self.pat_std_enum( diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 01b126f48b327..97b22282668ad 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -229,6 +229,7 @@ symbols! { eh_personality, eh_unwind_resume, enable, + err, Err, except, exclusive_range_pattern, @@ -260,6 +261,7 @@ symbols! { fundamental, future, Future, + gen_future, generators, generic_associated_types, generic_param_attrs, @@ -361,6 +363,7 @@ symbols! { never, never_type, next, + __next, nll, no_builtins, no_core, @@ -406,6 +409,7 @@ symbols! { Pending, pin, Pin, + pinned, platform_intrinsics, plugin, plugin_registrar, @@ -569,6 +573,7 @@ symbols! { trivial_bounds, Try, try_blocks, + try_trait, tuple_indexing, ty, type_alias_enum_variants, @@ -587,6 +592,7 @@ symbols! { uniform_paths, universal_impl_trait, unmarked_api, + unreachable_code, unrestricted_attribute_tokens, unsafe_destructor_blind_to_params, unsafe_no_drop_flag, @@ -601,6 +607,7 @@ symbols! { use_nested_groups, usize, v1, + val, vis, visible_private_types, volatile, From a759565763c51ed856937d3a8b520d26e5270ba2 Mon Sep 17 00:00:00 2001 From: VeryTastyTomato Date: Sun, 19 May 2019 13:51:46 +0000 Subject: [PATCH 13/17] Fix data types indication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the data types indication in basic examples of the Trait std::fmt::LowerExp and std::fmt::UpperExp. Since there aren’t any type annotation on the let statement using the number 42.0, they are of type f64 according to The Book: https://doc.rust-lang.org/book/ch03-02-data-types.html#floating-point-types --- src/libcore/fmt/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 43c1a3b7767ab..2f6d745d146d6 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -886,7 +886,7 @@ pub trait Pointer { /// /// # Examples /// -/// Basic usage with `i32`: +/// Basic usage with `f64`: /// /// ``` /// let x = 42.0; // 42.0 is '4.2e1' in scientific notation @@ -929,7 +929,7 @@ pub trait LowerExp { /// /// # Examples /// -/// Basic usage with `f32`: +/// Basic usage with `f64`: /// /// ``` /// let x = 42.0; // 42.0 is '4.2E1' in scientific notation From 8e99c76089ecb69479532e22ae2879e3bb1b3d68 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sat, 11 May 2019 10:55:34 -0400 Subject: [PATCH 14/17] [const-prop] Support propagating into Assert's `cond` Operand --- src/librustc_mir/transform/const_prop.rs | 146 +++++++++++---------- src/test/mir-opt/const_prop/array_index.rs | 2 +- src/test/mir-opt/const_prop/checked_add.rs | 2 +- 3 files changed, 81 insertions(+), 69 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 4e214c3c7253e..0247ffbb9d154 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -656,75 +656,87 @@ impl<'b, 'a, 'tcx> MutVisitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { location: Location, ) { self.super_terminator(terminator, location); - let source_info = terminator.source_info;; - if let TerminatorKind::Assert { expected, msg, cond, .. } = &terminator.kind { - if let Some(value) = self.eval_operand(&cond, source_info) { - trace!("assertion on {:?} should be {:?}", value, expected); - let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected)); - if expected != self.ecx.read_scalar(value).unwrap() { - // poison all places this operand references so that further code - // doesn't use the invalid value - match cond { - Operand::Move(ref place) | Operand::Copy(ref place) => { - let mut place = place; - while let Place::Projection(ref proj) = *place { - place = &proj.base; - } - if let Place::Base(PlaceBase::Local(local)) = *place { - self.places[local] = None; - } - }, - Operand::Constant(_) => {} + let source_info = terminator.source_info; + match &mut terminator.kind { + TerminatorKind::Assert { expected, msg, ref mut cond, .. } => { + if let Some(value) = self.eval_operand(&cond, source_info) { + trace!("assertion on {:?} should be {:?}", value, expected); + let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected)); + let value_const = self.ecx.read_scalar(value).unwrap(); + if expected != value_const { + // poison all places this operand references so that further code + // doesn't use the invalid value + match cond { + Operand::Move(ref place) | Operand::Copy(ref place) => { + let mut place = place; + while let Place::Projection(ref proj) = *place { + place = &proj.base; + } + if let Place::Base(PlaceBase::Local(local)) = *place { + self.places[local] = None; + } + }, + Operand::Constant(_) => {} + } + let span = terminator.source_info.span; + let hir_id = self + .tcx + .hir() + .as_local_hir_id(self.source.def_id()) + .expect("some part of a failing const eval must be local"); + use rustc::mir::interpret::InterpError::*; + let msg = match msg { + Overflow(_) | + OverflowNeg | + DivisionByZero | + RemainderByZero => msg.description().to_owned(), + BoundsCheck { ref len, ref index } => { + let len = self + .eval_operand(len, source_info) + .expect("len must be const"); + let len = match self.ecx.read_scalar(len) { + Ok(ScalarMaybeUndef::Scalar(Scalar::Bits { + bits, .. + })) => bits, + other => bug!("const len not primitive: {:?}", other), + }; + let index = self + .eval_operand(index, source_info) + .expect("index must be const"); + let index = match self.ecx.read_scalar(index) { + Ok(ScalarMaybeUndef::Scalar(Scalar::Bits { + bits, .. + })) => bits, + other => bug!("const index not primitive: {:?}", other), + }; + format!( + "index out of bounds: \ + the len is {} but the index is {}", + len, + index, + ) + }, + // Need proper const propagator for these + _ => return, + }; + self.tcx.lint_hir( + ::rustc::lint::builtin::CONST_ERR, + hir_id, + span, + &msg, + ); + } else { + if let ScalarMaybeUndef::Scalar(scalar) = value_const { + *cond = self.operand_from_scalar( + scalar, + self.tcx.types.bool, + source_info.span, + ); + } } - let span = terminator.source_info.span; - let hir_id = self - .tcx - .hir() - .as_local_hir_id(self.source.def_id()) - .expect("some part of a failing const eval must be local"); - use rustc::mir::interpret::InterpError::*; - let msg = match msg { - Overflow(_) | - OverflowNeg | - DivisionByZero | - RemainderByZero => msg.description().to_owned(), - BoundsCheck { ref len, ref index } => { - let len = self - .eval_operand(len, source_info) - .expect("len must be const"); - let len = match self.ecx.read_scalar(len) { - Ok(ScalarMaybeUndef::Scalar(Scalar::Bits { - bits, .. - })) => bits, - other => bug!("const len not primitive: {:?}", other), - }; - let index = self - .eval_operand(index, source_info) - .expect("index must be const"); - let index = match self.ecx.read_scalar(index) { - Ok(ScalarMaybeUndef::Scalar(Scalar::Bits { - bits, .. - })) => bits, - other => bug!("const index not primitive: {:?}", other), - }; - format!( - "index out of bounds: \ - the len is {} but the index is {}", - len, - index, - ) - }, - // Need proper const propagator for these - _ => return, - }; - self.tcx.lint_hir( - ::rustc::lint::builtin::CONST_ERR, - hir_id, - span, - &msg, - ); } - } + }, + _ => {} } } } diff --git a/src/test/mir-opt/const_prop/array_index.rs b/src/test/mir-opt/const_prop/array_index.rs index 4b97af68ff08a..dd22eb5d604ea 100644 --- a/src/test/mir-opt/const_prop/array_index.rs +++ b/src/test/mir-opt/const_prop/array_index.rs @@ -23,7 +23,7 @@ fn main() { // bb0: { // ... // _5 = const true; -// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb1; +// assert(const true, "index out of bounds: the len is move _4 but the index is _3") -> bb1; // } // bb1: { // _1 = _2[_3]; diff --git a/src/test/mir-opt/const_prop/checked_add.rs b/src/test/mir-opt/const_prop/checked_add.rs index 0718316307c5e..fe98cf24eec00 100644 --- a/src/test/mir-opt/const_prop/checked_add.rs +++ b/src/test/mir-opt/const_prop/checked_add.rs @@ -16,6 +16,6 @@ fn main() { // bb0: { // ... // _2 = (const 2u32, const false); -// assert(!move (_2.1: bool), "attempt to add with overflow") -> bb1; +// assert(!const false, "attempt to add with overflow") -> bb1; // } // END rustc.main.ConstProp.after.mir From 3f5c743b531e948788db18ce8d514de06113cb35 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sat, 11 May 2019 11:24:14 -0400 Subject: [PATCH 15/17] [const-prop] Support propagating into SwitchInt's `discr` Operand --- src/librustc_mir/transform/const_prop.rs | 7 +++++ src/test/mir-opt/const_prop/switch_int.rs | 38 +++++++++++++++++++++++ src/test/mir-opt/simplify_if.rs | 8 ++--- 3 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 src/test/mir-opt/const_prop/switch_int.rs diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 0247ffbb9d154..023b7132bd58d 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -736,6 +736,13 @@ impl<'b, 'a, 'tcx> MutVisitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { } } }, + TerminatorKind::SwitchInt { ref mut discr, switch_ty, .. } => { + if let Some(value) = self.eval_operand(&discr, source_info) { + if let ScalarMaybeUndef::Scalar(scalar) = self.ecx.read_scalar(value).unwrap() { + *discr = self.operand_from_scalar(scalar, switch_ty, source_info.span); + } + } + }, _ => {} } } diff --git a/src/test/mir-opt/const_prop/switch_int.rs b/src/test/mir-opt/const_prop/switch_int.rs new file mode 100644 index 0000000000000..0df1112ec3eb7 --- /dev/null +++ b/src/test/mir-opt/const_prop/switch_int.rs @@ -0,0 +1,38 @@ +#[inline(never)] +fn foo(_: i32) { } + +fn main() { + match 1 { + 1 => foo(0), + _ => foo(-1), + } +} + +// END RUST SOURCE +// START rustc.main.ConstProp.before.mir +// bb0: { +// ... +// _1 = const 1i32; +// switchInt(_1) -> [1i32: bb1, otherwise: bb2]; +// } +// END rustc.main.ConstProp.before.mir +// START rustc.main.ConstProp.after.mir +// bb0: { +// ... +// switchInt(const 1i32) -> [1i32: bb1, otherwise: bb2]; +// } +// END rustc.main.ConstProp.after.mir +// START rustc.main.SimplifyBranches-after-const-prop.before.mir +// bb0: { +// ... +// _1 = const 1i32; +// switchInt(const 1i32) -> [1i32: bb1, otherwise: bb2]; +// } +// END rustc.main.SimplifyBranches-after-const-prop.before.mir +// START rustc.main.SimplifyBranches-after-const-prop.after.mir +// bb0: { +// ... +// _1 = const 1i32; +// goto -> bb1; +// } +// END rustc.main.SimplifyBranches-after-const-prop.after.mir diff --git a/src/test/mir-opt/simplify_if.rs b/src/test/mir-opt/simplify_if.rs index b2a99a6d446bb..35512b94c0c8c 100644 --- a/src/test/mir-opt/simplify_if.rs +++ b/src/test/mir-opt/simplify_if.rs @@ -5,15 +5,15 @@ fn main() { } // END RUST SOURCE -// START rustc.main.SimplifyBranches-after-copy-prop.before.mir +// START rustc.main.SimplifyBranches-after-const-prop.before.mir // bb0: { // ... // switchInt(const false) -> [false: bb3, otherwise: bb1]; // } -// END rustc.main.SimplifyBranches-after-copy-prop.before.mir -// START rustc.main.SimplifyBranches-after-copy-prop.after.mir +// END rustc.main.SimplifyBranches-after-const-prop.before.mir +// START rustc.main.SimplifyBranches-after-const-prop.after.mir // bb0: { // ... // goto -> bb3; // } -// END rustc.main.SimplifyBranches-after-copy-prop.after.mir +// END rustc.main.SimplifyBranches-after-const-prop.after.mir From 2baab0eaaa8daa0f972b580748815db970ca547d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sat, 11 May 2019 12:28:53 -0400 Subject: [PATCH 16/17] [const-prop] Remove catch all match and add FIXME --- src/librustc_mir/transform/const_prop.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 023b7132bd58d..86c7f7bbdedcc 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -743,7 +743,20 @@ impl<'b, 'a, 'tcx> MutVisitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { } } }, - _ => {} + //none of these have Operands to const-propagate + TerminatorKind::Goto { .. } | + TerminatorKind::Resume | + TerminatorKind::Abort | + TerminatorKind::Return | + TerminatorKind::Unreachable | + TerminatorKind::Drop { .. } | + TerminatorKind::DropAndReplace { .. } | + TerminatorKind::Yield { .. } | + TerminatorKind::GeneratorDrop | + TerminatorKind::FalseEdges { .. } | + TerminatorKind::FalseUnwind { .. } => { } + //FIXME(wesleywiser) Call does have Operands that could be const-propagated + TerminatorKind::Call { .. } => { } } } } From ec853ba026261bc1c8c53a99d210c02f88fde54f Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sat, 11 May 2019 12:33:10 -0400 Subject: [PATCH 17/17] [const-prop] Don't const-prop into terminators unless mir-opt-level >= 2 --- src/librustc_mir/transform/const_prop.rs | 29 ++++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 86c7f7bbdedcc..8f3dd72c4f245 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -546,6 +546,10 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { } } } + + fn should_const_prop(&self) -> bool { + self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 + } } fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -639,7 +643,7 @@ impl<'b, 'a, 'tcx> MutVisitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { assert!(self.places[local].is_none()); self.places[local] = Some(value); - if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { + if self.should_const_prop() { self.replace_with_const(rval, value, statement.source_info.span); } } @@ -726,20 +730,25 @@ impl<'b, 'a, 'tcx> MutVisitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { &msg, ); } else { - if let ScalarMaybeUndef::Scalar(scalar) = value_const { - *cond = self.operand_from_scalar( - scalar, - self.tcx.types.bool, - source_info.span, - ); + if self.should_const_prop() { + if let ScalarMaybeUndef::Scalar(scalar) = value_const { + *cond = self.operand_from_scalar( + scalar, + self.tcx.types.bool, + source_info.span, + ); + } } } } }, TerminatorKind::SwitchInt { ref mut discr, switch_ty, .. } => { - if let Some(value) = self.eval_operand(&discr, source_info) { - if let ScalarMaybeUndef::Scalar(scalar) = self.ecx.read_scalar(value).unwrap() { - *discr = self.operand_from_scalar(scalar, switch_ty, source_info.span); + if self.should_const_prop() { + if let Some(value) = self.eval_operand(&discr, source_info) { + if let ScalarMaybeUndef::Scalar(scalar) = + self.ecx.read_scalar(value).unwrap() { + *discr = self.operand_from_scalar(scalar, switch_ty, source_info.span); + } } } },