You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is there anything besides the task of creating an RFC that blocks stabilization of this feature? This feature is a cornerstone in a library I wrote and use, and I'd love to be able to use the library on a stable toolchain.
Needs to be done before stabilizing this: #[used] should only be allowed on static variables. Right now you can put it on functions (which has no effect) and the compiler won't complain -- that should be an error.
There is still an open bug where an used static is optimized away if the surrounding module is not used by any code: #47384.
That's not a problem with #[used] AFAICT. The symbol is in the libfoo.rlib., which is the only thing #[used] guarantees. See below
#![feature(used)]mod foo {// private and non-reachable#[no_mangle]#[used]staticSTATIC:[u32;10] = [1;10];}
$ cargo build
$ nm -C target/debug/libfoo.rlibfoo-d351a64747b10042.18cd33xhzunvqw3h.rcgu.o:0000000000000000 r STATIC
$ cargo build --release
$ nm -C target/release/libfoo.rlibfoo-f1e69902e2c50980.foo0-f8ffab837addfc521cde53270051d9b7.rs.rcgu.o:0000000000000000 r STATIC
You are not getting the behavior you want for other reasons, mainly due to link-time visibility: you want STATIC to be an exported symbol (it should show up as R in the output of nm, not as r).
Also KEEP does not guarantee that a symbol will be in the output binary: the linker will stop inspecting inputs as soon as all undefined symbols are resolved so it may not get to libfoo.rlib, or the linker may look into libfoo.rlib but it may not look into the object file that contains STATIC -- these days .rlibs contain several object files due to parallel codegen.
To make your example work I would rewrite it like this:
// foo/src/lib.rs#![feature(used)]#![no_std]// not required but I'm using thumbv7m-none-eabi as the example targetpubmod foo {// `STATIC` needs to be an *exported* symbol; they only way to do that right now is to make the// item *both* public and reachable#[doc(hidden)]// don't show this in the API docs#[export_name = "STATIC"]// or you could use `no_mangle` and rename the item, same thing#[used]// required or the compiler will drop this symbol when optimizations are enabledpubstatic __HIDDEN:[u32;10] = [1;10];}
/* link.x */EXTERN(STATIC); /* Forces the linker to look into libfoo.rlib *//* In general this makes the linker continue looking into the inputs until it finds this symbol */SECTIONS
{
/* put STATIC in the .static linker section */ .static : ALIGN(4)
{
KEEP(*(.rodata.STATIC));
}
}
I think EXTERN was the main thing you were missing. Without it the linker doesn't even look into libfoo.rlib (then visibility doesn't even matter). Without EXTERN the linker will only look into libfoo.rlib if it's looking for other symbols -- this is why you got STATIC in the output binary when there were calls into functions defined in foo (the linker was looking for the function foo::hello and it happened to find STATIC). But it's not certain that will work because of parallel codegen: foo::hello may end in the first object file in libfoo.rlib then the linker won't bother to look into the second object file which could happen to contain STATIC.
Visibility is important too: if STATIC wasn't an exported symbol the linker would ignore it and you would end with an undefined reference to STATIC in your binary (U STATIC in the output of nm).
@japaric Thanks so much for the detailed explanation! The behavior makes sense to me now and I agree that this has nothing to do with the used attribute.
#[used] item is misleading. It's used until linking, but not used at writing or compiling code.
should be #[to_be_used] or #[maybe_useful], or #[useful] for short?
useful also implies: compiler, don't dismiss this item, it's useful for later use, i.e. linking.
cc #51363
I propose that we stabilize this feature. The #[used] attribute, which can only be applied to static variables, forces the compiler to keep the variable in the output object file (.o, .rlib, etc.) even if the variable is not used, or referenced, by any other item in the crate.
Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
Note: __attribute__((used)) has different behaviors on ELF and non-ELF targets. I recently added __attribute__((retain)) to Clang: https://reviews.llvm.org/D97447
I can sort of understand why one might want used and retain to be different, but I don't see any reason they can't have more analogous behavior across different targets.
Activity
est31 commentedon Apr 29, 2017
cc #41628
acmcarther commentedon Dec 1, 2017
Is there anything besides the task of creating an RFC that blocks stabilization of this feature? This feature is a cornerstone in a library I wrote and use, and I'd love to be able to use the library on a stable toolchain.
japaric commentedon Apr 3, 2018
I have opened an RFC to stabilize this: rust-lang/rfcs#2386
phil-opp commentedon Apr 20, 2018
There is still an open bug where an
usedstatic is optimized away if the surrounding module is not used by any code: #47384.japaric commentedon Apr 25, 2018
Needs to be done before stabilizing this:
#[used]should only be allowed onstaticvariables. Right now you can put it on functions (which has no effect) and the compiler won't complain -- that should be an error.Rollup merge of rust-lang#50330 - japaric:used, r=nagisa
japaric commentedon May 1, 2018
@phil-opp
That's not a problem with
#[used]AFAICT. The symbol is in the libfoo.rlib., which is the only thing#[used]guarantees. See belowYou are not getting the behavior you want for other reasons, mainly due to link-time visibility: you want
STATICto be an exported symbol (it should show up asRin the output ofnm, not asr).Also
KEEPdoes not guarantee that a symbol will be in the output binary: the linker will stop inspecting inputs as soon as all undefined symbols are resolved so it may not get to libfoo.rlib, or the linker may look into libfoo.rlib but it may not look into the object file that containsSTATIC-- these days .rlibs contain several object files due to parallel codegen.To make your example work I would rewrite it like this:
I think
EXTERNwas the main thing you were missing. Without it the linker doesn't even look into libfoo.rlib (then visibility doesn't even matter). WithoutEXTERNthe linker will only look into libfoo.rlib if it's looking for other symbols -- this is why you gotSTATICin the output binary when there were calls into functions defined infoo(the linker was looking for the functionfoo::helloand it happened to findSTATIC). But it's not certain that will work because of parallel codegen:foo::hellomay end in the first object file in libfoo.rlib then the linker won't bother to look into the second object file which could happen to containSTATIC.Visibility is important too: if
STATICwasn't an exported symbol the linker would ignore it and you would end with an undefined reference toSTATICin your binary (U STATICin the output ofnm).phil-opp commentedon May 4, 2018
@japaric Thanks so much for the detailed explanation! The behavior makes sense to me now and I agree that this has nothing to do with the
usedattribute.Mark `EXCEPTIONS` and `INTERRUPTS` as `EXTERN` in the linker script
Centril commentedon May 27, 2018
The stabilization RFC is now merged. Anyone writing up the stabilization PR?
liigo commentedon Jun 6, 2018
#[used] itemis misleading. It's used until linking, but not used at writing or compiling code.should be #[to_be_used] or #[maybe_useful], or
#[useful]for short?useful also implies: compiler, don't dismiss this item, it's useful for later use, i.e. linking.
cc #51363
cramertj commentedon Jun 25, 2018
@rfcbot fcp merge
I propose that we stabilize this feature. The #[used] attribute, which can only be applied to static variables, forces the compiler to keep the variable in the output object file (.o, .rlib, etc.) even if the variable is not used, or referenced, by any other item in the crate.
See the latest RFC here.
1 remaining item
cramertj commentedon Jun 25, 2018
Trying again w/ a lang tag...
@rfcbot fcp merge
rfcbot commentedon Jun 25, 2018
Team member @cramertj has proposed to merge this. The next step is review by the rest of the tagged teams:
No concerns currently listed.
Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
rfcbot commentedon Aug 29, 2018
🔔 This is now entering its final comment period, as per the review above. 🔔
rfcbot commentedon Sep 8, 2018
The final comment period, with a disposition to merge, as per the review above, is now complete.
stabilize `#[used]`
Auto merge of #51363 - japaric:stable-used, r=cramertj
MaskRay commentedon Mar 2, 2021
Note:
__attribute__((used))has different behaviors on ELF and non-ELF targets. I recently added__attribute__((retain))to Clang: https://reviews.llvm.org/D97447See https://reviews.llvm.org/D97448 for the
llvm.usedchange (SHF_GNU_RETAIN) on ELF targets.See:
https://clang.llvm.org/docs/AttributeReference.html#used
https://clang.llvm.org/docs/AttributeReference.html#retain
comex commentedon Mar 7, 2021
Argh, why did GCC do that?
Apparently there's still some active debate about it: https://gcc.gnu.org/pipermail/gcc-patches/2021-February/565418.html
I can sort of understand why one might want
usedandretainto be different, but I don't see any reason they can't have more analogous behavior across different targets.