Files
carbon-lang/toolchain/check/testdata/impl/lookup/instance_method.carbon
T
Richard Smith 2044366652 Support initialization of specific classes from struct literals (#4320)
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.
2024-09-19 19:18:32 +00:00

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: