From 9918693037dce8aa4bb6f08741b6812923486c18 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 19 Jun 2024 11:26:03 +0200 Subject: Merging upstream version 1.76.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_mir_build/src/build/block.rs | 158 +++++++++------------ compiler/rustc_mir_build/src/build/cfg.rs | 13 ++ compiler/rustc_mir_build/src/build/custom/mod.rs | 17 ++- compiler/rustc_mir_build/src/build/custom/parse.rs | 48 +++++-- .../src/build/custom/parse/instruction.rs | 83 +++++++---- .../rustc_mir_build/src/build/expr/as_constant.rs | 6 +- .../rustc_mir_build/src/build/expr/as_place.rs | 4 +- .../rustc_mir_build/src/build/expr/as_rvalue.rs | 11 +- compiler/rustc_mir_build/src/build/matches/mod.rs | 114 ++++++++------- .../rustc_mir_build/src/build/matches/simplify.rs | 8 +- compiler/rustc_mir_build/src/build/matches/test.rs | 53 ++++--- compiler/rustc_mir_build/src/build/mod.rs | 36 ++--- compiler/rustc_mir_build/src/build/scope.rs | 48 ++----- 13 files changed, 324 insertions(+), 275 deletions(-) (limited to 'compiler/rustc_mir_build/src/build') 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(¶ms)?; + 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 = Result; 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) -> 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) -> 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> { + fn parse_block_def(&self, expr_id: ExprId, is_cleanup: bool) -> PResult> { 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> { 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> { 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 { + 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 { + 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 { 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> { 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> { 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> { 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 { 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 { - // 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, + target_blocks: Vec, ) { 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, + 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( - &mut self, - opt_scope: Option<(region::Scope, SourceInfo)>, - f: F, - ) -> BlockAnd - where - F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd, - { - 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); -- cgit v1.2.3