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