From 2a41d4dff6e89622cee963c53bb8b57343481153 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 9 Apr 2026 21:42:34 +0200 Subject: [PATCH 1/4] error on invalid macho section specifier --- .../src/attributes/link_attrs.rs | 40 ++++++++++++- .../src/session_diagnostics.rs | 19 ++++++ .../rustc_hir/src/attrs/data_structures.rs | 2 +- .../codegen-llvm/naked-fn/naked-functions.rs | 7 ++- tests/ui/linkage-attr/link-section-macho.rs | 58 +++++++++++++++++++ .../ui/linkage-attr/link-section-macho.stderr | 37 ++++++++++++ 6 files changed, 158 insertions(+), 5 deletions(-) create mode 100644 tests/ui/linkage-attr/link-section-macho.rs create mode 100644 tests/ui/linkage-attr/link-section-macho.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 8aa7759daa043..6e28b26d04a94 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -14,8 +14,9 @@ use crate::attributes::cfg::parse_cfg_entry; use crate::session_diagnostics::{ AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ExportSymbolsNeedsStatic, ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink, InvalidLinkModifier, - LinkFrameworkApple, LinkOrdinalOutOfRange, LinkRequiresName, MultipleModifiers, - NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows, WholeArchiveNeedsStatic, + InvalidMachoSection, InvalidMachoSectionReason, LinkFrameworkApple, LinkOrdinalOutOfRange, + LinkRequiresName, MultipleModifiers, NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows, + WholeArchiveNeedsStatic, }; pub(crate) struct LinkNameParser; @@ -460,6 +461,29 @@ impl LinkParser { pub(crate) struct LinkSectionParser; +fn check_link_section_macho(name: Symbol) -> Result<(), InvalidMachoSectionReason> { + let mut parts = name.as_str().split(',').map(|s| s.trim()); + + // The segment can be empty. + let _segment = parts.next(); + + // But the section is required. + let section = match parts.next() { + None | Some("") => return Err(InvalidMachoSectionReason::MissingSection), + Some(section) => section, + }; + + if section.len() > 16 { + return Err(InvalidMachoSectionReason::SectionTooLong { section: section.to_string() }); + } + + // LLVM also checks the other components of the section specifier, but that logic is hard to + // keep in sync. We skip it here for now, assuming that if you got that far you'll be able + // to interpret the LLVM errors. + + Ok(()) +} + impl SingleAttributeParser for LinkSectionParser { const PATH: &[Symbol] = &[sym::link_section]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; @@ -492,6 +516,18 @@ impl SingleAttributeParser for LinkSectionParser { return None; } + // We (currently) only validate macho section specifiers. + match cx.sess.target.binary_format { + BinaryFormat::MachO => match check_link_section_macho(name) { + Ok(()) => {} + Err(reason) => { + cx.emit_err(InvalidMachoSection { name_span: nv.value_span, reason }); + return None; + } + }, + BinaryFormat::Coff | BinaryFormat::Elf | BinaryFormat::Wasm | BinaryFormat::Xcoff => {} + } + Some(LinkSection { name, span: cx.attr_span }) } } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index ace233acbd50b..bb1e6d14e9af8 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -1133,3 +1133,22 @@ pub(crate) struct UnstableAttrForAlreadyStableFeature { #[label("the stability attribute annotates this item")] pub item_span: Span, } + +#[derive(Diagnostic)] +#[diag("invalid Mach-O section specifier")] +pub(crate) struct InvalidMachoSection { + #[primary_span] + #[label("not a valid Mach-O section specifier")] + pub name_span: Span, + #[subdiagnostic] + pub reason: InvalidMachoSectionReason, +} + +#[derive(Subdiagnostic)] +pub(crate) enum InvalidMachoSectionReason { + #[note("a Mach-O section specifier requires a segment and a section, separated by a comma")] + #[help("an example of a valid Mach-O section specifier is `__TEXT,__cstring`")] + MissingSection, + #[note("section name `{$section}` is longer than 16 bytes")] + SectionTooLong { section: String }, +} diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 48b03bc946591..3832b02b18366 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1090,8 +1090,8 @@ pub enum AttributeKind { /// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute) LinkSection { - name: Symbol, span: Span, + name: Symbol, }, /// Represents `#[linkage]`. diff --git a/tests/codegen-llvm/naked-fn/naked-functions.rs b/tests/codegen-llvm/naked-fn/naked-functions.rs index b5c84ede8f063..770b2b21e8fe0 100644 --- a/tests/codegen-llvm/naked-fn/naked-functions.rs +++ b/tests/codegen-llvm/naked-fn/naked-functions.rs @@ -145,13 +145,16 @@ pub extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize { } // linux: .pushsection .text.some_different_name,\22ax\22, @progbits -// macos: .pushsection .text.some_different_name,regular,pure_instructions +// macos: .pushsection __TEXT,different,regular,pure_instructions // win_x86,win_i686: .pushsection .text.some_different_name,\22xr\22 // thumb: .pushsection .text.some_different_name,\22ax\22, %progbits // CHECK-LABEL: test_link_section: #[no_mangle] #[unsafe(naked)] -#[link_section = ".text.some_different_name"] +// FIXME: configure this with `cfg(target_binary_format = "mach-o")`, +// see https://github.com/rust-lang/rust/issues/152586. +#[cfg_attr(not(target_vendor = "apple"), link_section = ".text.some_different_name")] +#[cfg_attr(target_vendor = "apple", link_section = "__TEXT,different")] pub extern "C" fn test_link_section() { cfg_select! { all(target_arch = "arm", target_feature = "thumb-mode") => { diff --git a/tests/ui/linkage-attr/link-section-macho.rs b/tests/ui/linkage-attr/link-section-macho.rs new file mode 100644 index 0000000000000..b414a8cc18607 --- /dev/null +++ b/tests/ui/linkage-attr/link-section-macho.rs @@ -0,0 +1,58 @@ +//@ add-minicore +//@ compile-flags: --target aarch64-apple-darwin +//@ needs-llvm-components: aarch64 +//@ ignore-backends: gcc +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +#[unsafe(link_section = "foo")] +//~^ ERROR invalid Mach-O section specifier +#[unsafe(no_mangle)] +fn missing_section() {} + +#[unsafe(link_section = "foo,")] +//~^ ERROR invalid Mach-O section specifier +#[unsafe(no_mangle)] +fn empty_section() {} + +#[unsafe(link_section = "foo, ")] +//~^ ERROR invalid Mach-O section specifier +#[unsafe(no_mangle)] +fn whitespace_section() {} + +#[unsafe(link_section = "foo,somelongwindedthing")] +//~^ ERROR invalid Mach-O section specifier +#[unsafe(no_mangle)] +fn section_too_long() {} + +#[unsafe(link_section = "foo,bar")] +#[unsafe(no_mangle)] +fn segment_and_section() {} + +#[unsafe(link_section = "foo,bar,")] +#[unsafe(no_mangle)] +fn segment_and_section_and_comma() {} + +#[unsafe(link_section = ",foo")] +#[unsafe(no_mangle)] +fn missing_segment_is_fine() {} + +#[unsafe(link_section = "__TEXT,__stubs,symbol_stubs,none,16")] +#[unsafe(no_mangle)] +fn stub_size_decimal() {} + +#[unsafe(link_section = "__TEXT,__stubs,symbol_stubs,none,0x10")] +#[unsafe(no_mangle)] +fn stub_size_hex() {} + +#[unsafe(link_section = "__TEXT,__stubs,symbol_stubs,none,020")] +#[unsafe(no_mangle)] +fn stub_size_oct() {} + +#[unsafe(link_section = "__TEXT,__stubs,symbol_stubs,none,020,rest,is,ignored")] +#[unsafe(no_mangle)] +fn rest_is_ignored() {} diff --git a/tests/ui/linkage-attr/link-section-macho.stderr b/tests/ui/linkage-attr/link-section-macho.stderr new file mode 100644 index 0000000000000..42eac39c78069 --- /dev/null +++ b/tests/ui/linkage-attr/link-section-macho.stderr @@ -0,0 +1,37 @@ +error: invalid Mach-O section specifier + --> $DIR/link-section-macho.rs:12:25 + | +LL | #[unsafe(link_section = "foo")] + | ^^^^^ not a valid Mach-O section specifier + | + = note: a Mach-O section specifier requires a segment and a section, separated by a comma + = help: an example of a valid Mach-O section specifier is `__TEXT,__cstring` + +error: invalid Mach-O section specifier + --> $DIR/link-section-macho.rs:17:25 + | +LL | #[unsafe(link_section = "foo,")] + | ^^^^^^ not a valid Mach-O section specifier + | + = note: a Mach-O section specifier requires a segment and a section, separated by a comma + = help: an example of a valid Mach-O section specifier is `__TEXT,__cstring` + +error: invalid Mach-O section specifier + --> $DIR/link-section-macho.rs:22:25 + | +LL | #[unsafe(link_section = "foo, ")] + | ^^^^^^^ not a valid Mach-O section specifier + | + = note: a Mach-O section specifier requires a segment and a section, separated by a comma + = help: an example of a valid Mach-O section specifier is `__TEXT,__cstring` + +error: invalid Mach-O section specifier + --> $DIR/link-section-macho.rs:27:25 + | +LL | #[unsafe(link_section = "foo,somelongwindedthing")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a valid Mach-O section specifier + | + = note: section name `somelongwindedthing` is longer than 16 bytes + +error: aborting due to 4 previous errors + From 0d364667daeb3f3b696a592eab712b80ea8dd9ae Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 11 Apr 2026 18:12:22 +0200 Subject: [PATCH 2/4] fix usage of `#[link_section]` to be compatible with mach-o rules --- tests/codegen-llvm/link_section.rs | 18 +++---- tests/ui/asm/naked-functions.rs | 5 +- tests/ui/attributes/attr-on-mac-call.rs | 2 +- tests/ui/attributes/attr-on-mac-call.stderr | 4 +- .../codegen_attr_on_required_trait_method.rs | 2 +- ...degen_attr_on_required_trait_method.stderr | 4 +- .../issue-43106-gating-of-builtin-attrs.rs | 26 +++++----- ...issue-43106-gating-of-builtin-attrs.stderr | 32 ++++++------- tests/ui/lint/lint-unsafe-code.rs | 4 +- tests/ui/lint/lint-unsafe-code.stderr | 8 ++-- tests/ui/lint/unused/unused-attr-duplicate.rs | 11 +++-- .../lint/unused/unused-attr-duplicate.stderr | 48 +++++++++---------- .../unsafe-attributes-fix.fixed | 10 ++-- .../unsafe-attributes-fix.rs | 10 ++-- .../unsafe-attributes-fix.stderr | 4 +- 15 files changed, 95 insertions(+), 93 deletions(-) diff --git a/tests/codegen-llvm/link_section.rs b/tests/codegen-llvm/link_section.rs index f62f694807933..f196ea86c447d 100644 --- a/tests/codegen-llvm/link_section.rs +++ b/tests/codegen-llvm/link_section.rs @@ -3,14 +3,14 @@ #![crate_type = "lib"] -// CHECK: @VAR1 = {{(dso_local )?}}constant [4 x i8] c"\01\00\00\00", section ".test_one" +// CHECK: @VAR1 = {{(dso_local )?}}constant [4 x i8] c"\01\00\00\00", section "__TEST,one" #[no_mangle] -#[link_section = ".test_one"] +#[link_section = "__TEST,one"] #[cfg(target_endian = "little")] pub static VAR1: u32 = 1; #[no_mangle] -#[link_section = ".test_one"] +#[link_section = "__TEST,one"] #[cfg(target_endian = "big")] pub static VAR1: u32 = 0x01000000; @@ -19,17 +19,17 @@ pub enum E { B(f32), } -// CHECK: @VAR2 = {{(dso_local )?}}constant {{.*}}, section ".test_two" +// CHECK: @VAR2 = {{(dso_local )?}}constant {{.*}}, section "__TEST,two" #[no_mangle] -#[link_section = ".test_two"] +#[link_section = "__TEST,two"] pub static VAR2: E = E::A(666); -// CHECK: @VAR3 = {{(dso_local )?}}constant {{.*}}, section ".test_three" +// CHECK: @VAR3 = {{(dso_local )?}}constant {{.*}}, section "__TEST,three" #[no_mangle] -#[link_section = ".test_three"] +#[link_section = "__TEST,three"] pub static VAR3: E = E::B(1.); -// CHECK: define {{(dso_local )?}}void @fn1() {{.*}} section ".test_four" { +// CHECK: define {{(dso_local )?}}void @fn1() {{.*}} section "__TEST,four" { #[no_mangle] -#[link_section = ".test_four"] +#[link_section = "__TEST,four"] pub fn fn1() {} diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index dadacb8d4683e..13b5b677f23c3 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -3,7 +3,7 @@ //@ ignore-spirv //@ reference: attributes.codegen.naked.body -#![feature(asm_unwind, linkage, rustc_attrs)] +#![feature(asm_unwind, linkage, rustc_attrs, cfg_target_object_format)] #![crate_type = "lib"] use std::arch::{asm, naked_asm}; @@ -200,7 +200,8 @@ pub extern "C" fn compatible_must_use_attributes() -> u64 { } #[export_name = "exported_function_name"] -#[link_section = ".custom_section"] +#[cfg_attr(not(target_object_format = "mach-o"), link_section = ".custom")] +#[cfg_attr(target_object_format = "mach-o", link_section = "__TEXT,__custom")] #[unsafe(naked)] pub extern "C" fn compatible_ffi_attributes_1() { naked_asm!("", options(raw)); diff --git a/tests/ui/attributes/attr-on-mac-call.rs b/tests/ui/attributes/attr-on-mac-call.rs index a23ced123efb5..577272a99a0d9 100644 --- a/tests/ui/attributes/attr-on-mac-call.rs +++ b/tests/ui/attributes/attr-on-mac-call.rs @@ -27,7 +27,7 @@ fn main() { #[link_name = "x"] //~^ WARN attribute cannot be used on macro calls //~| WARN previously accepted - #[link_section = "x"] + #[link_section = "__TEXT,__text"] //~^ WARN attribute cannot be used on macro calls //~| WARN previously accepted #[link_ordinal(42)] diff --git a/tests/ui/attributes/attr-on-mac-call.stderr b/tests/ui/attributes/attr-on-mac-call.stderr index 3bb50f2d6f654..9fc4e319117f6 100644 --- a/tests/ui/attributes/attr-on-mac-call.stderr +++ b/tests/ui/attributes/attr-on-mac-call.stderr @@ -78,8 +78,8 @@ LL | #[link_name = "x"] warning: `#[link_section]` attribute cannot be used on macro calls --> $DIR/attr-on-mac-call.rs:30:5 | -LL | #[link_section = "x"] - | ^^^^^^^^^^^^^^^^^^^^^ +LL | #[link_section = "__TEXT,__text"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[link_section]` can be applied to functions and statics diff --git a/tests/ui/attributes/codegen_attr_on_required_trait_method.rs b/tests/ui/attributes/codegen_attr_on_required_trait_method.rs index 6301a5a8ebf70..cd9987f1e6a38 100644 --- a/tests/ui/attributes/codegen_attr_on_required_trait_method.rs +++ b/tests/ui/attributes/codegen_attr_on_required_trait_method.rs @@ -7,7 +7,7 @@ trait Test { //~^ ERROR cannot be used on required trait methods [unused_attributes] //~| WARN previously accepted fn method1(&self); - #[link_section = ".text"] + #[link_section = "__TEXT,__text"] //~^ ERROR cannot be used on required trait methods [unused_attributes] //~| WARN previously accepted fn method2(&self); diff --git a/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr b/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr index 0770ccae41469..7b529440b008c 100644 --- a/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr +++ b/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr @@ -15,8 +15,8 @@ LL | #![deny(unused_attributes)] error: `#[link_section]` attribute cannot be used on required trait methods --> $DIR/codegen_attr_on_required_trait_method.rs:10:5 | -LL | #[link_section = ".text"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[link_section = "__TEXT,__text"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[link_section]` can be applied to functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index 36568449b82e1..8f3e98cfc2a7c 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -74,7 +74,7 @@ //~| WARN previously accepted //~| HELP can be applied to //~| HELP remove the attribute -#![link_section = "1800"] +#![link_section = ",1800"] //~^ WARN attribute cannot be used on //~| WARN previously accepted //~| HELP can be applied to @@ -616,66 +616,66 @@ mod link_name { //~| HELP remove the attribute } -#[link_section = "1800"] +#[link_section = ",1800"] //~^ WARN attribute cannot be used on //~| WARN previously accepted //~| HELP can be applied to //~| HELP remove the attribute mod link_section { - mod inner { #![link_section="1800"] } + mod inner { #![link_section=",1800"] } //~^ WARN attribute cannot be used on //~| WARN previously accepted //~| HELP can be applied to //~| HELP remove the attribute - #[link_section = "1800"] fn f() { } + #[link_section = ",1800"] fn f() { } - #[link_section = "1800"] struct S; + #[link_section = ",1800"] struct S; //~^ WARN attribute cannot be used on //~| WARN previously accepted //~| HELP can be applied to //~| HELP remove the attribute - #[link_section = "1800"] type T = S; + #[link_section = ",1800"] type T = S; //~^ WARN attribute cannot be used on //~| WARN previously accepted //~| HELP can be applied to //~| HELP remove the attribute - #[link_section = "1800"] impl S { } + #[link_section = ",1800"] impl S { } //~^ WARN attribute cannot be used on //~| WARN previously accepted //~| HELP can be applied to //~| HELP remove the attribute - #[link_section = "1800"] + #[link_section = ",1800"] //~^ WARN attribute cannot be used on //~| WARN previously accepted //~| HELP can be applied to //~| HELP remove the attribute trait Tr { - #[link_section = "1800"] + #[link_section = ",1800"] //~^ WARN attribute cannot be used on //~| WARN previously accepted //~| HELP can be applied to //~| HELP remove the attribute fn inside_tr_no_default(&self); - #[link_section = "1800"] + #[link_section = ",1800"] fn inside_tr_default(&self) { } } impl S { - #[link_section = "1800"] + #[link_section = ",1800"] fn inside_abc_123(&self) { } } impl Tr for S { - #[link_section = "1800"] + #[link_section = ",1800"] fn inside_tr_no_default(&self) { } } - #[link_section = "1800"] + #[link_section = ",1800"] fn should_always_link() { } } diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index 724d623e79eee..f6ed182b17ef1 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -866,8 +866,8 @@ LL | #[link_name = "1900"] impl S { } warning: `#[link_section]` attribute cannot be used on modules --> $DIR/issue-43106-gating-of-builtin-attrs.rs:619:1 | -LL | #[link_section = "1800"] - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[link_section = ",1800"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[link_section]` can be applied to functions and statics @@ -875,8 +875,8 @@ LL | #[link_section = "1800"] warning: `#[link_section]` attribute cannot be used on modules --> $DIR/issue-43106-gating-of-builtin-attrs.rs:625:17 | -LL | mod inner { #![link_section="1800"] } - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | mod inner { #![link_section=",1800"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[link_section]` can be applied to functions and statics @@ -884,8 +884,8 @@ LL | mod inner { #![link_section="1800"] } warning: `#[link_section]` attribute cannot be used on structs --> $DIR/issue-43106-gating-of-builtin-attrs.rs:633:5 | -LL | #[link_section = "1800"] struct S; - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[link_section = ",1800"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[link_section]` can be applied to functions and statics @@ -893,8 +893,8 @@ LL | #[link_section = "1800"] struct S; warning: `#[link_section]` attribute cannot be used on type aliases --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639:5 | -LL | #[link_section = "1800"] type T = S; - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[link_section = ",1800"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[link_section]` can be applied to functions and statics @@ -902,8 +902,8 @@ LL | #[link_section = "1800"] type T = S; warning: `#[link_section]` attribute cannot be used on inherent impl blocks --> $DIR/issue-43106-gating-of-builtin-attrs.rs:645:5 | -LL | #[link_section = "1800"] impl S { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[link_section = ",1800"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[link_section]` can be applied to functions and statics @@ -911,8 +911,8 @@ LL | #[link_section = "1800"] impl S { } warning: `#[link_section]` attribute cannot be used on traits --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:5 | -LL | #[link_section = "1800"] - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[link_section = ",1800"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[link_section]` can be applied to functions and statics @@ -920,8 +920,8 @@ LL | #[link_section = "1800"] warning: `#[link_section]` attribute cannot be used on required trait methods --> $DIR/issue-43106-gating-of-builtin-attrs.rs:657:9 | -LL | #[link_section = "1800"] - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[link_section = ",1800"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[link_section]` can be applied to functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks @@ -1570,8 +1570,8 @@ LL | #![link_name = "1900"] warning: `#[link_section]` attribute cannot be used on crates --> $DIR/issue-43106-gating-of-builtin-attrs.rs:77:1 | -LL | #![link_section = "1800"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![link_section = ",1800"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[link_section]` can be applied to functions and statics diff --git a/tests/ui/lint/lint-unsafe-code.rs b/tests/ui/lint/lint-unsafe-code.rs index b72e4c3a9e7fb..9b32336b05d49 100644 --- a/tests/ui/lint/lint-unsafe-code.rs +++ b/tests/ui/lint/lint-unsafe-code.rs @@ -48,8 +48,8 @@ impl AssocFnTrait for AssocFnFoo { #[export_name = "bar"] fn bar() {} //~ ERROR: declaration of a function with `export_name` #[export_name = "BAR"] static BAR: u32 = 5; //~ ERROR: declaration of a static with `export_name` -#[link_section = ".example_section"] fn uwu() {} //~ ERROR: declaration of a function with `link_section` -#[link_section = ".example_section"] static UWU: u32 = 5; //~ ERROR: declaration of a static with `link_section` +#[link_section = "__TEXT,__text"] fn uwu() {} //~ ERROR: declaration of a function with `link_section` +#[link_section = "__TEXT,__text"] static UWU: u32 = 5; //~ ERROR: declaration of a static with `link_section` struct AssocFnBar; diff --git a/tests/ui/lint/lint-unsafe-code.stderr b/tests/ui/lint/lint-unsafe-code.stderr index 037f0a8323a75..aade33aef44ee 100644 --- a/tests/ui/lint/lint-unsafe-code.stderr +++ b/tests/ui/lint/lint-unsafe-code.stderr @@ -54,16 +54,16 @@ LL | #[export_name = "BAR"] static BAR: u32 = 5; error: declaration of a function with `link_section` --> $DIR/lint-unsafe-code.rs:51:1 | -LL | #[link_section = ".example_section"] fn uwu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[link_section = "__TEXT,__text"] fn uwu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them error: declaration of a static with `link_section` --> $DIR/lint-unsafe-code.rs:52:1 | -LL | #[link_section = ".example_section"] static UWU: u32 = 5; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[link_section = "__TEXT,__text"] static UWU: u32 = 5; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them diff --git a/tests/ui/lint/unused/unused-attr-duplicate.rs b/tests/ui/lint/unused/unused-attr-duplicate.rs index 2b29fde128e4f..54c040f4bcac4 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.rs +++ b/tests/ui/lint/unused/unused-attr-duplicate.rs @@ -61,8 +61,9 @@ pub mod from_path; fn t1() {} #[must_use] -#[must_use = "some message"] //~ ERROR unused attribute -//~^ WARN this was previously accepted +#[must_use = "some message"] +//~^ ERROR unused attribute +//~| WARN this was previously accepted // No warnings for #[repr], would require more logic. #[repr(C)] #[repr(C)] @@ -96,7 +97,7 @@ extern "C" { } #[export_name = "exported_symbol_name"] -#[export_name = "exported_symbol_name2"] //~ ERROR unused attribute +#[export_name = "exported_symbol_name2"] //~ ERROR unused attribute //~^ WARN this was previously accepted pub fn export_test() {} @@ -108,8 +109,8 @@ pub fn no_mangle_test() {} #[used] //~ ERROR unused attribute static FOO: u32 = 0; -#[link_section = ".text"] -#[link_section = ".bss"] +#[link_section = "__TEXT,__text"] +#[link_section = "__DATA,__mod_init_func"] //~^ ERROR unused attribute //~| WARN this was previously accepted pub extern "C" fn example() {} diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr index 1942249d1f8e1..f25263e9cef90 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.stderr +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -104,127 +104,127 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: unused attribute - --> $DIR/unused-attr-duplicate.rs:70:1 + --> $DIR/unused-attr-duplicate.rs:71:1 | LL | #[non_exhaustive] | ^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:69:1 + --> $DIR/unused-attr-duplicate.rs:70:1 | LL | #[non_exhaustive] | ^^^^^^^^^^^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:76:1 + --> $DIR/unused-attr-duplicate.rs:77:1 | LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:75:1 + --> $DIR/unused-attr-duplicate.rs:76:1 | LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:80:1 + --> $DIR/unused-attr-duplicate.rs:81:1 | LL | #[inline(never)] | ^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:79:1 + --> $DIR/unused-attr-duplicate.rs:80:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: unused attribute - --> $DIR/unused-attr-duplicate.rs:83:1 + --> $DIR/unused-attr-duplicate.rs:84:1 | LL | #[cold] | ^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:82:1 + --> $DIR/unused-attr-duplicate.rs:83:1 | LL | #[cold] | ^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:85:1 + --> $DIR/unused-attr-duplicate.rs:86:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:84:1 + --> $DIR/unused-attr-duplicate.rs:85:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:93:5 + --> $DIR/unused-attr-duplicate.rs:94:5 | LL | #[link_name = "rust_dbg_extern_identity_u32"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:92:5 + --> $DIR/unused-attr-duplicate.rs:93:5 | LL | #[link_name = "this_does_not_exist"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: unused attribute - --> $DIR/unused-attr-duplicate.rs:99:1 + --> $DIR/unused-attr-duplicate.rs:100:1 | LL | #[export_name = "exported_symbol_name2"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:98:1 + --> $DIR/unused-attr-duplicate.rs:99:1 | LL | #[export_name = "exported_symbol_name"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: unused attribute - --> $DIR/unused-attr-duplicate.rs:104:1 + --> $DIR/unused-attr-duplicate.rs:105:1 | LL | #[no_mangle] | ^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:103:1 + --> $DIR/unused-attr-duplicate.rs:104:1 | LL | #[no_mangle] | ^^^^^^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:108:1 + --> $DIR/unused-attr-duplicate.rs:109:1 | LL | #[used] | ^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:107:1 + --> $DIR/unused-attr-duplicate.rs:108:1 | LL | #[used] | ^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:112:1 + --> $DIR/unused-attr-duplicate.rs:113:1 | -LL | #[link_section = ".bss"] - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute +LL | #[link_section = "__DATA,__mod_init_func"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:111:1 + --> $DIR/unused-attr-duplicate.rs:112:1 | -LL | #[link_section = ".text"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[link_section = "__TEXT,__text"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: unused attribute diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed index c1adc90161a46..1865405de8e52 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed @@ -15,7 +15,7 @@ macro_rules! ident { //~^ ERROR: unsafe attribute used without unsafe //~| WARN this is accepted in the current edition extern "C" fn bar() {} - } + }; } macro_rules! ident2 { @@ -24,26 +24,26 @@ macro_rules! ident2 { //~^ ERROR: unsafe attribute used without unsafe //~| WARN this is accepted in the current edition extern "C" fn bars() {} - } + }; } macro_rules! meta { ($m:meta) => { #[$m] extern "C" fn baz() {} - } + }; } macro_rules! meta2 { ($m:meta) => { #[$m] extern "C" fn baw() {} - } + }; } macro_rules! with_cfg_attr { () => { - #[cfg_attr(true, unsafe(link_section = ".custom_section"))] + #[cfg_attr(true, unsafe(link_section = "__TEXT,__custom"))] //~^ ERROR: unsafe attribute used without unsafe //~| WARN this is accepted in the current edition pub extern "C" fn abc() {} diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs index 9fdf379046345..ec290957e537e 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs @@ -15,7 +15,7 @@ macro_rules! ident { //~^ ERROR: unsafe attribute used without unsafe //~| WARN this is accepted in the current edition extern "C" fn bar() {} - } + }; } macro_rules! ident2 { @@ -24,26 +24,26 @@ macro_rules! ident2 { //~^ ERROR: unsafe attribute used without unsafe //~| WARN this is accepted in the current edition extern "C" fn bars() {} - } + }; } macro_rules! meta { ($m:meta) => { #[$m] extern "C" fn baz() {} - } + }; } macro_rules! meta2 { ($m:meta) => { #[$m] extern "C" fn baw() {} - } + }; } macro_rules! with_cfg_attr { () => { - #[cfg_attr(true, link_section = ".custom_section")] + #[cfg_attr(true, link_section = "__TEXT,__custom")] //~^ ERROR: unsafe attribute used without unsafe //~| WARN this is accepted in the current edition pub extern "C" fn abc() {} diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr index 279e61a9cb673..f03842139f0b8 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr @@ -79,7 +79,7 @@ LL | #[unsafe($e = $l)] error: unsafe attribute used without unsafe --> $DIR/unsafe-attributes-fix.rs:46:26 | -LL | #[cfg_attr(true, link_section = ".custom_section")] +LL | #[cfg_attr(true, link_section = "__TEXT,__custom")] | ^^^^^^^^^^^^ usage of unsafe attribute ... LL | with_cfg_attr!(); @@ -90,7 +90,7 @@ LL | with_cfg_attr!(); = note: this error originates in the macro `with_cfg_attr` (in Nightly builds, run with -Z macro-backtrace for more info) help: wrap the attribute in `unsafe(...)` | -LL | #[cfg_attr(true, unsafe(link_section = ".custom_section"))] +LL | #[cfg_attr(true, unsafe(link_section = "__TEXT,__custom"))] | +++++++ + error: unsafe attribute used without unsafe From 6f0c76c8d5f122bfdf0c167ce0fa1e5cccb79d1d Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 11 Apr 2026 19:07:36 +0200 Subject: [PATCH 3/4] use `cfg(target_object_format = "mach-o")` to clean up tests --- .../codegen-llvm/naked-fn/naked-functions.rs | 6 +-- .../ui/linkage-attr/link-section-placement.rs | 45 ++++++++++--------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/tests/codegen-llvm/naked-fn/naked-functions.rs b/tests/codegen-llvm/naked-fn/naked-functions.rs index 770b2b21e8fe0..f1138d61350f6 100644 --- a/tests/codegen-llvm/naked-fn/naked-functions.rs +++ b/tests/codegen-llvm/naked-fn/naked-functions.rs @@ -13,7 +13,7 @@ //@[thumb] needs-llvm-components: arm #![crate_type = "lib"] -#![feature(no_core, lang_items, rustc_attrs)] +#![feature(no_core, lang_items, rustc_attrs, cfg_target_object_format)] #![no_core] extern crate minicore; @@ -153,8 +153,8 @@ pub extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize { #[unsafe(naked)] // FIXME: configure this with `cfg(target_binary_format = "mach-o")`, // see https://github.com/rust-lang/rust/issues/152586. -#[cfg_attr(not(target_vendor = "apple"), link_section = ".text.some_different_name")] -#[cfg_attr(target_vendor = "apple", link_section = "__TEXT,different")] +#[cfg_attr(not(target_object_format = "mach-o"), link_section = ".text.some_different_name")] +#[cfg_attr(target_object_format = "mach-o", link_section = "__TEXT,different")] pub extern "C" fn test_link_section() { cfg_select! { all(target_arch = "arm", target_feature = "thumb-mode") => { diff --git a/tests/ui/linkage-attr/link-section-placement.rs b/tests/ui/linkage-attr/link-section-placement.rs index 6a143bfedb451..299ad31d82d0d 100644 --- a/tests/ui/linkage-attr/link-section-placement.rs +++ b/tests/ui/linkage-attr/link-section-placement.rs @@ -2,36 +2,37 @@ //@ run-pass +#![feature(cfg_target_object_format)] // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint #![allow(static_mut_refs)] #![allow(non_upper_case_globals)] -#[cfg(not(target_vendor = "apple"))] -#[link_section = ".moretext"] -fn i_live_in_more_text() -> &'static str { - "knock knock" -} -#[cfg(not(target_vendor = "apple"))] -#[link_section = ".imm"] -static magic: usize = 42; +cfg_select! { + target_object_format = "mach-o" => { + #[link_section = "__TEXT,__moretext"] + fn i_live_in_more_text() -> &'static str { + "knock knock" + } -#[cfg(not(target_vendor = "apple"))] -#[link_section = ".mut"] -static mut frobulator: usize = 0xdeadbeef; + #[link_section = "__RODATA,__imm"] + static magic: usize = 42; -#[cfg(target_vendor = "apple")] -#[link_section = "__TEXT,__moretext"] -fn i_live_in_more_text() -> &'static str { - "knock knock" -} + #[link_section = "__DATA,__mut"] + static mut frobulator: usize = 0xdeadbeef; + } + _ => { + #[link_section = ".moretext"] + fn i_live_in_more_text() -> &'static str { + "knock knock" + } -#[cfg(target_vendor = "apple")] -#[link_section = "__RODATA,__imm"] -static magic: usize = 42; + #[link_section = ".imm"] + static magic: usize = 42; -#[cfg(target_vendor = "apple")] -#[link_section = "__DATA,__mut"] -static mut frobulator: usize = 0xdeadbeef; + #[link_section = ".mut"] + static mut frobulator: usize = 0xdeadbeef; + } +} pub fn main() { unsafe { From 7aeba4ebd71f415b09c2faa1ed39ea5141baafd0 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 12 Apr 2026 18:15:38 +0200 Subject: [PATCH 4/4] fix `rustdoc` tests that assume elf --- tests/rustdoc-html/attributes-2021-edition.rs | 4 ++-- tests/rustdoc-html/attributes.rs | 1 + tests/rustdoc-html/inline_cross/attributes.rs | 2 +- tests/rustdoc-html/inline_cross/auxiliary/attributes.rs | 2 +- tests/rustdoc-json/attrs/link_section_2021.rs | 4 ++-- tests/rustdoc-json/attrs/link_section_2024.rs | 4 ++-- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/rustdoc-html/attributes-2021-edition.rs b/tests/rustdoc-html/attributes-2021-edition.rs index b5028d8c85254..40d6dda508a59 100644 --- a/tests/rustdoc-html/attributes-2021-edition.rs +++ b/tests/rustdoc-html/attributes-2021-edition.rs @@ -9,6 +9,6 @@ pub extern "C" fn f() {} #[export_name = "bar"] pub extern "C" fn g() {} -//@ has foo/fn.example.html '//pre[@class="rust item-decl"]' '#[unsafe(link_section = ".text")]' -#[link_section = ".text"] +//@ has foo/fn.example.html '//pre[@class="rust item-decl"]' '#[unsafe(link_section = "__TEXT,__text")]' +#[link_section = "__TEXT,__text"] pub extern "C" fn example() {} diff --git a/tests/rustdoc-html/attributes.rs b/tests/rustdoc-html/attributes.rs index 6032c3d388011..8a6dd5ab33d55 100644 --- a/tests/rustdoc-html/attributes.rs +++ b/tests/rustdoc-html/attributes.rs @@ -1,4 +1,5 @@ //@ edition: 2024 +//@ only-linux #![crate_name = "foo"] //@ has foo/fn.f.html '//*[@class="code-attribute"]' '#[unsafe(no_mangle)]' diff --git a/tests/rustdoc-html/inline_cross/attributes.rs b/tests/rustdoc-html/inline_cross/attributes.rs index 1657b7bdc8f77..324686a33612f 100644 --- a/tests/rustdoc-html/inline_cross/attributes.rs +++ b/tests/rustdoc-html/inline_cross/attributes.rs @@ -9,7 +9,7 @@ pub use attributes::no_mangle; //@ has 'user/fn.link_section.html' '//pre[@class="rust item-decl"]' \ -// '#[unsafe(link_section = ".here")]' +// '#[unsafe(link_section = "__TEXT,__here")]' pub use attributes::link_section; //@ has 'user/fn.export_name.html' '//pre[@class="rust item-decl"]' \ diff --git a/tests/rustdoc-html/inline_cross/auxiliary/attributes.rs b/tests/rustdoc-html/inline_cross/auxiliary/attributes.rs index 6068d38558586..efceda87165c5 100644 --- a/tests/rustdoc-html/inline_cross/auxiliary/attributes.rs +++ b/tests/rustdoc-html/inline_cross/auxiliary/attributes.rs @@ -1,7 +1,7 @@ #[unsafe(no_mangle)] pub fn no_mangle() {} -#[unsafe(link_section = ".here")] +#[unsafe(link_section = "__TEXT,__here")] pub fn link_section() {} #[unsafe(export_name = "exonym")] diff --git a/tests/rustdoc-json/attrs/link_section_2021.rs b/tests/rustdoc-json/attrs/link_section_2021.rs index acd8ecd0e30ca..82df8071592c7 100644 --- a/tests/rustdoc-json/attrs/link_section_2021.rs +++ b/tests/rustdoc-json/attrs/link_section_2021.rs @@ -2,6 +2,6 @@ #![no_std] //@ count "$.index[?(@.name=='example')].attrs[*]" 1 -//@ is "$.index[?(@.name=='example')].attrs[*].link_section" '".text"' -#[link_section = ".text"] +//@ is "$.index[?(@.name=='example')].attrs[*].link_section" '"__TEXT,__text"' +#[link_section = "__TEXT,__text"] pub extern "C" fn example() {} diff --git a/tests/rustdoc-json/attrs/link_section_2024.rs b/tests/rustdoc-json/attrs/link_section_2024.rs index 8107493229b52..acf9406ce5284 100644 --- a/tests/rustdoc-json/attrs/link_section_2024.rs +++ b/tests/rustdoc-json/attrs/link_section_2024.rs @@ -5,6 +5,6 @@ // However, the unsafe qualification is not shown by rustdoc. //@ count "$.index[?(@.name=='example')].attrs[*]" 1 -//@ is "$.index[?(@.name=='example')].attrs[*].link_section" '".text"' -#[unsafe(link_section = ".text")] +//@ is "$.index[?(@.name=='example')].attrs[*].link_section" '"__TEXT,__text"' +#[unsafe(link_section = "__TEXT,__text")] pub extern "C" fn example() {}