|
| 1 | +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM |
| 2 | +// Exceptions. See /LICENSE for license information. |
| 3 | +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 4 | +// |
| 5 | +// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon |
| 6 | +// |
| 7 | +// This test is producing a case where interface ordering will differ between |
| 8 | +// interfaces.carbon and use.carbon, testing that witnesses are maintained in a |
| 9 | +// canonical order. This checks a regression where the imported ordering would |
| 10 | +// be incorrectly used, resulting in witnesses getting swapped and an opaque |
| 11 | +// error for the `SimpleOp` lookup because `Empty`'s table is empty. |
| 12 | +// |
| 13 | +// The IR is generally not significant, but the important difference is as |
| 14 | +// follows (if these become the same, it means the test is no longer effective): |
| 15 | +// |
| 16 | +// SET-CHECK-SUBSET |
| 17 | +// CHECK:STDOUT: --- interfaces.carbon |
| 18 | +// CHECK:STDOUT: %facet_type: type = facet_type <@SimpleOp & @Empty> [concrete] |
| 19 | +// CHECK:STDOUT: --- use.carbon |
| 20 | +// CHECK:STDOUT: %facet_type: type = facet_type <@Empty & @SimpleOp> [concrete] |
| 21 | +// |
| 22 | +// This check does not strictly exclude extra facet types, although that should |
| 23 | +// create different instruction names. We also anticipate diagnostics should be |
| 24 | +// produced if there's a significant error. |
| 25 | +// |
| 26 | +// NOAUTOUPDATE |
| 27 | +// TIP: To test this file alone, run: |
| 28 | +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/import_canonical_witnesses.carbon |
| 29 | +// TIP: To dump output, run: |
| 30 | +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/import_canonical_witnesses.carbon |
| 31 | + |
| 32 | + |
| 33 | +// --- interfaces.carbon |
| 34 | +//@include-in-dumps |
| 35 | +library "[[@TEST_NAME]]"; |
| 36 | + |
| 37 | +// An interface with a trivial function and blanket impl for pointers. |
| 38 | +interface SimpleOp { |
| 39 | + fn Op[self: Self](); |
| 40 | +} |
| 41 | + |
| 42 | +impl forall [T:! type] T as SimpleOp { |
| 43 | + fn Op[self: Self]() {} |
| 44 | +} |
| 45 | + |
| 46 | +// An empty interface with blanket impl for pointers. |
| 47 | +interface Empty {} |
| 48 | +impl forall [T:! type] T as Empty {} |
| 49 | + |
| 50 | +// Class with a use of `SimpleOp.Op`. |
| 51 | +class InterfaceWrap(T:! SimpleOp & Empty) { |
| 52 | + fn UseSimpleOp[self: Self](value:! T) { |
| 53 | + value.(SimpleOp.Op)(); |
| 54 | + } |
| 55 | +} |
| 56 | + |
| 57 | +// Interface combining the above for an indirect `SimpleOp` use through `C`, |
| 58 | +// particularly use an associated constant. |
| 59 | +interface CombinedFacet { |
| 60 | + let T:! SimpleOp & Empty; |
| 61 | + fn GetInterfaceWrap[self: Self]() -> InterfaceWrap(T); |
| 62 | +} |
| 63 | + |
| 64 | +// A wrapper providing `CombinedFacet`. |
| 65 | +class TypeWrap(T:! type) { |
| 66 | + impl as CombinedFacet where .T = T { |
| 67 | + fn GetInterfaceWrap[self: Self]() -> InterfaceWrap(T) { |
| 68 | + return {}; |
| 69 | + } |
| 70 | + } |
| 71 | +} |
| 72 | + |
| 73 | +// --- use.carbon |
| 74 | +//@include-in-dumps |
| 75 | +library "[[@TEST_NAME]]"; |
| 76 | +import library "interfaces"; |
| 77 | + |
| 78 | +class C {} |
| 79 | + |
| 80 | +fn F(t: TypeWrap(C), c:! C) { |
| 81 | + t.(CombinedFacet.GetInterfaceWrap)().UseSimpleOp(c); |
| 82 | +} |
0 commit comments