Disallow unsafe in derive
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index a3d6a1c..2d1269e 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -110,6 +110,9 @@
builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
.suggestion = remove the value
+builtin_macros_derive_unsafe_path = traits in `#[derive(...)]` don't accept `unsafe(...)`
+ .suggestion = remove the `unsafe(...)`
+
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
.custom = use `std::env::var({$var_expr})` to read the variable at run time
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index d14858e..d70eaa6 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -2,7 +2,7 @@
use crate::errors;
use rustc_ast as ast;
-use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
+use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind, Unsafe};
use rustc_expand::base::{
Annotatable, DeriveResolution, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier,
};
@@ -60,6 +60,7 @@ fn expand(
// Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the
// paths.
report_path_args(sess, meta);
+ report_unsafe_args(sess, meta);
meta.path.clone()
})
.map(|path| DeriveResolution {
@@ -159,3 +160,12 @@ fn report_path_args(sess: &Session, meta: &ast::MetaItem) {
}
}
}
+
+fn report_unsafe_args(sess: &Session, meta: &ast::MetaItem) {
+ match meta.unsafety {
+ Unsafe::Yes(span) => {
+ sess.dcx().emit_err(errors::DeriveUnsafePath { span });
+ }
+ Unsafe::No => {}
+ }
+}
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index d157703..b14eb2b 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -296,6 +296,13 @@ pub(crate) struct DerivePathArgsValue {
}
#[derive(Diagnostic)]
+#[diag(builtin_macros_derive_unsafe_path)]
+pub(crate) struct DeriveUnsafePath {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
#[diag(builtin_macros_no_default_variant)]
#[help]
pub(crate) struct NoDefaultVariant {
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 77cb617..dfef254 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -778,7 +778,8 @@ fn expand_invoc(
if let SyntaxExtensionKind::Derive(..) = ext {
self.gate_proc_macro_input(&item);
}
- // FIX THIS LATER
+ // The `MetaItem` representing the trait to derive can't
+ // have an unsafe around it (as of now).
let meta = ast::MetaItem {
unsafety: ast::Unsafe::No,
kind: MetaItemKind::Word,
diff --git a/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs b/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs
new file mode 100644
index 0000000..774ce86
--- /dev/null
+++ b/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs
@@ -0,0 +1,6 @@
+#![feature(unsafe_attributes)]
+
+#[derive(unsafe(Debug))] //~ ERROR: traits in `#[derive(...)]` don't accept `unsafe(...)`
+struct Foo;
+
+fn main() {}
diff --git a/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr
new file mode 100644
index 0000000..fc0daf1
--- /dev/null
+++ b/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr
@@ -0,0 +1,8 @@
+error: traits in `#[derive(...)]` don't accept `unsafe(...)`
+ --> $DIR/derive-unsafe-attributes.rs:3:10
+ |
+LL | #[derive(unsafe(Debug))]
+ | ^^^^^^
+
+error: aborting due to 1 previous error
+