mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:40:12 +01:00
Forbid nested where inside a where expression (#7378)
This disallows building a facet type that contains another facet type with non-extend constraints in it. Which in turn prevents the possibility of introducing a different `.Self` into a facet type. Eval can still insert a facet type with non-extend constraints, as we only prevent it for `where` being written into the facet type. There is a TODO in handle_where.cpp for this and some tests in toolchain/check/testdata/facet/nested_facet_types_from_eval.carbon
This commit is contained in:
@@ -278,6 +278,8 @@ class Context {
|
||||
SemIR::ConstantId facet_type_const_id;
|
||||
};
|
||||
llvm::SmallVector<SelfImplsFacetType> impls;
|
||||
|
||||
SemIR::LocId loc_id;
|
||||
};
|
||||
|
||||
auto where_stack() -> llvm::SmallVector<WhereStackEntry>& {
|
||||
|
||||
@@ -3243,6 +3243,10 @@ auto TryEvalTypedInst<SemIR::WhereExpr>(EvalContext& eval_context,
|
||||
Phase phase = Phase::Concrete;
|
||||
SemIR::FacetTypeInfo info;
|
||||
|
||||
if (inst.type_id() == SemIR::ErrorInst::TypeId) {
|
||||
return SemIR::ErrorInst::ConstantId;
|
||||
}
|
||||
|
||||
// Note that these requirement instructions don't have a constant value. That
|
||||
// means we have to look for errors inside them, we can't just look to see if
|
||||
// their constant value is an error.
|
||||
|
||||
@@ -98,7 +98,7 @@ auto HandleParseNode(Context& context, Parse::WhereOperandId node_id) -> bool {
|
||||
|
||||
// Add a context stack for tracking constraints, that will be used to allow
|
||||
// later constraints to read from them eagerly.
|
||||
context.where_stack().emplace_back();
|
||||
context.where_stack().push_back({.loc_id = node_id});
|
||||
|
||||
// Make rewrite constraints from the self facet type available immediately to
|
||||
// expressions in rewrite constraints for this `where` expression.
|
||||
@@ -339,12 +339,6 @@ auto HandleParseNode(Context& context, Parse::RequirementImplsId node_id)
|
||||
// TODO: For things like `HashSet(.T) as type`, add an implied constraint
|
||||
// that `.T impls Hash`.
|
||||
|
||||
if (FindAndDiagnoseAmbiguousPeriodSelf(context, lhs_as_type.inst_id,
|
||||
rhs_id)) {
|
||||
rhs_as_type.type_id = SemIR::ErrorInst::TypeId;
|
||||
rhs_as_type.inst_id = SemIR::ErrorInst::TypeInstId;
|
||||
}
|
||||
|
||||
// Build up the list of arguments for the `WhereExpr` inst.
|
||||
context.args_type_info_stack().AddInstId(
|
||||
AddInstInNoBlock<SemIR::RequirementImpls>(
|
||||
@@ -387,6 +381,23 @@ auto HandleParseNode(Context& /*context*/, Parse::RequirementAndId /*node_id*/)
|
||||
return true;
|
||||
}
|
||||
|
||||
// There are two ways to nest `where` expressions, this diagnoses a `where`
|
||||
// expression inside the RHS of another `where` expression.
|
||||
//
|
||||
// Whereas it is valid to nest a `where` expression on the LHS of another
|
||||
// `where` expression.
|
||||
static auto DiagnoseNestedWhere(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::LocId outer_loc_id) -> void {
|
||||
CARBON_DIAGNOSTIC(
|
||||
NestedWhereInsideWhere, Error,
|
||||
"found `where` expression nested on the right-hand side of `where`");
|
||||
auto builder = context.emitter().Build(loc_id, NestedWhereInsideWhere);
|
||||
CARBON_DIAGNOSTIC(NestedWhereInsideWhereOuterNote, Note,
|
||||
"on right-hand side of `where` here");
|
||||
builder.Note(outer_loc_id, NestedWhereInsideWhereOuterNote);
|
||||
builder.Emit();
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::WhereExprId node_id) -> bool {
|
||||
context.where_stack().pop_back();
|
||||
// Remove `PeriodSelf` from name lookup, undoing the `Push` done for the
|
||||
@@ -394,9 +405,17 @@ auto HandleParseNode(Context& context, Parse::WhereExprId node_id) -> bool {
|
||||
context.scope_stack().Pop(/*check_unused=*/true);
|
||||
SemIR::InstBlockId requirements_id = context.args_type_info_stack().Pop();
|
||||
|
||||
auto type_id = SemIR::TypeType::TypeId;
|
||||
if (!context.where_stack().empty()) {
|
||||
DiagnoseNestedWhere(context, node_id, context.where_stack().back().loc_id);
|
||||
type_id = SemIR::ErrorInst::TypeId;
|
||||
}
|
||||
|
||||
// TODO: Look at the constant value and diagnose NestedWhereInsideWhere if
|
||||
// there are any non-extend constraints present.
|
||||
AddInstAndPush<SemIR::WhereExpr>(
|
||||
context, node_id,
|
||||
{.type_id = SemIR::TypeType::TypeId, .requirements_id = requirements_id});
|
||||
{.type_id = type_id, .requirements_id = requirements_id});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -491,320 +491,4 @@ auto IsPeriodSelf(Context& context, SemIR::InstId inst_id, bool canonicalize)
|
||||
return false;
|
||||
}
|
||||
|
||||
class SearchNonCanonicalForExplicitPeriodSelf : public SubstInstCallbacks {
|
||||
public:
|
||||
explicit SearchNonCanonicalForExplicitPeriodSelf(Context* context,
|
||||
SemIR::LocId* found)
|
||||
: SubstInstCallbacks(context), found_(found) {}
|
||||
|
||||
auto Subst(SemIR::InstId& inst_id) -> SubstResult override {
|
||||
if (found_->has_value()) {
|
||||
return FullySubstituted;
|
||||
}
|
||||
|
||||
auto const_inst_id = context().constant_values().GetConstantInstId(inst_id);
|
||||
if (const_inst_id == SemIR::TypeType::TypeInstId) {
|
||||
// Recursion base case. TypeType has type TypeType.
|
||||
return FullySubstituted;
|
||||
}
|
||||
if (context().insts().Is<SemIR::FacetType>(const_inst_id)) {
|
||||
// Don't look for `.Self` in nested facet types, they aren't replaced
|
||||
// with a facet value and just remain as abstract. WhereExprs evaluate
|
||||
// to a FacetType but are handled outside of Subst.
|
||||
return FullySubstituted;
|
||||
}
|
||||
|
||||
if (auto name_ref = context().insts().TryGetAs<SemIR::NameRef>(inst_id)) {
|
||||
// Canonicalization not necessary; NameRef contains the SymbolicBinding
|
||||
// directly, not an `as type` conversion.
|
||||
if (IsPeriodSelf(context(), name_ref->value_id,
|
||||
/*canonicalize=*/false)) {
|
||||
// `.Self` does not have a location, the NameRef pointing to it does.
|
||||
*found_ = SemIR::LocId(inst_id);
|
||||
return FullySubstituted;
|
||||
}
|
||||
}
|
||||
|
||||
return SubstOperands;
|
||||
}
|
||||
|
||||
auto Rebuild(SemIR::InstId /*orig_inst_id*/, SemIR::Inst /*new_inst*/)
|
||||
-> SemIR::InstId override {
|
||||
CARBON_FATAL();
|
||||
}
|
||||
|
||||
private:
|
||||
SemIR::LocId* found_;
|
||||
};
|
||||
|
||||
class SearchCanonicalForExplicitPeriodSelf : public SubstInstCallbacks {
|
||||
public:
|
||||
explicit SearchCanonicalForExplicitPeriodSelf(Context* context, bool* found)
|
||||
: SubstInstCallbacks(context), found_(found) {}
|
||||
|
||||
auto Subst(SemIR::InstId& inst_id) -> SubstResult override {
|
||||
if (*found_) {
|
||||
return FullySubstituted;
|
||||
}
|
||||
|
||||
auto const_inst_id = context().constant_values().GetConstantInstId(inst_id);
|
||||
if (const_inst_id == SemIR::TypeType::TypeInstId) {
|
||||
// Recursion base case. TypeType has type TypeType.
|
||||
return FullySubstituted;
|
||||
}
|
||||
if (context().insts().Is<SemIR::FacetType>(const_inst_id)) {
|
||||
// Don't look for `.Self` in nested facet types, they aren't replaced
|
||||
// with a facet value and just remain as abstract. WhereExprs evaluate
|
||||
// to a FacetType but are handled outside of Subst.
|
||||
return FullySubstituted;
|
||||
}
|
||||
|
||||
if (auto access = context().insts().TryGetAs<SemIR::ImplWitnessAccess>(
|
||||
const_inst_id)) {
|
||||
if (auto lookup = context().insts().TryGetAs<SemIR::LookupImplWitness>(
|
||||
access->witness_id)) {
|
||||
// Canonicalization not necessary; we are working with the constant
|
||||
// value already, and the query self in a witness is already
|
||||
// canonicalized.
|
||||
if (IsPeriodSelf(context(), lookup->query_self_inst_id,
|
||||
/*canonicalize=*/false)) {
|
||||
// An implicit `.Self` in a member designator is always allowed.
|
||||
return FullySubstituted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Canonicalization not necessary; Subst will recurse anyway, so avoid
|
||||
// extra work for non-matches.
|
||||
if (IsPeriodSelf(context(), const_inst_id, /*canonicalize=*/false)) {
|
||||
*found_ = true;
|
||||
return FullySubstituted;
|
||||
}
|
||||
|
||||
return SubstOperands;
|
||||
}
|
||||
|
||||
auto Rebuild(SemIR::InstId /*orig_inst_id*/, SemIR::Inst /*new_inst*/)
|
||||
-> SemIR::InstId override {
|
||||
CARBON_FATAL();
|
||||
}
|
||||
|
||||
private:
|
||||
bool* found_;
|
||||
};
|
||||
|
||||
static auto ReportAmbiguousPeriodSelf(Context& context, SemIR::LocId loc_id)
|
||||
-> void {
|
||||
CARBON_DIAGNOSTIC(AmbiguousPeriodSelf, Error,
|
||||
"`.Self` is ambiguous after nested `where` in `<type> "
|
||||
"impls ...` clause.");
|
||||
context.emitter().Emit(loc_id, AmbiguousPeriodSelf);
|
||||
}
|
||||
|
||||
// Searches a type for a reference to `.Self`. Types are canonical, so they
|
||||
// only contain canonical values/inststructions, which have no location of
|
||||
// their own.
|
||||
//
|
||||
// The search excludes ImplWitnessAccess into `.Self`, which represents a
|
||||
// designator like `.X`.
|
||||
//
|
||||
// The search does not recurse into FacetTypes, as some can include valid
|
||||
// references to the top level `.Self`, or abstract `.Self` references that
|
||||
// are not replaced. FacetTypes are handled by the higher level search.
|
||||
//
|
||||
// Returns true if found, and diagnosed.
|
||||
static auto SearchTypeForPeriodSelf(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::TypeId type_id) -> bool {
|
||||
bool found_canonical = false;
|
||||
SearchCanonicalForExplicitPeriodSelf callbacks(&context, &found_canonical);
|
||||
|
||||
auto canonical_inst_id = context.types().GetTypeInstId(type_id);
|
||||
SubstInst(context, canonical_inst_id, callbacks);
|
||||
|
||||
// The type has no locations internally, as it stores canonical
|
||||
// instructions. If we find any `.Self` reference, we report the entire
|
||||
// type.
|
||||
if (found_canonical) {
|
||||
ReportAmbiguousPeriodSelf(context, loc_id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Searches a facet type for a reference to `.Self`. FacetTypes are canonical,
|
||||
// so they only contain canonical values/inststructions, which have no
|
||||
// location of their own.
|
||||
//
|
||||
// The search excludes ImplWitnessAccess into `.Self`, which represents a
|
||||
// designator like `.X`.
|
||||
//
|
||||
// Returns true if found, and diagnosed.
|
||||
static auto SearchFacetTypeForPeriodSelf(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::FacetTypeId facet_type_id)
|
||||
-> bool {
|
||||
bool found_canonical = false;
|
||||
SearchCanonicalForExplicitPeriodSelf callbacks(&context, &found_canonical);
|
||||
|
||||
const auto& info = context.facet_types().Get(facet_type_id);
|
||||
// The LHS of a `WhereExpr` only has extend constraints.
|
||||
for (auto extend : info.extend_constraints) {
|
||||
auto block_id = context.specifics().GetArgsOrEmpty(extend.specific_id);
|
||||
for (auto inst_id : context.inst_blocks().GetOrEmpty(block_id)) {
|
||||
SubstInst(context, inst_id, callbacks);
|
||||
}
|
||||
}
|
||||
for (auto extend : info.extend_named_constraints) {
|
||||
auto block_id = context.specifics().GetArgsOrEmpty(extend.specific_id);
|
||||
for (auto inst_id : context.inst_blocks().GetOrEmpty(block_id)) {
|
||||
SubstInst(context, inst_id, callbacks);
|
||||
}
|
||||
}
|
||||
// The facet type has no locations internally, as it stores canonical
|
||||
// instructions. If we find any `.Self` reference, we report the entire
|
||||
// facet type.
|
||||
if (found_canonical) {
|
||||
ReportAmbiguousPeriodSelf(context, loc_id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Searches a non-canonical instruction for an explicitly written use of
|
||||
// `.Self`, which is represented as a NameRef instruction.
|
||||
//
|
||||
// Returns true if found, and diagnosed.
|
||||
static auto SearchNonCanonicalInstForPeriodSelf(Context& context,
|
||||
SemIR::InstId inst_id) -> bool {
|
||||
auto found = SemIR::LocId::None;
|
||||
SearchNonCanonicalForExplicitPeriodSelf callbacks(&context, &found);
|
||||
SubstInst(context, inst_id, callbacks);
|
||||
if (found.has_value()) {
|
||||
ReportAmbiguousPeriodSelf(context, found);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto FindAndDiagnoseAmbiguousPeriodSelf(Context& context,
|
||||
SemIR::InstId impls_lhs_id,
|
||||
SemIR::InstId impls_rhs_id) -> bool {
|
||||
// Look for errors up front. We don't need to look for them in the rest of
|
||||
// the function.
|
||||
if (context.constant_values().Get(impls_lhs_id) ==
|
||||
SemIR::ErrorInst::ConstantId ||
|
||||
context.constant_values().Get(impls_rhs_id) ==
|
||||
SemIR::ErrorInst::ConstantId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsPeriodSelf(context, impls_lhs_id)) {
|
||||
// `.Self impls X where ...` does not restrict any use of `.Self` on the
|
||||
// RHS of the `where` since the `.Self` on the LHS of `where` did not
|
||||
// introduce any ambiguity. A `.Self` on the RHS of the `where` applies to
|
||||
// the same thing as on the LHS of the `impls`.
|
||||
return false;
|
||||
}
|
||||
|
||||
struct WorkItem {
|
||||
SemIR::WhereExpr where_expr;
|
||||
bool search_lhs;
|
||||
};
|
||||
|
||||
llvm::SmallVector<WorkItem> work;
|
||||
if (auto where_expr =
|
||||
context.insts().TryGetAs<SemIR::WhereExpr>(impls_rhs_id)) {
|
||||
work.push_back({.where_expr = *where_expr, .search_lhs = false});
|
||||
}
|
||||
|
||||
while (!work.empty()) {
|
||||
auto work_item = work.pop_back_val();
|
||||
|
||||
// Look in the non-canonical WhereExpr for explicit references to `.Self`,
|
||||
// which will be considered as ambiguous.
|
||||
for (auto inst_id : context.inst_blocks().GetOrEmpty(
|
||||
work_item.where_expr.requirements_id)) {
|
||||
auto inst = context.insts().Get(inst_id);
|
||||
CARBON_KIND_SWITCH(inst) {
|
||||
case CARBON_KIND(SemIR::RequirementBaseFacetType base): {
|
||||
if (work_item.search_lhs) {
|
||||
// If the base type is more than a reference to an interface or
|
||||
// constraint, such as having specific arguments, it will be a
|
||||
// FacetType instruction.
|
||||
if (auto facet_type = context.insts().TryGetAs<SemIR::FacetType>(
|
||||
base.base_type_inst_id)) {
|
||||
if (SearchFacetTypeForPeriodSelf(
|
||||
context, SemIR::LocId(base.base_type_inst_id),
|
||||
facet_type->facet_type_id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::RequirementRewrite rewrite): {
|
||||
if (SearchNonCanonicalInstForPeriodSelf(context, rewrite.lhs_id)) {
|
||||
return true;
|
||||
}
|
||||
if (SearchNonCanonicalInstForPeriodSelf(context, rewrite.rhs_id)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::RequirementEquivalent equiv): {
|
||||
if (SearchNonCanonicalInstForPeriodSelf(context, equiv.lhs_id)) {
|
||||
return true;
|
||||
}
|
||||
if (SearchNonCanonicalInstForPeriodSelf(context, equiv.rhs_id)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::RequirementImpls impls): {
|
||||
if (!IsPeriodSelf(context, impls.lhs_id)) {
|
||||
if (SearchTypeForPeriodSelf(
|
||||
context, SemIR::LocId(impls.lhs_id),
|
||||
context.types().GetTypeIdForTypeInstId(impls.lhs_id))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CARBON_KIND_SWITCH(context.insts().Get(impls.rhs_id)) {
|
||||
case CARBON_KIND(SemIR::FacetType facet_type): {
|
||||
// If the RHS of the `impls` is a complex facet type (such as
|
||||
// when it has specific arguments) but has no `where`, then it
|
||||
// will be a FacetType instruction.
|
||||
if (SearchFacetTypeForPeriodSelf(context,
|
||||
SemIR::LocId(impls.rhs_id),
|
||||
facet_type.facet_type_id)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::WhereExpr rhs_where_expr): {
|
||||
// If the RHS of the `impls` contains a `where`, then it will be
|
||||
// a WhereExpr instruction.
|
||||
work.push_back(
|
||||
{.where_expr = rhs_where_expr, .search_lhs = true});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Otherwise, it's a simple facet type, which is just a
|
||||
// reference to an interface or constraint. There's nowhere to
|
||||
// look for a
|
||||
// `.Self`.
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CARBON_FATAL("unexpected inst {0} in WhereExpr requirements block",
|
||||
inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Carbon::Check
|
||||
|
||||
@@ -85,21 +85,6 @@ auto SubstPeriodSelfInFacetType(Context& context, SemIR::LocId loc_id,
|
||||
auto IsPeriodSelf(Context& context, SemIR::InstId inst_id,
|
||||
bool canonicalize = true) -> bool;
|
||||
|
||||
// Look for ambiguous `.Self` in a `T impls X where ...` statement. The given
|
||||
// inst ids are the non-canonical insts for the LHS and RHS of the `impls`
|
||||
// inside a `where` expression.
|
||||
//
|
||||
// If the LHS is not `.Self` and RHS contains a nested `where` expression, the
|
||||
// value of `.Self` becomes ambiguous on the RHS of the `where` (it could mean
|
||||
// either the original value or new value given by the LHS of the `impls`). Note
|
||||
// that implicit `.Self` references are never ambiguous, they always refer to
|
||||
// the innermost value that `.Self` could refer to.
|
||||
//
|
||||
// Returns true if an error was diagnosed.
|
||||
auto FindAndDiagnoseAmbiguousPeriodSelf(Context& context,
|
||||
SemIR::InstId impls_lhs_id,
|
||||
SemIR::InstId impls_rhs_id) -> bool;
|
||||
|
||||
} // namespace Carbon::Check
|
||||
|
||||
#endif // CARBON_TOOLCHAIN_CHECK_PERIOD_SELF_H_
|
||||
|
||||
+20
-69
@@ -367,61 +367,7 @@ fn F(U:! W, V:! Z(.Self) where .Z1 impls Y(U)) {
|
||||
V.(Z(V).Z1).(Y(U).Y1).(X.X1) as W;
|
||||
}
|
||||
|
||||
// --- find_access_value_in_second_nested_access.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface W {}
|
||||
interface X {
|
||||
let X1:! type;
|
||||
}
|
||||
interface Y(T:! type) {
|
||||
let Y0:! type;
|
||||
let Y1:! type;
|
||||
let Y2:! type;
|
||||
}
|
||||
interface Z(U:! type, PeriodSelf:! type) {
|
||||
let Z1:! Y(PeriodSelf) where .Y0 impls (X where .X1 = ())
|
||||
and .Y1 impls (X where .X1 = U)
|
||||
and .Y2 impls (X where .X1 = ()) ;
|
||||
}
|
||||
|
||||
fn F(U:! W, V:! Z(U, .Self)) {
|
||||
// This has to search for a value for `.Z1.Y1.X1` in V. To do so it needs to
|
||||
// look for a rewrite of .X1. First it looks in `V.Z1.Y1`, then `V.Z1`, where
|
||||
// it finds the rewrite of `.Y1.X1 = U`.
|
||||
//
|
||||
// Only U impls W so we use `as W` to test that the LHS is U.
|
||||
V.(Z(U, V).Z1).(Y(V).Y1).(X.X1) as W;
|
||||
}
|
||||
|
||||
// --- find_access_value_in_third_nested_access.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface W {}
|
||||
interface X {
|
||||
let X1:! type;
|
||||
}
|
||||
interface Y {
|
||||
let Y1:! type;
|
||||
}
|
||||
interface Z(T:! type) {
|
||||
let Z0:! type;
|
||||
let Z1:! type;
|
||||
let Z2:! type;
|
||||
}
|
||||
|
||||
fn F(U:! W, V:! Z(.Self) where .Z0 impls (Y where .Y1 impls (X where .X1 = ()))
|
||||
and .Z1 impls (Y where .Y1 impls (X where .X1 = U))
|
||||
and .Z2 impls (Y where .Y1 impls (X where .X1 = ()))) {
|
||||
// This has to search for a value for `.Z1.Y1.X1` in V. To do so it needs to
|
||||
// look for a rewrite of .X1. First it looks in `V.Z1.Y1`, then `V.Z1`, then
|
||||
// `V` where it finds the rewrite of `.Z1.Y1.X1 = U`.
|
||||
//
|
||||
// Only U impls W so we use `as W` to test that the LHS is U.
|
||||
V.(Z(V).Z1).(Y.Y1).(X.X1) as W;
|
||||
}
|
||||
|
||||
// --- fail_todo_find_access_value_in_second_nested_access_through_named_constraint.carbon
|
||||
// --- fail_todo_find_access_value_in_second_nested_access.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface W {}
|
||||
@@ -451,17 +397,17 @@ fn F(V:! Z(.Self)) {
|
||||
//
|
||||
// TODO: The identified facet type `NX` includes `X` and should provide a
|
||||
// same-type constraint `X.X1 == {}` which would allow this conversion.
|
||||
// CHECK:STDERR: fail_todo_find_access_value_in_second_nested_access_through_named_constraint.carbon:[[@LINE+7]]:3: error: cannot convert expression of type `{}` to `V.(Z(V).Z1).(Y(V).Y1).(X.X1)` with `as` [ConversionFailure]
|
||||
// CHECK:STDERR: fail_todo_find_access_value_in_second_nested_access.carbon:[[@LINE+7]]:3: error: cannot convert expression of type `{}` to `V.(Z(V).Z1).(Y(V).Y1).(X.X1)` with `as` [ConversionFailure]
|
||||
// CHECK:STDERR: {} as V.(Z(V).Z1).(Y(V).Y1).(X.X1);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_find_access_value_in_second_nested_access_through_named_constraint.carbon:[[@LINE+4]]:3: note: type `{}` does not implement interface `Core.As(V.(Z(V).Z1).(Y(V).Y1).(X.X1))` [MissingImplInMemberAccessInContext]
|
||||
// CHECK:STDERR: fail_todo_find_access_value_in_second_nested_access.carbon:[[@LINE+4]]:3: note: type `{}` does not implement interface `Core.As(V.(Z(V).Z1).(Y(V).Y1).(X.X1))` [MissingImplInMemberAccessInContext]
|
||||
// CHECK:STDERR: {} as V.(Z(V).Z1).(Y(V).Y1).(X.X1);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
{} as V.(Z(V).Z1).(Y(V).Y1).(X.X1);
|
||||
}
|
||||
|
||||
// --- fail_todo_find_access_value_in_third_nested_access_through_named_constraint.carbon
|
||||
// --- fail_todo_find_access_value_in_third_nested_access.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface W {}
|
||||
@@ -481,21 +427,22 @@ constraint NX(V:! type) {
|
||||
extend require impls X where .X1 = V;
|
||||
}
|
||||
|
||||
fn F(V:! Z(.Self) where .Z0 impls (Y where .Y1 impls NX(()))
|
||||
and .Z1 impls (Y where .Y1 impls NX({}))
|
||||
and .Z2 impls (Y where .Y1 impls NX(()))) {
|
||||
constraint NY(V:! type) {
|
||||
extend require impls Y where .Y1 = NX(V);
|
||||
}
|
||||
|
||||
fn F(V:! Z(.Self) where .Z0 impls NY(())
|
||||
and .Z1 impls NY({})
|
||||
and .Z2 impls NY(())) {
|
||||
// This has to search for a value for `.Z1.Y1.X1` in V. To do so it needs to
|
||||
// look for a rewrite of .X1. First it looks in `V.Z1.Y1`, then `V.Z1`, then
|
||||
// `V` where it finds the rewrite of `.Z1.Y1.X1 = {}`.
|
||||
//
|
||||
// TODO: The identified facet type `NX` includes `X` and should provide a
|
||||
// same-type constraint `X.X1 == V` which would allow this conversion.
|
||||
// CHECK:STDERR: fail_todo_find_access_value_in_third_nested_access_through_named_constraint.carbon:[[@LINE+7]]:3: error: cannot convert expression of type `{}` to `V.(Z(V).Z1).(Y.Y1).(X.X1)` with `as` [ConversionFailure]
|
||||
// CHECK:STDERR: fail_todo_find_access_value_in_third_nested_access.carbon:[[@LINE+4]]:9: error: cannot convert type `V.(Z(V).Z1).(Y.Y1)` into type implementing `X` [ConversionFailureTypeToFacet]
|
||||
// CHECK:STDERR: {} as V.(Z(V).Z1).(Y.Y1).(X.X1);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_find_access_value_in_third_nested_access_through_named_constraint.carbon:[[@LINE+4]]:3: note: type `{}` does not implement interface `Core.As(V.(Z(V).Z1).(Y.Y1).(X.X1))` [MissingImplInMemberAccessInContext]
|
||||
// CHECK:STDERR: {} as V.(Z(V).Z1).(Y.Y1).(X.X1);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
{} as V.(Z(V).Z1).(Y.Y1).(X.X1);
|
||||
}
|
||||
@@ -509,10 +456,14 @@ interface Y(T:! 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
|
||||
constraint NY(PeriodSelf:! type) {
|
||||
extend require impls Y(PeriodSelf) where .Y1 = {};
|
||||
}
|
||||
|
||||
// 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) {
|
||||
fn F(T:! Z where C impls NY(.Self)) -> 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: ^~~~~~~~~~
|
||||
|
||||
+13
-5
@@ -244,7 +244,7 @@ constraint N(V:! type) {
|
||||
// CHECK:STDERR:
|
||||
fn F(_:! Z(.Self) where C impls N(.Z1) and .Z2 = (.Z1 as Y(.Self))) {}
|
||||
|
||||
// --- early_type_impls_nested_self_impls.carbon
|
||||
// --- fail_todo_early_type_impls_nested_self_impls.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z {
|
||||
@@ -258,10 +258,18 @@ 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.
|
||||
constraint NY {
|
||||
require impls Y where .Y1 impls X;
|
||||
}
|
||||
|
||||
// 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
|
||||
// constraint is visible through the `C(.Self) impls NY` 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))) {}
|
||||
// CHECK:STDERR: fail_todo_early_type_impls_nested_self_impls.carbon:[[@LINE+7]]:53: error: cannot convert type `C(.Self).(Y.Y1)` into type implementing `X` [ConversionFailureTypeToFacet]
|
||||
// CHECK:STDERR: fn F(unused V:! Z where C(.Self) impls NY and .Z1 = D(C(.Self).(Y.Y1))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_early_type_impls_nested_self_impls.carbon:[[@LINE-12]]:9: note: initializing generic parameter `T` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: class D(T:! X);
|
||||
// CHECK:STDERR: ^~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(unused V:! Z where C(.Self) impls NY and .Z1 = D(C(.Self).(Y.Y1))) {}
|
||||
|
||||
+36
-16
@@ -384,7 +384,7 @@ fn G(T:! J where .J1 = D) {
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- early_rewrite_from_previous_impls_constraint.carbon
|
||||
// --- fail_todo_early_rewrite_from_previous_impls_constraint.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z {
|
||||
@@ -399,7 +399,18 @@ 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))) {}
|
||||
constraint NY(V:! type) {
|
||||
extend require impls Y where .Y1 = V;
|
||||
}
|
||||
|
||||
// CHECK:STDERR: fail_todo_early_rewrite_from_previous_impls_constraint.carbon:[[@LINE+7]]:52: error: cannot convert type `.(Z.Z1).(Y.Y1)` into type implementing `Tuple` [ConversionFailureTypeToFacet]
|
||||
// CHECK:STDERR: fn F(unused T:! Z where .Z1 impls NY(()) and .Z2 = C(.Z1.(Y.Y1))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_early_rewrite_from_previous_impls_constraint.carbon:[[@LINE-9]]: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 .Z1 impls NY(()) and .Z2 = C(.Z1.(Y.Y1))) {}
|
||||
|
||||
// --- fail_early_rewrite_correct_interface_wrong_self_access_rewrite_in_period_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
@@ -416,17 +427,21 @@ interface Tuple {}
|
||||
impl () as Tuple {}
|
||||
class C(U:! Tuple);
|
||||
|
||||
constraint NY(V:! type) {
|
||||
extend require impls Y where .Y1 = V;
|
||||
}
|
||||
|
||||
// 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: fail_early_rewrite_correct_interface_wrong_self_access_rewrite_in_period_self.carbon:[[@LINE+7]]:70: error: cannot convert type `.(Z.Z1).(Y.Y1)` into type implementing `Tuple` [ConversionFailureTypeToFacet]
|
||||
// CHECK:STDERR: fn F(unused T:! Z where .Self impls NY(()) 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-12]]: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))) {}
|
||||
fn F(unused T:! Z where .Self impls NY(()) 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]]";
|
||||
@@ -443,14 +458,18 @@ interface Tuple {}
|
||||
impl () as Tuple {}
|
||||
class C(U:! Tuple);
|
||||
|
||||
constraint NY(V:! type) {
|
||||
extend require impls Y where .Y1 = V;
|
||||
}
|
||||
|
||||
// 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: fail_early_rewrite_correct_interface_wrong_self_access_rewrite_in_associated_constant.carbon:[[@LINE+4]]:72: error: name `Self` not found [NameNotFound]
|
||||
// CHECK:STDERR: fn G(unused T:! Z where .Z1 impls NY(()) 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))) {}
|
||||
fn G(unused T:! Z where .Z1 impls NY(()) 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]]";
|
||||
@@ -460,17 +479,18 @@ interface Z {
|
||||
let Y:! type;
|
||||
}
|
||||
|
||||
// TODO: Does the `.X = .Y` contain an ambiguous `.Self` in `.Y`? See
|
||||
// https://github.com/carbon-language/carbon-lang/issues/7138.
|
||||
constraint NZ(PeriodY:! type) {
|
||||
extend require impls Z where .X = PeriodY;
|
||||
}
|
||||
|
||||
fn F(T:! Z where .Y = {} and .X = (Z where .X = .Y), U:! T.X) -> U.(Z.X) {
|
||||
fn F(T:! Z where .Y = {} and .X = NZ(.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: 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.X)` [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: 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.X))` [MissingImplInMemberAccessInContext]
|
||||
// CHECK:STDERR: return {};
|
||||
// CHECK:STDERR: ^~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
|
||||
+69
-7
@@ -244,16 +244,20 @@ library "[[@TEST_NAME]]";
|
||||
|
||||
interface Y {}
|
||||
interface Z {
|
||||
let T:! type;
|
||||
let U:! type;
|
||||
let Z1:! type;
|
||||
let Z2:! type;
|
||||
}
|
||||
class C(T:! type) {}
|
||||
|
||||
fn F(unused FF:! ((Y where .Self impls (Z where .T = C(.U)))
|
||||
where .Self impls (Z where .T = C(.U)))
|
||||
where .Self impls (Z where .T = C(.U))) {}
|
||||
constraint NZ {
|
||||
extend require impls Z where .Z1 = C(.Z2);
|
||||
}
|
||||
|
||||
// --- nested_impl_unique.carbon
|
||||
fn F(unused FF:! ((Y where .Self impls NZ)
|
||||
where .Self impls NZ)
|
||||
where .Self impls NZ) {}
|
||||
|
||||
// --- fail_todo_nested_impl_combine_rewrites_from_named_constraints.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Y {
|
||||
@@ -265,6 +269,64 @@ interface Z {
|
||||
}
|
||||
class C(T:! type) { adapt (); }
|
||||
|
||||
fn F(FF:! ((Y where .Y1 = ()) where .Self impls (Z where .Z1 = C(.Z2) and .Z2 = ()))) -> FF.(Z.Z1) {
|
||||
constraint NZ1 {
|
||||
// This uses the rewrite from NZ2.
|
||||
extend require impls Z where .Z1 = C(.Z2);
|
||||
}
|
||||
constraint NZ2 {
|
||||
extend require impls Z where .Z2 = ();
|
||||
}
|
||||
|
||||
fn F(FF:! ((Y where .Y1 = ()) where .Self impls NZ1) where .Self impls NZ2) -> FF.(Z.Z1) {
|
||||
// CHECK:STDERR: fail_todo_nested_impl_combine_rewrites_from_named_constraints.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `C(())` to `FF.(Z.Z1)` [ConversionFailure]
|
||||
// CHECK:STDERR: return () as C(());
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_nested_impl_combine_rewrites_from_named_constraints.carbon:[[@LINE+4]]:3: note: type `C(())` does not implement interface `Core.ImplicitAs(FF.(Z.Z1))` [MissingImplInMemberAccessInContext]
|
||||
// CHECK:STDERR: return () as C(());
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
return () as C(());
|
||||
}
|
||||
|
||||
// --- fail_where_nested_inside_where_impls.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
// CHECK:STDERR: fail_where_nested_inside_where_impls.carbon:[[@LINE+7]]:34: error: found `where` expression nested on the right-hand side of `where` [NestedWhereInsideWhere]
|
||||
// CHECK:STDERR: fn F(_:! type where .Self impls (type where .Self impls type)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_where_nested_inside_where_impls.carbon:[[@LINE+4]]:10: note: on right-hand side of `where` here [NestedWhereInsideWhereOuterNote]
|
||||
// CHECK:STDERR: fn F(_:! type where .Self impls (type where .Self impls type)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(_:! type where .Self impls (type where .Self impls type)) {}
|
||||
|
||||
// --- fail_where_nested_inside_where_rewrite.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z {
|
||||
let Z1:! type;
|
||||
}
|
||||
|
||||
// CHECK:STDERR: fail_where_nested_inside_where_rewrite.carbon:[[@LINE+7]]:25: error: found `where` expression nested on the right-hand side of `where` [NestedWhereInsideWhere]
|
||||
// CHECK:STDERR: fn F(_:! Z where .Z1 = (type where .Self impls type)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_where_nested_inside_where_rewrite.carbon:[[@LINE+4]]:10: note: on right-hand side of `where` here [NestedWhereInsideWhereOuterNote]
|
||||
// CHECK:STDERR: fn F(_:! Z where .Z1 = (type where .Self impls type)) {}
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(_:! Z where .Z1 = (type where .Self impls type)) {}
|
||||
|
||||
// --- fail_where_nested_inside_where_same_type.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z {}
|
||||
class C;
|
||||
|
||||
// CHECK:STDERR: fail_where_nested_inside_where_same_type.carbon:[[@LINE+7]]:24: error: found `where` expression nested on the right-hand side of `where` [NestedWhereInsideWhere]
|
||||
// CHECK:STDERR: fn F(_:! Z where C == (type where .Self impls type)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_where_nested_inside_where_same_type.carbon:[[@LINE+4]]:10: note: on right-hand side of `where` here [NestedWhereInsideWhereOuterNote]
|
||||
// CHECK:STDERR: fn F(_:! Z where C == (type where .Self impls type)) {}
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(_:! Z where C == (type where .Self impls type)) {}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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/full.carbon
|
||||
//
|
||||
// AUTOUPDATE
|
||||
// TIP: To test this file alone, run:
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/nested_facet_types_from_eval.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/nested_facet_types_from_eval.carbon
|
||||
|
||||
// --- todo_fail_where_nested_inside_where_through_alias.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {}
|
||||
class C;
|
||||
|
||||
alias A = I where .Self == C;
|
||||
|
||||
// The use of `A` introduces a `where` expression inside the `where` written
|
||||
// here, which is an error.
|
||||
//
|
||||
// TODO This should fail.
|
||||
fn F(_:! type where .Self impls A) {}
|
||||
|
||||
// --- todo_fail_where_nested_inside_where_through_fn_eval.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {}
|
||||
class C;
|
||||
|
||||
eval fn E() -> type {
|
||||
return I where .Self == C;
|
||||
}
|
||||
|
||||
// The use of `E()` introduces a `where` expression inside the `where`
|
||||
// written here, which is an error.
|
||||
//
|
||||
// TODO This should fail.
|
||||
fn F(_:! type where .Self impls E()) {}
|
||||
|
||||
// --- todo_fail_where_nested_inside_where_through_operator_eval.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {}
|
||||
class C;
|
||||
|
||||
class X1 {
|
||||
impl type as Core.MulWith(X1) where .Result = type {
|
||||
eval fn Op(unused self, _: X1) -> type {
|
||||
return I where .Self == C;
|
||||
}
|
||||
}
|
||||
}
|
||||
alias X = {} as X1;
|
||||
|
||||
// The use of `type * X` introduces a `where` expression inside the `where`
|
||||
// written here, which is an error.
|
||||
//
|
||||
// TODO This should fail.
|
||||
fn F(_:! type where .Self impls type * X) {}
|
||||
-170
@@ -224,64 +224,6 @@ fn F(U:! Core.Destroy & I where .X = .Self) {
|
||||
let unused a: U = U.G();
|
||||
}
|
||||
|
||||
// --- fail_todo_nested_period_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I(T:! type) {
|
||||
let A:! type;
|
||||
let B:! type;
|
||||
fn G() -> T;
|
||||
}
|
||||
|
||||
// Both `.Self` refer to `T`. The first because it's the interface for the
|
||||
// binding. The second because it refers to the top level facet type which is
|
||||
// constraining the binding.
|
||||
fn F(T:! I(.Self) where .A = ((I(.Self) where .B = {}) where .A = {}) and .B = {}, U:! T.A) {
|
||||
// T.G() has type T.
|
||||
// CHECK:STDERR: fail_todo_nested_period_self.carbon:[[@LINE+7]]:21: error: cannot implicitly convert expression of type `.Self` to `T` [ConversionFailure]
|
||||
// CHECK:STDERR: let unused t: T = T.G();
|
||||
// CHECK:STDERR: ^~~~~
|
||||
// CHECK:STDERR: fail_todo_nested_period_self.carbon:[[@LINE+4]]:21: note: type `.Self` does not implement interface `Core.ImplicitAs(T)` [MissingImplInMemberAccessInContext]
|
||||
// CHECK:STDERR: let unused t: T = T.G();
|
||||
// CHECK:STDERR: ^~~~~
|
||||
// CHECK:STDERR:
|
||||
let unused t: T = T.G();
|
||||
// U.G() has type T.
|
||||
// CHECK:STDERR: fail_todo_nested_period_self.carbon:[[@LINE+7]]:21: error: cannot implicitly convert expression of type `.Self` to `T` [ConversionFailure]
|
||||
// CHECK:STDERR: let unused u: T = U.G();
|
||||
// CHECK:STDERR: ^~~~~
|
||||
// CHECK:STDERR: fail_todo_nested_period_self.carbon:[[@LINE+4]]:21: note: type `.Self` does not implement interface `Core.ImplicitAs(T)` [MissingImplInMemberAccessInContext]
|
||||
// CHECK:STDERR: let unused u: T = U.G();
|
||||
// CHECK:STDERR: ^~~~~
|
||||
// CHECK:STDERR:
|
||||
let unused u: T = U.G();
|
||||
|
||||
// Shows both `I(.Self)` are `I(T)`.
|
||||
// CHECK:STDERR: fail_todo_nested_period_self.carbon:[[@LINE+4]]:9: error: found cycle in facet type constraint for `.(I(T).A)` [FacetTypeConstraintCycle]
|
||||
// CHECK:STDERR: T as (I(T) where .A = (I(T) where .A = {} and .B = {}));
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
T as (I(T) where .A = (I(T) where .A = {} and .B = {}));
|
||||
// CHECK:STDERR: fail_todo_nested_period_self.carbon:[[@LINE+4]]:3: error: cannot convert type `U` that implements `I(.Self) where .(I(.Self).B) = {} and .(I(.Self).A) = {}` into type implementing `I(T) where .(I(T).A) = {} and .(I(T).B) = {}` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: U as (I(T) where .A = {} and .B = {});
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
U as (I(T) where .A = {} and .B = {});
|
||||
}
|
||||
|
||||
// --- todo_fail_nested_period_self_ambiguous.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I(T:! type) {
|
||||
let A:! type;
|
||||
}
|
||||
|
||||
// TODO: This should be an error: The third `.Self` becomes is not able to be
|
||||
// bound to anything unambiguous here, as it could refer to `T` or to something
|
||||
// later being constrained by `T.A`.
|
||||
fn F(unused T:! I(.Self) where .A = (I(.Self) where .A = I(.Self))) {}
|
||||
|
||||
|
||||
// --- period_self_parameter_sees_lhs_of_where_expr.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
@@ -321,118 +263,6 @@ fn F[U:! Core.Destroy where .Self impls I(.Self)](u: U) {
|
||||
u.(I(U).G)().(I(U).G)().(I(U).G)();
|
||||
}
|
||||
|
||||
// --- unambiguous_period_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z(T:! type) {}
|
||||
interface Y(T:! type) {
|
||||
let Y1:! type;
|
||||
let Y2:! type;
|
||||
}
|
||||
interface X(T:! type) {}
|
||||
|
||||
class P;
|
||||
class Q(T:! type);
|
||||
class R(T:! type);
|
||||
|
||||
fn A(unused T:! Z(.Self) where .Self impls (Y(.Self) where .Self impls X(.Self))) {}
|
||||
// ^T as type ^T as Z(T) ^T as Z(T) ^T as Z(T) & Y(T)
|
||||
// ^ T as Z(T) & Y(T)
|
||||
|
||||
fn B(unused T:! Z(.Self) where .Self impls (Y(.Self) where Q(.Self) impls X(.Self))) {}
|
||||
// ^T as type ^T as Z(T) ^T as Z(T) ^T as Z(T) & Y(T)
|
||||
// ^ T as Z(T) & Y(T)
|
||||
|
||||
fn C(unused T:! Z(.Self) where .Self impls (Y(.Self) where .Y1 = .Self)) {}
|
||||
// ^T as type ^T as Z(T) ^T as Z(T) ^T as Z(T) & Y(T)
|
||||
// ^ T as Z(T) & Y(T)
|
||||
|
||||
// This introduces a different meaning of `.Self`, but we allow it here.
|
||||
fn D(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Self impls X(P))) {}
|
||||
// ^T as type ^T as Z(T) ^T as Z(T) ^R(T as Z(T)) as Y(T as Z(T))
|
||||
|
||||
// This introduces a different meaning of `.Self`, but we allow it here.
|
||||
fn E(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Y1 = .Y2)) {}
|
||||
// ^T as type ^T as Z(T) ^T as Z(T) ^R(T as Z(T)) as Y(T as Z(T))
|
||||
// ^R(T as Z(T)) as Y(T as Z(T))
|
||||
|
||||
// Member designators have an implicit `.Self` which is always allowed. It binds
|
||||
// to the innermost facet value rather than being ambiguous.
|
||||
fn F(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Self impls X(.Y1))) {}
|
||||
// ^T as type ^T as Z(T) ^T as Z(T) ^R(T as Z(T)) as Y(T as Z(T))
|
||||
// ^Implicit: R(T as Z(T)) as Y(T as Z(T))
|
||||
|
||||
// --- fail_type_impls_ambiguous_period_self_argument.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z(T:! type) {}
|
||||
interface Y(T:! type) {}
|
||||
interface X(T:! type) {}
|
||||
interface W {}
|
||||
|
||||
class P;
|
||||
class Q(T:! type);
|
||||
class R(T:! type);
|
||||
|
||||
// CHECK:STDERR: fail_type_impls_ambiguous_period_self_argument.carbon:[[@LINE+4]]:71: error: `.Self` is ambiguous after nested `where` in `<type> impls ...` clause. [AmbiguousPeriodSelf]
|
||||
// CHECK:STDERR: fn A(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where P impls X(.Self))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn A(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where P impls X(.Self))) {}
|
||||
// ^T as type ^T as Z(T) ^T as Z(T) ^ERROR: R(T as Z(T)) as Y(T as Z(T))
|
||||
|
||||
// --- fail_ambiguous_period_self_argument_impls.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z(T:! type) {}
|
||||
interface Y(T:! type) {}
|
||||
interface X {}
|
||||
|
||||
class Q(T:! type);
|
||||
class R(T:! type);
|
||||
|
||||
// CHECK:STDERR: fail_ambiguous_period_self_argument_impls.carbon:[[@LINE+4]]:63: error: `.Self` is ambiguous after nested `where` in `<type> impls ...` clause. [AmbiguousPeriodSelf]
|
||||
// CHECK:STDERR: fn B(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where Q(.Self) impls X)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn B(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where Q(.Self) impls X)) {}
|
||||
// ^T as type ^T as Z(T) ^T as Z(T) ^ERROR: R(T as Z(T)) as Y(T as Z(T))
|
||||
|
||||
// --- fail_period_self_impls_ambiguous_period_self_argument.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z(T:! type) {}
|
||||
interface Y(T:! type) {}
|
||||
interface X(T:! type) {}
|
||||
|
||||
class R(T:! type);
|
||||
|
||||
// CHECK:STDERR: fail_period_self_impls_ambiguous_period_self_argument.carbon:[[@LINE+4]]:75: error: `.Self` is ambiguous after nested `where` in `<type> impls ...` clause. [AmbiguousPeriodSelf]
|
||||
// CHECK:STDERR: fn C(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Self impls X(.Self))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn C(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Self impls X(.Self))) {}
|
||||
// ^T as type ^T as Z(T) ^T as Z(T) ^R(T as Z(T)) as Y(T as Z(T))
|
||||
// ^ERROR: R(T as Z(T)) as Y(T as Z(T))
|
||||
|
||||
// --- fail_rewrite_rhs_ambiguous_period_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z(T:! type) {}
|
||||
interface Y(T:! type) {
|
||||
let Y1:! type;
|
||||
}
|
||||
|
||||
class R(T:! type);
|
||||
|
||||
// CHECK:STDERR: fail_rewrite_rhs_ambiguous_period_self.carbon:[[@LINE+4]]:69: error: `.Self` is ambiguous after nested `where` in `<type> impls ...` clause. [AmbiguousPeriodSelf]
|
||||
// CHECK:STDERR: fn D(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Y1 = .Self)) {}
|
||||
// CHECK:STDERR: ^~~~~
|
||||
// CHECK:STDERR:
|
||||
fn D(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Y1 = .Self)) {}
|
||||
// ^T as type ^T as Z(T) ^T as Z(T) ^R(T as Z(T)) as Y(T as Z(T))
|
||||
// ^ERROR: R(T as Z(T)) as Y(T as Z(T))
|
||||
|
||||
// --- impl_as_rewrite_with_period_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
|
||||
+63
-76
@@ -10,14 +10,25 @@
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/validate_impl_constraints.carbon
|
||||
|
||||
// --- self_impls_modifies_assoc_constant.carbon
|
||||
// --- fail_todo_self_impls_modifies_assoc_constant.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I { let X:! type; }
|
||||
|
||||
fn F(unused T:! I where .X = ()) {}
|
||||
|
||||
fn G(T:! I where .Self impls (I where .X = ())) {
|
||||
constraint N {
|
||||
extend require impls I where .X = ();
|
||||
}
|
||||
|
||||
fn G(T:! I where .Self impls N) {
|
||||
// CHECK:STDERR: fail_todo_self_impls_modifies_assoc_constant.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .Self impls N` into type implementing `I where .(I.X) = ()` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_todo_self_impls_modifies_assoc_constant.carbon:[[@LINE-10]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused T:! I where .X = ()) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T);
|
||||
}
|
||||
|
||||
@@ -28,18 +39,22 @@ interface I { let X:! type; }
|
||||
|
||||
fn F(unused T:! I where .X = ()) {}
|
||||
|
||||
fn G(T:! I where .Self impls (I where .X = {})) {
|
||||
// CHECK:STDERR: fail_self_impls_modifies_assoc_constant_type_differs.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.X) = {}` into type implementing `I where .(I.X) = ()` [ConversionFailureFacetToFacet]
|
||||
constraint N {
|
||||
extend require impls I where .X = {};
|
||||
}
|
||||
|
||||
fn G(T:! I where .Self impls N) {
|
||||
// CHECK:STDERR: fail_self_impls_modifies_assoc_constant_type_differs.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .Self impls N` into type implementing `I where .(I.X) = ()` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_self_impls_modifies_assoc_constant_type_differs.carbon:[[@LINE-6]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fail_self_impls_modifies_assoc_constant_type_differs.carbon:[[@LINE-10]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused T:! I where .X = ()) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- fail_where_impls_tests_associated_constant_of_generic_type_non_final_impl.carbon
|
||||
// --- todo_fail_where_impls_tests_associated_constant_of_generic_type_non_final_impl.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C(U:! type) {}
|
||||
@@ -49,23 +64,22 @@ interface L {}
|
||||
interface M { let M0:! type; }
|
||||
impl forall [U:! L] C(U) as M where .M0 = {} {}
|
||||
|
||||
constraint M0IsStruct {
|
||||
extend require impls M where .M0 = {};
|
||||
}
|
||||
|
||||
// U requires that C(.Self) impls M.
|
||||
// - C(.Self) impls M can be rewritten as C(U) impls M.
|
||||
// - C(U) impls M if U impls L => Requires U impls L.
|
||||
fn F(unused U:! type where C(.Self) impls (M where .M0 = {})) {}
|
||||
fn F(unused U:! type where C(.Self) impls M0IsStruct) {}
|
||||
|
||||
fn G(T:! L) {
|
||||
// We have no final impl for `C(T) as M`, so we don't know the value of
|
||||
// `(C(T) as M).M0` concretely, so we don't know that it is `{}` and we can't
|
||||
// convert assuming it is.
|
||||
//
|
||||
// CHECK:STDERR: fail_where_impls_tests_associated_constant_of_generic_type_non_final_impl.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `L` into type implementing `type where C(.Self) impls M and C(.Self).(M.M0) = {}` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_where_impls_tests_associated_constant_of_generic_type_non_final_impl.carbon:[[@LINE-10]]:13: note: initializing generic parameter `U` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused U:! type where C(.Self) impls (M where .M0 = {})) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// TODO: This should fail. The rewrite constraint from `M0IsStruct` is not
|
||||
// being checked.
|
||||
F(T);
|
||||
}
|
||||
|
||||
@@ -79,16 +93,20 @@ interface L {}
|
||||
interface M { let M0:! type; }
|
||||
final impl forall [U:! L] C(U) as M where .M0 = {} {}
|
||||
|
||||
constraint M0IsStruct {
|
||||
extend require impls M where .M0 = {};
|
||||
}
|
||||
|
||||
// U requires that C(.Self) impls M.
|
||||
// - C(.Self) impls M can be rewritten as C(U) impls M.
|
||||
// - C(U) impls M if U impls L => Requires U impls L.
|
||||
fn F(unused U:! type where C(.Self) impls (M where .M0 = {})) {}
|
||||
fn F(unused U:! type where C(.Self) impls M0IsStruct) {}
|
||||
|
||||
fn G(T:! L) {
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- fail_where_impls_tests_associated_constant_of_generic_type_type_differs.carbon
|
||||
// --- todo_fail_where_impls_tests_associated_constant_of_generic_type_type_differs.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C(U:! type) {}
|
||||
@@ -98,23 +116,23 @@ interface L {}
|
||||
interface M { let M0:! type; }
|
||||
final impl forall [U:! L] C(U) as M where .M0 = () {}
|
||||
|
||||
constraint M0IsStruct {
|
||||
extend require impls M where .M0 = {};
|
||||
}
|
||||
|
||||
// U requires that C(.Self) impls M.
|
||||
// - C(.Self) impls M can be rewritten as C(U) impls M.
|
||||
// - C(U) impls M if U impls L => Requires U impls L.
|
||||
fn F(unused U:! type where C(.Self) impls (M where .M0 = {})) {}
|
||||
fn F(unused U:! type where C(.Self) impls M0IsStruct) {}
|
||||
|
||||
fn G(T:! L) {
|
||||
// CHECK:STDERR: fail_where_impls_tests_associated_constant_of_generic_type_type_differs.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `L` into type implementing `type where C(.Self) impls M and C(.Self).(M.M0) = {}` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_where_impls_tests_associated_constant_of_generic_type_type_differs.carbon:[[@LINE-6]]:13: note: initializing generic parameter `U` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused U:! type where C(.Self) impls (M where .M0 = {})) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// F requires .M0 = {}, but the final impl provides .M0 = ().
|
||||
//
|
||||
// TODO: This should fail.
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- fail_where_impls_tests_associated_constant_of_generic_interface_non_final_impl.carbon
|
||||
// --- todo_fail_where_impls_tests_associated_constant_of_generic_interface_non_final_impl.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {}
|
||||
@@ -124,23 +142,21 @@ interface L {}
|
||||
interface M(U:! type) { let M0:! type; }
|
||||
impl forall [U:! L] C as M(U) where .M0 = {} {}
|
||||
|
||||
constraint M0IsStruct(PeriodSelf:! type) {
|
||||
extend require impls M(PeriodSelf) where .M0 = {};
|
||||
}
|
||||
|
||||
// U requires that C impls M(.Self).
|
||||
// - C impls M(.Self) can be rewritten as C impls M(U).
|
||||
// - C impls M(U) if U impls L => Requires U impls L.
|
||||
fn F(unused U:! type where C impls (M(.Self) where .M0 = {})) {}
|
||||
fn F(unused U:! type where C impls M0IsStruct(.Self)) {}
|
||||
|
||||
fn G(T:! L) {
|
||||
// We have no final impl for `C as M(T)`, so we don't know the value of
|
||||
// `(C as M(T)).M0` concretely, so we don't know that it is `{}` and we can't
|
||||
// convert assuming it is.
|
||||
//
|
||||
// CHECK:STDERR: fail_where_impls_tests_associated_constant_of_generic_interface_non_final_impl.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `L` into type implementing `type where C impls M(.Self) and C.(M(.Self).M0) = {}` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_where_impls_tests_associated_constant_of_generic_interface_non_final_impl.carbon:[[@LINE-10]]:13: note: initializing generic parameter `U` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused U:! type where C impls (M(.Self) where .M0 = {})) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// TODO: This should fail.
|
||||
F(T);
|
||||
}
|
||||
|
||||
@@ -154,16 +170,20 @@ interface L {}
|
||||
interface M(U:! type) { let M0:! type; }
|
||||
final impl forall [U:! L] C as M(U) where .M0 = {} {}
|
||||
|
||||
constraint M0IsStruct(PeriodSelf:! type) {
|
||||
extend require impls M(PeriodSelf) where .M0 = {};
|
||||
}
|
||||
|
||||
// U requires that C impls M(.Self).
|
||||
// - C impls M(.Self) can be rewritten as C impls M(U).
|
||||
// - C impls M(U) if U impls L => Requires U impls L.
|
||||
fn F(unused U:! type where C impls (M(.Self) where .M0 = {})) {}
|
||||
fn F(unused U:! type where C impls M0IsStruct(.Self)) {}
|
||||
|
||||
fn G(T:! L) {
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- fail_where_impls_tests_associated_constant_of_generic_interface_type_differs.carbon
|
||||
// --- todo_fail_where_impls_tests_associated_constant_of_generic_interface_type_differs.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {}
|
||||
@@ -173,19 +193,19 @@ interface L {}
|
||||
interface M(U:! type) { let M0:! type; }
|
||||
final impl forall [U:! L] C as M(U) where .M0 = () {}
|
||||
|
||||
constraint M0IsStruct(PeriodSelf:! type) {
|
||||
extend require impls M(PeriodSelf) where .M0 = {};
|
||||
}
|
||||
|
||||
// U requires that C impls M(.Self).
|
||||
// - C impls M(.Self) can be rewritten as C impls M(U).
|
||||
// - C impls M(U) if U impls L => Requires U impls L.
|
||||
fn F(unused U:! type where C impls (M(.Self) where .M0 = {})) {}
|
||||
fn F(unused U:! type where C impls M0IsStruct(.Self)) {}
|
||||
|
||||
fn G(T:! L) {
|
||||
// CHECK:STDERR: fail_where_impls_tests_associated_constant_of_generic_interface_type_differs.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `L` into type implementing `type where C impls M(.Self) and C.(M(.Self).M0) = {}` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_where_impls_tests_associated_constant_of_generic_interface_type_differs.carbon:[[@LINE-6]]:13: note: initializing generic parameter `U` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused U:! type where C impls (M(.Self) where .M0 = {})) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// F requires that .M0 = {} but the final impl provides that .M0 = ().
|
||||
//
|
||||
// TODO: This should fail.
|
||||
F(T);
|
||||
}
|
||||
|
||||
@@ -276,39 +296,6 @@ fn G() {
|
||||
F(C);
|
||||
}
|
||||
|
||||
// --- fail_todo_where_period_self_rhs_impls_nested_period_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z {}
|
||||
interface Y {}
|
||||
interface X(T:! Z & Y) {}
|
||||
|
||||
constraint N {
|
||||
require impls Y;
|
||||
}
|
||||
|
||||
// TODO: The inner nested facet type (`N where...`) does not know about
|
||||
// constraints on the outer facet type (`Z where...`). But it should produce an
|
||||
// implied constraint that `.Self impls Z & Y` that is checked once the full
|
||||
// facet type is known.
|
||||
//
|
||||
// CHECK:STDERR: fail_todo_where_period_self_rhs_impls_nested_period_self.carbon:[[@LINE+7]]:51: error: cannot convert type `.Self` that implements `N` into type implementing `Z & Y` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: fn F(_:! Z where .Self impls (N where .Self impls X(.Self))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_where_period_self_rhs_impls_nested_period_self.carbon:[[@LINE-14]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: interface X(T:! Z & Y) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(_:! Z where .Self impls (N where .Self impls X(.Self))) {}
|
||||
|
||||
fn G() {
|
||||
class C;
|
||||
impl C as Z {}
|
||||
impl C as Y {}
|
||||
impl C as X(C) {}
|
||||
F(C);
|
||||
}
|
||||
|
||||
// --- associated_const_impls_interface_with_period_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
|
||||
+206
-275
@@ -556,9 +556,9 @@ library "[[@TEST_NAME]]";
|
||||
interface I { let X:! type; }
|
||||
interface K(Y:! type) { }
|
||||
|
||||
fn F(unused T:! I where .X = {.k: K(I where .X = ())}) {}
|
||||
fn F(unused T:! I where .X = {.k: K(I)}) {}
|
||||
|
||||
fn G(T:! I where .X = {.k: K(I where .X = ())}) {
|
||||
fn G(T:! I where .X = {.k: K(I)}) {
|
||||
F(T);
|
||||
}
|
||||
|
||||
@@ -717,25 +717,6 @@ fn H(T:! I where .X1 = .Self and .X2 = .X1.X3 and .X3 = ()) {
|
||||
G(T);
|
||||
}
|
||||
|
||||
// --- associated_constant_is_facet_type_of_same_interface.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let A:! type;
|
||||
let X:! type;
|
||||
}
|
||||
|
||||
class C;
|
||||
|
||||
// This looks for a bug where `.Self.A` resolves to `C` from `.T.A` in the
|
||||
// incoming facet value, which is incorrect. It should be `.T.X.A` which
|
||||
// resolves to `{}`.
|
||||
fn F(unused U:! I where .X = (I where .A = {})) {}
|
||||
|
||||
fn G(T:! I where .X = (I where .A = {}) and .A = C) {
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- rewrite_requires_subst_in_rhs.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
@@ -752,58 +733,6 @@ fn G(T:! I where .X = C({}) and .Y = {}) {
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- fail_todo_rewrite_requires_subst_in_nested_facet_type.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I(T:! type) {
|
||||
let X:! type;
|
||||
let Y:! type;
|
||||
}
|
||||
|
||||
class C;
|
||||
|
||||
fn F(unused T:! I(C) where .X = (I(.Y) where .Y = ())) {}
|
||||
|
||||
fn G(T:! I(C) where .X = (I({}) where .Y = ()) and .Y = {}) {
|
||||
// TODO: The T in G should match the T in F, once the .Self reference to the
|
||||
// top level facet value in `I(.Y)` is correctly substituted by tracking that
|
||||
// it is a .Self reference to the top level Self.
|
||||
// CHECK:STDERR: fail_todo_rewrite_requires_subst_in_nested_facet_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I(C) where .(I(C).X) = I({}) where .(I({}).Y) = () and .(I(C).Y) = {}` into type implementing `I(C) where .(I(C).X) = I(.(I(C).Y)) where .(I(.(I(C).Y)).Y) = ()` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_todo_rewrite_requires_subst_in_nested_facet_type.carbon:[[@LINE-9]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused T:! I(C) where .X = (I(.Y) where .Y = ())) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T);
|
||||
}
|
||||
|
||||
fn G2(T:! I(C) where .X = (I(.Y) where .Y = ()) and .Y = {}) {
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- fail_rewrite_requires_subst_in_nested_facet_type_types_differ.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I(T:! type) {
|
||||
let X:! type;
|
||||
let Y:! type;
|
||||
}
|
||||
|
||||
fn F(unused T:! I({}) where .X = (I(.Y) where .X = ())) {}
|
||||
|
||||
// I(.Y) is I({}) which doesn't match I(()).
|
||||
fn G(T:! I({}) where .X = (I(()) where .X = ()) and .Y = {}) {
|
||||
// CHECK:STDERR: fail_rewrite_requires_subst_in_nested_facet_type_types_differ.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I({}) where .(I({}).X) = I(()) where .(I(()).X) = () and .(I({}).Y) = {}` into type implementing `I({}) where .(I({}).X) = I(.(I({}).Y)) where .(I(.(I({}).Y)).X) = ()` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_rewrite_requires_subst_in_nested_facet_type_types_differ.carbon:[[@LINE-7]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused T:! I({}) where .X = (I(.Y) where .X = ())) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- facet_type_in_assoc_constant.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
@@ -811,10 +740,11 @@ interface I {
|
||||
let X:! type;
|
||||
let Y:! type;
|
||||
}
|
||||
interface J(T:! type) {}
|
||||
|
||||
fn F(unused T:! I where .X = (I where .X = () and .Y = ())) {}
|
||||
fn F(unused T:! I where .X = J(())) {}
|
||||
|
||||
fn G(T:! I where .X = (I where .X = .Y and .Y = ())) {
|
||||
fn G(T:! I where .X = J(()) and .Y = ()) {
|
||||
F(T);
|
||||
}
|
||||
|
||||
@@ -826,189 +756,21 @@ interface I {
|
||||
let Y:! type;
|
||||
let Z:! type;
|
||||
}
|
||||
interface J(T:! type) {}
|
||||
|
||||
fn F(unused T:! I where .X = (I where .X = .Y)) {}
|
||||
fn F(unused T:! I where .X = J(())) {}
|
||||
|
||||
fn G(T:! I where .X = (I where .X = () and .Y = () and .Z = {})) {
|
||||
// CHECK:STDERR: fail_facet_type_in_assoc_constant_differs.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.X) = I where .(I.X) = () and .(I.Y) = () and .(I.Z) = {}` into type implementing `I where .(I.X) = I where .(I.X) = .(I.Y)` [ConversionFailureFacetToFacet]
|
||||
fn G(T:! I where .X = J({}) and .Y = ()) {
|
||||
// CHECK:STDERR: fail_facet_type_in_assoc_constant_differs.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.X) = J({}) and .(I.Y) = ()` into type implementing `I where .(I.X) = J(())` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_facet_type_in_assoc_constant_differs.carbon:[[@LINE-6]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused T:! I where .X = (I where .X = .Y)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fn F(unused T:! I where .X = J(())) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- nested_facet_type_in_assoc_constant.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let X:! type;
|
||||
let Y:! type;
|
||||
let Z:! type;
|
||||
}
|
||||
|
||||
fn F(unused T:! I where .X = (I where .Y = (I where .X = () and .Y = ()))) {}
|
||||
|
||||
fn G(T:! I where .X = (I where .Y = (I where .X = .Y and .Y = ()))) {
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- fail_nested_facet_type_assigns_same_assoc_constant.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let X:! type;
|
||||
let Y:! type;
|
||||
}
|
||||
|
||||
fn F(unused T:! I where .Y = ()) {}
|
||||
|
||||
// The `.Y = ()` is on a different `.Self` than `T` (an unattached self), so
|
||||
// should not satisfy `F`.
|
||||
fn G(T:! I where .X = (I where .Y = ())) {
|
||||
// CHECK:STDERR: fail_nested_facet_type_assigns_same_assoc_constant.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.X) = I where .(I.Y) = ()` into type implementing `I where .(I.Y) = ()` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_nested_facet_type_assigns_same_assoc_constant.carbon:[[@LINE-8]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused T:! I where .Y = ()) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- fail_nested_facet_type_in_assoc_constant_differs.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let X:! type;
|
||||
let Y:! type;
|
||||
let Z:! type;
|
||||
}
|
||||
|
||||
fn F(unused T:! I where .X = (I where .Y = (I where .X = .Y))) {}
|
||||
|
||||
// `.X = .Y` does not match `.X = () and .Y = ()` as they are different resolved
|
||||
// facet types.
|
||||
fn G(T:! I where .X = (I where .Y = (I where .X = () and .Y = ()))) {
|
||||
// CHECK:STDERR: fail_nested_facet_type_in_assoc_constant_differs.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.X) = I where .(I.Y) = I where .(I.X) = () and .(I.Y) = ()` into type implementing `I where .(I.X) = I where .(I.Y) = I where .(I.X) = .(I.Y)` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_nested_facet_type_in_assoc_constant_differs.carbon:[[@LINE-8]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused T:! I where .X = (I where .Y = (I where .X = .Y))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T);
|
||||
}
|
||||
|
||||
// The extra .Z rewrite makes a different resolved facet type which does not
|
||||
// match.
|
||||
fn G2(T:! I where .X = (I where .Y = (I where .X = .Y and .Z = {}))) {
|
||||
// CHECK:STDERR: fail_nested_facet_type_in_assoc_constant_differs.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.X) = I where .(I.Y) = I where .(I.X) = .(I.Y) and .(I.Z) = {}` into type implementing `I where .(I.X) = I where .(I.Y) = I where .(I.X) = .(I.Y)` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_nested_facet_type_in_assoc_constant_differs.carbon:[[@LINE-21]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused T:! I where .X = (I where .Y = (I where .X = .Y))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- fail_nested_facet_type_from_constant.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let X:! type;
|
||||
let Y:! type;
|
||||
}
|
||||
|
||||
fn F(unused T:! I where .X = (I where .Y = (I where .X = .Y, ))) {}
|
||||
|
||||
// References to named constants in a facet type don't work at all. If they did,
|
||||
// then when the `Constant` facet type is put into the RHS of a rewrite
|
||||
// constraint, its references to `.Self` must be modified to not refer to the
|
||||
// top level `.Self` which is `T`. If done correctly, they will match the
|
||||
// `.Self` references in the same position in the parameter of `F`. If not, the
|
||||
// `.X` within becomes self-referential and makes a cycle.
|
||||
|
||||
fn G1() {
|
||||
// CHECK:STDERR: fail_nested_facet_type_from_constant.carbon:[[@LINE+4]]:7: error: semantics TODO: `local `let :!` bindings are currently unsupported` [SemanticsTodo]
|
||||
// CHECK:STDERR: let Constant:! type = I where .X = .Y;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
let Constant:! type = I where .X = .Y;
|
||||
|
||||
fn G(T:! I where .X = (I where .Y = (Constant, ))) {
|
||||
F(T);
|
||||
}
|
||||
}
|
||||
|
||||
fn G2() {
|
||||
let Constant:! type = (I where .X = .Y, );
|
||||
|
||||
fn G(T:! I where .X = (I where .Y = Constant)) {
|
||||
F(T);
|
||||
}
|
||||
}
|
||||
|
||||
fn G3() {
|
||||
let Constant:! type = I where .Y = (I where .X = .Y, );
|
||||
|
||||
fn G(T:! I where .X = Constant) {
|
||||
F(T);
|
||||
}
|
||||
}
|
||||
|
||||
fn G4() {
|
||||
let Constant2:! type = (I where .X = .Y, );
|
||||
let Constant:! type = Constant2;
|
||||
|
||||
fn G(T:! I where .X = (I where .Y = Constant)) {
|
||||
F(T);
|
||||
}
|
||||
}
|
||||
|
||||
fn G5() {
|
||||
let Constant2:! type = I where .X = .Y;
|
||||
let Constant:! type = (Constant2, );
|
||||
|
||||
fn G(T:! I where .X = (I where .Y = Constant)) {
|
||||
F(T);
|
||||
}
|
||||
}
|
||||
|
||||
fn G6() {
|
||||
let Constant2:! type = (I where .X = .Y, );
|
||||
let Constant:! type = I where .Y = Constant2;
|
||||
|
||||
fn G(T:! I where .X = Constant) {
|
||||
F(T);
|
||||
}
|
||||
}
|
||||
|
||||
// --- fail_nested_facet_type_from_constant_differs.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let X:! type;
|
||||
let Y:! type;
|
||||
}
|
||||
|
||||
fn F(unused T:! I where .X = (I where .Y = (I where .X = .Y, ))) {}
|
||||
|
||||
fn G1() {
|
||||
// CHECK:STDERR: fail_nested_facet_type_from_constant_differs.carbon:[[@LINE+4]]:7: error: semantics TODO: `local `let :!` bindings are currently unsupported` [SemanticsTodo]
|
||||
// CHECK:STDERR: let Constant:! type = I where .X = () and .Y = ();
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
let Constant:! type = I where .X = () and .Y = ();
|
||||
|
||||
fn G(T:! I where .X = (I where .Y = (Constant, ))) {
|
||||
F(T);
|
||||
}
|
||||
}
|
||||
|
||||
// --- rewrite_rhs_satisfies_lhs_requirement.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
@@ -1335,7 +1097,7 @@ fn G(T:! I where .I1 = .I2) {
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- nested_facet_type_used_as_root_facet_type.carbon
|
||||
// --- nested_facet_type_used_as_root_facet_type_in_callee.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
@@ -1343,9 +1105,118 @@ interface I {
|
||||
let Y:! type;
|
||||
}
|
||||
|
||||
fn F(T:! I where .X = (I where .Y = {}), unused U:! T.X) {}
|
||||
constraint NI(V:! type) {
|
||||
extend require impls I where .Y = V;
|
||||
}
|
||||
|
||||
fn G(T:! I where .X = (I where .Y = {}), U:! I where .Y = {}) {
|
||||
fn F(T:! I where .X = NI({}), unused U:! T.X) {}
|
||||
|
||||
fn G(T:! I where .X = NI({}), U:! I where .Y = {}) {
|
||||
F(T, U);
|
||||
}
|
||||
|
||||
// --- fail_todo_nested_facet_type_used_as_root_facet_type_in_caller.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let X:! type;
|
||||
let Y:! type;
|
||||
}
|
||||
|
||||
constraint NI(V:! type) {
|
||||
extend require impls I where .Y = V;
|
||||
}
|
||||
|
||||
fn F(unused T:! I where .X = NI({}), unused U:! I where .Y = {}) {}
|
||||
|
||||
fn G(T:! I where .X = NI({}), U:! T.X) {
|
||||
// TODO: This should pass, the rewrite in the constraint `NI` should be visible.
|
||||
// CHECK:STDERR: fail_todo_nested_facet_type_used_as_root_facet_type_in_caller.carbon:[[@LINE+7]]:3: error: cannot convert type `U` that implements `NI({})` into type implementing `I where .(I.Y) = {}` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T, U);
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_todo_nested_facet_type_used_as_root_facet_type_in_caller.carbon:[[@LINE-7]]:45: note: initializing generic parameter `U` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused T:! I where .X = NI({}), unused U:! I where .Y = {}) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T, U);
|
||||
}
|
||||
|
||||
// --- fail_nested_facet_type_used_as_root_facet_type_differs_in_interface.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let X:! type;
|
||||
let Y:! type;
|
||||
}
|
||||
interface J {
|
||||
let X:! type;
|
||||
let Y:! type;
|
||||
}
|
||||
|
||||
constraint NI(V:! type) {
|
||||
extend require impls I where .Y = V;
|
||||
}
|
||||
|
||||
fn F(T:! I where .X = NI({}), unused U:! T.X) {}
|
||||
|
||||
fn G(T:! I where .X = NI({}), U:! J where .Y = ()) {
|
||||
// CHECK:STDERR: fail_nested_facet_type_used_as_root_facet_type_differs_in_interface.carbon:[[@LINE+7]]:3: error: cannot convert type `U` that implements `J where .(J.Y) = ()` into type implementing `NI({})` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T, U);
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_nested_facet_type_used_as_root_facet_type_differs_in_interface.carbon:[[@LINE-6]]:38: note: initializing generic parameter `U` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(T:! I where .X = NI({}), unused U:! T.X) {}
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T, U);
|
||||
}
|
||||
|
||||
// --- todo_fail_nested_facet_type_used_as_root_facet_type_differs_in_rewrite_callee_access.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let X:! type;
|
||||
let Y:! type;
|
||||
}
|
||||
|
||||
constraint NI(V:! type) {
|
||||
extend require impls I where .Y = V;
|
||||
}
|
||||
|
||||
fn F(T:! I where .X = NI({}), unused U:! T.X) {}
|
||||
|
||||
fn G(T:! I where .X = NI({}), U:! I where .Y = ()) {
|
||||
// The caller's `U` has type `I where .Y = ()` but the callee wants something
|
||||
// of type `I where .Y = {}`.
|
||||
//
|
||||
// TODO: This should fail.
|
||||
F(T, U);
|
||||
}
|
||||
|
||||
// --- fail_nested_facet_type_used_as_root_facet_type_differs_in_rewrite_caller_access.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let X:! type;
|
||||
let Y:! type;
|
||||
}
|
||||
|
||||
constraint NI(V:! type) {
|
||||
extend require impls I where .Y = V;
|
||||
}
|
||||
|
||||
fn F(unused T:! I where .X = NI({}), unused U:! I where .Y = ()) {}
|
||||
|
||||
fn G(T:! I where .X = NI({}), U:! T.X) {
|
||||
// The caller's `U` has type `I where .Y = {}` but the callee wants something
|
||||
// of type `I where .Y = ()`.
|
||||
//
|
||||
// CHECK:STDERR: fail_nested_facet_type_used_as_root_facet_type_differs_in_rewrite_caller_access.carbon:[[@LINE+7]]:3: error: cannot convert type `U` that implements `NI({})` into type implementing `I where .(I.Y) = ()` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T, U);
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_nested_facet_type_used_as_root_facet_type_differs_in_rewrite_caller_access.carbon:[[@LINE-9]]:45: note: initializing generic parameter `U` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(unused T:! I where .X = NI({}), unused U:! I where .Y = ()) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T, U);
|
||||
}
|
||||
|
||||
@@ -1417,81 +1288,141 @@ fn G(T:! I where .I1 = {}) {
|
||||
// --- resolve_nested_impl_witness_access.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Y {
|
||||
let Y1:! type;
|
||||
}
|
||||
interface Z {
|
||||
let Z1:! Y;
|
||||
let Z1:! type;
|
||||
let Z2:! type;
|
||||
}
|
||||
|
||||
fn G(_:! Z where .Z2 = ()) {}
|
||||
|
||||
// Split the assignment of .Y1 and the use of it into separate facet types so
|
||||
// that the early rewrite application doesn't get to see the value of .Y1 where
|
||||
// Split the assignment of .Z1 and the use of it into separate facet types so
|
||||
// that the early rewrite application doesn't get to see the value of .Z1 where
|
||||
// it's used. Then rewrite constraint resolution has to do the replacement of
|
||||
// .Z1.Y1 so that we know .Z2 = () as required by G.
|
||||
fn F(T:! (Z where .Z1 impls (Y where .Y1 = ())) & (Z where .Z2 = .Z1.Y1)) {
|
||||
// .Z1 so that we know .Z2 = () as required by G.
|
||||
fn F(T:! (Z where .Z1 = ()) & (Z where .Z2 = .Z1)) {
|
||||
G(T);
|
||||
}
|
||||
|
||||
// --- rewrite_in_impls_provided_by_facet_type.carbon
|
||||
// --- rewrite_provided_by_facet_type.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z {
|
||||
let Z1:! type;
|
||||
let Z2:! type;
|
||||
}
|
||||
|
||||
fn F(_:! type where .Self impls (Z where .Z1 = {})) {}
|
||||
fn F(_:! Z where .Z1 = {}) {}
|
||||
|
||||
fn G(T:! Z where .Z1 = {}) {
|
||||
fn G(T:! Z where .Z1 = {} and .Z2 = {}) {
|
||||
//@dump-sem-ir-begin
|
||||
// We should see a conversion happen so we know the rewrite constraint is
|
||||
// being validated.
|
||||
F(T);
|
||||
//@dump-sem-ir-end
|
||||
}
|
||||
|
||||
// --- fail_todo_rewrite_in_impls_provided_by_extend_named_constraint.carbon
|
||||
// --- fail_todo_rewrite_provided_by_named_constraint.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z {
|
||||
let Z1:! type;
|
||||
}
|
||||
|
||||
fn F(_:! type where .Self impls (Z where .Z1 = {})) {}
|
||||
fn F(_:! Z where .Z1 = {}) {}
|
||||
|
||||
constraint N {
|
||||
// The extend means that the rewrite constraint is propagated out of `N`, so
|
||||
// it can satisfy the requirement in `F` that `.Z1` is rewritten to `{}`.
|
||||
extend require impls Z where .Z1 = {};
|
||||
}
|
||||
|
||||
fn G(T:! N) {
|
||||
// CHECK:STDERR: fail_todo_rewrite_in_impls_provided_by_extend_named_constraint.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `N` into type implementing `type where .Self impls Z and .(Z.Z1) = {}` [ConversionFailureFacetToFacet]
|
||||
// TODO: This should pass.
|
||||
// CHECK:STDERR: fail_todo_rewrite_provided_by_named_constraint.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `N` into type implementing `Z where .(Z.Z1) = {}` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_todo_rewrite_in_impls_provided_by_extend_named_constraint.carbon:[[@LINE-10]]:6: note: initializing generic parameter `_` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(_:! type where .Self impls (Z where .Z1 = {})) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_rewrite_provided_by_named_constraint.carbon:[[@LINE-13]]:6: note: initializing generic parameter `_` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(_:! Z where .Z1 = {}) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T);
|
||||
}
|
||||
|
||||
// --- fail_todo_rewrite_in_impls_provided_by_named_constraint.carbon
|
||||
// --- fail_rewrite_not_provided_by_named_constraint_without_extend.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z {
|
||||
let Z1:! type;
|
||||
}
|
||||
|
||||
fn F(_:! type where .Self impls (Z where .Z1 = {})) {}
|
||||
fn F(_:! Z where .Z1 = {}) {}
|
||||
|
||||
constraint N {
|
||||
// Without extend, this does not actually rewrite `.Z1 = {}`, it provides the
|
||||
// equivalent of `.Z1 == {}` which allows conversion of `.Z1` to `{}` but is
|
||||
// not enough to satisfy the requirement of `F` that `.Z1` is rewritten to
|
||||
// `{}`.
|
||||
require impls Z where .Z1 = {};
|
||||
}
|
||||
|
||||
fn G(T:! N) {
|
||||
// CHECK:STDERR: fail_todo_rewrite_in_impls_provided_by_named_constraint.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `N` into type implementing `type where .Self impls Z and .(Z.Z1) = {}` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: fail_rewrite_not_provided_by_named_constraint_without_extend.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `N` into type implementing `Z where .(Z.Z1) = {}` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: F(T);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_todo_rewrite_in_impls_provided_by_named_constraint.carbon:[[@LINE-10]]:6: note: initializing generic parameter `_` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(_:! type where .Self impls (Z where .Z1 = {})) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_rewrite_not_provided_by_named_constraint_without_extend.carbon:[[@LINE-14]]:6: note: initializing generic parameter `_` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(_:! Z where .Z1 = {}) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(T);
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: --- rewrite_provided_by_facet_type.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %Z.type: type = facet_type <@Z> [concrete]
|
||||
// CHECK:STDOUT: %.Self.94e: %Z.type = symbolic_binding .Self [symbolic_self]
|
||||
// CHECK:STDOUT: %Z.lookup_impl_witness.e2b: <witness> = lookup_impl_witness %.Self.94e, @Z [symbolic_self]
|
||||
// CHECK:STDOUT: %impl.elem0: type = impl_witness_access %Z.lookup_impl_witness.e2b, element0 [symbolic_self]
|
||||
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
|
||||
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
|
||||
// CHECK:STDOUT: %Z_where.type.767: type = facet_type <@Z where %impl.elem0 = %empty_struct_type> [concrete]
|
||||
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
|
||||
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %impl.elem1: type = impl_witness_access %Z.lookup_impl_witness.e2b, element1 [symbolic_self]
|
||||
// CHECK:STDOUT: %Z_where.type.a88: type = facet_type <@Z where %impl.elem0 = %empty_struct_type and %impl.elem1 = %empty_struct_type> [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.d22: type = pattern_type %Z_where.type.a88 [concrete]
|
||||
// CHECK:STDOUT: %T.patt: %pattern_type.d22 = symbolic_binding_pattern T, 0 [symbolic]
|
||||
// CHECK:STDOUT: %T: %Z_where.type.a88 = symbolic_binding T, 0 [symbolic]
|
||||
// CHECK:STDOUT: %T.as_type: type = facet_access_type %T [symbolic]
|
||||
// CHECK:STDOUT: %Z.lookup_impl_witness.d70: <witness> = lookup_impl_witness %T, @Z [symbolic]
|
||||
// CHECK:STDOUT: %facet_value: %Z_where.type.767 = facet_value %T.as_type, (%Z.lookup_impl_witness.d70) [symbolic]
|
||||
// CHECK:STDOUT: %F.specific_fn: <specific function> = specific_function %F, @F(%facet_value) [symbolic]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: generic fn @G(%T.loc10_7.2: %Z_where.type.a88) {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !definition:
|
||||
// CHECK:STDOUT: %T.as_type.loc14_6.2: type = facet_access_type %T.loc10_7.1 [symbolic = %T.as_type.loc14_6.2 (constants.%T.as_type)]
|
||||
// CHECK:STDOUT: %Z.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc10_7.1, @Z [symbolic = %Z.lookup_impl_witness (constants.%Z.lookup_impl_witness.d70)]
|
||||
// CHECK:STDOUT: %facet_value.loc14_6.2: %Z_where.type.767 = facet_value %T.as_type.loc14_6.2, (%Z.lookup_impl_witness) [symbolic = %facet_value.loc14_6.2 (constants.%facet_value)]
|
||||
// CHECK:STDOUT: %F.specific_fn.loc14_3.2: <specific function> = specific_function constants.%F, @F(%facet_value.loc14_6.2) [symbolic = %F.specific_fn.loc14_3.2 (constants.%F.specific_fn)]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
|
||||
// CHECK:STDOUT: %T.ref: %Z_where.type.a88 = name_ref T, %T.loc10_7.2 [symbolic = %T.loc10_7.1 (constants.%T)]
|
||||
// CHECK:STDOUT: %T.as_type.loc14_6.1: type = facet_access_type %T.ref [symbolic = %T.as_type.loc14_6.2 (constants.%T.as_type)]
|
||||
// CHECK:STDOUT: %facet_value.loc14_6.1: %Z_where.type.767 = facet_value %T.as_type.loc14_6.1, (constants.%Z.lookup_impl_witness.d70) [symbolic = %facet_value.loc14_6.2 (constants.%facet_value)]
|
||||
// CHECK:STDOUT: %.loc14: %Z_where.type.767 = converted %T.ref, %facet_value.loc14_6.1 [symbolic = %facet_value.loc14_6.2 (constants.%facet_value)]
|
||||
// CHECK:STDOUT: %F.specific_fn.loc14_3.1: <specific function> = specific_function %F.ref, @F(constants.%facet_value) [symbolic = %F.specific_fn.loc14_3.2 (constants.%F.specific_fn)]
|
||||
// CHECK:STDOUT: %F.call: init %empty_tuple.type = call %F.specific_fn.loc14_3.1()
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @G(constants.%T) {
|
||||
// CHECK:STDOUT: %T.patt.loc10_7.2 => constants.%T.patt
|
||||
// CHECK:STDOUT: %T.loc10_7.1 => constants.%T
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
+4
-1
@@ -341,8 +341,11 @@ impl CD as IF where .F = 0 {
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface M { let X:! type; }
|
||||
constraint N {
|
||||
extend require impls M where .X = {};
|
||||
}
|
||||
|
||||
impl () as M where .X = (M where .X = (M where .X = {})) {}
|
||||
impl () as M where .X = N {}
|
||||
|
||||
// --- fail_todo_period_self_impl_lookup.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
+11
-9
@@ -16,45 +16,47 @@
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I { let T:! type; }
|
||||
constraint N(U:! type) {}
|
||||
|
||||
// CHECK:STDERR: fail_match_with_associated_type.carbon:[[@LINE+4]]:1: error: impl declared but not defined [ImplMissingDefinition]
|
||||
// CHECK:STDERR: impl () as I where .T = {};
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
impl () as I where .T = {};
|
||||
impl () as I where .T = {} and .T impls (type where .Self impls type) {}
|
||||
impl () as I where .T = {} and .T impls N(.Self) {}
|
||||
|
||||
// CHECK:STDERR: fail_match_with_associated_type.carbon:[[@LINE+4]]:1: error: impl declared but not defined [ImplMissingDefinition]
|
||||
// CHECK:STDERR: impl {} as I;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
impl {} as I;
|
||||
impl {} as I where .T = {} and .T impls (type where .Self impls type) {}
|
||||
impl {} as I where .T = {} and .T impls N(.Self) {}
|
||||
|
||||
// CHECK:STDERR: fail_match_with_associated_type.carbon:[[@LINE+4]]:1: error: impl declared but not defined [ImplMissingDefinition]
|
||||
// CHECK:STDERR: impl ({},) as I where .T = {} and .T impls (type where .Self impls type);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: impl ({},) as I where .T = {} and .T impls N(.Self);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
impl ({},) as I where .T = {} and .T impls (type where .Self impls type);
|
||||
impl ({},) as I where .T = {} and .T impls N(.Self);
|
||||
impl ({},) as I where .T = {} {}
|
||||
|
||||
// --- fail_match_with_empty_interface.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface J {}
|
||||
constraint N {}
|
||||
|
||||
// CHECK:STDERR: fail_match_with_empty_interface.carbon:[[@LINE+4]]:1: error: impl declared but not defined [ImplMissingDefinition]
|
||||
// CHECK:STDERR: impl () as J;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
impl () as J;
|
||||
impl () as J where .Self impls type and .Self impls (type where .Self impls type) {}
|
||||
impl () as J where .Self impls type and .Self impls N {}
|
||||
|
||||
// CHECK:STDERR: fail_match_with_empty_interface.carbon:[[@LINE+4]]:1: error: impl declared but not defined [ImplMissingDefinition]
|
||||
// CHECK:STDERR: impl {} as J where .Self impls type and .Self impls (type where .Self impls type);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: impl {} as J where .Self impls type and .Self impls N;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
impl {} as J where .Self impls type and .Self impls (type where .Self impls type);
|
||||
impl {} as J where .Self impls type and .Self impls N;
|
||||
impl {} as J {}
|
||||
|
||||
// --- fail_parens_other_nesting.carbon
|
||||
|
||||
+11
-5
@@ -10,7 +10,7 @@
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/lookup/access.carbon
|
||||
|
||||
// --- impl_witness_access_in_impl_type_structure.carbon
|
||||
// --- fail_todo_impl_witness_access_in_impl_type_structure.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface X(T:! type) {}
|
||||
@@ -25,11 +25,11 @@ interface Z {
|
||||
// resolve to a symbolic type value, so the type structure is: `? as X(?)`
|
||||
impl forall [T:! Z where .Z1 impls Y] T as X(T.Z1.(Y.Y1)) {}
|
||||
|
||||
class C {
|
||||
impl as Y where .Y1 = {} {}
|
||||
class C(W:! type) {
|
||||
impl as Y where .Y1 = W {}
|
||||
}
|
||||
|
||||
fn F(V:! Z where .Z1 = C) {
|
||||
fn F(V:! Z where .Z1 = C({})) {
|
||||
// The type stucture is `? as X({})` which will match the impl's less specific
|
||||
// `? as X(?)`, then the impl will deduce the parameter of `X` to be `{}` from
|
||||
// the type of `V`. This would fail if ImplWitnessAccess instructions were
|
||||
@@ -45,11 +45,17 @@ fn G(V:! Z where .Z1 impls Y) {
|
||||
V as X(V.(Z.Z1).(Y.Y1));
|
||||
}
|
||||
|
||||
fn H(U:! type, V:! Z where .Z1 impls (Y where .Y1 = U)) {
|
||||
fn H(U:! type, V:! Z where .Z1 = C(U)) {
|
||||
// The type structure is `? as X(?)`, without using an ImplWitnessAccess,
|
||||
// which will match the impl's `? as X(?)`. This would fail if
|
||||
// ImplWitnessAccess instructions were treated as Concrete in the type
|
||||
// structure, since the impl's type structure would be more specific than the
|
||||
// query's.
|
||||
//
|
||||
// TODO: This should pass.
|
||||
// CHECK:STDERR: fail_todo_impl_witness_access_in_impl_type_structure.carbon:[[@LINE+4]]:3: error: cannot convert type `V` that implements `Z where .(Z.Z1) = C(U)` into type implementing `X(U)` [ConversionFailureFacetToFacet]
|
||||
// CHECK:STDERR: V as X(U);
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
V as X(U);
|
||||
}
|
||||
|
||||
+77
-157
@@ -143,142 +143,6 @@ fn F(unused T:! type where C(.Self) impls I(())) {}
|
||||
|
||||
fn G(unused T:! type where C(()) impls I(.Self)) {}
|
||||
|
||||
// --- fail_impls_with_nested_facet_type_with_rewrite_does_not_constrain_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let I1:! type;
|
||||
}
|
||||
class C;
|
||||
|
||||
// The `.I1` satisfies constraining the "current type" of the inner nested facet
|
||||
// type `I where ...`. But it does not constrain the current type of the outer
|
||||
// facet type `type where...`. We should not consider the designator in the
|
||||
// nested where expression as making the `C impls ...` constraint valid.
|
||||
|
||||
// CHECK:STDERR: fail_impls_with_nested_facet_type_with_rewrite_does_not_constrain_self.carbon:[[@LINE+4]]:29: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn F1(unused T:! type where C impls (I where .I1 = C)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F1(unused T:! type where C impls (I where .I1 = C)) {}
|
||||
|
||||
// --- fail_impls_with_nested_facet_type_with_equiv_does_not_constrain_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let I1:! type;
|
||||
}
|
||||
class C;
|
||||
|
||||
// The `.I1` satisfies constraining the "current type" of the inner nested facet
|
||||
// type `I where ...`. But it does not constrain the current type of the outer
|
||||
// facet type `type where...`. We should not consider the designator in the
|
||||
// nested where expression as making the `C impls ...` constraint valid.
|
||||
|
||||
// CHECK:STDERR: fail_impls_with_nested_facet_type_with_equiv_does_not_constrain_self.carbon:[[@LINE+4]]:29: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn F2(unused T:! type where C impls (I where .I1 == C)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F2(unused T:! type where C impls (I where .I1 == C)) {}
|
||||
|
||||
// --- fail_impls_with_nested_facet_type_with_impls_does_not_constrain_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let I1:! type;
|
||||
}
|
||||
interface J(T:! type) {}
|
||||
class C;
|
||||
|
||||
// The `.I1` satisfies constraining the "current type" of the inner nested facet
|
||||
// type `I where ...`. But it does not constrain the current type of the outer
|
||||
// facet type `type where...`. We should not consider the designator in the
|
||||
// nested where expression as making the `C impls ...` constraint valid.
|
||||
|
||||
// CHECK:STDERR: fail_impls_with_nested_facet_type_with_impls_does_not_constrain_self.carbon:[[@LINE+4]]:29: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn F3(unused T:! type where C impls (I where .I1 impls J(.Self))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F3(unused T:! type where C impls (I where .I1 impls J(.Self))) {}
|
||||
|
||||
// --- fail_equiv_with_nested_facet_type_with_rewrite_does_not_constrain_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let I1:! type;
|
||||
}
|
||||
class C;
|
||||
|
||||
// The `.I1` satisfies constraining the "current type" of the inner nested facet
|
||||
// type `I where ...`. But it does not constrain the current type of the outer
|
||||
// facet type `I where...`. We should not consider the designator in the nested
|
||||
// where expression as making the `C impls ...` constraint valid.
|
||||
|
||||
// CHECK:STDERR: fail_equiv_with_nested_facet_type_with_rewrite_does_not_constrain_self.carbon:[[@LINE+4]]:28: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn F(unused T:! type where C == (I where .I1 = C)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(unused T:! type where C == (I where .I1 = C)) {}
|
||||
|
||||
// --- fail_equiv_with_nested_facet_type_with_equiv_does_not_constrain_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let I1:! type;
|
||||
}
|
||||
class C;
|
||||
|
||||
// The `.I1` satisfies constraining the "current type" of the inner nested facet
|
||||
// type `I where ...`. But it does not constrain the current type of the outer
|
||||
// facet type `I where...`. We should not consider the designator in the nested
|
||||
// where expression as making the `C impls ...` constraint valid.
|
||||
|
||||
// CHECK:STDERR: fail_equiv_with_nested_facet_type_with_equiv_does_not_constrain_self.carbon:[[@LINE+4]]:28: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn F(unused T:! type where C == (I where .I1 == C)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(unused T:! type where C == (I where .I1 == C)) {}
|
||||
|
||||
// --- fail_equiv_with_nested_facet_type_with_impls_does_not_constrain_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let I1:! type;
|
||||
}
|
||||
interface J(T:! type) {}
|
||||
class C;
|
||||
|
||||
// The `.I1` satisfies constraining the "current type" of the inner nested facet
|
||||
// type `I where ...`. But it does not constrain the current type of the outer
|
||||
// facet type `I where...`. We should not consider the designator in the nested
|
||||
// where expression as making the `C impls ...` constraint valid.
|
||||
|
||||
// CHECK:STDERR: fail_equiv_with_nested_facet_type_with_impls_does_not_constrain_self.carbon:[[@LINE+4]]:28: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn F(unused T:! type where C == (I where .I1 impls J(.Self))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(unused T:! type where C == (I where .I1 impls J(.Self))) {}
|
||||
|
||||
// --- fail_impls_with_nested_facet_type_does_not_constrain_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
let I1:! type;
|
||||
}
|
||||
interface J(T:! type) {}
|
||||
class C;
|
||||
|
||||
// The `.I1` satisfies constraining the "current type" of the inner nested facet
|
||||
// type `I where ...`. But it does not constrain the current type of the outer
|
||||
// facet type `I where...`. We should not consider the designator in the nested
|
||||
// where expression as making the `(I where ...) impls ...` constraint valid.
|
||||
|
||||
// CHECK:STDERR: fail_impls_with_nested_facet_type_does_not_constrain_self.carbon:[[@LINE+4]]:28: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn F(unused T:! type where (I where .I1 impls J(.Self)) impls I) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(unused T:! type where (I where .I1 impls J(.Self)) impls I) {}
|
||||
|
||||
// --- fail_where_without_designator_in_one_equiv_constraint.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
@@ -304,51 +168,107 @@ interface Z {
|
||||
// CHECK:STDERR:
|
||||
fn G(unused T:! Z where A(.Z0) == B and A(B) == B) {}
|
||||
|
||||
// --- fail_where_without_designator_in_one_impls_interface.carbon
|
||||
// --- fail_where_without_self_designator_in_one_impls_interface.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z(T:! type) {}
|
||||
interface I {}
|
||||
interface J(T:! type) {}
|
||||
class C;
|
||||
|
||||
// CHECK:STDERR: fail_where_without_designator_in_one_impls_interface.carbon:[[@LINE+4]]:28: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fail_where_without_self_designator_in_one_impls_interface.carbon:[[@LINE+4]]:28: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn F(unused T:! type where C impls (I & J(.Self))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(unused T:! type where C impls (I & J(.Self))) {}
|
||||
|
||||
interface Z {
|
||||
let Z0:! type;
|
||||
}
|
||||
|
||||
// CHECK:STDERR: fail_where_without_designator_in_one_impls_interface.carbon:[[@LINE+4]]:25: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn G(unused T:! Z where C impls (I & J(.Z0))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn G(unused T:! Z where C impls (I & J(.Z0))) {}
|
||||
|
||||
// --- fail_where_without_designator_in_one_impls_named_constraint.carbon
|
||||
// --- fail_where_without_member_designator_in_one_impls_interface.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
constraint I {}
|
||||
constraint J(T:! type) {}
|
||||
interface Z {
|
||||
let Z0:! type;
|
||||
}
|
||||
interface I {}
|
||||
interface J(T:! type) {}
|
||||
class C;
|
||||
|
||||
// CHECK:STDERR: fail_where_without_designator_in_one_impls_named_constraint.carbon:[[@LINE+4]]:28: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn F(unused T:! type where C impls (I & J(.Self))) {}
|
||||
// CHECK:STDERR: fail_where_without_member_designator_in_one_impls_interface.carbon:[[@LINE+4]]:25: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn F(unused T:! Z where C impls (I & J(.Z0))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(unused T:! Z where C impls (I & J(.Z0))) {}
|
||||
|
||||
// --- fail_where_without_self_designator_in_one_impls_named_constraint.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z {}
|
||||
constraint I {}
|
||||
interface J(T:! type) {}
|
||||
constraint K(T:! type) {
|
||||
require T impls J(Self);
|
||||
}
|
||||
class C;
|
||||
|
||||
// CHECK:STDERR: fail_where_without_self_designator_in_one_impls_named_constraint.carbon:[[@LINE+4]]:28: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn F(unused T:! type where C impls (I & K(.Self))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(unused T:! type where C impls (I & J(.Self))) {}
|
||||
fn F(unused T:! type where C impls (I & K(.Self))) {}
|
||||
|
||||
// --- fail_where_without_member_designator_in_one_impls_named_constraint.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z {
|
||||
let Z0:! type;
|
||||
}
|
||||
constraint I {}
|
||||
interface J(T:! type) {}
|
||||
constraint K(T:! type) {
|
||||
require T impls J(Self);
|
||||
}
|
||||
class C;
|
||||
|
||||
// CHECK:STDERR: fail_where_without_designator_in_one_impls_named_constraint.carbon:[[@LINE+4]]:25: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn G(unused T:! Z where C impls (I & J(.Z0))) {}
|
||||
|
||||
// CHECK:STDERR: fail_where_without_member_designator_in_one_impls_named_constraint.carbon:[[@LINE+4]]:25: error: constraint in `where` clause without a designator; expected `.Self` or a member access like `.M` [WhereWithoutDesignator]
|
||||
// CHECK:STDERR: fn F(unused T:! Z where C impls (I & K(.Z0))) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn G(unused T:! Z where C impls (I & J(.Z0))) {}
|
||||
fn F(unused T:! Z where C impls (I & K(.Z0))) {}
|
||||
|
||||
// --- constraint_does_constrain_designator_as_self.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z(T:! type) {}
|
||||
constraint N(T:! type) {
|
||||
require T impls Z(Self);
|
||||
}
|
||||
class C;
|
||||
|
||||
fn F(unused T:! type where C impls N(.Self)) {}
|
||||
|
||||
// --- constraint_does_constrain_designator_as_specific.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z(T:! type) {}
|
||||
constraint N(T:! type) {
|
||||
require impls Z(T);
|
||||
}
|
||||
class C;
|
||||
|
||||
fn F(unused T:! type where C impls N(.Self)) {}
|
||||
|
||||
// --- todo_fail_constraint_does_not_constrain_designator.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface Z {}
|
||||
constraint N(T:! type) {
|
||||
require impls Z;
|
||||
}
|
||||
class C;
|
||||
|
||||
// TODO: This `.Self` is not actually constrained by `C impls N(.Self)`, so it
|
||||
// should fail.
|
||||
fn F(unused T:! type where C impls N(.Self)) {}
|
||||
|
||||
// CHECK:STDOUT: --- success.carbon
|
||||
// CHECK:STDOUT:
|
||||
|
||||
+64
-21
@@ -162,19 +162,13 @@ fn Test() {
|
||||
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
|
||||
// --- fail_todo_compare_equal_with_rewrite.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class WrapType(T:! type) {}
|
||||
@@ -182,19 +176,48 @@ fn AssertSame[T:! type](unused a: WrapType(T), unused b: WrapType(T)) {}
|
||||
fn Type(T:! type) -> WrapType(T) { return {}; }
|
||||
|
||||
interface I { let A:! type; }
|
||||
interface J { let A:! type; }
|
||||
interface J { let B:! type; }
|
||||
|
||||
// TODO: The `.Self` implied in `.A` contains all of the extended interfaces,
|
||||
// which is different between these facet types at the point where `.A` is
|
||||
// written. So the resulting facet types are different. We should drop
|
||||
// interfaces from the rewrite constraint's LHS that don't apply so that we get
|
||||
// a canonical representation of `.A` that is independent of the current state
|
||||
// of `.Self` since `.A = ()` can not be written as, and is thus not equivalent
|
||||
// to, `.Self.(I.A) = ()`.
|
||||
|
||||
fn Test() {
|
||||
// TODO: This should pass.
|
||||
// CHECK:STDERR: fail_todo_compare_equal_with_rewrite.carbon:[[@LINE+7]]:3: error: inconsistent deductions for value of generic parameter `T` [DeductionInconsistent]
|
||||
// CHECK:STDERR: AssertSame(Type((I where .A = ()) & J),
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_compare_equal_with_rewrite.carbon:[[@LINE-19]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
|
||||
// CHECK:STDERR: fn AssertSame[T:! type](unused a: WrapType(T), unused b: WrapType(T)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
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 = {})));
|
||||
Type(I & J where .A = ()));
|
||||
// TODO: This should pass.
|
||||
// CHECK:STDERR: fail_todo_compare_equal_with_rewrite.carbon:[[@LINE+7]]:3: error: inconsistent deductions for value of generic parameter `T` [DeductionInconsistent]
|
||||
// CHECK:STDERR: AssertSame(Type(I & (J where .B = {})),
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_compare_equal_with_rewrite.carbon:[[@LINE-29]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
|
||||
// CHECK:STDERR: fn AssertSame[T:! type](unused a: WrapType(T), unused b: WrapType(T)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
AssertSame(Type(I & (J where .B = {})),
|
||||
Type(I & J where .B = {}));
|
||||
|
||||
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 = {})));
|
||||
// TODO: This should pass.
|
||||
// CHECK:STDERR: fail_todo_compare_equal_with_rewrite.carbon:[[@LINE+7]]:3: error: inconsistent deductions for value of generic parameter `T` [DeductionInconsistent]
|
||||
// CHECK:STDERR: AssertSame(Type((I where .A = ()) & (J where .B = {})),
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_compare_equal_with_rewrite.carbon:[[@LINE-40]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
|
||||
// CHECK:STDERR: fn AssertSame[T:! type](unused a: WrapType(T), unused b: WrapType(T)) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
AssertSame(Type((I where .A = ()) & (J where .B = {})),
|
||||
Type(I & J where .A = () and .B = {}));
|
||||
}
|
||||
|
||||
// --- fail_compare_not_equal.carbon
|
||||
@@ -218,6 +241,25 @@ fn Test() {
|
||||
Same(Type(I where .Self impls J), Type(J where .Self impls I));
|
||||
}
|
||||
|
||||
// --- todo_fail_compare_not_equal_with_same_type.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class WrapType(T:! type) {}
|
||||
fn Same[T:! type](unused a: WrapType(T), unused b: WrapType(T)) {}
|
||||
fn Type(T:! type) -> WrapType(T) { return {}; }
|
||||
|
||||
interface I { let A:! type; }
|
||||
interface J { let B:! type; }
|
||||
|
||||
fn Test() {
|
||||
// The first `.A` has a `.Self` of type `I`. The second contains a `.Self` of
|
||||
// type `I & J`. That makes the two constaints `.A == ()` have different
|
||||
// constant values, so these are different facet types.
|
||||
//
|
||||
// TODO: This should fail. We don't store same-type constraints in the facet type yet.
|
||||
Same(Type((I where .A == ()) & J), Type(I & J where .A == ()));
|
||||
}
|
||||
|
||||
// --- impl_as.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
@@ -233,9 +275,6 @@ interface J { let T:! type; }
|
||||
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]]";
|
||||
|
||||
@@ -247,12 +286,16 @@ class C {}
|
||||
// Implementation of `C as J`.
|
||||
impl C as J where .A = {} {}
|
||||
|
||||
// Requirement of implementing J with `.A = A`.
|
||||
constraint NeedJ(A:! type) {
|
||||
require impls J where .A = 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 = ())) {}
|
||||
impl C as I where .A = () and .Self impls NeedJ({}) {}
|
||||
|
||||
let x: C.(I.A) = ();
|
||||
let y: C.(J.A) = {};
|
||||
|
||||
@@ -192,7 +192,8 @@ CARBON_DIAGNOSTIC_KIND(ExpectedAliasInitializer)
|
||||
// Where requirement diagnostics.
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedRequirementOperator)
|
||||
CARBON_DIAGNOSTIC_KIND(RequirementEqualAfterNonDesignator)
|
||||
CARBON_DIAGNOSTIC_KIND(AmbiguousPeriodSelf)
|
||||
CARBON_DIAGNOSTIC_KIND(NestedWhereInsideWhere)
|
||||
CARBON_DIAGNOSTIC_KIND(NestedWhereInsideWhereOuterNote)
|
||||
|
||||
// ============================================================================
|
||||
// Semantics diagnostics
|
||||
|
||||
Reference in New Issue
Block a user