Skip to content

Commit 4b94c23

Browse files
committed
Auto merge of rust-lang#111248 - Dylan-DPC:rollup-lbp0ui3, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - rust-lang#103056 (Fix `checked_{add,sub}_duration` incorrectly returning `None` when `other` has more than `i64::MAX` seconds) - rust-lang#108801 (Implement RFC 3348, `c"foo"` literals) - rust-lang#110773 (Reduce MIR dump file count for MIR-opt tests) - rust-lang#110876 (Added default target cpu to `--print target-cpus` output and updated docs) - rust-lang#111068 (Improve check-cfg implementation) - rust-lang#111238 (btree_map: `Cursor{,Mut}::peek_prev` must agree) Failed merges: - rust-lang#110694 (Implement builtin # syntax and use it for offset_of!(...)) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 4a18324 + c99ab29 commit 4b94c23

File tree

70 files changed

+1164
-524
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1164
-524
lines changed

compiler/rustc_ast/src/ast.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1821,6 +1821,8 @@ pub enum LitKind {
18211821
/// A byte string (`b"foo"`). Not stored as a symbol because it might be
18221822
/// non-utf8, and symbols only allow utf8 strings.
18231823
ByteStr(Lrc<[u8]>, StrStyle),
1824+
/// A C String (`c"foo"`). Guaranteed to only have `\0` at the end.
1825+
CStr(Lrc<[u8]>, StrStyle),
18241826
/// A byte char (`b'f'`).
18251827
Byte(u8),
18261828
/// A character literal (`'a'`).
@@ -1875,6 +1877,7 @@ impl LitKind {
18751877
// unsuffixed variants
18761878
LitKind::Str(..)
18771879
| LitKind::ByteStr(..)
1880+
| LitKind::CStr(..)
18781881
| LitKind::Byte(..)
18791882
| LitKind::Char(..)
18801883
| LitKind::Int(_, LitIntType::Unsuffixed)

compiler/rustc_ast/src/token.rs

+7
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ pub enum LitKind {
7474
StrRaw(u8), // raw string delimited by `n` hash symbols
7575
ByteStr,
7676
ByteStrRaw(u8), // raw byte string delimited by `n` hash symbols
77+
CStr,
78+
CStrRaw(u8),
7779
Err,
7880
}
7981

@@ -141,6 +143,10 @@ impl fmt::Display for Lit {
141143
delim = "#".repeat(n as usize),
142144
string = symbol
143145
)?,
146+
CStr => write!(f, "c\"{symbol}\"")?,
147+
CStrRaw(n) => {
148+
write!(f, "cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize))?
149+
}
144150
Integer | Float | Bool | Err => write!(f, "{symbol}")?,
145151
}
146152

@@ -170,6 +176,7 @@ impl LitKind {
170176
Float => "float",
171177
Str | StrRaw(..) => "string",
172178
ByteStr | ByteStrRaw(..) => "byte string",
179+
CStr | CStrRaw(..) => "C string",
173180
Err => "error",
174181
}
175182
}

compiler/rustc_ast/src/util/literal.rs

+62-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
33
use crate::ast::{self, LitKind, MetaItemLit, StrStyle};
44
use crate::token::{self, Token};
5-
use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode};
5+
use rustc_lexer::unescape::{
6+
byte_from_char, unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit,
7+
Mode,
8+
};
69
use rustc_span::symbol::{kw, sym, Symbol};
710
use rustc_span::Span;
11+
use std::ops::Range;
812
use std::{ascii, fmt, str};
913

1014
// Escapes a string, represented as a symbol. Reuses the original symbol,
@@ -35,6 +39,7 @@ pub enum LitError {
3539
InvalidFloatSuffix,
3640
NonDecimalFloat(u32),
3741
IntTooLarge(u32),
42+
NulInCStr(Range<usize>),
3843
}
3944

