summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_build/src/build
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_build/src/build')
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs158
-rw-r--r--compiler/rustc_mir_build/src/build/cfg.rs13
-rw-r--r--compiler/rustc_mir_build/src/build/custom/mod.rs17
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse.rs48
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs83
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs11
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs114
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs8
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs53
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs36
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs48
13 files changed, 324 insertions, 275 deletions
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index ab4cd2488..8cad6976c 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -13,42 +13,33 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ast_block: BlockId,
source_info: SourceInfo,
) -> BlockAnd<()> {
- let Block {
- region_scope,
- opt_destruction_scope,
- span,
- ref stmts,
- expr,
- targeted_by_break,
- safety_mode,
- } = self.thir[ast_block];
+ let Block { region_scope, span, ref stmts, expr, targeted_by_break, safety_mode } =
+ self.thir[ast_block];
let expr = expr.map(|expr| &self.thir[expr]);
- 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, span, |this| {
- Some(this.ast_block_stmts(
- destination,
- block,
- span,
- &stmts,
- expr,
- safety_mode,
- region_scope,
- ))
- })
- } else {
- this.ast_block_stmts(
+ self.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
+ if targeted_by_break {
+ this.in_breakable_scope(None, destination, span, |this| {
+ Some(this.ast_block_stmts(
destination,
block,
span,
- &stmts,
+ stmts,
expr,
safety_mode,
region_scope,
- )
- }
- })
+ ))
+ })
+ } else {
+ this.ast_block_stmts(
+ destination,
+ block,
+ span,
+ stmts,
+ expr,
+ safety_mode,
+ region_scope,
+ )
+ }
})
}
@@ -92,20 +83,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let source_info = this.source_info(span);
for stmt in stmts {
- let Stmt { ref kind, opt_destruction_scope } = this.thir[*stmt];
+ let Stmt { ref kind } = this.thir[*stmt];
match kind {
StmtKind::Expr { scope, expr } => {
this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
+ let si = (*scope, source_info);
unpack!(
- block = this.in_opt_scope(
- opt_destruction_scope.map(|de| (de, source_info)),
- |this| {
- let si = (*scope, source_info);
- this.in_scope(si, LintLevel::Inherited, |this| {
- this.stmt_expr(block, &this.thir[*expr], Some(*scope))
- })
- }
- )
+ block = this.in_scope(si, LintLevel::Inherited, |this| {
+ this.stmt_expr(block, &this.thir[*expr], Some(*scope))
+ })
);
}
StmtKind::Let {
@@ -221,43 +207,38 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let init = &this.thir[*initializer];
let initializer_span = init.span;
+ let scope = (*init_scope, source_info);
let failure = unpack!(
- block = this.in_opt_scope(
- opt_destruction_scope.map(|de| (de, source_info)),
- |this| {
- let scope = (*init_scope, source_info);
- this.in_scope(scope, *lint_level, |this| {
- this.declare_bindings(
- visibility_scope,
- remainder_span,
- pattern,
- None,
- Some((Some(&destination), initializer_span)),
- );
- this.visit_primary_bindings(
- pattern,
- UserTypeProjections::none(),
- &mut |this, _, _, _, node, span, _, _| {
- this.storage_live_binding(
- block,
- node,
- span,
- OutsideGuard,
- true,
- );
- },
- );
- this.ast_let_else(
+ block = this.in_scope(scope, *lint_level, |this| {
+ this.declare_bindings(
+ visibility_scope,
+ remainder_span,
+ pattern,
+ None,
+ Some((Some(&destination), initializer_span)),
+ );
+ this.visit_primary_bindings(
+ pattern,
+ UserTypeProjections::none(),
+ &mut |this, _, _, _, node, span, _, _| {
+ this.storage_live_binding(
block,
- init,
- initializer_span,
- *else_block,
- &last_remainder_scope,
- pattern,
- )
- })
- }
- )
+ node,
+ span,
+ OutsideGuard,
+ true,
+ );
+ },
+ );
+ this.ast_let_else(
+ block,
+ init,
+ initializer_span,
+ *else_block,
+ &last_remainder_scope,
+ pattern,
+ )
+ })
);
this.cfg.goto(failure, source_info, failure_entry);
@@ -298,25 +279,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
if let Some(init) = initializer {
let init = &this.thir[*init];
let initializer_span = init.span;
+ let scope = (*init_scope, source_info);
unpack!(
- block = this.in_opt_scope(
- opt_destruction_scope.map(|de| (de, source_info)),
- |this| {
- let scope = (*init_scope, source_info);
- this.in_scope(scope, *lint_level, |this| {
- this.declare_bindings(
- visibility_scope,
- remainder_span,
- pattern,
- None,
- Some((None, initializer_span)),
- );
- this.expr_into_pattern(block, &pattern, init)
- // irrefutable pattern
- })
- },
- )
+ block = this.in_scope(scope, *lint_level, |this| {
+ this.declare_bindings(
+ visibility_scope,
+ remainder_span,
+ pattern,
+ None,
+ Some((None, initializer_span)),
+ );
+ this.expr_into_pattern(block, &pattern, init)
+ // irrefutable pattern
+ })
)
} else {
let scope = (*init_scope, source_info);
diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs
index fddcf9de7..2bd0e2897 100644
--- a/compiler/rustc_mir_build/src/build/cfg.rs
+++ b/compiler/rustc_mir_build/src/build/cfg.rs
@@ -101,6 +101,19 @@ impl<'tcx> CFG<'tcx> {
self.push(block, stmt);
}
+ /// Adds a dummy statement whose only role is to associate a span with its
+ /// enclosing block for the purposes of coverage instrumentation.
+ ///
+ /// This results in more accurate coverage reports for certain kinds of
+ /// syntax (e.g. `continue` or `if !`) that would otherwise not appear in MIR.
+ pub(crate) fn push_coverage_span_marker(&mut self, block: BasicBlock, source_info: SourceInfo) {
+ let kind = StatementKind::Coverage(Box::new(Coverage {
+ kind: coverage::CoverageKind::SpanMarker,
+ }));
+ let stmt = Statement { source_info, kind };
+ self.push(block, stmt);
+ }
+
pub(crate) fn terminate(
&mut self,
block: BasicBlock,
diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs
index 3de2f45ad..ead20539e 100644
--- a/compiler/rustc_mir_build/src/build/custom/mod.rs
+++ b/compiler/rustc_mir_build/src/build/custom/mod.rs
@@ -88,11 +88,11 @@ pub(super) fn build_custom_mir<'tcx>(
};
let res: PResult<_> = try {
- pctxt.parse_args(&params)?;
+ pctxt.parse_args(params)?;
pctxt.parse_body(expr)?;
};
if let Err(err) = res {
- tcx.sess.diagnostic().span_fatal(
+ tcx.sess.dcx().span_fatal(
err.span,
format!("Could not parse {}, found: {:?}", err.expected, err.item_description),
)
@@ -162,6 +162,19 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
expected: expected.to_string(),
}
}
+
+ fn stmt_error(&self, stmt: StmtId, expected: &'static str) -> ParseError {
+ let stmt = &self.thir[stmt];
+ let span = match stmt.kind {
+ StmtKind::Expr { expr, .. } => self.thir[expr].span,
+ StmtKind::Let { span, .. } => span,
+ };
+ ParseError {
+ span,
+ item_description: format!("{:?}", stmt.kind),
+ expected: expected.to_string(),
+ }
+ }
}
type PResult<T> = Result<T, ParseError>;
diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs
index e2ab2cb90..a6f9caada 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse.rs
@@ -27,10 +27,13 @@ macro_rules! parse_by_kind {
$expr_name:pat,
$expected:literal,
$(
- @call($name:literal, $args:ident) => $call_expr:expr,
+ @call($name:ident, $args:ident) => $call_expr:expr,
)*
$(
- $pat:pat => $expr:expr,
+ @variant($adt:ident, $variant:ident) => $variant_expr:expr,
+ )*
+ $(
+ $pat:pat $(if $guard:expr)? => $expr:expr,
)*
) => {{
let expr_id = $self.preparse($expr_id);
@@ -42,14 +45,20 @@ macro_rules! parse_by_kind {
ExprKind::Call { ty, fun: _, args: $args, .. } if {
match ty.kind() {
ty::FnDef(did, _) => {
- $self.tcx.is_diagnostic_item(rustc_span::Symbol::intern($name), *did)
+ $self.tcx.is_diagnostic_item(rustc_span::sym::$name, *did)
}
_ => false,
}
} => $call_expr,
)*
$(
- $pat => $expr,
+ ExprKind::Adt(box AdtExpr { adt_def, variant_index, .. }) if {
+ $self.tcx.is_diagnostic_item(rustc_span::sym::$adt, adt_def.did()) &&
+ adt_def.variants()[*variant_index].name == rustc_span::sym::$variant
+ } => $variant_expr,
+ )*
+ $(
+ $pat $(if $guard)? => $expr,
)*
#[allow(unreachable_patterns)]
_ => return Err($self.expr_error(expr_id, $expected))
@@ -172,7 +181,8 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
ExprKind::Block { block } => &self.thir[*block].stmts,
);
for (i, block_def) in block_defs.iter().enumerate() {
- let block = self.parse_block_def(self.statement_as_expr(*block_def)?)?;
+ let is_cleanup = self.body.basic_blocks_mut()[BasicBlock::from_usize(i)].is_cleanup;
+ let block = self.parse_block_def(self.statement_as_expr(*block_def)?, is_cleanup)?;
self.body.basic_blocks_mut()[BasicBlock::from_usize(i)] = block;
}
@@ -181,15 +191,28 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
fn parse_block_decls(&mut self, stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
for stmt in stmts {
- let (var, _, _) = self.parse_let_statement(stmt)?;
- let data = BasicBlockData::new(None);
- let block = self.body.basic_blocks_mut().push(data);
- self.block_map.insert(var, block);
+ self.parse_basic_block_decl(stmt)?;
}
-
Ok(())
}
+ fn parse_basic_block_decl(&mut self, stmt: StmtId) -> PResult<()> {
+ match &self.thir[stmt].kind {
+ StmtKind::Let { pattern, initializer: Some(initializer), .. } => {
+ let (var, ..) = self.parse_var(pattern)?;
+ let mut data = BasicBlockData::new(None);
+ data.is_cleanup = parse_by_kind!(self, *initializer, _, "basic block declaration",
+ @variant(mir_basic_block, Normal) => false,
+ @variant(mir_basic_block, Cleanup) => true,
+ );
+ let block = self.body.basic_blocks_mut().push(data);
+ self.block_map.insert(var, block);
+ Ok(())
+ }
+ _ => Err(self.stmt_error(stmt, "let statement with an initializer")),
+ }
+ }
+
fn parse_local_decls(&mut self, mut stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
let (ret_var, ..) = self.parse_let_statement(stmts.next().unwrap())?;
self.local_map.insert(ret_var, Local::from_u32(0));
@@ -219,7 +242,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
};
let span = self.thir[expr].span;
let (name, operand) = parse_by_kind!(self, expr, _, "debuginfo",
- @call("mir_debuginfo", args) => {
+ @call(mir_debuginfo, args) => {
(args[0], args[1])
},
);
@@ -281,12 +304,13 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
}
}
- fn parse_block_def(&self, expr_id: ExprId) -> PResult<BasicBlockData<'tcx>> {
+ fn parse_block_def(&self, expr_id: ExprId, is_cleanup: bool) -> PResult<BasicBlockData<'tcx>> {
let block = parse_by_kind!(self, expr_id, _, "basic block",
ExprKind::Block { block } => &self.thir[*block],
);
let mut data = BasicBlockData::new(None);
+ data.is_cleanup = is_cleanup;
for stmt_id in &*block.stmts {
let stmt = self.statement_as_expr(*stmt_id)?;
let span = self.thir[stmt].span;
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index fd2c57a0a..4ce7f831c 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -13,19 +13,19 @@ use super::{parse_by_kind, PResult, ParseCtxt};
impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
pub fn parse_statement(&self, expr_id: ExprId) -> PResult<StatementKind<'tcx>> {
parse_by_kind!(self, expr_id, _, "statement",
- @call("mir_storage_live", args) => {
+ @call(mir_storage_live, args) => {
Ok(StatementKind::StorageLive(self.parse_local(args[0])?))
},
- @call("mir_storage_dead", args) => {
+ @call(mir_storage_dead, args) => {
Ok(StatementKind::StorageDead(self.parse_local(args[0])?))
},
- @call("mir_deinit", args) => {
+ @call(mir_deinit, args) => {
Ok(StatementKind::Deinit(Box::new(self.parse_place(args[0])?)))
},
- @call("mir_retag", args) => {
+ @call(mir_retag, args) => {
Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?)))
},
- @call("mir_set_discriminant", args) => {
+ @call(mir_set_discriminant, args) => {
let place = self.parse_place(args[0])?;
let var = self.parse_integer_literal(args[1])? as u32;
Ok(StatementKind::SetDiscriminant {
@@ -43,24 +43,30 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
pub fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind<'tcx>> {
parse_by_kind!(self, expr_id, expr, "terminator",
- @call("mir_return", _args) => {
+ @call(mir_return, _args) => {
Ok(TerminatorKind::Return)
},
- @call("mir_goto", args) => {
+ @call(mir_goto, args) => {
Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } )
},
- @call("mir_unreachable", _args) => {
+ @call(mir_unreachable, _args) => {
Ok(TerminatorKind::Unreachable)
},
- @call("mir_drop", args) => {
+ @call(mir_unwind_resume, _args) => {
+ Ok(TerminatorKind::UnwindResume)
+ },
+ @call(mir_unwind_terminate, args) => {
+ Ok(TerminatorKind::UnwindTerminate(self.parse_unwind_terminate_reason(args[0])?))
+ },
+ @call(mir_drop, args) => {
Ok(TerminatorKind::Drop {
place: self.parse_place(args[0])?,
target: self.parse_block(args[1])?,
- unwind: UnwindAction::Continue,
+ unwind: self.parse_unwind_action(args[2])?,
replace: false,
})
},
- @call("mir_call", args) => {
+ @call(mir_call, args) => {
self.parse_call(args)
},
ExprKind::Match { scrutinee, arms, .. } => {
@@ -70,6 +76,34 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
)
}
+ fn parse_unwind_terminate_reason(&self, expr_id: ExprId) -> PResult<UnwindTerminateReason> {
+ parse_by_kind!(self, expr_id, _, "unwind terminate reason",
+ @variant(mir_unwind_terminate_reason, Abi) => {
+ Ok(UnwindTerminateReason::Abi)
+ },
+ @variant(mir_unwind_terminate_reason, InCleanup) => {
+ Ok(UnwindTerminateReason::InCleanup)
+ },
+ )
+ }
+
+ fn parse_unwind_action(&self, expr_id: ExprId) -> PResult<UnwindAction> {
+ parse_by_kind!(self, expr_id, _, "unwind action",
+ @call(mir_unwind_continue, _args) => {
+ Ok(UnwindAction::Continue)
+ },
+ @call(mir_unwind_unreachable, _args) => {
+ Ok(UnwindAction::Unreachable)
+ },
+ @call(mir_unwind_terminate, args) => {
+ Ok(UnwindAction::Terminate(self.parse_unwind_terminate_reason(args[0])?))
+ },
+ @call(mir_unwind_cleanup, args) => {
+ Ok(UnwindAction::Cleanup(self.parse_block(args[0])?))
+ },
+ )
+ }
+
fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult<SwitchTargets> {
let Some((otherwise, rest)) = arms.split_last() else {
return Err(ParseError {
@@ -113,6 +147,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
);
let destination = self.parse_place(destination)?;
let target = self.parse_block(args[1])?;
+ let unwind = self.parse_unwind_action(args[2])?;
parse_by_kind!(self, call, _, "function call",
ExprKind::Call { fun, args, from_hir_call, fn_span, .. } => {
@@ -126,7 +161,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
args,
destination,
target: Some(target),
- unwind: UnwindAction::Continue,
+ unwind,
call_source: if *from_hir_call { CallSource::Normal } else {
CallSource::OverloadedOperator
},
@@ -138,25 +173,25 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
parse_by_kind!(self, expr_id, expr, "rvalue",
- @call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
- @call("mir_cast_transmute", args) => {
+ @call(mir_discriminant, args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
+ @call(mir_cast_transmute, args) => {
let source = self.parse_operand(args[0])?;
Ok(Rvalue::Cast(CastKind::Transmute, source, expr.ty))
},
- @call("mir_checked", args) => {
+ @call(mir_checked, args) => {
parse_by_kind!(self, args[0], _, "binary op",
ExprKind::Binary { op, lhs, rhs } => Ok(Rvalue::CheckedBinaryOp(
*op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?))
)),
)
},
- @call("mir_offset", args) => {
+ @call(mir_offset, args) => {
let ptr = self.parse_operand(args[0])?;
let offset = self.parse_operand(args[1])?;
Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset))))
},
- @call("mir_len", args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
- @call("mir_copy_for_deref", args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)),
+ @call(mir_len, args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
+ @call(mir_copy_for_deref, args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)),
ExprKind::Borrow { borrow_kind, arg } => Ok(
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
),
@@ -206,9 +241,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
pub fn parse_operand(&self, expr_id: ExprId) -> PResult<Operand<'tcx>> {
parse_by_kind!(self, expr_id, expr, "operand",
- @call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move),
- @call("mir_static", args) => self.parse_static(args[0]),
- @call("mir_static_mut", args) => self.parse_static(args[0]),
+ @call(mir_move, args) => self.parse_place(args[0]).map(Operand::Move),
+ @call(mir_static, args) => self.parse_static(args[0]),
+ @call(mir_static_mut, args) => self.parse_static(args[0]),
ExprKind::Literal { .. }
| ExprKind::NamedConst { .. }
| ExprKind::NonHirLiteral { .. }
@@ -229,7 +264,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
fn parse_place_inner(&self, expr_id: ExprId) -> PResult<(Place<'tcx>, PlaceTy<'tcx>)> {
let (parent, proj) = parse_by_kind!(self, expr_id, expr, "place",
- @call("mir_field", args) => {
+ @call(mir_field, args) => {
let (parent, ty) = self.parse_place_inner(args[0])?;
let field = FieldIdx::from_u32(self.parse_integer_literal(args[1])? as u32);
let field_ty = ty.field_ty(self.tcx, field);
@@ -237,7 +272,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
let place = parent.project_deeper(&[proj], self.tcx);
return Ok((place, PlaceTy::from_ty(field_ty)));
},
- @call("mir_variant", args) => {
+ @call(mir_variant, args) => {
(args[0], PlaceElem::Downcast(
None,
VariantIdx::from_u32(self.parse_integer_literal(args[1])? as u32)
@@ -245,7 +280,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
},
ExprKind::Deref { arg } => {
parse_by_kind!(self, *arg, _, "does not matter",
- @call("mir_make_place", args) => return self.parse_place_inner(args[0]),
+ @call(mir_make_place, args) => return self.parse_place_inner(args[0]),
_ => (*arg, PlaceElem::Deref),
)
},
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 4ed49e787..3bfffa735 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -114,7 +114,7 @@ fn lit_to_mir_constant<'tcx>(
let width = tcx
.layout_of(param_ty)
.map_err(|_| {
- LitToConstError::Reported(tcx.sess.delay_span_bug(
+ LitToConstError::Reported(tcx.sess.span_delayed_bug(
DUMMY_SP,
format!("couldn't compute width of literal: {:?}", lit_input.lit),
))
@@ -158,7 +158,7 @@ fn lit_to_mir_constant<'tcx>(
}
(ast::LitKind::Float(n, _), ty::Float(fty)) => parse_float_into_constval(*n, *fty, neg)
.ok_or_else(|| {
- LitToConstError::Reported(tcx.sess.delay_span_bug(
+ LitToConstError::Reported(tcx.sess.span_delayed_bug(
DUMMY_SP,
format!("couldn't parse float literal: {:?}", lit_input.lit),
))
@@ -167,7 +167,7 @@ fn lit_to_mir_constant<'tcx>(
(ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
(ast::LitKind::Err, _) => {
return Err(LitToConstError::Reported(
- tcx.sess.delay_span_bug(DUMMY_SP, "encountered LitKind::Err during mir build"),
+ tcx.sess.span_delayed_bug(DUMMY_SP, "encountered LitKind::Err during mir build"),
));
}
_ => return Err(LitToConstError::TypeError),
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 7e9191a37..43e834890 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -175,7 +175,7 @@ fn to_upvars_resolved_place_builder<'tcx>(
projection: &[PlaceElem<'tcx>],
) -> Option<PlaceBuilder<'tcx>> {
let Some((capture_index, capture)) =
- find_capture_matching_projections(&cx.upvars, var_hir_id, &projection)
+ find_capture_matching_projections(&cx.upvars, var_hir_id, projection)
else {
let closure_span = cx.tcx.def_span(closure_def_id);
if !enable_precise_capture(closure_span) {
@@ -683,7 +683,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fake_borrow_deref_ty);
let fake_borrow_temp =
self.local_decls.push(LocalDecl::new(fake_borrow_ty, expr_span));
- let projection = tcx.mk_place_elems(&base_place.projection);
+ let projection = tcx.mk_place_elems(base_place.projection);
self.cfg.push_assign(
block,
source_info,
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index eece8684e..a5f6bb12e 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -10,8 +10,6 @@ use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary};
use rustc_hir::lang_items::LangItem;
use rustc_middle::middle::region;
use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::mir::AssertKind;
-use rustc_middle::mir::Place;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
@@ -600,10 +598,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
BinOp::Shl | BinOp::Shr if self.check_overflow && ty.is_integral() => {
// For an unsigned RHS, the shift is in-range for `rhs < bits`.
// For a signed RHS, `IntToInt` cast to the equivalent unsigned
- // type and do that same comparison. Because the type is the
- // same size, there's no negative shift amount that ends up
- // overlapping with valid ones, thus it catches negatives too.
+ // type and do that same comparison.
+ // A negative value will be *at least* 128 after the cast (that's i8::MIN),
+ // and 128 is an overflowing shift amount for all our currently existing types,
+ // so this cast can never make us miss an overflow.
let (lhs_size, _) = ty.int_size_and_signed(self.tcx);
+ assert!(lhs_size.bits() <= 128);
let rhs_ty = rhs.ty(&self.local_decls, self.tcx);
let (rhs_size, _) = rhs_ty.int_size_and_signed(self.tcx);
@@ -625,7 +625,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// This can't overflow because the largest shiftable types are 128-bit,
// which fits in `u8`, the smallest possible `unsigned_ty`.
- // (And `from_uint` will `bug!` if that's ever no longer true.)
let lhs_bits = Operand::const_from_scalar(
self.tcx,
unsigned_ty,
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 304870274..487b1f44b 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -90,6 +90,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let local_scope = this.local_scope();
let (success_block, failure_block) =
this.in_if_then_scope(local_scope, expr_span, |this| {
+ // Help out coverage instrumentation by injecting a dummy statement with
+ // the original condition's span (including `!`). This fixes #115468.
+ if this.tcx.sess.instrument_coverage() {
+ this.cfg.push_coverage_span_marker(block, this.source_info(expr_span));
+ }
this.then_else_break(
block,
&this.thir[arg],
@@ -212,7 +217,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let scrutinee_place =
unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,));
- let mut arm_candidates = self.create_match_candidates(&scrutinee_place, &arms);
+ let mut arm_candidates = self.create_match_candidates(&scrutinee_place, arms);
let match_has_guard = arm_candidates.iter().any(|(_, candidate)| candidate.has_guard);
let mut candidates =
@@ -424,7 +429,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.source_scope = source_scope;
}
- this.expr_into_dest(destination, arm_block, &&this.thir[arm.body])
+ this.expr_into_dest(destination, arm_block, &this.thir[arm.body])
})
})
.collect();
@@ -505,7 +510,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let binding_end = self.bind_and_guard_matched_candidate(
leaf_candidate,
parent_bindings,
- &fake_borrow_temps,
+ fake_borrow_temps,
scrutinee_span,
arm_match_scope,
schedule_drops,
@@ -613,7 +618,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
_ => {
let place_builder =
unpack!(block = self.lower_scrutinee(block, initializer, initializer.span));
- self.place_into_pattern(block, &irrefutable_pat, place_builder, true)
+ self.place_into_pattern(block, irrefutable_pat, place_builder, true)
}
}
}
@@ -625,7 +630,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
initializer: PlaceBuilder<'tcx>,
set_match_place: bool,
) -> BlockAnd<()> {
- let mut candidate = Candidate::new(initializer.clone(), &irrefutable_pat, false, self);
+ let mut candidate = Candidate::new(initializer.clone(), irrefutable_pat, false, self);
let fake_borrow_temps = self.lower_match_tree(
block,
irrefutable_pat.span,
@@ -700,7 +705,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
) -> Option<SourceScope> {
self.visit_primary_bindings(
- &pattern,
+ pattern,
UserTypeProjections::none(),
&mut |this, mutability, name, mode, var, span, ty, user_ty| {
if visibility_scope.is_none() {
@@ -827,6 +832,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
PatKind::Constant { .. }
| PatKind::Range { .. }
| PatKind::Wild
+ | PatKind::Never
| PatKind::Error(_) => {}
PatKind::Deref { ref subpattern } => {
@@ -1693,59 +1699,51 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
debug!("tested_candidates: {}", total_candidate_count - candidates.len());
debug!("untested_candidates: {}", candidates.len());
- // HACK(matthewjasper) This is a closure so that we can let the test
- // create its blocks before the rest of the match. This currently
- // improves the speed of llvm when optimizing long string literal
- // matches
- let make_target_blocks = move |this: &mut Self| -> Vec<BasicBlock> {
- // The block that we should branch to if none of the
- // `target_candidates` match. This is either the block where we
- // start matching the untested candidates if there are any,
- // otherwise it's the `otherwise_block`.
- let remainder_start = &mut None;
- let remainder_start =
- if candidates.is_empty() { &mut *otherwise_block } else { remainder_start };
-
- // For each outcome of test, process the candidates that still
- // apply. Collect a list of blocks where control flow will
- // branch if one of the `target_candidate` sets is not
- // exhaustive.
- let target_blocks: Vec<_> = target_candidates
- .into_iter()
- .map(|mut candidates| {
- if !candidates.is_empty() {
- let candidate_start = this.cfg.start_new_block();
- this.match_candidates(
- span,
- scrutinee_span,
- candidate_start,
- remainder_start,
- &mut *candidates,
- fake_borrows,
- );
- candidate_start
- } else {
- *remainder_start.get_or_insert_with(|| this.cfg.start_new_block())
- }
- })
- .collect();
-
- if !candidates.is_empty() {
- let remainder_start = remainder_start.unwrap_or_else(|| this.cfg.start_new_block());
- this.match_candidates(
- span,
- scrutinee_span,
- remainder_start,
- otherwise_block,
- candidates,
- fake_borrows,
- );
- };
+ // The block that we should branch to if none of the
+ // `target_candidates` match. This is either the block where we
+ // start matching the untested candidates if there are any,
+ // otherwise it's the `otherwise_block`.
+ let remainder_start = &mut None;
+ let remainder_start =
+ if candidates.is_empty() { &mut *otherwise_block } else { remainder_start };
+
+ // For each outcome of test, process the candidates that still
+ // apply. Collect a list of blocks where control flow will
+ // branch if one of the `target_candidate` sets is not
+ // exhaustive.
+ let target_blocks: Vec<_> = target_candidates
+ .into_iter()
+ .map(|mut candidates| {
+ if !candidates.is_empty() {
+ let candidate_start = self.cfg.start_new_block();
+ self.match_candidates(
+ span,
+ scrutinee_span,
+ candidate_start,
+ remainder_start,
+ &mut *candidates,
+ fake_borrows,
+ );
+ candidate_start
+ } else {
+ *remainder_start.get_or_insert_with(|| self.cfg.start_new_block())
+ }
+ })
+ .collect();
- target_blocks
- };
+ if !candidates.is_empty() {
+ let remainder_start = remainder_start.unwrap_or_else(|| self.cfg.start_new_block());
+ self.match_candidates(
+ span,
+ scrutinee_span,
+ remainder_start,
+ otherwise_block,
+ candidates,
+ fake_borrows,
+ );
+ }
- self.perform_test(span, scrutinee_span, block, &match_place, &test, make_target_blocks);
+ self.perform_test(span, scrutinee_span, block, &match_place, &test, target_blocks);
}
/// Determine the fake borrows that are needed from a set of places that
@@ -1843,7 +1841,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let expr_span = expr.span;
let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span));
let wildcard = Pat::wildcard_from_ty(pat.ty);
- let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false, self);
+ let mut guard_candidate = Candidate::new(expr_place_builder.clone(), pat, false, self);
let mut otherwise_candidate =
Candidate::new(expr_place_builder.clone(), &wildcard, false, self);
let fake_borrow_temps = self.lower_match_tree(
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index 6a40c8d84..a7f6f4873 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -69,7 +69,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
{
existing_bindings.extend_from_slice(&new_bindings);
mem::swap(&mut candidate.bindings, &mut existing_bindings);
- candidate.subcandidates = self.create_or_subcandidates(candidate, &place, pats);
+ candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats);
return true;
}
@@ -194,6 +194,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Ok(())
}
+ PatKind::Never => {
+ // A never pattern acts like a load from the place.
+ // FIXME(never_patterns): load from the place
+ Ok(())
+ }
+
PatKind::Constant { .. } => {
// FIXME normalize patterns when possible
Err(match_pair)
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index bdd4f2011..53e5d70f9 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -75,6 +75,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| PatKind::Array { .. }
| PatKind::Wild
| PatKind::Binding { .. }
+ | PatKind::Never
| PatKind::Leaf { .. }
| PatKind::Deref { .. }
| PatKind::Error(_) => self.error_simplifiable(match_pair),
@@ -107,6 +108,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
PatKind::Slice { .. }
| PatKind::Array { .. }
| PatKind::Wild
+ | PatKind::Never
| PatKind::Or { .. }
| PatKind::Binding { .. }
| PatKind::AscribeUserType { .. }
@@ -145,7 +147,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}
- #[instrument(skip(self, make_target_blocks, place_builder), level = "debug")]
+ #[instrument(skip(self, target_blocks, place_builder), level = "debug")]
pub(super) fn perform_test(
&mut self,
match_start_span: Span,
@@ -153,7 +155,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block: BasicBlock,
place_builder: &PlaceBuilder<'tcx>,
test: &Test<'tcx>,
- make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
+ target_blocks: Vec<BasicBlock>,
) {
let place = place_builder.to_place(self);
let place_ty = place.ty(&self.local_decls, self.tcx);
@@ -162,7 +164,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let source_info = self.source_info(test.span);
match test.kind {
TestKind::Switch { adt_def, ref variants } => {
- let target_blocks = make_target_blocks(self);
// Variants is a BitVec of indexes into adt_def.variants.
let num_enum_variants = adt_def.variants().len();
debug_assert_eq!(target_blocks.len(), num_enum_variants + 1);
@@ -208,7 +209,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
TestKind::SwitchInt { switch_ty, ref options } => {
- let target_blocks = make_target_blocks(self);
let terminator = if *switch_ty.kind() == ty::Bool {
assert!(!options.is_empty() && options.len() <= 2);
let [first_bb, second_bb] = *target_blocks else {
@@ -238,6 +238,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
TestKind::Eq { value, ty } => {
let tcx = self.tcx;
+ let [success_block, fail_block] = *target_blocks else {
+ bug!("`TestKind::Eq` should have two target blocks")
+ };
if let ty::Adt(def, _) = ty.kind()
&& Some(def.did()) == tcx.lang_items().string()
{
@@ -278,38 +281,43 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
);
self.non_scalar_compare(
eq_block,
- make_target_blocks,
+ success_block,
+ fail_block,
source_info,
value,
ref_str,
ref_str_ty,
);
- return;
- }
- if !ty.is_scalar() {
+ } else if !ty.is_scalar() {
// Use `PartialEq::eq` instead of `BinOp::Eq`
// (the binop can only handle primitives)
self.non_scalar_compare(
block,
- make_target_blocks,
+ success_block,
+ fail_block,
source_info,
value,
place,
ty,
);
- } else if let [success, fail] = *make_target_blocks(self) {
+ } else {
assert_eq!(value.ty(), ty);
let expect = self.literal_operand(test.span, value);
let val = Operand::Copy(place);
- self.compare(block, success, fail, source_info, BinOp::Eq, expect, val);
- } else {
- bug!("`TestKind::Eq` should have two target blocks");
+ self.compare(
+ block,
+ success_block,
+ fail_block,
+ source_info,
+ BinOp::Eq,
+ expect,
+ val,
+ );
}
}
TestKind::Range(ref range) => {
let lower_bound_success = self.cfg.start_new_block();
- let target_blocks = make_target_blocks(self);
// Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
// FIXME: skip useless comparison when the range is half-open.
@@ -339,8 +347,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
TestKind::Len { len, op } => {
- let target_blocks = make_target_blocks(self);
-
let usize_ty = self.tcx.types.usize;
let actual = self.temp(usize_ty, test.span);
@@ -404,7 +410,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn non_scalar_compare(
&mut self,
block: BasicBlock,
- make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
+ success_block: BasicBlock,
+ fail_block: BasicBlock,
source_info: SourceInfo,
value: Const<'tcx>,
mut val: Place<'tcx>,
@@ -494,7 +501,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span));
- let method = trait_method(self.tcx, eq_def_id, sym::eq, [ty, ty]);
+ let method = trait_method(
+ self.tcx,
+ eq_def_id,
+ sym::eq,
+ self.tcx.with_opt_host_effect_param(self.def_id, eq_def_id, [ty, ty]),
+ );
let bool_ty = self.tcx.types.bool;
let eq_result = self.temp(bool_ty, source_info.span);
@@ -524,9 +536,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
);
self.diverge_from(block);
- let [success_block, fail_block] = *make_target_blocks(self) else {
- bug!("`TestKind::Eq` should have two target blocks")
- };
// check the result
self.cfg.terminate(
eq_block,
@@ -736,7 +745,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// These are all binary tests.
//
// FIXME(#29623) we can be more clever here
- let pattern_test = self.test(&match_pair);
+ let pattern_test = self.test(match_pair);
if pattern_test.kind == test.kind {
self.candidate_without_match_pair(match_pair_index, candidate);
Some(0)
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 886d80545..dae83d4b4 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -451,7 +451,7 @@ fn construct_fn<'tcx>(
fn_sig: ty::FnSig<'tcx>,
) -> Body<'tcx> {
let span = tcx.def_span(fn_def);
- let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def);
+ let fn_id = tcx.local_def_id_to_hir_id(fn_def);
let coroutine_kind = tcx.coroutine_kind(fn_def);
// The representation of thir for `-Zunpretty=thir-tree` relies on
@@ -569,10 +569,10 @@ fn construct_const<'a, 'tcx>(
expr: ExprId,
const_ty: Ty<'tcx>,
) -> Body<'tcx> {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def);
+ let hir_id = tcx.local_def_id_to_hir_id(def);
// Figure out what primary body this item has.
- let (span, const_ty_span) = match tcx.hir().get(hir_id) {
+ let (span, const_ty_span) = match tcx.hir_node(hir_id) {
Node::Item(hir::Item {
kind: hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _, _),
span,
@@ -622,7 +622,7 @@ fn construct_const<'a, 'tcx>(
/// with type errors, but normal MIR construction can't handle that in general.
fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -> Body<'_> {
let span = tcx.def_span(def_id);
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let hir_id = tcx.local_def_id_to_hir_id(def_id);
let coroutine_kind = tcx.coroutine_kind(def_id);
let (inputs, output, yield_ty) = match tcx.def_kind(def_id) {
@@ -638,9 +638,21 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -
);
(sig.inputs().to_vec(), sig.output(), None)
}
+ DefKind::Closure if coroutine_kind.is_some() => {
+ let coroutine_ty = tcx.type_of(def_id).instantiate_identity();
+ let ty::Coroutine(_, args, _) = coroutine_ty.kind() else {
+ bug!("expected type of coroutine-like closure to be a coroutine")
+ };
+ let args = args.as_coroutine();
+ let yield_ty = args.yield_ty();
+ let return_ty = args.return_ty();
+ (vec![coroutine_ty, args.resume_ty()], return_ty, Some(yield_ty))
+ }
DefKind::Closure => {
let closure_ty = tcx.type_of(def_id).instantiate_identity();
- let ty::Closure(_, args) = closure_ty.kind() else { bug!() };
+ let ty::Closure(_, args) = closure_ty.kind() else {
+ bug!("expected type of closure to be a closure")
+ };
let args = args.as_closure();
let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), args.sig());
let self_ty = match args.kind() {
@@ -650,14 +662,6 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -
};
([self_ty].into_iter().chain(sig.inputs().to_vec()).collect(), sig.output(), None)
}
- DefKind::Coroutine => {
- let coroutine_ty = tcx.type_of(def_id).instantiate_identity();
- let ty::Coroutine(_, args, _) = coroutine_ty.kind() else { bug!() };
- let args = args.as_coroutine();
- let yield_ty = args.yield_ty();
- let return_ty = args.return_ty();
- (vec![coroutine_ty, args.resume_ty()], return_ty, Some(yield_ty))
- }
dk => bug!("{:?} is not a body: {:?}", def_id, dk),
};
@@ -938,12 +942,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
scope = self.declare_bindings(
scope,
expr.span,
- &pat,
+ pat,
None,
Some((Some(&place), span)),
);
let place_builder = PlaceBuilder::from(local);
- unpack!(block = self.place_into_pattern(block, &pat, place_builder, false));
+ unpack!(block = self.place_into_pattern(block, pat, place_builder, false));
}
}
self.source_scope = original_source_scope;
@@ -954,7 +958,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.source_scope = source_scope;
}
- self.expr_into_dest(Place::return_place(), block, &expr)
+ self.expr_into_dest(Place::return_place(), block, expr)
}
fn set_correct_source_scope_for_arg(
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index b3d3863b5..25b79e6a5 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -90,7 +90,6 @@ use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::middle::region;
use rustc_middle::mir::*;
use rustc_middle::thir::{Expr, LintLevel};
-use rustc_middle::ty::Ty;
use rustc_session::lint::Level;
use rustc_span::{Span, DUMMY_SP};
@@ -186,6 +185,7 @@ pub(crate) enum BreakableTarget {
}
rustc_index::newtype_index! {
+ #[orderable]
struct DropIdx {}
}
@@ -536,27 +536,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
(then_block, else_block)
}
- pub(crate) fn in_opt_scope<F, R>(
- &mut self,
- opt_scope: Option<(region::Scope, SourceInfo)>,
- f: F,
- ) -> BlockAnd<R>
- where
- F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>,
- {
- debug!("in_opt_scope(opt_scope={:?})", opt_scope);
- if let Some(region_scope) = opt_scope {
- self.push_scope(region_scope);
- }
- let mut block;
- let rv = unpack!(block = f(self));
- if let Some(region_scope) = opt_scope {
- unpack!(block = self.pop_scope(region_scope, block));
- }
- debug!("in_scope: exiting opt_scope={:?} block={:?}", opt_scope, block);
- block.and(rv)
- }
-
/// Convenience wrapper that pushes a scope and then executes `f`
/// to build its contents, popping the scope afterwards.
#[instrument(skip(self, f), level = "debug")]
@@ -659,14 +638,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
(None, Some(_)) => {
panic!("`return`, `become` and `break` with value and must have a destination")
}
- (None, None) if self.tcx.sess.instrument_coverage() => {
- // Unlike `break` and `return`, which push an `Assign` statement to MIR, from which
- // a Coverage code region can be generated, `continue` needs no `Assign`; but
- // without one, the `InstrumentCoverage` MIR pass cannot generate a code region for
- // `continue`. Coverage will be missing unless we add a dummy `Assign` to MIR.
- self.add_dummy_assignment(span, block, source_info);
+ (None, None) => {
+ if self.tcx.sess.instrument_coverage() {
+ // Normally we wouldn't build any MIR in this case, but that makes it
+ // harder for coverage instrumentation to extract a relevant span for
+ // `continue` expressions. So here we inject a dummy statement with the
+ // desired span.
+ self.cfg.push_coverage_span_marker(block, source_info);
+ }
}
- (None, None) => {}
}
let region_scope = self.scopes.breakable_scopes[break_index].region_scope;
@@ -722,14 +702,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.cfg.terminate(block, source_info, TerminatorKind::UnwindResume);
}
- // Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue`
- // statement.
- fn add_dummy_assignment(&mut self, span: Span, block: BasicBlock, source_info: SourceInfo) {
- let local_decl = LocalDecl::new(Ty::new_unit(self.tcx), span);
- let temp_place = Place::from(self.local_decls.push(local_decl));
- self.cfg.push_assign_unit(block, source_info, temp_place, self.tcx);
- }
-
fn leave_top_scope(&mut self, block: BasicBlock) -> BasicBlock {
// If we are emitting a `drop` statement, we need to have the cached
// diverge cleanup pads ready in case that drop panics.
@@ -995,7 +967,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
if scope.region_scope == region_scope {
- let region_scope_span = region_scope.span(self.tcx, &self.region_scope_tree);
+ let region_scope_span = region_scope.span(self.tcx, self.region_scope_tree);
// Attribute scope exit drops to scope's closing brace.
let scope_end = self.tcx.sess.source_map().end_point(region_scope_span);