]> git.proxmox.com Git - rustc.git/blame - src/librustc_typeck/coherence/unsafety.rs
New upstream version 1.38.0+dfsg1
[rustc.git] / src / librustc_typeck / coherence / unsafety.rs
CommitLineData
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 4use rustc::ty::TyCtxt;
476ff2be 5use rustc::hir::itemlikevisit::ItemLikeVisitor;
c30ab7b3 6use rustc::hir::{self, Unsafety};
1a4d82fc 7
416331ca 8pub 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
13struct UnsafetyChecker<'tcx> {
14 tcx: TyCtxt<'tcx>,
1a4d82fc
JJ
15}
16
dc9dc135 17impl 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 72impl 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}