]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #69644 - ecstatic-morse:unified-dataflow-cleanup, r=eddyb
authorDylan DPC <dylan.dpc@gmail.com>
Fri, 27 Mar 2020 00:23:47 +0000 (01:23 +0100)
committerGitHub <noreply@github.com>
Fri, 27 Mar 2020 00:23:47 +0000 (01:23 +0100)
Remove framework in `dataflow/mod.rs` in favor of "generic" one

This is the culmination of the work described in rust-lang/compiler-team#202. All dataflow analyses (including the one in `clippy`) have been ported to use the framework in `dataflow/generic`, which can efficiently handle both gen/kill and generic problems. This PR moves the framework in `dataflow/generic` to `dataflow/framework`, and removes the gen/kill framework in `dataflow/mod.rs`.

More comprehensive documentation for the new framework is tracked in rust-lang/rustc-guide#564.

`clippy` will need to change the path it uses to import the dataflow analysis traits.

15 files changed:
src/librustc_codegen_llvm/back/write.rs
src/librustc_codegen_ssa/back/write.rs
src/librustc_error_codes/error_codes/E0459.md
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/lib.rs
src/librustc_mir_build/hair/pattern/_match.rs
src/librustc_mir_build/hair/pattern/check_match.rs
src/librustc_parse/parser/item.rs
src/librustc_target/spec/mod.rs
src/test/ui/or-patterns/issue-70413-no-unreachable-pat-and-guard.rs [new file with mode: 0644]
src/test/ui/parser/default-on-wrong-item-kind.stderr
src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr
src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr

index 5759eb2991a817d02781e84c1992aa4d21b2abdc..1557630fc7afdaeb5cde12d33a9ee5536497f04e 100644 (file)
@@ -16,7 +16,9 @@
 use log::debug;
 use rustc::bug;
 use rustc::ty::TyCtxt;
-use rustc_codegen_ssa::back::write::{run_assembler, CodegenContext, EmbedBitcode, ModuleConfig};
+use rustc_codegen_ssa::back::write::{
+    run_assembler, BitcodeSection, CodegenContext, EmitObj, ModuleConfig,
+};
 use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, RLIB_BYTECODE_EXTENSION};
 use rustc_data_structures::small_c_str::SmallCStr;
@@ -651,7 +653,7 @@ unsafe fn with_codegen<'ll, F, R>(
             let thin = ThinBuffer::new(llmod);
             let data = thin.data();
 
-            if config.emit_bc || config.obj_is_bitcode {
+            if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
                 let _timer = cgcx.prof.generic_activity_with_arg(
                     "LLVM_module_codegen_emit_bitcode",
                     &module.name[..],
@@ -662,7 +664,7 @@ unsafe fn with_codegen<'ll, F, R>(
                 }
             }
 
-            if config.embed_bitcode == EmbedBitcode::Full {
+            if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
                 let _timer = cgcx.prof.generic_activity_with_arg(
                     "LLVM_module_codegen_embed_bitcode",
                     &module.name[..],
@@ -682,7 +684,7 @@ unsafe fn with_codegen<'ll, F, R>(
                     diag_handler.err(&msg);
                 }
             }
-        } else if config.embed_bitcode == EmbedBitcode::Marker {
+        } else if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Marker) {
             embed_bitcode(cgcx, llcx, llmod, None);
         }
 
@@ -732,9 +734,9 @@ extern "C" fn demangle_callback(
             })?;
         }
 
-        let config_emit_normal_obj = config.emit_obj && !config.obj_is_bitcode;
+        let config_emit_object_code = matches!(config.emit_obj, EmitObj::ObjectCode(_));
 
-        if config.emit_asm || (config_emit_normal_obj && config.no_integrated_as) {
+        if config.emit_asm || (config_emit_object_code && config.no_integrated_as) {
             let _timer = cgcx
                 .prof
                 .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]);
@@ -743,60 +745,65 @@ extern "C" fn demangle_callback(
             // We can't use the same module for asm and binary output, because that triggers
             // various errors like invalid IR or broken binaries, so we might have to clone the
             // module to produce the asm output
-            let llmod = if config.emit_obj { llvm::LLVMCloneModule(llmod) } else { llmod };
+            let llmod = if config_emit_object_code { llvm::LLVMCloneModule(llmod) } else { llmod };
             with_codegen(tm, llmod, config.no_builtins, |cpm| {
                 write_output_file(diag_handler, tm, cpm, llmod, &path, llvm::FileType::AssemblyFile)
             })?;
         }
 
