Skip to content

Commit ba8ed99

Browse files
authored
Add failing tests for exposing the value of .Self through an interface (#5957)
We test using .Self in a generic parameter of an interface and as the value of an associated constant.
1 parent 7c13bdd commit ba8ed99

File tree

3 files changed

+750
-0
lines changed

3 files changed

+750
-0
lines changed

toolchain/check/testdata/facet/access.carbon

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,207 @@ fn UseIndirect[T:! I](x: T) -> T {
8080
//@dump-sem-ir-end
8181
}
8282

83+
// --- fail_todo_convert_from_period_self_to_full_facet_value.carbon
84+
library "[[@TEST_NAME]]";
85+
86+
interface I {
87+
let I1:! type;
88+
}
89+
90+
fn F(U:! I where .I1 = .Self) {
91+
// CHECK:STDERR: fail_todo_convert_from_period_self_to_full_facet_value.carbon:[[@LINE+4]]:3: error: cannot convert type `U` that implements `I where .(I.I1) = .Self` into type implementing `I where .(I.I1) = U` [ConversionFailureFacetToFacet]
92+
// CHECK:STDERR: U as (I where .I1 = U);
93+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
94+
// CHECK:STDERR:
95+
U as (I where .I1 = U);
96+
// CHECK:STDERR: fail_todo_convert_from_period_self_to_full_facet_value.carbon:[[@LINE+4]]:3: error: cannot convert type `U` that implements `I where .(I.I1) = .Self` into type implementing `I where .(I.I1) = U` [ConversionFailureFacetToFacet]
97+
// CHECK:STDERR: (U as type) as (I where .I1 = U);
98+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99+
// CHECK:STDERR:
100+
(U as type) as (I where .I1 = U);
101+
}
102+
103+
// --- convert_to_period_self.carbon
104+
library "[[@TEST_NAME]]";
105+
106+
interface I {
107+
let I1:! type;
108+
let I2:! type;
109+
}
110+
111+
fn F(U:! I where .I1 = .Self and .I2 = ()) {
112+
U as (I where .I1 = .Self);
113+
(U as type) as (I where .I1 = .Self);
114+
}
115+
116+
// --- fail_todo_access_through_call_once.carbon
117+
library "[[@TEST_NAME]]";
118+
119+
// TODO: Merge this test with the one below once they both work.
120+
121+
interface I {
122+
let X:! type;
123+
fn G() -> X*;
124+
}
125+
126+
fn F2[U:! I](V: U*) {}
127+
128+
fn F(U:! I where .X = .Self, V: U) {
129+
// The returned value of `G` type `U` which has access to the methods of `I`.
130+
U.G()->G();
131+
// CHECK:STDERR: fail_todo_access_through_call_once.carbon:[[@LINE+4]]:3: error: type `type` does not support qualified expressions [QualifiedExprUnsupported]
132+
// CHECK:STDERR: (U as type).G()->G();
133+
// CHECK:STDERR: ^~~~~~~~~~~~~
134+
// CHECK:STDERR:
135+
(U as type).G()->G();
136+
137+
// The returned value of type `U` can be used as a value of type `U`.
138+
F2(U.G());
139+
}
140+
141+
// --- fail_todo_access_through_call.carbon
142+
library "[[@TEST_NAME]]";
143+
144+
interface I {
145+
let X:! type;
146+
fn G() -> X*;
147+
}
148+
149+
fn F2[U:! I](V: U*) {}
150+
fn F3[U:! I where .X = .Self](V: U*) {}
151+
152+
fn F(U:! I where .X = .Self, V: U*) {
153+
// The returned value of `G` type `U` which has access to the methods of `I`.
154+
//
155+
// TODO: These should work.
156+
// - The first `.` is on a NameRef of type FacetType for `I where .X = .Self`.
157+
// - This finds `G` through the FacetType.
158+
// - The second `.` is on a Call of type FacetAccessType into `BindSymbolicName` with type FacetType for `I`.
159+
// - This finds `G` through the FacetType (impl lookup strips off FacetAccessType).
160+
// - The third `.` is on a Call of type FacetAccessType into `ImplWitnessAccess` of `I.X` into `LookupImplWitness`, which has type `type`
161+
// - Can't make calls on an `ImplWitnessAccess`.
162+
// - We could expect that the constant value of the `ImplWitnessAccess` would
163+
// be the same type that we got for the second lookup.
164+
// CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+4]]:3: error: type `.(I.X)` does not support qualified expressions [QualifiedExprUnsupported]
165+
// CHECK:STDERR: U.G()->G()->G();
166+
// CHECK:STDERR: ^~~~~~~~~~~~~
167+
// CHECK:STDERR:
168+
U.G()->G()->G();
169+
// CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+4]]:3: error: type `type` does not support qualified expressions [QualifiedExprUnsupported]
170+
// CHECK:STDERR: (U as type).G()->G()->G();
171+
// CHECK:STDERR: ^~~~~~~~~~~~~
172+
// CHECK:STDERR:
173+
(U as type).G()->G()->G();
174+
175+
// The returned value of type `U` can be used as a value of type `U`.
176+
//
177+
// TODO: This should work.
178+
// CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+4]]:6: error: type `.(I.X)` does not support qualified expressions [QualifiedExprUnsupported]
179+
// CHECK:STDERR: F2(U.G()->G()->G());
180+
// CHECK:STDERR: ^~~~~~~~~~~~~
181+
// CHECK:STDERR:
182+
F2(U.G()->G()->G());
183+
184+
// The constraints in the type `U` are preserved.
185+
//
186+
// TODO: These should work.
187+
// CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+7]]:3: error: cannot convert type `.Self` that implements `I` into type implementing `I where .(I.X) = .Self` [ConversionFailureFacetToFacet]
188+
// CHECK:STDERR: F3(U.G());
189+
// CHECK:STDERR: ^~~~~~~~~
190+
// CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE-40]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
191+
// CHECK:STDERR: fn F3[U:! I where .X = .Self](V: U*) {}
192+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
193+
// CHECK:STDERR:
194+
F3(U.G());
195+
// CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+4]]:6: error: type `.(I.X)` does not support qualified expressions [QualifiedExprUnsupported]
196+
// CHECK:STDERR: F3(U.G()->G()->G());
197+
// CHECK:STDERR: ^~~~~~~~~~~~~
198+
// CHECK:STDERR:
199+
F3(U.G()->G()->G());
200+
}
201+
202+
// --- fail_todo_compound_access_through_call.carbon
203+
library "[[@TEST_NAME]]";
204+
205+
interface I {
206+
let X:! type;
207+
fn G() -> X;
208+
}
209+
210+
fn F(U:! I where .X = .Self) {
211+
// Compound member lookup through a non-type value is possible for methods
212+
// which take a `self` parameter. But it's not possible for methods without
213+
// `self`. For those you need to go directly throug the type.
214+
// See: https://github.com/carbon-language/carbon-lang/issues/6025
215+
216+
// TODO: This step should work.
217+
//
218+
// CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+7]]:14: error: cannot implicitly convert expression of type `.Self` to `U` [ConversionFailure]
219+
// CHECK:STDERR: let u: U = U.(I.G)();
220+
// CHECK:STDERR: ^~~~~~~~~
221+
// CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+4]]:14: note: type `.Self` does not implement interface `Core.ImplicitAs(U)` [MissingImplInMemberAccessNote]
222+
// CHECK:STDERR: let u: U = U.(I.G)();
223+
// CHECK:STDERR: ^~~~~~~~~
224+
// CHECK:STDERR:
225+
let u: U = U.(I.G)();
226+
// `u` is a non-type value. Can call methods with `self` through compound
227+
// member lookup, but can't call methods without `self`. See the
228+
// `compound_access_through_call_with_self_param.carbon` test for the former.
229+
//
230+
// CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+7]]:3: error: cannot implicitly convert non-type value of type `U` into type implementing `I` [ConversionFailureNonTypeToFacet]
231+
// CHECK:STDERR: u.(I.G)();
232+
// CHECK:STDERR: ^~~~~~~
233+
// CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+4]]:3: note: type `U` does not implement interface `Core.ImplicitAs(I)` [MissingImplInMemberAccessNote]
234+
// CHECK:STDERR: u.(I.G)();
235+
// CHECK:STDERR: ^~~~~~~
236+
// CHECK:STDERR:
237+
u.(I.G)();
238+
239+
// This is the same as the above, since G() returns a non-type value of type
240+
// `U`.
241+
//
242+
// CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+7]]:3: error: cannot implicitly convert non-type value of type `.Self` into type implementing `I` [ConversionFailureNonTypeToFacet]
243+
// CHECK:STDERR: U.(I.G)().(I.G)();
244+
// CHECK:STDERR: ^~~~~~~~~~~~~~~
245+
// CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+4]]:3: note: type `.Self` does not implement interface `Core.ImplicitAs(I)` [MissingImplInMemberAccessNote]
246+
// CHECK:STDERR: U.(I.G)().(I.G)();
247+
// CHECK:STDERR: ^~~~~~~~~~~~~~~
248+
// CHECK:STDERR:
249+
U.(I.G)().(I.G)();
250+
}
251+
252+
// --- fail_todo_compound_access_through_call_with_self_param.carbon
253+
library "[[@TEST_NAME]]";
254+
255+
interface I {
256+
let X:! type;
257+
fn G[self: Self]() -> X*;
258+
}
259+
260+
fn F(U:! I where .X = .Self, v: U) {
261+
// Compound member lookup through a non-type value is possible for methods
262+
// which take a `self` parameter.
263+
264+
// TODO: This should all work.
265+
266+
// CHECK:STDERR: fail_todo_compound_access_through_call_with_self_param.carbon:[[@LINE+7]]:15: error: cannot implicitly convert expression of type `.Self*` to `U*` [ConversionFailure]
267+
// CHECK:STDERR: let u: U* = v.(I.G)();
268+
// CHECK:STDERR: ^~~~~~~~~
269+
// CHECK:STDERR: fail_todo_compound_access_through_call_with_self_param.carbon:[[@LINE+4]]:15: note: type `.Self*` does not implement interface `Core.ImplicitAs(U*)` [MissingImplInMemberAccessNote]
270+
// CHECK:STDERR: let u: U* = v.(I.G)();
271+
// CHECK:STDERR: ^~~~~~~~~
272+
// CHECK:STDERR:
273+
let u: U* = v.(I.G)();
274+
// `u` is a non-type value. Can call methods with `self` through compound
275+
// member lookup, but can't call methods without `self`. See the
276+
// `compound_access_through_call.carbon` test for the latter.
277+
u->(I.G)();
278+
279+
// This is the same as the above, since G() returns a non-type value of type
280+
// `U`. This works because G has a `self` parameter.
281+
v.(I.G)()->(I.G)();
282+
}
283+
83284
// --- fail_non_const_associated.carbon
84285
library "[[@TEST_NAME]]";
85286

0 commit comments

Comments
 (0)