]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_symbol_mangling/src/test.rs
Auto merge of #106283 - JulianKnodt:enum_err, r=cjgillot
[rust.git] / compiler / rustc_symbol_mangling / src / test.rs
1 //! Walks the crate looking for items/impl-items/trait-items that have
2 //! either a `rustc_symbol_name` or `rustc_def_path` attribute and
3 //! generates an error giving, respectively, the symbol name or
4 //! def-path. This is used for unit testing the code that generates
5 //! paths etc in all kinds of annoying scenarios.
6
7 use crate::errors::{Kind, TestOutput};
8 use rustc_hir::def_id::LocalDefId;
9 use rustc_middle::ty::print::with_no_trimmed_paths;
10 use rustc_middle::ty::{subst::InternalSubsts, Instance, TyCtxt};
11 use rustc_span::symbol::{sym, Symbol};
12
13 const SYMBOL_NAME: Symbol = sym::rustc_symbol_name;
14 const DEF_PATH: Symbol = sym::rustc_def_path;
15
16 pub fn report_symbol_names(tcx: TyCtxt<'_>) {
17     // if the `rustc_attrs` feature is not enabled, then the
18     // attributes we are interested in cannot be present anyway, so
19     // skip the walk.
20     if !tcx.features().rustc_attrs {
21         return;
22     }
23
24     tcx.dep_graph.with_ignore(|| {
25         let mut symbol_names = SymbolNamesTest { tcx };
26         let crate_items = tcx.hir_crate_items(());
27
28         for id in crate_items.items() {
29             symbol_names.process_attrs(id.owner_id.def_id);
30         }
31
32         for id in crate_items.trait_items() {
33             symbol_names.process_attrs(id.owner_id.def_id);
34         }
35
36         for id in crate_items.impl_items() {
37             symbol_names.process_attrs(id.owner_id.def_id);
38         }
39
40         for id in crate_items.foreign_items() {
41             symbol_names.process_attrs(id.owner_id.def_id);
42         }
43     })
44 }
45
46 struct SymbolNamesTest<'tcx> {
47     tcx: TyCtxt<'tcx>,
48 }
49
50 impl SymbolNamesTest<'_> {
51     fn process_attrs(&mut self, def_id: LocalDefId) {
52         let tcx = self.tcx;
53         // The formatting of `tag({})` is chosen so that tests can elect
54         // to test the entirety of the string, if they choose, or else just
55         // some subset.
56         for attr in tcx.get_attrs(def_id.to_def_id(), SYMBOL_NAME) {
57             let def_id = def_id.to_def_id();
58             let instance = Instance::new(
59                 def_id,
60                 tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def_id)),
61             );
62             let mangled = tcx.symbol_name(instance);
63             tcx.sess.emit_err(TestOutput {
64                 span: attr.span,
65                 kind: Kind::SymbolName,
66                 content: format!("{mangled}"),
67             });
68             if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) {
69                 tcx.sess.emit_err(TestOutput {
70                     span: attr.span,
71                     kind: Kind::Demangling,
72                     content: format!("{demangling}"),
73                 });
74                 tcx.sess.emit_err(TestOutput {
75                     span: attr.span,
76                     kind: Kind::DemanglingAlt,
77                     content: format!("{demangling:#}"),
78                 });
79             }
80         }
81
82         for attr in tcx.get_attrs(def_id.to_def_id(), DEF_PATH) {
83             tcx.sess.emit_err(TestOutput {
84                 span: attr.span,
85                 kind: Kind::DefPath,
86                 content: with_no_trimmed_paths!(tcx.def_path_str(def_id.to_def_id())),
87             });
88         }
89     }
90 }