Skip to content

[beta] backports #81774

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 6, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
@@ -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::<Vec<_>>()
);
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
101 changes: 73 additions & 28 deletions compiler/rustc_lint/src/levels.rs
Original file line number Diff line number Diff line change
@@ -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<HirId, u32>,
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));
11 changes: 6 additions & 5 deletions compiler/rustc_lint/src/panic_fmt.rs
Original file line number Diff line number Diff line change
@@ -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) {
37 changes: 37 additions & 0 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/rust-lang/rust/issues/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,
14 changes: 11 additions & 3 deletions compiler/rustc_middle/src/lint.rs
Original file line number Diff line number Diff line change
@@ -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 {
10 changes: 3 additions & 7 deletions compiler/rustc_mir_build/src/build/block.rs
Original file line number Diff line number Diff line change
@@ -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<region::Scope>,
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<region::Scope>,
mut block: BasicBlock,
span: Span,
stmts: Vec<StmtRef<'tcx>>,
@@ -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()));
20 changes: 4 additions & 16 deletions compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
@@ -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 { .. } => {
6 changes: 5 additions & 1 deletion compiler/rustc_mir_build/src/build/expr/as_temp.rs
Original file line number Diff line number Diff line change
@@ -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)
}
90 changes: 27 additions & 63 deletions compiler/rustc_mir_build/src/build/expr/into.rs
Original file line number Diff line number Diff line change
@@ -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<region::Scope>,
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,22 +430,19 @@ 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::Yield { value } => {
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()
}
};
2 changes: 0 additions & 2 deletions compiler/rustc_mir_build/src/build/expr/stmt.rs
Original file line number Diff line number Diff line change
@@ -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));
11 changes: 3 additions & 8 deletions compiler/rustc_mir_build/src/build/into.rs
Original file line number Diff line number Diff line change
@@ -6,15 +6,13 @@
use crate::build::{BlockAnd, Builder};
use crate::thir::*;
use rustc_middle::middle::region;
use rustc_middle::mir::*;

pub(in crate::build) trait EvalInto<'tcx> {
fn eval_into(
self,
builder: &mut Builder<'_, 'tcx>,
destination: Place<'tcx>,
scope: Option<region::Scope>,
block: BasicBlock,
) -> BlockAnd<()>;
}
@@ -23,14 +21,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
crate fn into<E>(
&mut self,
destination: Place<'tcx>,
scope: Option<region::Scope>,
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<region::Scope>,
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<region::Scope>,
block: BasicBlock,
) -> BlockAnd<()> {
builder.into_expr(destination, scope, block, self)
builder.into_expr(destination, block, self)
}
}
78 changes: 69 additions & 9 deletions compiler/rustc_mir_build/src/build/matches/mod.rs
Original file line number Diff line number Diff line change
@@ -87,7 +87,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
crate fn match_expr(
&mut self,
destination: Place<'tcx>,
destination_scope: Option<region::Scope>,
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,

20 changes: 5 additions & 15 deletions compiler/rustc_mir_build/src/build/mod.rs
Original file line number Diff line number Diff line change
@@ -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(
216 changes: 42 additions & 174 deletions compiler/rustc_mir_build/src/build/scope.rs
Original file line number Diff line number Diff line change
@@ -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<DropData>,

moved_locals: Vec<Local>,

/// The drop index that will drop everything in and below this scope on an
/// unwind path.
cached_unwind_block: Option<DropIdx>,
@@ -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<region::Scope>,
/// 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<BasicBlock>,
break_destination: Place<'tcx>,
destination_scope: Option<region::Scope>,
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,33 +589,30 @@ 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)
}
};

