Skip to content

Commit 28946b3

Browse files
committed
Track span of function in method calls, and use this in #[track_caller]
Fixes #69977 When we parse a chain of method calls like `foo.a().b().c()`, each `MethodCallExpr` gets assigned a span that starts at the beginning of the call chain (`foo`). While this is useful for diagnostics, it means that `Location::caller` will return the same location for every call in a call chain. This PR makes us separately record the span of the function name and arguments for a method call (e.g. `b()` in `foo.a().b().c()`). This `Span` is passed through HIR lowering and MIR building to `TerminatorKind::Call`, where it is used in preference to `Terminator.source_info.span` when determining `Location::caller`. This new span is also useful for diagnostics where we want to emphasize a particular method call - for an example, see #72389 (comment)
1 parent bb86748 commit 28946b3

File tree

42 files changed

+141
-50
lines changed

Some content is hidden

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

42 files changed

+141
-50
lines changed

src/librustc_ast/ast.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1165,7 +1165,9 @@ pub enum ExprKind {
11651165
/// and the remaining elements are the rest of the arguments.
11661166
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
11671167
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
1168-
MethodCall(PathSegment, Vec<P<Expr>>),
1168+
/// The `Span` is the span of the function, without the dot and receiver
1169+
/// (e.g. `foo(a, b)` in `x.foo(a, b)`
1170+
MethodCall(PathSegment, Vec<P<Expr>>, Span),
11691171
/// A tuple (e.g., `(a, b, c, d)`).
11701172
Tup(Vec<P<Expr>>),
11711173
/// A binary operation (e.g., `a + b`, `a * b`).

src/librustc_ast/mut_visit.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1111,11 +1111,12 @@ pub fn noop_visit_expr<T: MutVisitor>(
11111111
vis.visit_expr(f);
11121112
visit_exprs(args, vis);
11131113
}
1114-
ExprKind::MethodCall(PathSegment { ident, id, args }, exprs) => {
1114+
ExprKind::MethodCall(PathSegment { ident, id, args }, exprs, span) => {
11151115
vis.visit_ident(ident);
11161116
vis.visit_id(id);
11171117
visit_opt(args, |args| vis.visit_generic_args(args));
11181118
visit_exprs(exprs, vis);
1119+
vis.visit_span(span);
11191120
}
11201121
ExprKind::Binary(_binop, lhs, rhs) => {
11211122
vis.visit_expr(lhs);

src/librustc_ast/util/parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
394394
contains_exterior_struct_lit(&x)
395395
}
396396

397-
ast::ExprKind::MethodCall(.., ref exprs) => {
397+
ast::ExprKind::MethodCall(.., ref exprs, _) => {
398398
// X { y: 1 }.bar(...)
399399
contains_exterior_struct_lit(&exprs[0])
400400
}

src/librustc_ast/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
726726
visitor.visit_expr(callee_expression);
727727
walk_list!(visitor, visit_expr, arguments);
728728
}
729-
ExprKind::MethodCall(ref segment, ref arguments) => {
729+
ExprKind::MethodCall(ref segment, ref arguments, _span) => {
730730
visitor.visit_path_segment(expression.span, segment);
731731
walk_list!(visitor, visit_expr, arguments);
732732
}

src/librustc_ast_lowering/expr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
3939
let f = self.lower_expr(f);
4040
hir::ExprKind::Call(f, self.lower_exprs(args))
4141
}
42-
ExprKind::MethodCall(ref seg, ref args) => {
42+
ExprKind::MethodCall(ref seg, ref args, span) => {
4343
let hir_seg = self.arena.alloc(self.lower_path_segment(
4444
e.span,
4545
seg,
@@ -50,7 +50,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
5050
None,
5151
));
5252
let args = self.lower_exprs(args);
53-
hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args)
53+
hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args, span)
5454
}
5555
ExprKind::Binary(binop, ref lhs, ref rhs) => {
5656
let binop = self.lower_binop(binop);

src/librustc_ast_pretty/pprust.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1818,7 +1818,7 @@ impl<'a> State<'a> {
18181818
ast::ExprKind::Call(ref func, ref args) => {
18191819
self.print_expr_call(func, &args[..]);
18201820
}
1821-
ast::ExprKind::MethodCall(ref segment, ref args) => {
1821+
ast::ExprKind::MethodCall(ref segment, ref args, _) => {
18221822
self.print_expr_method_call(segment, &args[..]);
18231823
}
18241824
ast::ExprKind::Binary(op, ref lhs, ref rhs) => {

src/librustc_codegen_ssa/mir/block.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
530530
args: &Vec<mir::Operand<'tcx>>,
531531
destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
532532
cleanup: Option<mir::BasicBlock>,
533+
fn_span: Span,
533534
) {
534535
let span = terminator.source_info.span;
535536
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
@@ -634,7 +635,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
634635

635636
if intrinsic == Some("caller_location") {
636637
if let Some((_, target)) = destination.as_ref() {
637-
let location = self.get_caller_location(&mut bx, span);
638+
let location = self.get_caller_location(&mut bx, fn_span);
638639

639640
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
640641
location.val.store(&mut bx, tmp);
@@ -798,7 +799,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
798799
args.len() + 1,
799800
"#[track_caller] fn's must have 1 more argument in their ABI than in their MIR",
800801
);
801-
let location = self.get_caller_location(&mut bx, span);
802+
let location = self.get_caller_location(&mut bx, fn_span);
803+
debug!(
804+
"codegen_call_terminator({:?}): location={:?} (fn_span {:?})",
805+
terminator, location, fn_span
806+
);
807+
802808
let last_arg = fn_abi.args.last().unwrap();
803809
self.codegen_argument(&mut bx, location, &mut llargs, last_arg);
804810
}
@@ -1016,6 +1022,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10161022
ref destination,
10171023
cleanup,
10181024
from_hir_call: _,
1025+
fn_span,
10191026
} => {
10201027
self.codegen_call_terminator(
10211028
helper,
@@ -1025,6 +1032,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10251032
args,
10261033
destination,
10271034
cleanup,
1035+
fn_span,
10281036
);
10291037
}
10301038
mir::TerminatorKind::GeneratorDrop | mir::TerminatorKind::Yield { .. } => {

src/librustc_expand/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ impl<'a> ExtCtxt<'a> {
272272
) -> P<ast::Expr> {
273273
args.insert(0, expr);
274274
let segment = ast::PathSegment::from_ident(ident.with_span_pos(span));
275-
self.expr(span, ast::ExprKind::MethodCall(segment, args))
275+
self.expr(span, ast::ExprKind::MethodCall(segment, args, span))
276276
}
277277
pub fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
278278
self.expr(b.span, ast::ExprKind::Block(b, None))

src/librustc_hir/hir.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,7 +1371,7 @@ pub struct Expr<'hir> {
13711371

13721372
// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
13731373
#[cfg(target_arch = "x86_64")]
1374-
rustc_data_structures::static_assert_size!(Expr<'static>, 64);
1374+
rustc_data_structures::static_assert_size!(Expr<'static>, 72);
13751375

13761376
impl Expr<'_> {
13771377
pub fn precedence(&self) -> ExprPrecedence {
@@ -1568,12 +1568,14 @@ pub enum ExprKind<'hir> {
15681568
/// and the remaining elements are the rest of the arguments.
15691569
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
15701570
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
1571+
/// The final `Span` represents the span of the function and arguments
1572+
/// (e.g. `foo::<Bar, Baz>(a, b, c, d)` in `x.foo::<Bar, Baz>(a, b, c, d)`
15711573
///
15721574
/// To resolve the called method to a `DefId`, call [`type_dependent_def_id`] with
15731575
/// the `hir_id` of the `MethodCall` node itself.
15741576
///
15751577
/// [`type_dependent_def_id`]: ../ty/struct.TypeckTables.html#method.type_dependent_def_id
1576-
MethodCall(&'hir PathSegment<'hir>, Span, &'hir [Expr<'hir>]),
1578+
MethodCall(&'hir PathSegment<'hir>, Span, &'hir [Expr<'hir>], Span),
15771579
/// A tuple (e.g., `(a, b, c, d)`).
15781580
Tup(&'hir [Expr<'hir>]),
15791581
/// A binary operation (e.g., `a + b`, `a * b`).

src/librustc_hir/intravisit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1090,7 +1090,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
10901090
visitor.visit_expr(callee_expression);
10911091
walk_list!(visitor, visit_expr, arguments);
10921092
}
1093-
ExprKind::MethodCall(ref segment, _, arguments) => {
1093+
ExprKind::MethodCall(ref segment, _, arguments, _) => {
10941094
visitor.visit_path_segment(expression.span, segment);
10951095
walk_list!(visitor, visit_expr, arguments);
10961096
}

0 commit comments

Comments
 (0)