Skip to content

Commit fb79597

Browse files
authored
Rollup merge of #87832 - wesleywiser:fix_match_step, r=davidtwco
Fix debugger stepping behavior with `match` expressions Previously, we would set up the source lines for `match` expressions so that the code generated to perform the test of the scrutinee was matched to the line of the arm that required the test and then jump from the arm block to the "next" block was matched to all of the lines in the `match` expression. While that makes sense, it has the side effect of causing strange stepping behavior in debuggers. I've changed the source information so that all of the generated tests are sourced to `match {scrutinee}` and the jumps are sourced to the last line of the block they are inside. This resolves the weird stepping behavior in all debuggers and resolves some instances of "ambiguous symbol" errors in WinDbg preventing the user from setting breakpoints at `match` expressions. Before: https://user-images.githubusercontent.com/831192/128577421-ee0c9c03-da28-4d16-997a-d57988a7bb7f.mp4 After: https://user-images.githubusercontent.com/831192/128577433-2ceab04d-953e-4e31-9387-93f049c71ff3.mp4 Fixes #87817
2 parents 4b9f4b2 + 84a2661 commit fb79597

File tree

93 files changed

+916
-482
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+916
-482
lines changed

compiler/rustc_mir_build/src/build/matches/mod.rs

+54-9
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc_middle::mir::*;
2121
use rustc_middle::thir::{self, *};
2222
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
2323
use rustc_span::symbol::Symbol;
24-
use rustc_span::Span;
24+
use rustc_span::{BytePos, Pos, Span};
2525
use rustc_target::abi::VariantIdx;
2626
use smallvec::{smallvec, SmallVec};
2727

@@ -143,8 +143,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
143143
let mut candidates =
144144
arm_candidates.iter_mut().map(|(_, candidate)| candidate).collect::<Vec<_>>();
145145

146-
let fake_borrow_temps =
147-
self.lower_match_tree(block, scrutinee_span, match_has_guard, &mut candidates);
146+
let match_start_span = span.shrink_to_lo().to(scrutinee.span);
147+
148+
let fake_borrow_temps = self.lower_match_tree(
149+
block,
150+
scrutinee_span,
151+
match_start_span,
152+
match_has_guard,
153+
&mut candidates,
154+
);
148155

