mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Interop support for initialization via std::initializer_list. (#6672)
Add a new builtin function `cpp.std.initializer_list.make` that takes an array and returns a `std::initializer_list`, initialized to refer to that array. When C++ initialization wants to perform a `std::initializer_list`-from-array construction, synthesize a declaration of a matching builtin function and use that to perform the initialization. Ideally we would specify this conversion as an impl of `ImplicitAs` in the prelude instead of hardcoding it in the interop layer, but unfortunately that's not currently possible, for various reasons -- we can't make the conversion form-generic, we can't deduce the array length from the initializer, and we can't deduce against the arguments of imported C++ class templates yet -- so for now synthesizing a builtin function on demand is the best we can do. Assisted-by: Gemini 3 Pro via Antigravity
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "toolchain/sem_ir/cpp_initializer_list.h"
|
||||
#include "toolchain/sem_ir/file.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
#include "toolchain/sem_ir/type_info.h"
|
||||
@@ -146,14 +147,24 @@ struct CharCompatible {
|
||||
}
|
||||
};
|
||||
|
||||
// Constraint that requires the type to be a sized integer type.
|
||||
struct AnySizedInt {
|
||||
// Constraint that requires the type to be an type of the specified kind.
|
||||
template <typename InstT>
|
||||
struct Any {
|
||||
static auto CheckType(const File& sem_ir, ValidateState& /*state*/,
|
||||
TypeId type_id) -> bool {
|
||||
return sem_ir.types().Is<IntType>(type_id);
|
||||
return sem_ir.types().Is<InstT>(type_id);
|
||||
}
|
||||
};
|
||||
|
||||
// Constraint that requires the type to be a sized integer type.
|
||||
using AnySizedInt = Any<IntType>;
|
||||
|
||||
// Constraint that requires the type to be a sized floating-point type.
|
||||
using AnySizedFloat = Any<FloatType>;
|
||||
|
||||
// Constraint that requires the type to be an array type.
|
||||
using AnyArray = Any<ArrayType>;
|
||||
|
||||
// Constraint that requires the type to be an integer type: either a sized
|
||||
// integer type or a literal.
|
||||
struct AnyInt {
|
||||
@@ -165,14 +176,6 @@ struct AnyInt {
|
||||
}
|
||||
};
|
||||
|
||||
// Constraint that requires the type to be a sized floating-point type.
|
||||
struct AnySizedFloat {
|
||||
static auto CheckType(const File& sem_ir, ValidateState& /*state*/,
|
||||
TypeId type_id) -> bool {
|
||||
return sem_ir.types().Is<FloatType>(type_id);
|
||||
}
|
||||
};
|
||||
|
||||
// Constraint that requires the type to be a float type: either a sized float
|
||||
// type or a literal.
|
||||
struct AnyFloat {
|
||||
@@ -222,6 +225,16 @@ struct CoreCharType {
|
||||
}
|
||||
};
|
||||
|
||||
// Constraint that requires the type to have a recognized layout, compatible
|
||||
// with `std::initializer_list<T>`.
|
||||
struct StdInitializerList {
|
||||
static auto CheckType(const File& sem_ir, ValidateState& /*state*/,
|
||||
TypeId type_id) -> bool {
|
||||
return GetStdInitializerListLayout(sem_ir, type_id).kind !=
|
||||
StdInitializerListLayout::None;
|
||||
}
|
||||
};
|
||||
|
||||
// Constraint that requires the type to be the type type.
|
||||
using Type = BuiltinType<TypeType::TypeInstId>;
|
||||
|
||||
@@ -734,6 +747,12 @@ constexpr BuiltinInfo PointerUnsafeConvert = {
|
||||
constexpr BuiltinInfo TypeAnd = {"type.and",
|
||||
ValidateSignature<auto(Type, Type)->Type>};
|
||||
|
||||
// "cpp.std.initializer_list.make": construct a std::initializer_list from an
|
||||
// array.
|
||||
constexpr BuiltinInfo CppStdInitializerListMake = {
|
||||
"cpp.std.initializer_list.make",
|
||||
ValidateSignature<auto(AnyArray)->StdInitializerList>};
|
||||
|
||||
} // namespace BuiltinFunctionInfo
|
||||
|
||||
CARBON_DEFINE_ENUM_CLASS_NAMES(BuiltinFunctionKind) {
|
||||
|
||||
Reference in New Issue
Block a user