rustc_ast_passes/
show_spans.rs1use rustc_ast::visit::{self, Visitor};
2use rustc_ast::{self as ast, ItemKind};
3use rustc_attr_ir::{Attribute, AttributeKind, RustcShowSpansKind};
4use rustc_attr_parsing::AttributeParser;
5use rustc_session::Session;
6use rustc_span::sym;
7
8use crate::diagnostics;
9
10struct ShowSpans<'a> {
11 sess: &'a Session,
12 expr: bool,
13 ty: bool,
14 path: bool,
15}
16
17impl<'a> Visitor<'a> for ShowSpans<'a> {
18 fn visit_item(&mut self, item: &'a ast::Item) {
19 let saved = (self.expr, self.ty, self.path);
20 (self.expr, self.ty, self.path) = (false, false, false);
21
22 if let ItemKind::Fn(_) = &item.kind
23 && let Some(Attribute::Parsed(AttributeKind::RustcShowSpans(kinds))) =
24 AttributeParser::parse_limited_sym(self.sess, &item.attrs, &[sym::rustc_show_spans])
25 {
26 for kind in kinds {
27 match kind {
28 RustcShowSpansKind::Expr => self.expr = true,
29 RustcShowSpansKind::Ty => self.ty = true,
30 RustcShowSpansKind::Path => self.path = true,
31 }
32 }
33 }
34 visit::walk_item(self, item);
35
36 (self.expr, self.ty, self.path) = saved;
38 }
39
40 fn visit_attribute(&mut self, _: &'a ast::Attribute) {}
42
43 fn visit_expr(&mut self, e: &'a ast::Expr) {
44 if self.expr {
45 self.sess.dcx().emit_note(diagnostics::ShowSpan { span: e.span, kind: "expr" });
46 }
47 visit::walk_expr(self, e);
48 }
49
50 fn visit_ty(&mut self, t: &'a ast::Ty) {
51 if self.ty {
52 self.sess.dcx().emit_note(diagnostics::ShowSpan { span: t.span, kind: "ty" });
53 }
54 visit::walk_ty(self, t);
55 }
56
57 fn visit_path(&mut self, p: &'a ast::Path) {
58 if self.path {
59 self.sess.dcx().emit_note(diagnostics::ShowSpan { span: p.span, kind: "path" });
60 }
61 visit::walk_path(self, p);
62 }
63}
64
65pub fn check_crate(sess: &Session, krate: &ast::Crate) {
66 visit::walk_crate(&mut ShowSpans { sess, expr: false, ty: false, path: false }, krate);
67}