When a builtin function expects type T also allow an adapter for T. (#4643)

Extends the set of function signatures that support being given a
builtin definition to include cases where a parameter or return type is
an adapter for a supported type. For example, if we can give a builtin
definition to `Add(a: i32, b: i32) -> i32`, then we can also give a
builtin definition to `Add(a: MyI32, b: MyI32) - >MyI32` where `MyI32`
adapts `i32`.

This is a prerequisite for changing `Core.Int` to be a class type that
adapts the builtin int type.
This commit is contained in:
Richard Smith
2024-12-06 03:13:05 +00:00
committed by GitHub
parent 2bb520718d
commit cd1ecf1297
3 changed files with 307 additions and 18 deletions
+22 -15
View File
@@ -328,21 +328,9 @@ auto HandleParseNode(Context& context, Parse::FunctionDeclId node_id) -> bool {
return true;
}
// Processes a function definition after a signature for which we have already
// built a function ID. This logic is shared between processing regular function
// definitions and delayed parsing of inline method definitions.
static auto HandleFunctionDefinitionAfterSignature(
Context& context, Parse::FunctionDefinitionStartId node_id,
SemIR::FunctionId function_id, SemIR::InstId decl_id) -> void {
auto& function = context.functions().Get(function_id);
// Create the function scope and the entry block.
context.return_scope_stack().push_back({.decl_id = decl_id});
context.inst_block_stack().Push();
context.scope_stack().Push(decl_id);
StartGenericDefinition(context);
context.AddCurrentCodeBlockToFunction();
static auto CheckFunctionDefinitionSignature(Context& context,
SemIR::Function& function)
-> void {
// Check the return type is complete.
CheckFunctionReturnType(context, function.return_slot_pattern_id, function,
SemIR::SpecificId::Invalid);
@@ -370,6 +358,24 @@ static auto HandleFunctionDefinitionAfterSignature(
param_ref_id, IncompleteTypeInFunctionParam, param_ref_id);
});
}
}
// Processes a function definition after a signature for which we have already
// built a function ID. This logic is shared between processing regular function
// definitions and delayed parsing of inline method definitions.
static auto HandleFunctionDefinitionAfterSignature(
Context& context, Parse::FunctionDefinitionStartId node_id,
SemIR::FunctionId function_id, SemIR::InstId decl_id) -> void {
auto& function = context.functions().Get(function_id);
// Create the function scope and the entry block.
context.return_scope_stack().push_back({.decl_id = decl_id});
context.inst_block_stack().Push();
context.scope_stack().Push(decl_id);
StartGenericDefinition(context);
context.AddCurrentCodeBlockToFunction();
CheckFunctionDefinitionSignature(context, function);
context.node_stack().Push(node_id, function_id);
}
@@ -508,6 +514,7 @@ auto HandleParseNode(Context& context,
auto builtin_kind = LookupBuiltinFunctionKind(context, name_id);
if (builtin_kind != SemIR::BuiltinFunctionKind::None) {
auto& function = context.functions().Get(function_id);
CheckFunctionDefinitionSignature(context, function);
if (IsValidBuiltinDeclaration(context, function, builtin_kind)) {
function.builtin_function_kind = builtin_kind;
// Build an empty generic definition if this is a generic builtin.