Summary

Divide global declarations

宣言
into two categories:

  • constants
    定数
    declare
    宣言する
    constant
    定数
    values
    . These represent a value, not a memory address. This is the most common thing one would reach for and would replace static
    静的な
    as we know it today in almost all cases.
  • statics
    静的な
    declare
    宣言する
    global variables
    変数、ストレージ
    . These represent a memory address. They would be rarely used: the primary
    主要な、初等の、第一の
    use cases are global locks, global atomic counters, and interfacing with legacy C libraries.

Motivation

We have been wrestling with the best way to represent globals for some times. There are a number of interrelated issues:

  • Significant addresses and inlining: For optimization purposes, it is useful to be able to inline constant
    定数
    values directly
    直接
    into the program. It is even more useful if those constant
    定数
    values do not have known addresses, because that means the compiler is free to replicate them as it wishes. Moreover,
    その上
    if a constant
    定数
    is inlined into downstream crates, then they must be recompiled whenever that constant
    定数
    changes.
  • Read-only memory: Whenever possible, we'd like to place large constants
    定数
    into read-only memory. But this means that the data must be truly immutable,
    不変の
    or else a segfault will result.
    結果、戻り値
  • Global atomic counters and the like: We'd like to make it possible for people to create global locks or atomic counters that can be used without resorting to unsafe code.
  • Interfacing with C code: Some C libraries require the use of global, mutable data. Other times it's just convenient and threading is not a concern.
  • Initializer constants:
    定数
    There must be a way to have initializer constants
    定数
    for things like locks and atomic counters, so that people can write static
    静的な
    MY_COUNTER: AtomicUint = INIT_ZERO
    or some such. It should not be possible to modify these initializer constants.
    定数

The current design

設計(する)
is that we have only one keyword, static
静的な
, which declares
宣言
a global variable.
変数、ストレージ
By default, global variables
変数、ストレージ
do not have significant addresses and can be inlined into the program. You can make a global variable
変数、ストレージ
have a significant address by marking it #[inline(never)]. Furthermore, you can declare
宣言する
a mutable global using static
静的な
mut
: all accesses to static
静的な
mut
variables
変数、ストレージ
are considered
みなす、考慮する
unsafe. Because we wish to allow
許可する、可能にする
static
静的な
values to be placed in read-only memory, they are forbidden from having a type that includes interior mutable data (that is, an appearance of UnsafeCell type).

Some concrete

具体的な/具象的な
problems with this design
設計(する)
are:

  • There is no way to have a safe global counter or lock. Those must be placed in static
    静的な
    mut
    variables,
    変数、ストレージ
    which means that access to them is illegal.
    文法違反
    To resolve
    解決する
    this, there is an alternative
    代わりのもの、選択肢
    proposal, according
    according to 〜に応じて
    to which, access to static
    静的な
    mut
    is considered
    みなす、考慮する
    safe if the type of the static
    静的な
    mut meets the Sync trait.
  • The significance (no pun intended) of the #[inline(never)] annotation is not intuitive.
  • There is no way to have a generic type constant.
    定数

Other less practical and more aesthetic concerns are:

  • Although static
    静的な
    and let look and feel analogous, the two behave quite differently. Generally speaking, static
    静的な
    declarations
    宣言
    do not declare
    宣言する
    variables
    変数、ストレージ
    but rather values, which can be inlined and which do not have fixed addresses. You cannot have interior mutability in a static
    静的な
    variable,
    変数、ストレージ
    but you can in a let. So that static
    静的な
    variables
    変数、ストレージ
    can appear
    現れる
    in patterns, it is illegal
    文法違反
    to shadow a static
    静的な
    variable
    変数、ストレージ
    -- but let variables
    変数、ストレージ
    cannot appear
    現れる
    in patterns. Etc.
  • There are other constructs
    作る、構成体
    in the language,
    言語
    such as nullary enum variants and nullary structs,
    構造、構造体
    which look like global data but in fact act
    振る舞う
    quite differently. They are actual
    実際の
    values which do not have addresses. They are categorized as rvalues and so forth.

Detailed design
設計(する)

Constants
定数

Reintroduce a const declaration

宣言
which declares
宣言
a constant
定数
:

const name: type = value;

Constants

定数
may be declared
宣言
in any scope. They cannot be shadowed. Constants
定数
are considered
みなす、考慮する
rvalues. Therefore, taking
とる
the address of a constant
定数
actually creates a spot on the local stack -- they by definition
定義
have no significant addresses. Constants
定数
are intended to behave exactly
正確に
like nullary enum variants.

Possible extension: Generic constants
定数

As a possible extension, it is perfectly reasonable for constants

定数
to have generic parameters.
仮引数
For example, the following constant
定数
is legal:
(文法的に)適格

struct WrappedOption<T> { value: Option<T> } const NONE<T> = WrappedOption { value: None }

Note that this makes no sense for a static

静的な
variable,
変数、ストレージ
which represents
表現する
a memory location and hence must have a concrete
具体的な/具象的な
type.

Possible extension: constant
定数
functions

It is possible to imagine constant

定数
functions as well. This could help to address the problem of encapsulating initialization.
初期化
To avoid
避ける、回避する
the need to specify
特定する、指定する、規定する
what kinds of code can execute in a constant
定数
function, we can limit them syntactically to a single
単一の
constant
定数
expression
that can be expanded at compilation time (no recursion).

struct LockedData<T:Send> { lock: Lock, value: T } const LOCKED<T:Send>(t: T) -> LockedData<T> { LockedData { lock: INIT_LOCK, value: t } }

