Skip to content

Commit 93edb7c

Browse files
debuginfo: Fix problem with debug locations of constants in match patterns.
1 parent 0eec226 commit 93edb7c

File tree

4 files changed

+189
-30
lines changed

4 files changed

+189
-30
lines changed

src/librustc/middle/check_match.rs

+53-12
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ use std::iter::{range_inclusive, AdditiveIterator, FromIterator, repeat};
2828
use std::num::Float;
2929
use std::slice;
3030
use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat};
31-
use syntax::ast_util::walk_pat;
31+
use syntax::ast_util;
3232
use syntax::codemap::{Span, Spanned, DUMMY_SP};
3333
use syntax::fold::{Folder, noop_fold_pat};
3434
use syntax::print::pprust::pat_to_string;
3535
use syntax::parse::token;
3636
use syntax::ptr::P;
3737
use syntax::visit::{self, Visitor, FnKind};
3838
use util::ppaux::ty_to_string;
39+
use util::nodemap::FnvHashMap;
3940

4041
pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
4142
id: DUMMY_NODE_ID,
@@ -171,7 +172,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
171172
}
172173
}
173174

174-
let mut static_inliner = StaticInliner::new(cx.tcx);
175+
let mut static_inliner = StaticInliner::new(cx.tcx, None);
175176
let inlined_arms = arms.iter().map(|arm| {
176177
(arm.pats.iter().map(|pat| {
177178
static_inliner.fold_pat((*pat).clone())
@@ -235,7 +236,7 @@ fn is_expr_const_nan(tcx: &ty::ctxt, expr: &ast::Expr) -> bool {
235236
}
236237

237238
fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) {
238-
walk_pat(pat, |p| {
239+
ast_util::walk_pat(pat, |p| {
239240
match p.node {
240241
ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => {
241242
let pat_ty = ty::pat_ty(cx.tcx, p);
@@ -266,7 +267,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
266267

267268
// Check that we do not match against a static NaN (#6804)
268269
fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
269-
walk_pat(pat, |p| {
270+
ast_util::walk_pat(pat, |p| {
270271
match p.node {
271272
ast::PatLit(ref expr) if is_expr_const_nan(cx.tcx, &**expr) => {
272273
span_warn!(cx.tcx.sess, p.span, E0003,
@@ -399,28 +400,50 @@ fn const_val_to_expr(value: &const_val) -> P<ast::Expr> {
399400

400401
pub struct StaticInliner<'a, 'tcx: 'a> {
401402
pub tcx: &'a ty::ctxt<'tcx>,
402-
pub failed: bool
403+
pub failed: bool,
404+
pub renaming_map: Option<&'a mut FnvHashMap<(NodeId, Span), NodeId>>,
403405
}
404406

405407
impl<'a, 'tcx> StaticInliner<'a, 'tcx> {
406-
pub fn new<'b>(tcx: &'b ty::ctxt<'tcx>) -> StaticInliner<'b, 'tcx> {
408+
pub fn new<'b>(tcx: &'b ty::ctxt<'tcx>,
409+
renaming_map: Option<&'b mut FnvHashMap<(NodeId, Span), NodeId>>)
410+
-> StaticInliner<'b, 'tcx> {
407411
StaticInliner {
408412
tcx: tcx,
409-
failed: false
413+
failed: false,
414+
renaming_map: renaming_map
410415
}
411416
}
412417
}
413418

419+
struct RenamingRecorder<'map> {
420+
substituted_node_id: NodeId,
421+
origin_span: Span,
422+
renaming_map: &'map mut FnvHashMap<(NodeId, Span), NodeId>
423+
}
424+
425+
impl<'map> ast_util::IdVisitingOperation for RenamingRecorder<'map> {
426+
fn visit_id(&mut self, node_id: NodeId) {
427+
let key = (node_id, self.origin_span);
428+
self.renaming_map.insert(key, self.substituted_node_id);
429+
}
430+
}
431+
414432
impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
415433
fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
416-
match pat.node {
434+
return match pat.node {
417435
ast::PatIdent(..) | ast::PatEnum(..) => {
418436
let def = self.tcx.def_map.borrow().get(&pat.id).cloned();
419437
match def {
420438
Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did) {
421439
Some(const_expr) => {
422-
const_expr_to_pat(self.tcx, const_expr).map(|mut new_pat| {
423-
new_pat.span = pat.span;
440+
const_expr_to_pat(self.tcx, const_expr, pat.span).map(|new_pat| {
441+
442+
if let Some(ref mut renaming_map) = self.renaming_map {
443+
// Record any renamings we do here
444+
record_renamings(const_expr, &pat, renaming_map);
445+
}
446+
424447
new_pat
425448
})
426449
}
@@ -435,6 +458,24 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
435458
}
436459
}
437460
_ => noop_fold_pat(pat, self)
461+
};
462+
463+
fn record_renamings(const_expr: &ast::Expr,
464+
substituted_pat: &ast::Pat,
465+
renaming_map: &mut FnvHashMap<(NodeId, Span), NodeId>) {
466+
let mut renaming_recorder = RenamingRecorder {
467+
substituted_node_id: substituted_pat.id,
468+
origin_span: substituted_pat.span,
469+
renaming_map: renaming_map,
470+
};
471+
472+
let mut id_visitor = ast_util::IdVisitor {
473+
operation: &mut renaming_recorder,
474+
pass_through_items: true,
475+
visited_outermost: false,
476+
};
477+
478+
id_visitor.visit_expr(const_expr);
438479
}
439480
}
440481
}
@@ -953,7 +994,7 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &ast::Local) {
953994
ast::LocalFor => "`for` loop"
954995
};
955996

956-
let mut static_inliner = StaticInliner::new(cx.tcx);
997+
let mut static_inliner = StaticInliner::new(cx.tcx, None);
957998
is_refutable(cx, &*static_inliner.fold_pat(loc.pat.clone()), |pat| {
958999
span_err!(cx.tcx.sess, loc.pat.span, E0005,
9591000
"refutable pattern in {} binding: `{}` not covered",
@@ -1040,7 +1081,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
10401081
};
10411082

10421083
for pat in pats {
1043-
walk_pat(&**pat, |p| {
1084+
ast_util::walk_pat(&**pat, |p| {
10441085
if pat_is_binding(def_map, &*p) {
10451086
match p.node {
10461087
ast::PatIdent(ast::BindByValue(_), _, ref sub) => {

src/librustc/middle/const_eval.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use middle::astconv_util::{ast_ty_to_prim_ty};
2222
use util::nodemap::DefIdMap;
2323

2424
use syntax::ast::{self, Expr};
25+
use syntax::codemap::Span;
2526
use syntax::parse::token::InternedString;
2627
use syntax::ptr::P;
2728
use syntax::visit::{self, Visitor};
@@ -304,10 +305,10 @@ pub enum const_val {
304305
const_bool(bool)
305306
}
306307

307-
pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
308+
pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat> {
308309
let pat = match expr.node {
309310
ast::ExprTup(ref exprs) =>
310-
ast::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr)).collect()),
311+
ast::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect()),
311312

312313
ast::ExprCall(ref callee, ref args) => {
313314
let def = tcx.def_map.borrow()[callee.id].clone();
@@ -319,7 +320,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
319320
def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did),
320321
_ => unreachable!()
321322
};
322-
let pats = args.iter().map(|expr| const_expr_to_pat(tcx, &**expr)).collect();
323+
let pats = args.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect();
323324
ast::PatEnum(path, Some(pats))
324325
}
325326

@@ -328,15 +329,15 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
328329
span: codemap::DUMMY_SP,
329330
node: ast::FieldPat {
330331
ident: field.ident.node,
331-
pat: const_expr_to_pat(tcx, &*field.expr),
332+
pat: const_expr_to_pat(tcx, &*field.expr, span),
332333
is_shorthand: false,
333334
},
334335
}).collect();
335336
ast::PatStruct(path.clone(), field_pats, false)
336337
}
337338

338339
ast::ExprVec(ref exprs) => {
339-
let pats = exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr)).collect();
340+
let pats = exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect();
340341
ast::PatVec(pats, None, vec![])
341342
}
342343

@@ -349,7 +350,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
349350
ast::PatEnum(path.clone(), None),
350351
_ => {
351352
match lookup_const(tcx, expr) {
352-
Some(actual) => return const_expr_to_pat(tcx, actual),
353+
Some(actual) => return const_expr_to_pat(tcx, actual, span),
353354
_ => unreachable!()
354355
}
355356
}
@@ -358,14 +359,14 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
358359

359360
ast::ExprQPath(_) => {
360361
match lookup_const(tcx, expr) {
361-
Some(actual) => return const_expr_to_pat(tcx, actual),
362+
Some(actual) => return const_expr_to_pat(tcx, actual, span),
362363
_ => unreachable!()
363364
}
364365
}
365366

366367
_ => ast::PatLit(P(expr.clone()))
367368
};
368-
P(ast::Pat { id: expr.id, node: pat, span: expr.span })
369+
P(ast::Pat { id: expr.id, node: pat, span: span })
369370
}
370371

371372
pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val {

src/librustc_trans/trans/_match.rs

+35-10
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ use trans::expr::{self, Dest};
213213
use trans::tvec;
214214
use trans::type_of;
215215
use middle::ty::{self, Ty};
216-
use session::config::FullDebugInfo;
216+
use session::config::{NoDebugInfo, FullDebugInfo};
217217
use util::common::indenter;
218218
use util::nodemap::FnvHashMap;
219219
use util::ppaux::{Repr, vec_map_to_string};
@@ -222,7 +222,7 @@ use std;
222222
use std::iter::AdditiveIterator;
223223
use std::rc::Rc;
224224
use syntax::ast;
225-
use syntax::ast::{DUMMY_NODE_ID, Ident};
225+
use syntax::ast::{DUMMY_NODE_ID, Ident, NodeId};
226226
use syntax::codemap::Span;
227227
use syntax::fold::Folder;
228228
use syntax::ptr::P;
@@ -366,6 +366,9 @@ struct Match<'a, 'p: 'a, 'blk: 'a, 'tcx: 'blk> {
366366
pats: Vec<&'p ast::Pat>,
367367
data: &'a ArmData<'p, 'blk, 'tcx>,
368368
bound_ptrs: Vec<(Ident, ValueRef)>,
369+
// Thread along renamings done by the check_match::StaticInliner, so we can
370+
// map back to original NodeIds
371+
pat_renaming_map: Option<&'a FnvHashMap<(NodeId, Span), NodeId>>
369372
}
370373

371374
impl<'a, 'p, 'blk, 'tcx> Repr<'tcx> for Match<'a, 'p, 'blk, 'tcx> {
@@ -419,7 +422,8 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
419422
Match {
420423
pats: pats,
421424
data: &*br.data,
422-
bound_ptrs: bound_ptrs
425+
bound_ptrs: bound_ptrs,
426+
pat_renaming_map: br.pat_renaming_map,
423427
}
424428
}).collect()
425429
}
@@ -463,7 +467,8 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
463467
Match {
464468
pats: pats,
465469
data: br.data,
466-
bound_ptrs: bound_ptrs
470+
bound_ptrs: bound_ptrs,
471+
pat_renaming_map: br.pat_renaming_map,
467472
}
468473
})
469474
}).collect()
@@ -570,14 +575,23 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>(
570575
// needs to be conditionally matched at runtime; for example, the discriminant
571576
// on a set of enum variants or a literal.
572577
fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
573-
m: &[Match<'a, 'p, 'blk, 'tcx>], col: uint)
578+
m: &[Match<'a, 'p, 'blk, 'tcx>],
579+
col: uint)
574580
-> Vec<Opt<'p, 'tcx>> {
575581
let tcx = bcx.tcx();
576582

577583
let mut found: Vec<Opt> = vec![];
578584
for br in m {
579585
let cur = br.pats[col];
580-
let debug_loc = DebugLoc::At(cur.id, cur.span);
586+
let debug_loc = match br.pat_renaming_map {
587+
Some(pat_renaming_map) => {
588+
match pat_renaming_map.get(&(cur.id, cur.span)) {
589+
Some(&id) => DebugLoc::At(id, cur.span),
590+
None => DebugLoc::At(cur.id, cur.span),
591+
}
592+
}
593+
None => DebugLoc::None
594+
};
581595

582596
let opt = match cur.node {
583597
ast::PatLit(ref l) => {
@@ -1419,16 +1433,27 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
14191433
bindings_map: create_bindings_map(bcx, &*arm.pats[0], discr_expr, &*arm.body)
14201434
}).collect();
14211435

1422-
let mut static_inliner = StaticInliner::new(scope_cx.tcx());
1423-
let arm_pats: Vec<Vec<P<ast::Pat>>> = arm_datas.iter().map(|arm_data| {
1424-
arm_data.arm.pats.iter().map(|p| static_inliner.fold_pat((*p).clone())).collect()
1425-
}).collect();
1436+
let mut pat_renaming_map = if scope_cx.sess().opts.debuginfo != NoDebugInfo {
1437+
Some(FnvHashMap())
1438+
} else {
1439+
None
1440+
};
1441+
1442+
let arm_pats: Vec<Vec<P<ast::Pat>>> = {
1443+
let mut static_inliner = StaticInliner::new(scope_cx.tcx(),
1444+
pat_renaming_map.as_mut());
1445+
arm_datas.iter().map(|arm_data| {
1446+
arm_data.arm.pats.iter().map(|p| static_inliner.fold_pat((*p).clone())).collect()
1447+
}).collect()
1448+
};
1449+
14261450
let mut matches = Vec::new();
14271451
for (arm_data, pats) in arm_datas.iter().zip(arm_pats.iter()) {
14281452
matches.extend(pats.iter().map(|p| Match {
14291453
pats: vec![&**p],
14301454
data: arm_data,
14311455
bound_ptrs: Vec::new(),
1456+
pat_renaming_map: pat_renaming_map.as_ref()
14321457
}));
14331458
}
14341459

0 commit comments

Comments
 (0)