Skip to content

Commit e3cd43e

Browse files
committed
Use smaller def span for functions
Currently, the def span of a funtion encompasses the entire function signature and body. However, this is usually unnecessarily verbose - when we are pointing at an entire function in a diagnostic, we almost always want to point at the signature. The actual contents of the body tends to be irrelevant to the diagnostic we are emitting, and just takes up additional screen space. This commit changes the `def_span` of all function items (freestanding functions, `impl`-block methods, and `trait`-block methods) to be the span of the signature. For example, the function ```rust pub fn foo<T>(val: T) -> T { val } ``` now has a `def_span` corresponding to `pub fn foo<T>(val: T) -> T` (everything before the opening curly brace). Trait methods without a body have a `def_span` which includes the trailing semicolon. For example: ```rust trait Foo { fn bar(); }``` the function definition `Foo::bar` has a `def_span` of `fn bar();` This makes our diagnostic output much shorter, and emphasizes information that is relevant to whatever diagnostic we are reporting. We continue to use the full span (including the body) in a few of places: * MIR building uses the full span when building source scopes. * 'Outlives suggestions' use the full span to sort the diagnostics being emitted. * The `#[rustc_on_unimplemented(enclosing_scope="in this scope")]` attribute points the entire scope body. * The 'unconditional recursion' lint uses the full span to show additional context for the recursive call. All of these cases work only with local items, so we don't need to add anything extra to crate metadata.
1 parent 663d2f5 commit e3cd43e

File tree

107 files changed

+345
-576
lines changed

Some content is hidden

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

107 files changed

+345
-576
lines changed

src/librustc_ast/ast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1671,6 +1671,7 @@ pub struct MutTy {
16711671
pub struct FnSig {
16721672
pub header: FnHeader,
16731673
pub decl: P<FnDecl>,
1674+
pub span: Span,
16741675
}
16751676

16761677
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]

src/librustc_ast/mut_visit.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -363,9 +363,10 @@ pub fn visit_bounds<T: MutVisitor>(bounds: &mut GenericBounds, vis: &mut T) {
363363
}
364364

365365
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
366-
pub fn visit_fn_sig<T: MutVisitor>(FnSig { header, decl }: &mut FnSig, vis: &mut T) {
366+
pub fn visit_fn_sig<T: MutVisitor>(FnSig { header, decl, span }: &mut FnSig, vis: &mut T) {
367367
vis.visit_fn_header(header);
368368
vis.visit_fn_decl(decl);
369+
vis.visit_span(span);
369370
}
370371

371372
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.

src/librustc_ast_lowering/item.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
263263
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
264264
hir::ItemKind::Const(ty, body_id)
265265
}
266-
ItemKind::Fn(_, FnSig { ref decl, header }, ref generics, ref body) => {
266+
ItemKind::Fn(
267+
_,
268+
FnSig { ref decl, header, span: fn_sig_span },
269+
ref generics,
270+
ref body,
271+
) => {
267272
let fn_def_id = self.resolver.local_def_id(id);
268273
self.with_new_scopes(|this| {
269274
this.current_item = Some(ident.span);
@@ -290,7 +295,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
290295
)
291296
},
292297
);
293-
let sig = hir::FnSig { decl, header: this.lower_fn_header(header) };
298+
let sig = hir::FnSig {
299+
decl,
300+
header: this.lower_fn_header(header),
301+
span: fn_sig_span,
302+
};
294303
hir::ItemKind::Fn(sig, generics, body_id)
295304
})
296305
}
@@ -1243,7 +1252,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
12431252
)
12441253
},
12451254
);
1246-
(generics, hir::FnSig { header, decl })
1255+
(generics, hir::FnSig { header, decl, span: sig.span })
12471256
}
12481257

