On Thu, Sep 23, 2021 at 04:10:59PM +0200, Arthur Cohen wrote: > > Something I was thinking about outside of the scope of that patch was > about the utf8 how do they get represented? Is it some kind of wchar_t? > > Do you mean in C++ or in rustc? In rustc, they are represented as Unicode > Scalar Values which are 4 bytes wide. > > From the docs over here: [https://doc.rust-lang.org/std/primitive.char.html] > > So I'm assuming they could be represented as `int32_t`s which would also > make sense for the check
Yes, for rust characters a 32bit type (I would pick uint32_t or maybe char32_t) makes sense, since chars in rust are (almost) equal to unicode code points (technically only 21 bits are used). But not really, it is a Unicode scalar value, which excludes high-surrogate and low-surrogate code points and so the only valid values are 0x0 to 0xD7FF and 0xE000 to 0x10FFFF. We should not use the C type wchar_t, because wchar_t is implementation defined and can be 16 or 32 bits. See also https://doc.rust-lang.org/reference/types/textual.html But utf8 strings are made up of u8 "utf8 chars". You need 1 to 4 utf8 chars to encode a code point. https://en.wikipedia.org/wiki/UTF-8 We can use c++ strings made up of (8 bit) chars for that. Our lexer should make sure we only accept valid rust characters or utf-8 sequences. Note that the above doesn't hold for "byte chars" (b'A') or "byte strings" (b"abc"). Those are really just u8 or [u8] arrays which hold bytes (0x0 to 0xff). We currently get the type for byte strings wrong. We pretend they are &str, but they really should be &[u8]. I tried to fix that with the following: diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index fe8973a4d81..b0dd1c3ff2c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -609,15 +609,42 @@ public: break; case HIR::Literal::LitType::BYTE_STRING: { - /* We just treat this as a string, but it really is an arraytype of - u8. It isn't in UTF-8, but really just a byte array. */ - TyTy::BaseType *base = nullptr; - auto ok = context->lookup_builtin ("str", &base); + /* This is an arraytype of u8 reference (&[u8;size]). It isn't in + UTF-8, but really just a byte array. Code to construct the array + reference copied from ArrayElemsValues and ArrayType. */ + TyTy::BaseType *u8; + auto ok = context->lookup_builtin ("u8", &u8); rust_assert (ok); + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, UNKNOWN_NODEID, + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + /* Capacity is the size of the string (number of chars). + It is a constant, but for fold it to get a BExpression. */ + std::string capacity_str = std::to_string (expr.as_string ().size ()); + HIR::LiteralExpr literal_capacity (mapping, capacity_str, + HIR::Literal::LitType::INT, + PrimitiveCoreType::CORETYPE_USIZE, + expr.get_locus ()); + + // mark the type for this implicit node + context->insert_type (mapping, + new TyTy::USizeType (mapping.get_hirid ())); + + Bexpression *capacity + = ConstFold::ConstFoldExpr::fold (&literal_capacity); + + TyTy::ArrayType *array + = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), capacity, + TyTy::TyVar (u8->get_ref ())); + + context->insert_type (expr.get_mappings (), array); + infered = new TyTy::ReferenceType (expr.get_mappings ().get_hirid (), - TyTy::TyVar (base->get_ref ()), false); + TyTy::TyVar (array->get_ref ()), false); } break; But that looks more complicated than is probably necessary and it doesn't work. When the type checker wants to print this type ReferenceType.as_string () goes into a loop for some reason. Can anybody see what is wrong with the above? Cheers, Mark -- Gcc-rust mailing list Gcc-rust@gcc.gnu.org https://gcc.gnu.org/mailman/listinfo/gcc-rust