Skip to content

Commit 63d16b5

Browse files
committed
Auto merge of rust-lang#117472 - jmillikin:stable-c-str-literals, r=Nilstrieb
Stabilize C string literals RFC: https://rust-lang.github.io/rfcs/3348-c-str-literal.html Tracking issue: rust-lang#105723 Documentation PR (reference manual): rust-lang/reference#1423 # Stabilization report Stabilizes C string and raw C string literals (`c"..."` and `cr#"..."#`), which are expressions of type [`&CStr`](https://doc.rust-lang.org/stable/core/ffi/struct.CStr.html). Both new literals require Rust edition 2021 or later. ```rust const HELLO: &core::ffi::CStr = c"Hello, world!"; ``` C strings may contain any byte other than `NUL` (`b'\x00'`), and their in-memory representation is guaranteed to end with `NUL`. ## Implementation Originally implemented by PR rust-lang#108801, which was reverted due to unintentional changes to lexer behavior in Rust editions < 2021. The current implementation landed in PR rust-lang#113476, which restricts C string literals to Rust edition >= 2021. ## Resolutions to open questions from the RFC * Adding C character literals (`c'.'`) of type `c_char` is not part of this feature. * Support for `c"..."` literals does not prevent `c'.'` literals from being added in the future. * C string literals should not be blocked on making `&CStr` a thin pointer. * It's possible to declare constant expressions of type `&'static CStr` in stable Rust (as of v1.59), so C string literals are not adding additional coupling on the internal representation of `CStr`. * The unstable `concat_bytes!` macro should not accept `c"..."` literals. * C strings have two equally valid `&[u8]` representations (with or without terminal `NUL`), so allowing them to be used in `concat_bytes!` would be ambiguous. * Adding a type to represent C strings containing valid UTF-8 is not part of this feature. * Support for a hypothetical `&Utf8CStr` may be explored in the future, should such a type be added to Rust.
2 parents caf7300 + 0f41bc2 commit 63d16b5

File tree

19 files changed

+41
-90
lines changed

19 files changed