12491258
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {

src/librustc_builtin_macros/deriving/generic/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,7 @@ impl<'a> MethodDef<'a> {
924924
let sig = ast::FnSig {
925925
header: ast::FnHeader { unsafety, ext: ast::Extern::None, ..ast::FnHeader::default() },
926926
decl: fn_decl,
927+
span: trait_.span,
927928
};
928929
let def = ast::Defaultness::Final;
929930

src/librustc_builtin_macros/global_allocator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl AllocFnFactory<'_, '_> {
6767
let (output_ty, output_expr) = self.ret_ty(&method.output, result);
6868
let decl = self.cx.fn_decl(abi_args, ast::FnRetTy::Ty(output_ty));
6969
let header = FnHeader { unsafety: Unsafe::Yes(self.span), ..FnHeader::default() };
70-
let sig = FnSig { decl, header };
70+
let sig = FnSig { decl, header, span: self.span };
7171
let block = Some(self.cx.block_expr(output_expr));
7272
let kind = ItemKind::Fn(ast::Defaultness::Final, sig, Generics::default(), block);
7373
let item = self.cx.item(

src/librustc_builtin_macros/test_harness.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
318318
};
319319

320320
let decl = ecx.fn_decl(vec![], ast::FnRetTy::Ty(main_ret_ty));
321-
let sig = ast::FnSig { decl, header: ast::FnHeader::default() };
321+
let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp };
322322
let def = ast::Defaultness::Final;
323323
let main = ast::ItemKind::Fn(def, sig, ast::Generics::default(), Some(main_body));
324324

src/librustc_hir/hir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1851,6 +1851,7 @@ pub struct MutTy<'hir> {
18511851
pub struct FnSig<'hir> {
18521852
pub header: FnHeader,
18531853
pub decl: &'hir FnDecl<'hir>,
1854+
pub span: Span,
18541855
}
18551856

18561857
// The bodies for items are stored "out of line", in a separate

src/librustc_middle/hir/map/mod.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -828,13 +828,24 @@ impl<'hir> Map<'hir> {
828828
attrs.unwrap_or(&[])
829829
}
830830

831+
/// Gets the span of the definition of the specified HIR node.
832+
/// This is used by `tcx.get_span`
831833
pub fn span(&self, hir_id: HirId) -> Span {
832834
match self.find_entry(hir_id).map(|entry| entry.node) {
833835
Some(Node::Param(param)) => param.span,
834-
Some(Node::Item(item)) => item.span,
836+
Some(Node::Item(item)) => match &item.kind {
837+
ItemKind::Fn(sig, _, _) => sig.span,
838+
_ => item.span,
839+
},
835840
Some(Node::ForeignItem(foreign_item)) => foreign_item.span,
836-
Some(Node::TraitItem(trait_method)) => trait_method.span,
837-
Some(Node::ImplItem(impl_item)) => impl_item.span,
841+
Some(Node::TraitItem(trait_item)) => match &trait_item.kind {
842+
TraitItemKind::Fn(sig, _) => sig.span,
843+
_ => trait_item.span,
844+
},
845+
Some(Node::ImplItem(impl_item)) => match &impl_item.kind {
846+
ImplItemKind::Fn(sig, _) => sig.span,
847+
_ => impl_item.span,
848+
},
838849
Some(Node::Variant(variant)) => variant.span,
839850
Some(Node::Field(field)) => field.span,
840851
Some(Node::AnonConst(constant)) => self.body(constant.body).value.span,
@@ -866,6 +877,18 @@ impl<'hir> Map<'hir> {
866877
}
867878
}
868879

880+
/// Like `hir.span()`, but includes the body of function items
881+
/// (instead of just the function header)
882+
pub fn span_with_body(&self, hir_id: HirId) -> Span {
883+
match self.find_entry(hir_id).map(|entry| entry.node) {
884+
Some(Node::TraitItem(item)) => item.span,
885+
Some(Node::ImplItem(impl_item)) => impl_item.span,
886+
Some(Node::Item(item)) => item.span,
887+
Some(_) => self.span(hir_id),
888+
_ => bug!("hir::map::Map::span_with_body: id not in map: {:?}", hir_id),
889+
}
890+
}
891+
869892
pub fn span_if_local(&self, id: DefId) -> Option<Span> {
870893
id.as_local().map(|id| self.span(self.local_def_id_to_hir_id(id)))
871894
}

src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ impl OutlivesSuggestionBuilder {
257257
};
258258

259259
// We want this message to appear after other messages on the mir def.
260-
let mir_span = mbcx.infcx.tcx.def_span(mbcx.mir_def_id);
260+
let mir_span = mbcx.body.span;
261261
diag.sort_span = mir_span.shrink_to_hi();
262262

263263
// Buffer the diagnostic

src/librustc_mir_build/build/mod.rs

+20-7
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,29 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
3737
let id = tcx.hir().local_def_id_to_hir_id(def.did);
3838

3939
// Figure out what primary body this item has.
40-
let (body_id, return_ty_span) = match tcx.hir().get(id) {
40+
let (body_id, return_ty_span, span_with_body) = match tcx.hir().get(id) {
4141
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, decl, body_id, _, _), .. }) => {
42-
(*body_id, decl.output.span())
42+
(*body_id, decl.output.span(), None)
4343
}
4444
Node::Item(hir::Item {
4545
kind: hir::ItemKind::Fn(hir::FnSig { decl, .. }, _, body_id),
46+
span,
4647
..
4748
})
4849
| Node::ImplItem(hir::ImplItem {
4950
kind: hir::ImplItemKind::Fn(hir::FnSig { decl, .. }, body_id),
51+
span,
5052
..
5153
})
5254
| Node::TraitItem(hir::TraitItem {
5355
kind: hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitFn::Provided(body_id)),
56+
span,
5457
..
55-
}) => (*body_id, decl.output.span()),
58+
}) => {
59+
// Use the `Span` of the `Item/ImplItem/TraitItem` as the body span,
60+
// since the def span of a function does not include the body
61+
(*body_id, decl.output.span(), Some(*span))
62+
}
5663
Node::Item(hir::Item {
5764
kind: hir::ItemKind::Static(ty, _, body_id) | hir::ItemKind::Const(ty, body_id),
5865
..
@@ -61,12 +68,16 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
6168
| Node::TraitItem(hir::TraitItem {
6269
kind: hir::TraitItemKind::Const(ty, Some(body_id)),
6370
..
64-
}) => (*body_id, ty.span),
65-
Node::AnonConst(hir::AnonConst { body, hir_id, .. }) => (*body, tcx.hir().span(*hir_id)),
71+
}) => (*body_id, ty.span, None),
72+
Node::AnonConst(hir::AnonConst { body, hir_id, .. }) => (*body, tcx.hir().span(*hir_id), None),
6673