-        if config_emit_normal_obj {
-            if !config.no_integrated_as {
-                let _timer = cgcx
-                    .prof
-                    .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]);
-                with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                    write_output_file(
-                        diag_handler,
-                        tm,
-                        cpm,
-                        llmod,
-                        &obj_out,
-                        llvm::FileType::ObjectFile,
-                    )
-                })?;
-            } else {
-                let _timer = cgcx
-                    .prof
-                    .generic_activity_with_arg("LLVM_module_codegen_asm_to_obj", &module.name[..]);
-                let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
-                run_assembler(cgcx, diag_handler, &assembly, &obj_out);
-
-                if !config.emit_asm && !cgcx.save_temps {
-                    drop(fs::remove_file(&assembly));
+        match config.emit_obj {
+            EmitObj::ObjectCode(_) => {
+                if !config.no_integrated_as {
+                    let _timer = cgcx.prof.generic_activity_with_arg(
+                        "LLVM_module_codegen_emit_obj",
+                        &module.name[..],
+                    );
+                    with_codegen(tm, llmod, config.no_builtins, |cpm| {
+                        write_output_file(
+                            diag_handler,
+                            tm,
+                            cpm,
+                            llmod,
+                            &obj_out,
+                            llvm::FileType::ObjectFile,
+                        )
+                    })?;
+                } else {
+                    let _timer = cgcx.prof.generic_activity_with_arg(
+                        "LLVM_module_codegen_asm_to_obj",
+                        &module.name[..],
+                    );
+                    let assembly =
+                        cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
+                    run_assembler(cgcx, diag_handler, &assembly, &obj_out);
+
+                    if !config.emit_asm && !cgcx.save_temps {
+                        drop(fs::remove_file(&assembly));
+                    }
                 }
             }
-        }
 
-        if config.obj_is_bitcode {
-            if config.emit_obj {
+            EmitObj::Bitcode => {
                 debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
                 if let Err(e) = link_or_copy(&bc_out, &obj_out) {
                     diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
                 }
-            }
 
-            if !config.emit_bc {
-                debug!("removing_bitcode {:?}", bc_out);
-                if let Err(e) = fs::remove_file(&bc_out) {
-                    diag_handler.err(&format!("failed to remove bitcode: {}", e));
+                if !config.emit_bc {
+                    debug!("removing_bitcode {:?}", bc_out);
+                    if let Err(e) = fs::remove_file(&bc_out) {
+                        diag_handler.err(&format!("failed to remove bitcode: {}", e));
+                    }
                 }
             }
+
+            EmitObj::None => {}
         }
 
         drop(handlers);
     }
     Ok(module.into_compiled_module(
-        config.emit_obj,
+        config.emit_obj != EmitObj::None,
         config.emit_bc,
         config.emit_bc_compressed,
         &cgcx.output_filenames,
index a4b5acdcd18a2123a2bfbdb1cdf4cff3cae5898d..e9b3bf026b2ba5499977e91bbc8ddc1c99372129 100644 (file)
 
 const PRE_LTO_BC_EXT: &str = "pre-lto.bc";
 
-/// The kind of bitcode to embed in object files.
-#[derive(PartialEq)]
-pub enum EmbedBitcode {
+/// What kind of object file to emit.
+#[derive(Clone, Copy, PartialEq)]
+pub enum EmitObj {
+    // No object file.
     None,
+
+    // Just uncompressed llvm bitcode. Provides easy compatibility with
+    // emscripten's ecc compiler, when used as the linker.
+    Bitcode,
+
+    // Object code, possibly augmented with a bitcode section.
+    ObjectCode(BitcodeSection),
+}
+
+/// What kind of llvm bitcode section to embed in an object file.
+#[derive(Clone, Copy, PartialEq)]
+pub enum BitcodeSection {
+    // No bitcode section.
+    None,
+
+    // An empty bitcode section (to placate tools such as the iOS linker that
+    // require this section even if they don't use it).
     Marker,
+
+    // A full, uncompressed bitcode section.
     Full,
 }
 
@@ -84,7 +104,7 @@ pub struct ModuleConfig {
     pub emit_bc_compressed: bool,
     pub emit_ir: bool,
     pub emit_asm: bool,
-    pub emit_obj: bool,
+    pub emit_obj: EmitObj,
     // Miscellaneous flags.  These are mostly copied from command-line
     // options.
     pub verify_llvm_ir: bool,
@@ -96,12 +116,7 @@ pub struct ModuleConfig {
     pub merge_functions: bool,
     pub inline_threshold: Option<usize>,
     pub new_llvm_pass_manager: Option<bool>,
-    // Instead of creating an object file by doing LLVM codegen, just
-    // make the object file bitcode. Provides easy compatibility with
-    // emscripten's ecc compiler, when used as the linker.
-    pub obj_is_bitcode: bool,
     pub no_integrated_as: bool,
-    pub embed_bitcode: EmbedBitcode,
 }
 
 impl ModuleConfig {
@@ -124,9 +139,7 @@ fn new(passes: Vec<String>) -> ModuleConfig {
             emit_bc_compressed: false,
             emit_ir: false,
             emit_asm: false,
-            emit_obj: false,
-            obj_is_bitcode: false,
-            embed_bitcode: EmbedBitcode::None,
+            emit_obj: EmitObj::None,
             no_integrated_as: false,
 
             verify_llvm_ir: false,
@@ -147,17 +160,6 @@ fn set_flags(&mut self, sess: &Session, no_builtins: bool) {
         self.no_builtins = no_builtins || sess.target.target.options.no_builtins;
         self.inline_threshold = sess.opts.cg.inline_threshold;
         self.new_llvm_pass_manager = sess.opts.debugging_opts.new_llvm_pass_manager;
-        self.obj_is_bitcode =
-            sess.target.target.options.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled();
-        self.embed_bitcode =
-            if sess.target.target.options.embed_bitcode || sess.opts.debugging_opts.embed_bitcode {
-                match sess.opts.optimize {
-                    config::OptLevel::No | config::OptLevel::Less => EmbedBitcode::Marker,
-                    _ => EmbedBitcode::Full,
-                }
-            } else {
-                EmbedBitcode::None
-            };
 
         // Copy what clang does by turning on loop vectorization at O2 and
         // slp vectorization at O3. Otherwise configure other optimization aspects
@@ -194,9 +196,9 @@ fn set_flags(&mut self, sess: &Session, no_builtins: bool) {
 
     pub fn bitcode_needed(&self) -> bool {
         self.emit_bc
-            || self.obj_is_bitcode
             || self.emit_bc_compressed
-            || self.embed_bitcode == EmbedBitcode::Full
+            || self.emit_obj == EmitObj::Bitcode
+            || self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full)
     }
 }
 
@@ -397,6 +399,20 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
         allocator_config.emit_bc_compressed = true;
     }
 
+    let emit_obj =
+        if sess.target.target.options.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled() {
+            EmitObj::Bitcode
+        } else if sess.opts.debugging_opts.embed_bitcode {
+            match sess.opts.optimize {
+                config::OptLevel::No | config::OptLevel::Less => {
+                    EmitObj::ObjectCode(BitcodeSection::Marker)
+                }
+                _ => EmitObj::ObjectCode(BitcodeSection::Full),
+            }
+        } else {
+            EmitObj::ObjectCode(BitcodeSection::None)
+        };
+
     modules_config.emit_pre_lto_bc = need_pre_lto_bitcode_for_incr_comp(sess);
 
     modules_config.no_integrated_as =
@@ -416,20 +432,20 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
                 // could be invoked specially with output_type_assembly, so
                 // in this case we still want the metadata object file.
                 if !sess.opts.output_types.contains_key(&OutputType::Assembly) {
-                    metadata_config.emit_obj = true;
-                    allocator_config.emit_obj = true;
+                    metadata_config.emit_obj = emit_obj;
+                    allocator_config.emit_obj = emit_obj;
                 }
             }
             OutputType::Object => {
-                modules_config.emit_obj = true;
+                modules_config.emit_obj = emit_obj;
             }
             OutputType::Metadata => {
-                metadata_config.emit_obj = true;
+                metadata_config.emit_obj = emit_obj;
             }
             OutputType::Exe => {
-                modules_config.emit_obj = true;
-                metadata_config.emit_obj = true;
-                allocator_config.emit_obj = true;
+                modules_config.emit_obj = emit_obj;
+                metadata_config.emit_obj = emit_obj;
+                allocator_config.emit_obj = emit_obj;
             }
             OutputType::Mir => {}
             OutputType::DepInfo => {}
@@ -880,7 +896,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
         }
     }
 
-    assert_eq!(object.is_some(), module_config.emit_obj);
+    assert_eq!(object.is_some(), module_config.emit_obj != EmitObj::None);
     assert_eq!(bytecode.is_some(), module_config.emit_bc);
     assert_eq!(bytecode_compressed.is_some(), module_config.emit_bc_compressed);
 
index 580cbf1e1c6ed3afea7e0a3535b8f0460e88bc8a..6f75f2a99a563409ec581258fd33ae1d4a116842 100644 (file)
@@ -1,4 +1,6 @@
-A link was used without a name parameter. Erroneous code example:
+A link was used without a name parameter.
+
+Erroneous code example:
 
 ```compile_fail,E0459
 #[link(kind = "dylib")] extern {}
index f7327825ca4b76be26a6a59975bd46b5b57f0f6c..24176427ba526aebb9fcc722b28329a028283b95 100644 (file)
@@ -229,6 +229,8 @@ fn cast_from_float<F>(
             // float -> uint
             Uint(t) => {
                 let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits());
+                // `to_u128` is a saturating cast, which is what we need
+                // (https://doc.rust-lang.org/nightly/nightly-rustc/rustc_apfloat/trait.Float.html#method.to_i128_r).
                 let v = f.to_u128(usize::try_from(width).unwrap()).value;
                 // This should already fit the bit width
                 Ok(Scalar::from_uint(v, Size::from_bits(width)))
@@ -236,6 +238,8 @@ fn cast_from_float<F>(
             // float -> int
             Int(t) => {
                 let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits());
+                // `to_i128` is a saturating cast, which is what we need
+                // (https://doc.rust-lang.org/nightly/nightly-rustc/rustc_apfloat/trait.Float.html#method.to_i128_r).
                 let v = f.to_i128(usize::try_from(width).unwrap()).value;
                 Ok(Scalar::from_int(v, Size::from_bits(width)))
             }
index 8437399752e2947c3cd9114062c9f8de5abea813..7b6de4b0726c1ccce907cf29b4ab8fb939bee9a9 100644 (file)
@@ -833,17 +833,57 @@ pub fn write_bytes(
         ptr: Scalar<M::PointerTag>,
         src: impl IntoIterator<Item = u8>,
     ) -> InterpResult<'tcx> {
-        let src = src.into_iter();
+        let mut src = src.into_iter();
         let size = Size::from_bytes(src.size_hint().0);
         // `write_bytes` checks that this lower bound `size` matches the upper bound and reality.
         let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(1).unwrap())? {
             Some(ptr) => ptr,
-            None => return Ok(()), // zero-sized access
+            None => {
+                // zero-sized access
+                src.next().expect_none("iterator said it was empty but returned an element");
+                return Ok(());
+            }
         };
         let tcx = self.tcx.tcx;
         self.get_raw_mut(ptr.alloc_id)?.write_bytes(&tcx, ptr, src)
     }
 
+    /// Writes the given stream of u16s into memory.
+    ///
+    /// Performs appropriate bounds checks.
+    pub fn write_u16s(
+        &mut self,
+        ptr: Scalar<M::PointerTag>,
+        src: impl IntoIterator<Item = u16>,
+    ) -> InterpResult<'tcx> {
+        let mut src = src.into_iter();
+        let (lower, upper) = src.size_hint();
+        let len = upper.expect("can only write bounded iterators");
+        assert_eq!(lower, len, "can only write iterators with a precise length");
+
+        let size = Size::from_bytes(lower);
+        let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(2).unwrap())? {
+            Some(ptr) => ptr,
+            None => {
+                // zero-sized access
+                src.next().expect_none("iterator said it was empty but returned an element");
+                return Ok(());
+            }
+        };
+        let tcx = self.tcx.tcx;
+        let allocation = self.get_raw_mut(ptr.alloc_id)?;
+
+        for idx in 0..len {
+            let val = Scalar::from_u16(
+                src.next().expect("iterator was shorter than it said it would be"),
+            );
+            let offset_ptr = ptr.offset(Size::from_bytes(idx) * 2, &tcx)?; // `Size` multiplication
+            allocation.write_scalar(&tcx, offset_ptr, val.into(), Size::from_bytes(2))?;
+        }
+        src.next().expect_none("iterator was longer than it said it would be");
+        Ok(())
+    }
+
     /// Expects the caller to have checked bounds and alignment.
     pub fn copy(
         &mut self,
index 7d3aba3ff034e03ca6272c343e8139a8622d2ce3..85e44adc30b86a14c76f50e6fd82ee7426d44f65 100644 (file)
@@ -24,6 +24,7 @@
 #![feature(range_is_empty)]
 #![feature(stmt_expr_attributes)]
 #![feature(trait_alias)]
+#![feature(option_expect_none)]
 #![recursion_limit = "256"]
 
 #[macro_use]
index 76fcbf326fa788803ac06893ca838ad8b97e7377..5c69cea8b9169d1fc22241948f5722dfc055ded7 100644 (file)
@@ -1619,12 +1619,17 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// relation to preceding patterns, it is not reachable) and exhaustiveness
 /// checking (if a wildcard pattern is useful in relation to a matrix, the
 /// matrix isn't exhaustive).
+///
+/// `is_under_guard` is used to inform if the pattern has a guard. If it
+/// has one it must not be inserted into the matrix. This shouldn't be
+/// relied on for soundness.
 crate fn is_useful<'p, 'tcx>(
     cx: &mut MatchCheckCtxt<'p, 'tcx>,
     matrix: &Matrix<'p, 'tcx>,
     v: &PatStack<'p, 'tcx>,
     witness_preference: WitnessPreference,
     hir_id: HirId,
+    is_under_guard: bool,
     is_top_level: bool,
 ) -> Usefulness<'tcx, 'p> {
     let &Matrix(ref rows) = matrix;
@@ -1653,7 +1658,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut unreachable_pats = Vec::new();
         let mut any_is_useful = false;
         for v in vs {
-            let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, false);
+            let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
             match res {
                 Useful(pats) => {
                     any_is_useful = true;
@@ -1664,7 +1669,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     bug!("Encountered or-pat in `v` during exhaustiveness checking")
                 }
             }
-            matrix.push(v);
+            // If pattern has a guard don't add it to the matrix
+            if !is_under_guard {
+                matrix.push(v);
+            }
         }
         return if any_is_useful { Useful(unreachable_pats) } else { NotUseful };
     }
@@ -1712,7 +1720,18 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             Some(hir_id),
         )
         .into_iter()
-        .map(|c| is_useful_specialized(cx, matrix, v, c, pcx.ty, witness_preference, hir_id))
+        .map(|c| {
+            is_useful_specialized(
+                cx,
+                matrix,
+                v,
+                c,
+                pcx.ty,
+                witness_preference,
+                hir_id,
+                is_under_guard,
+            )
+        })
         .find(|result| result.is_useful())
         .unwrap_or(NotUseful)
     } else {
@@ -1746,14 +1765,24 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             split_grouped_constructors(cx.tcx, cx.param_env, pcx, all_ctors, matrix, DUMMY_SP, None)
                 .into_iter()
                 .map(|c| {
-                    is_useful_specialized(cx, matrix, v, c, pcx.ty, witness_preference, hir_id)
+                    is_useful_specialized(
+                        cx,
+                        matrix,
+                        v,
+                        c,
+                        pcx.ty,
+                        witness_preference,
+                        hir_id,
+                        is_under_guard,
+                    )
                 })
                 .find(|result| result.is_useful())
                 .unwrap_or(NotUseful)
         } else {
             let matrix = matrix.specialize_wildcard();
             let v = v.to_tail();
-            let usefulness = is_useful(cx, &matrix, &v, witness_preference, hir_id, false);
+            let usefulness =
+                is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
 
             // In this case, there's at least one "free"
             // constructor that is only matched against by
@@ -1810,6 +1839,7 @@ fn is_useful_specialized<'p, 'tcx>(
     lty: Ty<'tcx>,
     witness_preference: WitnessPreference,
     hir_id: HirId,
+    is_under_guard: bool,
 ) -> Usefulness<'tcx, 'p> {
     debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty);
 
@@ -1817,7 +1847,7 @@ fn is_useful_specialized<'p, 'tcx>(
         cx.pattern_arena.alloc_from_iter(ctor.wildcard_subpatterns(cx, lty));
     let matrix = matrix.specialize_constructor(cx, &ctor, ctor_wild_subpatterns);
     v.specialize_constructor(cx, &ctor, ctor_wild_subpatterns)
-        .map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id, false))
+        .map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false))
         .map(|u| u.apply_constructor(cx, &ctor, lty))
         .unwrap_or(NotUseful)
 }
index 9c86669cf9d929da307390d08eee390e0a6c03aa..c2eeac60b8b3bc709e2357f123f67ca2c0622ec4 100644 (file)
@@ -360,7 +360,7 @@ fn check_arms<'p, 'tcx>(
     let mut catchall = None;
     for (arm_index, (pat, id, has_guard)) in arms.iter().copied().enumerate() {
         let v = PatStack::from_pattern(pat);
-        match is_useful(cx, &seen, &v, LeaveOutWitness, id, true) {
+        match is_useful(cx, &seen, &v, LeaveOutWitness, id, has_guard, true) {
             NotUseful => {
                 match source {
                     hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => bug!(),
@@ -410,7 +410,10 @@ fn check_not_useful<'p, 'tcx>(
 ) -> Result<(), Vec<super::Pat<'tcx>>> {
     let wild_pattern = cx.pattern_arena.alloc(super::Pat::wildcard_from_ty(ty));
     let v = PatStack::from_pattern(wild_pattern);
-    match is_useful(cx, matrix, &v, ConstructWitness, hir_id, true) {
+
+    // false is given for `is_under_guard` argument due to the wildcard
+    // pattern not having a guard
+    match is_useful(cx, matrix, &v, ConstructWitness, hir_id, false, true) {
         NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
         UsefulWithWitness(pats) => Err(if pats.is_empty() {
             bug!("Exhaustiveness check returned no witnesses")
index cc88464d774e852aff90b474d6d45f4709966913..6b7a9ec658dffd296735d6754258ed9bcc47be48 100644 (file)
@@ -908,8 +908,10 @@ pub fn parse_foreign_item(&mut self) -> PResult<'a, Option<Option<P<ForeignItem>
 
     fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &str) -> Option<T> {
         let span = self.sess.source_map().guess_head_span(span);
-        let msg = format!("{} is not supported in {}", kind.descr(), ctx);
-        self.struct_span_err(span, &msg).emit();
+        let descr = kind.descr();
+        self.struct_span_err(span, &format!("{} is not supported in {}", descr, ctx))
+            .help(&format!("consider moving the {} out to a nearby module scope", descr))
+            .emit();
         None
     }
 
index 6e5111bd7018a460db2aaf627e5801b56f3be49c..6d688c12977e3acf4ba43db0258bb0263cb8bc15 100644 (file)
@@ -771,9 +771,6 @@ pub struct TargetOptions {
     /// rather than "default"
     pub default_hidden_visibility: bool,
 
-    /// Whether or not bitcode is embedded in object files
-    pub embed_bitcode: bool,
-
     /// Whether a .debug_gdb_scripts section will be added to the output object file
     pub emit_debug_gdb_scripts: bool,
 
@@ -893,7 +890,6 @@ fn default() -> TargetOptions {
             no_builtins: false,
             codegen_backend: "llvm".to_string(),
             default_hidden_visibility: false,
-            embed_bitcode: false,
             emit_debug_gdb_scripts: true,
             requires_uwtable: false,
             simd_types_indirect: true,
@@ -1208,7 +1204,6 @@ macro_rules! key {
         key!(no_builtins, bool);
         key!(codegen_backend);
         key!(default_hidden_visibility, bool);
-        key!(embed_bitcode, bool);
         key!(emit_debug_gdb_scripts, bool);
         key!(requires_uwtable, bool);
         key!(simd_types_indirect, bool);
@@ -1437,7 +1432,6 @@ macro_rules! target_option_val {
         target_option_val!(no_builtins);
         target_option_val!(codegen_backend);
         target_option_val!(default_hidden_visibility);
-        target_option_val!(embed_bitcode);
         target_option_val!(emit_debug_gdb_scripts);
         target_option_val!(requires_uwtable);
         target_option_val!(simd_types_indirect);
diff --git a/src/test/ui/or-patterns/issue-70413-no-unreachable-pat-and-guard.rs b/src/test/ui/or-patterns/issue-70413-no-unreachable-pat-and-guard.rs
new file mode 100644 (file)
index 0000000..eb6706e
--- /dev/null
@@ -0,0 +1,22 @@
+// check-pass
+
+#![deny(unreachable_patterns)]
+
+#![feature(or_patterns)]
+fn main() {
+    match (3,42) {
+        (a,_) | (_,a) if a > 10 => {println!("{}", a)}
+        _ => ()
+    }
+
+    match Some((3,42)) {
+        Some((a, _)) | Some((_, a)) if a > 10 => {println!("{}", a)}
+        _ => ()
+
+    }
+
+    match Some((3,42)) {
+        Some((a, _) | (_, a)) if a > 10 => {println!("{}", a)}
+        _ => ()
+    }
+}
index 9788bd64725b83152ec4adad8c19d0ba580c17a6..af513f7617b09aeaf3dc318aeba1322b34bfcbcd 100644 (file)
@@ -123,6 +123,8 @@ error: extern crate is not supported in `extern` blocks
    |
 LL |     default extern crate foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the extern crate out to a nearby module scope
 
 error: a `use` import cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:35:5
@@ -137,6 +139,8 @@ error: `use` import is not supported in `extern` blocks
    |
 LL |     default use foo;
    |     ^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the `use` import out to a nearby module scope
 
 error: a static item cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:37:5
@@ -169,6 +173,8 @@ error: module is not supported in `extern` blocks
    |
 LL |     default mod foo {}
    |     ^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the module out to a nearby module scope
 
 error: an extern block cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:43:5
@@ -183,6 +189,8 @@ error: extern block is not supported in `extern` blocks
    |
 LL |     default extern "C" {}
    |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the extern block out to a nearby module scope
 
 error: an enum cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:46:5
@@ -197,6 +205,8 @@ error: enum is not supported in `extern` blocks
    |
 LL |     default enum foo {}
    |     ^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the enum out to a nearby module scope
 
 error: a struct cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:48:5
@@ -211,6 +221,8 @@ error: struct is not supported in `extern` blocks
    |
 LL |     default struct foo {}
    |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the struct out to a nearby module scope
 
 error: a union cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:50:5
@@ -225,6 +237,8 @@ error: union is not supported in `extern` blocks
    |
 LL |     default union foo {}
    |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the union out to a nearby module scope
 
 error: a trait cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:52:5
@@ -239,6 +253,8 @@ error: trait is not supported in `extern` blocks
    |
 LL |     default trait foo {}
    |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the trait out to a nearby module scope
 
 error: a trait alias cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:54:5
@@ -253,12 +269,16 @@ error: trait alias is not supported in `extern` blocks
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the trait alias out to a nearby module scope
 
 error: implementation is not supported in `extern` blocks
   --> $DIR/default-on-wrong-item-kind.rs:56:5
    |
 LL |     default impl foo {}
    |     ^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the implementation out to a nearby module scope
 
 error: an item macro invocation cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:60:5
@@ -289,6 +309,8 @@ error: macro definition is not supported in `extern` blocks
    |
 LL |     default macro foo {}
    |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the macro definition out to a nearby module scope
 
 error: a macro definition cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:64:5
@@ -303,6 +325,8 @@ error: macro definition is not supported in `extern` blocks
    |
 LL |     default macro_rules! foo {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the macro definition out to a nearby module scope
 
 error: an extern crate cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:70:5
@@ -317,6 +341,8 @@ error: extern crate is not supported in `trait`s or `impl`s
    |
 LL |     default extern crate foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the extern crate out to a nearby module scope
 
 error: a `use` import cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:72:5
@@ -331,6 +357,8 @@ error: `use` import is not supported in `trait`s or `impl`s
    |
 LL |     default use foo;
    |     ^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the `use` import out to a nearby module scope
 
 error: a static item cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:74:5
@@ -359,6 +387,8 @@ error: module is not supported in `trait`s or `impl`s
    |
 LL |     default mod foo {}
    |     ^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the module out to a nearby module scope
 
 error: an extern block cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:80:5
@@ -373,6 +403,8 @@ error: extern block is not supported in `trait`s or `impl`s
    |
 LL |     default extern "C" {}
    |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the extern block out to a nearby module scope
 
 error: an enum cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:83:5
@@ -387,6 +419,8 @@ error: enum is not supported in `trait`s or `impl`s
    |
 LL |     default enum foo {}
    |     ^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the enum out to a nearby module scope
 
 error: a struct cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:85:5
@@ -401,6 +435,8 @@ error: struct is not supported in `trait`s or `impl`s
    |
 LL |     default struct foo {}
    |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the struct out to a nearby module scope
 
 error: a union cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:87:5
@@ -415,6 +451,8 @@ error: union is not supported in `trait`s or `impl`s
    |
 LL |     default union foo {}
    |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the union out to a nearby module scope
 
 error: a trait cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:89:5
@@ -429,6 +467,8 @@ error: trait is not supported in `trait`s or `impl`s
    |
 LL |     default trait foo {}
    |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the trait out to a nearby module scope
 
 error: a trait alias cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:91:5
@@ -443,12 +483,16 @@ error: trait alias is not supported in `trait`s or `impl`s
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the trait alias out to a nearby module scope
 
 error: implementation is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:93:5
    |
 LL |     default impl foo {}
    |     ^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the implementation out to a nearby module scope
 
 error: an item macro invocation cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:97:5
@@ -479,6 +523,8 @@ error: macro definition is not supported in `trait`s or `impl`s
    |
 LL |     default macro foo {}
    |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the macro definition out to a nearby module scope
 
 error: a macro definition cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:101:5
@@ -493,6 +539,8 @@ error: macro definition is not supported in `trait`s or `impl`s
    |
 LL |     default macro_rules! foo {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the macro definition out to a nearby module scope
 
 error: an extern crate cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:107:5
@@ -507,6 +555,8 @@ error: extern crate is not supported in `trait`s or `impl`s
    |
 LL |     default extern crate foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the extern crate out to a nearby module scope
 
 error: a `use` import cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:109:5
@@ -521,6 +571,8 @@ error: `use` import is not supported in `trait`s or `impl`s
    |
 LL |     default use foo;
    |     ^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the `use` import out to a nearby module scope
 
 error: a static item cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:111:5
@@ -549,6 +601,8 @@ error: module is not supported in `trait`s or `impl`s
    |
 LL |     default mod foo {}
    |     ^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the module out to a nearby module scope
 
 error: an extern block cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:117:5
@@ -563,6 +617,8 @@ error: extern block is not supported in `trait`s or `impl`s
    |
 LL |     default extern "C" {}
    |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the extern block out to a nearby module scope
 
 error: an enum cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:120:5
@@ -577,6 +633,8 @@ error: enum is not supported in `trait`s or `impl`s
    |
 LL |     default enum foo {}
    |     ^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the enum out to a nearby module scope
 
 error: a struct cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:122:5
@@ -591,6 +649,8 @@ error: struct is not supported in `trait`s or `impl`s
    |
 LL |     default struct foo {}
    |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the struct out to a nearby module scope
 
 error: a union cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:124:5
@@ -605,6 +665,8 @@ error: union is not supported in `trait`s or `impl`s
    |
 LL |     default union foo {}
    |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the union out to a nearby module scope
 
 error: a trait cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:126:5
@@ -619,6 +681,8 @@ error: trait is not supported in `trait`s or `impl`s
    |
 LL |     default trait foo {}
    |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the trait out to a nearby module scope
 
 error: a trait alias cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:128:5
@@ -633,12 +697,16 @@ error: trait alias is not supported in `trait`s or `impl`s
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the trait alias out to a nearby module scope
 
 error: implementation is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:130:5
    |
 LL |     default impl foo {}
    |     ^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the implementation out to a nearby module scope
 
 error: an item macro invocation cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:134:5
@@ -669,6 +737,8 @@ error: macro definition is not supported in `trait`s or `impl`s
    |
 LL |     default macro foo {}
    |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the macro definition out to a nearby module scope
 
 error: a macro definition cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:138:5
@@ -683,6 +753,8 @@ error: macro definition is not supported in `trait`s or `impl`s
    |
 LL |     default macro_rules! foo {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the macro definition out to a nearby module scope
 
 error: aborting due to 95 previous errors
 
index bfd27a1a41e13390c0afd53a7808736595bea280..c83205aadd6729a28b408be3b617e8babe5300bc 100644 (file)
@@ -3,6 +3,8 @@ error: struct is not supported in `trait`s or `impl`s
    |
 LL |     struct BadS;
    |     ^^^^^^^^^^^^
+   |
+   = help: consider moving the struct out to a nearby module scope
 
 error: enum is not supported in `trait`s or `impl`s
   --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9
@@ -13,6 +15,7 @@ LL |         enum BadE {}
 LL |     expand_to_enum!();
    |     ------------------ in this macro invocation
    |
+   = help: consider moving the enum out to a nearby module scope
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: struct is not supported in `trait`s or `impl`s
@@ -20,6 +23,8 @@ error: struct is not supported in `trait`s or `impl`s
    |
 LL |     struct BadS;
    |     ^^^^^^^^^^^^
+   |
+   = help: consider moving the struct out to a nearby module scope
 
 error: enum is not supported in `trait`s or `impl`s
   --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9
@@ -30,6 +35,7 @@ LL |         enum BadE {}
 LL |     expand_to_enum!();
    |     ------------------ in this macro invocation
    |
+   = help: consider moving the enum out to a nearby module scope
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: struct is not supported in `extern` blocks
@@ -37,6 +43,8 @@ error: struct is not supported in `extern` blocks
    |
 LL |     struct BadS;
    |     ^^^^^^^^^^^^
+   |
+   = help: consider moving the struct out to a nearby module scope
 
 error: enum is not supported in `extern` blocks
   --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9
@@ -47,6 +55,7 @@ LL |         enum BadE {}
 LL |     expand_to_enum!();
    |     ------------------ in this macro invocation
    |
+   = help: consider moving the enum out to a nearby module scope
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 6 previous errors
index 1655a96839569d0be255a04dec9cfab9853e65a4..cc7cc0c55d5ff1fe08d379bd3b593d306022e827 100644 (file)
@@ -12,12 +12,16 @@ error: trait is not supported in `trait`s or `impl`s
    |
 LL | trait T {
    | ^^^^^^^
+   |
+   = help: consider moving the trait out to a nearby module scope
 
 error: struct is not supported in `trait`s or `impl`s
   --> $DIR/missing-close-brace-in-impl-trait.rs:11:1
    |
 LL | pub(crate) struct Bar<T>();
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the struct out to a nearby module scope
 
 error[E0405]: cannot find trait `T` in this scope
   --> $DIR/missing-close-brace-in-impl-trait.rs:3:6
index 43a3883357a754112636611e79d0fccc42c898dd..7c6254356e0774be199e69435119fbc6f47d53df 100644 (file)
@@ -12,12 +12,16 @@ error: struct is not supported in `trait`s or `impl`s
    |
 LL | pub(crate) struct Bar<T>();
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the struct out to a nearby module scope
 
 error: implementation is not supported in `trait`s or `impl`s
   --> $DIR/missing-close-brace-in-trait.rs:7:1
    |
 LL | impl T for Bar<usize> {
    | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider moving the implementation out to a nearby module scope
 
 error: aborting due to 3 previous errors