]>
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 | |
60c5eb7d XL |
8 | use rustc_error_codes::*; |
9 | ||
416331ca | 10 | pub fn check(tcx: TyCtxt<'_>) { |
a1dfa0c6 | 11 | let mut unsafety = UnsafetyChecker { tcx }; |
0731742a | 12 | tcx.hir().krate().visit_all_item_likes(&mut unsafety); |
1a4d82fc JJ |
13 | } |
14 | ||
dc9dc135 XL |
15 | struct UnsafetyChecker<'tcx> { |
16 | tcx: TyCtxt<'tcx>, | |
1a4d82fc JJ |
17 | } |
18 | ||
dc9dc135 | 19 | impl UnsafetyChecker<'tcx> { |
c30ab7b3 SL |
20 | fn check_unsafety_coherence(&mut self, |
21 | item: &'v hir::Item, | |
22 | impl_generics: Option<&hir::Generics>, | |
e9174d1e | 23 | unsafety: hir::Unsafety, |
0bf4aa26 XL |
24 | polarity: hir::ImplPolarity) |
25 | { | |
416331ca | 26 | let local_did = self.tcx.hir().local_def_id(item.hir_id); |
532ac7d7 | 27 | if let Some(trait_ref) = self.tcx.impl_trait_ref(local_did) { |
0bf4aa26 XL |
28 | let trait_def = self.tcx.trait_def(trait_ref.def_id); |
29 | let unsafe_attr = impl_generics.and_then(|generics| { | |
30 | generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle") | |
31 | }); | |
32 | match (trait_def.unsafety, unsafe_attr, unsafety, polarity) { | |
33 | (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => { | |
34 | span_err!(self.tcx.sess, | |
35 | item.span, | |
36 | E0199, | |
37 | "implementing the trait `{}` is not unsafe", | |
60c5eb7d | 38 | trait_ref.print_only_trait_path()); |
0bf4aa26 | 39 | } |
1a4d82fc | 40 | |
0bf4aa26 XL |
41 | (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => { |
42 | span_err!(self.tcx.sess, | |
43 | item.span, | |
44 | E0200, | |
45 | "the trait `{}` requires an `unsafe impl` declaration", | |
60c5eb7d | 46 | trait_ref.print_only_trait_path()); |
0bf4aa26 | 47 | } |
85aaf69f | 48 | |
0bf4aa26 XL |
49 | (Unsafety::Normal, Some(attr_name), Unsafety::Normal, |
50 | hir::ImplPolarity::Positive) => | |
51 | { | |
52 | span_err!(self.tcx.sess, | |
53 | item.span, | |
54 | E0569, | |
55 | "requires an `unsafe impl` declaration due to `#[{}]` attribute", | |
56 | attr_name); | |
57 | } | |
c30ab7b3 | 58 | |
0bf4aa26 XL |
59 | (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => { |
60 | // Reported in AST validation | |
61 | self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl"); | |
62 | } | |
63 | (_, _, Unsafety::Normal, hir::ImplPolarity::Negative) | | |
64 | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) | | |
65 | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) | | |
66 | (Unsafety::Normal, None, Unsafety::Normal, _) => { | |
67 | // OK | |
1a4d82fc JJ |
68 | } |
69 | } | |
c34b1796 AL |
70 | } |
71 | } | |
72 | } | |
73 | ||
dc9dc135 | 74 | impl ItemLikeVisitor<'v> for UnsafetyChecker<'tcx> { |
e9174d1e | 75 | fn visit_item(&mut self, item: &'v hir::Item) { |
e74abb32 | 76 | if let hir::ItemKind::Impl(unsafety, polarity, _, ref generics, ..) = item.kind { |
0bf4aa26 | 77 | self.check_unsafety_coherence(item, Some(generics), unsafety, polarity); |
1a4d82fc | 78 | } |
1a4d82fc | 79 | } |
476ff2be | 80 | |
32a655c1 SL |
81 | fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { |
82 | } | |
83 | ||
476ff2be SL |
84 | fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { |
85 | } | |
1a4d82fc | 86 | } |