about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/coherence/unsafety.rs219
1 files changed, 136 insertions, 83 deletions
diff --git a/compiler/rustc_typeck/src/coherence/unsafety.rs b/compiler/rustc_typeck/src/coherence/unsafety.rs
index f7aabf2406f..619bae9b7ed 100644
--- a/compiler/rustc_typeck/src/coherence/unsafety.rs
+++ b/compiler/rustc_typeck/src/coherence/unsafety.rs
@@ -3,101 +3,154 @@
 
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::def::DefKind;
 use rustc_hir::Unsafety;
 use rustc_middle::ty::TyCtxt;
 
 pub fn check(tcx: TyCtxt<'_>) {
-    let mut unsafety = UnsafetyChecker { tcx };
-    tcx.hir().visit_all_item_likes(&mut unsafety);
+    for id in tcx.hir().items() {
+        if matches!(tcx.hir().def_kind(id.def_id), DefKind::Impl) {
+            let item = tcx.hir().item(id);
+            if let hir::ItemKind::Impl(ref impl_) = item.kind {
+                check_unsafety_coherence(
+                    tcx,
+                    item,
+                    Some(&impl_.generics),
+                    impl_.unsafety,
+                    impl_.polarity,
+                );
+            }
+        }
+    }
 }
 
-struct UnsafetyChecker<'tcx> {
+fn check_unsafety_coherence<'tcx>(
     tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> UnsafetyChecker<'tcx> {
-    fn check_unsafety_coherence(
-        &mut self,
-        item: &hir::Item<'_>,
-        impl_generics: Option<&hir::Generics<'_>>,
-        unsafety: hir::Unsafety,
-        polarity: hir::ImplPolarity,
-    ) {
-        if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id) {
-            let trait_def = self.tcx.trait_def(trait_ref.def_id);
-            let unsafe_attr = impl_generics.and_then(|generics| {
-                generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
-            });
-            match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
-                (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
-                    struct_span_err!(
-                        self.tcx.sess,
-                        item.span,
-                        E0199,
-                        "implementing the trait `{}` is not unsafe",
-                        trait_ref.print_only_trait_path()
-                    )
-                    .emit();
-                }
+    item: &hir::Item<'_>,
+    impl_generics: Option<&hir::Generics<'_>>,
+    unsafety: hir::Unsafety,
+    polarity: hir::ImplPolarity,
+) {
+    if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) {
+        let trait_def = tcx.trait_def(trait_ref.def_id);
+        let unsafe_attr = impl_generics.and_then(|generics| {
+            generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
+        });
+        match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
+            (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
+                struct_span_err!(
+                    tcx.sess,
+                    item.span,
+                    E0199,
+                    "implementing the trait `{}` is not unsafe",
+                    trait_ref.print_only_trait_path()
+                )
+                .emit();
+            }
 
-                (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
-                    struct_span_err!(
-                        self.tcx.sess,
-                        item.span,
-                        E0200,
-                        "the trait `{}` requires an `unsafe impl` declaration",
-                        trait_ref.print_only_trait_path()
-                    )
-                    .emit();
-                }
+            (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
+                struct_span_err!(
+                    tcx.sess,
+                    item.span,
+                    E0200,
+                    "the trait `{}` requires an `unsafe impl` declaration",
+                    trait_ref.print_only_trait_path()
+                )
+                .emit();
+            }
 
-                (
-                    Unsafety::Normal,
-                    Some(attr_name),
-                    Unsafety::Normal,
-                    hir::ImplPolarity::Positive,
-                ) => {
-                    struct_span_err!(
-                        self.tcx.sess,
-                        item.span,
-                        E0569,
-                        "requires an `unsafe impl` declaration due to `#[{}]` attribute",
-                        attr_name
-                    )
-                    .emit();
-                }
+            (Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => {
+                struct_span_err!(
+                    tcx.sess,
+                    item.span,
+                    E0569,
+                    "requires an `unsafe impl` declaration due to `#[{}]` attribute",
+                    attr_name
+                )
+                .emit();
+            }
 
-                (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
-                    // Reported in AST validation
-                    self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
-                }
-                (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_))
-                | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive)
-                | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive)
-                | (Unsafety::Normal, None, Unsafety::Normal, _) => {
-                    // OK
-                }
+            (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
+                // Reported in AST validation
+                tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
+            }
+            (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_))
+            | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive)
+            | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive)
+            | (Unsafety::Normal, None, Unsafety::Normal, _) => {
+                // OK
             }
         }
     }
 }
 
-impl<'tcx> ItemLikeVisitor<'_> for UnsafetyChecker<'tcx> {
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        if let hir::ItemKind::Impl(ref impl_) = item.kind {
-            self.check_unsafety_coherence(
-                item,
-                Some(&impl_.generics),
-                impl_.unsafety,
-                impl_.polarity,
-            );
-        }
-    }
-
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
-
-    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
-}
+// struct UnsafetyChecker<'tcx> {
+//     tcx: TyCtxt<'tcx>,
+// }
+//
+// impl<'tcx> UnsafetyChecker<'tcx> {
+//     fn check_unsafety_coherence(
+//         &mut self,
+//         item: &hir::Item<'_>,
+//         impl_generics: Option<&hir::Generics<'_>>,
+//         unsafety: hir::Unsafety,
+//         polarity: hir::ImplPolarity,
+//     ) {
+//         if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id) {
+//             let trait_def = self.tcx.trait_def(trait_ref.def_id);
+//             let unsafe_attr = impl_generics.and_then(|generics| {
+//                 generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
+//             });
+//             match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
+//                 (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
+//                     struct_span_err!(
+//                         self.tcx.sess,
+//                         item.span,
+//                         E0199,
+//                         "implementing the trait `{}` is not unsafe",
+//                         trait_ref.print_only_trait_path()
+//                     )
+//                     .emit();
+//                 }
+//
+//                 (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
+//                     struct_span_err!(
+//                         self.tcx.sess,
+//                         item.span,
+//                         E0200,
+//                         "the trait `{}` requires an `unsafe impl` declaration",
+//                         trait_ref.print_only_trait_path()
+//                     )
+//                     .emit();
+//                 }
+//
+//                 (
+//                     Unsafety::Normal,
+//                     Some(attr_name),
+//                     Unsafety::Normal,
+//                     hir::ImplPolarity::Positive,
+//                 ) => {
+//                     struct_span_err!(
+//                         self.tcx.sess,
+//                         item.span,
+//                         E0569,
+//                         "requires an `unsafe impl` declaration due to `#[{}]` attribute",
+//                         attr_name
+//                     )
+//                     .emit();
+//                 }
+//
+//                 (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
+//                     // Reported in AST validation
+//                     self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
+//                 }
+//                 (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_))
+//                 | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive)
+//                 | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive)
+//                 | (Unsafety::Normal, None, Unsafety::Normal, _) => {
+//                     // OK
+//                 }
+//             }
+//         }
+//     }
+// }