mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 09:31:05 +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.
135 lines
5.5 KiB
Plaintext
135 lines
5.5 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/extend_impl.carbon
|
|
// TIP: To dump output, run:
|
|
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/extend_impl.carbon
|
|
|
|
interface HasF {
|
|
fn F();
|
|
}
|
|
|
|
class C {
|
|
extend impl as HasF {
|
|
fn F() {}
|
|
}
|
|
}
|
|
|
|
fn G(c: C) {
|
|
C.F();
|
|
c.F();
|
|
}
|
|
|
|
// CHECK:STDOUT: --- extend_impl.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: constants {
|
|
// CHECK:STDOUT: %.1: type = interface_type @HasF [template]
|
|
// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic]
|
|
// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template]
|
|
// CHECK:STDOUT: %.2: type = tuple_type () [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, @HasF.%F.decl [template]
|
|
// CHECK:STDOUT: %C: type = class_type @C [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: %G.type: type = fn_type @G [template]
|
|
// CHECK:STDOUT: %G: %G.type = 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: 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: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
|
// CHECK:STDOUT: .Core = imports.%Core
|
|
// CHECK:STDOUT: .HasF = %HasF.decl
|
|
// CHECK:STDOUT: .C = %C.decl
|
|
// CHECK:STDOUT: .G = %G.decl
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %Core.import = import Core
|
|
// CHECK:STDOUT: %HasF.decl: type = interface_decl @HasF [template = constants.%.1] {}
|
|
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {}
|
|
// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] {
|
|
// CHECK:STDOUT: %C.ref: type = name_ref C, %C.decl [template = constants.%C]
|
|
// CHECK:STDOUT: %c.loc21_6.1: %C = param c, runtime_param0
|
|
// CHECK:STDOUT: @G.%c: %C = bind_name c, %c.loc21_6.1
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: interface @HasF {
|
|
// 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: %.loc12: %.3 = assoc_entity element0, %F.decl [template = constants.%.4]
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: .Self = %Self
|
|
// CHECK:STDOUT: .F = %.loc12
|
|
// 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: %.loc16: <witness> = interface_witness (%F.decl) [template = constants.%.5]
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !members:
|
|
// CHECK:STDOUT: .F = %F.decl
|
|
// CHECK:STDOUT: witness = %.loc16
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: class @C {
|
|
// CHECK:STDOUT: impl_decl @impl {
|
|
// CHECK:STDOUT: %HasF.ref: type = name_ref HasF, file.%HasF.decl [template = constants.%.1]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %.loc19: <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: generic fn @F.1(@HasF.%Self: %.1) {
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn();
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @F.2() {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: return
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @G(%c: %C) {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C]
|
|
// CHECK:STDOUT: %F.ref.loc22: %.3 = name_ref F, @HasF.%.loc12 [template = constants.%.4]
|
|
// CHECK:STDOUT: %.loc22: %F.type.1 = interface_witness_access @impl.%.loc16, element0 [template = constants.%F.2]
|
|
// CHECK:STDOUT: %F.call.loc22: init %.2 = call %.loc22()
|
|
// CHECK:STDOUT: %c.ref: %C = name_ref c, %c
|
|
// CHECK:STDOUT: %F.ref.loc23: %.3 = name_ref F, @HasF.%.loc12 [template = constants.%.4]
|
|
// CHECK:STDOUT: %.loc23: %F.type.1 = interface_witness_access @impl.%.loc16, element0 [template = constants.%F.2]
|
|
// CHECK:STDOUT: %F.call.loc23: init %.2 = call %.loc23()
|
|
// CHECK:STDOUT: return
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: specific @F.1(constants.%Self) {}
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: specific @F.1(constants.%C) {}
|
|
// CHECK:STDOUT:
|