- Feature Name: associated_statics
- Start Date: 2018-05-14
- RFC PR:
- Rust Issue:
Summary
Traits and impls can have associated consts, but not associated statics. This RFC proposes to allow associated statics in traits and impls.
Motivation
consts are useful, but they are limited:
- They can’t have some useful or necessary attributes applied to them (e.g.
export_name, link_section, etc.).
- They can’t refer to statics.
- They can’t be imported from some external library.
- They don’t represent a precise memory location.
These limitations apply to associated consts. Statics address these limitations, and associated statics in particular address these limitations with all the same benefits that associated consts have (compared to non-associated consts).
Guide-level explanation
Static items can be associated with a trait or type, much like const items can be associated with a trait or type.
A struct may contain associated statics:
struct CustomStruct;
impl CustomStruct {
// Statics may have attributes (like #[no_mangle]) applied to them.
#[no_mangle]
pub static CUSTOM_STRUCT_ID: u32 = 13;
}
fn main() {
println!("The struct's ID is {}", CustomStruct::CUSTOM_STRUCT_ID);
}
A struct’s associated statics may be provided by an external library by wrapping them in an extern {} block:
struct Struct;
impl Struct {
extern "C" {
static EXTERN_STATIC: usize;
}
}
fn main() {
println!("The extern static is {}", unsafe { Struct::EXTERN_STATIC });
}
Traits may also have an associated static (though the static may not be extern):
trait Trait {
static ID: usize;
}
struct Struct;
impl Trait for Struct {
static ID: usize = 15;
}
fn main() {
println!("The struct's ID is {}", Struct::ID);
}
The trait may define a default value (and linker-related attributes) for the static, though the implementation may override these:
trait Trait {
#[link_section = ".default_key_section"]
static KEY: usize = 1;
#[link_section = ".default_value_section"]
static VALUE: usize = 2;
#[link_section = ".default_key_ref_section"]
static KEY_REF: &'static usize = &Self::KEY;
}
struct Struct;
impl Trait for Struct {
#[link_section = ".custom_key_section"]
static KEY: usize = 16;
}
fn main() {
// Struct::KEY's link section is ".custom_key_section".
assert_eq!(Struct::KEY, 16);
// Struct::VALUE's link section is ".default_value_section".
assert_eq!(Struct::VALUE, 2);
// Struct::KEY_REF's link section is ".default_key_ref_section".
assert_eq!(Struct::KEY_REF as *const _, &Struct::KEY as *const _);
}
Reference-level explanation
Due to a number of complexities and limitations, this RFC proposes that the feature be kept minimal initially. Associated statics are only permitted as follows:
Drawbacks
Since this RFC proposes minimal support for associated statics, there are some unsupported situations that are unlikely to be obvious to users. The compiler should take this into consideration when emitting error messages, and perhaps links to additional information resources should be included in the diagnostic messages.
Rationale and alternatives
The rationale for this feature is largely the same as the rationale for associated consts, except associated statics will be more useful for FFI.
Prior art
Associated consts blazed the trail for associated statics, and this RFC attempts to draw as much as possible from the existing associated consts feature.
Associated statics have been discussed before:
The primary road block these discussions mentioned is the problem of monomorphizing generic statics in a dynamic library. This RFC attempts to avoid that road block by prohibiting generic statics.
Unresolved questions
None (yet).
Future possibilities
The syntax extern { ... } within a struct item opens the door for associated extern functions. This RFC does not propose adding these, but future RFCs may do so.
Generic statics might be feasible if they are not part of the crate’s public API (since all monomorphizations are known at compile time and the previously mentioned dynamic library is avoided). A future RFC could explore this further.
Associated statics for generic traits and types that don’t depend on a generic parameter (e.g., impl<T> Struct<T> { static DOES_NOT_USE_T: usize = 42; }) might be feasible to add in a future RFC.