]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/coherence/unsafety.rs
Rollup merge of #64876 - vertexclique:vcq/fix-fn-name-intrinsic-op-unsafety, r=varkor
[rust.git] / src / librustc_typeck / coherence / unsafety.rs
1 //! Unsafety checker: every impl either implements a trait defined in this
2 //! crate or pertains to a type defined in this crate.
3
4 use rustc::ty::TyCtxt;
5 use rustc::hir::itemlikevisit::ItemLikeVisitor;
6 use rustc::hir::{self, Unsafety};
7
8 pub fn check(tcx: TyCtxt<'_>) {
9     let mut unsafety = UnsafetyChecker { tcx };
10     tcx.hir().krate().visit_all_item_likes(&mut unsafety);
11 }
12
13 struct UnsafetyChecker<'tcx> {
14     tcx: TyCtxt<'tcx>,
15 }
16
17 impl UnsafetyChecker<'tcx> {
18     fn check_unsafety_coherence(&mut self,
19                                 item: &'v hir::Item,
20                                 impl_generics: Option<&hir::Generics>,
21                                 unsafety: hir::Unsafety,
22                                 polarity: hir::ImplPolarity)
23     {
24         let local_did = self.tcx.hir().local_def_id(item.hir_id);
25         if let Some(trait_ref) = self.tcx.impl_trait_ref(local_did) {
26             let trait_def = self.tcx.trait_def(trait_ref.def_id);
27             let unsafe_attr = impl_generics.and_then(|generics| {
28                 generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
29             });
30             match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
31                 (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
32                     span_err!(self.tcx.sess,
33                               item.span,
34                               E0199,
35                               "implementing the trait `{}` is not unsafe",
36                               trait_ref);
37                 }
38
39                 (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
40                     span_err!(self.tcx.sess,
41                               item.span,
42                               E0200,
43                               "the trait `{}` requires an `unsafe impl` declaration",
44                               trait_ref);
45                 }
46
47                 (Unsafety::Normal, Some(attr_name), Unsafety::Normal,
48                     hir::ImplPolarity::Positive) =>
49                 {
50                     span_err!(self.tcx.sess,
51                               item.span,
52                               E0569,
53                               "requires an `unsafe impl` declaration due to `#[{}]` attribute",
54                               attr_name);
55                 }
56
57                 (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
58                     // Reported in AST validation
59                     self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
60                 }
61                 (_, _, Unsafety::Normal, hir::ImplPolarity::Negative) |
62                 (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) |
63                 (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) |
64                 (Unsafety::Normal, None, Unsafety::Normal, _) => {
65                     // OK
66                 }
67             }
68         }
69     }
70 }
71
72 impl ItemLikeVisitor<'v> for UnsafetyChecker<'tcx> {
73     fn visit_item(&mut self, item: &'v hir::Item) {
74         if let hir::ItemKind::Impl(unsafety, polarity, _, ref generics, ..) = item.kind {
75             self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
76         }
77     }
78
79     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
80     }
81
82     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
83     }
84 }