// 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 // // INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon // // AUTOUPDATE // TIP: To test this file alone, run: // TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/where_expr/dot_self_impls.carbon // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/where_expr/dot_self_impls.carbon // --- compound_member_access_through_where_self_impls.carbon library "[[@TEST_NAME]]"; interface I { fn FNonInstance(); fn FSelf[self: Self](); } interface J { fn GNonInstance(); fn GSelf[self: Self](); } fn INotJ[T:! I where .Self impls J](x: T) { // Can access members of `I` using either kind of member access. T.FNonInstance(); T.(I.FNonInstance)(); x.FNonInstance(); x.FSelf(); x.(I.FSelf)(); // Can still find members of `J` using compound member access, // even though they are not available via `T.GNonInstance` or // `x.GSelf`. T.(J.GNonInstance)(); x.(J.GSelf)(); } fn TypeNotJ[T:! type where .Self impls J](x: T) { T.(J.GNonInstance)(); x.(J.GSelf)(); } // --- no_name_conflict_with_where_self_impls.carbon library "[[@TEST_NAME]]"; interface I { fn F() -> (); } interface J { fn F() -> {}; } fn INotJ(T:! I where .Self impls J) { // Gets `T.(I.F)`. Doesn't consider `T.(J.F)`, so no ambiguity. let x: () = T.F(); } // --- fail_name_lookup_through_where_self_impls.carbon library "[[@TEST_NAME]]"; interface I { fn F(); } interface J { fn G(); } fn INotJ(T:! I where .Self impls J) { // CHECK:STDERR: fail_name_lookup_through_where_self_impls.carbon:[[@LINE+4]]:3: error: member name `G` not found in `I` [MemberNameNotFoundInInstScope] // CHECK:STDERR: T.G(); // CHECK:STDERR: ^~~ // CHECK:STDERR: T.G(); } // --- fail_name_lookup_with_type.carbon library "[[@TEST_NAME]]"; interface J { fn G(); } fn TypeNotJ(T:! type where .Self impls J) { // CHECK:STDERR: fail_name_lookup_with_type.carbon:[[@LINE+4]]:3: error: member name `G` not found [MemberNameNotFound] // CHECK:STDERR: T.G(); // CHECK:STDERR: ^~~ // CHECK:STDERR: T.G(); } // --- fail_facet_type_simple_member_access.carbon library "[[@TEST_NAME]]"; interface A {} interface B { fn Bfn(); } fn F(T:! A & B) { // CHECK:STDERR: fail_facet_type_simple_member_access.carbon:[[@LINE+4]]:6: error: member name `Bfn` not found in `A` [MemberNameNotFoundInInstScope] // CHECK:STDERR: T.((A where .Self impls B).Bfn)(); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: T.((A where .Self impls B).Bfn)(); // CHECK:STDERR: fail_facet_type_simple_member_access.carbon:[[@LINE+4]]:3: error: member name `Bfn` not found in `A` [MemberNameNotFoundInInstScope] // CHECK:STDERR: (A where .Self impls B).Bfn; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: (A where .Self impls B).Bfn; } // --- fail_name_lookup_instance.carbon library "[[@TEST_NAME]]"; interface I { fn FNonInstance(); fn FSelf[self: Self](); } interface J { fn GNonInstance(); fn GSelf[self: Self](); } fn INotJ[T:! I where .Self impls J](x: T) { // CHECK:STDERR: fail_name_lookup_instance.carbon:[[@LINE+4]]:3: error: member name `GNonInstance` not found in `I` [MemberNameNotFoundInInstScope] // CHECK:STDERR: x.GNonInstance(); // CHECK:STDERR: ^~~~~~~~~~~~~~ // CHECK:STDERR: x.GNonInstance(); // CHECK:STDERR: fail_name_lookup_instance.carbon:[[@LINE+4]]:3: error: member name `GSelf` not found in `I` [MemberNameNotFoundInInstScope] // CHECK:STDERR: x.GSelf(); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: x.GSelf(); } // --- compare_equal.carbon library "[[@TEST_NAME]]"; class WrapType(T:! type) {} fn AssertSame[T:! type](a: WrapType(T), b: WrapType(T)) {} fn Type(T:! type) -> WrapType(T) { return {}; } interface I; interface J; interface K; fn Test() { AssertSame(Type(I), Type(I where .Self impls I)); AssertSame(Type(I), Type(I where .Self impls I & I)); AssertSame(Type(I & J), Type(J & I where .Self impls I)); AssertSame(Type(I & J), Type(J & I where .Self impls J)); AssertSame(Type(I & J), Type(J & I where .Self impls I & J)); AssertSame(Type(I & J where .Self impls K), Type(J & I where .Self impls I & K)); AssertSame(Type(I & J where .Self impls K), Type(J & I where .Self impls J & K)); AssertSame(Type(I & J where .Self impls K), Type(J & I where .Self impls K & I & J)); AssertSame(Type(I where .Self impls J & K), Type(I where .Self impls K & I & J)); AssertSame(Type(I where .Self impls J & K), Type(I where .Self impls (J where .Self impls K))); AssertSame(Type(I where .Self impls J & K), Type(I where .Self impls (K where .Self impls J))); AssertSame(Type(I where .Self impls J & K), Type(I where .Self impls (type where .Self impls (J where .Self impls K)))); } interface I {} interface J {} interface K {} // --- compare_equal_with_associated_constant.carbon library "[[@TEST_NAME]]"; class WrapType(T:! type) {} fn AssertSame[T:! type](a: WrapType(T), b: WrapType(T)) {} fn Type(T:! type) -> WrapType(T) { return {}; } interface I { let A:! type; } interface J { let A:! type; } fn Test() { AssertSame(Type((I where .A = ()) & J), Type(I & J where .Self impls (I where .A = ()))); AssertSame(Type(I & (J where .A = {})), Type(I & J where .Self impls (J where .A = {}))); AssertSame(Type((I where .A = ()) & (J where .A = {})), Type(I & J where .Self impls (I where .A = ()) and .Self impls (J where .A = {}))); AssertSame(Type((I where .A = ()) & (J where .A = {})), Type(I & J where .Self impls (I where .A = ()) & (J where .A = {}))); } // --- fail_compare_not_equal.carbon library "[[@TEST_NAME]]"; class WrapType(T:! type) {} fn Same[T:! type](a: WrapType(T), b: WrapType(T)) {} fn Type(T:! type) -> WrapType(T) { return {}; } interface I {} interface J {} fn Test() { // CHECK:STDERR: fail_compare_not_equal.carbon:[[@LINE+7]]:3: error: inconsistent deductions for value of generic parameter `T` [DeductionInconsistent] // CHECK:STDERR: Same(Type(I where .Self impls J), Type(J where .Self impls I)); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: fail_compare_not_equal.carbon:[[@LINE-10]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere] // CHECK:STDERR: fn Same[T:! type](a: WrapType(T), b: WrapType(T)) {} // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: Same(Type(I where .Self impls J), Type(J where .Self impls I)); } // --- impl_as.carbon library "[[@TEST_NAME]]"; class C {} interface I {} interface J { let T:! type; } // Interfaces to the right of the `where` don't interfere with the // "can only impl a facet type with a single interface" rule. Only // the interface being implemented needs to have all of its // associated constants set impl {.a: C} as I where .Self impls J {} impl {.b: C} as J where .Self impls I and .T = () {} // Rewrite constraints can appear inside the `where .Self impls`. impl {.c: C} as J where .Self impls (I & J where .T = ()) {} // --- impl_with_rewrite_of_interface_not_being_implemented.carbon library "[[@TEST_NAME]]"; interface I { let A:! type; } interface J { let A:! type; } class C {} // Implementation of `C as J`. impl C as J where .A = {} {} // This is an implementation of `I` with `I.A = ()`. The requirement // that `C` also impls `J where .A = {}` is an additional constraint // that must be satisfied (and is satisfied by the impl above, though // that currently isn't checked), but doesn't affect `C as I`. impl C as I where .Self impls (J where .A = {} and .Self impls (I where .A = ())) {} let x: C.(I.A) = (); let y: C.(J.A) = {};