if let Some(destination) = destination {
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::<FxHashSet<_>>();
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,116 +1098,18 @@ 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<region::Scope>,
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);

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<BasicBlock>,
) -> Option<BlockAnd<()>> {
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::<ExitScopes>(&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 {
11 changes: 3 additions & 8 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
@@ -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());
4 changes: 0 additions & 4 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
@@ -291,10 +291,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx.tcx
}

pub(super) fn query_mode(&self) -> TraitQueryMode {
self.query_mode
}

///////////////////////////////////////////////////////////////////////////
// Selection
//
1 change: 0 additions & 1 deletion compiler/rustc_typeck/src/check/check.rs
Original file line number Diff line number Diff line change
@@ -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);
2 changes: 1 addition & 1 deletion library/alloc/src/collections/btree/map/tests.rs
Original file line number Diff line number Diff line change
@@ -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]
4 changes: 2 additions & 2 deletions library/core/src/alloc/layout.rs
Original file line number Diff line number Diff line change
@@ -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: (),
4 changes: 2 additions & 2 deletions library/core/src/alloc/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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.<version>.
# 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
4 changes: 3 additions & 1 deletion src/ci/scripts/install-msys2.sh
Original file line number Diff line number Diff line change
@@ -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
21 changes: 19 additions & 2 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
@@ -1096,7 +1096,10 @@ impl Clean<Item> 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<Item> 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);
}
})
}
}
Original file line number Diff line number Diff line change
@@ -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
}
}
28 changes: 18 additions & 10 deletions src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir
Original file line number Diff line number Diff line change
@@ -14,45 +14,53 @@ 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(<ZST>)) }
}

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::<Box<S>>(move _4) -> [return: bb2, unwind: bb4]; // scope 1 at $DIR/box_expr.rs:8:5: 8:12
_3 = std::mem::drop::<Box<S>>(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<S>) {std::mem::drop::<std::boxed::Box<S>>}, val: Value(Scalar(<ZST>)) }
}

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
}
}
11 changes: 5 additions & 6 deletions src/test/mir-opt/inline/inline_diverging.h.Inline.diff
Original file line number Diff line number Diff line change
@@ -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::<!, fn() -> ! {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 <fn() -> ! {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(<ZST>)) }
+ 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
}

