Hi.
I have a small suggestion.
Short summary
Change the types of byte string and string literals. Introduce strings of fixed size.
Proposed changes
Keep the types of array literals as [T, ..N]
.
Change the types of byte string literals from &[u8]
to [u8, ..N]
Change the types of string literals form &str
to to str[..N]
.
Introduce the missing family of types - strings of fixed size: str[..N]
.
str[..N]
is essentially a [u8, ..N]
with UTF-8 invariants and, eventually, additional string methods/traits.
It fills the gap in the vector/string chart:
Vec<T>
| String
------
| ------
[T, N]
| ???
------
| ------
&[T]
| &str
Keep the autocoercion of array literals (not arrays of fixed size in general) to slices. Add the autocoercion of changed byte string literals to slices. Add the autocoercion of changed string literals to slices. Non-literal arrays and strings do not autocoerce to slices, in accordance with the general agreements on explicitness.
Motivation
The main motivation today is a “forward compatibility”.
Currently, given the lack of non-type generic parameters and compile time (function) evaluation, strings of fixed size are not very useful.
But after introducing CTE the need in compile time string operations will raise quickly.
Even with non-type generic parameters alone strings of fixed size can be used in runtime for “heapless” string operations, which is useful in constrained environments.
Before 1.0 str[..N]
can be implemented as minimally as possible just to allow the change of the types of string literals.
The secondary motivation is consistency between literal types and better design in general. All the literals stop losing the knowledge of their sizes at compile time. The changed types [T, ..N]
and str[..N]
can be easily converted to slices, but the reverse operation requires CTE. All the literals (and variables they are assigned to) have usual value semantics and do not refer to some external storage inaccessible by normal means.
Examples of uses not possible with current types, but possible with proposed types:
// Today: initialize mutable array with literal
let mut arr: [u8, ..3] = b"abc";
arr[0] = b'd';
// Future, with CTE: compile time string concatenation
static LANG_DIR: str[..5 /*Should, probably, be inferred*/ ] = "lang/";
static EN_FILE: str[.._] = LANG_DIR + "en"; // str[..N] implements Add
static FR_FILE: str[.._] = LANG_DIR + "fr";
// Or, without CTE: runtime heapless string concatenation
let DE_FILE = LANG_DIR + "fr";
The autocoercion of literals is kept for ergonomic purpose. Writing something like:
fn f(arg: &str) {}
f("Hello"[]);
f(&"Hello");
for all literals would be just unacceptable.
Backward compatibility
All the current static strings keep compiling.
static GOODBYE: &'static str = "Goodbye"; // Autocoercion
All the code using autocoercion for array literals keeps compiling.
fn g(arg: &[int]) {}
g([1i, 2, 3]); // Autocoercion
In general, the surface changes are minimal.
Drawbacks
Minor breakage.
Example:
fn main() {
let s = "Hello";
fn f(arg: &str) {}
f(s); // Will require explicit slicing f(s[]) or implicit DST coersion from reference f(&s)
}
Alternatives
Keep the status quo or apply the changes partially.
Drawbacks:
// Today: can't use byte string literals in some cases
let mut arr: [u8, ..3] = [b'a', b'b', b'c'];
arr[0] = b'd';
// Future: str[..N] is added, CTE is added, but the literal types remains old
// Have to use conversion methods
let mut arr: [u8, ..3] = b"abc".to_fixed();
arr[0] = b'd';
static LANG_DIR: str[.._] = "lang/".to_fixed();
static EN_FILE: str[.._] = LANG_DIR + "en".to_fixed();
static FR_FILE: str[.._] = LANG_DIR + "fr".to_fixed();
// Bad future: str[..N] is not added
// Heapless/compile-time string operations aren't possible, or performed with "magic" like extended concat! or recursive macros.
Precedents
C and C++ string literals are char arrays of fixed size. C++ library proposal for strings of fixed size (link), the paper also contains some discussion and motivation.
Afterword
I’d be glad to receive any feedback, in particular, how easy or difficult the minimal implementation of str[…N] would be.