diff --git a/Cargo.lock b/Cargo.lock index 14ee031ad047e..da99ac9b8afc7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3479,14 +3479,6 @@ dependencies = [ "wasmparser", ] -[[package]] -name = "rust-demangler" -version = "0.0.1" -dependencies = [ - "regex", - "rustc-demangle", -] - [[package]] name = "rustbook" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index a601ebf4369e0..c17ea99d03767 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ members = [ "src/tools/remote-test-client", "src/tools/remote-test-server", "src/tools/rust-installer", - "src/tools/rust-demangler", "src/tools/rustdoc", "src/tools/rls", "src/tools/rustfmt", diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index cb5aac7e56010..1a7e5bd70921b 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -73,8 +73,6 @@ const_eval_division_by_zero = dividing by zero const_eval_division_overflow = overflow in signed division (dividing MIN by -1) -const_eval_double_storage_live = - StorageLive on a local that was already live const_eval_dyn_call_not_a_method = `dyn` call trying to call something that is not a method diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index f602d989e0809..67eeb1b3b8712 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1100,11 +1100,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Operand::Immediate(Immediate::Uninit) }); - // StorageLive expects the local to be dead, and marks it live. + // If the local is already live, deallocate its old memory. let old = mem::replace(&mut self.frame_mut().locals[local].value, local_val); - if !matches!(old, LocalValue::Dead) { - throw_ub_custom!(fluent::const_eval_double_storage_live); - } + self.deallocate_local(old)?; Ok(()) } @@ -1118,7 +1116,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert!(local != mir::RETURN_PLACE, "Cannot make return place dead"); trace!("{:?} is now dead", local); - // It is entirely okay for this local to be already dead (at least that's how we currently generate MIR) + // If the local is already dead, this is a NOP. let old = mem::replace(&mut self.frame_mut().locals[local].value, LocalValue::Dead); self.deallocate_local(old)?; Ok(()) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 510e9a06dfb06..4d6ddd7ba66ab 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -878,9 +878,9 @@ impl<'tcx> InferCtxt<'tcx> { self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| { if a_is_expected { - Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::No, a, b)) + Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b)) } else { - Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::No, b, a)) + Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a)) } }) } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 3edc5fe36cd2f..736cef3cdb81c 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -361,16 +361,19 @@ pub enum StatementKind<'tcx> { /// At any point during the execution of a function, each local is either allocated or /// unallocated. Except as noted below, all locals except function parameters are initially /// unallocated. `StorageLive` statements cause memory to be allocated for the local while - /// `StorageDead` statements cause the memory to be freed. Using a local in any way (not only - /// reading/writing from it) while it is unallocated is UB. + /// `StorageDead` statements cause the memory to be freed. In other words, + /// `StorageLive`/`StorageDead` act like the heap operations `allocate`/`deallocate`, but for + /// stack-allocated local variables. Using a local in any way (not only reading/writing from it) + /// while it is unallocated is UB. /// /// Some locals have no `StorageLive` or `StorageDead` statements within the entire MIR body. /// These locals are implicitly allocated for the full duration of the function. There is a /// convenience method at `rustc_mir_dataflow::storage::always_storage_live_locals` for /// computing these locals. /// - /// If the local is already allocated, calling `StorageLive` again is UB. However, for an - /// unallocated local an additional `StorageDead` all is simply a nop. + /// If the local is already allocated, calling `StorageLive` again will implicitly free the + /// local and then allocate fresh uninitilized memory. If a local is already deallocated, + /// calling `StorageDead` again is a NOP. StorageLive(Local), /// See `StorageLive` above. diff --git a/compiler/rustc_mir_build/src/build/coverageinfo.rs b/compiler/rustc_mir_build/src/build/coverageinfo.rs index 855dcbbcb346e..876faca5172ac 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo.rs @@ -118,17 +118,35 @@ impl BranchInfoBuilder { } } - fn add_two_way_branch<'tcx>( + fn register_two_way_branch<'tcx>( &mut self, + tcx: TyCtxt<'tcx>, cfg: &mut CFG<'tcx>, source_info: SourceInfo, true_block: BasicBlock, false_block: BasicBlock, ) { - let true_marker = self.markers.inject_block_marker(cfg, source_info, true_block); - let false_marker = self.markers.inject_block_marker(cfg, source_info, false_block); - - self.branch_spans.push(BranchSpan { span: source_info.span, true_marker, false_marker }); + // Separate path for handling branches when MC/DC is enabled. + if let Some(mcdc_info) = self.mcdc_info.as_mut() { + let inject_block_marker = + |source_info, block| self.markers.inject_block_marker(cfg, source_info, block); + mcdc_info.visit_evaluated_condition( + tcx, + source_info, + true_block, + false_block, + inject_block_marker, + ); + } else { + let true_marker = self.markers.inject_block_marker(cfg, source_info, true_block); + let false_marker = self.markers.inject_block_marker(cfg, source_info, false_block); + + self.branch_spans.push(BranchSpan { + span: source_info.span, + true_marker, + false_marker, + }); + } } pub(crate) fn into_done(self) -> Option> { @@ -205,7 +223,14 @@ impl<'tcx> Builder<'_, 'tcx> { mir::TerminatorKind::if_(mir::Operand::Copy(place), true_block, false_block), ); - branch_info.add_two_way_branch(&mut self.cfg, source_info, true_block, false_block); + // Separate path for handling branches when MC/DC is enabled. + branch_info.register_two_way_branch( + self.tcx, + &mut self.cfg, + source_info, + true_block, + false_block, + ); let join_block = self.cfg.start_new_block(); self.cfg.goto(true_block, source_info, join_block); @@ -236,22 +261,13 @@ impl<'tcx> Builder<'_, 'tcx> { let source_info = SourceInfo { span: self.thir[expr_id].span, scope: self.source_scope }; - // Separate path for handling branches when MC/DC is enabled. - if let Some(mcdc_info) = branch_info.mcdc_info.as_mut() { - let inject_block_marker = |source_info, block| { - branch_info.markers.inject_block_marker(&mut self.cfg, source_info, block) - }; - mcdc_info.visit_evaluated_condition( - self.tcx, - source_info, - then_block, - else_block, - inject_block_marker, - ); - return; - } - - branch_info.add_two_way_branch(&mut self.cfg, source_info, then_block, else_block); + branch_info.register_two_way_branch( + self.tcx, + &mut self.cfg, + source_info, + then_block, + else_block, + ); } /// If branch coverage is enabled, inject marker statements into `true_block` @@ -270,6 +286,12 @@ impl<'tcx> Builder<'_, 'tcx> { // FIXME(#124144) This may need special handling when MC/DC is enabled. let source_info = SourceInfo { span: pattern.span, scope: self.source_scope }; - branch_info.add_two_way_branch(&mut self.cfg, source_info, true_block, false_block); + branch_info.register_two_way_branch( + self.tcx, + &mut self.cfg, + source_info, + true_block, + false_block, + ); } } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index c08a3b6691afc..6b4dd8b64a425 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -150,6 +150,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::LogicalOp { op, lhs, rhs } => { let condition_scope = this.local_scope(); let source_info = this.source_info(expr.span); + + this.visit_coverage_branch_operation(op, expr.span); + // We first evaluate the left-hand side of the predicate ... let (then_block, else_block) = this.in_if_then_scope(condition_scope, expr.span, |this| { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 5f9c3a14d6032..24143808ef492 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1311,6 +1311,20 @@ pub fn build_target_config(early_dcx: &EarlyDiagCtxt, opts: &Options, sysroot: & for warning in warnings.warning_messages() { early_dcx.early_warn(warning) } + + // The `wasm32-wasi` target is being renamed to `wasm32-wasip1` as + // part of rust-lang/compiler-team#607 and + // rust-lang/compiler-team#695. Warn unconditionally on usage to + // raise awareness of the renaming. This code will be deleted in + // October 2024. + if opts.target_triple.triple() == "wasm32-wasi" { + early_dcx.early_warn( + "the `wasm32-wasi` target is being renamed to \ + `wasm32-wasip1` and the `wasm32-wasi` target will be \ + removed from nightly in October 2024 and removed from \ + stable Rust in January 2025", + ) + } if !matches!(target.pointer_width, 16 | 32 | 64) { early_dcx.early_fatal(format!( "target specification was invalid: unrecognized target-pointer-width {}", diff --git a/config.example.toml b/config.example.toml index 76541ee4e9e7e..679abcdc7771b 100644 --- a/config.example.toml +++ b/config.example.toml @@ -321,8 +321,7 @@ # # If `extended = false`, the only one of these built by default is rustdoc. # -# If `extended = true`, they're all included, with the exception of -# rust-demangler which additionally requires `profiler = true` to be set. +# If `extended = true`, they are all included. # # If any enabled tool fails to build, the installation fails. #tools = [ @@ -334,7 +333,6 @@ # "rust-analyzer-proc-macro-srv", # "analysis", # "src", -# "rust-demangler", # if profiler = true #] # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose, 3 == print environment variables on each rustc invocation diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index 01b5e99116ff2..40a2112b19254 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -322,7 +322,6 @@ lint_any!( RemoteTestServer, "src/tools/remote-test-server", "remote-test-server"; Rls, "src/tools/rls", "rls"; RustAnalyzer, "src/tools/rust-analyzer", "rust-analyzer"; - RustDemangler, "src/tools/rust-demangler", "rust-demangler"; Rustdoc, "src/tools/rustdoc", "clippy"; Rustfmt, "src/tools/rustfmt", "rustfmt"; RustInstaller, "src/tools/rust-installer", "rust-installer"; diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index f651f751441f3..54136d2aebda2 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1459,62 +1459,6 @@ impl Step for Rustfmt { } } -#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] -pub struct RustDemangler { - pub compiler: Compiler, - pub target: TargetSelection, -} - -impl Step for RustDemangler { - type Output = Option; - const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - // While other tools use `should_build_extended_tool` to decide whether to be run by - // default or not, `rust-demangler` must be build when *either* it's enabled as a tool like - // the other ones or if `profiler = true`. Because we don't know the target at this stage - // we run the step by default when only `extended = true`, and decide whether to actually - // run it or not later. - let default = run.builder.config.extended; - run.alias("rust-demangler").default_condition(default) - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(RustDemangler { - compiler: run.builder.compiler_for( - run.builder.top_stage, - run.builder.config.build, - run.target, - ), - target: run.target, - }); - } - - fn run(self, builder: &Builder<'_>) -> Option { - let compiler = self.compiler; - let target = self.target; - - // Only build this extended tool if explicitly included in `tools`, or if `profiler = true` - let condition = should_build_extended_tool(builder, "rust-demangler") - || builder.config.profiler_enabled(target); - if builder.config.extended && !condition { - return None; - } - - let rust_demangler = - builder.ensure(tool::RustDemangler { compiler, target, extra_features: Vec::new() }); - - // Prepare the image directory - let mut tarball = Tarball::new(builder, "rust-demangler", &target.triple); - tarball.set_overlay(OverlayKind::RustDemangler); - tarball.is_preview(true); - tarball.add_file(rust_demangler, "bin", 0o755); - tarball.add_legal_and_readme_to("share/doc/rust-demangler"); - Some(tarball.generate()) - } -} - #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] pub struct Extended { stage: u32, @@ -1572,7 +1516,6 @@ impl Step for Extended { add_component!("rust-docs" => Docs { host: target }); add_component!("rust-json-docs" => JsonDocs { host: target }); - add_component!("rust-demangler"=> RustDemangler { compiler, target }); add_component!("cargo" => Cargo { compiler, target }); add_component!("rustfmt" => Rustfmt { compiler, target }); add_component!("rls" => Rls { compiler, target }); @@ -1636,7 +1579,7 @@ impl Step for Extended { let xform = |p: &Path| { let mut contents = t!(fs::read_to_string(p)); - for tool in &["rust-demangler", "miri", "rust-docs"] { + for tool in &["miri", "rust-docs"] { if !built_tools.contains(tool) { contents = filter(&contents, tool); } @@ -1677,7 +1620,7 @@ impl Step for Extended { prepare("rust-analysis"); prepare("clippy"); prepare("rust-analyzer"); - for tool in &["rust-docs", "rust-demangler", "miri", "rustc-codegen-cranelift"] { + for tool in &["rust-docs", "miri", "rustc-codegen-cranelift"] { if built_tools.contains(tool) { prepare(tool); } @@ -1717,8 +1660,6 @@ impl Step for Extended { "rust-analyzer-preview".to_string() } else if name == "clippy" { "clippy-preview".to_string() - } else if name == "rust-demangler" { - "rust-demangler-preview".to_string() } else if name == "miri" { "miri-preview".to_string() } else if name == "rustc-codegen-cranelift" { @@ -1738,7 +1679,7 @@ impl Step for Extended { prepare("cargo"); prepare("rust-analysis"); prepare("rust-std"); - for tool in &["clippy", "rust-analyzer", "rust-docs", "rust-demangler", "miri"] { + for tool in &["clippy", "rust-analyzer", "rust-docs", "miri"] { if built_tools.contains(tool) { prepare(tool); } @@ -1862,25 +1803,6 @@ impl Step for Extended { .arg(etc.join("msi/remove-duplicates.xsl")), ); } - if built_tools.contains("rust-demangler") { - builder.run( - Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("rust-demangler") - .args(heat_flags) - .arg("-cg") - .arg("RustDemanglerGroup") - .arg("-dr") - .arg("RustDemangler") - .arg("-var") - .arg("var.RustDemanglerDir") - .arg("-out") - .arg(exe.join("RustDemanglerGroup.wxs")) - .arg("-t") - .arg(etc.join("msi/remove-duplicates.xsl")), - ); - } if built_tools.contains("miri") { builder.run( Command::new(&heat) @@ -1958,9 +1880,6 @@ impl Step for Extended { if built_tools.contains("rust-docs") { cmd.arg("-dDocsDir=rust-docs"); } - if built_tools.contains("rust-demangler") { - cmd.arg("-dRustDemanglerDir=rust-demangler"); - } if built_tools.contains("rust-analyzer") { cmd.arg("-dRustAnalyzerDir=rust-analyzer"); } @@ -1987,9 +1906,6 @@ impl Step for Extended { if built_tools.contains("miri") { candle("MiriGroup.wxs".as_ref()); } - if built_tools.contains("rust-demangler") { - candle("RustDemanglerGroup.wxs".as_ref()); - } if built_tools.contains("rust-analyzer") { candle("RustAnalyzerGroup.wxs".as_ref()); } @@ -2031,9 +1947,6 @@ impl Step for Extended { if built_tools.contains("rust-analyzer") { cmd.arg("RustAnalyzerGroup.wixobj"); } - if built_tools.contains("rust-demangler") { - cmd.arg("RustDemanglerGroup.wixobj"); - } if built_tools.contains("rust-docs") { cmd.arg("DocsGroup.wixobj"); } diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 6a75f35c93a6e..c47233ca42abe 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -265,22 +265,6 @@ install!((self, builder, _config), ); } }; - RustDemangler, alias = "rust-demangler", Self::should_build(_config), only_hosts: true, { - // NOTE: Even though `should_build` may return true for `extended` default tools, - // dist::RustDemangler may still return None, unless the target-dependent `profiler` config - // is also true, or the `tools` array explicitly includes "rust-demangler". - if let Some(tarball) = builder.ensure(dist::RustDemangler { - compiler: self.compiler, - target: self.target - }) { - install_sh(builder, "rust-demangler", self.compiler.stage, Some(self.target), &tarball); - } else { - builder.info( - &format!("skipping Install RustDemangler stage{} ({})", - self.compiler.stage, self.target), - ); - } - }; Rustc, path = "compiler/rustc", true, only_hosts: true, { let tarball = builder.ensure(dist::Rustc { compiler: builder.compiler(builder.top_stage, self.target), diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 7556a19c90ca0..445096e9786d4 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -432,65 +432,6 @@ impl Step for Rustfmt { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct RustDemangler { - stage: u32, - host: TargetSelection, -} - -impl Step for RustDemangler { - type Output = (); - const ONLY_HOSTS: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/rust-demangler") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(RustDemangler { stage: run.builder.top_stage, host: run.target }); - } - - /// Runs `cargo test` for rust-demangler. - fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - let host = self.host; - let compiler = builder.compiler(stage, host); - - let rust_demangler = builder.ensure(tool::RustDemangler { - compiler, - target: self.host, - extra_features: Vec::new(), - }); - let mut cargo = tool::prepare_tool_cargo( - builder, - compiler, - Mode::ToolRustc, - host, - "test", - "src/tools/rust-demangler", - SourceType::InTree, - &[], - ); - - let dir = testdir(builder, compiler.host); - t!(fs::create_dir_all(dir)); - - cargo.env("RUST_DEMANGLER_DRIVER_PATH", rust_demangler); - cargo.add_rustc_lib_path(builder); - - run_cargo_test( - cargo, - &[], - &[], - "rust-demangler", - "rust-demangler", - compiler, - host, - builder, - ); - } -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Miri { target: TargetSelection, diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index e0a9674ae5a90..613484788b608 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -964,7 +964,6 @@ tool_extended!((self, builder), // But `builder.cargo` doesn't know how to handle ToolBootstrap in stages other than 0, // and this is close enough for now. Rls, "src/tools/rls", "rls", stable=true, tool_std=true; - RustDemangler, "src/tools/rust-demangler", "rust-demangler", stable=false, tool_std=true; Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, add_bins_to_sysroot = ["rustfmt", "cargo-fmt"]; ); diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index d9e4cbae17d71..3c4806a131179 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -736,7 +736,6 @@ impl<'a> Builder<'a> { tool::Rls, tool::RustAnalyzer, tool::RustAnalyzerProcMacroSrv, - tool::RustDemangler, tool::Rustdoc, tool::Clippy, tool::CargoClippy, @@ -774,7 +773,6 @@ impl<'a> Builder<'a> { clippy::RemoteTestServer, clippy::Rls, clippy::RustAnalyzer, - clippy::RustDemangler, clippy::Rustdoc, clippy::Rustfmt, clippy::RustInstaller, @@ -842,7 +840,6 @@ impl<'a> Builder<'a> { test::Miri, test::CargoMiri, test::Clippy, - test::RustDemangler, test::CompiletestTest, test::CrateRunMakeSupport, test::RustdocJSStd, @@ -903,7 +900,6 @@ impl<'a> Builder<'a> { dist::Rls, dist::RustAnalyzer, dist::Rustfmt, - dist::RustDemangler, dist::Clippy, dist::Miri, dist::LlvmTools, @@ -930,7 +926,6 @@ impl<'a> Builder<'a> { install::Cargo, install::RustAnalyzer, install::Rustfmt, - install::RustDemangler, install::Clippy, install::Miri, install::LlvmTools, @@ -1036,23 +1031,12 @@ impl<'a> Builder<'a> { } pub fn doc_rust_lang_org_channel(&self) -> String { - // When using precompiled compiler from CI, we need to use CI rustc's channel and - // ignore `rust.channel` from the configuration. Otherwise most of the rustdoc tests - // will fail due to incompatible `DOC_RUST_LANG_ORG_CHANNEL`. - let channel = if let Some(commit) = self.config.download_rustc_commit() { - self.config - .read_file_by_commit(&PathBuf::from("src/ci/channel"), commit) - .trim() - .to_owned() - } else { - match &*self.config.channel { - "stable" => &self.version, - "beta" => "beta", - "nightly" | "dev" => "nightly", - // custom build of rustdoc maybe? link to the latest stable docs just in case - _ => "stable", - } - .to_owned() + let channel = match &*self.config.channel { + "stable" => &self.version, + "beta" => "beta", + "nightly" | "dev" => "nightly", + // custom build of rustdoc maybe? link to the latest stable docs just in case + _ => "stable", }; format!("https://doc.rust-lang.org/{channel}") diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index a1d8ca3cbcaa7..0438dee7241fe 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1718,7 +1718,23 @@ impl Config { config.omit_git_hash = omit_git_hash.unwrap_or(default); config.rust_info = GitInfo::new(config.omit_git_hash, &config.src); - if config.rust_info.is_from_tarball() && !is_user_configured_rust_channel { + // We need to override `rust.channel` if it's manually specified when using the CI rustc. + // This is because if the compiler uses a different channel than the one specified in config.toml, + // tests may fail due to using a different channel than the one used by the compiler during tests. + if let Some(commit) = &config.download_rustc_commit { + if is_user_configured_rust_channel { + println!( + "WARNING: `rust.download-rustc` is enabled. The `rust.channel` option will be overridden by the CI rustc's channel." + ); + + let channel = config + .read_file_by_commit(&PathBuf::from("src/ci/channel"), commit) + .trim() + .to_owned(); + + config.channel = channel; + } + } else if config.rust_info.is_from_tarball() && !is_user_configured_rust_channel { ci_channel.clone_into(&mut config.channel); } diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs index 57cdf7473a191..fd934f18de23f 100644 --- a/src/bootstrap/src/utils/tarball.rs +++ b/src/bootstrap/src/utils/tarball.rs @@ -23,7 +23,6 @@ pub(crate) enum OverlayKind { Clippy, Miri, Rustfmt, - RustDemangler, Rls, RustAnalyzer, RustcCodegenCranelift, @@ -58,9 +57,6 @@ impl OverlayKind { "src/tools/rustfmt/LICENSE-APACHE", "src/tools/rustfmt/LICENSE-MIT", ], - OverlayKind::RustDemangler => { - &["src/tools/rust-demangler/README.md", "LICENSE-APACHE", "LICENSE-MIT"] - } OverlayKind::Rls => &["src/tools/rls/README.md", "LICENSE-APACHE", "LICENSE-MIT"], OverlayKind::RustAnalyzer => &[ "src/tools/rust-analyzer/README.md", @@ -85,7 +81,6 @@ impl OverlayKind { match self { OverlayKind::Rust => builder.rust_version(), OverlayKind::Llvm => builder.rust_version(), - OverlayKind::RustDemangler => builder.release_num("rust-demangler"), OverlayKind::Cargo => { builder.cargo_info.version(builder, &builder.release_num("cargo")) } diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md index 32dc992c42fac..ed091d8fc5710 100644 --- a/src/doc/rustc/src/instrument-coverage.md +++ b/src/doc/rustc/src/instrument-coverage.md @@ -49,12 +49,6 @@ One option for a Rust demangler is [`rustfilt`], which can be installed with: cargo install rustfilt ``` -Another option, if you are building from the Rust compiler source distribution, is to use the `rust-demangler` tool included in the Rust source distribution, which can be built with: - -```shell -$ ./x.py build rust-demangler -``` - [`rustfilt`]: https://crates.io/crates/rustfilt ## Compiling with coverage enabled @@ -164,7 +158,7 @@ $ llvm-cov show -Xdemangler=rustfilt target/debug/examples/formatjson5 \ Some of the more notable options in this example include: -- `--Xdemangler=rustfilt` - the command name or path used to demangle Rust symbols (`rustfilt` in the example, but this could also be a path to the `rust-demangler` tool) +- `--Xdemangler=rustfilt` - the command name or path used to demangle Rust symbols (`rustfilt` in the example) - `target/debug/examples/formatjson5` - the instrumented binary (from which to extract the coverage map) - `--instr-profile=.profdata` - the location of the `.profdata` file created by `llvm-profdata merge` (from the `.profraw` file generated by the instrumented binary) - `--name=` - to show coverage for a specific function (or, consider using another filter option, such as `--name-regex=`) diff --git a/src/tools/miri/tests/fail/storage-live-dead-var.rs b/src/tools/miri/tests/fail/storage-live-dead-var.rs new file mode 100644 index 0000000000000..83ab98d79d1a1 --- /dev/null +++ b/src/tools/miri/tests/fail/storage-live-dead-var.rs @@ -0,0 +1,14 @@ +#![feature(core_intrinsics, custom_mir)] +use std::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime")] +fn main() { + mir! { + let val: i32; + { + val = 42; //~ERROR: accessing a dead local variable + StorageLive(val); // too late... (but needs to be here to make `val` not implicitly live) + Return() + } + } +} diff --git a/src/tools/miri/tests/fail/storage-live-dead-var.stderr b/src/tools/miri/tests/fail/storage-live-dead-var.stderr new file mode 100644 index 0000000000000..ccc77b1c978dc --- /dev/null +++ b/src/tools/miri/tests/fail/storage-live-dead-var.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: accessing a dead local variable + --> $DIR/storage-live-dead-var.rs:LL:CC + | +LL | val = 42; + | ^^^^^^^^ accessing a dead local variable + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/storage-live-dead-var.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/storage-live-resets-var.rs b/src/tools/miri/tests/fail/storage-live-resets-var.rs new file mode 100644 index 0000000000000..bfdd9e78943e9 --- /dev/null +++ b/src/tools/miri/tests/fail/storage-live-resets-var.rs @@ -0,0 +1,17 @@ +#![feature(core_intrinsics, custom_mir)] +use std::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime")] +fn main() { + mir! { + let val: i32; + let _val2: i32; + { + StorageLive(val); + val = 42; + StorageLive(val); // reset val to `uninit` + _val2 = val; //~ERROR: uninitialized + Return() + } + } +} diff --git a/src/tools/miri/tests/fail/storage-live-resets-var.stderr b/src/tools/miri/tests/fail/storage-live-resets-var.stderr new file mode 100644 index 0000000000000..07d39cc9d6b3f --- /dev/null +++ b/src/tools/miri/tests/fail/storage-live-resets-var.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value: encountered uninitialized memory, but expected an integer + --> $DIR/storage-live-resets-var.rs:LL:CC + | +LL | _val2 = val; + | ^^^^^^^^^^^ constructing invalid value: encountered uninitialized memory, but expected an integer + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/storage-live-resets-var.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/rust-demangler/Cargo.toml b/src/tools/rust-demangler/Cargo.toml deleted file mode 100644 index 2bb73b3262d8d..0000000000000 --- a/src/tools/rust-demangler/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "rust-demangler" -version = "0.0.1" -edition = "2021" - -[dependencies] -regex = "1.0" -rustc-demangle = "0.1.17" - -[lib] -name = "rust_demangler" -doctest = false - -[[bin]] -name = "rust-demangler" -test = false diff --git a/src/tools/rust-demangler/README.md b/src/tools/rust-demangler/README.md deleted file mode 100644 index 4e8a689a13a47..0000000000000 --- a/src/tools/rust-demangler/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# rust-demangler - -_Demangles rustc mangled names._ - -`rust-demangler` supports the requirements of the [`llvm-cov show -Xdemangler` -option](https://llvm.org/docs/CommandGuide/llvm-cov.html#cmdoption-llvm-cov-show-xdemangler), -to perform Rust-specific symbol demangling: - -> _The demangler is expected to read a newline-separated list of symbols from -> stdin and write a newline-separated list of the same length to stdout._ - -To use `rust-demangler` with `llvm-cov` for example: - -```shell -$ TARGET="${PWD}/build/x86_64-unknown-linux-gnu" -$ "${TARGET}"/llvm/bin/llvm-cov show \ - --Xdemangler=path/to/rust-demangler \ - --instr-profile=main.profdata ./main --show-line-counts-or-regions -``` - -`rust-demangler` is a Rust "extended tool", used in Rust compiler tests, and -optionally included in Rust distributions that enable coverage profiling. Symbol -demangling is implemented using the -[rustc-demangle](https://crates.io/crates/rustc-demangle) crate. - -_(Note, for Rust developers, the third-party tool -[`rustfilt`](https://crates.io/crates/rustfilt) also supports `llvm-cov` symbol -demangling. `rustfilt` is a more generalized tool that searches any body of -text, using pattern matching, to find and demangle Rust symbols.)_ - -## License - -Rust-demangler is distributed under the terms of both the MIT license and the -Apache License (Version 2.0). - -See [LICENSE-APACHE](/LICENSE-APACHE) and [LICENSE-MIT](/LICENSE-MIT) for details. diff --git a/src/tools/rust-demangler/src/lib.rs b/src/tools/rust-demangler/src/lib.rs deleted file mode 100644 index 1d972229d9536..0000000000000 --- a/src/tools/rust-demangler/src/lib.rs +++ /dev/null @@ -1,21 +0,0 @@ -use regex::Regex; -use rustc_demangle::demangle; -use std::str::Lines; - -const REPLACE_COLONS: &str = "::"; - -pub fn create_disambiguator_re() -> Regex { - Regex::new(r"\[[a-f0-9]{5,16}\]::").unwrap() -} - -pub fn demangle_lines(lines: Lines<'_>, strip_crate_disambiguators: Option) -> Vec { - let mut demangled_lines = Vec::new(); - for mangled in lines { - let mut demangled = demangle(mangled).to_string(); - if let Some(re) = &strip_crate_disambiguators { - demangled = re.replace_all(&demangled, REPLACE_COLONS).to_string(); - } - demangled_lines.push(demangled); - } - demangled_lines -} diff --git a/src/tools/rust-demangler/src/main.rs b/src/tools/rust-demangler/src/main.rs deleted file mode 100644 index 1b5ef5d2442ba..0000000000000 --- a/src/tools/rust-demangler/src/main.rs +++ /dev/null @@ -1,97 +0,0 @@ -//! Demangles rustc mangled names. -//! -//! Note regarding crate disambiguators: -//! -//! Some demangled symbol paths can include "crate disambiguator" suffixes, represented as a large -//! hexadecimal value enclosed in square braces, and appended to the name of the crate. a suffix to the -//! original crate name. For example, the `core` crate, here, includes a disambiguator: -//! -//! ```rust -//! as core[a7a74cee373f048]::ops::drop::Drop>::drop -//! ``` -//! -//! These disambiguators are known to vary depending on environmental circumstances. As a result, -//! tests that compare results including demangled names can fail across development environments, -//! particularly with cross-platform testing. Also, the resulting crate paths are not syntactically -//! valid, and don't match the original source symbol paths, which can impact development tools. -//! -//! For these reasons, by default, `rust-demangler` uses a heuristic to remove crate disambiguators -//! from their original demangled representation before printing them to standard output. If crate -//! disambiguators are required, add the `-d` (or `--disambiguators`) flag, and the disambiguators -//! will not be removed. -//! -//! Also note that the disambiguators are stripped by a Regex pattern that is tolerant to some -//! variation in the number of hexadecimal digits. The disambiguators come from a hash value, which -//! typically generates a 16-digit hex representation on a 64-bit architecture; however, leading -//! zeros are not included, which can shorten the hex digit length, and a different hash algorithm -//! that might also be dependent on the architecture, might shorten the length even further. A -//! minimum length of 5 digits is assumed, which should be more than sufficient to support hex -//! representations that generate only 8-digits of precision with an extremely rare (but not -//! impossible) result with up to 3 leading zeros. -//! -//! Using a minimum number of digits less than 5 risks the possibility of stripping demangled name -//! components with a similar pattern. For example, some closures instantiated multiple times -//! include their own disambiguators, demangled as non-hashed zero-based indexes in square brackets. -//! These disambiguators seem to have more analytical value (for instance, in coverage analysis), so -//! they are not removed. - -use rust_demangler::*; -use std::io::{self, Read, Write}; - -fn main() -> io::Result<()> { - // FIXME(richkadel): In Issue #77615 discussed updating the `rustc-demangle` library, to provide - // an option to generate demangled names without including crate disambiguators. If that - // happens, update this tool to use that option (if the `-d` flag is not set) instead stripping - // them via the Regex heuristic. The update the doc comments and help. - - // Strip hashed hexadecimal crate disambiguators. Leading zeros are not enforced, and can be - // different across different platform/architecture types, so while 16 hex digits are common, - // they can also be shorter. - // - // Also note that a demangled symbol path may include the `[]` pattern, with zero-based - // indexes (such as for closures, and possibly for types defined in anonymous scopes). Preferably - // these should not be stripped. - // - // The minimum length of 5 digits supports the possibility that some target architecture (maybe - // a 32-bit or smaller architecture) could generate a hash value with a maximum of 8 digits, - // and more than three leading zeros should be extremely unlikely. Conversely, it should be - // sufficient to assume the zero-based indexes for closures and anonymous scopes will never - // exceed the value 9999. - let mut strip_crate_disambiguators = Some(create_disambiguator_re()); - - let mut args = std::env::args(); - let progname = args.next().unwrap(); - for arg in args { - if arg == "--disambiguators" || arg == "-d" { - strip_crate_disambiguators = None; - } else { - eprintln!(); - eprintln!("Usage: {} [-d|--disambiguators]", progname); - eprintln!(); - eprintln!( - "This tool converts a list of Rust mangled symbols (one per line) into a\n\ - corresponding list of demangled symbols." - ); - eprintln!(); - eprintln!( - "With -d (--disambiguators), Rust symbols mangled with the v0 symbol mangler may\n\ - include crate disambiguators (a hexadecimal hash value, typically up to 16 digits\n\ - long, enclosed in square brackets)." - ); - eprintln!(); - eprintln!( - "By default, crate disambiguators are removed, using a heuristics-based regular\n\ - expression. (See the `rust-demangler` doc comments for more information.)" - ); - eprintln!(); - std::process::exit(1) - } - } - - let mut buffer = String::new(); - io::stdin().read_to_string(&mut buffer)?; - let mut demangled_lines = demangle_lines(buffer.lines(), strip_crate_disambiguators); - demangled_lines.push("".to_string()); // ensure a trailing newline - io::stdout().write_all(demangled_lines.join("\n").as_bytes())?; - Ok(()) -} diff --git a/src/tools/rust-demangler/tests/lib.rs b/src/tools/rust-demangler/tests/lib.rs deleted file mode 100644 index 85019df7867dd..0000000000000 --- a/src/tools/rust-demangler/tests/lib.rs +++ /dev/null @@ -1,84 +0,0 @@ -use rust_demangler::*; - -const MANGLED_INPUT: &str = r" -_RNvC6_123foo3bar -_RNqCs4fqI2P2rA04_11utf8_identsu30____7hkackfecea1cbdathfdh9hlq6y -_RNCNCNgCs6DXkGYLi8lr_2cc5spawn00B5_ -_RNCINkXs25_NgCsbmNqQUJIY6D_4core5sliceINyB9_4IterhENuNgNoBb_4iter8iterator8Iterator9rpositionNCNgNpB9_6memchr7memrchrs_0E0Bb_ -_RINbNbCskIICzLVDPPb_5alloc5alloc8box_freeDINbNiB4_5boxed5FnBoxuEp6OutputuEL_ECs1iopQbuBiw2_3std -INtC8arrayvec8ArrayVechKj7b_E -_RMCs4fqI2P2rA04_13const_genericINtB0_8UnsignedKhb_E -_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKs98_E -_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKanb_E -_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb0_E -_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb1_E -_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc76_E -_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKca_E -_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc2202_E -_RNvNvMCs4fqI2P2rA04_13const_genericINtB4_3FooKpE3foo3FOO -_RC3foo.llvm.9D1C9369 -_RC3foo.llvm.9D1C9369@@16 -_RNvC9backtrace3foo.llvm.A5310EB9 -_RNvNtNtNtNtCs92dm3009vxr_4rand4rngs7adapter9reseeding4fork23FORK_HANDLER_REGISTERED.0.0 -"; - -const DEMANGLED_OUTPUT: &str = r" -123foo[0]::bar -utf8_idents[317d481089b8c8fe]::საჭმელად_გემრიელი_სადილი -cc[4d6468d6c9fd4bb3]::spawn::{closure#0}::{closure#0} - as core[846817f741e54dfd]::iter::iterator::Iterator>::rposition::::{closure#0} -alloc[f15a878b47eb696b]::alloc::box_free::> -INtC8arrayvec8ArrayVechKj7b_E -> -> -> -> -> -> -> -> ->::foo::FOO -foo[0] -foo[0] -backtrace[0]::foo -rand[693ea8e72247470f]::rngs::adapter::reseeding::fork::FORK_HANDLER_REGISTERED.0.0 -"; - -const DEMANGLED_OUTPUT_NO_CRATE_DISAMBIGUATORS: &str = r" -123foo[0]::bar -utf8_idents::საჭმელად_გემრიელი_სადილი -cc::spawn::{closure#0}::{closure#0} - as core::iter::iterator::Iterator>::rposition::::{closure#0} -alloc::alloc::box_free::> -INtC8arrayvec8ArrayVechKj7b_E -> -> -> -> -> -> -> -> ->::foo::FOO -foo[0] -foo[0] -backtrace[0]::foo -rand::rngs::adapter::reseeding::fork::FORK_HANDLER_REGISTERED.0.0 -"; - -#[test] -fn test_demangle_lines() { - let demangled_lines = demangle_lines(MANGLED_INPUT.lines(), None); - for (expected, actual) in DEMANGLED_OUTPUT.lines().zip(demangled_lines) { - assert_eq!(expected, actual); - } -} - -#[test] -fn test_demangle_lines_no_crate_disambiguators() { - let demangled_lines = demangle_lines(MANGLED_INPUT.lines(), Some(create_disambiguator_re())); - for (expected, actual) in DEMANGLED_OUTPUT_NO_CRATE_DISAMBIGUATORS.lines().zip(demangled_lines) - { - assert_eq!(expected, actual); - } -} diff --git a/tests/coverage/mcdc_non_control_flow.cov-map b/tests/coverage/mcdc_non_control_flow.cov-map new file mode 100644 index 0000000000000..937c36e1f16c4 --- /dev/null +++ b/tests/coverage/mcdc_non_control_flow.cov-map @@ -0,0 +1,204 @@ +Function name: mcdc_non_control_flow::assign_3 +Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 9 +- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add) +- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(4) +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +- expression 4 operands: lhs = Counter(0), rhs = Counter(1) +- expression 5 operands: lhs = Expression(8, Sub), rhs = Counter(4) +- expression 6 operands: lhs = Counter(0), rhs = Counter(1) +- expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(4) +- expression 8 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 40) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = (c1 + ((c2 + c3) + c4)) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) +- MCDCBranch { true: Counter(1), false: Expression(8, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Expression(8, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c0 - c1) +- MCDCBranch { true: Expression(7, Sub), false: Counter(4), condition_id: 2, true_next_id: 3, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) + true = ((c0 - c1) - c4) + false = c4 +- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 24) + = ((c0 - c1) - c4) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 3, true_next_id: 0, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = (c1 + ((c2 + c3) + c4)) + +Function name: mcdc_non_control_flow::assign_3_bis +Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 7 +- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(4) +- expression 1 operands: lhs = Counter(2), rhs = Counter(3) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Counter(1), rhs = Counter(2) +- expression 4 operands: lhs = Expression(5, Sub), rhs = Expression(6, Sub) +- expression 5 operands: lhs = Counter(1), rhs = Counter(2) +- expression 6 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 44) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = ((c2 + c3) + c4) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) +- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 3, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) +- MCDCBranch { true: Counter(2), false: Expression(5, Sub), condition_id: 3, true_next_id: 0, false_next_id: 2 } at (prev + 0, 18) to (start + 0, 19) + true = c2 + false = (c1 - c2) +- Code(Expression(4, Add)) at (prev + 0, 23) to (start + 0, 24) + = ((c1 - c2) + (c0 - c1)) +- MCDCBranch { true: Counter(3), false: Counter(4), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24) + true = c3 + false = c4 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = ((c2 + c3) + c4) + +Function name: mcdc_non_control_flow::assign_and +Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(3, Sub) +- expression 1 operands: lhs = Counter(2), rhs = Counter(3) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 33) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = ((c2 + c3) + (c0 - c1)) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) +- MCDCBranch { true: Counter(1), false: Expression(3, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = ((c2 + c3) + (c0 - c1)) + +Function name: mcdc_non_control_flow::assign_or +Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 32) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = ((c1 + c2) + c3) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) +- MCDCBranch { true: Counter(1), false: Expression(3, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Expression(3, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c0 - c1) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = ((c1 + c2) + c3) + +Function name: mcdc_non_control_flow::foo +Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2) + +Function name: mcdc_non_control_flow::func_call +Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 29, 01, 01, 0a, 28, 00, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 3 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15) +- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 9) to (start + 0, 10) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 14) to (start + 0, 15) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 14) to (start + 0, 15) + true = c2 + false = c3 +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = ((c2 + c3) + (c0 - c1)) + +Function name: mcdc_non_control_flow::right_comb_tree +Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 19 +- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(6, Sub) +- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(6) +- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(5) +- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(4) +- expression 4 operands: lhs = Counter(2), rhs = Counter(3) +- expression 5 operands: lhs = Counter(0), rhs = Counter(1) +- expression 6 operands: lhs = Counter(0), rhs = Counter(1) +- expression 7 operands: lhs = Counter(1), rhs = Counter(6) +- expression 8 operands: lhs = Counter(1), rhs = Counter(6) +- expression 9 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 10 operands: lhs = Counter(1), rhs = Counter(6) +- expression 11 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 12 operands: lhs = Counter(1), rhs = Counter(6) +- expression 13 operands: lhs = Expression(17, Sub), rhs = Counter(4) +- expression 14 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 15 operands: lhs = Counter(1), rhs = Counter(6) +- expression 16 operands: lhs = Expression(17, Sub), rhs = Counter(4) +- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 18 operands: lhs = Counter(1), rhs = Counter(6) +Number of file 0 mappings: 14 +- Code(Counter(0)) at (prev + 32, 1) to (start + 0, 65) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 5 } at (prev + 0, 13) to (start + 0, 42) +- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 19) to (start + 0, 20) +- MCDCBranch { true: Expression(18, Sub), false: Counter(6), condition_id: 2, true_next_id: 3, false_next_id: 0 } at (prev + 0, 19) to (start + 0, 20) + true = (c1 - c6) + false = c6 +- Code(Expression(18, Sub)) at (prev + 0, 25) to (start + 0, 26) + = (c1 - c6) +- MCDCBranch { true: Expression(17, Sub), false: Counter(5), condition_id: 3, true_next_id: 4, false_next_id: 0 } at (prev + 0, 25) to (start + 0, 26) + true = ((c1 - c6) - c5) + false = c5 +- Code(Expression(17, Sub)) at (prev + 0, 31) to (start + 0, 32) + = ((c1 - c6) - c5) +- MCDCBranch { true: Expression(16, Sub), false: Counter(4), condition_id: 4, true_next_id: 5, false_next_id: 0 } at (prev + 0, 31) to (start + 0, 32) + true = (((c1 - c6) - c5) - c4) + false = c4 +- Code(Expression(16, Sub)) at (prev + 0, 36) to (start + 0, 39) + = (((c1 - c6) - c5) - c4) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 5, true_next_id: 0, false_next_id: 0 } at (prev + 0, 36) to (start + 0, 39) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) + diff --git a/tests/coverage/mcdc_non_control_flow.coverage b/tests/coverage/mcdc_non_control_flow.coverage new file mode 100644 index 0000000000000..cd733885a98b6 --- /dev/null +++ b/tests/coverage/mcdc_non_control_flow.coverage @@ -0,0 +1,202 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2021 + LL| |//@ min-llvm-version: 18 + LL| |//@ compile-flags: -Zcoverage-options=mcdc + LL| |//@ llvm-cov-flags: --show-mcdc + LL| | + LL| |// This test ensures that boolean expressions that are not inside control flow + LL| |// decisions are correctly instrumented. + LL| | + LL| |use core::hint::black_box; + LL| | + LL| 3|fn assign_and(a: bool, b: bool) { + LL| 3| let x = a && b; + ^2 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:19) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:18) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, - = F } + | 2 { T, F = F } + | 3 { T, T = T } + | + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (2,3) + | MC/DC Coverage for Decision: 100.00% + | + ------------------ + LL| 3| black_box(x); + LL| 3|} + LL| | + LL| 3|fn assign_or(a: bool, b: bool) { + LL| 3| let x = a || b; + ^1 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:19) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:18) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, F = F } + | 2 { T, - = T } + | + | C1-Pair: covered: (1,2) + | C2-Pair: not covered + | MC/DC Coverage for Decision: 50.00% + | + ------------------ + LL| 3| black_box(x); + LL| 3|} + LL| | + LL| 4|fn assign_3(a: bool, b: bool, c: bool) { + LL| 4| let x = a || b && c; + ^2 ^1 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:24) + | + | Number of Conditions: 3 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:18) + | Condition C3 --> (LL:23) + | + | Executed MC/DC Test Vectors: + | + | C1, C2, C3 Result + | 1 { F, F, - = F } + | 2 { T, -, - = T } + | 3 { F, T, T = T } + | + | C1-Pair: covered: (1,2) + | C2-Pair: covered: (1,3) + | C3-Pair: not covered + | MC/DC Coverage for Decision: 66.67% + | + ------------------ + LL| 4| black_box(x); + LL| 4|} + LL| | + LL| 4|fn assign_3_bis(a: bool, b: bool, c: bool) { + LL| 4| let x = a && b || c; + ^2 ^3 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:24) + | + | Number of Conditions: 3 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:18) + | Condition C3 --> (LL:23) + | + | Executed MC/DC Test Vectors: + | + | C1, C2, C3 Result + | 1 { T, F, F = F } + | 2 { F, -, T = T } + | 3 { T, T, - = T } + | + | C1-Pair: not covered + | C2-Pair: covered: (1,3) + | C3-Pair: not covered + | MC/DC Coverage for Decision: 33.33% + | + ------------------ + LL| 4| black_box(x); + LL| 4|} + LL| | + LL| 3|fn right_comb_tree(a: bool, b: bool, c: bool, d: bool, e: bool) { + LL| 3| let x = a && (b && (c && (d && (e)))); + ^2 ^1 ^1 ^1 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:42) + | + | Number of Conditions: 5 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:19) + | Condition C3 --> (LL:25) + | Condition C4 --> (LL:31) + | Condition C5 --> (LL:36) + | + | Executed MC/DC Test Vectors: + | + | C1, C2, C3, C4, C5 Result + | 1 { F, -, -, -, - = F } + | 2 { T, F, -, -, - = F } + | 3 { T, T, T, T, T = T } + | + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (2,3) + | C3-Pair: not covered + | C4-Pair: not covered + | C5-Pair: not covered + | MC/DC Coverage for Decision: 40.00% + | + ------------------ + LL| 3| black_box(x); + LL| 3|} + LL| | + LL| 3|fn foo(a: bool) -> bool { + LL| 3| black_box(a) + LL| 3|} + LL| | + LL| 3|fn func_call(a: bool, b: bool) { + LL| 3| foo(a && b); + ^2 + ------------------ + |---> MC/DC Decision Region (LL:9) to (LL:15) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:9) + | Condition C2 --> (LL:14) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, - = F } + | 2 { T, F = F } + | 3 { T, T = T } + | + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (2,3) + | MC/DC Coverage for Decision: 100.00% + | + ------------------ + LL| 3|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | assign_and(true, false); + LL| | assign_and(true, true); + LL| | assign_and(false, false); + LL| | + LL| | assign_or(true, false); + LL| | assign_or(true, true); + LL| | assign_or(false, false); + LL| | + LL| | assign_3(true, false, false); + LL| | assign_3(true, true, false); + LL| | assign_3(false, false, true); + LL| | assign_3(false, true, true); + LL| | + LL| | assign_3_bis(true, false, false); + LL| | assign_3_bis(true, true, false); + LL| | assign_3_bis(false, false, true); + LL| | assign_3_bis(false, true, true); + LL| | + LL| | right_comb_tree(false, false, false, true, true); + LL| | right_comb_tree(true, false, false, true, true); + LL| | right_comb_tree(true, true, true, true, true); + LL| | + LL| | func_call(true, false); + LL| | func_call(true, true); + LL| | func_call(false, false); + LL| |} + diff --git a/tests/coverage/mcdc_non_control_flow.rs b/tests/coverage/mcdc_non_control_flow.rs new file mode 100644 index 0000000000000..85c0a6c6ae58a --- /dev/null +++ b/tests/coverage/mcdc_non_control_flow.rs @@ -0,0 +1,72 @@ +#![feature(coverage_attribute)] +//@ edition: 2021 +//@ min-llvm-version: 18 +//@ compile-flags: -Zcoverage-options=mcdc +//@ llvm-cov-flags: --show-mcdc + +// This test ensures that boolean expressions that are not inside control flow +// decisions are correctly instrumented. + +use core::hint::black_box; + +fn assign_and(a: bool, b: bool) { + let x = a && b; + black_box(x); +} + +fn assign_or(a: bool, b: bool) { + let x = a || b; + black_box(x); +} + +fn assign_3(a: bool, b: bool, c: bool) { + let x = a || b && c; + black_box(x); +} + +fn assign_3_bis(a: bool, b: bool, c: bool) { + let x = a && b || c; + black_box(x); +} + +fn right_comb_tree(a: bool, b: bool, c: bool, d: bool, e: bool) { + let x = a && (b && (c && (d && (e)))); + black_box(x); +} + +fn foo(a: bool) -> bool { + black_box(a) +} + +fn func_call(a: bool, b: bool) { + foo(a && b); +} + +#[coverage(off)] +fn main() { + assign_and(true, false); + assign_and(true, true); + assign_and(false, false); + + assign_or(true, false); + assign_or(true, true); + assign_or(false, false); + + assign_3(true, false, false); + assign_3(true, true, false); + assign_3(false, false, true); + assign_3(false, true, true); + + assign_3_bis(true, false, false); + assign_3_bis(true, true, false); + assign_3_bis(false, false, true); + assign_3_bis(false, true, true); + + right_comb_tree(false, false, false, true, true); + right_comb_tree(true, false, false, true, true); + right_comb_tree(true, true, true, true, true); + + func_call(true, false); + func_call(true, true); + func_call(false, false); +} diff --git a/tests/ui/impl-trait/lazy_subtyping_of_opaques.rs b/tests/ui/impl-trait/lazy_subtyping_of_opaques.rs index 65331894725a8..8fd1f35645a8a 100644 --- a/tests/ui/impl-trait/lazy_subtyping_of_opaques.rs +++ b/tests/ui/impl-trait/lazy_subtyping_of_opaques.rs @@ -2,58 +2,23 @@ //! No hidden types are being constrained in the subtyping predicate, but type and //! lifetime variables get subtyped in the generic parameter list of the opaque. -use std::iter; - -mod either { - pub enum Either { - Left(L), - Right(R), - } - - impl> Iterator for Either { - type Item = L::Item; - fn next(&mut self) -> Option { - todo!() - } - } - pub use self::Either::{Left, Right}; -} - -pub enum BabeConsensusLogRef<'a> { - NextEpochData(BabeNextEpochRef<'a>), - NextConfigData, -} - -impl<'a> BabeConsensusLogRef<'a> { - pub fn scale_encoding( - &self, - ) -> impl Iterator + Clone + 'a> + Clone + 'a { - //~^ ERROR is not satisfied - //~| ERROR is not satisfied - //~| ERROR is not satisfied - match self { - BabeConsensusLogRef::NextEpochData(digest) => either::Left(either::Left( - digest.scale_encoding().map(either::Left).map(either::Left), - )), - BabeConsensusLogRef::NextConfigData => either::Right( - // The Opaque type from ``scale_encoding` gets used opaquely here, while the `R` - // generic parameter of `Either` contains type variables that get subtyped and the - // opaque type contains lifetime variables that get subtyped. - iter::once(either::Right(either::Left([1]))) - .chain(std::iter::once([1]).map(either::Right).map(either::Right)), - ), - } - } -} - -pub struct BabeNextEpochRef<'a>(&'a ()); - -impl<'a> BabeNextEpochRef<'a> { - pub fn scale_encoding( - &self, - ) -> impl Iterator + Clone + 'a> + Clone + 'a { - std::iter::once([1]) +//@ check-pass + +fn foo() -> impl Default + Copy { + if false { + let x = Default::default(); + // add `Subtype(?x, ?y)` obligation + let y = x; + + // Make a tuple `(?x, ?y)` and equate it with `(impl Default, u32)`. + // For us to try and prove a `Subtype(impl Default, u32)` obligation, + // we have to instantiate both `?x` and `?y` without any + // `select_where_possible` calls inbetween. + let mut tup = &mut (x, y); + let assign_tup = &mut (foo(), 1u32); + tup = assign_tup; } + 1u32 } fn main() {} diff --git a/tests/ui/impl-trait/lazy_subtyping_of_opaques.stderr b/tests/ui/impl-trait/lazy_subtyping_of_opaques.stderr deleted file mode 100644 index 2f8c957c2c7dc..0000000000000 --- a/tests/ui/impl-trait/lazy_subtyping_of_opaques.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0277]: the trait bound `Either + Clone + '_> + Clone + '_, fn(impl AsRef<[u8]> + Clone + '_) -> Either + Clone + '_, _> {Either:: + Clone + '_, _>::Left}>, fn(Either + Clone + '_, _>) -> Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either:: + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Left}>, _>, std::iter::Chain + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>>, Map, fn([{integer}; 1]) -> Either<[{integer}; 1], [{integer}; 1]> {Either::<[{integer}; 1], [{integer}; 1]>::Right}>, fn(Either<[{integer}; 1], [{integer}; 1]>) -> Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either:: + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Right}>>>: Clone` is not satisfied - --> $DIR/lazy_subtyping_of_opaques.rs:30:10 - | -LL | ) -> impl Iterator + Clone + 'a> + Clone + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Either + Clone + '_> + Clone + '_, fn(impl AsRef<[u8]> + Clone + '_) -> Either + Clone + '_, _> {Either:: + Clone + '_, _>::Left}>, fn(Either + Clone + '_, _>) -> Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either:: + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Left}>, _>, std::iter::Chain + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>>, Map, fn([{integer}; 1]) -> Either<[{integer}; 1], [{integer}; 1]> {Either::<[{integer}; 1], [{integer}; 1]>::Right}>, fn(Either<[{integer}; 1], [{integer}; 1]>) -> Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either:: + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Right}>>>` - -error[E0277]: the trait bound `Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>: AsRef<[u8]>` is not satisfied - --> $DIR/lazy_subtyping_of_opaques.rs:30:31 - | -LL | ) -> impl Iterator + Clone + 'a> + Clone + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsRef<[u8]>` is not implemented for `Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>` - -error[E0277]: the trait bound `Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>: Clone` is not satisfied - --> $DIR/lazy_subtyping_of_opaques.rs:30:31 - | -LL | ) -> impl Iterator + Clone + 'a> + Clone + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs index 72a90287e374f..1bc352041a57d 100644 --- a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs +++ b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs @@ -7,9 +7,10 @@ type Tait = impl FnOnce() -> (); fn reify_as_tait() -> Thunk { + //~^ ERROR: expected a `FnOnce()` closure, found `()` Thunk::new(|cont| cont) //~^ ERROR: mismatched types - //~| ERROR: mismatched types + //~| ERROR: expected a `FnOnce()` closure, found `()` } struct Thunk(F); diff --git a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr index 5a35dc27446cb..7bc2fa1b09ea6 100644 --- a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr +++ b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr @@ -1,26 +1,31 @@ -error[E0308]: mismatched types - --> $DIR/lazy_subtyping_of_opaques.rs:10:23 +error[E0277]: expected a `FnOnce()` closure, found `()` + --> $DIR/lazy_subtyping_of_opaques.rs:11:23 | -LL | type Tait = impl FnOnce() -> (); - | ------------------- the found opaque type -... LL | Thunk::new(|cont| cont) - | ^^^^ expected `()`, found opaque type + | ^^^^ expected an `FnOnce()` closure, found `()` | - = note: expected unit type `()` - found opaque type `Tait` + = help: the trait `FnOnce()` is not implemented for `()` + = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` -error[E0308]: mismatched types - --> $DIR/lazy_subtyping_of_opaques.rs:10:5 +error[E0277]: expected a `FnOnce()` closure, found `()` + --> $DIR/lazy_subtyping_of_opaques.rs:9:23 | LL | fn reify_as_tait() -> Thunk { - | ----------- expected `Thunk<_>` because of return type + | ^^^^^^^^^^^ expected an `FnOnce()` closure, found `()` + | + = help: the trait `FnOnce()` is not implemented for `()` + = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` + +error[E0308]: mismatched types + --> $DIR/lazy_subtyping_of_opaques.rs:11:5 + | LL | Thunk::new(|cont| cont) | ^^^^^^^^^^^^^^^^^^^^^^^ expected `Thunk<_>`, found `()` | = note: expected struct `Thunk<_>` found unit type `()` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`.