mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Add support for initializing types like `GenericClass(i32)` from a struct literal. A new kind of instruction, `complete_type_witness`, is added to the class definition to track the object representation type so that it's visible to the generics machinery. Accesses to the object representation of a class have all been updated to pass in the class's `SpecificId` so that the types of the fields of the specific class are used instead of the types of the fields of the generic class in places that look at the object representation -- primarily class initialization.
166 lines
8.0 KiB
Plaintext
166 lines
8.0 KiB
Plaintext
// 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
|
|
// TIP: To test this file alone, run:
|
|
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/lookup/instance_method.carbon
|
|
// TIP: To dump output, run:
|
|
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/lookup/instance_method.carbon
|
|
|
|
class C;
|
|
|
|
interface I {
|
|
fn F[self: Self]() -> i32;
|
|
}
|
|
|
|
class C {
|
|
extend impl as I {
|
|
fn F[self: Self]() -> i32;
|
|
}
|
|
}
|
|
|
|
fn F(c: C) -> i32 {
|
|
return c.F();
|
|
}
|
|
|
|
// CHECK:STDOUT: --- instance_method.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: constants {
|
|
// CHECK:STDOUT: %C: type = class_type @C [template]
|
|
// CHECK:STDOUT: %.1: type = interface_type @I [template]
|
|
// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic]
|
|
// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template]
|
|
// CHECK:STDOUT: %.2: type = tuple_type () [template]
|
|
// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template]
|
|
// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template]
|
|
// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template]
|
|
// CHECK:STDOUT: %.3: type = assoc_entity_type %.1, %F.type.1 [template]
|
|
// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @I.%F.decl [template]
|
|
// CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template]
|
|
// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template]
|
|
// CHECK:STDOUT: %.5: <witness> = interface_witness (%F.2) [template]
|
|
// CHECK:STDOUT: %.6: type = struct_type {} [template]
|
|
// CHECK:STDOUT: %.7: <witness> = complete_type_witness %.6 [template]
|
|
// CHECK:STDOUT: %F.type.3: type = fn_type @F.3 [template]
|
|
// CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [template]
|
|
// CHECK:STDOUT: %.8: type = ptr_type %.6 [template]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: imports {
|
|
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
|
|
// CHECK:STDOUT: .Int32 = %import_ref
|
|
// CHECK:STDOUT: import Core//prelude
|
|
// CHECK:STDOUT: import Core//prelude/operators
|
|
// CHECK:STDOUT: import Core//prelude/types
|
|
// CHECK:STDOUT: import Core//prelude/operators/arithmetic
|
|
// CHECK:STDOUT: import Core//prelude/operators/as
|
|
// CHECK:STDOUT: import Core//prelude/operators/bitwise
|
|
// CHECK:STDOUT: import Core//prelude/operators/comparison
|
|
// CHECK:STDOUT: import Core//prelude/types/bool
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
|
// CHECK:STDOUT: .Core = imports.%Core
|
|
// CHECK:STDOUT: .C = %C.decl.loc11
|
|
// CHECK:STDOUT: .I = %I.decl
|
|
// CHECK:STDOUT: .F = %F.decl
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %Core.import = import Core
|
|
// CHECK:STDOUT: %C.decl.loc11: type = class_decl @C [template = constants.%C] {}
|
|
// CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%.1] {}
|
|
// CHECK:STDOUT: %C.decl.loc17: type = class_decl @C [template = constants.%C] {}
|
|
// CHECK:STDOUT: %F.decl: %F.type.3 = fn_decl @F.3 [template = constants.%F.3] {
|
|
// CHECK:STDOUT: %C.ref: type = name_ref C, %C.decl.loc11 [template = constants.%C]
|
|
// CHECK:STDOUT: %c.loc23_6.1: %C = param c, runtime_param0
|
|
// CHECK:STDOUT: @F.3.%c: %C = bind_name c, %c.loc23_6.1
|
|
// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32]
|
|
// CHECK:STDOUT: %.loc23_15.1: type = value_of_initializer %int.make_type_32 [template = i32]
|
|
// CHECK:STDOUT: %.loc23_15.2: type = converted %int.make_type_32, %.loc23_15.1 [template = i32]
|
|
// CHECK:STDOUT: @F.3.%return: ref i32 = var <return slot>
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: interface @I {
|
|
// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self]
|
|
// CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] {
|
|
// CHECK:STDOUT: %Self.ref: %.1 = name_ref Self, %Self [symbolic = @F.1.%Self (constants.%Self)]
|
|
// CHECK:STDOUT: %.loc14_14.1: type = facet_type_access %Self.ref [symbolic = @F.1.%Self (constants.%Self)]
|
|
// CHECK:STDOUT: %.loc14_14.2: type = converted %Self.ref, %.loc14_14.1 [symbolic = @F.1.%Self (constants.%Self)]
|
|
// CHECK:STDOUT: %self.loc14_8.1: @F.1.%Self (%Self) = param self, runtime_param0
|
|
// CHECK:STDOUT: %self.loc14_8.2: @F.1.%Self (%Self) = bind_name self, %self.loc14_8.1
|
|
// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32]
|
|
// CHECK:STDOUT: %.loc14_25.1: type = value_of_initializer %int.make_type_32 [template = i32]
|
|
// CHECK:STDOUT: %.loc14_25.2: type = converted %int.make_type_32, %.loc14_25.1 [template = i32]
|
|
// CHECK:STDOUT: %return.var: ref i32 = var <return slot>
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %.loc14_28: %.3 = assoc_entity element0, %F.decl [template = constants.%.4]
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: .Self = %Self
|
|
// CHECK:STDOUT: .F = %.loc14_28
|
|
// CHECK:STDOUT: witness = (%F.decl)
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: impl @impl: %C as %.1 {
|
|
// CHECK:STDOUT: %F.decl: %F.type.2 = fn_decl @F.2 [template = constants.%F.2] {
|
|
// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%C [template = constants.%C]
|
|
// CHECK:STDOUT: %self.loc19_10.1: %C = param self, runtime_param0
|
|
// CHECK:STDOUT: %self.loc19_10.2: %C = bind_name self, %self.loc19_10.1
|
|
// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32]
|
|
// CHECK:STDOUT: %.loc19_27.1: type = value_of_initializer %int.make_type_32 [template = i32]
|
|
// CHECK:STDOUT: %.loc19_27.2: type = converted %int.make_type_32, %.loc19_27.1 [template = i32]
|
|
// CHECK:STDOUT: %return.var: ref i32 = var <return slot>
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %.loc18: <witness> = interface_witness (%F.decl) [template = constants.%.5]
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: .F = %F.decl
|
|
// CHECK:STDOUT: witness = %.loc18
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: class @C {
|
|
// CHECK:STDOUT: impl_decl @impl {
|
|
// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%.1]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %.loc21: <witness> = complete_type_witness %.6 [template = constants.%.7]
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: .Self = constants.%C
|
|
// CHECK:STDOUT: extend name_scope2
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: generic fn @F.1(@I.%Self: %.1) {
|
|
// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)]
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn[@I.%self.loc14_8.2: @F.1.%Self (%Self)]() -> i32;
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @F.2[@impl.%self.loc19_10.2: %C]() -> i32;
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @F.3(%c: %C) -> i32 {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: %c.ref: %C = name_ref c, %c
|
|
// CHECK:STDOUT: %F.ref: %.3 = name_ref F, @I.%.loc14_28 [template = constants.%.4]
|
|
// CHECK:STDOUT: %.loc24_11.1: %F.type.1 = interface_witness_access @impl.%.loc18, element0 [template = constants.%F.2]
|
|
// CHECK:STDOUT: %.loc24_11.2: <bound method> = bound_method %c.ref, %.loc24_11.1
|
|
// CHECK:STDOUT: %F.call: init i32 = call %.loc24_11.2(%c.ref)
|
|
// CHECK:STDOUT: %.loc24_15.1: i32 = value_of_initializer %F.call
|
|
// CHECK:STDOUT: %.loc24_15.2: i32 = converted %F.call, %.loc24_15.1
|
|
// CHECK:STDOUT: return %.loc24_15.2
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: specific @F.1(constants.%Self) {
|
|
// CHECK:STDOUT: %Self => constants.%Self
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: specific @F.1(constants.%C) {
|
|
// CHECK:STDOUT: %Self => constants.%C
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|