4045
impl LitKind {
@@ -158,6 +163,52 @@ impl LitKind {
158163

159164
LitKind::ByteStr(bytes.into(), StrStyle::Raw(n))
160165
}
166+
token::CStr => {
167+
let s = symbol.as_str();
168+
let mut buf = Vec::with_capacity(s.len());
169+
let mut error = Ok(());
170+
unescape_c_string(s, Mode::CStr, &mut |span, c| match c {
171+
Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => {
172+
error = Err(LitError::NulInCStr(span));
173+
}
174+
Ok(CStrUnit::Byte(b)) => buf.push(b),
175+
Ok(CStrUnit::Char(c)) if c.len_utf8() == 1 => buf.push(c as u8),
176+
Ok(CStrUnit::Char(c)) => {
177+
buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes())
178+
}
179+
Err(err) => {
180+
if err.is_fatal() {
181+
error = Err(LitError::LexerError);
182+
}
183+
}
184+
});
185+
error?;
186+
buf.push(0);
187+
LitKind::CStr(buf.into(), StrStyle::Cooked)
188+
}
189+
token::CStrRaw(n) => {
190+
let s = symbol.as_str();
191+
let mut buf = Vec::with_capacity(s.len());
192+
let mut error = Ok(());
193+
unescape_c_string(s, Mode::RawCStr, &mut |span, c| match c {
194+
Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => {
195+
error = Err(LitError::NulInCStr(span));
196+
}
197+
Ok(CStrUnit::Byte(b)) => buf.push(b),
198+
Ok(CStrUnit::Char(c)) if c.len_utf8() == 1 => buf.push(c as u8),
199+
Ok(CStrUnit::Char(c)) => {
200+
buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes())
201+
}
202+
Err(err) => {
203+
if err.is_fatal() {
204+
error = Err(LitError::LexerError);
205+
}
206+
}
207+
});
208+
error?;
209+
buf.push(0);
210+
LitKind::CStr(buf.into(), StrStyle::Raw(n))
211+
}
161212
token::Err => LitKind::Err,
162213
})
163214
}
@@ -191,6 +242,14 @@ impl fmt::Display for LitKind {
191242
string = symbol
192243
)?;
193244
}
245+
LitKind::CStr(ref bytes, StrStyle::Cooked) => {
246+
write!(f, "c\"{}\"", escape_byte_str_symbol(bytes))?
247+
}
248+
LitKind::CStr(ref bytes, StrStyle::Raw(n)) => {
249+
// This can only be valid UTF-8.
250+
let symbol = str::from_utf8(bytes).unwrap();
251+
write!(f, "cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize),)?;
252+
}
194253
LitKind::Int(n, ty) => {
195254
write!(f, "{n}")?;
196255
match ty {
@@ -237,6 +296,8 @@ impl MetaItemLit {
237296
LitKind::Str(_, ast::StrStyle::Raw(n)) => token::StrRaw(n),
238297
LitKind::ByteStr(_, ast::StrStyle::Cooked) => token::ByteStr,
239298
LitKind::ByteStr(_, ast::StrStyle::Raw(n)) => token::ByteStrRaw(n),
299+
LitKind::CStr(_, ast::StrStyle::Cooked) => token::CStr,
300+
LitKind::CStr(_, ast::StrStyle::Raw(n)) => token::CStrRaw(n),
240301
LitKind::Byte(_) => token::Byte,
241302
LitKind::Char(_) => token::Char,
242303
LitKind::Int(..) => token::Integer,

compiler/rustc_ast_passes/src/feature_gate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
572572
}
573573
};
574574
}
575+
gate_all!(c_str_literals, "`c\"..\"` literals are experimental");
575576
gate_all!(
576577
if_let_guard,
577578
"`if let` guards are experimental",

compiler/rustc_ast_pretty/src/pprust/state.rs

+4
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ pub fn literal_to_string(lit: token::Lit) -> String {
210210
token::ByteStrRaw(n) => {
211211
format!("br{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol)
212212
}
213+
token::CStr => format!("c\"{symbol}\""),
214+
token::CStrRaw(n) => {
215+
format!("cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize))
216+
}
213217
token::Integer | token::Float | token::Bool | token::Err => symbol.to_string(),
214218
};
215219

compiler/rustc_attr/src/builtin.rs

+20-19
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_ast::{Attribute, LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedM
55
use rustc_ast_pretty::pprust;
66
use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
77
use rustc_macros::HashStable_Generic;
8+
use rustc_session::config::ExpectedValues;
89
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
910
use rustc_session::lint::BuiltinLintDiagnostics;
1011
use rustc_session::parse::{feature_err, ParseSess};
@@ -581,32 +582,32 @@ pub fn cfg_matches(
581582
) -> bool {
582583
eval_condition(cfg, sess, features, &mut |cfg| {
583584
try_gate_cfg(cfg.name, cfg.span, sess, features);
584-
if let Some(names_valid) = &sess.check_config.names_valid {
585-
if !names_valid.contains(&cfg.name) {
585+
match sess.check_config.expecteds.get(&cfg.name) {
586+
Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => {
586587
sess.buffer_lint_with_diagnostic(
587588
UNEXPECTED_CFGS,
588589
cfg.span,
589590
lint_node_id,
590-
"unexpected `cfg` condition name",
591-
BuiltinLintDiagnostics::UnexpectedCfg((cfg.name, cfg.name_span), None),
591+
"unexpected `cfg` condition value",
592+
BuiltinLintDiagnostics::UnexpectedCfgValue(
593+
(cfg.name, cfg.name_span),
594+
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
595+
),
592596
);
593597
}
594-
}
595-
if let Some(value) = cfg.value {
596-
if let Some(values) = &sess.check_config.values_valid.get(&cfg.name) {
597-
if !values.contains(&value) {
598-
sess.buffer_lint_with_diagnostic(
599-
UNEXPECTED_CFGS,
600-
cfg.span,
601-
lint_node_id,
602-
"unexpected `cfg` condition value",
603-
BuiltinLintDiagnostics::UnexpectedCfg(
604-
(cfg.name, cfg.name_span),
605-
cfg.value_span.map(|vs| (value, vs)),
606-
),
607-
);
608-
}
598+
None if sess.check_config.exhaustive_names => {
599+
sess.buffer_lint_with_diagnostic(
600+
UNEXPECTED_CFGS,
601+
cfg.span,
602+
lint_node_id,
603+
"unexpected `cfg` condition name",
604+
BuiltinLintDiagnostics::UnexpectedCfgName(
605+
(cfg.name, cfg.name_span),
606+
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
607+
),
608+
);
609609
}
610+
_ => { /* not unexpected */ }
610611
}
611612
sess.config.contains(&(cfg.name, cfg.value))
612613
})

compiler/rustc_builtin_macros/src/concat.rs

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ pub fn expand_concat(
3232
Ok(ast::LitKind::Bool(b)) => {
3333
accumulator.push_str(&b.to_string());
3434
}
35+
Ok(ast::LitKind::CStr(..)) => {
36+
cx.span_err(e.span, "cannot concatenate a C string literal");
37+
has_errors = true;
38+
}
3539
Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => {
3640
cx.emit_err(errors::ConcatBytestr { span: e.span });
3741
has_errors = true;

compiler/rustc_builtin_macros/src/concat_bytes.rs

+5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ fn invalid_type_err(
1818
};
1919
let snippet = cx.sess.source_map().span_to_snippet(span).ok();
2020
match ast::LitKind::from_token_lit(token_lit) {
21+
Ok(ast::LitKind::CStr(_, _)) => {
22+
// FIXME(c_str_literals): should concatenation of C string literals
23+
// include the null bytes in the end?
24+
cx.span_err(span, "cannot concatenate C string literals");
25+
}
2126
Ok(ast::LitKind::Char(_)) => {
2227
let sugg =
2328
snippet.map(|snippet| ConcatBytesInvalidSuggestion::CharLit { span, snippet });

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2249,7 +2249,7 @@ extern "C" {
22492249

22502250
pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
22512251

2252-
pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine);
2252+
pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine, cpu: *const c_char);
22532253
pub fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t;
22542254
pub fn LLVMRustGetTargetFeature(
22552255
T: &TargetMachine,

compiler/rustc_codegen_llvm/src/llvm_util.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,14 @@ pub(crate) fn print(req: PrintRequest, sess: &Session) {
329329
require_inited();
330330
let tm = create_informational_target_machine(sess);
331331
match req {
332-
PrintRequest::TargetCPUs => unsafe { llvm::LLVMRustPrintTargetCPUs(tm) },
332+
PrintRequest::TargetCPUs => {
333+
// SAFETY generate a C compatible string from a byte slice to pass
334+
// the target CPU name into LLVM, the lifetime of the reference is
335+
// at least as long as the C function
336+
let cpu_cstring = CString::new(handle_native(sess.target.cpu.as_ref()))
337+
.unwrap_or_else(|e| bug!("failed to convert to cstring: {}", e));
338+
unsafe { llvm::LLVMRustPrintTargetCPUs(tm, cpu_cstring.as_ptr()) };
339+
}
333340
PrintRequest::TargetFeatures => print_target_features(sess, tm),
334341
_ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req),
335342
}

compiler/rustc_expand/src/proc_macro_server.rs

+6
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ impl FromInternal<token::LitKind> for LitKind {
6161
token::StrRaw(n) => LitKind::StrRaw(n),
6262
token::ByteStr => LitKind::ByteStr,
6363
token::ByteStrRaw(n) => LitKind::ByteStrRaw(n),
64+
token::CStr => LitKind::CStr,
65+
token::CStrRaw(n) => LitKind::CStrRaw(n),
6466
token::Err => LitKind::Err,
6567
token::Bool => unreachable!(),
6668
}
@@ -78,6 +80,8 @@ impl ToInternal<token::LitKind> for LitKind {
7880
LitKind::StrRaw(n) => token::StrRaw(n),
7981
LitKind::ByteStr => token::ByteStr,
8082
LitKind::ByteStrRaw(n) => token::ByteStrRaw(n),
83+
LitKind::CStr => token::CStr,
84+
LitKind::CStrRaw(n) => token::CStrRaw(n),
8185
LitKind::Err => token::Err,
8286
}
8387
}
@@ -436,6 +440,8 @@ impl server::FreeFunctions for Rustc<'_, '_> {
436440
| token::LitKind::StrRaw(_)
437441
| token::LitKind::ByteStr
438442
| token::LitKind::ByteStrRaw(_)
443+
| token::LitKind::CStr
444+
| token::LitKind::CStrRaw(_)
439445
| token::LitKind::Err => return Err(()),
440446
token::LitKind::Integer | token::LitKind::Float => {}
441447
}

compiler/rustc_feature/src/active.rs

+2
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@ declare_features! (
313313
(active, async_closure, "1.37.0", Some(62290), None),
314314
/// Allows async functions to be declared, implemented, and used in traits.
315315
(active, async_fn_in_trait, "1.66.0", Some(91611), None),
316+
/// Allows `c"foo"` literals.
317+
(active, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723), None),
316318
/// Treat `extern "C"` function as nounwind.
317319
(active, c_unwind, "1.52.0", Some(74990), None),
318320
/// Allows using C-variadics.

compiler/rustc_hir/src/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ language_item_table! {
333333
RangeTo, sym::RangeTo, range_to_struct, Target::Struct, GenericRequirement::None;
334334

335335
String, sym::String, string, Target::Struct, GenericRequirement::None;
336+
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
336337
}
337338

338339
pub enum GenericRequirement {

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1300,6 +1300,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13001300
opt_ty.unwrap_or_else(|| self.next_float_var())
13011301
}
13021302
ast::LitKind::Bool(_) => tcx.types.bool,
1303+
ast::LitKind::CStr(_, _) => tcx.mk_imm_ref(
1304+
tcx.lifetimes.re_static,
1305+
tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, Some(lit.span)))
1306+
.skip_binder(),
1307+
),
13031308
ast::LitKind::Err => tcx.ty_error_misc(),
13041309
}
13051310
}

0 commit comments

Comments
 (0)