diff --git a/text/0195-associated-items.md b/text/0195-associated-items.md index 45f97efe0fb..c17018b580e 100644 --- a/text/0195-associated-items.md +++ b/text/0195-associated-items.md @@ -9,7 +9,7 @@ more convenient, scalable, and powerful. In particular, traits will consist of a set of methods, together with: * Associated functions (already present as "static" functions) -* Associated statics +* Associated consts * Associated types * Associated lifetimes @@ -20,6 +20,13 @@ This RFC also provides a mechanism for *multidispatch* traits, where the `impl` is selected based on multiple types. The connection to associated items will become clear in the detailed text below. +*Note: This RFC was originally accepted before RFC 246 introduced the +distinction between const and static items. The text has been updated to clarify +that associated consts will be added rather than statics, and to provide a +summary of restrictions on the initial implementation of associated +consts. Other than that modification, the proposal has not been changed to +reflect newer Rust features or syntax.* + # Motivation A typical example where associated items are helpful is data structures like @@ -173,7 +180,7 @@ provide a distinct `impl` for every member of this family. Associated types, lifetimes, and functions can already be expressed in today's Rust, though it is unwieldy to do so (as argued above). -But associated _statics_ cannot be expressed using today's traits. +But associated _consts_ cannot be expressed using today's traits. For example, today's Rust includes a variety of numeric traits, including `Float`, which must currently expose constants as static functions: @@ -190,20 +197,20 @@ trait Float { } ``` -Because these functions cannot be used in static initializers, the modules for -float types _also_ export a separate set of constants as statics, not using +Because these functions cannot be used in constant expressions, the modules for +float types _also_ export a separate set of constants as consts, not using traits. -Associated constants would allow the statics to live directly on the traits: +Associated constants would allow the consts to live directly on the traits: ```rust trait Float { - static NAN: Self; - static INFINITY: Self; - static NEG_INFINITY: Self; - static NEG_ZERO: Self; - static PI: Self; - static TWO_PI: Self; + const NAN: Self; + const INFINITY: Self; + const NEG_INFINITY: Self; + const NEG_ZERO: Self; + const PI: Self; + const TWO_PI: Self; ... } ``` @@ -282,14 +289,14 @@ distinction" below. ## Trait bodies: defining associated items -Trait bodies are expanded to include three new kinds of items: statics, types, +Trait bodies are expanded to include three new kinds of items: consts, types, and lifetimes: ``` TRAIT = TRAIT_HEADER '{' TRAIT_ITEM* '}' TRAIT_ITEM = ... - | 'static' IDENT ':' TYPE [ '=' CONST_EXP ] ';' + | 'const' IDENT ':' TYPE [ '=' CONST_EXP ] ';' | 'type' IDENT [ ':' BOUNDS ] [ WHERE_CLAUSE ] [ '=' TYPE ] ';' | 'lifetime' LIFETIME_IDENT ';' ``` @@ -352,7 +359,7 @@ external to the trait. ### Defaults -Notice that associated statics and types both permit defaults, just as trait +Notice that associated consts and types both permit defaults, just as trait methods and functions can provide defaults. Defaults are useful both as a code reuse mechanism, and as a way to expand the @@ -424,13 +431,13 @@ We deal with this in a very simple way: ## Trait implementations -Trait `impl` syntax is much the same as before, except that static, type, and +Trait `impl` syntax is much the same as before, except that const, type, and lifetime items are allowed: ``` IMPL_ITEM = ... - | 'static' IDENT ':' TYPE '=' CONST_EXP ';' + | 'const' IDENT ':' TYPE '=' CONST_EXP ';' | 'type' IDENT' '=' 'TYPE' ';' | 'lifetime' LIFETIME_IDENT '=' LIFETIME_REFERENCE ';' ``` @@ -767,7 +774,7 @@ as UFCS-style functions: trait Foo { type AssocType; lifetime 'assoc_lifetime; - static ASSOC_STATIC: uint; + const ASSOC_CONST: uint; fn assoc_fn() -> Self; // Note: 'assoc_lifetime and AssocType in scope: @@ -776,7 +783,7 @@ trait Foo { fn default_method(&self) -> uint { // method in scope UFCS-style, assoc_fn in scope let _ = method(self, assoc_fn()); - ASSOC_STATIC // in scope + ASSOC_CONST // in scope } } @@ -875,6 +882,7 @@ trait Foo { type Output1; type Output2; lifetime 'a; + const C: bool; ... } ``` @@ -887,6 +895,7 @@ T: Foo T: Foo T: Foo T: Foo>(t: T) // this is valid fn consume_obj(t: Box>) // this is NOT valid // but this IS valid: -fn consume_obj(t: Box::N; +let x: [u8; ::N] = [0u8; ALIAS_N]; +// Or... +let x: [u8; T::N + 1] = [0u8; T::N + 1]; +``` + +However, this causes some problems. What should we do with the following case in +type checking, where we need to prove that a generic is valid for any `T`? + +```rust +let x: [u8; T::N + T::N] = [0u8; 2 * T::N]; +``` + +We would like to handle at least some obvious cases (e.g. proving that +`T::N == T::N`), but without trying to prove arbitrary statements about +arithmetic. The question of how to do this is deferred.