Skip to content
184 changes: 184 additions & 0 deletions toolchain/check/testdata/facet/access.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,190 @@ fn UseIndirect[T:! I](x: T) -> T {
//@dump-sem-ir-end
}

// --- fail_todo_convert_from_period_self_to_full_facet_value.carbon
library "[[@TEST_NAME]]";

interface I {
let I1:! type;
}

fn F(U:! I where .I1 = .Self) {
// 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]
// CHECK:STDERR: U as (I where .I1 = U);
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
U as (I where .I1 = U);
// CHECK:STDERR: fail_todo_convert_from_period_self_to_full_facet_value.carbon:[[@LINE+4]]:3: error: cannot convert type `U` into type implementing `I where .(I.I1) = U` [ConversionFailureTypeToFacet]
// CHECK:STDERR: (U as type) as (I where .I1 = U);
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
(U as type) as (I where .I1 = U);
}

// --- access_through_call_once.carbon
library "[[@TEST_NAME]]";

// TODO: Merge this test with the one below once it works.

interface I {
let X:! type;
fn G() -> X;
}

fn F2[U:! I](V: U) {}

fn F(U:! I where .X = .Self, V: U) {
// The returned value of `G` type `U` which has access to the methods of `I`.
U.G().G();
(U as type).G().G();

// The returned value of type `U` can be used as a value of type `U`.
F2(U.G());
}

// --- fail_todo_access_through_call.carbon
library "[[@TEST_NAME]]";

interface I {
let X:! type;
fn G() -> X;
}

fn F2[U:! I](V: U) {}
fn F3[U:! I where .X = .Self](V: U) {}

fn F(U:! I where .X = .Self, V: U) {
// The returned value of `G` type `U` which has access to the methods of `I`.
//
// TODO: These should work.
// - The first `.` is on a NameRef of type FacetType for `I where .X = .Self`.
// - This finds `G` through the FacetType.
// - The second `.` is on a Call of type FacetAccessType into `BindSymbolicName` with type FacetType for `I`.
// - This finds `G` through the FacetType (impl lookup strips off FacetAccessType).
// - The third `.` is on a Call of type FacetAccessType into `ImplWitnessAccess` of `I.X` into `LookupImplWitness`, which has type `type`
// - Can't make calls on an `ImplWitnessAccess`.
// - We could expect that the constant value of the `ImplWitnessAccess` would
// be the same type that we got for the second lookup.
// CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+4]]:3: error: type `.(I.X)` does not support qualified expressions [QualifiedExprUnsupported]
// CHECK:STDERR: U.G().G().G();
// CHECK:STDERR: ^~~~~~~~~~~
// CHECK:STDERR:
U.G().G().G();
// CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+4]]:3: error: type `.(I.X)` does not support qualified expressions [QualifiedExprUnsupported]
// CHECK:STDERR: (U as type).G().G().G();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
(U as type).G().G().G();

// The returned value of type `U` can be used as a value of type `U`.
//
// TODO: This should work.
// CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+4]]:6: error: type `.(I.X)` does not support qualified expressions [QualifiedExprUnsupported]
// CHECK:STDERR: F2(U.G().G().G());
// CHECK:STDERR: ^~~~~~~~~~~
// CHECK:STDERR:
F2(U.G().G().G());

// The constraints in the type `U` are preserved.
//
// TODO: These should work.
// 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]
// CHECK:STDERR: F3(U.G());
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE-40]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
// CHECK:STDERR: fn F3[U:! I where .X = .Self](V: U) {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
F3(U.G());
// CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+4]]:6: error: type `.(I.X)` does not support qualified expressions [QualifiedExprUnsupported]
// CHECK:STDERR: F3(U.G().G().G());
// CHECK:STDERR: ^~~~~~~~~~~
// CHECK:STDERR:
F3(U.G().G().G());
}

// --- fail_todo_compound_access_through_call.carbon
library "[[@TEST_NAME]]";

interface I {
let X:! type;
fn G() -> X;
}

fn F(U:! I where .X = .Self) {
// Compound member lookup through a non-type value is possible for methods
// which take a `self` parameter. But it's not possible for methods without
// `self`. For those you need to go directly throug the type.
// See: https://github.com/carbon-language/carbon-lang/issues/6025

// TODO: This step should work.
//
// CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+7]]:14: error: cannot implicitly convert expression of type `.Self` to `U` [ConversionFailure]
// CHECK:STDERR: let u: U = U.(I.G)();
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+4]]:14: note: type `.Self` does not implement interface `Core.ImplicitAs(U)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: let u: U = U.(I.G)();
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR:
let u: U = U.(I.G)();
// `u` is a non-type value. Can call methods with `self` through compound
// member lookup, but can't call methods without `self`. See the
// `compound_access_through_call_with_self_param.carbon` test for the former.
//
// 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]
// CHECK:STDERR: u.(I.G)();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+4]]:3: note: type `U` does not implement interface `Core.ImplicitAs(I)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: u.(I.G)();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
u.(I.G)();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to split this and the next line out from the file that contains the previous let declaration, so that we don't have a mixture of "should not fail but does" and "should fail and does" in the same file?


// This is the same as the above, since G() returns a non-type value of type
// `U`.
//
// 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]
// CHECK:STDERR: U.(I.G)().(I.G)();
// CHECK:STDERR: ^~~~~~~~~~~~~~~
// CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+4]]:3: note: type `.Self` does not implement interface `Core.ImplicitAs(I)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: U.(I.G)().(I.G)();
// CHECK:STDERR: ^~~~~~~~~~~~~~~
// CHECK:STDERR:
U.(I.G)().(I.G)();
}

// --- fail_todo_compound_access_through_call_with_self_param.carbon
library "[[@TEST_NAME]]";

interface I {
let X:! type;
fn G[self: Self]() -> X;
}

fn F(U:! I where .X = .Self, v: U) {
// Compound member lookup through a non-type value is possible for methods
// which take a `self` parameter.

// TODO: This should all work.

// CHECK:STDERR: fail_todo_compound_access_through_call_with_self_param.carbon:[[@LINE+7]]:14: error: cannot implicitly convert expression of type `.Self` to `U` [ConversionFailure]
// CHECK:STDERR: let u: U = v.(I.G)();
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_todo_compound_access_through_call_with_self_param.carbon:[[@LINE+4]]:14: note: type `.Self` does not implement interface `Core.ImplicitAs(U)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: let u: U = v.(I.G)();
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR:
let u: U = v.(I.G)();
// `u` is a non-type value. Can call methods with `self` through compound
// member lookup, but can't call methods without `self`. See the
// `compound_access_through_call.carbon` test for the latter.
u.(I.G)();

// This is the same as the above, since G() returns a non-type value of type
// `U`. This works because G has a `self` parameter.
v.(I.G)().(I.G)();
}

// --- fail_non_const_associated.carbon
library "[[@TEST_NAME]]";

Expand Down
Loading
Loading