const TyTy::SliceType *slice = nullptr;
const TyTy::StrType *str = nullptr;
const TyTy::DynamicObjectType *dyn = nullptr;
+ const TyTy::ADTType *adt = nullptr;
if (type.is_dyn_slice_type (&slice))
{
tree type_record = create_slice_type_record (*slice);
return;
}
+ // Check for CStr, create a specific record for it
+ else if (type.is_dyn_cstr_type (&adt))
+ {
+ // CStr in core crate is defined as the following:
+ //
+ // #[repr(transparent)]
+ // pub struct CStr {
+ // inner: [u8]
+ // }
+ //
+ // Reuse the c_char (u8) slice fat-pointer layout
+ TyTy::BaseType *u8 = nullptr;
+ ctx->get_tyctx ()->lookup_builtin ("u8", &u8);
+ // Create a synthetic SliceType over u8 and use that record layout
+ TyTy::SliceType synthetic_slice (adt->get_ref (), adt->get_ident ().locus,
+ TyTy::TyVar (u8->get_ref ()));
+ tree type_record = create_slice_type_record (synthetic_slice);
+ translated
+ = Backend::named_type ("&CStr", type_record, adt->get_ident ().locus);
+
+ return;
+ }
tree base_compiled_type
= TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
break;
}
- /* This is a pointer to a null-terminated byte slice (&[u8]). */
- TyTy::BaseType *u8;
- auto ok = context->lookup_builtin ("u8", &u8);
- rust_assert (ok);
+ auto lang_item_defined
+ = mappings.lookup_lang_item (LangItem::Kind::CSTR);
- auto crate_num = mappings.get_current_crate ();
- Analysis::NodeMapping slice_mapping (crate_num, UNKNOWN_NODEID,
- mappings.get_next_hir_id (
- crate_num),
- UNKNOWN_LOCAL_DEFID);
+ if (!lang_item_defined)
+ {
+ rust_error_at (locus, "unable to find lang item: %<c_str%>");
+ infered = new TyTy::ErrorType (expr_mappings.get_hirid (), locus);
+ break;
+ }
- TyTy::SliceType *slice
- = new TyTy::SliceType (slice_mapping.get_hirid (), locus,
- TyTy::TyVar (u8->get_ref ()));
- context->insert_type (slice_mapping, slice);
+ DefId cstr_defid = lang_item_defined.value ();
+ HIR::Item *item = mappings.lookup_defid (cstr_defid).value ();
+
+ TyTy::BaseType *item_type = nullptr;
+ bool ok = context->lookup_type (item->get_mappings ().get_hirid (),
+ &item_type);
+
+ rust_assert (ok);
+ rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
infered = new TyTy::ReferenceType (expr_mappings.get_hirid (),
- TyTy::TyVar (slice->get_ref ()),
+ TyTy::TyVar (item_type->get_ref ()),
Mutability::Imm,
TyTy::Region::make_static ());
}
bool
ReferenceType::is_dyn_object () const
{
- return is_dyn_slice_type () || is_dyn_str_type () || is_dyn_obj_type ();
+ return is_dyn_slice_type () || is_dyn_str_type () || is_dyn_obj_type ()
+ || is_dyn_cstr_type ();
}
static const TyTy::BaseType *
return true;
}
+bool
+ReferenceType::is_dyn_cstr_type (const TyTy::ADTType **adt) const
+{
+ if (get_base ()->get_kind () != TyTy::TypeKind::ADT)
+ return false;
+
+ const TyTy::ADTType *adt_ty
+ = static_cast<const TyTy::ADTType *> (get_base ());
+ auto &mappings = Analysis::Mappings::get ();
+ auto cstr_item = mappings.lookup_lang_item (LangItem::Kind::CSTR);
+
+ if (!cstr_item.has_value ())
+ return false;
+
+ if (cstr_item.value () != adt_ty->get_id ())
+ return false;
+
+ *adt = adt_ty;
+ return true;
+}
+
void
ReferenceType::accept_vis (TyVisitor &vis)
{
bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const;
bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const;
bool is_dyn_obj_type (const TyTy::DynamicObjectType **dyn = nullptr) const;
+ bool is_dyn_cstr_type (const TyTy::ADTType **adt = nullptr) const;
private:
TyVar base;
{"slice_u8", Kind::SLICE_U8},
{"slice", Kind::SLICE},
{"str", Kind::STR},
+ // NOTE: CStr is not present in Rust 1.49, and is only backported for
+ // compilation of Rust for Linux with a patched core lib.
+ {"CStr", Kind::CSTR},
{"f32_runtime", Kind::F32_RUNTIME},
{"f64_runtime", Kind::F64_RUNTIME},
SLICE_U8,
SLICE,
STR,
+ // NOTE: CStr is not present in Rust 1.49, and is only backported for
+ // compilation of Rust for Linux with a patched core lib.
+ CSTR,
F32_RUNTIME,
F64_RUNTIME,
// { dg-additional-options "-frust-c-style-string-literals" }
-#![feature(no_core)]
+#![feature(no_core, lang_items)]
#![no_core]
+type c_char = u8;
+
+#[lang = "CStr"]
+pub struct CStr {
+ inner: [c_char]
+}
+
+impl CStr {
+ pub const fn to_ptr(&self) -> *const c_char {
+ &self.inner as *const [c_char] as *const c_char
+ }
+}
+
pub fn main() {
let _fail = c"gc\0crs";
// { dg-error "null characters in C string literals are not supported" "" { target *-*-* } .-1 }
// { dg-additional-options "-frust-c-style-string-literals" }
-// { dg-output "gccrs\n" }
-#![feature(no_core)]
+// { dg-output "gccrs" }
+#![feature(no_core, lang_items)]
#![no_core]
extern "C" {
- fn printf(s: *const i8, ...);
+ fn printf(s: *const u8, ...);
}
-pub fn main() {
+type c_char = u8;
+
+#[lang = "CStr"]
+pub struct CStr {
+ inner: [c_char]
+}
+
+impl CStr {
+ pub const fn to_ptr(&self) -> *const c_char {
+ &self.inner as *const [c_char] as *const c_char
+ }
+}
+
+fn main() -> i32 {
let a = c"gccrs";
unsafe {
- printf(a as *const [u8] as *const i8); // TODO change `as *const [u8]` to `.as_ptr()` when C strings are compiled to their own CStr type
+ printf(a.to_ptr());
}
+ 0
}
--- /dev/null
+// { dg-additional-options "-frust-c-style-string-literals" }
+#![feature(no_core, intrinsics, staged_api, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+// below's helper code copied from issue-1232.rs
+extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+ fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+ pub const unsafe fn offset(self, count: isize) -> *const T {
+ unsafe { offset(self, count) }
+ }
+
+ pub const unsafe fn add(self, count: usize) -> Self {
+ unsafe { self.offset(count as isize) }
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+extern "C" {
+ fn printf(s: *const u8, ...);
+}
+
+type c_char = u8;
+
+#[lang = "CStr"]
+pub struct CStr {
+ inner: [c_char]
+}
+
+impl CStr {
+ pub const fn to_ptr(&self) -> *const c_char {
+ &self.inner as *const [c_char] as *const c_char
+ }
+}
+
+pub fn main() -> u8 {
+ let a = c"gccrs";
+ let val = unsafe { a.to_ptr().add(5) };
+ unsafe { *val }
+}