From 3a7b49efaad41d9fb2c289864452d86f0b031827 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 15 Jun 2026 10:27:32 -0400 Subject: [PATCH] Add some more test coverage of designators (#7347) - A test showing we need to search facets in the specific interface of an access to find a witness - A test using a ` impls ...` constraint from earlier in the same facet type - Some tests to show a rewrite constraint from earlier in the same facet type is not incorrectly used when it's applied to a different facet - A test of a facet type with a rewrite as the RHS of another rewrite, and the rewrite there should not leak or access things from the outer facet type --- toolchain/check/testdata/facet/access.carbon | 22 +++++ .../check/testdata/facet/early_impls.carbon | 22 +++++ .../testdata/facet/early_rewrites.carbon | 82 ++++++++++++++++++- 3 files changed, 124 insertions(+), 2 deletions(-) diff --git a/toolchain/check/testdata/facet/access.carbon b/toolchain/check/testdata/facet/access.carbon index 9432700f8cd0..5360f8435f55 100644 --- a/toolchain/check/testdata/facet/access.carbon +++ b/toolchain/check/testdata/facet/access.carbon @@ -416,6 +416,28 @@ fn F(U:! W, V:! Z(.Self) where .Z1 impls (Y where .Y1 impls (X where .X1 = U))) V.(Z(V).Z1).(Y.Y1).(X.X1) as W; } + // --- fail_todo_find_access_value_in_facet_from_specific_interface.carbon +library "[[@TEST_NAME]]"; + +interface Z {} +interface Y(T:! type) { + let Y1:! type; +} +class C; + +// TODO: We need to look in `T` for the rewrite in the access of `(C as +// Y(T)).Y1` but we currently only look in `C`. See the TODO in +// `TryFindValueInRewriteConstraints()`. +fn F(T:! Z where C impls (Y(.Self) where .Y1 = {})) -> C.(Y(T).Y1) { + // CHECK:STDERR: fail_todo_find_access_value_in_facet_from_specific_interface.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `{}` to `C.(Y(T).Y1)` [ConversionFailure] + // CHECK:STDERR: return {}; + // CHECK:STDERR: ^~~~~~~~~~ + // CHECK:STDERR: fail_todo_find_access_value_in_facet_from_specific_interface.carbon:[[@LINE+4]]:3: note: type `{}` does not implement interface `Core.ImplicitAs(C.(Y(T).Y1))` [MissingImplInMemberAccessInContext] + // CHECK:STDERR: return {}; + // CHECK:STDERR: ^~~~~~~~~~ + // CHECK:STDERR: + return {}; +} // CHECK:STDOUT: --- access_assoc_fn.carbon // CHECK:STDOUT: diff --git a/toolchain/check/testdata/facet/early_impls.carbon b/toolchain/check/testdata/facet/early_impls.carbon index 6de135796aa5..06c20a9fd8a1 100644 --- a/toolchain/check/testdata/facet/early_impls.carbon +++ b/toolchain/check/testdata/facet/early_impls.carbon @@ -243,3 +243,25 @@ constraint N(V:! type) { // CHECK:STDERR: ^~~~~~~~~~~~~~~ // CHECK:STDERR: fn F(_:! Z(.Self) where C impls N(.Z1) and .Z2 = (.Z1 as Y(.Self))) {} + +// --- early_type_impls_nested_self_impls.carbon +library "[[@TEST_NAME]]"; + +interface Z { + let Z1:! type; +} +interface Y { + let Y1:! type; +} +interface X {} + +class C(T:! type); +class D(T:! X); + +// TODO: Does the `.Y1 impls X` contain an ambiguous `.Self`? See +// https://github.com/carbon-language/carbon-lang/issues/7138. + +// A lookup of `C(V).(Y.Y1) as X` requires us to see that the `.Y1 impls X` +// constraint is visible through the `C(.Self) impls (Y...)` constraint and that +// `C(.Self)` is used as the implied `.Self` in `.Y1 impls X`. +fn F(unused V:! Z where C(.Self) impls (Y where .Y1 impls X) and .Z1 = D(C(.Self).(Y.Y1))) {} diff --git a/toolchain/check/testdata/facet/early_rewrites.carbon b/toolchain/check/testdata/facet/early_rewrites.carbon index 5ba81407c248..5b154cb8ebeb 100644 --- a/toolchain/check/testdata/facet/early_rewrites.carbon +++ b/toolchain/check/testdata/facet/early_rewrites.carbon @@ -395,6 +395,84 @@ interface Y { let Y1:! type; } -fn F(T:! Z where .Z1 impls (Y where .Y1 = ()) and .Z2 = .Z1.(Y.Y1)) -> T.Z2 { - return (); +interface Tuple {} +impl () as Tuple {} +class C(U:! Tuple); + +fn F(unused T:! Z where .Z1 impls (Y where .Y1 = ()) and .Z2 = C(.Z1.(Y.Y1))) {} + +// --- fail_early_rewrite_correct_interface_wrong_self_access_rewrite_in_period_self.carbon +library "[[@TEST_NAME]]"; + +interface Z { + let Z1:! type; + let Z2:! type; +} +interface Y { + let Y1:! type; +} + +interface Tuple {} +impl () as Tuple {} +class C(U:! Tuple); + +// This should fail: `T.(Y.Y1)` is rewritten to be `()` but `T.(Z.Z1).(Y.Y1)` +// is used in the argument to `C`. +// +// CHECK:STDERR: fail_early_rewrite_correct_interface_wrong_self_access_rewrite_in_period_self.carbon:[[@LINE+7]]:82: error: cannot convert type `.(Z.Z1).(Y.Y1)` into type implementing `Tuple` [ConversionFailureTypeToFacet] +// CHECK:STDERR: fn F(unused T:! Z where .Self impls (Y where .Y1 = ()) and .Z1 impls Y and .Z2 = C(.Z1.(Y.Y1))) {} +// CHECK:STDERR: ^~~~~~~~~~~~~ +// CHECK:STDERR: fail_early_rewrite_correct_interface_wrong_self_access_rewrite_in_period_self.carbon:[[@LINE-8]]:9: note: initializing generic parameter `U` declared here [InitializingGenericParam] +// CHECK:STDERR: class C(U:! Tuple); +// CHECK:STDERR: ^~~~~~~~~ +// CHECK:STDERR: +fn F(unused T:! Z where .Self impls (Y where .Y1 = ()) and .Z1 impls Y and .Z2 = C(.Z1.(Y.Y1))) {} + +// --- fail_early_rewrite_correct_interface_wrong_self_access_rewrite_in_associated_constant.carbon +library "[[@TEST_NAME]]"; + +interface Z { + let Z1:! type; + let Z2:! type; +} +interface Y { + let Y1:! type; +} + +interface Tuple {} +impl () as Tuple {} +class C(U:! Tuple); + +// This should fail: `T.(Z.Z1).(Y.Y1)` is rewritten to be `()` but `T.(Y.Y1)` is used +// in the argument to `C`. +// +// CHECK:STDERR: fail_early_rewrite_correct_interface_wrong_self_access_rewrite_in_associated_constant.carbon:[[@LINE+4]]:84: error: name `Self` not found [NameNotFound] +// CHECK:STDERR: fn G(unused T:! Z where .Z1 impls (Y where .Y1 = ()) and .Self impls Y and .Z2 = C(Self.(Y.Y1))) {} +// CHECK:STDERR: ^~~~ +// CHECK:STDERR: +fn G(unused T:! Z where .Z1 impls (Y where .Y1 = ()) and .Self impls Y and .Z2 = C(Self.(Y.Y1))) {} + +// --- fail_nested_facet_type_in_rewrite_does_not_use_rewrite_from_outside.carbon +library "[[@TEST_NAME]]"; + +interface Z { + let X:! type; + let Y:! type; +} + +// TODO: Does the `.X = .Y` contain an ambiguous `.Self` in `.Y`? See +// https://github.com/carbon-language/carbon-lang/issues/7138. + +fn F(T:! Z where .Y = {} and .X = (Z where .X = .Y), U:! T.X) -> U.(Z.X) { + // This should fail: `U:! T.X` contains a rewrite `.X = .Y` in its type, but + // the value of `U.(Z.Y)` is not known. Only `T.(Z.Y)` is rewritten to `{}`. + // + // CHECK:STDERR: fail_nested_facet_type_in_rewrite_does_not_use_rewrite_from_outside.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `{}` to `U.(Z.Y)` [ConversionFailure] + // CHECK:STDERR: return {}; + // CHECK:STDERR: ^~~~~~~~~~ + // CHECK:STDERR: fail_nested_facet_type_in_rewrite_does_not_use_rewrite_from_outside.carbon:[[@LINE+4]]:3: note: type `{}` does not implement interface `Core.ImplicitAs(U.(Z.Y))` [MissingImplInMemberAccessInContext] + // CHECK:STDERR: return {}; + // CHECK:STDERR: ^~~~~~~~~~ + // CHECK:STDERR: + return {}; }