+41
-90
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
515515
}
516516
};
517517
}
518-
gate_all!(c_str_literals, "`c\"..\"` literals are experimental");
519518
gate_all!(
520519
if_let_guard,
521520
"`if let` guards are experimental",

compiler/rustc_builtin_macros/src/concat_bytes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ fn invalid_type_err(
1919
let snippet = cx.sess.source_map().span_to_snippet(span).ok();
2020
match ast::LitKind::from_token_lit(token_lit) {
2121
Ok(ast::LitKind::CStr(_, _)) => {
22-
// FIXME(c_str_literals): should concatenation of C string literals
23-
// include the null bytes in the end?
22+
// Avoid ambiguity in handling of terminal `NUL` by refusing to
23+
// concatenate C string literals as bytes.
2424
cx.emit_err(errors::ConcatCStrLit { span: span });
2525
}
2626
Ok(ast::LitKind::Char(_)) => {

compiler/rustc_feature/src/accepted.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ declare_features! (
7777
(accepted, bindings_after_at, "1.56.0", Some(65490), None),
7878
/// Allows empty structs and enum variants with braces.
7979
(accepted, braced_empty_structs, "1.8.0", Some(29720), None),
80+
/// Allows `c"foo"` literals.
81+
(accepted, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723), None),
8082
/// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`.
8183
(accepted, cfg_attr_multi, "1.33.0", Some(54881), None),
8284
/// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.

compiler/rustc_feature/src/unstable.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,6 @@ declare_features! (
354354
(unstable, async_fn_track_caller, "1.73.0", Some(110011), None),
355355
/// Allows builtin # foo() syntax
356356
(unstable, builtin_syntax, "1.71.0", Some(110680), None),
357-
/// Allows `c"foo"` literals.
358-
(unstable, c_str_literals, "1.71.0", Some(105723), None),
359357
/// Treat `extern "C"` function as nounwind.
360358
(unstable, c_unwind, "1.52.0", Some(74990), None),
361359
/// Allows using C-variadics.

compiler/rustc_parse/src/lexer/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,6 @@ impl<'a> StringReader<'a> {
223223
rustc_lexer::TokenKind::Literal { kind, suffix_start } => {
224224
let suffix_start = start + BytePos(suffix_start);
225225
let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind);
226-
if let token::LitKind::CStr | token::LitKind::CStrRaw(_) = kind {
227-
self.sess.gated_spans.gate(sym::c_str_literals, self.mk_sp(start, self.pos));
228-
}
229226
let suffix = if suffix_start < self.pos {
230227
let string = self.str_from(suffix_start);
231228
if string == "_" {

src/tools/clippy/tests/ui/needless_raw_string.fixed

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#![allow(clippy::needless_raw_string_hashes, clippy::no_effect, unused)]
22
#![warn(clippy::needless_raw_strings)]
3-
#![feature(c_str_literals)]
43

54
fn main() {
65
"aaa";

src/tools/clippy/tests/ui/needless_raw_string.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#![allow(clippy::needless_raw_string_hashes, clippy::no_effect, unused)]
22
#![warn(clippy::needless_raw_strings)]
3-
#![feature(c_str_literals)]
43

54
fn main() {
65
r#"aaa"#;

src/tools/clippy/tests/ui/needless_raw_string.stderr

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: unnecessary raw string literal
2-
--> $DIR/needless_raw_string.rs:6:5
2+
--> $DIR/needless_raw_string.rs:5:5
33
|
44
LL | r#"aaa"#;
55
| ^^^^^^^^
@@ -13,7 +13,7 @@ LL + "aaa";
1313
|
1414

1515
error: unnecessary raw string literal
16-
--> $DIR/needless_raw_string.rs:9:5
16+
--> $DIR/needless_raw_string.rs:8:5
1717
|
1818
LL | br#"aaa"#;
1919
| ^^^^^^^^^
@@ -25,7 +25,7 @@ LL + b"aaa";
2525
|
2626

2727
error: unnecessary raw string literal
28-
--> $DIR/needless_raw_string.rs:12:5
28+
--> $DIR/needless_raw_string.rs:11:5
2929
|
3030
LL | cr#"aaa"#;
3131
| ^^^^^^^^^
@@ -37,7 +37,7 @@ LL + c"aaa";
3737
|
3838

3939
error: unnecessary raw string literal
40-
--> $DIR/needless_raw_string.rs:16:5
40+
--> $DIR/needless_raw_string.rs:15:5
4141
|
4242
LL | / r#"
4343
LL | | a
@@ -56,7 +56,7 @@ LL ~ ";
5656
|
5757

5858
error: unnecessary raw string literal
59-
--> $DIR/needless_raw_string.rs:22:5
59+
--> $DIR/needless_raw_string.rs:21:5
6060
|
6161
LL | r"no hashes";
6262
| ^^^^^^^^^^^^
@@ -68,7 +68,7 @@ LL + "no hashes";
6868
|
6969

7070
error: unnecessary raw string literal
71-
--> $DIR/needless_raw_string.rs:23:5
71+
--> $DIR/needless_raw_string.rs:22:5
7272
|
7373
LL | br"no hashes";
7474
| ^^^^^^^^^^^^^
@@ -80,7 +80,7 @@ LL + b"no hashes";
8080
|
8181

8282
error: unnecessary raw string literal
83-
--> $DIR/needless_raw_string.rs:24:5
83+
--> $DIR/needless_raw_string.rs:23:5
8484
|
8585
LL | cr"no hashes";
8686
| ^^^^^^^^^^^^^

src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#![allow(clippy::no_effect, unused)]
22
#![warn(clippy::needless_raw_string_hashes)]
3-
#![feature(c_str_literals)]
43

54
fn main() {
65
r"\aaa";

src/tools/clippy/tests/ui/needless_raw_string_hashes.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#![allow(clippy::no_effect, unused)]
22
#![warn(clippy::needless_raw_string_hashes)]
3-
#![feature(c_str_literals)]
43

54
fn main() {
65
r#"\aaa"#;

0 commit comments

Comments
 (0)