27 changes: 24 additions & 3 deletions src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir
Original file line number Diff line number Diff line change
@@ -6,44 +6,65 @@ 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(<ZST>)) }
}

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(<ZST>)) }
}

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
return; // scope 0 at $DIR/issue-41110.rs:9:2: 9:2
}

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
}
}
48 changes: 30 additions & 18 deletions src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir
Original file line number Diff line number Diff line change
@@ -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::<S>(move _4) -> [return: bb1, unwind: bb5]; // scope 2 at $DIR/issue-41110.rs:17:5: 17:12
_3 = std::mem::drop::<S>(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::<S>}, val: Value(Scalar(<ZST>)) }
@@ -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
}
}
74 changes: 41 additions & 33 deletions src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir
Original file line number Diff line number Diff line change
@@ -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(<ZST>)) }
@@ -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,62 +87,66 @@ 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
_1 = move _3; // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
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
}
}
40 changes: 24 additions & 16 deletions src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ fn test() -> Option<Box<u32>> {
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::<u32>::None; // scope 0 at $DIR/issue-62289.rs:9:15: 9:19
_3 = <Option<u32> as Try>::into_result(move _4) -> [return: bb1, unwind: bb10]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
_3 = <Option<u32> 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<u32>) -> std::result::Result<<std::option::Option<u32> as std::ops::Try>::Ok, <std::option::Option<u32> as std::ops::Try>::Error> {<std::option::Option<u32> as std::ops::Try>::into_result}, val: Value(Scalar(<ZST>)) }
@@ -48,11 +48,7 @@ fn test() -> Option<Box<u32>> {
(*_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::<Box<u32>>::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,15 +61,15 @@ fn test() -> Option<Box<u32>> {
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 = <NoneError as From<NoneError>>::from(move _9) -> [return: bb5, unwind: bb10]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
_8 = <NoneError as From<NoneError>>::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 {<std::option::NoneError as std::convert::From<std::option::NoneError>>::from}, val: Value(Scalar(<ZST>)) }
}

bb5: {
StorageDead(_9); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
_0 = <Option<Box<u32>> as Try>::from_error(move _8) -> [return: bb6, unwind: bb10]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20
_0 = <Option<Box<u32>> 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(<std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::Error) -> std::option::Option<std::boxed::Box<u32>> {<std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::from_error}, val: Value(Scalar(<ZST>)) }
@@ -82,29 +78,41 @@ fn test() -> Option<Box<u32>> {
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::<Box<u32>>::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
}
}
Original file line number Diff line number Diff line change
@@ -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::<String>(move _2) -> bb2; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:5: 9:35
_1 = std::mem::drop::<String>(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::<std::string::String>}, val: Value(Scalar(<ZST>)) }
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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<i32>>:
| used_crate::used_only_from_bin_crate_generic_function::<&str>:
| 17| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(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<i32>>:
| 17| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
| 18| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
| 19| 1|}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -69,9 +69,9 @@
</style>
</head>
<body>
<div class="code" style="counter-reset: line 92"><span class="line"><span><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb15]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb15]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb15]
<div class="code" style="counter-reset: line 92"><span class="line"><span><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb16]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb16]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb16]
96:22-96:36: @5.Call: _3 = Box::&lt;impl Future&gt;::pin(move _4) -&gt; [return: bb6, unwind: bb15]
96:9-96:19: @6[1]: FakeRead(ForLet, _3)
97:5-97:9: @6.Call: _5 = j(const 7_u8) -&gt; [return: bb7, unwind: bb14]
@@ -82,9 +82,9 @@
100:5-100:40: @11.Call: _8 = block_on::&lt;Pin&lt;&amp;mut impl Future&gt;&gt;(move _9) -&gt; [return: bb12, unwind: bb14]
93:11-101:2: @12[2]: _0 = const ()
101:2-101:2: @13.Return: return"><span class="annotation">@0,1,2,3,4,5,6,7,8,9,10,11,12,13⦊</span>fn main() {</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb15]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb15]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb15]
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb16]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb16]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb16]
96:22-96:36: @5.Call: _3 = Box::&lt;impl Future&gt;::pin(move _4) -&gt; [return: bb6, unwind: bb15]
96:9-96:19: @6[1]: FakeRead(ForLet, _3)
97:5-97:9: @6.Call: _5 = j(const 7_u8) -&gt; [return: bb7, unwind: bb14]
@@ -95,9 +95,9 @@
100:5-100:40: @11.Call: _8 = block_on::&lt;Pin&lt;&amp;mut impl Future&gt;&gt;(move _9) -&gt; [return: bb12, unwind: bb14]
93:11-101:2: @12[2]: _0 = const ()
101:2-101:2: @13.Return: return"> let _ = g(10);</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb15]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb15]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb15]
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb16]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb16]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb16]
96:22-96:36: @5.Call: _3 = Box::&lt;impl Future&gt;::pin(move _4) -&gt; [return: bb6, unwind: bb15]
96:9-96:19: @6[1]: FakeRead(ForLet, _3)
97:5-97:9: @6.Call: _5 = j(const 7_u8) -&gt; [return: bb7, unwind: bb14]
@@ -108,9 +108,9 @@
100:5-100:40: @11.Call: _8 = block_on::&lt;Pin&lt;&amp;mut impl Future&gt;&gt;(move _9) -&gt; [return: bb12, unwind: bb14]
93:11-101:2: @12[2]: _0 = const ()
101:2-101:2: @13.Return: return"> let _ = h(9);</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb15]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb15]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb15]
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb16]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb16]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb16]
96:22-96:36: @5.Call: _3 = Box::&lt;impl Future&gt;::pin(move _4) -&gt; [return: bb6, unwind: bb15]
96:9-96:19: @6[1]: FakeRead(ForLet, _3)
97:5-97:9: @6.Call: _5 = j(const 7_u8) -&gt; [return: bb7, unwind: bb14]
@@ -121,9 +121,9 @@
100:5-100:40: @11.Call: _8 = block_on::&lt;Pin&lt;&amp;mut impl Future&gt;&gt;(move _9) -&gt; [return: bb12, unwind: bb14]
93:11-101:2: @12[2]: _0 = const ()
101:2-101:2: @13.Return: return"> let mut future = Box::pin(i(8));</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb15]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb15]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb15]
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb16]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb16]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb16]
96:22-96:36: @5.Call: _3 = Box::&lt;impl Future&gt;::pin(move _4) -&gt; [return: bb6, unwind: bb15]
96:9-96:19: @6[1]: FakeRead(ForLet, _3)
97:5-97:9: @6.Call: _5 = j(const 7_u8) -&gt; [return: bb7, unwind: bb14]
@@ -134,9 +134,9 @@
100:5-100:40: @11.Call: _8 = block_on::&lt;Pin&lt;&amp;mut impl Future&gt;&gt;(move _9) -&gt; [return: bb12, unwind: bb14]
93:11-101:2: @12[2]: _0 = const ()
101:2-101:2: @13.Return: return"> j(7);</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb15]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb15]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb15]
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb16]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb16]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb16]
96:22-96:36: @5.Call: _3 = Box::&lt;impl Future&gt;::pin(move _4) -&gt; [return: bb6, unwind: bb15]
96:9-96:19: @6[1]: FakeRead(ForLet, _3)
97:5-97:9: @6.Call: _5 = j(const 7_u8) -&gt; [return: bb7, unwind: bb14]
@@ -147,9 +147,9 @@
100:5-100:40: @11.Call: _8 = block_on::&lt;Pin&lt;&amp;mut impl Future&gt;&gt;(move _9) -&gt; [return: bb12, unwind: bb14]
93:11-101:2: @12[2]: _0 = const ()
101:2-101:2: @13.Return: return"> l(6);</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb15]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb15]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb15]
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb16]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb16]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb16]
96:22-96:36: @5.Call: _3 = Box::&lt;impl Future&gt;::pin(move _4) -&gt; [return: bb6, unwind: bb15]
96:9-96:19: @6[1]: FakeRead(ForLet, _3)
97:5-97:9: @6.Call: _5 = j(const 7_u8) -&gt; [return: bb7, unwind: bb14]
@@ -160,9 +160,9 @@
100:5-100:40: @11.Call: _8 = block_on::&lt;Pin&lt;&amp;mut impl Future&gt;&gt;(move _9) -&gt; [return: bb12, unwind: bb14]
93:11-101:2: @12[2]: _0 = const ()
101:2-101:2: @13.Return: return"> let _ = m(5);</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb15]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb15]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb15]
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb16]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb16]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb16]
96:22-96:36: @5.Call: _3 = Box::&lt;impl Future&gt;::pin(move _4) -&gt; [return: bb6, unwind: bb15]
96:9-96:19: @6[1]: FakeRead(ForLet, _3)
97:5-97:9: @6.Call: _5 = j(const 7_u8) -&gt; [return: bb7, unwind: bb14]
@@ -173,9 +173,9 @@
100:5-100:40: @11.Call: _8 = block_on::&lt;Pin&lt;&amp;mut impl Future&gt;&gt;(move _9) -&gt; [return: bb12, unwind: bb14]
93:11-101:2: @12[2]: _0 = const ()
101:2-101:2: @13.Return: return"> executor::block_on(future.as_mut());</span></span>
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb15]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb15]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb15]
<span class="line"><span class="code even" style="--layer: 1" title="94:13-94:18: @0.Call: _1 = g(const 10_u8) -&gt; [return: bb1, unwind: bb16]
95:13-95:17: @2.Call: _2 = h(const 9_usize) -&gt; [return: bb3, unwind: bb16]
96:31-96:35: @4.Call: _4 = i(const 8_u8) -&gt; [return: bb5, unwind: bb16]
96:22-96:36: @5.Call: _3 = Box::&lt;impl Future&gt;::pin(move _4) -&gt; [return: bb6, unwind: bb15]
96:9-96:19: @6[1]: FakeRead(ForLet, _3)
97:5-97:9: @6.Call: _5 = j(const 7_u8) -&gt; [return: bb7, unwind: bb14]
Original file line number Diff line number Diff line change
@@ -97,13 +97,13 @@
103:9-103:29: @4[23]: _18 = (_16.0: &amp;&amp;str)
103:9-103:29: @4[26]: _20 = &amp;(*_18)
103:9-103:29: @4[28]: _21 = &lt;&amp;str as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;str, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
103:9-103:29: @4.Call: _19 = ArgumentV1::new::&lt;&amp;str&gt;(move _20, move _21) -&gt; [return: bb5, unwind: bb10]
103:9-103:29: @4.Call: _19 = ArgumentV1::new::&lt;&amp;str&gt;(move _20, move _21) -&gt; [return: bb5, unwind: bb9]
103:9-103:29: @5[2]: _15 = [move _19]
103:9-103:29: @5[5]: _14 = &amp;_15
103:9-103:29: @5[6]: _13 = &amp;(*_14)
103:9-103:29: @5[7]: _12 = move _13 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
103:9-103:29: @5.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb6, unwind: bb10]
103:9-103:29: @6.Call: _6 = format(move _7) -&gt; [return: bb7, unwind: bb10]
103:9-103:29: @5.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb6, unwind: bb9]
103:9-103:29: @6.Call: _6 = format(move _7) -&gt; [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"><span class="annotation">@4,5,6,7,8⦊</span>format!("'{}'", val)</span></span>
@@ -117,13 +117,13 @@
103:9-103:29: @4[23]: _18 = (_16.0: &amp;&amp;str)
103:9-103:29: @4[26]: _20 = &amp;(*_18)
103:9-103:29: @4[28]: _21 = &lt;&amp;str as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;str, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
103:9-103:29: @4.Call: _19 = ArgumentV1::new::&lt;&amp;str&gt;(move _20, move _21) -&gt; [return: bb5, unwind: bb10]
103:9-103:29: @4.Call: _19 = ArgumentV1::new::&lt;&amp;str&gt;(move _20, move _21) -&gt; [return: bb5, unwind: bb9]
103:9-103:29: @5[2]: _15 = [move _19]
103:9-103:29: @5[5]: _14 = &amp;_15
103:9-103:29: @5[6]: _13 = &amp;(*_14)
103:9-103:29: @5[7]: _12 = move _13 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
103:9-103:29: @5.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb6, unwind: bb10]
103:9-103:29: @6.Call: _6 = format(move _7) -&gt; [return: bb7, unwind: bb10]
103:9-103:29: @5.Call: _7 = Arguments::new_v1(move _8, move _12) -&gt; [return: bb6, unwind: bb9]
103:9-103:29: @6.Call: _6 = format(move _7) -&gt; [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"> }<span class="annotation">⦉@4,5,6,7,8</span></span></span></span></div>
Loading