]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/coherence/unsafety.rs
On E0204 suggest missing type param bounds
[rust.git] / compiler / rustc_typeck / src / 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_errors::struct_span_err;
5 use rustc_hir as hir;
6 use rustc_hir::def::DefKind;
7 use rustc_hir::Unsafety;
8 use rustc_middle::ty::TyCtxt;
9
10 pub fn check(tcx: TyCtxt<'_>) {
11     for id in tcx.hir().items() {
12         if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
13             let item = tcx.hir().item(id);
14             if let hir::ItemKind::Impl(ref impl_) = item.kind {
15                 check_unsafety_coherence(
16                     tcx,
17                     item,
18                     Some(&impl_.generics),
19                     impl_.unsafety,
20                     impl_.polarity,
21                 );
22             }
23         }
24     }
25 }
26
27 fn check_unsafety_coherence<'tcx>(
28     tcx: TyCtxt<'tcx>,
29     item: &hir::Item<'_>,
30     impl_generics: Option<&hir::Generics<'_>>,
31     unsafety: hir::Unsafety,
32     polarity: hir::ImplPolarity,
33 ) {
34     if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) {
35         let trait_def = tcx.trait_def(trait_ref.def_id);
36         let unsafe_attr = impl_generics.and_then(|generics| {
37             generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
38         });
39         match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
40             (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
41                 struct_span_err!(
42                     tcx.sess,
43                     item.span,
44                     E0199,
45                     "implementing the trait `{}` is not unsafe",
46                     trait_ref.print_only_trait_path()
47                 )
48                 .emit();
49             }
50
51             (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
52                 struct_span_err!(
53                     tcx.sess,
54                     item.span,
55                     E0200,
56                     "the trait `{}` requires an `unsafe impl` declaration",
57                     trait_ref.print_only_trait_path()
58                 )
59                 .emit();
60             }
61
62             (Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => {
63                 struct_span_err!(
64                     tcx.sess,
65                     item.span,
66                     E0569,
67                     "requires an `unsafe impl` declaration due to `#[{}]` attribute",
68                     attr_name
69                 )
70                 .emit();
71             }
72
73             (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
74                 // Reported in AST validation
75                 tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
76             }
77             (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_))
78             | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive)
79             | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive)
80             | (Unsafety::Normal, None, Unsafety::Normal, _) => {
81                 // OK
82             }
83         }
84     }
85 }