Split `Type` in half: separate `RsType` and `CcType`.
This is, I think, adequately motivated by the sheer impossibility of the original design working. Consider the following compound data type:
`int*` in C++ may be `Option<&i32>` in Rust.
This cannot be expressed in the old `Type` struct because it assumed the generic layout was the same: it assumed that if the C++ type was e.g. `*<int>`, then the rust type would be shaped like `a<b>` for some type names `a` and `b`. But in this case, `*<int>` becomes `Option<&<i32>>`. And anyway, `&` takes a lifetime parameter, so this is actually `Option<&<'_, i32>>`. Just not shaped the same at all!
There are many more cases beside. Here's an incomplete list of possible type maps which are incompatible with the old layout:
* `const char*` becomes `CStr`
* function pointers AND functions -- that is, `Identity<void()>` and `Identity<void()>*` -- both can become non-pointer functions in Rust: `extern "C" fn()->()`.
* `std::span<char, std::dynamic_extent>` (2 params) becomes `&mut [u8]` (1 param)
We should change this to do the right thing now, early on, rather than later when it will be even more annoying. :)
This is, in cool news, our first major divergence from [Clif's AST proto](http://google3/third_party/clif/protos/ast.proto;l=156-171;rcl=397117954).
PiperOrigin-RevId: 399622062
diff --git a/rs_bindings_from_cc/ast_visitor.cc b/rs_bindings_from_cc/ast_visitor.cc
index 71b45e5..0659bd8 100644
--- a/rs_bindings_from_cc/ast_visitor.cc
+++ b/rs_bindings_from_cc/ast_visitor.cc
@@ -123,40 +123,40 @@
return true;
}
-absl::StatusOr<Type> AstVisitor::ConvertType(
+absl::StatusOr<MappedType> AstVisitor::ConvertType(
clang::QualType qual_type, const clang::ASTContext& ctx) const {
- std::optional<Type> type = std::nullopt;
+ std::optional<MappedType> type = std::nullopt;
std::string type_string = qual_type.getAsString();
if (const clang::PointerType* pointer_type =
qual_type->getAs<clang::PointerType>()) {
auto pointee_type = ConvertType(pointer_type->getPointeeType(), ctx);
if (pointee_type.ok()) {
- type = Type::PointerTo(*pointee_type);
+ type = MappedType::PointerTo(*pointee_type);
}
} else if (const clang::BuiltinType* builtin_type =
qual_type->getAs<clang::BuiltinType>()) {
switch (builtin_type->getKind()) {
case clang::BuiltinType::Bool:
- type = {"bool", "bool"};
+ type = MappedType::Simple("bool", "bool");
break;
case clang::BuiltinType::Float:
- type = {"float", "float"};
+ type = MappedType::Simple("float", "float");
break;
case clang::BuiltinType::Double:
- type = {"double", "double"};
+ type = MappedType::Simple("double", "double");
break;
case clang::BuiltinType::Void:
- type = Type::Void();
+ type = MappedType::Void();
break;
default:
if (builtin_type->isIntegerType()) {
auto size = ctx.getTypeSize(builtin_type);
if (size == 8 || size == 16 || size == 32 || size == 64) {
- type = Type{
+ type = MappedType::Simple(
absl::Substitute(
"$0$1", builtin_type->isSignedInteger() ? 'i' : 'u', size),
- type_string};
+ type_string);
}
}
}
@@ -170,7 +170,7 @@
}
// Add cv-qualification.
- type->cc_const = qual_type.isConstQualified();
+ type->cc_type.is_const = qual_type.isConstQualified();
// Not doing volatile for now -- note that volatile pointers do not exist in
// Rust, though volatile reads/writes still do.