]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //! Unsafety checker: every impl either implements a trait defined in this |
2 | //! crate or pertains to a type defined in this crate. | |
3 | ||
54a0048b | 4 | use rustc::ty::TyCtxt; |
476ff2be | 5 | use rustc::hir::itemlikevisit::ItemLikeVisitor; |
c30ab7b3 | 6 | use rustc::hir::{self, Unsafety}; |
1a4d82fc | 7 | |
416331ca | 8 | pub fn check(tcx: TyCtxt<'_>) { |
a1dfa0c6 | 9 | let mut unsafety = UnsafetyChecker { tcx }; |
0731742a | 10 | tcx.hir().krate().visit_all_item_likes(&mut unsafety); |
1a4d82fc JJ |
11 | } |
12 | ||
dc9dc135 XL |
13 | struct UnsafetyChecker<'tcx> { |
14 | tcx: TyCtxt<'tcx>, | |
1a4d82fc JJ |
15 | } |
16 | ||
dc9dc135 | 17 | impl UnsafetyChecker<'tcx> { |
c30ab7b3 SL |
18 | fn check_unsafety_coherence(&mut self, |
19 | item: &'v hir::Item, | |
20 | impl_generics: Option<&hir::Generics>, | |
e9174d1e | 21 | unsafety: hir::Unsafety, |
0bf4aa26 XL |
22 | polarity: hir::ImplPolarity) |
23 | { | |
416331ca | 24 | let local_did = self.tcx.hir().local_def_id(item.hir_id); |
532ac7d7 | 25 | if let Some(trait_ref) = self.tcx.impl_trait_ref(local_did) { |
0bf4aa26 XL |
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 | } | |
1a4d82fc | 38 | |
0bf4aa26 XL |
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 | } | |
85aaf69f | 46 | |
0bf4aa26 XL |
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 | } | |
c30ab7b3 | 56 | |
0bf4aa26 XL |
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 | |
1a4d82fc JJ |
66 | } |
67 | } | |
c34b1796 AL |
68 | } |
69 | } | |
70 | } | |
71 | ||
dc9dc135 | 72 | impl ItemLikeVisitor<'v> for UnsafetyChecker<'tcx> { |
e9174d1e | 73 | fn visit_item(&mut self, item: &'v hir::Item) { |
0bf4aa26 XL |
74 | if let hir::ItemKind::Impl(unsafety, polarity, _, ref generics, ..) = item.node { |
75 | self.check_unsafety_coherence(item, Some(generics), unsafety, polarity); | |
1a4d82fc | 76 | } |
1a4d82fc | 77 | } |
476ff2be | 78 | |
32a655c1 SL |
79 | fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { |
80 | } | |
81 | ||
476ff2be SL |
82 | fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { |
83 | } | |
1a4d82fc | 84 | } |