Files
carbon-lang/toolchain/check/testdata/operators/overloaded/bit_complement.carbon
T
Richard Smith 3c8fc714a8 Import support for generics and specifics (#4179)
Import generics and specifics when they are referenced by imported
entities.

When importing a generic, we import the symbolic constants required by
its eval block, and then rebuild the eval block itself given the list of
constants it needs to compute. This is likely a bit less efficient than
directly importing the contents of the eval block, but avoids needing to
either extend the importer code to be able to import the instructions
that can appear in the eval block or extend the evaluator to cope with
instructions from a different `SemIR::File`.

Importing a symbolic constant is unaffected, and does not yet preserve
the associated generic and index within that generic, so uses of a
generic from an imported IR still don't pick up values from the
specific, but the improved functionality can be seen in the changes to
the SemIR in the testcases.
2024-07-31 23:53:14 +00:00

139 lines
6.7 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/operators/overloaded/bit_complement.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/operators/overloaded/bit_complement.carbon
// This file was generated from unary_op.carbon.tmpl. Run make_tests.sh to regenerate.
package User;
class C {};
impl C as Core.BitComplement {
fn Op[self: C]() -> C {
return {};
}
}
fn TestOp(a: C) -> C {
return ^a;
}
// CHECK:STDOUT: --- bit_complement.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: %.2: type = interface_type @BitComplement [template]
// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic]
// CHECK:STDOUT: %Op.type.1: type = fn_type @Op.1 [template]
// CHECK:STDOUT: %.3: type = tuple_type () [template]
// CHECK:STDOUT: %Op.1: %Op.type.1 = struct_value () [template]
// CHECK:STDOUT: %Op.type.2: type = fn_type @Op.2 [template]
// CHECK:STDOUT: %Op.2: %Op.type.2 = struct_value () [template]
// CHECK:STDOUT: %.4: <witness> = interface_witness (%Op.1) [template]
// CHECK:STDOUT: %.5: type = ptr_type %.1 [template]
// CHECK:STDOUT: %struct: %C = struct_value () [template]
// CHECK:STDOUT: %TestOp.type: type = fn_type @TestOp [template]
// CHECK:STDOUT: %TestOp: %TestOp.type = struct_value () [template]
// CHECK:STDOUT: %.6: type = assoc_entity_type @BitComplement, %Op.type.2 [template]
// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.5 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .BitComplement = %import_ref.1
// 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/bitwise
// CHECK:STDOUT: import Core//prelude/operators/comparison
// CHECK:STDOUT: import Core//prelude/types/bool
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref Core//prelude/operators/bitwise, inst+1, loaded [template = constants.%.2]
// CHECK:STDOUT: %import_ref.2 = import_ref Core//prelude/operators/bitwise, inst+3, unloaded
// CHECK:STDOUT: %import_ref.3: %.6 = import_ref Core//prelude/operators/bitwise, inst+20, loaded [template = constants.%.7]
// CHECK:STDOUT: %import_ref.4: %Op.type.2 = import_ref Core//prelude/operators/bitwise, inst+14, loaded [template = constants.%Op.2]
// CHECK:STDOUT: %import_ref.5 = import_ref Core//prelude/operators/bitwise, inst+14, unloaded
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .C = %C.decl
// CHECK:STDOUT: .TestOp = %TestOp.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {}
// CHECK:STDOUT: impl_decl @impl {
// CHECK:STDOUT: %C.ref.loc17: type = name_ref C, %C.decl [template = constants.%C]
// CHECK:STDOUT: %Core.ref: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
// CHECK:STDOUT: %BitComplement.ref: type = name_ref BitComplement, imports.%import_ref.1 [template = constants.%.2]
// CHECK:STDOUT: }
// CHECK:STDOUT: %TestOp.decl: %TestOp.type = fn_decl @TestOp [template = constants.%TestOp] {
// CHECK:STDOUT: %C.ref.loc23_14: type = name_ref C, %C.decl [template = constants.%C]
// CHECK:STDOUT: %a.loc23_11.1: %C = param a
// CHECK:STDOUT: @TestOp.%a: %C = bind_name a, %a.loc23_11.1
// CHECK:STDOUT: %C.ref.loc23_20: type = name_ref C, %C.decl [template = constants.%C]
// CHECK:STDOUT: @TestOp.%return: ref %C = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @BitComplement {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = imports.%import_ref.2
// CHECK:STDOUT: .Op = imports.%import_ref.3
// CHECK:STDOUT: witness = (imports.%import_ref.4)
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: impl @impl: %C as %.2 {
// CHECK:STDOUT: %Op.decl: %Op.type.1 = fn_decl @Op.1 [template = constants.%Op.1] {
// CHECK:STDOUT: %C.ref.loc18_15: type = name_ref C, file.%C.decl [template = constants.%C]
// CHECK:STDOUT: %self.loc18_9.1: %C = param self
// CHECK:STDOUT: %self.loc18_9.2: %C = bind_name self, %self.loc18_9.1
// CHECK:STDOUT: %C.ref.loc18_23: type = name_ref C, file.%C.decl [template = constants.%C]
// CHECK:STDOUT: %return.var: ref %C = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %.1: <witness> = interface_witness (%Op.decl) [template = constants.%.4]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Op = %Op.decl
// CHECK:STDOUT: witness = %.1
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%C
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Op.1[@impl.%self.loc18_9.2: %C]() -> @impl.%return.var: %C {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc19_13.1: %.1 = struct_literal ()
// CHECK:STDOUT: %.loc19_13.2: init %C = class_init (), @impl.%return.var [template = constants.%struct]
// CHECK:STDOUT: %.loc19_14: init %C = converted %.loc19_13.1, %.loc19_13.2 [template = constants.%struct]
// CHECK:STDOUT: return %.loc19_14 to @impl.%return.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @Op.2(constants.%Self: %.2) {
// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%self: %Self]() -> %Self;
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @TestOp(%a: %C) -> %return: %C {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %a.ref: %C = name_ref a, %a
// CHECK:STDOUT: %.1: %Op.type.2 = interface_witness_access @impl.%.1, element0 [template = constants.%Op.1]
// CHECK:STDOUT: %.loc24: <bound method> = bound_method %a.ref, %.1
// CHECK:STDOUT: %.loc23: ref %C = splice_block %return {}
// CHECK:STDOUT: %Op.call: init %C = call %.loc24(%a.ref) to %.loc23
// CHECK:STDOUT: return %Op.call to %return
// CHECK:STDOUT: }
// CHECK:STDOUT: