mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Rough support for calling a generic class name to form a class type. (#3939)
Co-authored-by: Jon Ross-Perkins <jperkins@google.com> Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
This commit is contained in:
co-authored by
Jon Ross-Perkins
Carbon Infra Bot
parent
76471cf701
commit
20c0322bbe
@@ -12,12 +12,35 @@
|
||||
|
||||
namespace Carbon::Check {
|
||||
|
||||
// Performs a call where the callee is the name of a generic class, such as
|
||||
// `Vector(i32)`.
|
||||
static auto PerformCallToGenericClass(Context& context, Parse::NodeId node_id,
|
||||
SemIR::ClassId class_id,
|
||||
llvm::ArrayRef<SemIR::InstId> arg_ids)
|
||||
-> SemIR::InstId {
|
||||
auto& class_info = context.classes().Get(class_id);
|
||||
|
||||
// Convert the arguments to match the parameters.
|
||||
auto converted_args_id = ConvertCallArgs(
|
||||
context, node_id, /*self_id=*/SemIR::InstId::Invalid, arg_ids,
|
||||
/*return_storage_id=*/SemIR::InstId::Invalid, class_info.decl_id,
|
||||
class_info.implicit_param_refs_id, class_info.param_refs_id);
|
||||
return context.AddInst(
|
||||
{node_id,
|
||||
SemIR::ClassType{SemIR::TypeId::TypeType, class_id, converted_args_id}});
|
||||
}
|
||||
|
||||
auto PerformCall(Context& context, Parse::NodeId node_id,
|
||||
SemIR::InstId callee_id, llvm::ArrayRef<SemIR::InstId> arg_ids)
|
||||
-> SemIR::InstId {
|
||||
// Identify the function we're calling.
|
||||
auto callee_function = GetCalleeFunction(context.sem_ir(), callee_id);
|
||||
if (!callee_function.function_id.is_valid()) {
|
||||
if (auto generic_class = context.types().TryGetAs<SemIR::GenericClassType>(
|
||||
context.insts().Get(callee_id).type_id())) {
|
||||
return PerformCallToGenericClass(context, node_id,
|
||||
generic_class->class_id, arg_ids);
|
||||
}
|
||||
if (!callee_function.is_error) {
|
||||
CARBON_DIAGNOSTIC(CallToNonCallable, Error,
|
||||
"Value of type `{0}` is not callable.", SemIR::TypeId);
|
||||
|
||||
@@ -1158,8 +1158,9 @@ auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
|
||||
SemIR::InstId return_storage_id, SemIR::InstId callee_id,
|
||||
SemIR::InstBlockId implicit_param_refs_id,
|
||||
SemIR::InstBlockId param_refs_id) -> SemIR::InstBlockId {
|
||||
auto implicit_param_refs = context.inst_blocks().Get(implicit_param_refs_id);
|
||||
auto param_refs = context.inst_blocks().Get(param_refs_id);
|
||||
auto implicit_param_refs =
|
||||
context.inst_blocks().GetOrEmpty(implicit_param_refs_id);
|
||||
auto param_refs = context.inst_blocks().GetOrEmpty(param_refs_id);
|
||||
|
||||
// If sizes mismatch, fail early.
|
||||
if (arg_refs.size() != param_refs.size()) {
|
||||
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
|
||||
// --- call.carbon
|
||||
|
||||
library "call" api;
|
||||
|
||||
class Class(T:! type, N:! i32) {}
|
||||
|
||||
var a: Class(i32*, 5);
|
||||
|
||||
// Requires an implicit conversion to type `type`.
|
||||
var b: Class((), 0);
|
||||
|
||||
// --- fail_too_few.carbon
|
||||
|
||||
library "too_few" api;
|
||||
|
||||
class Class(T:! type, N:! i32) {}
|
||||
|
||||
// CHECK:STDERR: fail_too_few.carbon:[[@LINE+7]]:8: ERROR: 1 argument(s) passed to function expecting 2 argument(s).
|
||||
// CHECK:STDERR: var a: Class(i32*);
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: fail_too_few.carbon:[[@LINE-5]]:1: Calling function declared here.
|
||||
// CHECK:STDERR: class Class(T:! type, N:! i32) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
var a: Class(i32*);
|
||||
|
||||
// --- fail_too_many.carbon
|
||||
|
||||
library "too_many" api;
|
||||
|
||||
class Class(T:! type, N:! i32) {}
|
||||
|
||||
// CHECK:STDERR: fail_too_many.carbon:[[@LINE+7]]:8: ERROR: 3 argument(s) passed to function expecting 2 argument(s).
|
||||
// CHECK:STDERR: var a: Class(i32*, 1, 2);
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: fail_too_many.carbon:[[@LINE-5]]:1: Calling function declared here.
|
||||
// CHECK:STDERR: class Class(T:! type, N:! i32) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
var a: Class(i32*, 1, 2);
|
||||
|
||||
// --- fail_no_conversion.carbon
|
||||
|
||||
library "no_conversion" api;
|
||||
|
||||
class Class(T:! type, N:! i32) {}
|
||||
|
||||
// CHECK:STDERR: fail_no_conversion.carbon:[[@LINE+6]]:8: ERROR: Cannot implicitly convert from `i32` to `type`.
|
||||
// CHECK:STDERR: var a: Class(5, i32*);
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: fail_no_conversion.carbon:[[@LINE-5]]:1: Initializing parameter 1 of function declared here.
|
||||
// CHECK:STDERR: class Class(T:! type, N:! i32) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
var a: Class(5, i32*);
|
||||
|
||||
// CHECK:STDOUT: --- call.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic]
|
||||
// CHECK:STDOUT: %N: i32 = bind_symbolic_name N 1 [symbolic]
|
||||
// CHECK:STDOUT: %Class.1: type = generic_class_type @Class [template]
|
||||
// CHECK:STDOUT: %.1: type = tuple_type () [template]
|
||||
// CHECK:STDOUT: %struct: Class = struct_value () [template]
|
||||
// CHECK:STDOUT: %Class.2: type = class_type @Class [template]
|
||||
// CHECK:STDOUT: %.2: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type i32 [template]
|
||||
// CHECK:STDOUT: %.4: i32 = int_literal 5 [template]
|
||||
// CHECK:STDOUT: %Class.3: type = class_type @Class, (file.%.loc6_17, file.%.loc6_20) [template]
|
||||
// CHECK:STDOUT: %.5: type = ptr_type {} [template]
|
||||
// CHECK:STDOUT: %.6: i32 = int_literal 0 [template]
|
||||
// CHECK:STDOUT: %Class.4: type = class_type @Class, (file.%.loc9_13, file.%.loc9_18) [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .Class = %Class.decl
|
||||
// CHECK:STDOUT: .a = %a
|
||||
// CHECK:STDOUT: .b = %b
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %Class.decl: Class = class_decl @Class [template = constants.%struct] {
|
||||
// CHECK:STDOUT: %T.loc4_13.1: type = param T
|
||||
// CHECK:STDOUT: %T.loc4_13.2: type = bind_symbolic_name T 0, %T.loc4_13.1 [symbolic = constants.%T]
|
||||
// CHECK:STDOUT: %N.loc4_23.1: i32 = param N
|
||||
// CHECK:STDOUT: %N.loc4_23.2: i32 = bind_symbolic_name N 1, %N.loc4_23.1 [symbolic = constants.%N]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Class.ref.loc6: Class = name_ref Class, %Class.decl [template = constants.%struct]
|
||||
// CHECK:STDOUT: %.loc6_17: type = ptr_type i32 [template = constants.%.3]
|
||||
// CHECK:STDOUT: %.loc6_20: i32 = int_literal 5 [template = constants.%.4]
|
||||
// CHECK:STDOUT: %Class.loc6: type = class_type @Class, (%.loc6_17, %.loc6_20) [template = constants.%Class.3]
|
||||
// CHECK:STDOUT: %a.var: ref Class = var a
|
||||
// CHECK:STDOUT: %a: ref Class = bind_name a, %a.var
|
||||
// CHECK:STDOUT: %Class.ref.loc9: Class = name_ref Class, %Class.decl [template = constants.%struct]
|
||||
// CHECK:STDOUT: %.loc9_15: () = tuple_literal ()
|
||||
// CHECK:STDOUT: %.loc9_18: i32 = int_literal 0 [template = constants.%.6]
|
||||
// CHECK:STDOUT: %.loc9_13: type = converted %.loc9_15, constants.%.1 [template = constants.%.1]
|
||||
// CHECK:STDOUT: %Class.loc9: type = class_type @Class, (%.loc9_13, %.loc9_18) [template = constants.%Class.4]
|
||||
// CHECK:STDOUT: %b.var: ref Class = var b
|
||||
// CHECK:STDOUT: %b: ref Class = bind_name b, %b.var
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @Class {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%Class.2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_too_few.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic]
|
||||
// CHECK:STDOUT: %N: i32 = bind_symbolic_name N 1 [symbolic]
|
||||
// CHECK:STDOUT: %Class.1: type = generic_class_type @Class [template]
|
||||
// CHECK:STDOUT: %.1: type = tuple_type () [template]
|
||||
// CHECK:STDOUT: %struct: Class = struct_value () [template]
|
||||
// CHECK:STDOUT: %Class.2: type = class_type @Class [template]
|
||||
// CHECK:STDOUT: %.2: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type i32 [template]
|
||||
// CHECK:STDOUT: %.4: type = ptr_type {} [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .Class = %Class.decl
|
||||
// CHECK:STDOUT: .a = %a
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %Class.decl: Class = class_decl @Class [template = constants.%struct] {
|
||||
// CHECK:STDOUT: %T.loc4_13.1: type = param T
|
||||
// CHECK:STDOUT: %T.loc4_13.2: type = bind_symbolic_name T 0, %T.loc4_13.1 [symbolic = constants.%T]
|
||||
// CHECK:STDOUT: %N.loc4_23.1: i32 = param N
|
||||
// CHECK:STDOUT: %N.loc4_23.2: i32 = bind_symbolic_name N 1, %N.loc4_23.1 [symbolic = constants.%N]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Class.ref: Class = name_ref Class, %Class.decl [template = constants.%struct]
|
||||
// CHECK:STDOUT: %.loc13: type = ptr_type i32 [template = constants.%.3]
|
||||
// CHECK:STDOUT: %Class: type = class_type @Class [template = constants.%Class.2]
|
||||
// CHECK:STDOUT: %a.var: ref Class = var a
|
||||
// CHECK:STDOUT: %a: ref Class = bind_name a, %a.var
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @Class {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%Class.2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_too_many.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic]
|
||||
// CHECK:STDOUT: %N: i32 = bind_symbolic_name N 1 [symbolic]
|
||||
// CHECK:STDOUT: %Class.1: type = generic_class_type @Class [template]
|
||||
// CHECK:STDOUT: %.1: type = tuple_type () [template]
|
||||
// CHECK:STDOUT: %struct: Class = struct_value () [template]
|
||||
// CHECK:STDOUT: %Class.2: type = class_type @Class [template]
|
||||
// CHECK:STDOUT: %.2: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type i32 [template]
|
||||
// CHECK:STDOUT: %.4: i32 = int_literal 1 [template]
|
||||
// CHECK:STDOUT: %.5: i32 = int_literal 2 [template]
|
||||
// CHECK:STDOUT: %.6: type = ptr_type {} [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .Class = %Class.decl
|
||||
// CHECK:STDOUT: .a = %a
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %Class.decl: Class = class_decl @Class [template = constants.%struct] {
|
||||
// CHECK:STDOUT: %T.loc4_13.1: type = param T
|
||||
// CHECK:STDOUT: %T.loc4_13.2: type = bind_symbolic_name T 0, %T.loc4_13.1 [symbolic = constants.%T]
|
||||
// CHECK:STDOUT: %N.loc4_23.1: i32 = param N
|
||||
// CHECK:STDOUT: %N.loc4_23.2: i32 = bind_symbolic_name N 1, %N.loc4_23.1 [symbolic = constants.%N]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Class.ref: Class = name_ref Class, %Class.decl [template = constants.%struct]
|
||||
// CHECK:STDOUT: %.loc13_17: type = ptr_type i32 [template = constants.%.3]
|
||||
// CHECK:STDOUT: %.loc13_20: i32 = int_literal 1 [template = constants.%.4]
|
||||
// CHECK:STDOUT: %.loc13_23: i32 = int_literal 2 [template = constants.%.5]
|
||||
// CHECK:STDOUT: %Class: type = class_type @Class [template = constants.%Class.2]
|
||||
// CHECK:STDOUT: %a.var: ref Class = var a
|
||||
// CHECK:STDOUT: %a: ref Class = bind_name a, %a.var
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @Class {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%Class.2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_no_conversion.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic]
|
||||
// CHECK:STDOUT: %N: i32 = bind_symbolic_name N 1 [symbolic]
|
||||
// CHECK:STDOUT: %Class.1: type = generic_class_type @Class [template]
|
||||
// CHECK:STDOUT: %.1: type = tuple_type () [template]
|
||||
// CHECK:STDOUT: %struct: Class = struct_value () [template]
|
||||
// CHECK:STDOUT: %Class.2: type = class_type @Class [template]
|
||||
// CHECK:STDOUT: %.2: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %.3: i32 = int_literal 5 [template]
|
||||
// CHECK:STDOUT: %.4: type = ptr_type i32 [template]
|
||||
// CHECK:STDOUT: %.5: type = ptr_type {} [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .Class = %Class.decl
|
||||
// CHECK:STDOUT: .a = %a
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %Class.decl: Class = class_decl @Class [template = constants.%struct] {
|
||||
// CHECK:STDOUT: %T.loc4_13.1: type = param T
|
||||
// CHECK:STDOUT: %T.loc4_13.2: type = bind_symbolic_name T 0, %T.loc4_13.1 [symbolic = constants.%T]
|
||||
// CHECK:STDOUT: %N.loc4_23.1: i32 = param N
|
||||
// CHECK:STDOUT: %N.loc4_23.2: i32 = bind_symbolic_name N 1, %N.loc4_23.1 [symbolic = constants.%N]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Class.ref: Class = name_ref Class, %Class.decl [template = constants.%struct]
|
||||
// CHECK:STDOUT: %.loc12_14: i32 = int_literal 5 [template = constants.%.3]
|
||||
// CHECK:STDOUT: %.loc12_20: type = ptr_type i32 [template = constants.%.4]
|
||||
// CHECK:STDOUT: %Class: type = class_type @Class [template = constants.%Class.2]
|
||||
// CHECK:STDOUT: %a.var: ref Class = var a
|
||||
// CHECK:STDOUT: %a: ref Class = bind_name a, %a.var
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @Class {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%Class.2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
+25
-7
@@ -14,10 +14,21 @@ class Class(T:! type) {
|
||||
|
||||
// TODO: The following should work.
|
||||
fn Run() -> i32 {
|
||||
// CHECK:STDERR: fail_todo_use.carbon:[[@LINE+3]]:10: ERROR: Value of type `Class` is not callable.
|
||||
// CHECK:STDERR: fail_todo_use.carbon:[[@LINE+4]]:23: ERROR: Cannot implicitly convert from `i32` to `T`.
|
||||
// CHECK:STDERR: var v: Class(i32) = {.k = 0};
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
var v: Class(i32) = {.k = 0};
|
||||
// CHECK:STDERR: fail_todo_use.carbon:[[@LINE+10]]:3: ERROR: Cannot implicitly convert from `T*` to `i32`.
|
||||
// CHECK:STDERR: return v.Get();
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// CHECK:STDERR: fail_todo_use.carbon:[[@LINE+6]]:10: ERROR: Cannot implicitly convert from `Class*` to `Class*`.
|
||||
// CHECK:STDERR: return v.Get();
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: fail_todo_use.carbon:[[@LINE-21]]:15: Initializing `addr self` parameter of method declared here.
|
||||
// CHECK:STDERR: fn Get[addr self: Self*]() -> T* {
|
||||
// CHECK:STDERR: ^~~~
|
||||
return v.Get();
|
||||
}
|
||||
|
||||
@@ -38,8 +49,10 @@ fn Run() -> i32 {
|
||||
// CHECK:STDOUT: %.6: type = ptr_type {.k: T} [symbolic]
|
||||
// CHECK:STDOUT: %Run: type = fn_type @Run [template]
|
||||
// CHECK:STDOUT: %struct.3: Run = struct_value () [template]
|
||||
// CHECK:STDOUT: %Class.3: type = class_type @Class, (i32) [template]
|
||||
// CHECK:STDOUT: %.7: i32 = int_literal 0 [template]
|
||||
// CHECK:STDOUT: %.8: type = struct_type {.k: i32} [template]
|
||||
// CHECK:STDOUT: %.9: type = ptr_type Class [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
@@ -91,12 +104,17 @@ fn Run() -> i32 {
|
||||
// CHECK:STDOUT: fn @Run() -> i32 {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %Class.ref: Class = name_ref Class, file.%Class.decl [template = constants.%struct.1]
|
||||
// CHECK:STDOUT: %v.var: ref <error> = var v
|
||||
// CHECK:STDOUT: %v: ref <error> = bind_name v, %v.var
|
||||
// CHECK:STDOUT: %.loc20_29: i32 = int_literal 0 [template = constants.%.7]
|
||||
// CHECK:STDOUT: %.loc20_30: {.k: i32} = struct_literal (%.loc20_29)
|
||||
// CHECK:STDOUT: %Class: type = class_type @Class, (i32) [template = constants.%Class.3]
|
||||
// CHECK:STDOUT: %v.var: ref Class = var v
|
||||
// CHECK:STDOUT: %v: ref Class = bind_name v, %v.var
|
||||
// CHECK:STDOUT: %.loc21_29: i32 = int_literal 0 [template = constants.%.7]
|
||||
// CHECK:STDOUT: %.loc21_30: {.k: i32} = struct_literal (%.loc21_29)
|
||||
// CHECK:STDOUT: assign %v.var, <error>
|
||||
// CHECK:STDOUT: %v.ref: ref <error> = name_ref v, %v
|
||||
// CHECK:STDOUT: %v.ref: ref Class = name_ref v, %v
|
||||
// CHECK:STDOUT: %Get.ref: Get = name_ref Get, @Class.%Get.decl [template = constants.%struct.2]
|
||||
// CHECK:STDOUT: %.loc32_11: <bound method> = bound_method %v.ref, %Get.ref
|
||||
// CHECK:STDOUT: %.loc32_10: Class* = addr_of %v.ref
|
||||
// CHECK:STDOUT: %Get.call: init T* = call %.loc32_11(<invalid>) [template = <error>]
|
||||
// CHECK:STDOUT: return <error>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
@@ -604,6 +604,14 @@ class Formatter {
|
||||
FormatTrailingBlock(inst.decl_block_id);
|
||||
}
|
||||
|
||||
auto FormatInstructionRHS(ClassType inst) -> void {
|
||||
if (inst.args_id.is_valid()) {
|
||||
FormatArgs(inst.class_id, inst.args_id);
|
||||
} else {
|
||||
FormatArgs(inst.class_id);
|
||||
}
|
||||
}
|
||||
|
||||
auto FormatInstructionRHS(ImplDecl inst) -> void {
|
||||
FormatArgs(inst.impl_id);
|
||||
FormatTrailingBlock(inst.decl_block_id);
|
||||
|
||||
@@ -437,6 +437,12 @@ class InstBlockStore : public BlockValueStore<InstBlockId> {
|
||||
CARBON_CHECK(block_id != InstBlockId::Unreachable);
|
||||
BlockValueStore<InstBlockId>::Set(block_id, content);
|
||||
}
|
||||
|
||||
// Returns the contents of the specified block, or an empty array if the block
|
||||
// is empty.
|
||||
auto GetOrEmpty(InstBlockId block_id) -> llvm::ArrayRef<InstId> {
|
||||
return block_id.is_valid() ? Get(block_id) : llvm::ArrayRef<InstId>();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Carbon::SemIR
|
||||
|
||||
@@ -35,7 +35,15 @@ static auto DefaultProfileArgFunction(llvm::FoldingSetNodeID& id,
|
||||
static auto InstBlockProfileArgFunction(llvm::FoldingSetNodeID& id,
|
||||
const File& sem_ir, int32_t arg)
|
||||
-> void {
|
||||
for (auto inst_id : sem_ir.inst_blocks().Get(InstBlockId(arg))) {
|
||||
auto inst_block_id = InstBlockId(arg);
|
||||
if (!inst_block_id.is_valid()) {
|
||||
id.AddInteger(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
auto inst_block = sem_ir.inst_blocks().Get(inst_block_id);
|
||||
id.AddInteger(inst_block.size());
|
||||
for (auto inst_id : inst_block) {
|
||||
id.AddInteger(inst_id.index);
|
||||
}
|
||||
}
|
||||
@@ -45,7 +53,15 @@ static auto InstBlockProfileArgFunction(llvm::FoldingSetNodeID& id,
|
||||
static auto TypeBlockProfileArgFunction(llvm::FoldingSetNodeID& id,
|
||||
const File& sem_ir, int32_t arg)
|
||||
-> void {
|
||||
for (auto type_id : sem_ir.type_blocks().Get(TypeBlockId(arg))) {
|
||||
auto type_block_id = TypeBlockId(arg);
|
||||
if (!type_block_id.is_valid()) {
|
||||
id.AddInteger(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
auto type_block = sem_ir.type_blocks().Get(type_block_id);
|
||||
id.AddInteger(type_block.size());
|
||||
for (auto type_id : type_block) {
|
||||
id.AddInteger(type_id.index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,11 +402,11 @@ struct ClassInit {
|
||||
|
||||
struct ClassType {
|
||||
static constexpr auto Kind =
|
||||
InstKind::ClassType.Define<Parse::AnyClassDeclId>("class_type");
|
||||
InstKind::ClassType.Define<Parse::NodeId>("class_type");
|
||||
|
||||
TypeId type_id;
|
||||
ClassId class_id;
|
||||
// TODO: Once we support generic classes, include the class's arguments here.
|
||||
InstBlockId args_id = InstBlockId::Invalid;
|
||||
};
|
||||
|
||||
struct ConstType {
|
||||
|
||||
Reference in New Issue
Block a user