This would allow

許可する、可能にする
us to make the value field on UnsafeCell private, among other things.

Static
静的な
variables
変数、ストレージ

Repurpose the static

静的な
declaration
宣言
to declare
宣言する
static
静的な
variables
変数、ストレージ
only. Static
静的な
variables
変数、ストレージ
always have single
単一の
addresses. static
静的な
variables
変数、ストレージ
can optionally be declared
宣言
as mut. The lifetime of a static
静的な
variable
変数、ストレージ
is 'static
静的な
. It is not legal
(文法的に)適格
to move from a static.
静的な
Accesses to a static
静的な
variable
変数、ストレージ
generate actual
実際の
reads and writes: the value is not inlined (but see "Unresolved Questions" below).

Non-mut statics

静的な
must have a type that meets the Sync bound.
制限する、結び付けられて
All access to the static
静的な
is considered
みなす、考慮する
safe (that is, reading the variable
変数、ストレージ
and taking
とる
its address). If the type of the static
静的な
does not contain
含む
an UnsafeCell in its interior, the compiler may place it in read-only memory, but otherwise it must be placed in mutable memory.

mut statics

静的な
may have any type. All access is considered
みなす、考慮する
unsafe. They may not be placed in read-only memory.

Globals referencing Globals

const => const

It is possible to create a const or a static

静的な
which references
参照
another const or another static
静的な
by its address. For example:

struct SomeStruct { x: uint } const FOO: SomeStruct = SomeStruct { x: 1 }; const BAR: &'static SomeStruct = &FOO;

Constants

定数
are generally inlined into the stack frame from which they are referenced, but in a static
静的な
context
文脈、背景
there is no stack frame. Instead, the compiler will reinterpret this as if it were written as:

struct SomeStruct { x: uint } const FOO: SomeStruct = SomeStruct { x: 1 }; const BAR: &'static SomeStruct = { static TMP: SomeStruct = FOO; &TMP };

Here a static

静的な
is introduced to be able to give the const a pointer which does indeed have the 'static
静的な
lifetime. Due to this rewriting, the compiler will disallow
許可しない
SomeStruct from containing
含む
an UnsafeCell (interior mutability). In general,
一般
a constant
定数
A cannot reference
参照
the address of another constant
定数
B if B contains
含む
an UnsafeCell in its interior.

const => static
静的な

It is illegal

文法違反
for a constant
定数
to refer
参照する
to another static.
静的な
A constant
定数
represents
表現する
a constant
定数
value while a static
静的な
represents
表現する
a memory location, and this sort of reference
参照
is difficult to reconcile in light of their definitions.
定義

static
静的な
=> const

If a static

静的な
references
参照
the address of a const, then a similar
似ている、同様の
rewriting happens, but there is no interior mutability restriction
制限
(only a Sync restriction).

static
静的な
=> static
静的な

It is illegal

文法違反
for a static
静的な
to reference
参照
another static
静的な
by value. It is required that all references
参照
be borrowed. Additionally, not all kinds of borrows are allowed,
許可する、可能にする
only explicitly
明示的に
taking
とる
the address of another static
静的な
is allowed.
許可する、可能にする
For example, interior borrows of fields and elements
要素
or accessing elements
要素
of an array
配列
are both disallowed.
許可しない

If a by-value reference

参照
were allowed,
許可する、可能にする
then this sort of reference
参照
would require that the static
静的な
being referenced fall into one of two categories:

  1. It's an initializer pattern. This is the purpose of const, however.
  2. The values are kept in sync. This is currently technically infeasible.

Instead of falling into one of these two categories, the compiler will instead disallow

許可しない
any references
参照
to statics
静的な
by value (from other statics).

Patterns

Today, a static

静的な
is allowed
許可する、可能にする
to be used in pattern matching. With the introduction
はじめに、導入
of const, however, a static
静的な
will be forbidden from appearing
現れる
in a pattern match,
一致する、マッチさせる
and instead only a const can appear.
現れる

Drawbacks

This RFC introduces two keywords for global data. Global data is kind of an edge feature so this feels like overkill. (On the other hand, the only keyword that most Rust programmers should need to know is const -- I imagine static

静的な
variables
変数、ストレージ
will be used quite rarely.)

Alternatives

The other design

設計(する)
under consideration
考慮
is to keep the current split but make access to static
静的な
mut
be considered
みなす、考慮する
safe if the type of the static
静的な
mut is Sync. For the details of this discussion, please see RFC 177.

One serious concern is with regard to timing. Adding

たす
more things to the Rust 1.0 schedule is inadvisable. Therefore, it would be possible to take
とる
a hybrid approach: keep the current static
静的な
rules, or perhaps the variation where access to static
静的な
mut
is safe, for the time being, and create const declarations
宣言
after Rust 1.0 is released.

Unresolved questions

  • Should the compiler be allowed

    許可する、可能にする
    to inline the values of static
    静的な
    variables
    変数、ストレージ
    which are deeply immutable
    不変の
    (and thus
    それゆえに、従って、
    force recompilation)?

  • Should we permit

    許す
    static
    静的な
    variables
    変数、ストレージ
    whose type is not Sync, but simply make access to them unsafe?

  • Should we permit

    許す
    static
    静的な
    variables
    変数、ストレージ
    whose type is not Sync, but whose initializer value does not actually contain
    含む
    interior mutability? For example, a static
    静的な
    of Option<UnsafeCell<uint>> with the initializer of None is in theory safe.

  • How hard are the envisioned extensions to implement? If easy, they would be nice to have. If hard, they can wait.