Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,14 +642,13 @@ pub(crate) struct LinkageParser;
impl SingleAttributeParser for LinkageParser {
const PATH: &[Symbol] = &[sym::linkage];
const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
Allow(Target::Fn),
Allow(Target::Fn), // const fn denied in check_attr
Allow(Target::Method(MethodKind::Inherent)),
Allow(Target::Method(MethodKind::Trait { body: true })),
Allow(Target::Method(MethodKind::TraitImpl)),
Allow(Target::Static),
Allow(Target::ForeignStatic),
Allow(Target::ForeignStatic), // extern static mut denied in check_attr
Allow(Target::ForeignFn),
Warn(Target::Method(MethodKind::Trait { body: false })), // Not inherited
]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: [
"available_externally",
Expand Down
10 changes: 2 additions & 8 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,16 +198,10 @@ fn process_builtin_attrs(
codegen_fn_attrs.import_linkage = linkage;

if tcx.is_mutable_static(did.into()) {
let mut diag = tcx.dcx().struct_span_err(
tcx.dcx().span_delayed_bug(
*span,
"extern mutable statics are not allowed with `#[linkage]`",
"`extern { #[linkage] static mut ...` is checked in check_attr}",
);
diag.note(
"marking the extern static mutable would allow changing which \
symbol the static references rather than make the target of the \
symbol mutable",
);
diag.emit();
}
} else {
codegen_fn_attrs.linkage = linkage;
Expand Down
29 changes: 28 additions & 1 deletion compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttributeKind::OnTypeError { directive, .. } => {
self.check_diagnostic_on_type_error(hir_id, directive.as_deref())
}
AttributeKind::Linkage(_linkage, span) => {
self.check_linkage(*span, hir_id, target, item)
}

// All of the following attributes have no specific checks.
// tidy-alphabetical-start
Expand Down Expand Up @@ -268,7 +271,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttributeKind::LinkName { .. } => (),
AttributeKind::LinkOrdinal { .. } => (),
AttributeKind::LinkSection { .. } => (),
AttributeKind::Linkage(..) => (),
AttributeKind::LoopMatch(..) => {}
AttributeKind::MacroEscape => (),
AttributeKind::MacroUse { .. } => (),
Expand Down Expand Up @@ -1627,6 +1629,31 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
.emit_err(diagnostics::BothOptimizeNoneAndInline { optimize_span, inline_span });
}
}

fn check_linkage(
&self,
span: Span,
hir_id: HirId,
target: Target,
item: Option<&'tcx Item<'tcx>>,
) {
// FIXME(eii) Once eii is no longer so experimental, suggest doing
// linkage stuff with externally implementable items instead
match target {
Target::ForeignStatic
if self.tcx.is_mutable_static(hir_id.expect_owner().def_id.into()) =>
{
self.tcx.dcx().emit_err(diagnostics::StaticMutLinkage { span });
}
Target::Fn
if let Item { kind: ItemKind::Fn { sig, .. }, .. } = item.unwrap()
&& matches!(sig.header.constness, Constness::Const { .. }) =>
{
self.tcx.dcx().emit_err(diagnostics::ConstFnLinkage { span });
}
_ => {}
}
}
}

impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_passes/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1190,3 +1190,23 @@ pub(crate) struct OnTypeErrorMalformedFormatLiterals {
pub(crate) struct OnTypeErrorNotExactlyOneGeneric {
pub count: usize,
}

#[derive(Diagnostic)]
#[diag("extern mutable statics are incompatible with the `linkage` attribute")]
#[note(
"the `linkage` attribute on extern statics generates a symbol that contains the address of \
another static. Making the extern static mutable would allow changing the address, rather \
than the static the address is pointing to"
)]
pub(crate) struct StaticMutLinkage {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("`const fn` are incompatible with the `linkage` attribute")]
#[note("`const fn` may be called at compile time, which happens before linking")]
pub(crate) struct ConstFnLinkage {
#[primary_span]
pub span: Span,
}
3 changes: 1 addition & 2 deletions tests/ui/attributes/codegen_attr_on_required_trait_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ trait Test {
//~| WARN previously accepted
fn method2(&self);
#[linkage = "common"]
//~^ ERROR cannot be used on required trait methods [unused_attributes]
//~| WARN previously accepted
//~^ ERROR `linkage` attribute cannot be used on required trait methods
fn method3(&self);
#[track_caller]
fn method4(&self);
Expand Down
17 changes: 8 additions & 9 deletions tests/ui/attributes/codegen_attr_on_required_trait_method.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
error: the `linkage` attribute cannot be used on required trait methods
--> $DIR/codegen_attr_on_required_trait_method.rs:14:7
|
LL | #[linkage = "common"]
| ^^^^^^^
|
= help: the `linkage` attribute can be applied to foreign functions, foreign statics, functions with a body, and statics

error: the `cold` attribute cannot be used on required trait methods
--> $DIR/codegen_attr_on_required_trait_method.rs:6:7
|
Expand All @@ -21,14 +29,5 @@ LL | #[link_section = "__TEXT,__text"]
= help: the `link_section` attribute can be applied to functions with a body and statics
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

error: the `linkage` attribute cannot be used on required trait methods
--> $DIR/codegen_attr_on_required_trait_method.rs:14:7
|
LL | #[linkage = "common"]
| ^^^^^^^
|
= help: the `linkage` attribute can be applied to foreign functions, foreign statics, functions with a body, and statics
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

error: aborting due to 3 previous errors

7 changes: 6 additions & 1 deletion tests/ui/attributes/linkage.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![crate_type = "lib"]
#![feature(linkage)]
#![feature(stmt_expr_attributes)]
#![deny(unused_attributes)]
Expand Down Expand Up @@ -35,8 +36,12 @@ extern "C" {
fn bar();
}

fn main() {
fn foo() {
let _ = #[linkage = "weak"]
(|| 1);
//~^^ ERROR attribute cannot be used on
}

#[linkage = "weak"]
//~^ERROR `const fn` are incompatible with the `linkage` attribute
const fn linkage() {}
22 changes: 15 additions & 7 deletions tests/ui/attributes/linkage.stderr
Original file line number Diff line number Diff line change
@@ -1,50 +1,58 @@
error: the `linkage` attribute cannot be used on type aliases
--> $DIR/linkage.rs:6:3
--> $DIR/linkage.rs:7:3
|
LL | #[linkage = "weak"]
| ^^^^^^^
|
= help: the `linkage` attribute can be applied to foreign statics, functions, and statics

error: the `linkage` attribute cannot be used on modules
--> $DIR/linkage.rs:9:3
--> $DIR/linkage.rs:10:3
|
LL | #[linkage = "weak"]
| ^^^^^^^
|
= help: the `linkage` attribute can be applied to foreign statics, functions, and statics

error: the `linkage` attribute cannot be used on structs
--> $DIR/linkage.rs:12:3
--> $DIR/linkage.rs:13:3
|
LL | #[linkage = "weak"]
| ^^^^^^^
|
= help: the `linkage` attribute can be applied to foreign statics, functions, and statics

error: the `linkage` attribute cannot be used on inherent impl blocks
--> $DIR/linkage.rs:15:3
--> $DIR/linkage.rs:16:3
|
LL | #[linkage = "weak"]
| ^^^^^^^
|
= help: the `linkage` attribute can be applied to foreign statics, functions, and statics

error: the `linkage` attribute cannot be used on expressions
--> $DIR/linkage.rs:23:7
--> $DIR/linkage.rs:24:7
|
LL | #[linkage = "weak"]
| ^^^^^^^
|
= help: the `linkage` attribute can be applied to foreign statics, functions, and statics

error: the `linkage` attribute cannot be used on closures
--> $DIR/linkage.rs:39:15
--> $DIR/linkage.rs:40:15
|
LL | let _ = #[linkage = "weak"]
| ^^^^^^^
|
= help: the `linkage` attribute can be applied to foreign functions, foreign statics, functions, methods, and statics

error: aborting due to 6 previous errors
error: `const fn` are incompatible with the `linkage` attribute
--> $DIR/linkage.rs:45:1
|
LL | #[linkage = "weak"]
| ^^^^^^^^^^^^^^^^^^^
|
= note: `const fn` may be called at compile time, which happens before linking

error: aborting due to 7 previous errors

3 changes: 2 additions & 1 deletion tests/ui/linkage-attr/linkage-attr-mutable-static.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
fn main() {
#[rustfmt::skip]
extern "C" {
#[linkage = "extern_weak"] //~ ERROR extern mutable statics are not allowed with `#[linkage]`
#[linkage = "extern_weak"]
//~^ ERROR extern mutable statics are incompatible with the `linkage` attribute
static mut EXTERN_WEAK: *const u8;
}

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/linkage-attr/linkage-attr-mutable-static.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
error: extern mutable statics are not allowed with `#[linkage]`
error: extern mutable statics are incompatible with the `linkage` attribute
--> $DIR/linkage-attr-mutable-static.rs:11:9
|
LL | #[linkage = "extern_weak"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: marking the extern static mutable would allow changing which symbol the static references rather than make the target of the symbol mutable
= note: the `linkage` attribute on extern statics generates a symbol that contains the address of another static. Making the extern static mutable would allow changing the address, rather than the static the address is pointing to

error: aborting due to 1 previous error

Loading