Skip to content

Commit 9f13b9d

Browse files
committed
Auto merge of #119000 - celinval:smir-cstr, r=ouz-a
Add a method to StableMIR to check if a type is a CStr Also add a check that StableMIR works properly with C string literal.
2 parents 2f19122 + 86451ba commit 9f13b9d

File tree

4 files changed

+37
-0
lines changed

4 files changed

+37
-0
lines changed

compiler/rustc_smir/src/rustc_smir/context.rs

+6
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,12 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
219219
def.internal(&mut *tables).repr().simd()
220220
}
221221

222+
fn adt_is_cstr(&self, def: AdtDef) -> bool {
223+
let mut tables = self.0.borrow_mut();
224+
let def_id = def.0.internal(&mut *tables);
225+
tables.tcx.lang_items().c_str() == Some(def_id)
226+
}
227+
222228
fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
223229
let mut tables = self.0.borrow_mut();
224230
let def_id = def.0.internal(&mut *tables);

compiler/stable_mir/src/compiler_interface.rs

+3
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ pub trait Context {
7272
/// Returns whether this ADT is simd.
7373
fn adt_is_simd(&self, def: AdtDef) -> bool;
7474

75+
/// Returns whether this definition is a C string.
76+
fn adt_is_cstr(&self, def: AdtDef) -> bool;
77+
7578
/// Retrieve the function signature for the given generic arguments.
7679
fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig;
7780

compiler/stable_mir/src/ty.rs

+6
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,12 @@ impl TyKind {
316316
*self == TyKind::RigidTy(RigidTy::Str)
317317
}
318318

319+
#[inline]
320+
pub fn is_cstr(&self) -> bool {
321+
let TyKind::RigidTy(RigidTy::Adt(def, _)) = self else { return false };
322+
with(|cx| cx.adt_is_cstr(*def))
323+
}
324+
319325
#[inline]
320326
pub fn is_slice(&self) -> bool {
321327
matches!(self, TyKind::RigidTy(RigidTy::Slice(_)))

tests/ui-fulldeps/stable-mir/check_allocation.rs

+22
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use std::ascii::Char;
3333
use std::assert_matches::assert_matches;
3434
use std::cmp::{max, min};
3535
use std::collections::HashMap;
36+
use std::ffi::CStr;
3637
use std::io::Write;
3738
use std::ops::ControlFlow;
3839

@@ -45,6 +46,7 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
4546
check_foo(*get_item(&items, (ItemKind::Static, "FOO")).unwrap());
4647
check_bar(*get_item(&items, (ItemKind::Static, "BAR")).unwrap());
4748
check_len(*get_item(&items, (ItemKind::Static, "LEN")).unwrap());
49+
check_cstr(*get_item(&items, (ItemKind::Static, "C_STR")).unwrap());
4850
check_other_consts(*get_item(&items, (ItemKind::Fn, "other_consts")).unwrap());
4951
check_type_id(*get_item(&items, (ItemKind::Fn, "check_type_id")).unwrap());
5052
ControlFlow::Continue(())
@@ -86,6 +88,24 @@ fn check_bar(item: CrateItem) {
8688
assert_eq!(std::str::from_utf8(&allocation.raw_bytes().unwrap()), Ok("Bar"));
8789
}
8890

91+
/// Check the allocation data for static `C_STR`.
92+
///
93+
/// ```no_run
94+
/// static C_STR: &core::ffi::cstr = c"cstr";
95+
/// ```
96+
fn check_cstr(item: CrateItem) {
97+
let def = StaticDef::try_from(item).unwrap();
98+
let alloc = def.eval_initializer().unwrap();
99+
assert_eq!(alloc.provenance.ptrs.len(), 1);
100+
let deref = item.ty().kind().builtin_deref(true).unwrap();
101+
assert!(deref.ty.kind().is_cstr(), "Expected CStr, but got: {:?}", item.ty());
102+
103+
let alloc_id_0 = alloc.provenance.ptrs[0].1.0;
104+
let GlobalAlloc::Memory(allocation) = GlobalAlloc::from(alloc_id_0) else { unreachable!() };
105+
assert_eq!(allocation.bytes.len(), 5);
106+
assert_eq!(CStr::from_bytes_until_nul(&allocation.raw_bytes().unwrap()), Ok(c"cstr"));
107+
}
108+
89109
/// Check the allocation data for constants used in `other_consts` function.
90110
fn check_other_consts(item: CrateItem) {
91111
// Instance body will force constant evaluation.
@@ -206,6 +226,7 @@ fn main() {
206226
generate_input(&path).unwrap();
207227
let args = vec![
208228
"rustc".to_string(),
229+
"--edition=2021".to_string(),
209230
"--crate-name".to_string(),
210231
CRATE_NAME.to_string(),
211232
path.to_string(),
@@ -224,6 +245,7 @@ fn generate_input(path: &str) -> std::io::Result<()> {
224245
static LEN: usize = 2;
225246
static FOO: [&str; 2] = ["hi", "there"];
226247
static BAR: &str = "Bar";
248+
static C_STR: &std::ffi::CStr = c"cstr";
227249
const NULL: *const u8 = std::ptr::null();
228250
const TUPLE: (u32, u32) = (10, u32::MAX);
229251

0 commit comments

Comments
 (0)