From f86b143602a626f8516a496aa15464ead79c1f3e Mon Sep 17 00:00:00 2001 From: bors Date: Thu, 4 Feb 2021 20:30:11 +0000 Subject: [PATCH 01/10] Auto merge of #81762 - pietroalbini:fix-install-msys2, r=m-ou-se CI: only copy python.exe to python3.exe if the latter does not exist We're copying the binary to make sure we can call `python3.exe` around, but it seems like the base image of GitHub Actions changed, copying the file before we do so. This PR changes the CI script to only copy the file if it doesn't already exist. r? `@m-ou-se` cc `@Mark-Simulacrum` --- src/ci/scripts/install-msys2.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ci/scripts/install-msys2.sh b/src/ci/scripts/install-msys2.sh index 185d361582505..0aa4b42a6a8fb 100755 --- a/src/ci/scripts/install-msys2.sh +++ b/src/ci/scripts/install-msys2.sh @@ -24,7 +24,9 @@ if isWindows; then # baked in which break LLVM's build system one way or another, so let's use the # native version which keeps everything as native as possible. python_home="/c/hostedtoolcache/windows/Python/${native_python_version}/x64" - cp "${python_home}/python.exe" "${python_home}/python3.exe" + if ! [[ -f "${python_home}/python3.exe" ]]; then + cp "${python_home}/python.exe" "${python_home}/python3.exe" + fi ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\${native_python_version}\\x64" ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\${native_python_version}\\x64\\Scripts" fi From 567eb04105cd4441b441b152bf637ad408832d81 Mon Sep 17 00:00:00 2001 From: bors Date: Thu, 28 Jan 2021 18:57:10 +0000 Subject: [PATCH 02/10] Auto merge of #81055 - matthewjasper:non-fatal-overflow, r=nikomatsakis Make hitting the recursion limit in projection non-fatal This change was originally made in #80246 to avoid future (effectively) infinite loop bugs in projections, but wundergraph relies on rustc recovering here. cc #80953 r? `@nikomatsakis` --- .../src/traits/project.rs | 11 +--- .../src/traits/select/mod.rs | 4 -- .../project-recursion-limit-non-fatal.rs | 58 +++++++++++++++++++ src/test/ui/issues/issue-23122-2.stderr | 3 +- 4 files changed, 63 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/associated-types/project-recursion-limit-non-fatal.rs diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index fa0526445c194..f22b5b9661699 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -736,14 +736,9 @@ fn project_type<'cx, 'tcx>( if !selcx.tcx().sess.recursion_limit().value_within_limit(obligation.recursion_depth) { debug!("project: overflow!"); - match selcx.query_mode() { - super::TraitQueryMode::Standard => { - selcx.infcx().report_overflow_error(&obligation, true); - } - super::TraitQueryMode::Canonical => { - return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow)); - } - } + // This should really be an immediate error, but some existing code + // relies on being able to recover from this. + return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow)); } let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx()); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a8f81445b0397..f1c86eab0956e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -291,10 +291,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.tcx } - pub(super) fn query_mode(&self) -> TraitQueryMode { - self.query_mode - } - /////////////////////////////////////////////////////////////////////////// // Selection // diff --git a/src/test/ui/associated-types/project-recursion-limit-non-fatal.rs b/src/test/ui/associated-types/project-recursion-limit-non-fatal.rs new file mode 100644 index 0000000000000..3e68b1401020f --- /dev/null +++ b/src/test/ui/associated-types/project-recursion-limit-non-fatal.rs @@ -0,0 +1,58 @@ +// Regression test for #80953. Hitting the recursion limit in projection +// is non-fatal. The above code, minimised from wundergraph shows a case +// where this is relied on. + +// check-pass + +struct AlternateTable {} +struct AlternateQuery {} + +pub trait Query {} +pub trait AsQuery { + type Query; +} +impl AsQuery for T { + type Query = Self; +} +impl AsQuery for AlternateTable { + type Query = AlternateQuery; +} + +pub trait Table: AsQuery { + type PrimaryKey; +} +impl Table for AlternateTable { + type PrimaryKey = (); +} + +pub trait FilterDsl { + type Output; +} +pub type Filter = >::Output; +impl FilterDsl for T +where + T: Table, + T::Query: FilterDsl, +{ + type Output = Filter; +} +impl FilterDsl for AlternateQuery { + type Output = &'static str; +} + +pub trait HandleDelete { + type Filter; +} +impl HandleDelete for T +where + T: Table, + T::Query: FilterDsl, + Filter: , +{ + type Filter = Filter; +} + +fn main() { + let x: ::Filter = "Hello, world"; + println!("{}", x); +} diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr index ff7e884ea6f83..ce3bffe602ca0 100644 --- a/src/test/ui/issues/issue-23122-2.stderr +++ b/src/test/ui/issues/issue-23122-2.stderr @@ -1,10 +1,11 @@ -error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next` +error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized` --> $DIR/issue-23122-2.rs:9:5 | LL | type Next = as Next>::Next; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`) + = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` error: aborting due to previous error From f6b8e2be8da317318eb3639681f6cd3bec20a355 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 3 Feb 2021 18:51:14 +0100 Subject: [PATCH 03/10] Rollup merge of #81532 - estebank:ice-ice-baby, r=pnkfelix Remove incorrect `delay_span_bug` The following code is supposed to compile ```rust use std::ops::BitOr; pub trait IntWrapper { type InternalStorage; } impl BitOr for dyn IntWrapper where Self: Sized, T: BitOr + BitOr, { type Output = Self; fn bitor(self, _other: Self) -> Self { todo!() } } ``` Before this change it would ICE. In #70998 the removed logic was added to provide better suggestions, and the `delay_span_bug` guard was added to protect against a potential logic error when returning traits. As it happens, there are cases, like the one above, where traits can indeed be returned, so valid code was being rejected. Fix (but not close) #80207. --- compiler/rustc_typeck/src/check/check.rs | 1 - .../ui/typeck/issue-80207-unsized-return.rs | 20 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/typeck/issue-80207-unsized-return.rs diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index ec7369fd3e8ee..d235ad21c7b95 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -188,7 +188,6 @@ pub(super) fn check_fn<'a, 'tcx>( // possible cases. fcx.check_expr(&body.value); fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); - tcx.sess.delay_span_bug(decl.output.span(), "`!Sized` return type"); } else { fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); fcx.check_return_expr(&body.value); diff --git a/src/test/ui/typeck/issue-80207-unsized-return.rs b/src/test/ui/typeck/issue-80207-unsized-return.rs new file mode 100644 index 0000000000000..75430da148239 --- /dev/null +++ b/src/test/ui/typeck/issue-80207-unsized-return.rs @@ -0,0 +1,20 @@ +// check-pass + +trait Foo { + fn do_stuff() -> Self; +} + +trait Bar { + type Output; +} + +impl Foo for dyn Bar +where + Self: Sized, +{ + fn do_stuff() -> Self { + todo!() + } +} + +fn main() {} From 3b034464a48ff1e75d4db765ee4bf51134975141 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 4 Feb 2021 21:10:34 +0100 Subject: [PATCH 04/10] Rollup merge of #81556 - nikomatsakis:forbidden-lint-groups-lint, r=pnkfelix introduce future-compatibility warning for forbidden lint groups We used to ignore `forbid(group)` scenarios completely. This changed in #78864, but that led to a number of regressions (#80988, #81218). This PR introduces a future compatibility warning for the case where a group is forbidden but then an individual lint within that group is allowed. We now issue a FCW when we see the "allow", but permit it to take effect. r? ``@Mark-Simulacrum`` --- compiler/rustc_lint/src/context.rs | 15 +++ compiler/rustc_lint/src/levels.rs | 101 ++++++++++----- compiler/rustc_lint_defs/src/builtin.rs | 37 ++++++ compiler/rustc_middle/src/lint.rs | 14 ++- src/test/ui/lint/forbid-group-group-1.rs | 13 ++ src/test/ui/lint/forbid-group-group-1.stderr | 15 +++ src/test/ui/lint/forbid-group-group-2.rs | 26 ++++ src/test/ui/lint/forbid-group-group-2.stderr | 115 ++++++++++++++++++ src/test/ui/lint/forbid-group-member.rs | 19 +++ src/test/ui/lint/forbid-group-member.stderr | 51 ++++++++ src/test/ui/lint/forbid-member-group.rs | 12 ++ src/test/ui/lint/forbid-member-group.stderr | 30 +++++ ...0819-dont-override-forbid-in-same-scope.rs | 7 +- ...-dont-override-forbid-in-same-scope.stderr | 30 ++--- src/test/ui/lint/issue-80988.rs | 16 +++ src/test/ui/lint/issue-80988.stderr | 51 ++++++++ src/test/ui/lint/issue-81218.rs | 14 +++ src/test/ui/lint/outer-forbid.rs | 5 + src/test/ui/lint/outer-forbid.stderr | 37 ++++-- 19 files changed, 553 insertions(+), 55 deletions(-) create mode 100644 src/test/ui/lint/forbid-group-group-1.rs create mode 100644 src/test/ui/lint/forbid-group-group-1.stderr create mode 100644 src/test/ui/lint/forbid-group-group-2.rs create mode 100644 src/test/ui/lint/forbid-group-group-2.stderr create mode 100644 src/test/ui/lint/forbid-group-member.rs create mode 100644 src/test/ui/lint/forbid-group-member.stderr create mode 100644 src/test/ui/lint/forbid-member-group.rs create mode 100644 src/test/ui/lint/forbid-member-group.stderr create mode 100644 src/test/ui/lint/issue-80988.rs create mode 100644 src/test/ui/lint/issue-80988.stderr create mode 100644 src/test/ui/lint/issue-81218.rs diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index bfeef4904893a..780bf5fecffe3 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -39,6 +39,7 @@ use rustc_session::SessionLintStore; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP}; use rustc_target::abi::LayoutOf; +use tracing::debug; use std::cell::Cell; use std::slice; @@ -335,6 +336,20 @@ impl LintStore { } } + /// True if this symbol represents a lint group name. + pub fn is_lint_group(&self, lint_name: Symbol) -> bool { + debug!( + "is_lint_group(lint_name={:?}, lint_groups={:?})", + lint_name, + self.lint_groups.keys().collect::>() + ); + let lint_name_str = &*lint_name.as_str(); + self.lint_groups.contains_key(&lint_name_str) || { + let warnings_name_str = crate::WARNINGS.name_lower(); + lint_name_str == &*warnings_name_str + } + } + /// Checks the name of a lint for its existence, and whether it was /// renamed or removed. Generates a DiagnosticBuilder containing a /// warning for renamed and removed lints. This is over both lint diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 5cece569903c7..570578ff08f17 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -5,7 +5,7 @@ use rustc_ast::attr; use rustc_ast::unwrap_or; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{struct_span_err, Applicability}; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::{intravisit, HirId}; @@ -17,11 +17,15 @@ use rustc_middle::lint::{ }; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; -use rustc_session::lint::{builtin, Level, Lint, LintId}; +use rustc_session::lint::{ + builtin::{self, FORBIDDEN_LINT_GROUPS}, + Level, Lint, LintId, +}; use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{source_map::MultiSpan, Span, DUMMY_SP}; +use tracing::debug; use std::cmp; @@ -51,6 +55,7 @@ pub struct LintLevelsBuilder<'s> { id_to_set: FxHashMap, cur: u32, warn_about_weird_lints: bool, + store: &'s LintStore, } pub struct BuilderPush { @@ -59,13 +64,14 @@ pub struct BuilderPush { } impl<'s> LintLevelsBuilder<'s> { - pub fn new(sess: &'s Session, warn_about_weird_lints: bool, store: &LintStore) -> Self { + pub fn new(sess: &'s Session, warn_about_weird_lints: bool, store: &'s LintStore) -> Self { let mut builder = LintLevelsBuilder { sess, sets: LintLevelSets::new(), cur: 0, id_to_set: Default::default(), warn_about_weird_lints, + store, }; builder.process_command_line(sess, store); assert_eq!(builder.sets.list.len(), 1); @@ -120,36 +126,75 @@ impl<'s> LintLevelsBuilder<'s> { if let (Level::Forbid, old_src) = self.sets.get_lint_level(id.lint, self.cur, Some(&specs), &self.sess) { - let mut diag_builder = struct_span_err!( - self.sess, - src.span(), - E0453, - "{}({}) incompatible with previous forbid", - level.as_str(), - src.name(), + // Backwards compatibility check: + // + // We used to not consider `forbid(lint_group)` + // as preventing `allow(lint)` for some lint `lint` in + // `lint_group`. For now, issue a future-compatibility + // warning for this case. + let id_name = id.lint.name_lower(); + let fcw_warning = match old_src { + LintLevelSource::Default => false, + LintLevelSource::Node(symbol, _, _) => self.store.is_lint_group(symbol), + LintLevelSource::CommandLine(symbol, _) => self.store.is_lint_group(symbol), + }; + debug!( + "fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}", + fcw_warning, specs, old_src, id_name ); - diag_builder.span_label(src.span(), "overruled by previous forbid"); - match old_src { - LintLevelSource::Default => { - diag_builder.note(&format!( - "`forbid` lint level is the default for {}", - id.to_string() - )); - } - LintLevelSource::Node(_, forbid_source_span, reason) => { - diag_builder.span_label(forbid_source_span, "`forbid` level set here"); - if let Some(rationale) = reason { - diag_builder.note(&rationale.as_str()); + + let decorate_diag_builder = |mut diag_builder: DiagnosticBuilder<'_>| { + diag_builder.span_label(src.span(), "overruled by previous forbid"); + match old_src { + LintLevelSource::Default => { + diag_builder.note(&format!( + "`forbid` lint level is the default for {}", + id.to_string() + )); + } + LintLevelSource::Node(_, forbid_source_span, reason) => { + diag_builder.span_label(forbid_source_span, "`forbid` level set here"); + if let Some(rationale) = reason { + diag_builder.note(&rationale.as_str()); + } + } + LintLevelSource::CommandLine(_, _) => { + diag_builder.note("`forbid` lint level was set on command line"); } } - LintLevelSource::CommandLine(_, _) => { - diag_builder.note("`forbid` lint level was set on command line"); - } + diag_builder.emit(); + }; + if !fcw_warning { + let diag_builder = struct_span_err!( + self.sess, + src.span(), + E0453, + "{}({}) incompatible with previous forbid", + level.as_str(), + src.name(), + ); + decorate_diag_builder(diag_builder); + } else { + self.struct_lint( + FORBIDDEN_LINT_GROUPS, + Some(src.span().into()), + |diag_builder| { + let diag_builder = diag_builder.build(&format!( + "{}({}) incompatible with previous forbid", + level.as_str(), + src.name(), + )); + decorate_diag_builder(diag_builder); + }, + ); } - diag_builder.emit(); - // Retain the forbid lint level - return; + // Retain the forbid lint level, unless we are + // issuing a FCW. In the FCW case, we want to + // respect the new setting. + if !fcw_warning { + return; + } } } specs.insert(id, (level, src)); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 1c692d4f20762..655eb229e6c8e 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -8,6 +8,42 @@ use crate::{declare_lint, declare_lint_pass, declare_tool_lint}; use rustc_span::edition::Edition; use rustc_span::symbol::sym; +declare_lint! { + /// The `forbidden_lint_groups` lint detects violations of + /// `forbid` applied to a lint group. Due to a bug in the compiler, + /// these used to be overlooked entirely. They now generate a warning. + /// + /// ### Example + /// + /// ```rust + /// #![forbid(warnings)] + /// #![deny(bad_style)] + /// + /// fn main() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Recommended fix + /// + /// If your crate is using `#![forbid(warnings)]`, + /// we recommend that you change to `#![deny(warnings)]`. + /// + /// ### Explanation + /// + /// Due to a compiler bug, applying `forbid` to lint groups + /// previously had no effect. The bug is now fixed but instead of + /// enforcing `forbid` we issue this future-compatibility warning + /// to avoid breaking existing crates. + pub FORBIDDEN_LINT_GROUPS, + Warn, + "applying forbid to lint-groups", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #81670 ", + edition: None, + }; +} + declare_lint! { /// The `ill_formed_attribute_input` lint detects ill-formed attribute /// inputs that were previously accepted and used in practice. @@ -2839,6 +2875,7 @@ declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. HardwiredLints => [ + FORBIDDEN_LINT_GROUPS, ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, ARITHMETIC_OVERFLOW, UNCONDITIONAL_PANIC, diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 64d850192f449..bd724a5830470 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -5,14 +5,17 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_hir::HirId; -use rustc_session::lint::{builtin, Level, Lint, LintId}; +use rustc_session::lint::{ + builtin::{self, FORBIDDEN_LINT_GROUPS}, + Level, Lint, LintId, +}; use rustc_session::{DiagnosticMessageId, Session}; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan}; use rustc_span::{symbol, Span, Symbol, DUMMY_SP}; /// How a lint level was set. -#[derive(Clone, Copy, PartialEq, Eq, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, HashStable, Debug)] pub enum LintLevelSource { /// Lint is at the default level as declared /// in rustc or a plugin. @@ -87,7 +90,12 @@ impl LintLevelSets { // If we're about to issue a warning, check at the last minute for any // directives against the warnings "lint". If, for example, there's an // `allow(warnings)` in scope then we want to respect that instead. - if level == Level::Warn { + // + // We exempt `FORBIDDEN_LINT_GROUPS` from this because it specifically + // triggers in cases (like #80988) where you have `forbid(warnings)`, + // and so if we turned that into an error, it'd defeat the purpose of the + // future compatibility warning. + if level == Level::Warn && LintId::of(lint) != LintId::of(FORBIDDEN_LINT_GROUPS) { let (warnings_level, warnings_src) = self.get_lint_id_level(LintId::of(builtin::WARNINGS), idx, aux); if let Some(configured_warning_level) = warnings_level { diff --git a/src/test/ui/lint/forbid-group-group-1.rs b/src/test/ui/lint/forbid-group-group-1.rs new file mode 100644 index 0000000000000..80f7db4e56036 --- /dev/null +++ b/src/test/ui/lint/forbid-group-group-1.rs @@ -0,0 +1,13 @@ +// Check what happens when we forbid a smaller group but +// then allow a superset of that group. + +#![forbid(nonstandard_style)] + +// FIXME: Arguably this should be an error, but the WARNINGS group is +// treated in a very special (and rather ad-hoc) way and +// it fails to trigger. +#[allow(warnings)] +fn main() { + let A: (); + //~^ ERROR should have a snake case name +} diff --git a/src/test/ui/lint/forbid-group-group-1.stderr b/src/test/ui/lint/forbid-group-group-1.stderr new file mode 100644 index 0000000000000..fd425e5f74e6f --- /dev/null +++ b/src/test/ui/lint/forbid-group-group-1.stderr @@ -0,0 +1,15 @@ +error: variable `A` should have a snake case name + --> $DIR/forbid-group-group-1.rs:11:9 + | +LL | let A: (); + | ^ help: convert the identifier to snake case: `a` + | +note: the lint level is defined here + --> $DIR/forbid-group-group-1.rs:4:11 + | +LL | #![forbid(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ + = note: `#[forbid(non_snake_case)]` implied by `#[forbid(nonstandard_style)]` + +error: aborting due to previous error + diff --git a/src/test/ui/lint/forbid-group-group-2.rs b/src/test/ui/lint/forbid-group-group-2.rs new file mode 100644 index 0000000000000..b12fd72da7494 --- /dev/null +++ b/src/test/ui/lint/forbid-group-group-2.rs @@ -0,0 +1,26 @@ +// Check what happens when we forbid a bigger group but +// then deny a subset of that group. + +#![forbid(warnings)] +#![deny(forbidden_lint_groups)] + +#[allow(nonstandard_style)] +//~^ ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +fn main() {} diff --git a/src/test/ui/lint/forbid-group-group-2.stderr b/src/test/ui/lint/forbid-group-group-2.stderr new file mode 100644 index 0000000000000..214e949c11a74 --- /dev/null +++ b/src/test/ui/lint/forbid-group-group-2.stderr @@ -0,0 +1,115 @@ +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | +note: the lint level is defined here + --> $DIR/forbid-group-group-2.rs:5:9 + | +LL | #![deny(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/lint/forbid-group-member.rs b/src/test/ui/lint/forbid-group-member.rs new file mode 100644 index 0000000000000..6f1b2e9f66812 --- /dev/null +++ b/src/test/ui/lint/forbid-group-member.rs @@ -0,0 +1,19 @@ +// Check what happens when we forbid a group but +// then allow a member of that group. +// +// check-pass + +#![forbid(unused)] + +#[allow(unused_variables)] +//~^ WARNING incompatible with previous forbid +//~| WARNING previously accepted +//~| WARNING incompatible with previous forbid +//~| WARNING previously accepted +//~| WARNING incompatible with previous forbid +//~| WARNING previously accepted +//~| WARNING incompatible with previous forbid +//~| WARNING previously accepted +fn main() { + let a: (); +} diff --git a/src/test/ui/lint/forbid-group-member.stderr b/src/test/ui/lint/forbid-group-member.stderr new file mode 100644 index 0000000000000..c818d7ff60605 --- /dev/null +++ b/src/test/ui/lint/forbid-group-member.stderr @@ -0,0 +1,51 @@ +warning: allow(unused_variables) incompatible with previous forbid + --> $DIR/forbid-group-member.rs:8:9 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = note: `#[warn(forbidden_lint_groups)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +warning: allow(unused_variables) incompatible with previous forbid + --> $DIR/forbid-group-member.rs:8:9 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +warning: allow(unused_variables) incompatible with previous forbid + --> $DIR/forbid-group-member.rs:8:9 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +warning: allow(unused_variables) incompatible with previous forbid + --> $DIR/forbid-group-member.rs:8:9 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +warning: 4 warnings emitted + diff --git a/src/test/ui/lint/forbid-member-group.rs b/src/test/ui/lint/forbid-member-group.rs new file mode 100644 index 0000000000000..3279029a9cbc3 --- /dev/null +++ b/src/test/ui/lint/forbid-member-group.rs @@ -0,0 +1,12 @@ +// Check what happens when we forbid a member of +// a group but then allow the group. + +#![forbid(unused_variables)] + +#[allow(unused)] +//~^ ERROR incompatible with previous forbid +//~| ERROR incompatible with previous forbid +//~| ERROR incompatible with previous forbid +fn main() { + let a: (); +} diff --git a/src/test/ui/lint/forbid-member-group.stderr b/src/test/ui/lint/forbid-member-group.stderr new file mode 100644 index 0000000000000..1d8ab4d5edb0c --- /dev/null +++ b/src/test/ui/lint/forbid-member-group.stderr @@ -0,0 +1,30 @@ +error[E0453]: allow(unused) incompatible with previous forbid + --> $DIR/forbid-member-group.rs:6:9 + | +LL | #![forbid(unused_variables)] + | ---------------- `forbid` level set here +LL | +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + +error[E0453]: allow(unused) incompatible with previous forbid + --> $DIR/forbid-member-group.rs:6:9 + | +LL | #![forbid(unused_variables)] + | ---------------- `forbid` level set here +LL | +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + +error[E0453]: allow(unused) incompatible with previous forbid + --> $DIR/forbid-member-group.rs:6:9 + | +LL | #![forbid(unused_variables)] + | ---------------- `forbid` level set here +LL | +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs index f725304cf29d4..05d7d924c8fab 100644 --- a/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs +++ b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs @@ -14,14 +14,17 @@ // compile-flags: -Z deduplicate-diagnostics=yes +#![forbid(forbidden_lint_groups)] + fn forbid_first(num: i32) -> i32 { #![forbid(unused)] #![deny(unused)] //~^ ERROR: deny(unused) incompatible with previous forbid + //~| WARNING being phased out + //~| ERROR: deny(unused) incompatible with previous forbid + //~| WARNING being phased out #![warn(unused)] - //~^ ERROR: warn(unused) incompatible with previous forbid #![allow(unused)] - //~^ ERROR: allow(unused) incompatible with previous forbid num * num } diff --git a/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr index 9f107411c102a..475410cecffa3 100644 --- a/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr +++ b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr @@ -1,29 +1,29 @@ -error[E0453]: deny(unused) incompatible with previous forbid - --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:19:13 +error: deny(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:21:13 | LL | #![forbid(unused)] | ------ `forbid` level set here LL | #![deny(unused)] | ^^^^^^ overruled by previous forbid + | +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 -error[E0453]: warn(unused) incompatible with previous forbid +error: deny(unused) incompatible with previous forbid --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:21:13 | LL | #![forbid(unused)] | ------ `forbid` level set here -... -LL | #![warn(unused)] +LL | #![deny(unused)] | ^^^^^^ overruled by previous forbid - -error[E0453]: allow(unused) incompatible with previous forbid - --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:23:14 | -LL | #![forbid(unused)] - | ------ `forbid` level set here -... -LL | #![allow(unused)] - | ^^^^^^ overruled by previous forbid + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui/lint/issue-80988.rs b/src/test/ui/lint/issue-80988.rs new file mode 100644 index 0000000000000..16a041928db73 --- /dev/null +++ b/src/test/ui/lint/issue-80988.rs @@ -0,0 +1,16 @@ +// Regression test for #80988 +// +// check-pass + +#![forbid(warnings)] + +#[deny(warnings)] +//~^ WARNING incompatible with previous forbid +//~| WARNING being phased out +//~| WARNING incompatible with previous forbid +//~| WARNING being phased out +//~| WARNING incompatible with previous forbid +//~| WARNING being phased out +//~| WARNING incompatible with previous forbid +//~| WARNING being phased out +fn main() {} diff --git a/src/test/ui/lint/issue-80988.stderr b/src/test/ui/lint/issue-80988.stderr new file mode 100644 index 0000000000000..4cae11f97c0fb --- /dev/null +++ b/src/test/ui/lint/issue-80988.stderr @@ -0,0 +1,51 @@ +warning: deny(warnings) incompatible with previous forbid + --> $DIR/issue-80988.rs:7:8 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +LL | +LL | #[deny(warnings)] + | ^^^^^^^^ overruled by previous forbid + | + = note: `#[warn(forbidden_lint_groups)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +warning: deny(warnings) incompatible with previous forbid + --> $DIR/issue-80988.rs:7:8 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +LL | +LL | #[deny(warnings)] + | ^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +warning: deny(warnings) incompatible with previous forbid + --> $DIR/issue-80988.rs:7:8 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +LL | +LL | #[deny(warnings)] + | ^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +warning: deny(warnings) incompatible with previous forbid + --> $DIR/issue-80988.rs:7:8 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +LL | +LL | #[deny(warnings)] + | ^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +warning: 4 warnings emitted + diff --git a/src/test/ui/lint/issue-81218.rs b/src/test/ui/lint/issue-81218.rs new file mode 100644 index 0000000000000..f02aa9040ebc5 --- /dev/null +++ b/src/test/ui/lint/issue-81218.rs @@ -0,0 +1,14 @@ +// Regression test for #81218 +// +// check-pass + +#![forbid(warnings)] + +#[allow(unused_variables)] +fn main() { + // We want to ensure that you don't get an error + // here. The idea is that a derive might generate + // code that would otherwise trigger the "unused variables" + // lint, but it is meant to be suppressed. + let x: (); +} diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs index d45848bf706f3..486ec3c46804f 100644 --- a/src/test/ui/lint/outer-forbid.rs +++ b/src/test/ui/lint/outer-forbid.rs @@ -15,11 +15,16 @@ // compile-flags: -Z deduplicate-diagnostics=yes #![forbid(unused, non_snake_case)] +#![forbid(forbidden_lint_groups)] #[allow(unused_variables)] //~ ERROR incompatible with previous +//~^ ERROR incompatible with previous +//~| WARNING this was previously accepted by the compiler +//~| WARNING this was previously accepted by the compiler fn foo() {} #[allow(unused)] //~ ERROR incompatible with previous +//~^ WARNING this was previously accepted by the compiler fn bar() {} #[allow(nonstandard_style)] //~ ERROR incompatible with previous diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr index c012c20697e16..d69157a8bb3ad 100644 --- a/src/test/ui/lint/outer-forbid.stderr +++ b/src/test/ui/lint/outer-forbid.stderr @@ -1,23 +1,34 @@ -error[E0453]: allow(unused_variables) incompatible with previous forbid - --> $DIR/outer-forbid.rs:19:9 +error: allow(unused_variables) incompatible with previous forbid + --> $DIR/outer-forbid.rs:20:9 | LL | #![forbid(unused, non_snake_case)] | ------ `forbid` level set here -LL | +... LL | #[allow(unused_variables)] | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 -error[E0453]: allow(unused) incompatible with previous forbid - --> $DIR/outer-forbid.rs:22:9 +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:26:9 | LL | #![forbid(unused, non_snake_case)] | ------ `forbid` level set here ... LL | #[allow(unused)] | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 error[E0453]: allow(nonstandard_style) incompatible with previous forbid - --> $DIR/outer-forbid.rs:25:9 + --> $DIR/outer-forbid.rs:30:9 | LL | #![forbid(unused, non_snake_case)] | -------------- `forbid` level set here @@ -25,6 +36,18 @@ LL | #![forbid(unused, non_snake_case)] LL | #[allow(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ overruled by previous forbid -error: aborting due to 3 previous errors +error: allow(unused_variables) incompatible with previous forbid + --> $DIR/outer-forbid.rs:20:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0453`. From d1eff4c300f6ec268c9820c5d5b6008929f71f79 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 4 Feb 2021 09:08:42 -0800 Subject: [PATCH 05/10] [beta] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 1a8df6a5196e4..f04e7fab73128 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 1a8df6a5196e4cad9a3956867e7e928f2bfaaba4 +Subproject commit f04e7fab73128592a4063983c302da788bdfaba5 From 7906dc00fbfb610fa70169eb9c4ebc82c15aac35 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 23 Jan 2021 20:16:16 +0100 Subject: [PATCH 06/10] Rollup merge of #81288 - camelid:fix-trait-item-vis, r=jyn514 rustdoc: Fix visibility of trait and impl items Fixes #81274. r? `@jyn514` --- src/librustdoc/clean/mod.rs | 21 +++++++++++++++++++-- src/test/rustdoc/visibility.rs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index cd59e7d32dde8..2ac8950bcac3c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1096,7 +1096,10 @@ impl Clean for hir::TraitItem<'_> { AssocTypeItem(bounds.clean(cx), default.clean(cx)) } }; - Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx) + let what_rustc_thinks = + Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx); + // Trait items always inherit the trait's visibility -- we don't want to show `pub`. + Item { visibility: Inherited, ..what_rustc_thinks } }) } } @@ -1124,7 +1127,21 @@ impl Clean for hir::ImplItem<'_> { TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true) } }; - Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx) + + let what_rustc_thinks = + Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx); + let parent_item = cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(self.hir_id)); + if let hir::ItemKind::Impl { of_trait, .. } = &parent_item.kind { + if of_trait.is_some() { + // Trait impl items always inherit the impl's visibility -- + // we don't want to show `pub`. + Item { visibility: Inherited, ..what_rustc_thinks } + } else { + what_rustc_thinks + } + } else { + panic!("found impl item with non-impl parent {:?}", parent_item); + } }) } } diff --git a/src/test/rustdoc/visibility.rs b/src/test/rustdoc/visibility.rs index 59427693c5a5d..beb638406c4be 100644 --- a/src/test/rustdoc/visibility.rs +++ b/src/test/rustdoc/visibility.rs @@ -42,3 +42,35 @@ mod a { struct FooBPriv; } } + +// @has 'foo/trait.PubTrait.html' '//pre' 'pub trait PubTrait' +// +// @has 'foo/trait.PubTrait.html' '//pre' 'type Type;' +// @!has 'foo/trait.PubTrait.html' '//pre' 'pub type Type;' +// +// @has 'foo/trait.PubTrait.html' '//pre' 'const CONST: usize;' +// @!has 'foo/trait.PubTrait.html' '//pre' 'pub const CONST: usize;' +// +// @has 'foo/trait.PubTrait.html' '//pre' 'fn function();' +// @!has 'foo/trait.PubTrait.html' '//pre' 'pub fn function();' + +pub trait PubTrait { + type Type; + const CONST: usize; + fn function(); +} + +// @has 'foo/struct.FooPublic.html' '//code' 'type Type' +// @!has 'foo/struct.FooPublic.html' '//code' 'pub type Type' +// +// @has 'foo/struct.FooPublic.html' '//code' 'const CONST: usize' +// @!has 'foo/struct.FooPublic.html' '//code' 'pub const CONST: usize' +// +// @has 'foo/struct.FooPublic.html' '//code' 'fn function()' +// @!has 'foo/struct.FooPublic.html' '//code' 'pub fn function()' + +impl PubTrait for FooPublic { + type Type = usize; + const CONST: usize = 0; + fn function() {} +} From e364d4a326c89ba43e7ae3f3eba149d267ff34a2 Mon Sep 17 00:00:00 2001 From: bors Date: Wed, 20 Jan 2021 23:40:09 +0000 Subject: [PATCH 07/10] Auto merge of #81229 - m-ou-se:solaris-workaround, r=pietroalbini Work around missing -dev packages in solaris docker image. This should hopefully make the `dist-various-2` docker build work again on CI, which is now blocking everything from getting merged. r? `@pietroalbini` --- .../dist-various-2/build-solaris-toolchain.sh | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh index 4b3f284450eaa..6c4aa875269f9 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh @@ -30,12 +30,12 @@ cd solaris dpkg --add-architecture $APT_ARCH apt-get update apt-get download $(apt-cache depends --recurse --no-replaces \ - libc-dev:$APT_ARCH \ + libc:$APT_ARCH \ libm-dev:$APT_ARCH \ - libpthread-dev:$APT_ARCH \ - libresolv-dev:$APT_ARCH \ - librt-dev:$APT_ARCH \ - libsocket-dev:$APT_ARCH \ + libpthread:$APT_ARCH \ + libresolv:$APT_ARCH \ + librt:$APT_ARCH \ + libsocket:$APT_ARCH \ system-crt:$APT_ARCH \ system-header:$APT_ARCH \ | grep "^\w") @@ -44,6 +44,14 @@ for deb in *$APT_ARCH.deb; do dpkg -x $deb . done +# The -dev packages are not available from the apt repository we're using. +# However, those packages are just symlinks from *.so to *.so.. +# This makes all those symlinks. +for lib in $(find -name '*.so.*'); do + target=${lib%.so.*}.so + [ -e $target ] || ln -s ${lib##*/} $target +done + # Remove Solaris 11 functions that are optionally used by libbacktrace. # This is for Solaris 10 compatibility. rm usr/include/link.h From 78e57dc9803b3f283eb067e984869f90c82747c2 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 5 Feb 2021 12:26:07 +0100 Subject: [PATCH 08/10] Rollup merge of #81767 - exrook:layout-error-stability, r=Mark-Simulacrum Update LayoutError/LayoutErr stability attributes `LayoutError` ended up not making it into 1.49.0, updating the stability attributes to reflect that. I also pushed `LayoutErr` deprecation back a release to allow 2 releases before the deprecation comes into effect. This change should be backported to beta. --- library/core/src/alloc/layout.rs | 4 ++-- library/core/src/alloc/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 57c6624b64f9e..997c1a16cc025 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -394,7 +394,7 @@ impl Layout { #[stable(feature = "alloc_layout", since = "1.28.0")] #[rustc_deprecated( - since = "1.51.0", + since = "1.52.0", reason = "Name does not follow std convention, use LayoutError", suggestion = "LayoutError" )] @@ -403,7 +403,7 @@ pub type LayoutErr = LayoutError; /// The parameters given to `Layout::from_size_align` /// or some other `Layout` constructor /// do not satisfy its documented constraints. -#[stable(feature = "alloc_layout_error", since = "1.49.0")] +#[stable(feature = "alloc_layout_error", since = "1.50.0")] #[derive(Clone, PartialEq, Eq, Debug)] pub struct LayoutError { private: (), diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 045eb58d0135a..c1c993bbc51af 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -11,14 +11,14 @@ pub use self::global::GlobalAlloc; pub use self::layout::Layout; #[stable(feature = "alloc_layout", since = "1.28.0")] #[rustc_deprecated( - since = "1.51.0", + since = "1.52.0", reason = "Name does not follow std convention, use LayoutError", suggestion = "LayoutError" )] #[allow(deprecated, deprecated_in_future)] pub use self::layout::LayoutErr; -#[stable(feature = "alloc_layout_error", since = "1.49.0")] +#[stable(feature = "alloc_layout_error", since = "1.50.0")] pub use self::layout::LayoutError; use crate::fmt; From eba543261df42672c692e45e3062c4cbbcd03920 Mon Sep 17 00:00:00 2001 From: bors Date: Fri, 5 Feb 2021 14:52:57 +0000 Subject: [PATCH 09/10] Auto merge of #81257 - pnkfelix:issue-80949-short-term-resolution-via-revert-of-pr-78373, r=matthewjasper Revert 78373 ("dont leak return value after panic in drop") Short term resolution for issue #80949. Reopen #47949 after this lands. (We plan to fine-tune PR #78373 to not run into this problem.) --- compiler/rustc_mir_build/src/build/block.rs | 10 +- .../src/build/expr/as_rvalue.rs | 20 +- .../rustc_mir_build/src/build/expr/as_temp.rs | 6 +- .../rustc_mir_build/src/build/expr/into.rs | 90 +- .../rustc_mir_build/src/build/expr/stmt.rs | 2 - compiler/rustc_mir_build/src/build/into.rs | 11 +- .../rustc_mir_build/src/build/matches/mod.rs | 78 +- compiler/rustc_mir_build/src/build/mod.rs | 20 +- compiler/rustc_mir_build/src/build/scope.rs | 216 +- .../alloc/src/collections/btree/map/tests.rs | 2 +- ...ignment.main.SimplifyCfg-initial.after.mir | 28 +- .../box_expr.main.ElaborateDrops.before.mir | 28 +- .../inline/inline_diverging.h.Inline.diff | 11 +- .../issue_41110.main.ElaborateDrops.after.mir | 27 +- .../issue_41110.test.ElaborateDrops.after.mir | 48 +- .../issue_41888.main.ElaborateDrops.after.mir | 74 +- ...issue_62289.test.ElaborateDrops.before.mir | 40 +- ..._after_call.main.ElaborateDrops.before.mir | 10 +- ...ove_out.move_out_by_subslice.mir_map.0.mir | 38 +- ...y_move_out.move_out_from_end.mir_map.0.mir | 38 +- .../expected_show_coverage.uses_crate.txt | 4 +- ...block_on.-------.InstrumentCoverage.0.html | 114 +- ...ync.main.-------.InstrumentCoverage.0.html | 54 +- ...osure#2}.-------.InstrumentCoverage.0.html | 12 +- ...ure.main.-------.InstrumentCoverage.0.html | 19992 ++++++++-------- ...ib_crate.-------.InstrumentCoverage.0.html | 162 +- ...ate.main.-------.InstrumentCoverage.0.html | 176 +- src/test/ui/drop/dynamic-drop-async.rs | 165 +- src/test/ui/drop/dynamic-drop.rs | 437 +- src/test/ui/mir/issue-80949.rs | 34 + 30 files changed, 10904 insertions(+), 11043 deletions(-) create mode 100644 src/test/ui/mir/issue-80949.rs diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 82f38ac0e7620..d5f72e6f22dfa 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -3,7 +3,6 @@ use crate::build::ForGuard::OutsideGuard; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::thir::*; use rustc_hir as hir; -use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_session::lint::builtin::UNSAFE_OP_IN_UNSAFE_FN; use rustc_session::lint::Level; @@ -13,7 +12,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn ast_block( &mut self, destination: Place<'tcx>, - scope: Option, block: BasicBlock, ast_block: &'tcx hir::Block<'tcx>, source_info: SourceInfo, @@ -30,10 +28,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| { this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| { if targeted_by_break { - this.in_breakable_scope(None, destination, scope, span, |this| { + this.in_breakable_scope(None, destination, span, |this| { Some(this.ast_block_stmts( destination, - scope, block, span, stmts, @@ -42,7 +39,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { )) }) } else { - this.ast_block_stmts(destination, scope, block, span, stmts, expr, safety_mode) + this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode) } }) }) @@ -51,7 +48,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn ast_block_stmts( &mut self, destination: Place<'tcx>, - scope: Option, mut block: BasicBlock, span: Span, stmts: Vec>, @@ -186,7 +182,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }; this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored, span }); - unpack!(block = this.into(destination, scope, block, expr)); + unpack!(block = this.into(destination, block, expr)); let popped = this.block_context.pop(); assert!(popped.map_or(false, |bf| bf.is_tail_expr())); diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 3f381f3f15e8e..581d842142f7b 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -12,8 +12,6 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, UpvarSubsts}; use rustc_span::Span; -use std::slice; - impl<'a, 'tcx> Builder<'a, 'tcx> { /// Returns an rvalue suitable for use until the end of the current /// scope expression. @@ -115,19 +113,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty); this.cfg.push_assign(block, source_info, Place::from(result), box_); - // Initialize the box contents. No scope is needed since the - // `Box` is already scheduled to be dropped. + // initialize the box contents: unpack!( - block = this.into( - this.hir.tcx().mk_place_deref(Place::from(result)), - None, - block, - value, - ) + block = + this.into(this.hir.tcx().mk_place_deref(Place::from(result)), block, value) ); - let result_operand = Operand::Move(Place::from(result)); - this.record_operands_moved(slice::from_ref(&result_operand)); - block.and(Rvalue::Use(result_operand)) + block.and(Rvalue::Use(Operand::Move(Place::from(result)))) } ExprKind::Cast { source } => { let source = unpack!(block = this.as_operand(block, scope, source)); @@ -171,7 +162,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .map(|f| unpack!(block = this.as_operand(block, scope, f))) .collect(); - this.record_operands_moved(&fields); block.and(Rvalue::Aggregate(box AggregateKind::Array(el_ty), fields)) } ExprKind::Tuple { fields } => { @@ -182,7 +172,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .map(|f| unpack!(block = this.as_operand(block, scope, f))) .collect(); - this.record_operands_moved(&fields); block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields)) } ExprKind::Closure { closure_id, substs, upvars, movability } => { @@ -234,7 +223,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } UpvarSubsts::Closure(substs) => box AggregateKind::Closure(closure_id, substs), }; - this.record_operands_moved(&operands); block.and(Rvalue::Aggregate(result, operands)) } ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => { diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs index 241330d96e7bd..9984b527ffdb4 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs @@ -114,7 +114,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - unpack!(block = this.into(temp_place, temp_lifetime, block, expr)); + unpack!(block = this.into(temp_place, block, expr)); + + if let Some(temp_lifetime) = temp_lifetime { + this.schedule_drop(expr_span, temp_lifetime, temp, DropKind::Value); + } block.and(temp) } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 1f70fdb5ae30b..a86e4cb99c7f9 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -1,37 +1,27 @@ //! See docs in build/expr/mod.rs use crate::build::expr::category::{Category, RvalueFunc}; -use crate::build::scope::DropKind; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::thir::*; use rustc_ast::InlineAsmOptions; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; -use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi; -use std::slice; - impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, storing the result into `destination`, which /// is assumed to be uninitialized. - /// If a `drop_scope` is provided, `destination` is scheduled to be dropped - /// in `scope` once it has been initialized. crate fn into_expr( &mut self, destination: Place<'tcx>, - scope: Option, mut block: BasicBlock, expr: Expr<'tcx>, ) -> BlockAnd<()> { - debug!( - "into_expr(destination={:?}, scope={:?}, block={:?}, expr={:?})", - destination, scope, block, expr - ); + debug!("into_expr(destination={:?}, block={:?}, expr={:?})", destination, block, expr); // since we frequently have to reference `self` from within a // closure, where `self` would be shadowed, it's easier to @@ -46,14 +36,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ => false, }; - let schedule_drop = move |this: &mut Self| { - if let Some(drop_scope) = scope { - let local = - destination.as_local().expect("cannot schedule drop of non-Local place"); - this.schedule_drop(expr_span, drop_scope, local, DropKind::Value); - } - }; - if !expr_is_block_or_scope { this.block_context.push(BlockFrame::SubExpr); } @@ -63,15 +45,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let region_scope = (region_scope, source_info); ensure_sufficient_stack(|| { this.in_scope(region_scope, lint_level, |this| { - this.into(destination, scope, block, value) + this.into(destination, block, value) }) }) } ExprKind::Block { body: ast_block } => { - this.ast_block(destination, scope, block, ast_block, source_info) + this.ast_block(destination, block, ast_block, source_info) } ExprKind::Match { scrutinee, arms } => { - this.match_expr(destination, scope, expr_span, block, scrutinee, arms) + this.match_expr(destination, expr_span, block, scrutinee, arms) } ExprKind::NeverToAny { source } => { let source = this.hir.mirror(source); @@ -83,7 +65,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // This is an optimization. If the expression was a call then we already have an // unreachable block. Don't bother to terminate it and create a new one. - schedule_drop(this); if is_call { block.unit() } else { @@ -159,35 +140,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Start the loop. this.cfg.goto(block, source_info, loop_block); - this.in_breakable_scope( - Some(loop_block), - destination, - scope, - expr_span, - move |this| { - // conduct the test, if necessary - let body_block = this.cfg.start_new_block(); - this.cfg.terminate( - loop_block, - source_info, - TerminatorKind::FalseUnwind { real_target: body_block, unwind: None }, - ); - this.diverge_from(loop_block); - - // The “return” value of the loop body must always be an unit. We therefore - // introduce a unit temporary as the destination for the loop body. - let tmp = this.get_unit_temp(); - // Execute the body, branching back to the test. - // We don't need to provide a drop scope because `tmp` - // has type `()`. - let body_block_end = unpack!(this.into(tmp, None, body_block, body)); - this.cfg.goto(body_block_end, source_info, loop_block); - schedule_drop(this); - - // Loops are only exited by `break` expressions. - None - }, - ) + this.in_breakable_scope(Some(loop_block), destination, expr_span, move |this| { + // conduct the test, if necessary + let body_block = this.cfg.start_new_block(); + this.cfg.terminate( + loop_block, + source_info, + TerminatorKind::FalseUnwind { real_target: body_block, unwind: None }, + ); + this.diverge_from(loop_block); + + // The “return” value of the loop body must always be an unit. We therefore + // introduce a unit temporary as the destination for the loop body. + let tmp = this.get_unit_temp(); + // Execute the body, branching back to the test. + let body_block_end = unpack!(this.into(tmp, body_block, body)); + this.cfg.goto(body_block_end, source_info, loop_block); + + // Loops are only exited by `break` expressions. + None + }) } ExprKind::Call { ty, fun, args, from_hir_call, fn_span } => { let intrinsic = match *ty.kind() { @@ -220,13 +192,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .push(LocalDecl::with_source_info(ptr_ty, source_info).internal()); let ptr_temp = Place::from(ptr_temp); // No need for a scope, ptr_temp doesn't need drop - let block = unpack!(this.into(ptr_temp, None, block, ptr)); + let block = unpack!(this.into(ptr_temp, block, ptr)); // Maybe we should provide a scope here so that // `move_val_init` wouldn't leak on panic even with an // arbitrary `val` expression, but `schedule_drop`, // borrowck and drop elaboration all prevent us from // dropping `ptr_temp.deref()`. - this.into(this.hir.tcx().mk_place_deref(ptr_temp), None, block, val) + this.into(this.hir.tcx().mk_place_deref(ptr_temp), block, val) } else { let args: Vec<_> = args .into_iter() @@ -259,11 +231,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, ); this.diverge_from(block); - schedule_drop(this); success.unit() } } - ExprKind::Use { source } => this.into(destination, scope, block, source), + ExprKind::Use { source } => this.into(destination, block, source), ExprKind::Borrow { arg, borrow_kind } => { // We don't do this in `as_rvalue` because we use `as_place` // for borrow expressions, so we cannot create an `RValue` that @@ -340,14 +311,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { user_ty, active_field_index, ); - this.record_operands_moved(&fields); this.cfg.push_assign( block, source_info, destination, Rvalue::Aggregate(adt, fields), ); - schedule_drop(this); block.unit() } ExprKind::InlineAsm { template, operands, options, line_spans } => { @@ -444,7 +413,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let place = unpack!(block = this.as_place(block, expr)); let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place)); this.cfg.push_assign(block, source_info, destination, rvalue); - schedule_drop(this); block.unit() } ExprKind::Index { .. } | ExprKind::Deref { .. } | ExprKind::Field { .. } => { @@ -462,7 +430,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let place = unpack!(block = this.as_place(block, expr)); let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place)); this.cfg.push_assign(block, source_info, destination, rvalue); - schedule_drop(this); block.unit() } @@ -470,14 +437,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let scope = this.local_scope(); let value = unpack!(block = this.as_operand(block, Some(scope), value)); let resume = this.cfg.start_new_block(); - this.record_operands_moved(slice::from_ref(&value)); this.cfg.terminate( block, source_info, TerminatorKind::Yield { value, resume, resume_arg: destination, drop: None }, ); this.generator_drop_cleanup(block); - schedule_drop(this); resume.unit() } @@ -509,7 +474,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let rvalue = unpack!(block = this.as_local_rvalue(block, expr)); this.cfg.push_assign(block, source_info, destination, rvalue); - schedule_drop(this); block.unit() } }; diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index a974ea0db5f3c..f117689d940fd 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -3,7 +3,6 @@ use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::thir::*; use rustc_middle::middle::region; use rustc_middle::mir::*; -use std::slice; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Builds a block of MIR statements to evaluate the THIR `expr`. @@ -47,7 +46,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if this.hir.needs_drop(lhs.ty) { let rhs = unpack!(block = this.as_local_operand(block, rhs)); let lhs = unpack!(block = this.as_place(block, lhs)); - this.record_operands_moved(slice::from_ref(&rhs)); unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs)); } else { let rhs = unpack!(block = this.as_local_rvalue(block, rhs)); diff --git a/compiler/rustc_mir_build/src/build/into.rs b/compiler/rustc_mir_build/src/build/into.rs index ee1838ddea66c..7264e495b84fd 100644 --- a/compiler/rustc_mir_build/src/build/into.rs +++ b/compiler/rustc_mir_build/src/build/into.rs @@ -6,7 +6,6 @@ use crate::build::{BlockAnd, Builder}; use crate::thir::*; -use rustc_middle::middle::region; use rustc_middle::mir::*; pub(in crate::build) trait EvalInto<'tcx> { @@ -14,7 +13,6 @@ pub(in crate::build) trait EvalInto<'tcx> { self, builder: &mut Builder<'_, 'tcx>, destination: Place<'tcx>, - scope: Option, block: BasicBlock, ) -> BlockAnd<()>; } @@ -23,14 +21,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn into( &mut self, destination: Place<'tcx>, - scope: Option, block: BasicBlock, expr: E, ) -> BlockAnd<()> where E: EvalInto<'tcx>, { - expr.eval_into(self, destination, scope, block) + expr.eval_into(self, destination, block) } } @@ -39,11 +36,10 @@ impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> { self, builder: &mut Builder<'_, 'tcx>, destination: Place<'tcx>, - scope: Option, block: BasicBlock, ) -> BlockAnd<()> { let expr = builder.hir.mirror(self); - builder.into_expr(destination, scope, block, expr) + builder.into_expr(destination, block, expr) } } @@ -52,9 +48,8 @@ impl<'tcx> EvalInto<'tcx> for Expr<'tcx> { self, builder: &mut Builder<'_, 'tcx>, destination: Place<'tcx>, - scope: Option, block: BasicBlock, ) -> BlockAnd<()> { - builder.into_expr(destination, scope, block, self) + builder.into_expr(destination, block, self) } } diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 2e108d480932a..c5f9412bf0ebe 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -87,7 +87,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn match_expr( &mut self, destination: Place<'tcx>, - destination_scope: Option, span: Span, mut block: BasicBlock, scrutinee: ExprRef<'tcx>, @@ -108,7 +107,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.lower_match_arms( destination, - destination_scope, scrutinee_place, scrutinee_span, arm_candidates, @@ -215,13 +213,76 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } + /// Lower the bindings, guards and arm bodies of a `match` expression. + /// + /// The decision tree should have already been created + /// (by [Builder::lower_match_tree]). + /// + /// `outer_source_info` is the SourceInfo for the whole match. + fn lower_match_arms( + &mut self, + destination: Place<'tcx>, + scrutinee_place: Place<'tcx>, + scrutinee_span: Span, + arm_candidates: Vec<(&'_ Arm<'tcx>, Candidate<'_, 'tcx>)>, + outer_source_info: SourceInfo, + fake_borrow_temps: Vec<(Place<'tcx>, Local)>, + ) -> BlockAnd<()> { + let arm_end_blocks: Vec<_> = arm_candidates + .into_iter() + .map(|(arm, candidate)| { + debug!("lowering arm {:?}\ncandidate = {:?}", arm, candidate); + + let arm_source_info = self.source_info(arm.span); + let arm_scope = (arm.scope, arm_source_info); + self.in_scope(arm_scope, arm.lint_level, |this| { + let body = this.hir.mirror(arm.body.clone()); + let scope = this.declare_bindings( + None, + arm.span, + &arm.pattern, + ArmHasGuard(arm.guard.is_some()), + Some((Some(&scrutinee_place), scrutinee_span)), + ); + + let arm_block = this.bind_pattern( + outer_source_info, + candidate, + arm.guard.as_ref(), + &fake_borrow_temps, + scrutinee_span, + Some(arm.span), + Some(arm.scope), + ); + + if let Some(source_scope) = scope { + this.source_scope = source_scope; + } + + this.into(destination, arm_block, body) + }) + }) + .collect(); + + // all the arm blocks will rejoin here + let end_block = self.cfg.start_new_block(); + + for arm_block in arm_end_blocks { + self.cfg.goto(unpack!(arm_block), outer_source_info, end_block); + } + + self.source_scope = outer_source_info.scope; + + end_block.unit() + } + /// Binds the variables and ascribes types for a given `match` arm or /// `let` binding. /// /// Also check if the guard matches, if it's provided. /// `arm_scope` should be `Some` if and only if this is called for a /// `match` arm. - crate fn bind_pattern( + fn bind_pattern( &mut self, outer_source_info: SourceInfo, candidate: Candidate<'_, 'tcx>, @@ -308,14 +369,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Binding { mode: BindingMode::ByValue, var, subpattern: None, .. } => { let place = self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true); - let region_scope = self.hir.region_scope_tree.var_scope(var.local_id); - - unpack!(block = self.into(place, Some(region_scope), block, initializer)); + unpack!(block = self.into(place, block, initializer)); // Inject a fake read, see comments on `FakeReadCause::ForLet`. let source_info = self.source_info(irrefutable_pat.span); self.cfg.push_fake_read(block, source_info, FakeReadCause::ForLet, place); + self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } @@ -342,10 +402,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ascription: thir::pattern::Ascription { user_ty: pat_ascription_ty, variance: _, user_ty_span }, } => { - let region_scope = self.hir.region_scope_tree.var_scope(var.local_id); let place = self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true); - unpack!(block = self.into(place, Some(region_scope), block, initializer)); + unpack!(block = self.into(place, block, initializer)); // Inject a fake read, see comments on `FakeReadCause::ForLet`. let pattern_source_info = self.source_info(irrefutable_pat.span); @@ -383,6 +442,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, ); + self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } @@ -629,7 +689,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } #[derive(Debug)] -pub(super) struct Candidate<'pat, 'tcx> { +struct Candidate<'pat, 'tcx> { /// `Span` of the original pattern that gave rise to this candidate span: Span, diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index e041464381220..a207997f5780d 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -618,12 +618,8 @@ where let arg_scope_s = (arg_scope, source_info); // Attribute epilogue to function's closing brace let fn_end = span_with_body.shrink_to_hi(); - let return_block = unpack!(builder.in_breakable_scope( - None, - Place::return_place(), - Some(call_site_scope), - fn_end, - |builder| { + let return_block = + unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| { Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| { builder.args_and_body( START_BLOCK, @@ -633,13 +629,11 @@ where &body.value, ) })) - }, - )); + })); let source_info = builder.source_info(fn_end); builder.cfg.terminate(return_block, source_info, TerminatorKind::Return); let should_abort = should_abort_on_panic(tcx, fn_def_id, abi); builder.build_drop_trees(should_abort); - builder.unschedule_return_place_drop(); return_block.unit() })); @@ -672,9 +666,7 @@ fn construct_const<'a, 'tcx>( let mut block = START_BLOCK; let ast_expr = &tcx.hir().body(body_id).value; let expr = builder.hir.mirror(ast_expr); - // We don't provide a scope because we can't unwind in constants, so won't - // need to drop the return place. - unpack!(block = builder.into_expr(Place::return_place(), None, block, expr)); + unpack!(block = builder.into_expr(Place::return_place(), block, expr)); let source_info = builder.source_info(span); builder.cfg.terminate(block, source_info, TerminatorKind::Return); @@ -963,9 +955,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } let body = self.hir.mirror(ast_body); - let call_site = - region::Scope { id: ast_body.hir_id.local_id, data: region::ScopeData::CallSite }; - self.into(Place::return_place(), Some(call_site), block, body) + self.into(Place::return_place(), block, body) } fn set_correct_source_scope_for_arg( diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 62d2212d10962..e76175c0456a8 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -81,10 +81,9 @@ that contains only loops and breakable blocks. It tracks where a `break`, */ -use crate::build::matches::{ArmHasGuard, Candidate}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG}; -use crate::thir::{Arm, Expr, ExprRef, LintLevel}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use crate::thir::{Expr, ExprRef, LintLevel}; +use rustc_data_structures::fx::FxHashMap; use rustc_index::vec::IndexVec; use rustc_middle::middle::region; use rustc_middle::mir::*; @@ -121,6 +120,8 @@ struct Scope { /// end of the vector (top of the stack) first. drops: Vec, + moved_locals: Vec, + /// The drop index that will drop everything in and below this scope on an /// unwind path. cached_unwind_block: Option, @@ -156,8 +157,6 @@ struct BreakableScope<'tcx> { /// The destination of the loop/block expression itself (i.e., where to put /// the result of a `break` or `return` expression) break_destination: Place<'tcx>, - /// The scope that the destination should have its drop scheduled in. - destination_scope: Option, /// Drops that happen on the `break`/`return` path. break_drops: DropTree, /// Drops that happen on the `continue` path. @@ -406,6 +405,7 @@ impl<'tcx> Scopes<'tcx> { region_scope: region_scope.0, region_scope_span: region_scope.1.span, drops: vec![], + moved_locals: vec![], cached_unwind_block: None, cached_generator_drop_block: None, }); @@ -440,7 +440,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, loop_block: Option, break_destination: Place<'tcx>, - destination_scope: Option, span: Span, f: F, ) -> BlockAnd<()> @@ -451,19 +450,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let scope = BreakableScope { region_scope, break_destination, - destination_scope, break_drops: DropTree::new(), continue_drops: loop_block.map(|_| DropTree::new()), }; - let continue_block = loop_block.map(|block| (block, self.diverge_cleanup())); self.scopes.breakable_scopes.push(scope); let normal_exit_block = f(self); let breakable_scope = self.scopes.breakable_scopes.pop().unwrap(); assert!(breakable_scope.region_scope == region_scope); + let break_block = self.build_exit_tree(breakable_scope.break_drops, None); if let Some(drops) = breakable_scope.continue_drops { - self.build_exit_tree(drops, continue_block); + self.build_exit_tree(drops, loop_block); } - let break_block = self.build_exit_tree(breakable_scope.break_drops, None); match (normal_exit_block, break_block) { (Some(block), None) | (None, Some(block)) => block, (None, None) => self.cfg.start_new_block().unit(), @@ -592,22 +589,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .rposition(|breakable_scope| breakable_scope.region_scope == scope) .unwrap_or_else(|| span_bug!(span, "no enclosing breakable scope found")) }; - let (break_index, destination, dest_scope) = match target { + let (break_index, destination) = match target { BreakableTarget::Return => { let scope = &self.scopes.breakable_scopes[0]; if scope.break_destination != Place::return_place() { span_bug!(span, "`return` in item with no return scope"); } - (0, Some(scope.break_destination), scope.destination_scope) + (0, Some(scope.break_destination)) } BreakableTarget::Break(scope) => { let break_index = get_scope_index(scope); let scope = &self.scopes.breakable_scopes[break_index]; - (break_index, Some(scope.break_destination), scope.destination_scope) + (break_index, Some(scope.break_destination)) } BreakableTarget::Continue(scope) => { let break_index = get_scope_index(scope); - (break_index, None, None) + (break_index, None) } }; @@ -615,10 +612,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let Some(value) = value { debug!("stmt_expr Break val block_context.push(SubExpr)"); self.block_context.push(BlockFrame::SubExpr); - unpack!(block = self.into(destination, dest_scope, block, value)); - if let Some(scope) = dest_scope { - self.unschedule_drop(scope, destination.as_local().unwrap()) - }; + unpack!(block = self.into(destination, block, value)); self.block_context.pop(); } else { self.cfg.push_assign_unit(block, source_info, destination, self.hir.tcx()) @@ -858,47 +852,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span_bug!(span, "region scope {:?} not in scope to drop {:?}", region_scope, local); } - /// Unschedule a drop. Used for `break`, `return` and `match` expressions, - /// where `record_operands_moved` is not powerful enough. - /// - /// The given local is expected to have a value drop scheduled in the given - /// scope and for that drop to be the most recent thing scheduled in that - /// scope. - fn unschedule_drop(&mut self, region_scope: region::Scope, local: Local) { - if !self.hir.needs_drop(self.local_decls[local].ty) { - return; - } - for scope in self.scopes.scopes.iter_mut().rev() { - scope.invalidate_cache(); - - if scope.region_scope == region_scope { - let drop = scope.drops.pop(); - - match drop { - Some(DropData { local: removed_local, kind: DropKind::Value, .. }) - if removed_local == local => - { - return; - } - _ => bug!( - "found wrong drop, expected value drop of {:?}, found {:?}", - local, - drop, - ), - } - } - } - - bug!("region scope {:?} not in scope to unschedule drop of {:?}", region_scope, local); - } - - /// Indicates that the "local operands" stored in `local` is + /// Indicates that the "local operand" stored in `local` is /// *moved* at some point during execution (see `local_scope` for /// more information about what a "local operand" is -- in short, /// it's an intermediate operand created as part of preparing some /// MIR instruction). We use this information to suppress - /// redundant drops. This results in less MIR, but also avoids spurious - /// borrow check errors (c.f. #64391). + /// redundant drops on the non-unwind paths. This results in less + /// MIR, but also avoids spurious borrow check errors + /// (c.f. #64391). /// /// Example: when compiling the call to `foo` here: /// @@ -937,19 +898,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); // look for moves of a local variable, like `MOVE(_X)` - let locals_moved = operands - .iter() - .filter_map(|operand| match operand { - Operand::Copy(_) | Operand::Constant(_) => None, - Operand::Move(place) => place.as_local(), - }) - .collect::>(); + let locals_moved = operands.iter().flat_map(|operand| match operand { + Operand::Copy(_) | Operand::Constant(_) => None, + Operand::Move(place) => place.as_local(), + }); - // Remove the drops for the moved operands. - scope - .drops - .retain(|drop| drop.kind == DropKind::Storage || !locals_moved.contains(&drop.local)); - scope.invalidate_cache(); + for local in locals_moved { + // check if we have a Drop for this operand and -- if so + // -- add it to the list of moved operands. Note that this + // local might not have been an operand created for this + // call, it could come from other places too. + if scope.drops.iter().any(|drop| drop.local == local && drop.kind == DropKind::Value) { + scope.moved_locals.push(local); + } + } } // Other @@ -1136,97 +1098,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { success_block } - /// Lower the arms and guards of a match. - /// - /// The decision tree should have already been created (by - /// [Builder::lower_match_tree]). - /// - /// This is this module, and not in `build::matches` because we have to do - /// some careful scope manipulation to have the drop of the destination be - /// scheduled at the end of each arm and then cleared for the next arm. - crate fn lower_match_arms( - &mut self, - destination: Place<'tcx>, - destination_scope: Option, - scrutinee_place: Place<'tcx>, - scrutinee_span: Span, - arm_candidates: Vec<(&'_ Arm<'tcx>, Candidate<'_, 'tcx>)>, - outer_source_info: SourceInfo, - fake_borrow_temps: Vec<(Place<'tcx>, Local)>, - ) -> BlockAnd<()> { - if arm_candidates.is_empty() { - // If there are no arms to schedule drops, then we have to do it - // manually. - if let Some(scope) = destination_scope { - self.schedule_drop( - outer_source_info.span, - scope, - destination.as_local().unwrap(), - DropKind::Value, - ); - } - return self.cfg.start_new_block().unit(); - } - let mut first_arm = true; - let arm_end_blocks: Vec<_> = arm_candidates - .into_iter() - .map(|(arm, candidate)| { - debug!("lowering arm {:?}\ncandidate = {:?}", arm, candidate); - - if first_arm { - first_arm = false; - } else if let Some(scope) = destination_scope { - self.unschedule_drop(scope, destination.as_local().unwrap()); - } - - let arm_source_info = self.source_info(arm.span); - let arm_scope = (arm.scope, arm_source_info); - self.in_scope(arm_scope, arm.lint_level, |this| { - let body = this.hir.mirror(arm.body.clone()); - let scope = this.declare_bindings( - None, - arm.span, - &arm.pattern, - ArmHasGuard(arm.guard.is_some()), - Some((Some(&scrutinee_place), scrutinee_span)), - ); - - let arm_block = this.bind_pattern( - outer_source_info, - candidate, - arm.guard.as_ref(), - &fake_borrow_temps, - scrutinee_span, - Some(arm.span), - Some(arm.scope), - ); - - if let Some(source_scope) = scope { - this.source_scope = source_scope; - } - - this.into(destination, destination_scope, arm_block, body) - }) - }) - .collect(); - - // all the arm blocks will rejoin here - let end_block = self.cfg.start_new_block(); - - for arm_block in arm_end_blocks { - self.cfg.goto(unpack!(arm_block), outer_source_info, end_block); - } - - self.source_scope = outer_source_info.scope; - - end_block.unit() - } - /// Unschedules any drops in the top scope. /// /// This is only needed for `match` arm scopes, because they have one /// entrance per pattern, but only one exit. - pub(super) fn clear_top_scope(&mut self, region_scope: region::Scope) { + crate fn clear_top_scope(&mut self, region_scope: region::Scope) { let top_scope = self.scopes.scopes.last_mut().unwrap(); assert_eq!(top_scope.region_scope, region_scope); @@ -1234,18 +1110,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { top_scope.drops.clear(); top_scope.invalidate_cache(); } - - /// Unschedules the drop of the return place. - /// - /// If the return type of a function requires drop, then we schedule it - /// in the outermost scope so that it's dropped if there's a panic while - /// we drop any local variables. But we don't want to drop it if we - /// return normally. - crate fn unschedule_return_place_drop(&mut self) { - assert_eq!(self.scopes.scopes.len(), 1); - assert!(self.scopes.scopes[0].drops.len() <= 1); - self.scopes.scopes[0].drops.clear(); - } } /// Builds drops for `pop_scope` and `leave_top_scope`. @@ -1292,6 +1156,14 @@ fn build_scope_drops<'tcx>( debug_assert_eq!(unwind_drops.drops[unwind_to].0.kind, drop_data.kind); unwind_to = unwind_drops.drops[unwind_to].1; + // If the operand has been moved, and we are not on an unwind + // path, then don't generate the drop. (We only take this into + // account for non-unwind paths so as not to disturb the + // caching mechanism.) + if scope.moved_locals.iter().any(|&o| o == local) { + continue; + } + unwind_drops.add_entry(block, unwind_to); let next = cfg.start_new_block(); @@ -1321,24 +1193,20 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { /// Build a drop tree for a breakable scope. /// /// If `continue_block` is `Some`, then the tree is for `continue` inside a - /// loop. Otherwise this is for `break` or `return`. The `DropIdx` is the - /// next drop in the case that the drop tree unwinds. This is needed - /// because the drop of the break destination has already been scheduled - /// but it hasn't been initialized on the `continue` paths. + /// loop. Otherwise this is for `break` or `return`. fn build_exit_tree( &mut self, mut drops: DropTree, - continue_block: Option<(BasicBlock, DropIdx)>, + continue_block: Option, ) -> Option> { let mut blocks = IndexVec::from_elem(None, &drops.drops); - blocks[ROOT_NODE] = continue_block.map(|(block, _)| block); + blocks[ROOT_NODE] = continue_block; drops.build_mir::(&mut self.cfg, &mut blocks); // Link the exit drop tree to unwind drop tree. if drops.drops.iter().any(|(drop, _)| drop.kind == DropKind::Value) { - let unwind_target = continue_block - .map_or_else(|| self.diverge_cleanup(), |(_, unwind_target)| unwind_target); + let unwind_target = self.diverge_cleanup(); let mut unwind_indices = IndexVec::from_elem_n(unwind_target, 1); for (drop_idx, drop_data) in drops.drops.iter_enumerated().skip(1) { match drop_data.0.kind { diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index c857d4317e495..90bef37f71a93 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -1772,7 +1772,7 @@ fn test_append_drop_leak() { catch_unwind(move || left.append(&mut right)).unwrap_err(); - assert_eq!(DROPS.load(SeqCst), 5); + assert_eq!(DROPS.load(SeqCst), 4); // Rust issue #47949 ate one little piggy } #[test] diff --git a/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir index 0c7b64cb97f8f..7e0ca3dea4b71 100644 --- a/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir @@ -41,36 +41,44 @@ fn main() -> () { StorageLive(_5); // scope 3 at $DIR/basic_assignment.rs:19:9: 19:15 StorageLive(_6); // scope 4 at $DIR/basic_assignment.rs:23:14: 23:20 _6 = move _4; // scope 4 at $DIR/basic_assignment.rs:23:14: 23:20 - replace(_5 <- move _6) -> [return: bb1, unwind: bb4]; // scope 4 at $DIR/basic_assignment.rs:23:5: 23:11 + replace(_5 <- move _6) -> [return: bb1, unwind: bb5]; // scope 4 at $DIR/basic_assignment.rs:23:5: 23:11 } bb1: { + drop(_6) -> [return: bb2, unwind: bb6]; // scope 4 at $DIR/basic_assignment.rs:23:19: 23:20 + } + + bb2: { StorageDead(_6); // scope 4 at $DIR/basic_assignment.rs:23:19: 23:20 _0 = const (); // scope 0 at $DIR/basic_assignment.rs:10:11: 24:2 - drop(_5) -> [return: bb2, unwind: bb5]; // scope 3 at $DIR/basic_assignment.rs:24:1: 24:2 + drop(_5) -> [return: bb3, unwind: bb7]; // scope 3 at $DIR/basic_assignment.rs:24:1: 24:2 } - bb2: { + bb3: { StorageDead(_5); // scope 3 at $DIR/basic_assignment.rs:24:1: 24:2 - drop(_4) -> [return: bb3, unwind: bb6]; // scope 2 at $DIR/basic_assignment.rs:24:1: 24:2 + drop(_4) -> [return: bb4, unwind: bb8]; // scope 2 at $DIR/basic_assignment.rs:24:1: 24:2 } - bb3: { + bb4: { StorageDead(_4); // scope 2 at $DIR/basic_assignment.rs:24:1: 24:2 StorageDead(_2); // scope 1 at $DIR/basic_assignment.rs:24:1: 24:2 StorageDead(_1); // scope 0 at $DIR/basic_assignment.rs:24:1: 24:2 return; // scope 0 at $DIR/basic_assignment.rs:24:2: 24:2 } - bb4 (cleanup): { - drop(_5) -> bb5; // scope 3 at $DIR/basic_assignment.rs:24:1: 24:2 - } - bb5 (cleanup): { - drop(_4) -> bb6; // scope 2 at $DIR/basic_assignment.rs:24:1: 24:2 + drop(_6) -> bb6; // scope 4 at $DIR/basic_assignment.rs:23:19: 23:20 } bb6 (cleanup): { + drop(_5) -> bb7; // scope 3 at $DIR/basic_assignment.rs:24:1: 24:2 + } + + bb7 (cleanup): { + drop(_4) -> bb8; // scope 2 at $DIR/basic_assignment.rs:24:1: 24:2 + } + + bb8 (cleanup): { resume; // scope 0 at $DIR/basic_assignment.rs:10:1: 24:2 } } diff --git a/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir b/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir index 20ea7b026bc6e..cfbd3a58637c0 100644 --- a/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir +++ b/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir @@ -14,7 +14,7 @@ fn main() -> () { StorageLive(_1); // scope 0 at $DIR/box_expr.rs:7:9: 7:10 StorageLive(_2); // scope 0 at $DIR/box_expr.rs:7:13: 7:25 _2 = Box(S); // scope 0 at $DIR/box_expr.rs:7:13: 7:25 - (*_2) = S::new() -> [return: bb1, unwind: bb5]; // scope 0 at $DIR/box_expr.rs:7:17: 7:25 + (*_2) = S::new() -> [return: bb1, unwind: bb7]; // scope 0 at $DIR/box_expr.rs:7:17: 7:25 // mir::Constant // + span: $DIR/box_expr.rs:7:17: 7:23 // + literal: Const { ty: fn() -> S {S::new}, val: Value(Scalar()) } @@ -22,37 +22,45 @@ fn main() -> () { bb1: { _1 = move _2; // scope 0 at $DIR/box_expr.rs:7:13: 7:25 + drop(_2) -> bb2; // scope 0 at $DIR/box_expr.rs:7:24: 7:25 + } + + bb2: { StorageDead(_2); // scope 0 at $DIR/box_expr.rs:7:24: 7:25 StorageLive(_3); // scope 1 at $DIR/box_expr.rs:8:5: 8:12 StorageLive(_4); // scope 1 at $DIR/box_expr.rs:8:10: 8:11 _4 = move _1; // scope 1 at $DIR/box_expr.rs:8:10: 8:11 - _3 = std::mem::drop::>(move _4) -> [return: bb2, unwind: bb4]; // scope 1 at $DIR/box_expr.rs:8:5: 8:12 + _3 = std::mem::drop::>(move _4) -> [return: bb3, unwind: bb5]; // scope 1 at $DIR/box_expr.rs:8:5: 8:12 // mir::Constant // + span: $DIR/box_expr.rs:8:5: 8:9 // + literal: Const { ty: fn(std::boxed::Box) {std::mem::drop::>}, val: Value(Scalar()) } } - bb2: { + bb3: { StorageDead(_4); // scope 1 at $DIR/box_expr.rs:8:11: 8:12 StorageDead(_3); // scope 1 at $DIR/box_expr.rs:8:12: 8:13 _0 = const (); // scope 0 at $DIR/box_expr.rs:6:11: 9:2 - drop(_1) -> bb3; // scope 0 at $DIR/box_expr.rs:9:1: 9:2 + drop(_1) -> bb4; // scope 0 at $DIR/box_expr.rs:9:1: 9:2 } - bb3: { + bb4: { StorageDead(_1); // scope 0 at $DIR/box_expr.rs:9:1: 9:2 return; // scope 0 at $DIR/box_expr.rs:9:2: 9:2 } - bb4 (cleanup): { - drop(_1) -> bb6; // scope 0 at $DIR/box_expr.rs:9:1: 9:2 - } - bb5 (cleanup): { - drop(_2) -> bb6; // scope 0 at $DIR/box_expr.rs:7:24: 7:25 + drop(_4) -> bb6; // scope 1 at $DIR/box_expr.rs:8:11: 8:12 } bb6 (cleanup): { + drop(_1) -> bb8; // scope 0 at $DIR/box_expr.rs:9:1: 9:2 + } + + bb7 (cleanup): { + drop(_2) -> bb8; // scope 0 at $DIR/box_expr.rs:7:24: 7:25 + } + + bb8 (cleanup): { resume; // scope 0 at $DIR/box_expr.rs:6:1: 9:2 } } diff --git a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff index 22737381c71ae..07994eb3c1661 100644 --- a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff @@ -5,19 +5,18 @@ let mut _0: (); // return place in scope 0 at $DIR/inline-diverging.rs:21:12: 21:12 let _1: (!, !); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 + let mut _2: fn() -> ! {sleep}; // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 ++ let mut _7: (); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 + let mut _8: (); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 -+ let mut _9: (); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 + scope 1 (inlined call_twice:: ! {sleep}>) { // at $DIR/inline-diverging.rs:22:5: 22:22 + debug f => _2; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 + let _3: !; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 + let mut _4: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 + let mut _5: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 + let mut _6: !; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 -+ let mut _7: !; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 + scope 2 { + debug a => _3; // in scope 2 at $DIR/inline-diverging.rs:22:5: 22:22 + scope 3 { -+ debug b => _7; // in scope 3 at $DIR/inline-diverging.rs:22:5: 22:22 ++ debug b => _6; // in scope 3 at $DIR/inline-diverging.rs:22:5: 22:22 + } + scope 6 (inlined ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline-diverging.rs:22:5: 22:22 + scope 7 (inlined sleep) { // at $DIR/inline-diverging.rs:22:5: 22:22 @@ -41,12 +40,12 @@ - // mir::Constant // + span: $DIR/inline-diverging.rs:22:16: 22:21 // + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar()) } -+ StorageLive(_7); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 ++ StorageLive(_6); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 + StorageLive(_3); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 + StorageLive(_4); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 + _4 = &_2; // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 -+ StorageLive(_8); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 -+ _8 = const (); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 ++ StorageLive(_7); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 ++ _7 = const (); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 + goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:22:5: 22:22 } diff --git a/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir b/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir index bbbd2bcf128b1..7113c42b9c77f 100644 --- a/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir +++ b/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir @@ -6,18 +6,21 @@ fn main() -> () { let mut _2: S; // in scope 0 at $DIR/issue-41110.rs:8:13: 8:14 let mut _3: S; // in scope 0 at $DIR/issue-41110.rs:8:21: 8:27 let mut _4: S; // in scope 0 at $DIR/issue-41110.rs:8:21: 8:22 + let mut _5: bool; // in scope 0 at $DIR/issue-41110.rs:8:27: 8:28 scope 1 { debug x => _1; // in scope 1 at $DIR/issue-41110.rs:8:9: 8:10 } bb0: { + _5 = const false; // scope 0 at $DIR/issue-41110.rs:8:9: 8:10 StorageLive(_1); // scope 0 at $DIR/issue-41110.rs:8:9: 8:10 StorageLive(_2); // scope 0 at $DIR/issue-41110.rs:8:13: 8:14 + _5 = const true; // scope 0 at $DIR/issue-41110.rs:8:13: 8:14 _2 = S; // scope 0 at $DIR/issue-41110.rs:8:13: 8:14 StorageLive(_3); // scope 0 at $DIR/issue-41110.rs:8:21: 8:27 StorageLive(_4); // scope 0 at $DIR/issue-41110.rs:8:21: 8:22 _4 = S; // scope 0 at $DIR/issue-41110.rs:8:21: 8:22 - _3 = S::id(move _4) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-41110.rs:8:21: 8:27 + _3 = S::id(move _4) -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-41110.rs:8:21: 8:27 // mir::Constant // + span: $DIR/issue-41110.rs:8:23: 8:25 // + literal: Const { ty: fn(S) -> S {S::id}, val: Value(Scalar()) } @@ -25,7 +28,8 @@ fn main() -> () { bb1: { StorageDead(_4); // scope 0 at $DIR/issue-41110.rs:8:26: 8:27 - _1 = S::other(move _2, move _3) -> bb2; // scope 0 at $DIR/issue-41110.rs:8:13: 8:28 + _5 = const false; // scope 0 at $DIR/issue-41110.rs:8:13: 8:28 + _1 = S::other(move _2, move _3) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/issue-41110.rs:8:13: 8:28 // mir::Constant // + span: $DIR/issue-41110.rs:8:15: 8:20 // + literal: Const { ty: fn(S, S) {S::other}, val: Value(Scalar()) } @@ -33,6 +37,7 @@ fn main() -> () { bb2: { StorageDead(_3); // scope 0 at $DIR/issue-41110.rs:8:27: 8:28 + _5 = const false; // scope 0 at $DIR/issue-41110.rs:8:27: 8:28 StorageDead(_2); // scope 0 at $DIR/issue-41110.rs:8:27: 8:28 _0 = const (); // scope 0 at $DIR/issue-41110.rs:7:11: 9:2 StorageDead(_1); // scope 0 at $DIR/issue-41110.rs:9:1: 9:2 @@ -40,10 +45,26 @@ fn main() -> () { } bb3 (cleanup): { - drop(_2) -> bb4; // scope 0 at $DIR/issue-41110.rs:8:27: 8:28 + goto -> bb5; // scope 0 at $DIR/issue-41110.rs:8:27: 8:28 } bb4 (cleanup): { + goto -> bb5; // scope 0 at $DIR/issue-41110.rs:8:26: 8:27 + } + + bb5 (cleanup): { + goto -> bb8; // scope 0 at $DIR/issue-41110.rs:8:27: 8:28 + } + + bb6 (cleanup): { resume; // scope 0 at $DIR/issue-41110.rs:7:1: 9:2 } + + bb7 (cleanup): { + drop(_2) -> bb6; // scope 0 at $DIR/issue-41110.rs:8:27: 8:28 + } + + bb8 (cleanup): { + switchInt(_5) -> [false: bb6, otherwise: bb7]; // scope 0 at $DIR/issue-41110.rs:8:27: 8:28 + } } diff --git a/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir b/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir index b0c7260f0f4dc..c4e852ca3212a 100644 --- a/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir +++ b/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir @@ -25,7 +25,7 @@ fn test() -> () { StorageLive(_3); // scope 2 at $DIR/issue-41110.rs:17:5: 17:12 StorageLive(_4); // scope 2 at $DIR/issue-41110.rs:17:10: 17:11 _4 = move _2; // scope 2 at $DIR/issue-41110.rs:17:10: 17:11 - _3 = std::mem::drop::(move _4) -> [return: bb1, unwind: bb5]; // scope 2 at $DIR/issue-41110.rs:17:5: 17:12 + _3 = std::mem::drop::(move _4) -> [return: bb1, unwind: bb7]; // scope 2 at $DIR/issue-41110.rs:17:5: 17:12 // mir::Constant // + span: $DIR/issue-41110.rs:17:5: 17:9 // + literal: Const { ty: fn(S) {std::mem::drop::}, val: Value(Scalar()) } @@ -37,53 +37,65 @@ fn test() -> () { StorageLive(_5); // scope 2 at $DIR/issue-41110.rs:18:9: 18:10 _6 = const false; // scope 2 at $DIR/issue-41110.rs:18:9: 18:10 _5 = move _1; // scope 2 at $DIR/issue-41110.rs:18:9: 18:10 - goto -> bb9; // scope 2 at $DIR/issue-41110.rs:18:5: 18:6 + goto -> bb12; // scope 2 at $DIR/issue-41110.rs:18:5: 18:6 } bb2: { + goto -> bb3; // scope 2 at $DIR/issue-41110.rs:18:9: 18:10 + } + + bb3: { StorageDead(_5); // scope 2 at $DIR/issue-41110.rs:18:9: 18:10 _0 = const (); // scope 0 at $DIR/issue-41110.rs:14:15: 19:2 - drop(_2) -> [return: bb3, unwind: bb6]; // scope 1 at $DIR/issue-41110.rs:19:1: 19:2 + drop(_2) -> [return: bb4, unwind: bb9]; // scope 1 at $DIR/issue-41110.rs:19:1: 19:2 } - bb3: { + bb4: { StorageDead(_2); // scope 1 at $DIR/issue-41110.rs:19:1: 19:2 - goto -> bb4; // scope 0 at $DIR/issue-41110.rs:19:1: 19:2 + goto -> bb5; // scope 0 at $DIR/issue-41110.rs:19:1: 19:2 } - bb4: { + bb5: { _6 = const false; // scope 0 at $DIR/issue-41110.rs:19:1: 19:2 StorageDead(_1); // scope 0 at $DIR/issue-41110.rs:19:1: 19:2 return; // scope 0 at $DIR/issue-41110.rs:19:2: 19:2 } - bb5 (cleanup): { - goto -> bb6; // scope 1 at $DIR/issue-41110.rs:19:1: 19:2 - } - bb6 (cleanup): { - goto -> bb11; // scope 0 at $DIR/issue-41110.rs:19:1: 19:2 + goto -> bb8; // scope 2 at $DIR/issue-41110.rs:18:9: 18:10 } bb7 (cleanup): { - resume; // scope 0 at $DIR/issue-41110.rs:14:1: 19:2 + goto -> bb8; // scope 2 at $DIR/issue-41110.rs:17:11: 17:12 } bb8 (cleanup): { + goto -> bb9; // scope 1 at $DIR/issue-41110.rs:19:1: 19:2 + } + + bb9 (cleanup): { + goto -> bb14; // scope 0 at $DIR/issue-41110.rs:19:1: 19:2 + } + + bb10 (cleanup): { + resume; // scope 0 at $DIR/issue-41110.rs:14:1: 19:2 + } + + bb11 (cleanup): { _2 = move _5; // scope 2 at $DIR/issue-41110.rs:18:5: 18:6 - goto -> bb5; // scope 2 at $DIR/issue-41110.rs:18:5: 18:6 + goto -> bb6; // scope 2 at $DIR/issue-41110.rs:18:5: 18:6 } - bb9: { + bb12: { _2 = move _5; // scope 2 at $DIR/issue-41110.rs:18:5: 18:6 goto -> bb2; // scope 2 at $DIR/issue-41110.rs:18:5: 18:6 } - bb10 (cleanup): { - drop(_1) -> bb7; // scope 0 at $DIR/issue-41110.rs:19:1: 19:2 + bb13 (cleanup): { + drop(_1) -> bb10; // scope 0 at $DIR/issue-41110.rs:19:1: 19:2 } - bb11 (cleanup): { - switchInt(_6) -> [false: bb7, otherwise: bb10]; // scope 0 at $DIR/issue-41110.rs:19:1: 19:2 + bb14 (cleanup): { + switchInt(_6) -> [false: bb10, otherwise: bb13]; // scope 0 at $DIR/issue-41110.rs:19:1: 19:2 } } diff --git a/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir b/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir index 5011c2adfa581..453886f3effdf 100644 --- a/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir +++ b/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir @@ -26,7 +26,7 @@ fn main() -> () { _8 = const false; // scope 0 at $DIR/issue-41888.rs:7:9: 7:10 StorageLive(_1); // scope 0 at $DIR/issue-41888.rs:7:9: 7:10 StorageLive(_2); // scope 1 at $DIR/issue-41888.rs:8:8: 8:14 - _2 = cond() -> [return: bb1, unwind: bb9]; // scope 1 at $DIR/issue-41888.rs:8:8: 8:14 + _2 = cond() -> [return: bb1, unwind: bb11]; // scope 1 at $DIR/issue-41888.rs:8:8: 8:14 // mir::Constant // + span: $DIR/issue-41888.rs:8:8: 8:12 // + literal: Const { ty: fn() -> bool {cond}, val: Value(Scalar()) } @@ -38,7 +38,7 @@ fn main() -> () { bb2: { _0 = const (); // scope 1 at $DIR/issue-41888.rs:14:6: 14:6 - goto -> bb7; // scope 1 at $DIR/issue-41888.rs:8:5: 14:6 + goto -> bb8; // scope 1 at $DIR/issue-41888.rs:8:5: 14:6 } bb3: { @@ -47,34 +47,38 @@ fn main() -> () { _4 = K; // scope 1 at $DIR/issue-41888.rs:9:18: 9:19 _3 = E::F(move _4); // scope 1 at $DIR/issue-41888.rs:9:13: 9:20 StorageDead(_4); // scope 1 at $DIR/issue-41888.rs:9:19: 9:20 - goto -> bb12; // scope 1 at $DIR/issue-41888.rs:9:9: 9:10 + goto -> bb14; // scope 1 at $DIR/issue-41888.rs:9:9: 9:10 } bb4: { + goto -> bb5; // scope 1 at $DIR/issue-41888.rs:9:19: 9:20 + } + + bb5: { StorageDead(_3); // scope 1 at $DIR/issue-41888.rs:9:19: 9:20 _5 = discriminant(_1); // scope 1 at $DIR/issue-41888.rs:10:16: 10:24 - switchInt(move _5) -> [0_isize: bb6, otherwise: bb5]; // scope 1 at $DIR/issue-41888.rs:10:16: 10:24 + switchInt(move _5) -> [0_isize: bb7, otherwise: bb6]; // scope 1 at $DIR/issue-41888.rs:10:16: 10:24 } - bb5: { + bb6: { _0 = const (); // scope 1 at $DIR/issue-41888.rs:13:10: 13:10 - goto -> bb7; // scope 1 at $DIR/issue-41888.rs:10:9: 13:10 + goto -> bb8; // scope 1 at $DIR/issue-41888.rs:10:9: 13:10 } - bb6: { + bb7: { StorageLive(_6); // scope 1 at $DIR/issue-41888.rs:10:21: 10:23 _9 = const false; // scope 1 at $DIR/issue-41888.rs:10:21: 10:23 _6 = move ((_1 as F).0: K); // scope 1 at $DIR/issue-41888.rs:10:21: 10:23 _0 = const (); // scope 2 at $DIR/issue-41888.rs:10:29: 13:10 StorageDead(_6); // scope 1 at $DIR/issue-41888.rs:13:9: 13:10 - goto -> bb7; // scope 1 at $DIR/issue-41888.rs:10:9: 13:10 + goto -> bb8; // scope 1 at $DIR/issue-41888.rs:10:9: 13:10 } - bb7: { - goto -> bb18; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 + bb8: { + goto -> bb20; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 } - bb8: { + bb9: { _7 = const false; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 _8 = const false; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 _9 = const false; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 @@ -83,23 +87,27 @@ fn main() -> () { return; // scope 0 at $DIR/issue-41888.rs:15:2: 15:2 } - bb9 (cleanup): { - goto -> bb10; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 + bb10 (cleanup): { + goto -> bb11; // scope 1 at $DIR/issue-41888.rs:9:19: 9:20 + } + + bb11 (cleanup): { + goto -> bb12; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 } - bb10 (cleanup): { + bb12 (cleanup): { resume; // scope 0 at $DIR/issue-41888.rs:6:1: 15:2 } - bb11 (cleanup): { + bb13 (cleanup): { _7 = const true; // scope 1 at $DIR/issue-41888.rs:9:9: 9:10 _8 = const true; // scope 1 at $DIR/issue-41888.rs:9:9: 9:10 _9 = const true; // scope 1 at $DIR/issue-41888.rs:9:9: 9:10 _1 = move _3; // scope 1 at $DIR/issue-41888.rs:9:9: 9:10 - goto -> bb9; // scope 1 at $DIR/issue-41888.rs:9:9: 9:10 + goto -> bb10; // scope 1 at $DIR/issue-41888.rs:9:9: 9:10 } - bb12: { + bb14: { _7 = const true; // scope 1 at $DIR/issue-41888.rs:9:9: 9:10 _8 = const true; // scope 1 at $DIR/issue-41888.rs:9:9: 9:10 _9 = const true; // scope 1 at $DIR/issue-41888.rs:9:9: 9:10 @@ -107,38 +115,38 @@ fn main() -> () { goto -> bb4; // scope 1 at $DIR/issue-41888.rs:9:9: 9:10 } - bb13: { + bb15: { _7 = const false; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 - goto -> bb8; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 + goto -> bb9; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 } - bb14 (cleanup): { - goto -> bb10; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 + bb16 (cleanup): { + goto -> bb12; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 } - bb15: { - drop(_1) -> [return: bb13, unwind: bb10]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 + bb17: { + drop(_1) -> [return: bb15, unwind: bb12]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 } - bb16 (cleanup): { - drop(_1) -> bb10; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 + bb18 (cleanup): { + drop(_1) -> bb12; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 } - bb17: { + bb19: { _10 = discriminant(_1); // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 - switchInt(move _10) -> [0_isize: bb13, otherwise: bb15]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 + switchInt(move _10) -> [0_isize: bb15, otherwise: bb17]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 } - bb18: { - switchInt(_7) -> [false: bb13, otherwise: bb17]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 + bb20: { + switchInt(_7) -> [false: bb15, otherwise: bb19]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 } - bb19 (cleanup): { + bb21 (cleanup): { _11 = discriminant(_1); // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 - switchInt(move _11) -> [0_isize: bb14, otherwise: bb16]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 + switchInt(move _11) -> [0_isize: bb16, otherwise: bb18]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 } - bb20 (cleanup): { - switchInt(_7) -> [false: bb10, otherwise: bb19]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 + bb22 (cleanup): { + switchInt(_7) -> [false: bb12, otherwise: bb21]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2 } } diff --git a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir index f74cdd7191927..c1421f20a0ba2 100644 --- a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir +++ b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir @@ -30,7 +30,7 @@ fn test() -> Option> { StorageLive(_3); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 StorageLive(_4); // scope 0 at $DIR/issue-62289.rs:9:15: 9:19 _4 = Option::::None; // scope 0 at $DIR/issue-62289.rs:9:15: 9:19 - _3 = as Try>::into_result(move _4) -> [return: bb1, unwind: bb10]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + _3 = as Try>::into_result(move _4) -> [return: bb1, unwind: bb12]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 // mir::Constant // + span: $DIR/issue-62289.rs:9:15: 9:20 // + literal: Const { ty: fn(std::option::Option) -> std::result::Result< as std::ops::Try>::Ok, as std::ops::Try>::Error> { as std::ops::Try>::into_result}, val: Value(Scalar()) } @@ -48,11 +48,7 @@ fn test() -> Option> { (*_2) = _10; // scope 4 at $DIR/issue-62289.rs:9:15: 9:20 StorageDead(_10); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 _1 = move _2; // scope 0 at $DIR/issue-62289.rs:9:10: 9:21 - StorageDead(_2); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 - _0 = Option::>::Some(move _1); // scope 0 at $DIR/issue-62289.rs:9:5: 9:22 - StorageDead(_1); // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 - StorageDead(_3); // scope 0 at $DIR/issue-62289.rs:10:1: 10:2 - goto -> bb8; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 + drop(_2) -> [return: bb7, unwind: bb11]; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 } bb3: { @@ -65,7 +61,7 @@ fn test() -> Option> { StorageLive(_8); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 StorageLive(_9); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 _9 = _6; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 - _8 = >::from(move _9) -> [return: bb5, unwind: bb10]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 + _8 = >::from(move _9) -> [return: bb5, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 // mir::Constant // + span: $DIR/issue-62289.rs:9:19: 9:20 // + literal: Const { ty: fn(std::option::NoneError) -> std::option::NoneError {>::from}, val: Value(Scalar()) } @@ -73,7 +69,7 @@ fn test() -> Option> { bb5: { StorageDead(_9); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 - _0 = > as Try>::from_error(move _8) -> [return: bb6, unwind: bb10]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20 + _0 = > as Try>::from_error(move _8) -> [return: bb6, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20 // mir::Constant // + span: $DIR/issue-62289.rs:9:15: 9:20 // + literal: Const { ty: fn(> as std::ops::Try>::Error) -> std::option::Option> {> as std::ops::Try>::from_error}, val: Value(Scalar()) } @@ -82,29 +78,41 @@ fn test() -> Option> { bb6: { StorageDead(_8); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 StorageDead(_6); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - drop(_2) -> [return: bb7, unwind: bb9]; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 + drop(_2) -> bb9; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 } bb7: { + StorageDead(_2); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 + _0 = Option::>::Some(move _1); // scope 0 at $DIR/issue-62289.rs:9:5: 9:22 + drop(_1) -> bb8; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 + } + + bb8: { + StorageDead(_1); // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 + StorageDead(_3); // scope 0 at $DIR/issue-62289.rs:10:1: 10:2 + goto -> bb10; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 + } + + bb9: { StorageDead(_2); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 StorageDead(_1); // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 StorageDead(_3); // scope 0 at $DIR/issue-62289.rs:10:1: 10:2 - goto -> bb8; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 + goto -> bb10; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 } - bb8: { + bb10: { return; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 } - bb9 (cleanup): { - drop(_0) -> bb11; // scope 0 at $DIR/issue-62289.rs:10:1: 10:2 + bb11 (cleanup): { + drop(_1) -> bb13; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 } - bb10 (cleanup): { - drop(_2) -> bb11; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 + bb12 (cleanup): { + drop(_2) -> bb13; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 } - bb11 (cleanup): { + bb13 (cleanup): { resume; // scope 0 at $DIR/issue-62289.rs:8:1: 10:2 } } diff --git a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir index 2f95931d2b2a1..bbb433dbe25c7 100644 --- a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir +++ b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir @@ -28,7 +28,7 @@ fn main() -> () { bb1: { StorageDead(_3); // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:33: 9:34 - _1 = std::mem::drop::(move _2) -> bb2; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:5: 9:35 + _1 = std::mem::drop::(move _2) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:5: 9:35 // mir::Constant // + span: $DIR/no-spurious-drop-after-call.rs:9:5: 9:19 // + literal: Const { ty: fn(std::string::String) {std::mem::drop::}, val: Value(Scalar()) } @@ -41,4 +41,12 @@ fn main() -> () { _0 = const (); // scope 0 at $DIR/no-spurious-drop-after-call.rs:8:11: 10:2 return; // scope 0 at $DIR/no-spurious-drop-after-call.rs:10:2: 10:2 } + + bb3 (cleanup): { + drop(_2) -> bb4; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:34: 9:35 + } + + bb4 (cleanup): { + resume; // scope 0 at $DIR/no-spurious-drop-after-call.rs:8:1: 10:2 + } } diff --git a/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir index 9bca5d24605fb..d18f6308ded84 100644 --- a/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir +++ b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir @@ -22,38 +22,62 @@ fn move_out_by_subslice() -> () { _3 = Box(i32); // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 (*_3) = const 1_i32; // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19 _2 = move _3; // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 + drop(_3) -> [return: bb1, unwind: bb9]; // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19 + } + + bb1: { StorageDead(_3); // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19 StorageLive(_4); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 StorageLive(_5); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 _5 = Box(i32); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 (*_5) = const 2_i32; // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26 _4 = move _5; // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 + drop(_5) -> [return: bb2, unwind: bb8]; // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26 + } + + bb2: { StorageDead(_5); // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26 _1 = [move _2, move _4]; // scope 0 at $DIR/uniform_array_move_out.rs:11:13: 11:27 + drop(_4) -> [return: bb3, unwind: bb9]; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 + } + + bb3: { StorageDead(_4); // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 + drop(_2) -> [return: bb4, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 + } + + bb4: { StorageDead(_2); // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 FakeRead(ForLet, _1); // scope 0 at $DIR/uniform_array_move_out.rs:11:9: 11:10 StorageLive(_6); // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17 _6 = move _1[0..2]; // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17 _0 = const (); // scope 0 at $DIR/uniform_array_move_out.rs:10:27: 13:2 - drop(_6) -> [return: bb1, unwind: bb3]; // scope 1 at $DIR/uniform_array_move_out.rs:13:1: 13:2 + drop(_6) -> [return: bb5, unwind: bb7]; // scope 1 at $DIR/uniform_array_move_out.rs:13:1: 13:2 } - bb1: { + bb5: { StorageDead(_6); // scope 1 at $DIR/uniform_array_move_out.rs:13:1: 13:2 - drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2 + drop(_1) -> [return: bb6, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2 } - bb2: { + bb6: { StorageDead(_1); // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2 return; // scope 0 at $DIR/uniform_array_move_out.rs:13:2: 13:2 } - bb3 (cleanup): { - drop(_1) -> bb4; // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2 + bb7 (cleanup): { + drop(_1) -> bb10; // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2 + } + + bb8 (cleanup): { + drop(_4) -> bb9; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 + } + + bb9 (cleanup): { + drop(_2) -> bb10; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 } - bb4 (cleanup): { + bb10 (cleanup): { resume; // scope 0 at $DIR/uniform_array_move_out.rs:10:1: 13:2 } } diff --git a/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir index c9004416f2ec1..eda8e5fd3afe7 100644 --- a/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir +++ b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir @@ -22,38 +22,62 @@ fn move_out_from_end() -> () { _3 = Box(i32); // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 (*_3) = const 1_i32; // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19 _2 = move _3; // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 + drop(_3) -> [return: bb1, unwind: bb9]; // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19 + } + + bb1: { StorageDead(_3); // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19 StorageLive(_4); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 StorageLive(_5); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 _5 = Box(i32); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 (*_5) = const 2_i32; // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26 _4 = move _5; // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 + drop(_5) -> [return: bb2, unwind: bb8]; // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26 + } + + bb2: { StorageDead(_5); // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26 _1 = [move _2, move _4]; // scope 0 at $DIR/uniform_array_move_out.rs:5:13: 5:27 + drop(_4) -> [return: bb3, unwind: bb9]; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 + } + + bb3: { StorageDead(_4); // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 + drop(_2) -> [return: bb4, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 + } + + bb4: { StorageDead(_2); // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 FakeRead(ForLet, _1); // scope 0 at $DIR/uniform_array_move_out.rs:5:9: 5:10 StorageLive(_6); // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16 _6 = move _1[1 of 2]; // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16 _0 = const (); // scope 0 at $DIR/uniform_array_move_out.rs:4:24: 7:2 - drop(_6) -> [return: bb1, unwind: bb3]; // scope 1 at $DIR/uniform_array_move_out.rs:7:1: 7:2 + drop(_6) -> [return: bb5, unwind: bb7]; // scope 1 at $DIR/uniform_array_move_out.rs:7:1: 7:2 } - bb1: { + bb5: { StorageDead(_6); // scope 1 at $DIR/uniform_array_move_out.rs:7:1: 7:2 - drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2 + drop(_1) -> [return: bb6, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2 } - bb2: { + bb6: { StorageDead(_1); // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2 return; // scope 0 at $DIR/uniform_array_move_out.rs:7:2: 7:2 } - bb3 (cleanup): { - drop(_1) -> bb4; // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2 + bb7 (cleanup): { + drop(_1) -> bb10; // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2 + } + + bb8 (cleanup): { + drop(_4) -> bb9; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 + } + + bb9 (cleanup): { + drop(_2) -> bb10; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 } - bb4 (cleanup): { + bb10 (cleanup): { resume; // scope 0 at $DIR/uniform_array_move_out.rs:4:1: 7:2 } } diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt index 4c03e950af029..e14e733fff6d4 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt @@ -19,12 +19,12 @@ 18| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg); 19| 2|} ------------------ - | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec>: + | used_crate::used_only_from_bin_crate_generic_function::<&str>: | 17| 1|pub fn used_only_from_bin_crate_generic_function(arg: T) { | 18| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); | 19| 1|} ------------------ - | used_crate::used_only_from_bin_crate_generic_function::<&str>: + | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec>: | 17| 1|pub fn used_only_from_bin_crate_generic_function(arg: T) { | 18| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); | 19| 1|} diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on.-------.InstrumentCoverage.0.html index 19707255d07c7..81310c8cb25aa 100644 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on.-------.InstrumentCoverage.0.html @@ -70,166 +70,166 @@
@0,1,2,3,4,5⦊pub fn block_on<F: Future>(mut future: F) -> F::Output { let mut future = unsafe { Pin::new_unchecked(&mut future) }; static VTABLE: RawWakerVTable = RawWakerVTable::new( |_| unimplemented!("clone"), |_| unimplemented!("wake"), |_| unimplemented!("wake_by_ref"), |_| (), ); let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; let mut context = Context::from_waker(&waker)⦉@0,1,2,3,4,5; loop { if let Poll::Ready(@10,12,14,15,16,17⦊val⦉@10,12,14,15,16,17) = @6,7,8,9⦊future.as_mut().poll(&mut context)⦉@6,7,8,9 { break @10,12,14,15,16,17⦊val⦉@10,12,14,15,16,17; }@11,13⦊⦉@11,13 diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.main.-------.InstrumentCoverage.0.html index 611799161d398..313a36ed6c2f2 100644 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.main.-------.InstrumentCoverage.0.html @@ -69,9 +69,9 @@ -
@0,1,2,3,4,5,6,7,8,9,10,11,12,13⦊fn main() { - let _ = g(10); - let _ = h(9); - let mut future = Box::pin(i(8)); - j(7); - l(6); - let _ = m(5); - executor::block_on(future.as_mut()); -@4,5,6,7,8⦊format!("'{}'", val) @@ -117,13 +117,13 @@ 103:9-103:29: @4[23]: _18 = (_16.0: &&str) 103:9-103:29: @4[26]: _20 = &(*_18) 103:9-103:29: @4[28]: _21 = <&str as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r &str, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) -103:9-103:29: @4.Call: _19 = ArgumentV1::new::<&str>(move _20, move _21) -> [return: bb5, unwind: bb10] +103:9-103:29: @4.Call: _19 = ArgumentV1::new::<&str>(move _20, move _21) -> [return: bb5, unwind: bb9] 103:9-103:29: @5[2]: _15 = [move _19] 103:9-103:29: @5[5]: _14 = &_15 103:9-103:29: @5[6]: _13 = &(*_14) 103:9-103:29: @5[7]: _12 = move _13 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) -103:9-103:29: @5.Call: _7 = Arguments::new_v1(move _8, move _12) -> [return: bb6, unwind: bb10] -103:9-103:29: @6.Call: _6 = format(move _7) -> [return: bb7, unwind: bb10] +103:9-103:29: @5.Call: _7 = Arguments::new_v1(move _8, move _12) -> [return: bb6, unwind: bb9] +103:9-103:29: @6.Call: _6 = format(move _7) -> [return: bb7, unwind: bb9] 103:9-103:29: @7[1]: FakeRead(ForLet, _6) 103:9-103:29: @7[6]: _0 = move _6 104:6-104:6: @8.Return: return"> }⦉@4,5,6,7,8
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main.-------.InstrumentCoverage.0.html index 3bd446b0e049d..702c7937064b7 100644 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main.-------.InstrumentCoverage.0.html @@ -69,7079 +69,7079 @@ -
@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37⦊fn main() { -@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊fn main() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure - // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. - // dependent conditions. + let is_true = std::env::args().len() == 1; - let is_true = std::env::args().len() == 1; + let is_false = ! is_true; - let is_false = ! is_true; + - + let mut some_string = Some(String::from("the string content")); - let mut some_string = Some(String::from("the string content")); + println!( - println!( + "The string or alt: {}" - "The string or alt: {}" + , - , + some_string - some_string + . - . + unwrap_or_else - unwrap_or_else + ( - ( + ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37|| +10:9-10:24: @5[1]: FakeRead(ForLet, _7) +12:9-12:32: @5[8]: _137 = const main::promoted[4] +12:9-12:32: @5[9]: _14 = &(*_137) +12:9-12:32: @5[10]: _13 = &(*_14) +12:9-12:32: @5[11]: _12 = move _13 as &[&str] (Pointer(Unsize)) +14:9-14:20: @5[21]: _23 = move _7 +14:9-26:10: @5.Call: _22 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:18:13: 25:14]>(move _23, move _24) -> [return: bb6, unwind: bb54] +14:9-26:10: @6[2]: _21 = &_22 +11:5-27:7: @6[3]: _20 = (move _21,) +11:5-27:7: @6[5]: FakeRead(ForMatchedPlace, _20) +11:5-27:7: @6[7]: _26 = (_20.0: &std::string::String) +11:5-27:7: @6[10]: _28 = &(*_26) +11:5-27:7: @6[12]: _29 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +11:5-27:7: @6.Call: _27 = ArgumentV1::new::<String>(move _28, move _29) -> [return: bb7, unwind: bb53] +11:5-27:7: @7[2]: _19 = [move _27] +11:5-27:7: @7[5]: _18 = &_19 +11:5-27:7: @7[6]: _17 = &(*_18) +11:5-27:7: @7[7]: _16 = move _17 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +11:5-27:7: @7.Call: _11 = Arguments::new_v1(move _12, move _16) -> [return: bb8, unwind: bb53] +11:5-27:7: @8.Call: _10 = _print(move _11) -> [return: bb9, unwind: bb53] +11:5-27:7: @10[6]: _9 = const () +3:11-155:2: @41[38]: _0 = const ()"> ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42|| { let mut countdown = 0; if is_false { countdown = 10; } "alt string 1".to_owned() - } }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37⦊ -@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊ + ) - ) + ); - ); + - + some_string = Some(String::from("the string content")); - some_string = Some(String::from("the string content")); + let - let + a - a + = - = + ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37|| +10:9-10:24: @5[1]: FakeRead(ForLet, _7) +12:9-12:32: @5[8]: _137 = const main::promoted[4] +12:9-12:32: @5[9]: _14 = &(*_137) +12:9-12:32: @5[10]: _13 = &(*_14) +12:9-12:32: @5[11]: _12 = move _13 as &[&str] (Pointer(Unsize)) +14:9-14:20: @5[21]: _23 = move _7 +14:9-26:10: @5.Call: _22 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:18:13: 25:14]>(move _23, move _24) -> [return: bb6, unwind: bb54] +14:9-26:10: @6[2]: _21 = &_22 +11:5-27:7: @6[3]: _20 = (move _21,) +11:5-27:7: @6[5]: FakeRead(ForMatchedPlace, _20) +11:5-27:7: @6[7]: _26 = (_20.0: &std::string::String) +11:5-27:7: @6[10]: _28 = &(*_26) +11:5-27:7: @6[12]: _29 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +11:5-27:7: @6.Call: _27 = ArgumentV1::new::<String>(move _28, move _29) -> [return: bb7, unwind: bb53] +11:5-27:7: @7[2]: _19 = [move _27] +11:5-27:7: @7[5]: _18 = &_19 +11:5-27:7: @7[6]: _17 = &(*_18) +11:5-27:7: @7[7]: _16 = move _17 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +11:5-27:7: @7.Call: _11 = Arguments::new_v1(move _12, move _16) -> [return: bb8, unwind: bb53] +11:5-27:7: @8.Call: _10 = _print(move _11) -> [return: bb9, unwind: bb53] +11:5-27:7: @10[6]: _9 = const () +29:24-29:58: @10.Call: _31 = <String as From<&str>>::from(const "the string content") -> [return: bb11, unwind: bb55] +29:19-29:59: @11[0]: _30 = Option::<String>::Some(move _31) +33:9-40:6: @14[3]: _33 = &_5 +31:9-31:10: @14[6]: FakeRead(ForLet, _32) +3:11-155:2: @41[38]: _0 = const ()"> ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42|| { let mut countdown = 0; if is_false { countdown = 10; } "alt string 2".to_owned() - } }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37⦊; -@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; + println!( - println!( + "The string or alt: {}" - "The string or alt: {}" + , - , + some_string - some_string + . - . + unwrap_or_else - unwrap_or_else + ( - ( + a - a + ) - ) + ); - ); + - + some_string = None; - some_string = None; + println!( - println!( + "The string or alt: {}" - "The string or alt: {}" + , - , + some_string - some_string + . - . + unwrap_or_else - unwrap_or_else + ( - ( + ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37|| +10:9-10:24: @5[1]: FakeRead(ForLet, _7) +12:9-12:32: @5[8]: _137 = const main::promoted[4] +12:9-12:32: @5[9]: _14 = &(*_137) +12:9-12:32: @5[10]: _13 = &(*_14) +12:9-12:32: @5[11]: _12 = move _13 as &[&str] (Pointer(Unsize)) +14:9-14:20: @5[21]: _23 = move _7 +14:9-26:10: @5.Call: _22 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:18:13: 25:14]>(move _23, move _24) -> [return: bb6, unwind: bb54] +14:9-26:10: @6[2]: _21 = &_22 +11:5-27:7: @6[3]: _20 = (move _21,) +11:5-27:7: @6[5]: FakeRead(ForMatchedPlace, _20) +11:5-27:7: @6[7]: _26 = (_20.0: &std::string::String) +11:5-27:7: @6[10]: _28 = &(*_26) +11:5-27:7: @6[12]: _29 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +11:5-27:7: @6.Call: _27 = ArgumentV1::new::<String>(move _28, move _29) -> [return: bb7, unwind: bb53] +11:5-27:7: @7[2]: _19 = [move _27] +11:5-27:7: @7[5]: _18 = &_19 +11:5-27:7: @7[6]: _17 = &(*_18) +11:5-27:7: @7[7]: _16 = move _17 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +11:5-27:7: @7.Call: _11 = Arguments::new_v1(move _12, move _16) -> [return: bb8, unwind: bb53] +11:5-27:7: @8.Call: _10 = _print(move _11) -> [return: bb9, unwind: bb53] +11:5-27:7: @10[6]: _9 = const () +29:24-29:58: @10.Call: _31 = <String as From<&str>>::from(const "the string content") -> [return: bb11, unwind: bb55] +29:19-29:59: @11[0]: _30 = Option::<String>::Some(move _31) +33:9-40:6: @14[3]: _33 = &_5 +31:9-31:10: @14[6]: FakeRead(ForLet, _32) +42:9-42:32: @14[13]: _136 = const main::promoted[3] +42:9-42:32: @14[14]: _39 = &(*_136) +42:9-42:32: @14[15]: _38 = &(*_39) +42:9-42:32: @14[16]: _37 = move _38 as &[&str] (Pointer(Unsize)) +44:9-44:20: @14[26]: _48 = move _7 +48:13-48:14: @14[28]: _49 = _32 +44:9-49:10: @14.Call: _47 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:33:9: 40:6]>(move _48, move _49) -> [return: bb15, unwind: bb51] +44:9-49:10: @15[2]: _46 = &_47 +41:5-50:7: @15[3]: _45 = (move _46,) +41:5-50:7: @15[5]: FakeRead(ForMatchedPlace, _45) +41:5-50:7: @15[7]: _50 = (_45.0: &std::string::String) +41:5-50:7: @15[10]: _52 = &(*_50) +41:5-50:7: @15[12]: _53 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +41:5-50:7: @15.Call: _51 = ArgumentV1::new::<String>(move _52, move _53) -> [return: bb16, unwind: bb50] +41:5-50:7: @16[2]: _44 = [move _51] +41:5-50:7: @16[5]: _43 = &_44 +41:5-50:7: @16[6]: _42 = &(*_43) +41:5-50:7: @16[7]: _41 = move _42 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +41:5-50:7: @16.Call: _36 = Arguments::new_v1(move _37, move _41) -> [return: bb17, unwind: bb50] +41:5-50:7: @17.Call: _35 = _print(move _36) -> [return: bb18, unwind: bb50] +41:5-50:7: @19[6]: _34 = const () +52:19-52:23: @19[9]: _54 = Option::<String>::None +54:9-54:32: @21[7]: _135 = const main::promoted[2] +54:9-54:32: @21[8]: _60 = &(*_135) +54:9-54:32: @21[9]: _59 = &(*_60) +54:9-54:32: @21[10]: _58 = move _59 as &[&str] (Pointer(Unsize)) +56:9-56:20: @21[20]: _69 = move _7 +56:9-68:10: @21.Call: _68 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:60:13: 67:14]>(move _69, move _70) -> [return: bb22, unwind: bb48] +56:9-68:10: @22[2]: _67 = &_68 +53:5-69:7: @22[3]: _66 = (move _67,) +53:5-69:7: @22[5]: FakeRead(ForMatchedPlace, _66) +53:5-69:7: @22[7]: _72 = (_66.0: &std::string::String) +53:5-69:7: @22[10]: _74 = &(*_72) +53:5-69:7: @22[12]: _75 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +53:5-69:7: @22.Call: _73 = ArgumentV1::new::<String>(move _74, move _75) -> [return: bb23, unwind: bb47] +53:5-69:7: @23[2]: _65 = [move _73] +53:5-69:7: @23[5]: _64 = &_65 +53:5-69:7: @23[6]: _63 = &(*_64) +53:5-69:7: @23[7]: _62 = move _63 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +53:5-69:7: @23.Call: _57 = Arguments::new_v1(move _58, move _62) -> [return: bb24, unwind: bb47] +53:5-69:7: @24.Call: _56 = _print(move _57) -> [return: bb25, unwind: bb47] +53:5-69:7: @26[6]: _55 = const () +3:11-155:2: @41[38]: _0 = const ()"> ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42|| { let mut countdown = 0; if is_false { countdown = 10; } "alt string 3".to_owned() - } }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37⦊ -@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊ + ) - ) + ); - ); + - + some_string = None; - some_string = None; + let - let + a - a + = - = + ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37|| +10:9-10:24: @5[1]: FakeRead(ForLet, _7) +12:9-12:32: @5[8]: _137 = const main::promoted[4] +12:9-12:32: @5[9]: _14 = &(*_137) +12:9-12:32: @5[10]: _13 = &(*_14) +12:9-12:32: @5[11]: _12 = move _13 as &[&str] (Pointer(Unsize)) +14:9-14:20: @5[21]: _23 = move _7 +14:9-26:10: @5.Call: _22 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:18:13: 25:14]>(move _23, move _24) -> [return: bb6, unwind: bb54] +14:9-26:10: @6[2]: _21 = &_22 +11:5-27:7: @6[3]: _20 = (move _21,) +11:5-27:7: @6[5]: FakeRead(ForMatchedPlace, _20) +11:5-27:7: @6[7]: _26 = (_20.0: &std::string::String) +11:5-27:7: @6[10]: _28 = &(*_26) +11:5-27:7: @6[12]: _29 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +11:5-27:7: @6.Call: _27 = ArgumentV1::new::<String>(move _28, move _29) -> [return: bb7, unwind: bb53] +11:5-27:7: @7[2]: _19 = [move _27] +11:5-27:7: @7[5]: _18 = &_19 +11:5-27:7: @7[6]: _17 = &(*_18) +11:5-27:7: @7[7]: _16 = move _17 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +11:5-27:7: @7.Call: _11 = Arguments::new_v1(move _12, move _16) -> [return: bb8, unwind: bb53] +11:5-27:7: @8.Call: _10 = _print(move _11) -> [return: bb9, unwind: bb53] +11:5-27:7: @10[6]: _9 = const () +29:24-29:58: @10.Call: _31 = <String as From<&str>>::from(const "the string content") -> [return: bb11, unwind: bb55] +29:19-29:59: @11[0]: _30 = Option::<String>::Some(move _31) +33:9-40:6: @14[3]: _33 = &_5 +31:9-31:10: @14[6]: FakeRead(ForLet, _32) +42:9-42:32: @14[13]: _136 = const main::promoted[3] +42:9-42:32: @14[14]: _39 = &(*_136) +42:9-42:32: @14[15]: _38 = &(*_39) +42:9-42:32: @14[16]: _37 = move _38 as &[&str] (Pointer(Unsize)) +44:9-44:20: @14[26]: _48 = move _7 +48:13-48:14: @14[28]: _49 = _32 +44:9-49:10: @14.Call: _47 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:33:9: 40:6]>(move _48, move _49) -> [return: bb15, unwind: bb51] +44:9-49:10: @15[2]: _46 = &_47 +41:5-50:7: @15[3]: _45 = (move _46,) +41:5-50:7: @15[5]: FakeRead(ForMatchedPlace, _45) +41:5-50:7: @15[7]: _50 = (_45.0: &std::string::String) +41:5-50:7: @15[10]: _52 = &(*_50) +41:5-50:7: @15[12]: _53 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +41:5-50:7: @15.Call: _51 = ArgumentV1::new::<String>(move _52, move _53) -> [return: bb16, unwind: bb50] +41:5-50:7: @16[2]: _44 = [move _51] +41:5-50:7: @16[5]: _43 = &_44 +41:5-50:7: @16[6]: _42 = &(*_43) +41:5-50:7: @16[7]: _41 = move _42 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +41:5-50:7: @16.Call: _36 = Arguments::new_v1(move _37, move _41) -> [return: bb17, unwind: bb50] +41:5-50:7: @17.Call: _35 = _print(move _36) -> [return: bb18, unwind: bb50] +41:5-50:7: @19[6]: _34 = const () +52:19-52:23: @19[9]: _54 = Option::<String>::None +54:9-54:32: @21[7]: _135 = const main::promoted[2] +54:9-54:32: @21[8]: _60 = &(*_135) +54:9-54:32: @21[9]: _59 = &(*_60) +54:9-54:32: @21[10]: _58 = move _59 as &[&str] (Pointer(Unsize)) +56:9-56:20: @21[20]: _69 = move _7 +56:9-68:10: @21.Call: _68 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:60:13: 67:14]>(move _69, move _70) -> [return: bb22, unwind: bb48] +56:9-68:10: @22[2]: _67 = &_68 +53:5-69:7: @22[3]: _66 = (move _67,) +53:5-69:7: @22[5]: FakeRead(ForMatchedPlace, _66) +53:5-69:7: @22[7]: _72 = (_66.0: &std::string::String) +53:5-69:7: @22[10]: _74 = &(*_72) +53:5-69:7: @22[12]: _75 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +53:5-69:7: @22.Call: _73 = ArgumentV1::new::<String>(move _74, move _75) -> [return: bb23, unwind: bb47] +53:5-69:7: @23[2]: _65 = [move _73] +53:5-69:7: @23[5]: _64 = &_65 +53:5-69:7: @23[6]: _63 = &(*_64) +53:5-69:7: @23[7]: _62 = move _63 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +53:5-69:7: @23.Call: _57 = Arguments::new_v1(move _58, move _62) -> [return: bb24, unwind: bb47] +53:5-69:7: @24.Call: _56 = _print(move _57) -> [return: bb25, unwind: bb47] +53:5-69:7: @26[6]: _55 = const () +71:19-71:23: @26[9]: _76 = Option::<String>::None +75:9-82:6: @28[3]: _78 = &_5 +73:9-73:10: @28[6]: FakeRead(ForLet, _77) +3:11-155:2: @41[38]: _0 = const ()"> ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42|| { let mut countdown = 0; if is_false { countdown = 10; } "alt string 4".to_owned() - } }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37⦊; -@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; + println!( - println!( + "The string or alt: {}" - "The string or alt: {}" + , - , + some_string - some_string + . - . + unwrap_or_else - unwrap_or_else + ( - ( + a - a + ) - ) + ); - ); + - + let - let + quote_closure - quote_closure + = - = + ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37|val| +10:9-10:24: @5[1]: FakeRead(ForLet, _7) +12:9-12:32: @5[8]: _137 = const main::promoted[4] +12:9-12:32: @5[9]: _14 = &(*_137) +12:9-12:32: @5[10]: _13 = &(*_14) +12:9-12:32: @5[11]: _12 = move _13 as &[&str] (Pointer(Unsize)) +14:9-14:20: @5[21]: _23 = move _7 +14:9-26:10: @5.Call: _22 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:18:13: 25:14]>(move _23, move _24) -> [return: bb6, unwind: bb54] +14:9-26:10: @6[2]: _21 = &_22 +11:5-27:7: @6[3]: _20 = (move _21,) +11:5-27:7: @6[5]: FakeRead(ForMatchedPlace, _20) +11:5-27:7: @6[7]: _26 = (_20.0: &std::string::String) +11:5-27:7: @6[10]: _28 = &(*_26) +11:5-27:7: @6[12]: _29 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +11:5-27:7: @6.Call: _27 = ArgumentV1::new::<String>(move _28, move _29) -> [return: bb7, unwind: bb53] +11:5-27:7: @7[2]: _19 = [move _27] +11:5-27:7: @7[5]: _18 = &_19 +11:5-27:7: @7[6]: _17 = &(*_18) +11:5-27:7: @7[7]: _16 = move _17 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +11:5-27:7: @7.Call: _11 = Arguments::new_v1(move _12, move _16) -> [return: bb8, unwind: bb53] +11:5-27:7: @8.Call: _10 = _print(move _11) -> [return: bb9, unwind: bb53] +11:5-27:7: @10[6]: _9 = const () +29:24-29:58: @10.Call: _31 = <String as From<&str>>::from(const "the string content") -> [return: bb11, unwind: bb55] +29:19-29:59: @11[0]: _30 = Option::<String>::Some(move _31) +33:9-40:6: @14[3]: _33 = &_5 +31:9-31:10: @14[6]: FakeRead(ForLet, _32) +42:9-42:32: @14[13]: _136 = const main::promoted[3] +42:9-42:32: @14[14]: _39 = &(*_136) +42:9-42:32: @14[15]: _38 = &(*_39) +42:9-42:32: @14[16]: _37 = move _38 as &[&str] (Pointer(Unsize)) +44:9-44:20: @14[26]: _48 = move _7 +48:13-48:14: @14[28]: _49 = _32 +44:9-49:10: @14.Call: _47 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:33:9: 40:6]>(move _48, move _49) -> [return: bb15, unwind: bb51] +44:9-49:10: @15[2]: _46 = &_47 +41:5-50:7: @15[3]: _45 = (move _46,) +41:5-50:7: @15[5]: FakeRead(ForMatchedPlace, _45) +41:5-50:7: @15[7]: _50 = (_45.0: &std::string::String) +41:5-50:7: @15[10]: _52 = &(*_50) +41:5-50:7: @15[12]: _53 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +41:5-50:7: @15.Call: _51 = ArgumentV1::new::<String>(move _52, move _53) -> [return: bb16, unwind: bb50] +41:5-50:7: @16[2]: _44 = [move _51] +41:5-50:7: @16[5]: _43 = &_44 +41:5-50:7: @16[6]: _42 = &(*_43) +41:5-50:7: @16[7]: _41 = move _42 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +41:5-50:7: @16.Call: _36 = Arguments::new_v1(move _37, move _41) -> [return: bb17, unwind: bb50] +41:5-50:7: @17.Call: _35 = _print(move _36) -> [return: bb18, unwind: bb50] +41:5-50:7: @19[6]: _34 = const () +52:19-52:23: @19[9]: _54 = Option::<String>::None +54:9-54:32: @21[7]: _135 = const main::promoted[2] +54:9-54:32: @21[8]: _60 = &(*_135) +54:9-54:32: @21[9]: _59 = &(*_60) +54:9-54:32: @21[10]: _58 = move _59 as &[&str] (Pointer(Unsize)) +56:9-56:20: @21[20]: _69 = move _7 +56:9-68:10: @21.Call: _68 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:60:13: 67:14]>(move _69, move _70) -> [return: bb22, unwind: bb48] +56:9-68:10: @22[2]: _67 = &_68 +53:5-69:7: @22[3]: _66 = (move _67,) +53:5-69:7: @22[5]: FakeRead(ForMatchedPlace, _66) +53:5-69:7: @22[7]: _72 = (_66.0: &std::string::String) +53:5-69:7: @22[10]: _74 = &(*_72) +53:5-69:7: @22[12]: _75 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +53:5-69:7: @22.Call: _73 = ArgumentV1::new::<String>(move _74, move _75) -> [return: bb23, unwind: bb47] +53:5-69:7: @23[2]: _65 = [move _73] +53:5-69:7: @23[5]: _64 = &_65 +53:5-69:7: @23[6]: _63 = &(*_64) +53:5-69:7: @23[7]: _62 = move _63 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +53:5-69:7: @23.Call: _57 = Arguments::new_v1(move _58, move _62) -> [return: bb24, unwind: bb47] +53:5-69:7: @24.Call: _56 = _print(move _57) -> [return: bb25, unwind: bb47] +53:5-69:7: @26[6]: _55 = const () +71:19-71:23: @26[9]: _76 = Option::<String>::None +75:9-82:6: @28[3]: _78 = &_5 +73:9-73:10: @28[6]: FakeRead(ForLet, _77) +84:9-84:32: @28[13]: _134 = const main::promoted[1] +84:9-84:32: @28[14]: _84 = &(*_134) +84:9-84:32: @28[15]: _83 = &(*_84) +84:9-84:32: @28[16]: _82 = move _83 as &[&str] (Pointer(Unsize)) +86:9-86:20: @28[26]: _93 = move _7 +90:13-90:14: @28[28]: _94 = _77 +86:9-91:10: @28.Call: _92 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:75:9: 82:6]>(move _93, move _94) -> [return: bb29, unwind: bb45] +86:9-91:10: @29[2]: _91 = &_92 +83:5-92:7: @29[3]: _90 = (move _91,) +83:5-92:7: @29[5]: FakeRead(ForMatchedPlace, _90) +83:5-92:7: @29[7]: _95 = (_90.0: &std::string::String) +83:5-92:7: @29[10]: _97 = &(*_95) +83:5-92:7: @29[12]: _98 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +83:5-92:7: @29.Call: _96 = ArgumentV1::new::<String>(move _97, move _98) -> [return: bb30, unwind: bb44] +83:5-92:7: @30[2]: _89 = [move _96] +83:5-92:7: @30[5]: _88 = &_89 +83:5-92:7: @30[6]: _87 = &(*_88) +83:5-92:7: @30[7]: _86 = move _87 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +83:5-92:7: @30.Call: _81 = Arguments::new_v1(move _82, move _86) -> [return: bb31, unwind: bb44] +83:5-92:7: @31.Call: _80 = _print(move _81) -> [return: bb32, unwind: bb44] +83:5-92:7: @33[6]: _79 = const () +97:9-104:6: @33[10]: _100 = &_5 +95:9-95:22: @33[13]: FakeRead(ForLet, _99) +3:11-155:2: @41[38]: _0 = const ()"> ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42|val| { let mut countdown = 0; if is_false { countdown = 10; } format!("'{}'", val) - } }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37⦊; -@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; + println!( - println!( + "Repeated, quoted string: {:?}" - "Repeated, quoted string: {:?}" + , - , + std::iter::repeat("repeat me") - std::iter::repeat("repeat me") + .take(5) - .take(5) + .map - .map + ( - ( + quote_closure - quote_closure + ) - ) + .collect::<Vec<_>>() - .collect::<Vec<_>>() + ); - ); + - + let - let + _unused_closure - _unused_closure + = - = + ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37| +10:9-10:24: @5[1]: FakeRead(ForLet, _7) +12:9-12:32: @5[8]: _137 = const main::promoted[4] +12:9-12:32: @5[9]: _14 = &(*_137) +12:9-12:32: @5[10]: _13 = &(*_14) +12:9-12:32: @5[11]: _12 = move _13 as &[&str] (Pointer(Unsize)) +14:9-14:20: @5[21]: _23 = move _7 +14:9-26:10: @5.Call: _22 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:18:13: 25:14]>(move _23, move _24) -> [return: bb6, unwind: bb54] +14:9-26:10: @6[2]: _21 = &_22 +11:5-27:7: @6[3]: _20 = (move _21,) +11:5-27:7: @6[5]: FakeRead(ForMatchedPlace, _20) +11:5-27:7: @6[7]: _26 = (_20.0: &std::string::String) +11:5-27:7: @6[10]: _28 = &(*_26) +11:5-27:7: @6[12]: _29 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +11:5-27:7: @6.Call: _27 = ArgumentV1::new::<String>(move _28, move _29) -> [return: bb7, unwind: bb53] +11:5-27:7: @7[2]: _19 = [move _27] +11:5-27:7: @7[5]: _18 = &_19 +11:5-27:7: @7[6]: _17 = &(*_18) +11:5-27:7: @7[7]: _16 = move _17 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +11:5-27:7: @7.Call: _11 = Arguments::new_v1(move _12, move _16) -> [return: bb8, unwind: bb53] +11:5-27:7: @8.Call: _10 = _print(move _11) -> [return: bb9, unwind: bb53] +11:5-27:7: @10[6]: _9 = const () +29:24-29:58: @10.Call: _31 = <String as From<&str>>::from(const "the string content") -> [return: bb11, unwind: bb55] +29:19-29:59: @11[0]: _30 = Option::<String>::Some(move _31) +33:9-40:6: @14[3]: _33 = &_5 +31:9-31:10: @14[6]: FakeRead(ForLet, _32) +42:9-42:32: @14[13]: _136 = const main::promoted[3] +42:9-42:32: @14[14]: _39 = &(*_136) +42:9-42:32: @14[15]: _38 = &(*_39) +42:9-42:32: @14[16]: _37 = move _38 as &[&str] (Pointer(Unsize)) +44:9-44:20: @14[26]: _48 = move _7 +48:13-48:14: @14[28]: _49 = _32 +44:9-49:10: @14.Call: _47 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:33:9: 40:6]>(move _48, move _49) -> [return: bb15, unwind: bb51] +44:9-49:10: @15[2]: _46 = &_47 +41:5-50:7: @15[3]: _45 = (move _46,) +41:5-50:7: @15[5]: FakeRead(ForMatchedPlace, _45) +41:5-50:7: @15[7]: _50 = (_45.0: &std::string::String) +41:5-50:7: @15[10]: _52 = &(*_50) +41:5-50:7: @15[12]: _53 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +41:5-50:7: @15.Call: _51 = ArgumentV1::new::<String>(move _52, move _53) -> [return: bb16, unwind: bb50] +41:5-50:7: @16[2]: _44 = [move _51] +41:5-50:7: @16[5]: _43 = &_44 +41:5-50:7: @16[6]: _42 = &(*_43) +41:5-50:7: @16[7]: _41 = move _42 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +41:5-50:7: @16.Call: _36 = Arguments::new_v1(move _37, move _41) -> [return: bb17, unwind: bb50] +41:5-50:7: @17.Call: _35 = _print(move _36) -> [return: bb18, unwind: bb50] +41:5-50:7: @19[6]: _34 = const () +52:19-52:23: @19[9]: _54 = Option::<String>::None +54:9-54:32: @21[7]: _135 = const main::promoted[2] +54:9-54:32: @21[8]: _60 = &(*_135) +54:9-54:32: @21[9]: _59 = &(*_60) +54:9-54:32: @21[10]: _58 = move _59 as &[&str] (Pointer(Unsize)) +56:9-56:20: @21[20]: _69 = move _7 +56:9-68:10: @21.Call: _68 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:60:13: 67:14]>(move _69, move _70) -> [return: bb22, unwind: bb48] +56:9-68:10: @22[2]: _67 = &_68 +53:5-69:7: @22[3]: _66 = (move _67,) +53:5-69:7: @22[5]: FakeRead(ForMatchedPlace, _66) +53:5-69:7: @22[7]: _72 = (_66.0: &std::string::String) +53:5-69:7: @22[10]: _74 = &(*_72) +53:5-69:7: @22[12]: _75 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +53:5-69:7: @22.Call: _73 = ArgumentV1::new::<String>(move _74, move _75) -> [return: bb23, unwind: bb47] +53:5-69:7: @23[2]: _65 = [move _73] +53:5-69:7: @23[5]: _64 = &_65 +53:5-69:7: @23[6]: _63 = &(*_64) +53:5-69:7: @23[7]: _62 = move _63 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +53:5-69:7: @23.Call: _57 = Arguments::new_v1(move _58, move _62) -> [return: bb24, unwind: bb47] +53:5-69:7: @24.Call: _56 = _print(move _57) -> [return: bb25, unwind: bb47] +53:5-69:7: @26[6]: _55 = const () +71:19-71:23: @26[9]: _76 = Option::<String>::None +75:9-82:6: @28[3]: _78 = &_5 +73:9-73:10: @28[6]: FakeRead(ForLet, _77) +84:9-84:32: @28[13]: _134 = const main::promoted[1] +84:9-84:32: @28[14]: _84 = &(*_134) +84:9-84:32: @28[15]: _83 = &(*_84) +84:9-84:32: @28[16]: _82 = move _83 as &[&str] (Pointer(Unsize)) +86:9-86:20: @28[26]: _93 = move _7 +90:13-90:14: @28[28]: _94 = _77 +86:9-91:10: @28.Call: _92 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:75:9: 82:6]>(move _93, move _94) -> [return: bb29, unwind: bb45] +86:9-91:10: @29[2]: _91 = &_92 +83:5-92:7: @29[3]: _90 = (move _91,) +83:5-92:7: @29[5]: FakeRead(ForMatchedPlace, _90) +83:5-92:7: @29[7]: _95 = (_90.0: &std::string::String) +83:5-92:7: @29[10]: _97 = &(*_95) +83:5-92:7: @29[12]: _98 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +83:5-92:7: @29.Call: _96 = ArgumentV1::new::<String>(move _97, move _98) -> [return: bb30, unwind: bb44] +83:5-92:7: @30[2]: _89 = [move _96] +83:5-92:7: @30[5]: _88 = &_89 +83:5-92:7: @30[6]: _87 = &(*_88) +83:5-92:7: @30[7]: _86 = move _87 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +83:5-92:7: @30.Call: _81 = Arguments::new_v1(move _82, move _86) -> [return: bb31, unwind: bb44] +83:5-92:7: @31.Call: _80 = _print(move _81) -> [return: bb32, unwind: bb44] +83:5-92:7: @33[6]: _79 = const () +97:9-104:6: @33[10]: _100 = &_5 +95:9-95:22: @33[13]: FakeRead(ForLet, _99) +106:9-106:40: @33[20]: _133 = const main::promoted[0] +106:9-106:40: @33[21]: _106 = &(*_133) +106:9-106:40: @33[22]: _105 = &(*_106) +106:9-106:40: @33[23]: _104 = move _105 as &[&str] (Pointer(Unsize)) +108:9-108:39: @33.Call: _117 = std::iter::repeat::<&str>(const "repeat me") -> [return: bb34, unwind: bb55] +108:9-109:21: @34.Call: _116 = <std::iter::Repeat<&str> as Iterator>::take(move _117, const 5_usize) -> [return: bb35, unwind: bb55] +112:13-112:26: @35[2]: _118 = _99 +108:9-113:10: @35.Call: _115 = <std::iter::Take<std::iter::Repeat<&str>> as Iterator>::map::<String, [closure@../coverage/closure.rs:97:9: 104:6]>(move _116, move _118) -> [return: bb36, unwind: bb55] +108:9-114:33: @36.Call: _114 = <Map<std::iter::Take<std::iter::Repeat<&str>>, [closure@../coverage/closure.rs:97:9: 104:6]> as Iterator>::collect::<Vec<String>>(move _115) -> [return: bb37, unwind: bb55] +108:9-114:33: @37[1]: _113 = &_114 +105:5-115:7: @37[2]: _112 = (move _113,) +105:5-115:7: @37[4]: FakeRead(ForMatchedPlace, _112) +105:5-115:7: @37[6]: _119 = (_112.0: &std::vec::Vec<std::string::String>) +105:5-115:7: @37[9]: _121 = &(*_119) +105:5-115:7: @37[11]: _122 = <Vec<String> as Debug>::fmt as for<'r, 's, 't0> fn(&'r std::vec::Vec<std::string::String>, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +105:5-115:7: @37.Call: _120 = ArgumentV1::new::<Vec<String>>(move _121, move _122) -> [return: bb38, unwind: bb43] +105:5-115:7: @38[2]: _111 = [move _120] +105:5-115:7: @38[5]: _110 = &_111 +105:5-115:7: @38[6]: _109 = &(*_110) +105:5-115:7: @38[7]: _108 = move _109 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +105:5-115:7: @38.Call: _103 = Arguments::new_v1(move _104, move _108) -> [return: bb39, unwind: bb43] +105:5-115:7: @39.Call: _102 = _print(move _103) -> [return: bb40, unwind: bb43] +105:5-115:7: @41[6]: _101 = const () +118:9-118:24: @41[13]: FakeRead(ForLet, _123) +3:11-155:2: @41[38]: _0 = const ()"> ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| mut countdown | { @@ -7149,3773 +7149,3773 @@ countdown = 10; } "closure should be unused".to_owned() - } }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37⦊; -@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; + - + let mut countdown = 10; - let mut countdown = 10; + let _short_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37| _unused_arg: u8 | countdown += 1 let _short_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| _unused_arg: u8 | countdown += 1@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37⦊; -@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; + - + // Macros can sometimes confuse the coverage results. Compare this next assignment, with an - // Macros can sometimes confuse the coverage results. Compare this next assignment, with an + // unused closure that invokes the `println!()` macro, with the closure assignment above, that - // unused closure that invokes the `println!()` macro, with the closure assignment above, that + // does not use a macro. The closure above correctly shows `0` executions. - // does not use a macro. The closure above correctly shows `0` executions. + let _short_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37| _unused_arg: u8 | println!("not called") let _short_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| _unused_arg: u8 | println!("not called")@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37⦊; -@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; + // The closure assignment above is executed, with a line count of `1`, but the `println!()` - // The closure assignment above is executed, with a line count of `1`, but the `println!()` + // could not have been called, and yet, there is no indication that it wasn't... - // could not have been called, and yet, there is no indication that it wasn't... + - + // ...but adding block braces gives the expected result, showing the block was not executed. - // ...but adding block braces gives the expected result, showing the block was not executed. + let _short_unused_closure_block = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37| _unused_arg: u8 | { println!("not called") } let _short_unused_closure_block = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| _unused_arg: u8 | { println!("not called") }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37⦊; -@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; + - + let _shortish_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37| _unused_arg: u8 | { +10:9-10:24: @5[1]: FakeRead(ForLet, _7) +12:9-12:32: @5[8]: _137 = const main::promoted[4] +12:9-12:32: @5[9]: _14 = &(*_137) +12:9-12:32: @5[10]: _13 = &(*_14) +12:9-12:32: @5[11]: _12 = move _13 as &[&str] (Pointer(Unsize)) +14:9-14:20: @5[21]: _23 = move _7 +14:9-26:10: @5.Call: _22 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:18:13: 25:14]>(move _23, move _24) -> [return: bb6, unwind: bb54] +14:9-26:10: @6[2]: _21 = &_22 +11:5-27:7: @6[3]: _20 = (move _21,) +11:5-27:7: @6[5]: FakeRead(ForMatchedPlace, _20) +11:5-27:7: @6[7]: _26 = (_20.0: &std::string::String) +11:5-27:7: @6[10]: _28 = &(*_26) +11:5-27:7: @6[12]: _29 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +11:5-27:7: @6.Call: _27 = ArgumentV1::new::<String>(move _28, move _29) -> [return: bb7, unwind: bb53] +11:5-27:7: @7[2]: _19 = [move _27] +11:5-27:7: @7[5]: _18 = &_19 +11:5-27:7: @7[6]: _17 = &(*_18) +11:5-27:7: @7[7]: _16 = move _17 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +11:5-27:7: @7.Call: _11 = Arguments::new_v1(move _12, move _16) -> [return: bb8, unwind: bb53] +11:5-27:7: @8.Call: _10 = _print(move _11) -> [return: bb9, unwind: bb53] +11:5-27:7: @10[6]: _9 = const () +29:24-29:58: @10.Call: _31 = <String as From<&str>>::from(const "the string content") -> [return: bb11, unwind: bb55] +29:19-29:59: @11[0]: _30 = Option::<String>::Some(move _31) +33:9-40:6: @14[3]: _33 = &_5 +31:9-31:10: @14[6]: FakeRead(ForLet, _32) +42:9-42:32: @14[13]: _136 = const main::promoted[3] +42:9-42:32: @14[14]: _39 = &(*_136) +42:9-42:32: @14[15]: _38 = &(*_39) +42:9-42:32: @14[16]: _37 = move _38 as &[&str] (Pointer(Unsize)) +44:9-44:20: @14[26]: _48 = move _7 +48:13-48:14: @14[28]: _49 = _32 +44:9-49:10: @14.Call: _47 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:33:9: 40:6]>(move _48, move _49) -> [return: bb15, unwind: bb51] +44:9-49:10: @15[2]: _46 = &_47 +41:5-50:7: @15[3]: _45 = (move _46,) +41:5-50:7: @15[5]: FakeRead(ForMatchedPlace, _45) +41:5-50:7: @15[7]: _50 = (_45.0: &std::string::String) +41:5-50:7: @15[10]: _52 = &(*_50) +41:5-50:7: @15[12]: _53 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +41:5-50:7: @15.Call: _51 = ArgumentV1::new::<String>(move _52, move _53) -> [return: bb16, unwind: bb50] +41:5-50:7: @16[2]: _44 = [move _51] +41:5-50:7: @16[5]: _43 = &_44 +41:5-50:7: @16[6]: _42 = &(*_43) +41:5-50:7: @16[7]: _41 = move _42 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +41:5-50:7: @16.Call: _36 = Arguments::new_v1(move _37, move _41) -> [return: bb17, unwind: bb50] +41:5-50:7: @17.Call: _35 = _print(move _36) -> [return: bb18, unwind: bb50] +41:5-50:7: @19[6]: _34 = const () +52:19-52:23: @19[9]: _54 = Option::<String>::None +54:9-54:32: @21[7]: _135 = const main::promoted[2] +54:9-54:32: @21[8]: _60 = &(*_135) +54:9-54:32: @21[9]: _59 = &(*_60) +54:9-54:32: @21[10]: _58 = move _59 as &[&str] (Pointer(Unsize)) +56:9-56:20: @21[20]: _69 = move _7 +56:9-68:10: @21.Call: _68 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:60:13: 67:14]>(move _69, move _70) -> [return: bb22, unwind: bb48] +56:9-68:10: @22[2]: _67 = &_68 +53:5-69:7: @22[3]: _66 = (move _67,) +53:5-69:7: @22[5]: FakeRead(ForMatchedPlace, _66) +53:5-69:7: @22[7]: _72 = (_66.0: &std::string::String) +53:5-69:7: @22[10]: _74 = &(*_72) +53:5-69:7: @22[12]: _75 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +53:5-69:7: @22.Call: _73 = ArgumentV1::new::<String>(move _74, move _75) -> [return: bb23, unwind: bb47] +53:5-69:7: @23[2]: _65 = [move _73] +53:5-69:7: @23[5]: _64 = &_65 +53:5-69:7: @23[6]: _63 = &(*_64) +53:5-69:7: @23[7]: _62 = move _63 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +53:5-69:7: @23.Call: _57 = Arguments::new_v1(move _58, move _62) -> [return: bb24, unwind: bb47] +53:5-69:7: @24.Call: _56 = _print(move _57) -> [return: bb25, unwind: bb47] +53:5-69:7: @26[6]: _55 = const () +71:19-71:23: @26[9]: _76 = Option::<String>::None +75:9-82:6: @28[3]: _78 = &_5 +73:9-73:10: @28[6]: FakeRead(ForLet, _77) +84:9-84:32: @28[13]: _134 = const main::promoted[1] +84:9-84:32: @28[14]: _84 = &(*_134) +84:9-84:32: @28[15]: _83 = &(*_84) +84:9-84:32: @28[16]: _82 = move _83 as &[&str] (Pointer(Unsize)) +86:9-86:20: @28[26]: _93 = move _7 +90:13-90:14: @28[28]: _94 = _77 +86:9-91:10: @28.Call: _92 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:75:9: 82:6]>(move _93, move _94) -> [return: bb29, unwind: bb45] +86:9-91:10: @29[2]: _91 = &_92 +83:5-92:7: @29[3]: _90 = (move _91,) +83:5-92:7: @29[5]: FakeRead(ForMatchedPlace, _90) +83:5-92:7: @29[7]: _95 = (_90.0: &std::string::String) +83:5-92:7: @29[10]: _97 = &(*_95) +83:5-92:7: @29[12]: _98 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +83:5-92:7: @29.Call: _96 = ArgumentV1::new::<String>(move _97, move _98) -> [return: bb30, unwind: bb44] +83:5-92:7: @30[2]: _89 = [move _96] +83:5-92:7: @30[5]: _88 = &_89 +83:5-92:7: @30[6]: _87 = &(*_88) +83:5-92:7: @30[7]: _86 = move _87 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +83:5-92:7: @30.Call: _81 = Arguments::new_v1(move _82, move _86) -> [return: bb31, unwind: bb44] +83:5-92:7: @31.Call: _80 = _print(move _81) -> [return: bb32, unwind: bb44] +83:5-92:7: @33[6]: _79 = const () +97:9-104:6: @33[10]: _100 = &_5 +95:9-95:22: @33[13]: FakeRead(ForLet, _99) +106:9-106:40: @33[20]: _133 = const main::promoted[0] +106:9-106:40: @33[21]: _106 = &(*_133) +106:9-106:40: @33[22]: _105 = &(*_106) +106:9-106:40: @33[23]: _104 = move _105 as &[&str] (Pointer(Unsize)) +108:9-108:39: @33.Call: _117 = std::iter::repeat::<&str>(const "repeat me") -> [return: bb34, unwind: bb55] +108:9-109:21: @34.Call: _116 = <std::iter::Repeat<&str> as Iterator>::take(move _117, const 5_usize) -> [return: bb35, unwind: bb55] +112:13-112:26: @35[2]: _118 = _99 +108:9-113:10: @35.Call: _115 = <std::iter::Take<std::iter::Repeat<&str>> as Iterator>::map::<String, [closure@../coverage/closure.rs:97:9: 104:6]>(move _116, move _118) -> [return: bb36, unwind: bb55] +108:9-114:33: @36.Call: _114 = <Map<std::iter::Take<std::iter::Repeat<&str>>, [closure@../coverage/closure.rs:97:9: 104:6]> as Iterator>::collect::<Vec<String>>(move _115) -> [return: bb37, unwind: bb55] +108:9-114:33: @37[1]: _113 = &_114 +105:5-115:7: @37[2]: _112 = (move _113,) +105:5-115:7: @37[4]: FakeRead(ForMatchedPlace, _112) +105:5-115:7: @37[6]: _119 = (_112.0: &std::vec::Vec<std::string::String>) +105:5-115:7: @37[9]: _121 = &(*_119) +105:5-115:7: @37[11]: _122 = <Vec<String> as Debug>::fmt as for<'r, 's, 't0> fn(&'r std::vec::Vec<std::string::String>, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +105:5-115:7: @37.Call: _120 = ArgumentV1::new::<Vec<String>>(move _121, move _122) -> [return: bb38, unwind: bb43] +105:5-115:7: @38[2]: _111 = [move _120] +105:5-115:7: @38[5]: _110 = &_111 +105:5-115:7: @38[6]: _109 = &(*_110) +105:5-115:7: @38[7]: _108 = move _109 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +105:5-115:7: @38.Call: _103 = Arguments::new_v1(move _104, move _108) -> [return: bb39, unwind: bb43] +105:5-115:7: @39.Call: _102 = _print(move _103) -> [return: bb40, unwind: bb43] +105:5-115:7: @41[6]: _101 = const () +118:9-118:24: @41[13]: FakeRead(ForLet, _123) +130:25-130:27: @41[15]: _125 = const 10_i32 +130:9-130:22: @41[16]: FakeRead(ForLet, _125) +131:33-131:67: @41[19]: _127 = &mut _125 +131:9-131:30: @41[22]: FakeRead(ForLet, _126) +136:9-136:30: @41[25]: FakeRead(ForLet, _128) +141:9-141:36: @41[28]: FakeRead(ForLet, _129) +143:9-143:33: @41[31]: FakeRead(ForLet, _130) +3:11-155:2: @41[38]: _0 = const ()"> let _shortish_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| _unused_arg: u8 | { println!("not called") - } }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37⦊; -@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; + - + let _as_short_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37| +10:9-10:24: @5[1]: FakeRead(ForLet, _7) +12:9-12:32: @5[8]: _137 = const main::promoted[4] +12:9-12:32: @5[9]: _14 = &(*_137) +12:9-12:32: @5[10]: _13 = &(*_14) +12:9-12:32: @5[11]: _12 = move _13 as &[&str] (Pointer(Unsize)) +14:9-14:20: @5[21]: _23 = move _7 +14:9-26:10: @5.Call: _22 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:18:13: 25:14]>(move _23, move _24) -> [return: bb6, unwind: bb54] +14:9-26:10: @6[2]: _21 = &_22 +11:5-27:7: @6[3]: _20 = (move _21,) +11:5-27:7: @6[5]: FakeRead(ForMatchedPlace, _20) +11:5-27:7: @6[7]: _26 = (_20.0: &std::string::String) +11:5-27:7: @6[10]: _28 = &(*_26) +11:5-27:7: @6[12]: _29 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +11:5-27:7: @6.Call: _27 = ArgumentV1::new::<String>(move _28, move _29) -> [return: bb7, unwind: bb53] +11:5-27:7: @7[2]: _19 = [move _27] +11:5-27:7: @7[5]: _18 = &_19 +11:5-27:7: @7[6]: _17 = &(*_18) +11:5-27:7: @7[7]: _16 = move _17 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +11:5-27:7: @7.Call: _11 = Arguments::new_v1(move _12, move _16) -> [return: bb8, unwind: bb53] +11:5-27:7: @8.Call: _10 = _print(move _11) -> [return: bb9, unwind: bb53] +11:5-27:7: @10[6]: _9 = const () +29:24-29:58: @10.Call: _31 = <String as From<&str>>::from(const "the string content") -> [return: bb11, unwind: bb55] +29:19-29:59: @11[0]: _30 = Option::<String>::Some(move _31) +33:9-40:6: @14[3]: _33 = &_5 +31:9-31:10: @14[6]: FakeRead(ForLet, _32) +42:9-42:32: @14[13]: _136 = const main::promoted[3] +42:9-42:32: @14[14]: _39 = &(*_136) +42:9-42:32: @14[15]: _38 = &(*_39) +42:9-42:32: @14[16]: _37 = move _38 as &[&str] (Pointer(Unsize)) +44:9-44:20: @14[26]: _48 = move _7 +48:13-48:14: @14[28]: _49 = _32 +44:9-49:10: @14.Call: _47 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:33:9: 40:6]>(move _48, move _49) -> [return: bb15, unwind: bb51] +44:9-49:10: @15[2]: _46 = &_47 +41:5-50:7: @15[3]: _45 = (move _46,) +41:5-50:7: @15[5]: FakeRead(ForMatchedPlace, _45) +41:5-50:7: @15[7]: _50 = (_45.0: &std::string::String) +41:5-50:7: @15[10]: _52 = &(*_50) +41:5-50:7: @15[12]: _53 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +41:5-50:7: @15.Call: _51 = ArgumentV1::new::<String>(move _52, move _53) -> [return: bb16, unwind: bb50] +41:5-50:7: @16[2]: _44 = [move _51] +41:5-50:7: @16[5]: _43 = &_44 +41:5-50:7: @16[6]: _42 = &(*_43) +41:5-50:7: @16[7]: _41 = move _42 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +41:5-50:7: @16.Call: _36 = Arguments::new_v1(move _37, move _41) -> [return: bb17, unwind: bb50] +41:5-50:7: @17.Call: _35 = _print(move _36) -> [return: bb18, unwind: bb50] +41:5-50:7: @19[6]: _34 = const () +52:19-52:23: @19[9]: _54 = Option::<String>::None +54:9-54:32: @21[7]: _135 = const main::promoted[2] +54:9-54:32: @21[8]: _60 = &(*_135) +54:9-54:32: @21[9]: _59 = &(*_60) +54:9-54:32: @21[10]: _58 = move _59 as &[&str] (Pointer(Unsize)) +56:9-56:20: @21[20]: _69 = move _7 +56:9-68:10: @21.Call: _68 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:60:13: 67:14]>(move _69, move _70) -> [return: bb22, unwind: bb48] +56:9-68:10: @22[2]: _67 = &_68 +53:5-69:7: @22[3]: _66 = (move _67,) +53:5-69:7: @22[5]: FakeRead(ForMatchedPlace, _66) +53:5-69:7: @22[7]: _72 = (_66.0: &std::string::String) +53:5-69:7: @22[10]: _74 = &(*_72) +53:5-69:7: @22[12]: _75 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +53:5-69:7: @22.Call: _73 = ArgumentV1::new::<String>(move _74, move _75) -> [return: bb23, unwind: bb47] +53:5-69:7: @23[2]: _65 = [move _73] +53:5-69:7: @23[5]: _64 = &_65 +53:5-69:7: @23[6]: _63 = &(*_64) +53:5-69:7: @23[7]: _62 = move _63 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +53:5-69:7: @23.Call: _57 = Arguments::new_v1(move _58, move _62) -> [return: bb24, unwind: bb47] +53:5-69:7: @24.Call: _56 = _print(move _57) -> [return: bb25, unwind: bb47] +53:5-69:7: @26[6]: _55 = const () +71:19-71:23: @26[9]: _76 = Option::<String>::None +75:9-82:6: @28[3]: _78 = &_5 +73:9-73:10: @28[6]: FakeRead(ForLet, _77) +84:9-84:32: @28[13]: _134 = const main::promoted[1] +84:9-84:32: @28[14]: _84 = &(*_134) +84:9-84:32: @28[15]: _83 = &(*_84) +84:9-84:32: @28[16]: _82 = move _83 as &[&str] (Pointer(Unsize)) +86:9-86:20: @28[26]: _93 = move _7 +90:13-90:14: @28[28]: _94 = _77 +86:9-91:10: @28.Call: _92 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:75:9: 82:6]>(move _93, move _94) -> [return: bb29, unwind: bb45] +86:9-91:10: @29[2]: _91 = &_92 +83:5-92:7: @29[3]: _90 = (move _91,) +83:5-92:7: @29[5]: FakeRead(ForMatchedPlace, _90) +83:5-92:7: @29[7]: _95 = (_90.0: &std::string::String) +83:5-92:7: @29[10]: _97 = &(*_95) +83:5-92:7: @29[12]: _98 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +83:5-92:7: @29.Call: _96 = ArgumentV1::new::<String>(move _97, move _98) -> [return: bb30, unwind: bb44] +83:5-92:7: @30[2]: _89 = [move _96] +83:5-92:7: @30[5]: _88 = &_89 +83:5-92:7: @30[6]: _87 = &(*_88) +83:5-92:7: @30[7]: _86 = move _87 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +83:5-92:7: @30.Call: _81 = Arguments::new_v1(move _82, move _86) -> [return: bb31, unwind: bb44] +83:5-92:7: @31.Call: _80 = _print(move _81) -> [return: bb32, unwind: bb44] +83:5-92:7: @33[6]: _79 = const () +97:9-104:6: @33[10]: _100 = &_5 +95:9-95:22: @33[13]: FakeRead(ForLet, _99) +106:9-106:40: @33[20]: _133 = const main::promoted[0] +106:9-106:40: @33[21]: _106 = &(*_133) +106:9-106:40: @33[22]: _105 = &(*_106) +106:9-106:40: @33[23]: _104 = move _105 as &[&str] (Pointer(Unsize)) +108:9-108:39: @33.Call: _117 = std::iter::repeat::<&str>(const "repeat me") -> [return: bb34, unwind: bb55] +108:9-109:21: @34.Call: _116 = <std::iter::Repeat<&str> as Iterator>::take(move _117, const 5_usize) -> [return: bb35, unwind: bb55] +112:13-112:26: @35[2]: _118 = _99 +108:9-113:10: @35.Call: _115 = <std::iter::Take<std::iter::Repeat<&str>> as Iterator>::map::<String, [closure@../coverage/closure.rs:97:9: 104:6]>(move _116, move _118) -> [return: bb36, unwind: bb55] +108:9-114:33: @36.Call: _114 = <Map<std::iter::Take<std::iter::Repeat<&str>>, [closure@../coverage/closure.rs:97:9: 104:6]> as Iterator>::collect::<Vec<String>>(move _115) -> [return: bb37, unwind: bb55] +108:9-114:33: @37[1]: _113 = &_114 +105:5-115:7: @37[2]: _112 = (move _113,) +105:5-115:7: @37[4]: FakeRead(ForMatchedPlace, _112) +105:5-115:7: @37[6]: _119 = (_112.0: &std::vec::Vec<std::string::String>) +105:5-115:7: @37[9]: _121 = &(*_119) +105:5-115:7: @37[11]: _122 = <Vec<String> as Debug>::fmt as for<'r, 's, 't0> fn(&'r std::vec::Vec<std::string::String>, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +105:5-115:7: @37.Call: _120 = ArgumentV1::new::<Vec<String>>(move _121, move _122) -> [return: bb38, unwind: bb43] +105:5-115:7: @38[2]: _111 = [move _120] +105:5-115:7: @38[5]: _110 = &_111 +105:5-115:7: @38[6]: _109 = &(*_110) +105:5-115:7: @38[7]: _108 = move _109 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +105:5-115:7: @38.Call: _103 = Arguments::new_v1(move _104, move _108) -> [return: bb39, unwind: bb43] +105:5-115:7: @39.Call: _102 = _print(move _103) -> [return: bb40, unwind: bb43] +105:5-115:7: @41[6]: _101 = const () +118:9-118:24: @41[13]: FakeRead(ForLet, _123) +130:25-130:27: @41[15]: _125 = const 10_i32 +130:9-130:22: @41[16]: FakeRead(ForLet, _125) +131:33-131:67: @41[19]: _127 = &mut _125 +131:9-131:30: @41[22]: FakeRead(ForLet, _126) +136:9-136:30: @41[25]: FakeRead(ForLet, _128) +141:9-141:36: @41[28]: FakeRead(ForLet, _129) +143:9-143:33: @41[31]: FakeRead(ForLet, _130) +147:9-147:33: @41[34]: FakeRead(ForLet, _131) +3:11-155:2: @41[38]: _0 = const ()"> let _as_short_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| _unused_arg: u8 - | { println!("not called") } | { println!("not called") }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37⦊; -@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; + - + let _almost_as_short_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37| +10:9-10:24: @5[1]: FakeRead(ForLet, _7) +12:9-12:32: @5[8]: _137 = const main::promoted[4] +12:9-12:32: @5[9]: _14 = &(*_137) +12:9-12:32: @5[10]: _13 = &(*_14) +12:9-12:32: @5[11]: _12 = move _13 as &[&str] (Pointer(Unsize)) +14:9-14:20: @5[21]: _23 = move _7 +14:9-26:10: @5.Call: _22 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:18:13: 25:14]>(move _23, move _24) -> [return: bb6, unwind: bb54] +14:9-26:10: @6[2]: _21 = &_22 +11:5-27:7: @6[3]: _20 = (move _21,) +11:5-27:7: @6[5]: FakeRead(ForMatchedPlace, _20) +11:5-27:7: @6[7]: _26 = (_20.0: &std::string::String) +11:5-27:7: @6[10]: _28 = &(*_26) +11:5-27:7: @6[12]: _29 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +11:5-27:7: @6.Call: _27 = ArgumentV1::new::<String>(move _28, move _29) -> [return: bb7, unwind: bb53] +11:5-27:7: @7[2]: _19 = [move _27] +11:5-27:7: @7[5]: _18 = &_19 +11:5-27:7: @7[6]: _17 = &(*_18) +11:5-27:7: @7[7]: _16 = move _17 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +11:5-27:7: @7.Call: _11 = Arguments::new_v1(move _12, move _16) -> [return: bb8, unwind: bb53] +11:5-27:7: @8.Call: _10 = _print(move _11) -> [return: bb9, unwind: bb53] +11:5-27:7: @10[6]: _9 = const () +29:24-29:58: @10.Call: _31 = <String as From<&str>>::from(const "the string content") -> [return: bb11, unwind: bb55] +29:19-29:59: @11[0]: _30 = Option::<String>::Some(move _31) +33:9-40:6: @14[3]: _33 = &_5 +31:9-31:10: @14[6]: FakeRead(ForLet, _32) +42:9-42:32: @14[13]: _136 = const main::promoted[3] +42:9-42:32: @14[14]: _39 = &(*_136) +42:9-42:32: @14[15]: _38 = &(*_39) +42:9-42:32: @14[16]: _37 = move _38 as &[&str] (Pointer(Unsize)) +44:9-44:20: @14[26]: _48 = move _7 +48:13-48:14: @14[28]: _49 = _32 +44:9-49:10: @14.Call: _47 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:33:9: 40:6]>(move _48, move _49) -> [return: bb15, unwind: bb51] +44:9-49:10: @15[2]: _46 = &_47 +41:5-50:7: @15[3]: _45 = (move _46,) +41:5-50:7: @15[5]: FakeRead(ForMatchedPlace, _45) +41:5-50:7: @15[7]: _50 = (_45.0: &std::string::String) +41:5-50:7: @15[10]: _52 = &(*_50) +41:5-50:7: @15[12]: _53 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +41:5-50:7: @15.Call: _51 = ArgumentV1::new::<String>(move _52, move _53) -> [return: bb16, unwind: bb50] +41:5-50:7: @16[2]: _44 = [move _51] +41:5-50:7: @16[5]: _43 = &_44 +41:5-50:7: @16[6]: _42 = &(*_43) +41:5-50:7: @16[7]: _41 = move _42 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +41:5-50:7: @16.Call: _36 = Arguments::new_v1(move _37, move _41) -> [return: bb17, unwind: bb50] +41:5-50:7: @17.Call: _35 = _print(move _36) -> [return: bb18, unwind: bb50] +41:5-50:7: @19[6]: _34 = const () +52:19-52:23: @19[9]: _54 = Option::<String>::None +54:9-54:32: @21[7]: _135 = const main::promoted[2] +54:9-54:32: @21[8]: _60 = &(*_135) +54:9-54:32: @21[9]: _59 = &(*_60) +54:9-54:32: @21[10]: _58 = move _59 as &[&str] (Pointer(Unsize)) +56:9-56:20: @21[20]: _69 = move _7 +56:9-68:10: @21.Call: _68 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:60:13: 67:14]>(move _69, move _70) -> [return: bb22, unwind: bb48] +56:9-68:10: @22[2]: _67 = &_68 +53:5-69:7: @22[3]: _66 = (move _67,) +53:5-69:7: @22[5]: FakeRead(ForMatchedPlace, _66) +53:5-69:7: @22[7]: _72 = (_66.0: &std::string::String) +53:5-69:7: @22[10]: _74 = &(*_72) +53:5-69:7: @22[12]: _75 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +53:5-69:7: @22.Call: _73 = ArgumentV1::new::<String>(move _74, move _75) -> [return: bb23, unwind: bb47] +53:5-69:7: @23[2]: _65 = [move _73] +53:5-69:7: @23[5]: _64 = &_65 +53:5-69:7: @23[6]: _63 = &(*_64) +53:5-69:7: @23[7]: _62 = move _63 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +53:5-69:7: @23.Call: _57 = Arguments::new_v1(move _58, move _62) -> [return: bb24, unwind: bb47] +53:5-69:7: @24.Call: _56 = _print(move _57) -> [return: bb25, unwind: bb47] +53:5-69:7: @26[6]: _55 = const () +71:19-71:23: @26[9]: _76 = Option::<String>::None +75:9-82:6: @28[3]: _78 = &_5 +73:9-73:10: @28[6]: FakeRead(ForLet, _77) +84:9-84:32: @28[13]: _134 = const main::promoted[1] +84:9-84:32: @28[14]: _84 = &(*_134) +84:9-84:32: @28[15]: _83 = &(*_84) +84:9-84:32: @28[16]: _82 = move _83 as &[&str] (Pointer(Unsize)) +86:9-86:20: @28[26]: _93 = move _7 +90:13-90:14: @28[28]: _94 = _77 +86:9-91:10: @28.Call: _92 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:75:9: 82:6]>(move _93, move _94) -> [return: bb29, unwind: bb45] +86:9-91:10: @29[2]: _91 = &_92 +83:5-92:7: @29[3]: _90 = (move _91,) +83:5-92:7: @29[5]: FakeRead(ForMatchedPlace, _90) +83:5-92:7: @29[7]: _95 = (_90.0: &std::string::String) +83:5-92:7: @29[10]: _97 = &(*_95) +83:5-92:7: @29[12]: _98 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +83:5-92:7: @29.Call: _96 = ArgumentV1::new::<String>(move _97, move _98) -> [return: bb30, unwind: bb44] +83:5-92:7: @30[2]: _89 = [move _96] +83:5-92:7: @30[5]: _88 = &_89 +83:5-92:7: @30[6]: _87 = &(*_88) +83:5-92:7: @30[7]: _86 = move _87 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +83:5-92:7: @30.Call: _81 = Arguments::new_v1(move _82, move _86) -> [return: bb31, unwind: bb44] +83:5-92:7: @31.Call: _80 = _print(move _81) -> [return: bb32, unwind: bb44] +83:5-92:7: @33[6]: _79 = const () +97:9-104:6: @33[10]: _100 = &_5 +95:9-95:22: @33[13]: FakeRead(ForLet, _99) +106:9-106:40: @33[20]: _133 = const main::promoted[0] +106:9-106:40: @33[21]: _106 = &(*_133) +106:9-106:40: @33[22]: _105 = &(*_106) +106:9-106:40: @33[23]: _104 = move _105 as &[&str] (Pointer(Unsize)) +108:9-108:39: @33.Call: _117 = std::iter::repeat::<&str>(const "repeat me") -> [return: bb34, unwind: bb55] +108:9-109:21: @34.Call: _116 = <std::iter::Repeat<&str> as Iterator>::take(move _117, const 5_usize) -> [return: bb35, unwind: bb55] +112:13-112:26: @35[2]: _118 = _99 +108:9-113:10: @35.Call: _115 = <std::iter::Take<std::iter::Repeat<&str>> as Iterator>::map::<String, [closure@../coverage/closure.rs:97:9: 104:6]>(move _116, move _118) -> [return: bb36, unwind: bb55] +108:9-114:33: @36.Call: _114 = <Map<std::iter::Take<std::iter::Repeat<&str>>, [closure@../coverage/closure.rs:97:9: 104:6]> as Iterator>::collect::<Vec<String>>(move _115) -> [return: bb37, unwind: bb55] +108:9-114:33: @37[1]: _113 = &_114 +105:5-115:7: @37[2]: _112 = (move _113,) +105:5-115:7: @37[4]: FakeRead(ForMatchedPlace, _112) +105:5-115:7: @37[6]: _119 = (_112.0: &std::vec::Vec<std::string::String>) +105:5-115:7: @37[9]: _121 = &(*_119) +105:5-115:7: @37[11]: _122 = <Vec<String> as Debug>::fmt as for<'r, 's, 't0> fn(&'r std::vec::Vec<std::string::String>, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +105:5-115:7: @37.Call: _120 = ArgumentV1::new::<Vec<String>>(move _121, move _122) -> [return: bb38, unwind: bb43] +105:5-115:7: @38[2]: _111 = [move _120] +105:5-115:7: @38[5]: _110 = &_111 +105:5-115:7: @38[6]: _109 = &(*_110) +105:5-115:7: @38[7]: _108 = move _109 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +105:5-115:7: @38.Call: _103 = Arguments::new_v1(move _104, move _108) -> [return: bb39, unwind: bb43] +105:5-115:7: @39.Call: _102 = _print(move _103) -> [return: bb40, unwind: bb43] +105:5-115:7: @41[6]: _101 = const () +118:9-118:24: @41[13]: FakeRead(ForLet, _123) +130:25-130:27: @41[15]: _125 = const 10_i32 +130:9-130:22: @41[16]: FakeRead(ForLet, _125) +131:33-131:67: @41[19]: _127 = &mut _125 +131:9-131:30: @41[22]: FakeRead(ForLet, _126) +136:9-136:30: @41[25]: FakeRead(ForLet, _128) +141:9-141:36: @41[28]: FakeRead(ForLet, _129) +143:9-143:33: @41[31]: FakeRead(ForLet, _130) +147:9-147:33: @41[34]: FakeRead(ForLet, _131) +151:9-151:40: @41[37]: FakeRead(ForLet, _132) +3:11-155:2: @41[38]: _0 = const ()"> let _almost_as_short_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| _unused_arg: u8 - | { println!("not called") } | { println!("not called") }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37⦊ -@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊ + ; - ; +}⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37
+10:9-10:24: @5[1]: FakeRead(ForLet, _7) +12:9-12:32: @5[8]: _137 = const main::promoted[4] +12:9-12:32: @5[9]: _14 = &(*_137) +12:9-12:32: @5[10]: _13 = &(*_14) +12:9-12:32: @5[11]: _12 = move _13 as &[&str] (Pointer(Unsize)) +14:9-14:20: @5[21]: _23 = move _7 +14:9-26:10: @5.Call: _22 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:18:13: 25:14]>(move _23, move _24) -> [return: bb6, unwind: bb54] +14:9-26:10: @6[2]: _21 = &_22 +11:5-27:7: @6[3]: _20 = (move _21,) +11:5-27:7: @6[5]: FakeRead(ForMatchedPlace, _20) +11:5-27:7: @6[7]: _26 = (_20.0: &std::string::String) +11:5-27:7: @6[10]: _28 = &(*_26) +11:5-27:7: @6[12]: _29 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +11:5-27:7: @6.Call: _27 = ArgumentV1::new::<String>(move _28, move _29) -> [return: bb7, unwind: bb53] +11:5-27:7: @7[2]: _19 = [move _27] +11:5-27:7: @7[5]: _18 = &_19 +11:5-27:7: @7[6]: _17 = &(*_18) +11:5-27:7: @7[7]: _16 = move _17 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +11:5-27:7: @7.Call: _11 = Arguments::new_v1(move _12, move _16) -> [return: bb8, unwind: bb53] +11:5-27:7: @8.Call: _10 = _print(move _11) -> [return: bb9, unwind: bb53] +11:5-27:7: @10[6]: _9 = const () +29:24-29:58: @10.Call: _31 = <String as From<&str>>::from(const "the string content") -> [return: bb11, unwind: bb55] +29:19-29:59: @11[0]: _30 = Option::<String>::Some(move _31) +33:9-40:6: @14[3]: _33 = &_5 +31:9-31:10: @14[6]: FakeRead(ForLet, _32) +42:9-42:32: @14[13]: _136 = const main::promoted[3] +42:9-42:32: @14[14]: _39 = &(*_136) +42:9-42:32: @14[15]: _38 = &(*_39) +42:9-42:32: @14[16]: _37 = move _38 as &[&str] (Pointer(Unsize)) +44:9-44:20: @14[26]: _48 = move _7 +48:13-48:14: @14[28]: _49 = _32 +44:9-49:10: @14.Call: _47 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:33:9: 40:6]>(move _48, move _49) -> [return: bb15, unwind: bb51] +44:9-49:10: @15[2]: _46 = &_47 +41:5-50:7: @15[3]: _45 = (move _46,) +41:5-50:7: @15[5]: FakeRead(ForMatchedPlace, _45) +41:5-50:7: @15[7]: _50 = (_45.0: &std::string::String) +41:5-50:7: @15[10]: _52 = &(*_50) +41:5-50:7: @15[12]: _53 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +41:5-50:7: @15.Call: _51 = ArgumentV1::new::<String>(move _52, move _53) -> [return: bb16, unwind: bb50] +41:5-50:7: @16[2]: _44 = [move _51] +41:5-50:7: @16[5]: _43 = &_44 +41:5-50:7: @16[6]: _42 = &(*_43) +41:5-50:7: @16[7]: _41 = move _42 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +41:5-50:7: @16.Call: _36 = Arguments::new_v1(move _37, move _41) -> [return: bb17, unwind: bb50] +41:5-50:7: @17.Call: _35 = _print(move _36) -> [return: bb18, unwind: bb50] +41:5-50:7: @19[6]: _34 = const () +52:19-52:23: @19[9]: _54 = Option::<String>::None +54:9-54:32: @21[7]: _135 = const main::promoted[2] +54:9-54:32: @21[8]: _60 = &(*_135) +54:9-54:32: @21[9]: _59 = &(*_60) +54:9-54:32: @21[10]: _58 = move _59 as &[&str] (Pointer(Unsize)) +56:9-56:20: @21[20]: _69 = move _7 +56:9-68:10: @21.Call: _68 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:60:13: 67:14]>(move _69, move _70) -> [return: bb22, unwind: bb48] +56:9-68:10: @22[2]: _67 = &_68 +53:5-69:7: @22[3]: _66 = (move _67,) +53:5-69:7: @22[5]: FakeRead(ForMatchedPlace, _66) +53:5-69:7: @22[7]: _72 = (_66.0: &std::string::String) +53:5-69:7: @22[10]: _74 = &(*_72) +53:5-69:7: @22[12]: _75 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +53:5-69:7: @22.Call: _73 = ArgumentV1::new::<String>(move _74, move _75) -> [return: bb23, unwind: bb47] +53:5-69:7: @23[2]: _65 = [move _73] +53:5-69:7: @23[5]: _64 = &_65 +53:5-69:7: @23[6]: _63 = &(*_64) +53:5-69:7: @23[7]: _62 = move _63 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +53:5-69:7: @23.Call: _57 = Arguments::new_v1(move _58, move _62) -> [return: bb24, unwind: bb47] +53:5-69:7: @24.Call: _56 = _print(move _57) -> [return: bb25, unwind: bb47] +53:5-69:7: @26[6]: _55 = const () +71:19-71:23: @26[9]: _76 = Option::<String>::None +75:9-82:6: @28[3]: _78 = &_5 +73:9-73:10: @28[6]: FakeRead(ForLet, _77) +84:9-84:32: @28[13]: _134 = const main::promoted[1] +84:9-84:32: @28[14]: _84 = &(*_134) +84:9-84:32: @28[15]: _83 = &(*_84) +84:9-84:32: @28[16]: _82 = move _83 as &[&str] (Pointer(Unsize)) +86:9-86:20: @28[26]: _93 = move _7 +90:13-90:14: @28[28]: _94 = _77 +86:9-91:10: @28.Call: _92 = Option::<String>::unwrap_or_else::<[closure@../coverage/closure.rs:75:9: 82:6]>(move _93, move _94) -> [return: bb29, unwind: bb45] +86:9-91:10: @29[2]: _91 = &_92 +83:5-92:7: @29[3]: _90 = (move _91,) +83:5-92:7: @29[5]: FakeRead(ForMatchedPlace, _90) +83:5-92:7: @29[7]: _95 = (_90.0: &std::string::String) +83:5-92:7: @29[10]: _97 = &(*_95) +83:5-92:7: @29[12]: _98 = <String as std::fmt::Display>::fmt as for<'r, 's, 't0> fn(&'r std::string::String, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +83:5-92:7: @29.Call: _96 = ArgumentV1::new::<String>(move _97, move _98) -> [return: bb30, unwind: bb44] +83:5-92:7: @30[2]: _89 = [move _96] +83:5-92:7: @30[5]: _88 = &_89 +83:5-92:7: @30[6]: _87 = &(*_88) +83:5-92:7: @30[7]: _86 = move _87 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +83:5-92:7: @30.Call: _81 = Arguments::new_v1(move _82, move _86) -> [return: bb31, unwind: bb44] +83:5-92:7: @31.Call: _80 = _print(move _81) -> [return: bb32, unwind: bb44] +83:5-92:7: @33[6]: _79 = const () +97:9-104:6: @33[10]: _100 = &_5 +95:9-95:22: @33[13]: FakeRead(ForLet, _99) +106:9-106:40: @33[20]: _133 = const main::promoted[0] +106:9-106:40: @33[21]: _106 = &(*_133) +106:9-106:40: @33[22]: _105 = &(*_106) +106:9-106:40: @33[23]: _104 = move _105 as &[&str] (Pointer(Unsize)) +108:9-108:39: @33.Call: _117 = std::iter::repeat::<&str>(const "repeat me") -> [return: bb34, unwind: bb55] +108:9-109:21: @34.Call: _116 = <std::iter::Repeat<&str> as Iterator>::take(move _117, const 5_usize) -> [return: bb35, unwind: bb55] +112:13-112:26: @35[2]: _118 = _99 +108:9-113:10: @35.Call: _115 = <std::iter::Take<std::iter::Repeat<&str>> as Iterator>::map::<String, [closure@../coverage/closure.rs:97:9: 104:6]>(move _116, move _118) -> [return: bb36, unwind: bb55] +108:9-114:33: @36.Call: _114 = <Map<std::iter::Take<std::iter::Repeat<&str>>, [closure@../coverage/closure.rs:97:9: 104:6]> as Iterator>::collect::<Vec<String>>(move _115) -> [return: bb37, unwind: bb55] +108:9-114:33: @37[1]: _113 = &_114 +105:5-115:7: @37[2]: _112 = (move _113,) +105:5-115:7: @37[4]: FakeRead(ForMatchedPlace, _112) +105:5-115:7: @37[6]: _119 = (_112.0: &std::vec::Vec<std::string::String>) +105:5-115:7: @37[9]: _121 = &(*_119) +105:5-115:7: @37[11]: _122 = <Vec<String> as Debug>::fmt as for<'r, 's, 't0> fn(&'r std::vec::Vec<std::string::String>, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)) +105:5-115:7: @37.Call: _120 = ArgumentV1::new::<Vec<String>>(move _121, move _122) -> [return: bb38, unwind: bb43] +105:5-115:7: @38[2]: _111 = [move _120] +105:5-115:7: @38[5]: _110 = &_111 +105:5-115:7: @38[6]: _109 = &(*_110) +105:5-115:7: @38[7]: _108 = move _109 as &[std::fmt::ArgumentV1] (Pointer(Unsize)) +105:5-115:7: @38.Call: _103 = Arguments::new_v1(move _104, move _108) -> [return: bb39, unwind: bb43] +105:5-115:7: @39.Call: _102 = _print(move _103) -> [return: bb40, unwind: bb43] +105:5-115:7: @41[6]: _101 = const () +118:9-118:24: @41[13]: FakeRead(ForLet, _123) +130:25-130:27: @41[15]: _125 = const 10_i32 +130:9-130:22: @41[16]: FakeRead(ForLet, _125) +131:33-131:67: @41[19]: _127 = &mut _125 +131:9-131:30: @41[22]: FakeRead(ForLet, _126) +136:9-136:30: @41[25]: FakeRead(ForLet, _128) +141:9-141:36: @41[28]: FakeRead(ForLet, _129) +143:9-143:33: @41[31]: FakeRead(ForLet, _130) +147:9-147:33: @41[34]: FakeRead(ForLet, _131) +151:9-151:40: @41[37]: FakeRead(ForLet, _132) +3:11-155:2: @41[38]: _0 = const () +155:2-155:2: @42.Return: return">}⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.use_this_lib_crate.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.use_this_lib_crate.-------.InstrumentCoverage.0.html index 7c44c536379d2..bed5e7bb7ce88 100644 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.use_this_lib_crate.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.use_this_lib_crate.-------.InstrumentCoverage.0.html @@ -69,122 +69,122 @@ -
@0,1,2,3,4,5,6,7⦊fn use_this_lib_crate() { -@0,1,2,3,4,5,6,7,8⦊fn use_this_lib_crate() { + used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs"); - used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs"); + used_with_same_type_from_bin_crate_and_lib_crate_generic_function( - used_with_same_type_from_bin_crate_and_lib_crate_generic_function( + "used from library used_crate.rs", - "used from library used_crate.rs", + ); - ); + let some_vec = vec![5, 6, 7, 8]; - let some_vec = vec![5, 6, 7, 8]; + used_only_from_this_lib_crate_generic_function(some_vec); - used_only_from_this_lib_crate_generic_function(some_vec); + used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); - used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); +}⦉@0,1,2,3,4,5,6,7
+58:20-58:36: @4.Call: _3 = slice::<impl [i32]>::into_vec::<std::alloc::Global>(move _4) -> [return: bb5, unwind: bb12] +58:9-58:17: @5[1]: FakeRead(ForLet, _3) +59:52-59:60: @5[4]: _8 = move _3 +59:5-59:61: @5.Call: _7 = used_only_from_this_lib_crate_generic_function::<Vec<i32>>(move _8) -> [return: bb6, unwind: bb9] +60:5-60:91: @6.Call: _9 = used_only_from_this_lib_crate_generic_function::<&str>(const "used ONLY from library used_crate.rs") -> [return: bb7, unwind: bb10] +53:25-61:2: @7[1]: _0 = const () +61:2-61:2: @8.Return: return">}⦉@0,1,2,3,4,5,6,7,8 diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.uses_crate/uses_crate.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.uses_crate/uses_crate.main.-------.InstrumentCoverage.0.html index ba6af60fa5cc9..acb2c7d63f51b 100644 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.uses_crate/uses_crate.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.uses_crate/uses_crate.main.-------.InstrumentCoverage.0.html @@ -69,125 +69,125 @@ -
@0,1,2,3,4,5,6,7,8⦊fn main() { -@0,1,2,3,4,5,6,7,8,9⦊fn main() { + used_crate::used_function(); - used_crate::used_function(); + let some_vec = vec![1, 2, 3, 4]; - let some_vec = vec![1, 2, 3, 4]; + used_crate::used_only_from_bin_crate_generic_function(&some_vec); - used_crate::used_only_from_bin_crate_generic_function(&some_vec); + used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs"); - used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs"); + used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec); - used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec); + used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?"); - used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?"); +}⦉@0,1,2,3,4,5,6,7,8
+7:20-7:36: @3.Call: _2 = slice::<impl [i32]>::into_vec::<std::alloc::Global>(move _3) -> [return: bb4, unwind: bb13] +7:9-7:17: @4[1]: FakeRead(ForLet, _2) +8:59-8:68: @4[4]: _7 = &_2 +8:5-8:69: @4.Call: _6 = used_only_from_bin_crate_generic_function::<&Vec<i32>>(move _7) -> [return: bb5, unwind: bb11] +9:5-9:89: @5.Call: _8 = used_only_from_bin_crate_generic_function::<&str>(const "used from bin uses_crate.rs") -> [return: bb6, unwind: bb11] +10:68-10:76: @6[3]: _10 = move _2 +10:5-10:77: @6.Call: _9 = used_from_bin_crate_and_lib_crate_generic_function::<Vec<i32>>(move _10) -> [return: bb7, unwind: bb10] +11:5-11:98: @7.Call: _11 = used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>(const "interesting?") -> [return: bb8, unwind: bb11] +5:11-12:2: @8[1]: _0 = const () +12:2-12:2: @9.Return: return">}⦉@0,1,2,3,4,5,6,7,8,9 diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs index a952fe8e76e81..c4f7c3786168b 100644 --- a/src/test/ui/drop/dynamic-drop-async.rs +++ b/src/test/ui/drop/dynamic-drop-async.rs @@ -43,7 +43,6 @@ impl Future for Defer { /// The `failing_op`-th operation will panic. struct Allocator { data: RefCell>, - name: &'static str, failing_op: usize, cur_ops: Cell, } @@ -55,28 +54,23 @@ impl Drop for Allocator { fn drop(&mut self) { let data = self.data.borrow(); if data.iter().any(|d| *d) { - panic!("missing free in {:?}: {:?}", self.name, data); + panic!("missing free: {:?}", data); } } } impl Allocator { - fn new(failing_op: usize, name: &'static str) -> Self { - Allocator { - failing_op, - name, - cur_ops: Cell::new(0), - data: RefCell::new(vec![]), - } + fn new(failing_op: usize) -> Self { + Allocator { failing_op, cur_ops: Cell::new(0), data: RefCell::new(vec![]) } } - fn alloc(self: &Rc) -> impl Future + 'static { + fn alloc(&self) -> impl Future> + '_ { self.fallible_operation(); let mut data = self.data.borrow_mut(); let addr = data.len(); data.push(true); - Defer { ready: false, value: Some(Ptr(addr, self.clone())) } + Defer { ready: false, value: Some(Ptr(addr, self)) } } fn fallible_operation(&self) { self.cur_ops.set(self.cur_ops.get() + 1); @@ -89,11 +83,11 @@ impl Allocator { // Type that tracks whether it was dropped and can panic when it's created or // destroyed. -struct Ptr(usize, Rc); -impl Drop for Ptr { +struct Ptr<'a>(usize, &'a Allocator); +impl<'a> Drop for Ptr<'a> { fn drop(&mut self) { match self.1.data.borrow_mut()[self.0] { - false => panic!("double free in {:?} at index {:?}", self.1.name, self.0), + false => panic!("double free at index {:?}", self.0), ref mut d => *d = false, } @@ -117,7 +111,7 @@ async fn dynamic_drop(a: Rc, c: bool) { }; } -struct TwoPtrs(Ptr, Ptr); +struct TwoPtrs<'a>(Ptr<'a>, Ptr<'a>); async fn struct_dynamic_drop(a: Rc, c0: bool, c1: bool, c: bool) { for i in 0..2 { let x; @@ -238,62 +232,21 @@ async fn move_ref_pattern(a: Rc) { a.alloc().await; } -async fn panic_after_return(a: Rc, c: bool) -> (Ptr,) { - a.alloc().await; - let p = a.alloc().await; - if c { - a.alloc().await; - let q = a.alloc().await; - // We use a return type that isn't used anywhere else to make sure that - // the return place doesn't incorrectly end up in the generator state. - return (a.alloc().await,); - } - (a.alloc().await,) -} - - -async fn panic_after_init_by_loop(a: Rc) { - a.alloc().await; - let p = a.alloc().await; - let q = loop { - a.alloc().await; - let r = a.alloc().await; - break a.alloc().await; - }; -} - -async fn panic_after_init_by_match_with_bindings_and_guard(a: Rc, b: bool) { - a.alloc().await; - let p = a.alloc().await; - let q = match a.alloc().await { - ref _x if b => { - a.alloc().await; - let r = a.alloc().await; - a.alloc().await - } - _x => { - a.alloc().await; - let r = a.alloc().await; - a.alloc().await - }, - }; -} - -fn run_test(cx: &mut Context<'_>, ref f: F, name: &'static str) +fn run_test(cx: &mut Context<'_>, ref f: F) where F: Fn(Rc) -> G, - G: Future, + G: Future, { for polls in 0.. { // Run without any panics to find which operations happen after the // penultimate `poll`. - let first_alloc = Rc::new(Allocator::new(usize::MAX, name)); + let first_alloc = Rc::new(Allocator::new(usize::MAX)); let mut fut = Box::pin(f(first_alloc.clone())); let mut ops_before_last_poll = 0; let mut completed = false; for _ in 0..polls { ops_before_last_poll = first_alloc.cur_ops.get(); - if let Poll::Ready(_) = fut.as_mut().poll(cx) { + if let Poll::Ready(()) = fut.as_mut().poll(cx) { completed = true; } } @@ -302,7 +255,7 @@ where // Start at `ops_before_last_poll` so that we will always be able to // `poll` the expected number of times. for failing_op in ops_before_last_poll..first_alloc.cur_ops.get() { - let alloc = Rc::new(Allocator::new(failing_op + 1, name)); + let alloc = Rc::new(Allocator::new(failing_op + 1)); let f = &f; let cx = &mut *cx; let result = panic::catch_unwind(panic::AssertUnwindSafe(move || { @@ -332,58 +285,48 @@ fn clone_waker(data: *const ()) -> RawWaker { RawWaker::new(data, &RawWakerVTable::new(clone_waker, drop, drop, drop)) } -macro_rules! run_test { - ($ctxt:expr, $e:expr) => { run_test($ctxt, $e, stringify!($e)); }; -} - fn main() { let waker = unsafe { Waker::from_raw(clone_waker(ptr::null())) }; let context = &mut Context::from_waker(&waker); - run_test!(context, |a| dynamic_init(a, false)); - run_test!(context, |a| dynamic_init(a, true)); - run_test!(context, |a| dynamic_drop(a, false)); - run_test!(context, |a| dynamic_drop(a, true)); - - run_test!(context, |a| assignment(a, false, false)); - run_test!(context, |a| assignment(a, false, true)); - run_test!(context, |a| assignment(a, true, false)); - run_test!(context, |a| assignment(a, true, true)); - - run_test!(context, |a| array_simple(a)); - run_test!(context, |a| vec_simple(a)); - run_test!(context, |a| vec_unreachable(a)); - - run_test!(context, |a| struct_dynamic_drop(a, false, false, false)); - run_test!(context, |a| struct_dynamic_drop(a, false, false, true)); - run_test!(context, |a| struct_dynamic_drop(a, false, true, false)); - run_test!(context, |a| struct_dynamic_drop(a, false, true, true)); - run_test!(context, |a| struct_dynamic_drop(a, true, false, false)); - run_test!(context, |a| struct_dynamic_drop(a, true, false, true)); - run_test!(context, |a| struct_dynamic_drop(a, true, true, false)); - run_test!(context, |a| struct_dynamic_drop(a, true, true, true)); - - run_test!(context, |a| field_assignment(a, false)); - run_test!(context, |a| field_assignment(a, true)); - - run_test!(context, |a| mixed_drop_and_nondrop(a)); - - run_test!(context, |a| slice_pattern_one_of(a, 0)); - run_test!(context, |a| slice_pattern_one_of(a, 1)); - run_test!(context, |a| slice_pattern_one_of(a, 2)); - run_test!(context, |a| slice_pattern_one_of(a, 3)); - - run_test!(context, |a| subslice_pattern_from_end_with_drop(a, true, true)); - run_test!(context, |a| subslice_pattern_from_end_with_drop(a, true, false)); - run_test!(context, |a| subslice_pattern_from_end_with_drop(a, false, true)); - run_test!(context, |a| subslice_pattern_from_end_with_drop(a, false, false)); - run_test!(context, |a| subslice_pattern_reassign(a)); - - run_test!(context, |a| move_ref_pattern(a)); - - run_test!(context, |a| panic_after_return(a, false)); - run_test!(context, |a| panic_after_return(a, true)); - run_test!(context, |a| panic_after_init_by_loop(a)); - run_test!(context, |a| panic_after_init_by_match_with_bindings_and_guard(a, false)); - run_test!(context, |a| panic_after_init_by_match_with_bindings_and_guard(a, true)); + run_test(context, |a| dynamic_init(a, false)); + run_test(context, |a| dynamic_init(a, true)); + run_test(context, |a| dynamic_drop(a, false)); + run_test(context, |a| dynamic_drop(a, true)); + + run_test(context, |a| assignment(a, false, false)); + run_test(context, |a| assignment(a, false, true)); + run_test(context, |a| assignment(a, true, false)); + run_test(context, |a| assignment(a, true, true)); + + run_test(context, |a| array_simple(a)); + run_test(context, |a| vec_simple(a)); + run_test(context, |a| vec_unreachable(a)); + + run_test(context, |a| struct_dynamic_drop(a, false, false, false)); + run_test(context, |a| struct_dynamic_drop(a, false, false, true)); + run_test(context, |a| struct_dynamic_drop(a, false, true, false)); + run_test(context, |a| struct_dynamic_drop(a, false, true, true)); + run_test(context, |a| struct_dynamic_drop(a, true, false, false)); + run_test(context, |a| struct_dynamic_drop(a, true, false, true)); + run_test(context, |a| struct_dynamic_drop(a, true, true, false)); + run_test(context, |a| struct_dynamic_drop(a, true, true, true)); + + run_test(context, |a| field_assignment(a, false)); + run_test(context, |a| field_assignment(a, true)); + + run_test(context, |a| mixed_drop_and_nondrop(a)); + + run_test(context, |a| slice_pattern_one_of(a, 0)); + run_test(context, |a| slice_pattern_one_of(a, 1)); + run_test(context, |a| slice_pattern_one_of(a, 2)); + run_test(context, |a| slice_pattern_one_of(a, 3)); + + run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, true)); + run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, false)); + run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, true)); + run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, false)); + run_test(context, |a| subslice_pattern_reassign(a)); + + run_test(context, |a| move_ref_pattern(a)); } diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index ddccee20e12a6..88f557055f371 100644 --- a/src/test/ui/drop/dynamic-drop.rs +++ b/src/test/ui/drop/dynamic-drop.rs @@ -3,6 +3,7 @@ #![feature(generators, generator_trait)] #![feature(bindings_after_at)] + #![allow(unused_assignments)] #![allow(unused_variables)] @@ -16,7 +17,6 @@ struct InjectedFailure; struct Allocator { data: RefCell>, - name: &'static str, failing_op: usize, cur_ops: Cell, } @@ -28,18 +28,17 @@ impl Drop for Allocator { fn drop(&mut self) { let data = self.data.borrow(); if data.iter().any(|d| *d) { - panic!("missing free in {:?}: {:?}", self.name, data); + panic!("missing free: {:?}", data); } } } impl Allocator { - fn new(failing_op: usize, name: &'static str) -> Self { + fn new(failing_op: usize) -> Self { Allocator { failing_op: failing_op, cur_ops: Cell::new(0), - data: RefCell::new(vec![]), - name, + data: RefCell::new(vec![]) } } fn alloc(&self) -> Ptr<'_> { @@ -54,17 +53,33 @@ impl Allocator { data.push(true); Ptr(addr, self) } + // FIXME(#47949) Any use of this indicates a bug in rustc: we should never + // be leaking values in the cases here. + // + // Creates a `Ptr<'_>` and checks that the allocated value is leaked if the + // `failing_op` is in the list of exception. + fn alloc_leaked(&self, exceptions: Vec) -> Ptr<'_> { + let ptr = self.alloc(); + + if exceptions.iter().any(|operation| *operation == self.failing_op) { + let mut data = self.data.borrow_mut(); + data[ptr.0] = false; + } + ptr + } } struct Ptr<'a>(usize, &'a Allocator); impl<'a> Drop for Ptr<'a> { fn drop(&mut self) { match self.1.data.borrow_mut()[self.0] { - false => panic!("double free in {:?} at index {:?}", self.1.name, self.0), - ref mut d => *d = false, + false => { + panic!("double free at index {:?}", self.0) + } + ref mut d => *d = false } - self.1.cur_ops.set(self.1.cur_ops.get() + 1); + self.1.cur_ops.set(self.1.cur_ops.get()+1); if self.1.cur_ops.get() == self.1.failing_op { panic!(InjectedFailure); @@ -162,7 +177,11 @@ fn generator(a: &Allocator, run_count: usize) { assert!(run_count < 4); let mut gen = || { - (a.alloc(), yield a.alloc(), a.alloc(), yield a.alloc()); + (a.alloc(), + yield a.alloc(), + a.alloc(), + yield a.alloc() + ); }; for _ in 0..run_count { Pin::new(&mut gen).resume(()); @@ -186,40 +205,28 @@ fn vec_unreachable(a: &Allocator) { } fn slice_pattern_first(a: &Allocator) { - let [_x, ..] = [a.alloc(), a.alloc(), a.alloc()]; + let[_x, ..] = [a.alloc(), a.alloc(), a.alloc()]; } fn slice_pattern_middle(a: &Allocator) { - let [_, _x, _] = [a.alloc(), a.alloc(), a.alloc()]; + let[_, _x, _] = [a.alloc(), a.alloc(), a.alloc()]; } fn slice_pattern_two(a: &Allocator) { - let [_x, _, _y, _] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()]; + let[_x, _, _y, _] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()]; } fn slice_pattern_last(a: &Allocator) { - let [.., _y] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()]; + let[.., _y] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()]; } fn slice_pattern_one_of(a: &Allocator, i: usize) { let array = [a.alloc(), a.alloc(), a.alloc(), a.alloc()]; let _x = match i { - 0 => { - let [a, ..] = array; - a - } - 1 => { - let [_, a, ..] = array; - a - } - 2 => { - let [_, _, a, _] = array; - a - } - 3 => { - let [_, _, _, a] = array; - a - } + 0 => { let [a, ..] = array; a } + 1 => { let [_, a, ..] = array; a } + 2 => { let [_, _, a, _] = array; a } + 3 => { let [_, _, _, a] = array; a } _ => panic!("unmatched"), }; } @@ -227,9 +234,9 @@ fn slice_pattern_one_of(a: &Allocator, i: usize) { fn subslice_pattern_from_end(a: &Allocator, arg: bool) { let a = [a.alloc(), a.alloc(), a.alloc()]; if arg { - let [.., _x, _] = a; + let[.., _x, _] = a; } else { - let [_, _y @ ..] = a; + let[_, _y @ ..] = a; } } @@ -241,61 +248,45 @@ fn subslice_pattern_from_end_with_drop(a: &Allocator, arg: bool, arg2: bool) { } if arg { - let [.., _x, _] = a; + let[.., _x, _] = a; } else { - let [_, _y @ ..] = a; + let[_, _y @ ..] = a; } } fn slice_pattern_reassign(a: &Allocator) { let mut ar = [a.alloc(), a.alloc()]; - let [_, _x] = ar; + let[_, _x] = ar; ar = [a.alloc(), a.alloc()]; - let [.., _y] = ar; + let[.., _y] = ar; } fn subslice_pattern_reassign(a: &Allocator) { let mut ar = [a.alloc(), a.alloc(), a.alloc()]; - let [_, _, _x] = ar; + let[_, _, _x] = ar; ar = [a.alloc(), a.alloc(), a.alloc()]; - let [_, _y @ ..] = ar; + let[_, _y @ ..] = ar; } fn index_field_mixed_ends(a: &Allocator) { let ar = [(a.alloc(), a.alloc()), (a.alloc(), a.alloc())]; - let [(_x, _), ..] = ar; - let [(_, _y), _] = ar; - let [_, (_, _w)] = ar; - let [.., (_z, _)] = ar; + let[(_x, _), ..] = ar; + let[(_, _y), _] = ar; + let[_, (_, _w)] = ar; + let[.., (_z, _)] = ar; } fn subslice_mixed_min_lengths(a: &Allocator, c: i32) { let ar = [(a.alloc(), a.alloc()), (a.alloc(), a.alloc())]; match c { - 0 => { - let [_x, ..] = ar; - } - 1 => { - let [_x, _, ..] = ar; - } - 2 => { - let [_x, _] = ar; - } - 3 => { - let [(_x, _), _, ..] = ar; - } - 4 => { - let [.., (_x, _)] = ar; - } - 5 => { - let [.., (_x, _), _] = ar; - } - 6 => { - let [_y @ ..] = ar; - } - _ => { - let [_y @ .., _] = ar; - } + 0 => { let[_x, ..] = ar; } + 1 => { let[_x, _, ..] = ar; } + 2 => { let[_x, _] = ar; } + 3 => { let[(_x, _), _, ..] = ar; } + 4 => { let[.., (_x, _)] = ar; } + 5 => { let[.., (_x, _), _] = ar; } + 6 => { let [_y @ ..] = ar; } + _ => { let [_y @ .., _] = ar; } } } @@ -343,160 +334,87 @@ fn move_ref_pattern(a: &Allocator) { } fn panic_after_return(a: &Allocator) -> Ptr<'_> { + // Panic in the drop of `p` or `q` can leak + let exceptions = vec![8, 9]; a.alloc(); let p = a.alloc(); { a.alloc(); let p = a.alloc(); - a.alloc() + // FIXME (#47949) We leak values when we panic in a destructor after + // evaluating an expression with `rustc_mir::build::Builder::into`. + a.alloc_leaked(exceptions) } } fn panic_after_return_expr(a: &Allocator) -> Ptr<'_> { + // Panic in the drop of `p` or `q` can leak + let exceptions = vec![8, 9]; a.alloc(); let p = a.alloc(); { a.alloc(); let q = a.alloc(); - return a.alloc(); + // FIXME (#47949) + return a.alloc_leaked(exceptions); } } fn panic_after_init(a: &Allocator) { + // Panic in the drop of `r` can leak + let exceptions = vec![8]; a.alloc(); let p = a.alloc(); let q = { a.alloc(); let r = a.alloc(); - a.alloc() + // FIXME (#47949) + a.alloc_leaked(exceptions) }; } fn panic_after_init_temp(a: &Allocator) { + // Panic in the drop of `r` can leak + let exceptions = vec![8]; a.alloc(); let p = a.alloc(); { a.alloc(); let r = a.alloc(); - a.alloc() + // FIXME (#47949) + a.alloc_leaked(exceptions) }; } fn panic_after_init_by_loop(a: &Allocator) { + // Panic in the drop of `r` can leak + let exceptions = vec![8]; a.alloc(); let p = a.alloc(); let q = loop { a.alloc(); let r = a.alloc(); - break a.alloc(); - }; -} - -fn panic_after_init_by_match(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let _ = loop { - let q = match b { - true => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - false => { - a.alloc(); - let r = a.alloc(); - break a.alloc(); - } - }; - return; - }; -} - -fn panic_after_init_by_match_with_guard(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let q = match a.alloc() { - _ if b => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - _ => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - }; -} - -fn panic_after_init_by_match_with_bindings_and_guard(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let q = match a.alloc() { - _x if b => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - _x => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - }; -} - -fn panic_after_init_by_match_with_ref_bindings_and_guard(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let q = match a.alloc() { - ref _x if b => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - ref _x => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - }; -} - -fn panic_after_init_by_break_if(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let q = loop { - let r = a.alloc(); - break if b { - let s = a.alloc(); - a.alloc() - } else { - a.alloc() - }; + // FIXME (#47949) + break a.alloc_leaked(exceptions); }; } -fn run_test(mut f: F, name: &'static str) -where - F: FnMut(&Allocator), +fn run_test(mut f: F) + where F: FnMut(&Allocator) { - let first_alloc = Allocator::new(usize::MAX, name); + let first_alloc = Allocator::new(usize::MAX); f(&first_alloc); - for failing_op in 1..first_alloc.cur_ops.get() + 1 { - let alloc = Allocator::new(failing_op, name); + for failing_op in 1..first_alloc.cur_ops.get()+1 { + let alloc = Allocator::new(failing_op); let alloc = &alloc; let f = panic::AssertUnwindSafe(&mut f); let result = panic::catch_unwind(move || { f.0(alloc); }); match result { - Ok(..) => panic!( - "test executed {} ops but now {}", - first_alloc.cur_ops.get(), - alloc.cur_ops.get() - ), + Ok(..) => panic!("test executed {} ops but now {}", + first_alloc.cur_ops.get(), alloc.cur_ops.get()), Err(e) => { if e.downcast_ref::().is_none() { panic::resume_unwind(e); @@ -506,115 +424,98 @@ where } } -fn run_test_nopanic(mut f: F, name: &'static str) -where - F: FnMut(&Allocator), +fn run_test_nopanic(mut f: F) + where F: FnMut(&Allocator) { - let first_alloc = Allocator::new(usize::MAX, name); + let first_alloc = Allocator::new(usize::MAX); f(&first_alloc); } -macro_rules! run_test { - ($e:expr) => { - run_test($e, stringify!($e)); - }; -} - fn main() { - run_test!(|a| dynamic_init(a, false)); - run_test!(|a| dynamic_init(a, true)); - run_test!(|a| dynamic_drop(a, false)); - run_test!(|a| dynamic_drop(a, true)); - - run_test!(|a| assignment2(a, false, false)); - run_test!(|a| assignment2(a, false, true)); - run_test!(|a| assignment2(a, true, false)); - run_test!(|a| assignment2(a, true, true)); - - run_test!(|a| assignment1(a, false)); - run_test!(|a| assignment1(a, true)); - - run_test!(|a| array_simple(a)); - run_test!(|a| vec_simple(a)); - run_test!(|a| vec_unreachable(a)); - - run_test!(|a| struct_dynamic_drop(a, false, false, false)); - run_test!(|a| struct_dynamic_drop(a, false, false, true)); - run_test!(|a| struct_dynamic_drop(a, false, true, false)); - run_test!(|a| struct_dynamic_drop(a, false, true, true)); - run_test!(|a| struct_dynamic_drop(a, true, false, false)); - run_test!(|a| struct_dynamic_drop(a, true, false, true)); - run_test!(|a| struct_dynamic_drop(a, true, true, false)); - run_test!(|a| struct_dynamic_drop(a, true, true, true)); - - run_test!(|a| field_assignment(a, false)); - run_test!(|a| field_assignment(a, true)); - - run_test!(|a| generator(a, 0)); - run_test!(|a| generator(a, 1)); - run_test!(|a| generator(a, 2)); - run_test!(|a| generator(a, 3)); - - run_test!(|a| mixed_drop_and_nondrop(a)); - - run_test!(|a| slice_pattern_first(a)); - run_test!(|a| slice_pattern_middle(a)); - run_test!(|a| slice_pattern_two(a)); - run_test!(|a| slice_pattern_last(a)); - run_test!(|a| slice_pattern_one_of(a, 0)); - run_test!(|a| slice_pattern_one_of(a, 1)); - run_test!(|a| slice_pattern_one_of(a, 2)); - run_test!(|a| slice_pattern_one_of(a, 3)); - - run_test!(|a| subslice_pattern_from_end(a, true)); - run_test!(|a| subslice_pattern_from_end(a, false)); - run_test!(|a| subslice_pattern_from_end_with_drop(a, true, true)); - run_test!(|a| subslice_pattern_from_end_with_drop(a, true, false)); - run_test!(|a| subslice_pattern_from_end_with_drop(a, false, true)); - run_test!(|a| subslice_pattern_from_end_with_drop(a, false, false)); - run_test!(|a| slice_pattern_reassign(a)); - run_test!(|a| subslice_pattern_reassign(a)); - - run_test!(|a| index_field_mixed_ends(a)); - run_test!(|a| subslice_mixed_min_lengths(a, 0)); - run_test!(|a| subslice_mixed_min_lengths(a, 1)); - run_test!(|a| subslice_mixed_min_lengths(a, 2)); - run_test!(|a| subslice_mixed_min_lengths(a, 3)); - run_test!(|a| subslice_mixed_min_lengths(a, 4)); - run_test!(|a| subslice_mixed_min_lengths(a, 5)); - run_test!(|a| subslice_mixed_min_lengths(a, 6)); - run_test!(|a| subslice_mixed_min_lengths(a, 7)); - - run_test!(|a| move_ref_pattern(a)); - - run_test!(|a| { + run_test(|a| dynamic_init(a, false)); + run_test(|a| dynamic_init(a, true)); + run_test(|a| dynamic_drop(a, false)); + run_test(|a| dynamic_drop(a, true)); + + run_test(|a| assignment2(a, false, false)); + run_test(|a| assignment2(a, false, true)); + run_test(|a| assignment2(a, true, false)); + run_test(|a| assignment2(a, true, true)); + + run_test(|a| assignment1(a, false)); + run_test(|a| assignment1(a, true)); + + run_test(|a| array_simple(a)); + run_test(|a| vec_simple(a)); + run_test(|a| vec_unreachable(a)); + + run_test(|a| struct_dynamic_drop(a, false, false, false)); + run_test(|a| struct_dynamic_drop(a, false, false, true)); + run_test(|a| struct_dynamic_drop(a, false, true, false)); + run_test(|a| struct_dynamic_drop(a, false, true, true)); + run_test(|a| struct_dynamic_drop(a, true, false, false)); + run_test(|a| struct_dynamic_drop(a, true, false, true)); + run_test(|a| struct_dynamic_drop(a, true, true, false)); + run_test(|a| struct_dynamic_drop(a, true, true, true)); + + run_test(|a| field_assignment(a, false)); + run_test(|a| field_assignment(a, true)); + + run_test(|a| generator(a, 0)); + run_test(|a| generator(a, 1)); + run_test(|a| generator(a, 2)); + run_test(|a| generator(a, 3)); + + run_test(|a| mixed_drop_and_nondrop(a)); + + run_test(|a| slice_pattern_first(a)); + run_test(|a| slice_pattern_middle(a)); + run_test(|a| slice_pattern_two(a)); + run_test(|a| slice_pattern_last(a)); + run_test(|a| slice_pattern_one_of(a, 0)); + run_test(|a| slice_pattern_one_of(a, 1)); + run_test(|a| slice_pattern_one_of(a, 2)); + run_test(|a| slice_pattern_one_of(a, 3)); + + run_test(|a| subslice_pattern_from_end(a, true)); + run_test(|a| subslice_pattern_from_end(a, false)); + run_test(|a| subslice_pattern_from_end_with_drop(a, true, true)); + run_test(|a| subslice_pattern_from_end_with_drop(a, true, false)); + run_test(|a| subslice_pattern_from_end_with_drop(a, false, true)); + run_test(|a| subslice_pattern_from_end_with_drop(a, false, false)); + run_test(|a| slice_pattern_reassign(a)); + run_test(|a| subslice_pattern_reassign(a)); + + run_test(|a| index_field_mixed_ends(a)); + run_test(|a| subslice_mixed_min_lengths(a, 0)); + run_test(|a| subslice_mixed_min_lengths(a, 1)); + run_test(|a| subslice_mixed_min_lengths(a, 2)); + run_test(|a| subslice_mixed_min_lengths(a, 3)); + run_test(|a| subslice_mixed_min_lengths(a, 4)); + run_test(|a| subslice_mixed_min_lengths(a, 5)); + run_test(|a| subslice_mixed_min_lengths(a, 6)); + run_test(|a| subslice_mixed_min_lengths(a, 7)); + + run_test(|a| move_ref_pattern(a)); + + run_test(|a| { panic_after_return(a); }); - run_test!(|a| { + run_test(|a| { panic_after_return_expr(a); }); - run_test!(|a| panic_after_init(a)); - run_test!(|a| panic_after_init_temp(a)); - run_test!(|a| panic_after_init_by_loop(a)); - run_test!(|a| panic_after_init_by_match(a, false)); - run_test!(|a| panic_after_init_by_match(a, true)); - run_test!(|a| panic_after_init_by_match_with_guard(a, false)); - run_test!(|a| panic_after_init_by_match_with_guard(a, true)); - run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, false)); - run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, true)); - run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, false)); - run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, true)); - run_test!(|a| panic_after_init_by_break_if(a, false)); - run_test!(|a| panic_after_init_by_break_if(a, true)); - - run_test!(|a| bindings_after_at_dynamic_init_move(a, true)); - run_test!(|a| bindings_after_at_dynamic_init_move(a, false)); - run_test!(|a| bindings_after_at_dynamic_init_ref(a, true)); - run_test!(|a| bindings_after_at_dynamic_init_ref(a, false)); - run_test!(|a| bindings_after_at_dynamic_drop_move(a, true)); - run_test!(|a| bindings_after_at_dynamic_drop_move(a, false)); - run_test!(|a| bindings_after_at_dynamic_drop_ref(a, true)); - run_test!(|a| bindings_after_at_dynamic_drop_ref(a, false)); - - run_test_nopanic(|a| union1(a), "|a| union1(a)"); + run_test(|a| panic_after_init(a)); + run_test(|a| panic_after_init_temp(a)); + run_test(|a| panic_after_init_by_loop(a)); + + run_test(|a| bindings_after_at_dynamic_init_move(a, true)); + run_test(|a| bindings_after_at_dynamic_init_move(a, false)); + run_test(|a| bindings_after_at_dynamic_init_ref(a, true)); + run_test(|a| bindings_after_at_dynamic_init_ref(a, false)); + run_test(|a| bindings_after_at_dynamic_drop_move(a, true)); + run_test(|a| bindings_after_at_dynamic_drop_move(a, false)); + run_test(|a| bindings_after_at_dynamic_drop_ref(a, true)); + run_test(|a| bindings_after_at_dynamic_drop_ref(a, false)); + + run_test_nopanic(|a| union1(a)); } diff --git a/src/test/ui/mir/issue-80949.rs b/src/test/ui/mir/issue-80949.rs new file mode 100644 index 0000000000000..7e34a4f5c2737 --- /dev/null +++ b/src/test/ui/mir/issue-80949.rs @@ -0,0 +1,34 @@ +// build-pass + +trait Trait { type Item; } + +impl<'a, X> Trait for &'a Vec { + type Item = &'a X; +} + +impl Trait for Box> { + type Item = X; +} + +fn make_dyn_trait(_: &()) -> Box> { + todo!() +} + +fn diff<'a, M, N, S>(_: N, _: S) +where + M: 'a, + N: Trait, + S: Trait, +{ + todo!() +} + +fn may_panic(_: X) { } + +fn main() { + let dyn_trait = make_dyn_trait(&()); + let storage = vec![()]; + let _x = may_panic(()); + let storage_ref = &storage; + diff(dyn_trait, storage_ref); +} From fc81b7c091d13f3fd2ca7f1ff9221693fdf7e53b Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 2 Feb 2021 19:22:44 +0100 Subject: [PATCH 10/10] Rename `panic_fmt` lint to `non_fmt_panic`. --- compiler/rustc_lint/src/panic_fmt.rs | 11 ++++++----- src/test/ui/fmt/format-args-capture.rs | 2 +- src/test/ui/macros/macro-comma-behavior-rpass.rs | 2 +- src/test/ui/panic-brace.stderr | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_lint/src/panic_fmt.rs b/compiler/rustc_lint/src/panic_fmt.rs index 0d2b20989b0c3..e01ff1641b296 100644 --- a/compiler/rustc_lint/src/panic_fmt.rs +++ b/compiler/rustc_lint/src/panic_fmt.rs @@ -7,7 +7,8 @@ use rustc_parse_format::{ParseMode, Parser, Piece}; use rustc_span::{sym, InnerSpan}; declare_lint! { - /// The `panic_fmt` lint detects `panic!("..")` with `{` or `}` in the string literal. + /// The `non_fmt_panic` lint detects `panic!("..")` with `{` or `}` in the string literal + /// when it is not used as a format string. /// /// ### Example /// @@ -23,13 +24,13 @@ declare_lint! { /// with a single argument does not use `format_args!()`. /// A future edition of Rust will interpret this string as format string, /// which would break this. - PANIC_FMT, + NON_FMT_PANIC, Warn, "detect braces in single-argument panic!() invocations", report_in_external_macro } -declare_lint_pass!(PanicFmt => [PANIC_FMT]); +declare_lint_pass!(PanicFmt => [NON_FMT_PANIC]); impl<'tcx> LateLintPass<'tcx> for PanicFmt { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { @@ -92,7 +93,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc [] => vec![fmt_span], v => v.iter().map(|span| fmt_span.from_inner(*span)).collect(), }; - cx.struct_span_lint(PANIC_FMT, arg_spans, |lint| { + cx.struct_span_lint(NON_FMT_PANIC, arg_spans, |lint| { let mut l = lint.build(match n_arguments { 1 => "panic message contains an unused formatting placeholder", _ => "panic message contains unused formatting placeholders", @@ -129,7 +130,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc Some(v) if v.len() == 1 => "panic message contains a brace", _ => "panic message contains braces", }; - cx.struct_span_lint(PANIC_FMT, brace_spans.unwrap_or(vec![expn.call_site]), |lint| { + cx.struct_span_lint(NON_FMT_PANIC, brace_spans.unwrap_or(vec![expn.call_site]), |lint| { let mut l = lint.build(msg); l.note("this message is not used as a format string, but will be in a future Rust edition"); if expn.call_site.contains(arg.span) { diff --git a/src/test/ui/fmt/format-args-capture.rs b/src/test/ui/fmt/format-args-capture.rs index 4e3fa9a3c589a..d5886a13558c6 100644 --- a/src/test/ui/fmt/format-args-capture.rs +++ b/src/test/ui/fmt/format-args-capture.rs @@ -31,7 +31,7 @@ fn panic_with_single_argument_does_not_get_formatted() { // RFC #2795 suggests that this may need to change so that captured arguments are formatted. // For stability reasons this will need to part of an edition change. - #[allow(panic_fmt)] + #[allow(non_fmt_panic)] let msg = std::panic::catch_unwind(|| { panic!("{foo}"); }).unwrap_err(); diff --git a/src/test/ui/macros/macro-comma-behavior-rpass.rs b/src/test/ui/macros/macro-comma-behavior-rpass.rs index e5e656de6fa7f..e814e075647b1 100644 --- a/src/test/ui/macros/macro-comma-behavior-rpass.rs +++ b/src/test/ui/macros/macro-comma-behavior-rpass.rs @@ -57,7 +57,7 @@ fn writeln_1arg() { // // (Example: Issue #48042) #[test] -#[allow(panic_fmt)] +#[allow(non_fmt_panic)] fn to_format_or_not_to_format() { // ("{}" is the easiest string to test because if this gets // sent to format_args!, it'll simply fail to compile. diff --git a/src/test/ui/panic-brace.stderr b/src/test/ui/panic-brace.stderr index 93808891c3c37..c2aa19c580662 100644 --- a/src/test/ui/panic-brace.stderr +++ b/src/test/ui/panic-brace.stderr @@ -4,7 +4,7 @@ warning: panic message contains a brace LL | panic!("here's a brace: {"); | ^ | - = note: `#[warn(panic_fmt)]` on by default + = note: `#[warn(non_fmt_panic)]` on by default = note: this message is not used as a format string, but will be in a future Rust edition help: add a "{}" format string to use the message literally |