]> git.lizzy.rs Git - rust.git/blob - src/librustc_lint/levels.rs
GlobalCtxt: Erase `LintStore` type.
[rust.git] / src / librustc_lint / levels.rs
1 use super::late::unerased_lint_store;
2 use rustc::hir::map::Map;
3 use rustc::lint::{LintLevelMap, LintLevelSets, LintLevelsBuilder, LintStore};
4 use rustc::ty::query::Providers;
5 use rustc::ty::TyCtxt;
6 use rustc_hir as hir;
7 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
8 use rustc_hir::intravisit;
9 use syntax::ast;
10
11 pub use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintId};
12
13 fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
14     assert_eq!(cnum, LOCAL_CRATE);
15     let store = unerased_lint_store(tcx);
16     let mut builder = LintLevelMapBuilder {
17         levels: LintLevelSets::builder(tcx.sess, false, &store),
18         tcx: tcx,
19         store,
20     };
21     let krate = tcx.hir().krate();
22
23     let push = builder.levels.push(&krate.attrs, &store);
24     builder.levels.register_id(hir::CRATE_HIR_ID);
25     for macro_def in krate.exported_macros {
26         builder.levels.register_id(macro_def.hir_id);
27     }
28     intravisit::walk_crate(&mut builder, krate);
29     builder.levels.pop(push);
30
31     tcx.arena.alloc(builder.levels.build_map())
32 }
33
34 struct LintLevelMapBuilder<'a, 'tcx> {
35     levels: LintLevelsBuilder<'tcx>,
36     tcx: TyCtxt<'tcx>,
37     store: &'a LintStore,
38 }
39
40 impl LintLevelMapBuilder<'_, '_> {
41     fn with_lint_attrs<F>(&mut self, id: hir::HirId, attrs: &[ast::Attribute], f: F)
42     where
43         F: FnOnce(&mut Self),
44     {
45         let push = self.levels.push(attrs, self.store);
46         if push.changed {
47             self.levels.register_id(id);
48         }
49         f(self);
50         self.levels.pop(push);
51     }
52 }
53
54 impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
55     type Map = Map<'tcx>;
56
57     fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
58         intravisit::NestedVisitorMap::All(&self.tcx.hir())
59     }
60
61     fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
62         self.with_lint_attrs(param.hir_id, &param.attrs, |builder| {
63             intravisit::walk_param(builder, param);
64         });
65     }
66
67     fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
68         self.with_lint_attrs(it.hir_id, &it.attrs, |builder| {
69             intravisit::walk_item(builder, it);
70         });
71     }
72
73     fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
74         self.with_lint_attrs(it.hir_id, &it.attrs, |builder| {
75             intravisit::walk_foreign_item(builder, it);
76         })
77     }
78
79     fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
80         self.with_lint_attrs(e.hir_id, &e.attrs, |builder| {
81             intravisit::walk_expr(builder, e);
82         })
83     }
84
85     fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) {
86         self.with_lint_attrs(s.hir_id, &s.attrs, |builder| {
87             intravisit::walk_struct_field(builder, s);
88         })
89     }
90
91     fn visit_variant(
92         &mut self,
93         v: &'tcx hir::Variant<'tcx>,
94         g: &'tcx hir::Generics<'tcx>,
95         item_id: hir::HirId,
96     ) {
97         self.with_lint_attrs(v.id, &v.attrs, |builder| {
98             intravisit::walk_variant(builder, v, g, item_id);
99         })
100     }
101
102     fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) {
103         self.with_lint_attrs(l.hir_id, &l.attrs, |builder| {
104             intravisit::walk_local(builder, l);
105         })
106     }
107
108     fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) {
109         self.with_lint_attrs(a.hir_id, &a.attrs, |builder| {
110             intravisit::walk_arm(builder, a);
111         })
112     }
113
114     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
115         self.with_lint_attrs(trait_item.hir_id, &trait_item.attrs, |builder| {
116             intravisit::walk_trait_item(builder, trait_item);
117         });
118     }
119
120     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
121         self.with_lint_attrs(impl_item.hir_id, &impl_item.attrs, |builder| {
122             intravisit::walk_impl_item(builder, impl_item);
123         });
124     }
125 }
126
127 pub fn provide(providers: &mut Providers<'_>) {
128     providers.lint_levels = lint_levels;
129 }