149156
self.lower_match_arms(
150157
destination,
@@ -224,6 +231,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
224231
&mut self,
225232
block: BasicBlock,
226233
scrutinee_span: Span,
234+
match_start_span: Span,
227235
match_has_guard: bool,
228236
candidates: &mut [&mut Candidate<'pat, 'tcx>],
229237
) -> Vec<(Place<'tcx>, Local)> {
@@ -236,7 +244,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
236244

237245
// This will generate code to test scrutinee_place and
238246
// branch to the appropriate arm block
239-
self.match_candidates(scrutinee_span, block, &mut otherwise, candidates, &mut fake_borrows);
247+
self.match_candidates(
248+
match_start_span,
249+
scrutinee_span,
250+
block,
251+
&mut otherwise,
252+
candidates,
253+
&mut fake_borrows,
254+
);
240255

241256
if let Some(otherwise_block) = otherwise {
242257
// See the doc comment on `match_candidates` for why we may have an
@@ -339,8 +354,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
339354
// all the arm blocks will rejoin here
340355
let end_block = self.cfg.start_new_block();
341356

357+
let end_brace = self.source_info(
358+
outer_source_info.span.with_lo(outer_source_info.span.hi() - BytePos::from_usize(1)),
359+
);
342360
for arm_block in arm_end_blocks {
343-
self.cfg.goto(unpack!(arm_block), outer_source_info, end_block);
361+
let block = &self.cfg.basic_blocks[arm_block.0];
362+
let last_location = block.statements.last().map(|s| s.source_info);
363+
364+
self.cfg.goto(unpack!(arm_block), last_location.unwrap_or(end_brace), end_block);
344365
}
345366

346367
self.source_scope = outer_source_info.scope;
@@ -533,8 +554,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
533554
set_match_place: bool,
534555
) -> BlockAnd<()> {
535556
let mut candidate = Candidate::new(initializer.clone(), &irrefutable_pat, false);
536-
let fake_borrow_temps =
537-
self.lower_match_tree(block, irrefutable_pat.span, false, &mut [&mut candidate]);
557+
let fake_borrow_temps = self.lower_match_tree(
558+
block,
559+
irrefutable_pat.span,
560+
irrefutable_pat.span,
561+
false,
562+
&mut [&mut candidate],
563+
);
538564
// For matches and function arguments, the place that is being matched
539565
// can be set when creating the variables. But the place for
540566
// let PATTERN = ... might not even exist until we do the assignment.
@@ -993,6 +1019,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
9931019
fn match_candidates<'pat>(
9941020
&mut self,
9951021
span: Span,
1022+
scrutinee_span: Span,
9961023
start_block: BasicBlock,
9971024
otherwise_block: &mut Option<BasicBlock>,
9981025
candidates: &mut [&mut Candidate<'pat, 'tcx>],
@@ -1022,6 +1049,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10221049
}
10231050
self.match_simplified_candidates(
10241051
span,
1052+
scrutinee_span,
10251053
start_block,
10261054
otherwise_block,
10271055
&mut *new_candidates,
@@ -1030,6 +1058,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10301058
} else {
10311059
self.match_simplified_candidates(
10321060
span,
1061+
scrutinee_span,
10331062
start_block,
10341063
otherwise_block,
10351064
candidates,
@@ -1042,6 +1071,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10421071
fn match_simplified_candidates(
10431072
&mut self,
10441073
span: Span,
1074+
scrutinee_span: Span,
10451075
start_block: BasicBlock,
10461076
otherwise_block: &mut Option<BasicBlock>,
10471077
candidates: &mut [&mut Candidate<'_, 'tcx>],
@@ -1087,6 +1117,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10871117
// Test for the remaining candidates.
10881118
self.test_candidates_with_or(
10891119
span,
1120+
scrutinee_span,
10901121
unmatched_candidates,
10911122
block,
10921123
otherwise_block,
@@ -1257,6 +1288,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12571288
fn test_candidates_with_or(
12581289
&mut self,
12591290
span: Span,
1291+
scrutinee_span: Span,
12601292
candidates: &mut [&mut Candidate<'_, 'tcx>],
12611293
block: BasicBlock,
12621294
otherwise_block: &mut Option<BasicBlock>,
@@ -1269,7 +1301,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12691301
match *first_candidate.match_pairs[0].pattern.kind {
12701302
PatKind::Or { .. } => (),
12711303
_ => {
1272-
self.test_candidates(span, candidates, block, otherwise_block, fake_borrows);
1304+
self.test_candidates(
1305+
span,
1306+
scrutinee_span,
1307+
candidates,
1308+
block,
1309+
otherwise_block,
1310+
fake_borrows,
1311+
);
12731312
return;
12741313
}
12751314
}
@@ -1302,6 +1341,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13021341

13031342
self.match_candidates(
13041343
span,
1344+
scrutinee_span,
13051345
remainder_start,
13061346
otherwise_block,
13071347
remaining_candidates,
@@ -1330,6 +1370,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13301370
otherwise
13311371
};
13321372
self.match_candidates(
1373+
or_span,
13331374
or_span,
13341375
candidate.pre_binding_block.unwrap(),
13351376
otherwise,
@@ -1497,6 +1538,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14971538
fn test_candidates<'pat, 'b, 'c>(
14981539
&mut self,
14991540
span: Span,
1541+
scrutinee_span: Span,
15001542
mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
15011543
block: BasicBlock,
15021544
otherwise_block: &mut Option<BasicBlock>,
@@ -1591,6 +1633,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15911633
let candidate_start = this.cfg.start_new_block();
15921634
this.match_candidates(
15931635
span,
1636+
scrutinee_span,
15941637
candidate_start,
15951638
remainder_start,
15961639
&mut *candidates,
@@ -1607,6 +1650,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16071650
let remainder_start = remainder_start.unwrap_or_else(|| this.cfg.start_new_block());
16081651
this.match_candidates(
16091652
span,
1653+
scrutinee_span,
16101654
remainder_start,
16111655
otherwise_block,
16121656
candidates,
@@ -1617,7 +1661,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16171661
target_blocks
16181662
};
16191663

1620-
self.perform_test(block, match_place, &test, make_target_blocks);
1664+
self.perform_test(span, scrutinee_span, block, match_place, &test, make_target_blocks);
16211665
}
16221666

16231667
/// Determine the fake borrows that are needed from a set of places that
@@ -1713,6 +1757,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17131757
let fake_borrow_temps = self.lower_match_tree(
17141758
block,
17151759
pat.span,
1760+
pat.span,
17161761
false,
17171762
&mut [&mut guard_candidate, &mut otherwise_candidate],
17181763
);

compiler/rustc_mir_build/src/build/matches/test.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use rustc_middle::ty::util::IntTypeExt;
1919
use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
2020
use rustc_span::def_id::DefId;
2121
use rustc_span::symbol::{sym, Symbol};
22+
use rustc_span::Span;
2223
use rustc_target::abi::VariantIdx;
2324

2425
use std::cmp::Ordering;
@@ -151,6 +152,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
151152

152153
pub(super) fn perform_test(
153154
&mut self,
155+
match_start_span: Span,
156+
scrutinee_span: Span,
154157
block: BasicBlock,
155158
place_builder: PlaceBuilder<'tcx>,
156159
test: &Test<'tcx>,
@@ -206,10 +209,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
206209
debug!("num_enum_variants: {}, variants: {:?}", num_enum_variants, variants);
207210
let discr_ty = adt_def.repr.discr_type().to_ty(tcx);
208211
let discr = self.temp(discr_ty, test.span);
209-
self.cfg.push_assign(block, source_info, discr, Rvalue::Discriminant(place));
212+
self.cfg.push_assign(
213+
block,
214+
self.source_info(scrutinee_span),
215+
discr,
216+
Rvalue::Discriminant(place),
217+
);
210218
self.cfg.terminate(
211219
block,
212-
source_info,
220+
self.source_info(match_start_span),
213221
TerminatorKind::SwitchInt {
214222
discr: Operand::Move(discr),
215223
switch_ty: discr_ty,
@@ -246,7 +254,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
246254
targets: switch_targets,
247255
}
248256
};
249-
self.cfg.terminate(block, source_info, terminator);
257+
self.cfg.terminate(block, self.source_info(match_start_span), terminator);
250258
}
251259

252260
TestKind::Eq { value, ty } => {

0 commit comments

Comments
 (0)