6774
_ => span_bug!(tcx.hir().span(id), "can't build MIR for {:?}", def.did),
6875
};
6976

77+
// If we don't have a specialized span for the body, just use the
78+
// normal def span.
79+
let span_with_body = span_with_body.unwrap_or_else(|| tcx.hir().span(id));
80+
7081
tcx.infer_ctxt().enter(|infcx| {
7182
let cx = Cx::new(&infcx, def, id);
7283
let body = if let Some(ErrorReported) = cx.typeck_results().tainted_by_errors {
@@ -167,6 +178,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
167178
return_ty,
168179
return_ty_span,
169180
body,
181+
span_with_body
170182
);
171183
mir.yield_ty = yield_ty;
172184
mir
@@ -571,6 +583,7 @@ fn construct_fn<'a, 'tcx, A>(
571583
return_ty: Ty<'tcx>,
572584
return_ty_span: Span,
573585
body: &'tcx hir::Body<'tcx>,
586+
span_with_body: Span
574587
) -> Body<'tcx>
575588
where
576589
A: Iterator<Item = ArgInfo<'tcx>>,
@@ -585,7 +598,7 @@ where
585598

586599
let mut builder = Builder::new(
587600
hir,
588-
span,
601+
span_with_body,
589602
arguments.len(),
590603
safety,
591604
return_ty,
@@ -628,7 +641,7 @@ where
628641
)
629642
);
630643
// Attribute epilogue to function's closing brace
631-
let fn_end = span.shrink_to_hi();
644+
let fn_end = span_with_body.shrink_to_hi();
632645
let source_info = builder.source_info(fn_end);
633646
let return_block = builder.return_block();
634647
builder.cfg.goto(block, source_info, return_block);

src/librustc_mir_build/lints.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: LocalDefId) {
3838
vis.reachable_recursive_calls.sort();
3939

4040
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
41-
let sp = tcx.sess.source_map().guess_head_span(tcx.hir().span(hir_id));
41+
let sp = tcx.sess.source_map().guess_head_span(tcx.hir().span_with_body(hir_id));
4242
tcx.struct_span_lint_hir(UNCONDITIONAL_RECURSION, hir_id, sp, |lint| {
4343
let mut db = lint.build("function cannot return without recursing");
4444
db.span_label(sp, "cannot return without recursing");

src/librustc_parse/parser/item.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ impl<'a> Parser<'a> {
227227
(Ident::invalid(), ItemKind::Use(P(tree)))
228228
} else if self.check_fn_front_matter() {
229229
// FUNCTION ITEM
230-
let (ident, sig, generics, body) = self.parse_fn(attrs, req_name)?;
230+
let (ident, sig, generics, body) = self.parse_fn(attrs, req_name, lo)?;
231231
(ident, ItemKind::Fn(def(), sig, generics, body))
232232
} else if self.eat_keyword(kw::Extern) {
233233
if self.eat_keyword(kw::Crate) {
@@ -1492,21 +1492,31 @@ impl<'a> Parser<'a> {
14921492
&mut self,
14931493
attrs: &mut Vec<Attribute>,
14941494
req_name: ReqName,
1495+
sig_lo: Span,
14951496
) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
14961497
let header = self.parse_fn_front_matter()?; // `const ... fn`
14971498
let ident = self.parse_ident()?; // `foo`
14981499
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
14991500
let decl = self.parse_fn_decl(req_name, AllowPlus::Yes)?; // `(p: u8, ...)`
15001501
generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
1501-
let body = self.parse_fn_body(attrs)?; // `;` or `{ ... }`.
1502-
Ok((ident, FnSig { header, decl }, generics, body))
1502+
1503+
let mut sig_hi = self.prev_token.span;
1504+
let body = self.parse_fn_body(attrs, &mut sig_hi)?; // `;` or `{ ... }`.
1505+
let fn_sig_span = sig_lo.to(sig_hi);
1506+
Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, body))
15031507
}
15041508

15051509
/// Parse the "body" of a function.
15061510
/// This can either be `;` when there's no body,
15071511
/// or e.g. a block when the function is a provided one.
1508-
fn parse_fn_body(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, Option<P<Block>>> {
1512+
fn parse_fn_body(
1513+
&mut self,
1514+
attrs: &mut Vec<Attribute>,
1515+
sig_hi: &mut Span,
1516+
) -> PResult<'a, Option<P<Block>>> {
15091517
let (inner_attrs, body) = if self.check(&token::Semi) {
1518+
// Include the trailing semicolon in the span of the signature
1519+
*sig_hi = self.token.span;
15101520
self.bump(); // `;`
15111521
(Vec::new(), None)
15121522
} else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {

src/librustc_save_analysis/sig.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ impl<'hir> Sig for hir::Item<'hir> {
377377

378378
Ok(extend_sig(ty, text, defs, vec![]))
379379
}
380-
hir::ItemKind::Fn(hir::FnSig { ref decl, header }, ref generics, _) => {
380+
hir::ItemKind::Fn(hir::FnSig { ref decl, header, span: _ }, ref generics, _) => {
381381
let mut text = String::new();
382382
if let hir::Constness::Const = header.constness {
383383
text.push_str("const ");

src/librustc_trait_selection/traits/error_reporting/mod.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -399,16 +399,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
399399
err.note(s.as_str());
400400
}
401401
if let Some(ref s) = enclosing_scope {
402-
let enclosing_scope_span = tcx.def_span(
403-
tcx.hir()
404-
.opt_local_def_id(obligation.cause.body_id)
405-
.unwrap_or_else(|| {
406-
tcx.hir().body_owner_def_id(hir::BodyId {
407-
hir_id: obligation.cause.body_id,
408-
})
402+
let body = tcx
403+
.hir()
404+
.opt_local_def_id(obligation.cause.body_id)
405+
.unwrap_or_else(|| {
406+
tcx.hir().body_owner_def_id(hir::BodyId {
407+
hir_id: obligation.cause.body_id,
409408
})
410-
.to_def_id(),
411-
);
409+
});
410+
411+
let enclosing_scope_span =
412+
tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(body));
412413

413414
err.span_label(enclosing_scope_span, s.as_str());
414415
}

src/librustc_typeck/collect.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1543,7 +1543,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
15431543
}
15441544

15451545
TraitItem(hir::TraitItem {
1546-
kind: TraitItemKind::Fn(FnSig { header, decl }, _),
1546+
kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
15471547
ident,
15481548
generics,
15491549
..

src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: fatal error triggered by #[rustc_error]
22
--> $DIR/bound-lifetime-in-binding-only.rs:71:1
33
|
44
LL | fn main() { }
5-
| ^^^^^^^^^^^^^
5+
| ^^^^^^^^^
66

77
error: aborting due to previous error
88

src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: fatal error triggered by #[rustc_error]
22
--> $DIR/bound-lifetime-in-return-only.rs:49:1
33
|
44
LL | fn main() { }
5-
| ^^^^^^^^^^^^^
5+
| ^^^^^^^^^
66

77
error: aborting due to previous error
88

src/test/ui/associated-types/cache/project-fn-ret-contravariant.ok.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: fatal error triggered by #[rustc_error]
22
--> $DIR/project-fn-ret-contravariant.rs:50:1
33
|
44
LL | fn main() { }
5-
| ^^^^^^^^^^^^^
5+
| ^^^^^^^^^
66

77
error: aborting due to previous error
88

src/test/ui/associated-types/cache/project-fn-ret-contravariant.oneuse.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: fatal error triggered by #[rustc_error]
22
--> $DIR/project-fn-ret-contravariant.rs:50:1
33
|
44
LL | fn main() { }
5-
| ^^^^^^^^^^^^^
5+
| ^^^^^^^^^
66

77
error: aborting due to previous error
88

src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: fatal error triggered by #[rustc_error]
22
--> $DIR/project-fn-ret-invariant.rs:60:1
33
|
44
LL | fn main() {}
5-
| ^^^^^^^^^^^^
5+
| ^^^^^^^^^
66

77
error: aborting due to previous error
88

Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
error: fatal error triggered by #[rustc_error]
22
--> $DIR/higher-ranked-projection.rs:24:1
33
|
4-
LL | / fn main() {
5-
LL | | foo(());
6-
LL | |
7-
LL | | }
8-
| |_^
4+
LL | fn main() {
5+
| ^^^^^^^^^
96

107
error: aborting due to previous error
118

0 commit comments

Comments
 (0)