]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_hir_analysis/src/coherence/unsafety.rs
change usages of impl_trait_ref to bound_impl_trait_ref
[rust.git] / compiler / rustc_hir_analysis / 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 use rustc_span::def_id::LocalDefId;
10
11 pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
12     debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Impl));
13     let item = tcx.hir().expect_item(def_id);
14     let hir::ItemKind::Impl(ref impl_) = item.kind else { bug!() };
15
16     if let Some(trait_ref) =
17         tcx.bound_impl_trait_ref(item.owner_id.to_def_id()).map(|t| t.subst_identity())
18     {
19         let trait_def = tcx.trait_def(trait_ref.def_id);
20         let unsafe_attr =
21             impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle");
22         match (trait_def.unsafety, unsafe_attr, impl_.unsafety, impl_.polarity) {
23             (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
24                 struct_span_err!(
25                     tcx.sess,
26                     tcx.def_span(def_id),
27                     E0199,
28                     "implementing the trait `{}` is not unsafe",
29                     trait_ref.print_only_trait_path()
30                 )
31                 .span_suggestion_verbose(
32                     item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)),
33                     "remove `unsafe` from this trait implementation",
34                     "",
35                     rustc_errors::Applicability::MachineApplicable,
36                 )
37                 .emit();
38             }
39
40             (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
41                 struct_span_err!(
42                     tcx.sess,
43                     tcx.def_span(def_id),
44                     E0200,
45                     "the trait `{}` requires an `unsafe impl` declaration",
46                     trait_ref.print_only_trait_path()
47                 )
48                 .note(format!(
49                     "the trait `{}` enforces invariants that the compiler can't check. \
50                     Review the trait documentation and make sure this implementation \
51                     upholds those invariants before adding the `unsafe` keyword",
52                     trait_ref.print_only_trait_path()
53                 ))
54                 .span_suggestion_verbose(
55                     item.span.shrink_to_lo(),
56                     "add `unsafe` to this trait implementation",
57                     "unsafe ",
58                     rustc_errors::Applicability::MaybeIncorrect,
59                 )
60                 .emit();
61             }
62
63             (Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => {
64                 struct_span_err!(
65                     tcx.sess,
66                     tcx.def_span(def_id),
67                     E0569,
68                     "requires an `unsafe impl` declaration due to `#[{}]` attribute",
69                     attr_name
70                 )
71                 .note(format!(
72                     "the trait `{}` enforces invariants that the compiler can't check. \
73                     Review the trait documentation and make sure this implementation \
74                     upholds those invariants before adding the `unsafe` keyword",
75                     trait_ref.print_only_trait_path()
76                 ))
77                 .span_suggestion_verbose(
78                     item.span.shrink_to_lo(),
79                     "add `unsafe` to this trait implementation",
80                     "unsafe ",
81                     rustc_errors::Applicability::MaybeIncorrect,
82                 )
83                 .emit();
84             }
85
86             (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
87                 // Reported in AST validation
88                 tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
89             }
90             (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_))
91             | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive)
92             | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive)
93             | (Unsafety::Normal, None, Unsafety::Normal, _) => {
94                 // OK
95             }
96         }
97     }
98 }