about summary refs log tree commit diff
path: root/compiler/rustc_passes/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_passes/src')
-rw-r--r--compiler/rustc_passes/src/check_attr.rs28
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs2
-rw-r--r--compiler/rustc_passes/src/errors.rs11
3 files changed, 34 insertions, 7 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index a47add929eb..c93fb5c23b1 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -189,6 +189,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
                 [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
                 [sym::must_use, ..] => self.check_must_use(hir_id, attr, target),
+                [sym::may_dangle, ..] => self.check_may_dangle(hir_id, attr),
                 [sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target),
                 [sym::rustc_allow_incoherent_impl, ..] => {
                     self.check_allow_incoherent_impl(attr, span, target)
@@ -255,7 +256,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     | sym::cfg_attr
                     // need to be fixed
                     | sym::cfi_encoding // FIXME(cfi_encoding)
-                    | sym::may_dangle // FIXME(dropck_eyepatch)
                     | sym::pointee // FIXME(derive_smart_pointer)
                     | sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section)
                     | sym::used // handled elsewhere to restrict to static items
@@ -1363,7 +1363,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    /// Checks if `#[must_not_suspend]` is applied to a function.
+    /// Checks if `#[must_not_suspend]` is applied to a struct, enum, union, or trait.
     fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) {
         match target {
             Target::Struct | Target::Enum | Target::Union | Target::Trait => {}
@@ -1373,6 +1373,27 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
+    /// Checks if `#[may_dangle]` is applied to a lifetime or type generic parameter in `Drop` impl.
+    fn check_may_dangle(&self, hir_id: HirId, attr: &Attribute) {
+        if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id)
+            && matches!(
+                param.kind,
+                hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. }
+            )
+            && matches!(param.source, hir::GenericParamSource::Generics)
+            && let parent_hir_id = self.tcx.parent_hir_id(hir_id)
+            && let hir::Node::Item(item) = self.tcx.hir_node(parent_hir_id)
+            && let hir::ItemKind::Impl(impl_) = item.kind
+            && let Some(trait_) = impl_.of_trait
+            && let Some(def_id) = trait_.trait_def_id()
+            && self.tcx.is_lang_item(def_id, hir::LangItem::Drop)
+        {
+            return;
+        }
+
+        self.dcx().emit_err(errors::InvalidMayDangle { attr_span: attr.span });
+    }
+
     /// Checks if `#[cold]` is applied to a non-function.
     fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
         match target {
@@ -2598,8 +2619,7 @@ fn check_duplicates(
                             warning: matches!(
                                 duplicates,
                                 FutureWarnFollowing | FutureWarnPreceding
-                            )
-                            .then_some(()),
+                            ),
                         },
                     );
                 }
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 659281c5e71..624ebb2f9f2 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -49,7 +49,7 @@ fn report_duplicate_item(
         orig_span,
         crate_name: tcx.crate_name(item_def_id.krate),
         orig_crate_name: tcx.crate_name(original_def_id.krate),
-        different_crates: (item_def_id.krate != original_def_id.krate).then_some(()),
+        different_crates: (item_def_id.krate != original_def_id.krate),
         name,
     });
 }
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 3a043e0e3c1..1190e60f41f 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -737,6 +737,13 @@ pub struct NonExportedMacroInvalidAttrs {
     pub attr_span: Span,
 }
 
+#[derive(Diagnostic)]
+#[diag(passes_may_dangle)]
+pub struct InvalidMayDangle {
+    #[primary_span]
+    pub attr_span: Span,
+}
+
 #[derive(LintDiagnostic)]
 #[diag(passes_unused_duplicate)]
 pub struct UnusedDuplicate {
@@ -745,7 +752,7 @@ pub struct UnusedDuplicate {
     #[note]
     pub other: Span,
     #[warning]
-    pub warning: Option<()>,
+    pub warning: bool,
 }
 
 #[derive(Diagnostic)]
@@ -904,7 +911,7 @@ pub struct DuplicateDiagnosticItemInCrate {
     #[note(passes_diagnostic_item_first_defined)]
     pub orig_span: Option<Span>,
     #[note]
-    pub different_crates: Option<()>,
+    pub different_crates: bool,
     pub crate_name: Symbol,
     pub orig_crate_name: Symbol,
     pub name: Symbol,