Facet member access (#4371)

Adds `FacetAccessWitness` instruction and uses it in `member_access.cpp`
to support accessing members of facets. Still to do: interface witness
access is producing runtime values when it should produce symbolic
values.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
This commit is contained in:
josh11b
2024-11-26 01:12:46 +00:00
committed by GitHub
co-authored by Josh L
parent 0b209c3fbc
commit ed80cd2f15
12 changed files with 309 additions and 142 deletions
+15 -1
View File
@@ -1627,7 +1627,21 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
return MakeNonConstantResult(phase);
}
}
case CARBON_KIND(SemIR::FacetAccessWitness typed_inst): {
Phase phase = Phase::Template;
if (ReplaceFieldWithConstantValue(
eval_context, &typed_inst,
&SemIR::FacetAccessWitness::facet_value_inst_id, &phase)) {
if (auto facet_value = eval_context.insts().TryGetAs<SemIR::FacetValue>(
typed_inst.facet_value_inst_id)) {
return eval_context.constant_values().Get(
facet_value->witness_inst_id);
}
return MakeConstantResult(eval_context.context(), typed_inst, phase);
} else {
return MakeNonConstantResult(phase);
}
}
case CARBON_KIND(SemIR::WhereExpr typed_inst): {
Phase phase = Phase::Template;
SemIR::TypeId base_facet_type_id =
+110 -36
View File
@@ -124,6 +124,46 @@ static auto ScopeNeedsImplLookup(Context& context,
return true;
}
static auto GetInterfaceFromFacetType(Context& context, SemIR::TypeId type_id)
-> std::optional<SemIR::FacetTypeInfo::ImplsConstraint> {
auto facet_type = context.types().GetAs<SemIR::FacetType>(type_id);
const auto& facet_type_info =
context.facet_types().Get(facet_type.facet_type_id);
return facet_type_info.TryAsSingleInterface();
}
static auto AccessMemberOfInterfaceWitness(
Context& context, SemIR::LocId loc_id, SemIR::InstId witness_id,
SemIR::SpecificId interface_specific_id,
SemIR::AssociatedEntityType assoc_type, SemIR::InstId member_id)
-> SemIR::InstId {
auto member_value_id = context.constant_values().GetConstantInstId(member_id);
if (!member_value_id.is_valid()) {
if (member_value_id != SemIR::InstId::BuiltinErrorInst) {
context.TODO(member_id, "non-constant associated entity");
}
return SemIR::InstId::BuiltinErrorInst;
}
auto assoc_entity =
context.insts().TryGetAs<SemIR::AssociatedEntity>(member_value_id);
if (!assoc_entity) {
context.TODO(member_id, "unexpected value for associated entity");
return SemIR::InstId::BuiltinErrorInst;
}
// TODO: This produces the type of the associated entity with no value for
// `Self`. The type `Self` might appear in the type of an associated constant,
// and if so, we'll need to substitute it here somehow.
auto subst_type_id = SemIR::GetTypeInSpecific(
context.sem_ir(), interface_specific_id, assoc_type.entity_type_id);
return context.GetOrAddInst<SemIR::InterfaceWitnessAccess>(
loc_id, {.type_id = subst_type_id,
.witness_id = witness_id,
.index = assoc_entity->index});
}
// Performs impl lookup for a member name expression. This finds the relevant
// impl witness and extracts the corresponding impl member.
static auto PerformImplLookup(
@@ -131,11 +171,8 @@ static auto PerformImplLookup(
SemIR::AssociatedEntityType assoc_type, SemIR::InstId member_id,
Context::BuildDiagnosticFn missing_impl_diagnoser = nullptr)
-> SemIR::InstId {
auto facet_type =
context.types().GetAs<SemIR::FacetType>(assoc_type.interface_type_id);
const auto& facet_type_info =
context.facet_types().Get(facet_type.facet_type_id);
auto interface_type = facet_type_info.TryAsSingleInterface();
auto interface_type =
GetInterfaceFromFacetType(context, assoc_type.interface_type_id);
if (!interface_type) {
context.TODO(loc_id,
"Lookup of impl witness not yet supported except for a single "
@@ -170,42 +207,20 @@ static auto PerformImplLookup(
}
return SemIR::InstId::BuiltinErrorInst;
}
auto member_value_id = context.constant_values().GetConstantInstId(member_id);
if (!member_value_id.is_valid()) {
if (member_value_id != SemIR::InstId::BuiltinErrorInst) {
context.TODO(member_id, "non-constant associated entity");
}
return SemIR::InstId::BuiltinErrorInst;
}
auto assoc_entity =
context.insts().TryGetAs<SemIR::AssociatedEntity>(member_value_id);
if (!assoc_entity) {
context.TODO(member_id, "unexpected value for associated entity");
return SemIR::InstId::BuiltinErrorInst;
}
// TODO: This produces the type of the associated entity with no value for
// `Self`. The type `Self` might appear in the type of an associated constant,
// and if so, we'll need to substitute it here somehow.
auto subst_type_id = SemIR::GetTypeInSpecific(
context.sem_ir(), interface_type->specific_id, assoc_type.entity_type_id);
return context.GetOrAddInst<SemIR::InterfaceWitnessAccess>(
loc_id, {.type_id = subst_type_id,
.witness_id = witness_id,
.index = assoc_entity->index});
return AccessMemberOfInterfaceWitness(context, loc_id, witness_id,
interface_type->specific_id, assoc_type,
member_id);
}
// Performs a member name lookup into the specified scope, including performing
// impl lookup if necessary. If the scope is invalid, assume an error has
// already been diagnosed, and return BuiltinErrorInst.
static auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id,
SemIR::InstId /*base_id*/,
SemIR::InstId base_id,
SemIR::NameId name_id,
SemIR::ConstantId name_scope_const_id,
llvm::ArrayRef<LookupScope> lookup_scopes)
llvm::ArrayRef<LookupScope> lookup_scopes,
bool lookup_in_type_of_base)
-> SemIR::InstId {
AccessInfo access_info = {
.constant_id = name_scope_const_id,
@@ -250,7 +265,64 @@ static auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id,
// impl member is not supposed to be treated as ambiguous.
if (auto assoc_type =
context.types().TryGetAs<SemIR::AssociatedEntityType>(type_id)) {
if (ScopeNeedsImplLookup(context, name_scope_const_id)) {
if (lookup_in_type_of_base) {
SemIR::TypeId base_type_id = context.insts().Get(base_id).type_id();
if (base_type_id != SemIR::TypeId::TypeType &&
context.IsFacetType(base_type_id)) {
// Handles `T.F` when `T` is a non-type facet.
auto assoc_interface =
GetInterfaceFromFacetType(context, assoc_type->interface_type_id);
// An associated entity should always be associated with a single
// interface.
CARBON_CHECK(assoc_interface);
// First look for `*assoc_interface` in the type of the base. If it is
// found, get the witness that the interface is implemented from
// `base_id`.
auto facet_type = context.types().GetAs<SemIR::FacetType>(base_type_id);
const auto& facet_type_info =
context.facet_types().Get(facet_type.facet_type_id);
// Witness that `T` implements the `*assoc_interface`.
SemIR::InstId witness_inst_id = SemIR::InstId::Invalid;
for (auto base_interface : facet_type_info.impls_constraints) {
// Get the witness that `T` implements `base_type_id`.
if (base_interface == *assoc_interface) {
witness_inst_id = context.GetOrAddInst<SemIR::FacetAccessWitness>(
loc_id, {.type_id = context.GetBuiltinType(
SemIR::BuiltinInstKind::WitnessType),
.facet_value_inst_id = base_id});
// TODO: Result will eventually be a facet type witness instead of
// an interface witness. Will need to use the index
// `*assoc_interface` was found in
// `facet_type_info.impls_constraints` to get the correct interface
// witness out.
break;
}
}
// TODO: If that fails, would need to do impl lookup to see if the facet
// value implements the interface of `*assoc_type`.
if (!witness_inst_id.is_valid()) {
context.TODO(member_id,
"associated entity not found in facet type, need to do "
"impl lookup");
return SemIR::InstId::BuiltinErrorInst;
}
member_id = AccessMemberOfInterfaceWitness(
context, loc_id, witness_inst_id, assoc_interface->specific_id,
*assoc_type, member_id);
} else {
// Handles `x.F` if `x` is of type `class C` that extends an interface
// containing `F`.
SemIR::ConstantId constant_id =
context.types().GetConstantId(base_type_id);
member_id = PerformImplLookup(context, loc_id, constant_id, *assoc_type,
member_id);
}
} else if (ScopeNeedsImplLookup(context, name_scope_const_id)) {
// Handles `T.F` where `T` is a type extending an interface containing
// `F`.
member_id = PerformImplLookup(context, loc_id, name_scope_const_id,
*assoc_type, member_id);
}
@@ -342,7 +414,8 @@ auto PerformMemberAccess(Context& context, SemIR::LocId loc_id,
if (context.AppendLookupScopesForConstant(loc_id, base_const_id,
&lookup_scopes)) {
return LookupMemberNameInScope(context, loc_id, base_id, name_id,
base_const_id, lookup_scopes);
base_const_id, lookup_scopes,
/*lookup_in_type_of_base=*/false);
}
}
@@ -401,7 +474,8 @@ auto PerformMemberAccess(Context& context, SemIR::LocId loc_id,
// Perform lookup into the base type.
auto member_id = LookupMemberNameInScope(context, loc_id, base_id, name_id,
base_type_const_id, lookup_scopes);
base_type_const_id, lookup_scopes,
/*lookup_in_type_of_base=*/true);
// Perform instance binding if we found an instance member.
member_id = PerformInstanceBinding(context, loc_id, base_id, member_id);
@@ -10,35 +10,28 @@
interface I { let T:! type; }
// CHECK:STDERR: fail_todo_impl_assoc_const.carbon:[[@LINE+10]]:1: error: semantics TODO: `impl of interface with associated constant` [SemanticsTodo]
// CHECK:STDERR: fail_todo_impl_assoc_const.carbon:[[@LINE+3]]:1: error: semantics TODO: `impl of interface with associated constant` [SemanticsTodo]
// CHECK:STDERR: impl bool as I where .T = bool {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_todo_impl_assoc_const.carbon:[[@LINE+6]]:27: error: cannot implicitly convert from `type` to `<associated type in I>` [ImplicitAsConversionFailure]
// CHECK:STDERR: impl bool as I where .T = bool {}
// CHECK:STDERR: ^~~~
// CHECK:STDERR: fail_todo_impl_assoc_const.carbon:[[@LINE+3]]:27: note: type `type` does not implement interface `ImplicitAs(<associated type in I>)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: impl bool as I where .T = bool {}
// CHECK:STDERR: ^~~~
impl bool as I where .T = bool {}
// CHECK:STDOUT: --- fail_todo_impl_assoc_const.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %I.type.1: type = facet_type <@I> [template]
// CHECK:STDOUT: %Self.1: %I.type.1 = bind_symbolic_name Self, 0 [symbolic]
// CHECK:STDOUT: %Self: %I.type.1 = bind_symbolic_name Self, 0 [symbolic]
// CHECK:STDOUT: %.1: type = assoc_entity_type %I.type.1, type [template]
// CHECK:STDOUT: %.2: %.1 = assoc_entity element0, @I.%T [template]
// CHECK:STDOUT: %Bool.type: type = fn_type @Bool [template]
// CHECK:STDOUT: %Bool: %Bool.type = struct_value () [template]
// CHECK:STDOUT: %.Self: %I.type.1 = bind_symbolic_name .Self, 0 [symbolic]
// CHECK:STDOUT: %.3: <witness> = facet_access_witness %.Self [symbolic]
// CHECK:STDOUT: %I.type.2: type = facet_type <@I where TODO> [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .Bool = %import_ref.1
// CHECK:STDOUT: .ImplicitAs = %import_ref.2
// CHECK:STDOUT: .Bool = %import_ref
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
@@ -51,24 +44,27 @@ impl bool as I where .T = bool {}
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%I.type.1] {} {}
// CHECK:STDOUT: impl_decl @impl.9 [template] {} {
// CHECK:STDOUT: %bool.make_type.loc23_6: init type = call constants.%Bool() [template = bool]
// CHECK:STDOUT: %.loc23_6.1: type = value_of_initializer %bool.make_type.loc23_6 [template = bool]
// CHECK:STDOUT: %.loc23_6.2: type = converted %bool.make_type.loc23_6, %.loc23_6.1 [template = bool]
// CHECK:STDOUT: impl_decl @impl [template] {} {
// CHECK:STDOUT: %bool.make_type.loc16_6: init type = call constants.%Bool() [template = bool]
// CHECK:STDOUT: %.loc16_6.1: type = value_of_initializer %bool.make_type.loc16_6 [template = bool]
// CHECK:STDOUT: %.loc16_6.2: type = converted %bool.make_type.loc16_6, %.loc16_6.1 [template = bool]
// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%I.type.1]
// CHECK:STDOUT: %.Self: %I.type.1 = bind_symbolic_name .Self, 0 [symbolic = constants.%.Self]
// CHECK:STDOUT: %.Self.ref: %I.type.1 = name_ref .Self, %.Self [symbolic = constants.%.Self]
// CHECK:STDOUT: %T.ref: %.1 = name_ref T, @I.%.loc11 [template = constants.%.2]
// CHECK:STDOUT: %bool.make_type.loc23_27: init type = call constants.%Bool() [template = bool]
// CHECK:STDOUT: %.loc23_27: %.1 = converted %bool.make_type.loc23_27, <error> [template = <error>]
// CHECK:STDOUT: %.loc23_16: type = where_expr %.Self [template = constants.%I.type.2] {
// CHECK:STDOUT: requirement_rewrite %T.ref, <error>
// CHECK:STDOUT: %.loc16_22.1: <witness> = facet_access_witness %.Self.ref [symbolic = constants.%.3]
// CHECK:STDOUT: %.loc16_22.2: type = interface_witness_access %.loc16_22.1, element0
// CHECK:STDOUT: %bool.make_type.loc16_27: init type = call constants.%Bool() [template = bool]
// CHECK:STDOUT: %.loc16_27.1: type = value_of_initializer %bool.make_type.loc16_27 [template = bool]
// CHECK:STDOUT: %.loc16_27.2: type = converted %bool.make_type.loc16_27, %.loc16_27.1 [template = bool]
// CHECK:STDOUT: %.loc16_16: type = where_expr %.Self [template = constants.%I.type.2] {
// CHECK:STDOUT: requirement_rewrite %.loc16_22.2, %.loc16_27.2
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @I {
// CHECK:STDOUT: %Self: %I.type.1 = bind_symbolic_name Self, 0 [symbolic = constants.%Self.1]
// CHECK:STDOUT: %Self: %I.type.1 = bind_symbolic_name Self, 0 [symbolic = constants.%Self]
// CHECK:STDOUT: %T: type = assoc_const_decl T [template]
// CHECK:STDOUT: %.loc11: %.1 = assoc_entity element0, %T [template = constants.%.2]
// CHECK:STDOUT:
@@ -78,7 +74,7 @@ impl bool as I where .T = bool {}
// CHECK:STDOUT: witness = (%T)
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: impl @impl.9: %.loc23_6.2 as %.loc23_16 {
// CHECK:STDOUT: impl @impl: %.loc16_6.2 as %.loc16_16 {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: witness = <error>
// CHECK:STDOUT: }
@@ -21,17 +21,25 @@ fn F() {
// CHECK:STDERR:
Interface.F();
// CHECK:STDERR: fail_member_lookup.carbon:[[@LINE+3]]:10: error: `Core.ImplicitAs` implicitly referenced here, but package `Core` not found [CoreNotFound]
// CHECK:STDERR: fail_member_lookup.carbon:[[@LINE+4]]:10: error: `Core.ImplicitAs` implicitly referenced here, but package `Core` not found [CoreNotFound]
// CHECK:STDERR: var v: Interface.T;
// CHECK:STDERR: ^~~~~~~~~~~
// CHECK:STDERR:
var v: Interface.T;
}
interface Different {}
// CHECK:STDERR: fail_member_lookup.carbon:[[@LINE+3]]:24: error: cannot access member of interface `Interface` in type `Different` that does not implement that interface [MissingImplInMemberAccess]
// CHECK:STDERR: fn G(U:! Different) -> U.(Interface.T);
// CHECK:STDERR: ^~~~~~~~~~~~~~~
fn G(U:! Different) -> U.(Interface.T);
// CHECK:STDOUT: --- fail_member_lookup.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Interface.type: type = facet_type <@Interface> [template]
// CHECK:STDOUT: %Self: %Interface.type = bind_symbolic_name Self, 0 [symbolic]
// CHECK:STDOUT: %Self.1: %Interface.type = bind_symbolic_name Self, 0 [symbolic]
// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template]
// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template]
// CHECK:STDOUT: %.1: type = assoc_entity_type %Interface.type, %F.type.1 [template]
@@ -40,19 +48,43 @@ fn F() {
// CHECK:STDOUT: %.4: %.3 = assoc_entity element1, @Interface.%T [template]
// CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template]
// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template]
// CHECK:STDOUT: %Different.type: type = facet_type <@Different> [template]
// CHECK:STDOUT: %Self.2: %Different.type = bind_symbolic_name Self, 0 [symbolic]
// CHECK:STDOUT: %U: %Different.type = bind_symbolic_name U, 0 [symbolic]
// CHECK:STDOUT: %U.patt: %Different.type = symbolic_binding_pattern U, 0 [symbolic]
// CHECK:STDOUT: %G.type: type = fn_type @G [template]
// CHECK:STDOUT: %G: %G.type = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Interface = %Interface.decl
// CHECK:STDOUT: .F = %F.decl
// CHECK:STDOUT: .Different = %Different.decl
// CHECK:STDOUT: .G = %G.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Interface.decl: type = interface_decl @Interface [template = constants.%Interface.type] {} {}
// CHECK:STDOUT: %F.decl: %F.type.2 = fn_decl @F.2 [template = constants.%F.2] {} {}
// CHECK:STDOUT: %Different.decl: type = interface_decl @Different [template = constants.%Different.type] {} {}
// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] {
// CHECK:STDOUT: %U.patt.loc36_6.1: %Different.type = symbolic_binding_pattern U, 0 [symbolic = %U.patt.loc36_6.2 (constants.%U.patt)]
// CHECK:STDOUT: %U.param_patt: %Different.type = value_param_pattern %U.patt.loc36_6.1, runtime_param<invalid> [symbolic = %U.patt.loc36_6.2 (constants.%U.patt)]
// CHECK:STDOUT: %return.patt: <error> = return_slot_pattern
// CHECK:STDOUT: %return.param_patt: <error> = out_param_pattern %return.patt, runtime_param0
// CHECK:STDOUT: } {
// CHECK:STDOUT: %Different.ref: type = name_ref Different, file.%Different.decl [template = constants.%Different.type]
// CHECK:STDOUT: %U.ref: %Different.type = name_ref U, %U.loc36_6.1 [symbolic = %U.loc36_6.2 (constants.%U)]
// CHECK:STDOUT: %Interface.ref: type = name_ref Interface, file.%Interface.decl [template = constants.%Interface.type]
// CHECK:STDOUT: %T.ref: %.3 = name_ref T, @Interface.%.loc14 [template = constants.%.4]
// CHECK:STDOUT: %U.param: %Different.type = value_param runtime_param<invalid>
// CHECK:STDOUT: %U.loc36_6.1: %Different.type = bind_symbolic_name U, 0, %U.param [symbolic = %U.loc36_6.2 (constants.%U)]
// CHECK:STDOUT: %return.param: ref <error> = out_param runtime_param0
// CHECK:STDOUT: %return: ref <error> = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @Interface {
// CHECK:STDOUT: %Self: %Interface.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self]
// CHECK:STDOUT: %Self: %Interface.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.1]
// CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] {} {}
// CHECK:STDOUT: %.loc12: %.1 = assoc_entity element0, %F.decl [template = constants.%.2]
// CHECK:STDOUT: %T: type = assoc_const_decl T [template]
@@ -65,6 +97,14 @@ fn F() {
// CHECK:STDOUT: witness = (%F.decl, %T)
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @Different {
// CHECK:STDOUT: %Self: %Different.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.2]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = %Self
// CHECK:STDOUT: witness = ()
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @F.1(@Interface.%Self: %Interface.type) {
// CHECK:STDOUT:
// CHECK:STDOUT: fn();
@@ -74,13 +114,25 @@ fn F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Interface.ref.loc22: type = name_ref Interface, file.%Interface.decl [template = constants.%Interface.type]
// CHECK:STDOUT: %F.ref: %.1 = name_ref F, @Interface.%.loc12 [template = constants.%.2]
// CHECK:STDOUT: %Interface.ref.loc27: type = name_ref Interface, file.%Interface.decl [template = constants.%Interface.type]
// CHECK:STDOUT: %Interface.ref.loc28: type = name_ref Interface, file.%Interface.decl [template = constants.%Interface.type]
// CHECK:STDOUT: %T.ref: %.3 = name_ref T, @Interface.%.loc14 [template = constants.%.4]
// CHECK:STDOUT: %.loc27: type = converted %T.ref, <error> [template = <error>]
// CHECK:STDOUT: %.loc28: type = converted %T.ref, <error> [template = <error>]
// CHECK:STDOUT: %v.var: ref <error> = var v
// CHECK:STDOUT: %v: ref <error> = bind_name v, %v.var
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @F.1(constants.%Self) {}
// CHECK:STDOUT: generic fn @G(%U.loc36_6.1: %Different.type) {
// CHECK:STDOUT: %U.loc36_6.2: %Different.type = bind_symbolic_name U, 0 [symbolic = %U.loc36_6.2 (constants.%U)]
// CHECK:STDOUT: %U.patt.loc36_6.2: %Different.type = symbolic_binding_pattern U, 0 [symbolic = %U.patt.loc36_6.2 (constants.%U.patt)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%U.param_patt: %Different.type) -> <error>;
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @F.1(constants.%Self.1) {}
// CHECK:STDOUT:
// CHECK:STDOUT: specific @G(constants.%U) {
// CHECK:STDOUT: %U.loc36_6.2 => constants.%U
// CHECK:STDOUT: %U.patt.loc36_6.2 => constants.%U
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -11,7 +11,7 @@
interface Interface { fn F(); }
fn CallStatic(T:! Interface) {
// CHECK:STDERR: fail_todo_facet_lookup.carbon:[[@LINE+4]]:3: error: value of type `<associated <type of F> in Interface>` is not callable [CallToNonCallable]
// CHECK:STDERR: fail_todo_facet_lookup.carbon:[[@LINE+4]]:3: error: value of type `<type of F>` is not callable [CallToNonCallable]
// CHECK:STDERR: T.F();
// CHECK:STDERR: ^~~~
// CHECK:STDERR:
@@ -38,7 +38,8 @@ fn CallFacet(T:! Interface, x: T) {
// CHECK:STDOUT: %T.patt: %Interface.type = symbolic_binding_pattern T, 0 [symbolic]
// CHECK:STDOUT: %CallStatic.type: type = fn_type @CallStatic [template]
// CHECK:STDOUT: %CallStatic: %CallStatic.type = struct_value () [template]
// CHECK:STDOUT: %.3: type = facet_access_type %T [symbolic]
// CHECK:STDOUT: %.3: <witness> = facet_access_witness %T [symbolic]
// CHECK:STDOUT: %.4: type = facet_access_type %T [symbolic]
// CHECK:STDOUT: %CallFacet.type: type = fn_type @CallFacet [template]
// CHECK:STDOUT: %CallFacet: %CallFacet.type = struct_value () [template]
// CHECK:STDOUT: }
@@ -61,17 +62,17 @@ fn CallFacet(T:! Interface, x: T) {
// CHECK:STDOUT: %CallFacet.decl: %CallFacet.type = fn_decl @CallFacet [template = constants.%CallFacet] {
// CHECK:STDOUT: %T.patt.loc21_14.1: %Interface.type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc21_14.2 (constants.%T.patt)]
// CHECK:STDOUT: %T.param_patt: %Interface.type = value_param_pattern %T.patt.loc21_14.1, runtime_param<invalid> [symbolic = %T.patt.loc21_14.2 (constants.%T.patt)]
// CHECK:STDOUT: %x.patt: @CallFacet.%.loc21_32.3 (%.3) = binding_pattern x
// CHECK:STDOUT: %x.param_patt: @CallFacet.%.loc21_32.3 (%.3) = value_param_pattern %x.patt, runtime_param0
// CHECK:STDOUT: %x.patt: @CallFacet.%.loc21_32.3 (%.4) = binding_pattern x
// CHECK:STDOUT: %x.param_patt: @CallFacet.%.loc21_32.3 (%.4) = value_param_pattern %x.patt, runtime_param0
// CHECK:STDOUT: } {
// CHECK:STDOUT: %Interface.ref: type = name_ref Interface, file.%Interface.decl [template = constants.%Interface.type]
// CHECK:STDOUT: %T.ref: %Interface.type = name_ref T, %T.loc21_14.1 [symbolic = %T.loc21_14.2 (constants.%T)]
// CHECK:STDOUT: %.loc21_32.1: type = facet_access_type %T.ref [symbolic = %.loc21_32.3 (constants.%.3)]
// CHECK:STDOUT: %.loc21_32.2: type = converted %T.ref, %.loc21_32.1 [symbolic = %.loc21_32.3 (constants.%.3)]
// CHECK:STDOUT: %.loc21_32.1: type = facet_access_type %T.ref [symbolic = %.loc21_32.3 (constants.%.4)]
// CHECK:STDOUT: %.loc21_32.2: type = converted %T.ref, %.loc21_32.1 [symbolic = %.loc21_32.3 (constants.%.4)]
// CHECK:STDOUT: %T.param: %Interface.type = value_param runtime_param<invalid>
// CHECK:STDOUT: %T.loc21_14.1: %Interface.type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc21_14.2 (constants.%T)]
// CHECK:STDOUT: %x.param: @CallFacet.%.loc21_32.3 (%.3) = value_param runtime_param0
// CHECK:STDOUT: %x: @CallFacet.%.loc21_32.3 (%.3) = bind_name x, %x.param
// CHECK:STDOUT: %x.param: @CallFacet.%.loc21_32.3 (%.4) = value_param runtime_param0
// CHECK:STDOUT: %x: @CallFacet.%.loc21_32.3 (%.4) = bind_name x, %x.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -96,11 +97,14 @@ fn CallFacet(T:! Interface, x: T) {
// CHECK:STDOUT: %T.patt.loc13_15.2: %Interface.type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc13_15.2 (constants.%T.patt)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc18_4.3: <witness> = facet_access_witness %T.loc13_15.2 [symbolic = %.loc18_4.3 (constants.%.3)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%T.param_patt: %Interface.type) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %T.ref: %Interface.type = name_ref T, %T.loc13_15.1 [symbolic = %T.loc13_15.2 (constants.%T)]
// CHECK:STDOUT: %F.ref: %.1 = name_ref F, @Interface.%.loc11 [template = constants.%.2]
// CHECK:STDOUT: %.loc18_4.1: <witness> = facet_access_witness %T.ref [symbolic = %.loc18_4.3 (constants.%.3)]
// CHECK:STDOUT: %.loc18_4.2: %F.type = interface_witness_access %.loc18_4.1, element0
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: }
@@ -108,13 +112,13 @@ fn CallFacet(T:! Interface, x: T) {
// CHECK:STDOUT: generic fn @CallFacet(%T.loc21_14.1: %Interface.type) {
// CHECK:STDOUT: %T.loc21_14.2: %Interface.type = bind_symbolic_name T, 0 [symbolic = %T.loc21_14.2 (constants.%T)]
// CHECK:STDOUT: %T.patt.loc21_14.2: %Interface.type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc21_14.2 (constants.%T.patt)]
// CHECK:STDOUT: %.loc21_32.3: type = facet_access_type %T.loc21_14.2 [symbolic = %.loc21_32.3 (constants.%.3)]
// CHECK:STDOUT: %.loc21_32.3: type = facet_access_type %T.loc21_14.2 [symbolic = %.loc21_32.3 (constants.%.4)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%T.param_patt: %Interface.type, %x.param_patt: @CallFacet.%.loc21_32.3 (%.3)) {
// CHECK:STDOUT: fn(%T.param_patt: %Interface.type, %x.param_patt: @CallFacet.%.loc21_32.3 (%.4)) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %x.ref: @CallFacet.%.loc21_32.3 (%.3) = name_ref x, %x
// CHECK:STDOUT: %x.ref: @CallFacet.%.loc21_32.3 (%.4) = name_ref x, %x
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: }
@@ -129,6 +133,6 @@ fn CallFacet(T:! Interface, x: T) {
// CHECK:STDOUT: specific @CallFacet(constants.%T) {
// CHECK:STDOUT: %T.loc21_14.2 => constants.%T
// CHECK:STDOUT: %T.patt.loc21_14.2 => constants.%T
// CHECK:STDOUT: %.loc21_32.3 => constants.%.3
// CHECK:STDOUT: %.loc21_32.3 => constants.%.4
// CHECK:STDOUT: }
// CHECK:STDOUT:
+59 -60
View File
@@ -25,7 +25,7 @@ fn Impls(V:! J where .Self impls I);
fn And(W:! I where .Self impls J and .Member == ());
// --- fail_todo_equal_constraint.carbon
// --- equal_constraint.carbon
library "[[@TEST_NAME]]";
@@ -33,13 +33,6 @@ interface N {
let P:! type;
}
// CHECK:STDERR: fail_todo_equal_constraint.carbon:[[@LINE+7]]:27: error: cannot implicitly convert from `{}` to `<associated type in N>` [ImplicitAsConversionFailure]
// CHECK:STDERR: fn Equal(T:! N where .P = {});
// CHECK:STDERR: ^~
// CHECK:STDERR: fail_todo_equal_constraint.carbon:[[@LINE+4]]:27: note: type `{}` does not implement interface `ImplicitAs(<associated type in N>)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: fn Equal(T:! N where .P = {});
// CHECK:STDERR: ^~
// CHECK:STDERR:
fn Equal(T:! N where .P = {});
// --- fail_todo_associated_type_impls.carbon
@@ -53,10 +46,7 @@ interface K {
let Associated:! L;
}
// CHECK:STDERR: fail_todo_associated_type_impls.carbon:[[@LINE+7]]:36: error: cannot implicitly convert from `<associated L in K>` to `type` [ImplicitAsConversionFailure]
// CHECK:STDERR: fn AssociatedTypeImpls(W:! K where .Associated impls M);
// CHECK:STDERR: ^~~~~~~~~~~
// CHECK:STDERR: fail_todo_associated_type_impls.carbon:[[@LINE+4]]:36: note: type `<associated L in K>` does not implement interface `ImplicitAs(type)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: fail_todo_associated_type_impls.carbon:[[@LINE+4]]:36: error: cannot evaluate type expression [TypeExprEvaluationFailure]
// CHECK:STDERR: fn AssociatedTypeImpls(W:! K where .Associated impls M);
// CHECK:STDERR: ^~~~~~~~~~~
// CHECK:STDERR:
@@ -69,12 +59,10 @@ library "[[@TEST_NAME]]";
import library "state_constraints";
// `2` can't be converted to the type of `I.Member`
// TODO: The diagnostics are wrong since member access into facets isn't
// working properly yet.
// CHECK:STDERR: fail_check_rewrite_constraints.carbon:[[@LINE+7]]:46: error: cannot implicitly convert from `Core.IntLiteral` to `<associated type in I>` [ImplicitAsConversionFailure]
// CHECK:STDERR: fail_check_rewrite_constraints.carbon:[[@LINE+7]]:46: error: cannot implicitly convert from `Core.IntLiteral` to `type` [ImplicitAsConversionFailure]
// CHECK:STDERR: fn RewriteTypeMismatch(X:! I where .Member = 2);
// CHECK:STDERR: ^
// CHECK:STDERR: fail_check_rewrite_constraints.carbon:[[@LINE+4]]:46: note: type `Core.IntLiteral` does not implement interface `ImplicitAs(<associated type in I>)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: fail_check_rewrite_constraints.carbon:[[@LINE+4]]:46: note: type `Core.IntLiteral` does not implement interface `ImplicitAs(type)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: fn RewriteTypeMismatch(X:! I where .Member = 2);
// CHECK:STDERR: ^
// CHECK:STDERR:
@@ -201,6 +189,7 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT: %Impls.type: type = fn_type @Impls [template]
// CHECK:STDOUT: %Impls: %Impls.type = struct_value () [template]
// CHECK:STDOUT: %.6: type = facet_access_type %.Self.1 [symbolic]
// CHECK:STDOUT: %.7: <witness> = facet_access_witness %.Self.1 [symbolic]
// CHECK:STDOUT: %I.type.3: type = facet_type <@I where TODO> [template]
// CHECK:STDOUT: %W: %I.type.3 = bind_symbolic_name W, 0 [symbolic]
// CHECK:STDOUT: %W.patt: %I.type.3 = symbolic_binding_pattern W, 0 [symbolic]
@@ -269,10 +258,12 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT: %.loc15_20.2: type = converted %.Self.ref.loc15_20, %.loc15_20.1 [symbolic = constants.%.6]
// CHECK:STDOUT: %.Self.ref.loc15_38: %I.type.1 = name_ref .Self, %.Self [symbolic = constants.%.Self.1]
// CHECK:STDOUT: %Member.ref: %.1 = name_ref Member, @I.%.loc7 [template = constants.%.2]
// CHECK:STDOUT: %.loc15_38.1: <witness> = facet_access_witness %.Self.ref.loc15_38 [symbolic = constants.%.7]
// CHECK:STDOUT: %.loc15_38.2: type = interface_witness_access %.loc15_38.1, element0
// CHECK:STDOUT: %.loc15_50: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc15_14: type = where_expr %.Self [template = constants.%I.type.3] {
// CHECK:STDOUT: requirement_impls %.loc15_20.2, %J.ref
// CHECK:STDOUT: requirement_equivalent %Member.ref, %.loc15_50
// CHECK:STDOUT: requirement_equivalent %.loc15_38.2, %.loc15_50
// CHECK:STDOUT: }
// CHECK:STDOUT: %W.param: %I.type.3 = value_param runtime_param<invalid>
// CHECK:STDOUT: %W.loc15_8.1: %I.type.3 = bind_symbolic_name W, 0, %W.param [symbolic = %W.loc15_8.2 (constants.%W)]
@@ -338,15 +329,16 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT: %W.patt.loc15_8.2 => constants.%W
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_equal_constraint.carbon
// CHECK:STDOUT: --- equal_constraint.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %N.type.1: type = facet_type <@N> [template]
// CHECK:STDOUT: %Self.1: %N.type.1 = bind_symbolic_name Self, 0 [symbolic]
// CHECK:STDOUT: %Self: %N.type.1 = bind_symbolic_name Self, 0 [symbolic]
// CHECK:STDOUT: %.1: type = assoc_entity_type %N.type.1, type [template]
// CHECK:STDOUT: %.2: %.1 = assoc_entity element0, @N.%P [template]
// CHECK:STDOUT: %.Self: %N.type.1 = bind_symbolic_name .Self, 0 [symbolic]
// CHECK:STDOUT: %.3: type = struct_type {} [template]
// CHECK:STDOUT: %.3: <witness> = facet_access_witness %.Self [symbolic]
// CHECK:STDOUT: %.4: type = struct_type {} [template]
// CHECK:STDOUT: %N.type.2: type = facet_type <@N where TODO> [template]
// CHECK:STDOUT: %T: %N.type.2 = bind_symbolic_name T, 0 [symbolic]
// CHECK:STDOUT: %T.patt: %N.type.2 = symbolic_binding_pattern T, 0 [symbolic]
@@ -356,7 +348,6 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .ImplicitAs = %import_ref.1
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
@@ -371,25 +362,27 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %N.decl: type = interface_decl @N [template = constants.%N.type.1] {} {}
// CHECK:STDOUT: %Equal.decl: %Equal.type = fn_decl @Equal [template = constants.%Equal] {
// CHECK:STDOUT: %T.patt.loc15_10.1: %N.type.2 = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc15_10.2 (constants.%T.patt)]
// CHECK:STDOUT: %T.param_patt: %N.type.2 = value_param_pattern %T.patt.loc15_10.1, runtime_param<invalid> [symbolic = %T.patt.loc15_10.2 (constants.%T.patt)]
// CHECK:STDOUT: %T.patt.loc8_10.1: %N.type.2 = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc8_10.2 (constants.%T.patt)]
// CHECK:STDOUT: %T.param_patt: %N.type.2 = value_param_pattern %T.patt.loc8_10.1, runtime_param<invalid> [symbolic = %T.patt.loc8_10.2 (constants.%T.patt)]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %N.ref: type = name_ref N, file.%N.decl [template = constants.%N.type.1]
// CHECK:STDOUT: %.Self: %N.type.1 = bind_symbolic_name .Self, 0 [symbolic = constants.%.Self]
// CHECK:STDOUT: %.Self.ref: %N.type.1 = name_ref .Self, %.Self [symbolic = constants.%.Self]
// CHECK:STDOUT: %P.ref: %.1 = name_ref P, @N.%.loc5 [template = constants.%.2]
// CHECK:STDOUT: %.loc15_28.1: %.3 = struct_literal ()
// CHECK:STDOUT: %.loc15_28.2: %.1 = converted %.loc15_28.1, <error> [template = <error>]
// CHECK:STDOUT: %.loc15_16: type = where_expr %.Self [template = constants.%N.type.2] {
// CHECK:STDOUT: requirement_rewrite %P.ref, <error>
// CHECK:STDOUT: %.loc8_22.1: <witness> = facet_access_witness %.Self.ref [symbolic = constants.%.3]
// CHECK:STDOUT: %.loc8_22.2: type = interface_witness_access %.loc8_22.1, element0
// CHECK:STDOUT: %.loc8_28.1: %.4 = struct_literal ()
// CHECK:STDOUT: %.loc8_28.2: type = converted %.loc8_28.1, constants.%.4 [template = constants.%.4]
// CHECK:STDOUT: %.loc8_16: type = where_expr %.Self [template = constants.%N.type.2] {
// CHECK:STDOUT: requirement_rewrite %.loc8_22.2, %.loc8_28.2
// CHECK:STDOUT: }
// CHECK:STDOUT: %T.param: %N.type.2 = value_param runtime_param<invalid>
// CHECK:STDOUT: %T.loc15_10.1: %N.type.2 = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc15_10.2 (constants.%T)]
// CHECK:STDOUT: %T.loc8_10.1: %N.type.2 = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc8_10.2 (constants.%T)]
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @N {
// CHECK:STDOUT: %Self: %N.type.1 = bind_symbolic_name Self, 0 [symbolic = constants.%Self.1]
// CHECK:STDOUT: %Self: %N.type.1 = bind_symbolic_name Self, 0 [symbolic = constants.%Self]
// CHECK:STDOUT: %P: type = assoc_const_decl P [template]
// CHECK:STDOUT: %.loc5: %.1 = assoc_entity element0, %P [template = constants.%.2]
// CHECK:STDOUT:
@@ -399,16 +392,16 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT: witness = (%P)
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @Equal(%T.loc15_10.1: %N.type.2) {
// CHECK:STDOUT: %T.loc15_10.2: %N.type.2 = bind_symbolic_name T, 0 [symbolic = %T.loc15_10.2 (constants.%T)]
// CHECK:STDOUT: %T.patt.loc15_10.2: %N.type.2 = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc15_10.2 (constants.%T.patt)]
// CHECK:STDOUT: generic fn @Equal(%T.loc8_10.1: %N.type.2) {
// CHECK:STDOUT: %T.loc8_10.2: %N.type.2 = bind_symbolic_name T, 0 [symbolic = %T.loc8_10.2 (constants.%T)]
// CHECK:STDOUT: %T.patt.loc8_10.2: %N.type.2 = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc8_10.2 (constants.%T.patt)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%T.param_patt: %N.type.2);
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Equal(constants.%T) {
// CHECK:STDOUT: %T.loc15_10.2 => constants.%T
// CHECK:STDOUT: %T.patt.loc15_10.2 => constants.%T
// CHECK:STDOUT: %T.loc8_10.2 => constants.%T
// CHECK:STDOUT: %T.patt.loc8_10.2 => constants.%T
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_associated_type_impls.carbon
@@ -423,6 +416,7 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT: %.1: type = assoc_entity_type %K.type.1, %L.type [template]
// CHECK:STDOUT: %.2: %.1 = assoc_entity element0, @K.%Associated [template]
// CHECK:STDOUT: %.Self: %K.type.1 = bind_symbolic_name .Self, 0 [symbolic]
// CHECK:STDOUT: %.3: <witness> = facet_access_witness %.Self [symbolic]
// CHECK:STDOUT: %K.type.2: type = facet_type <@K where TODO> [template]
// CHECK:STDOUT: %W: %K.type.2 = bind_symbolic_name W, 0 [symbolic]
// CHECK:STDOUT: %W.patt: %K.type.2 = symbolic_binding_pattern W, 0 [symbolic]
@@ -432,7 +426,6 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .ImplicitAs = %import_ref.1
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
@@ -451,20 +444,23 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT: %M.decl: type = interface_decl @M [template = constants.%M.type] {} {}
// CHECK:STDOUT: %K.decl: type = interface_decl @K [template = constants.%K.type.1] {} {}
// CHECK:STDOUT: %AssociatedTypeImpls.decl: %AssociatedTypeImpls.type = fn_decl @AssociatedTypeImpls [template = constants.%AssociatedTypeImpls] {
// CHECK:STDOUT: %W.patt.loc18_24.1: %K.type.2 = symbolic_binding_pattern W, 0 [symbolic = %W.patt.loc18_24.2 (constants.%W.patt)]
// CHECK:STDOUT: %W.param_patt: %K.type.2 = value_param_pattern %W.patt.loc18_24.1, runtime_param<invalid> [symbolic = %W.patt.loc18_24.2 (constants.%W.patt)]
// CHECK:STDOUT: %W.patt.loc15_24.1: %K.type.2 = symbolic_binding_pattern W, 0 [symbolic = %W.patt.loc15_24.2 (constants.%W.patt)]
// CHECK:STDOUT: %W.param_patt: %K.type.2 = value_param_pattern %W.patt.loc15_24.1, runtime_param<invalid> [symbolic = %W.patt.loc15_24.2 (constants.%W.patt)]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %K.ref: type = name_ref K, file.%K.decl [template = constants.%K.type.1]
// CHECK:STDOUT: %.Self: %K.type.1 = bind_symbolic_name .Self, 0 [symbolic = constants.%.Self]
// CHECK:STDOUT: %.Self.ref: %K.type.1 = name_ref .Self, %.Self [symbolic = constants.%.Self]
// CHECK:STDOUT: %Associated.ref: %.1 = name_ref Associated, @K.%.loc8 [template = constants.%.2]
// CHECK:STDOUT: %.loc15_36.1: <witness> = facet_access_witness %.Self.ref [symbolic = constants.%.3]
// CHECK:STDOUT: %.loc15_36.2: %L.type = interface_witness_access %.loc15_36.1, element0
// CHECK:STDOUT: %M.ref: type = name_ref M, file.%M.decl [template = constants.%M.type]
// CHECK:STDOUT: %.loc18_36: type = converted %Associated.ref, <error> [template = <error>]
// CHECK:STDOUT: %.loc18_30: type = where_expr %.Self [template = constants.%K.type.2] {
// CHECK:STDOUT: %.loc15_36.3: type = facet_access_type %.loc15_36.2
// CHECK:STDOUT: %.loc15_36.4: type = converted %.loc15_36.2, %.loc15_36.3
// CHECK:STDOUT: %.loc15_30: type = where_expr %.Self [template = constants.%K.type.2] {
// CHECK:STDOUT: requirement_impls <error>, %M.ref
// CHECK:STDOUT: }
// CHECK:STDOUT: %W.param: %K.type.2 = value_param runtime_param<invalid>
// CHECK:STDOUT: %W.loc18_24.1: %K.type.2 = bind_symbolic_name W, 0, %W.param [symbolic = %W.loc18_24.2 (constants.%W)]
// CHECK:STDOUT: %W.loc15_24.1: %K.type.2 = bind_symbolic_name W, 0, %W.param [symbolic = %W.loc15_24.2 (constants.%W)]
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -496,16 +492,16 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT: witness = (%Associated)
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @AssociatedTypeImpls(%W.loc18_24.1: %K.type.2) {
// CHECK:STDOUT: %W.loc18_24.2: %K.type.2 = bind_symbolic_name W, 0 [symbolic = %W.loc18_24.2 (constants.%W)]
// CHECK:STDOUT: %W.patt.loc18_24.2: %K.type.2 = symbolic_binding_pattern W, 0 [symbolic = %W.patt.loc18_24.2 (constants.%W.patt)]
// CHECK:STDOUT: generic fn @AssociatedTypeImpls(%W.loc15_24.1: %K.type.2) {
// CHECK:STDOUT: %W.loc15_24.2: %K.type.2 = bind_symbolic_name W, 0 [symbolic = %W.loc15_24.2 (constants.%W)]
// CHECK:STDOUT: %W.patt.loc15_24.2: %K.type.2 = symbolic_binding_pattern W, 0 [symbolic = %W.patt.loc15_24.2 (constants.%W.patt)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%W.param_patt: %K.type.2);
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @AssociatedTypeImpls(constants.%W) {
// CHECK:STDOUT: %W.loc18_24.2 => constants.%W
// CHECK:STDOUT: %W.patt.loc18_24.2 => constants.%W
// CHECK:STDOUT: %W.loc15_24.2 => constants.%W
// CHECK:STDOUT: %W.patt.loc15_24.2 => constants.%W
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_check_rewrite_constraints.carbon
@@ -515,7 +511,8 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT: %.Self: %I.type.1 = bind_symbolic_name .Self, 0 [symbolic]
// CHECK:STDOUT: %.1: type = assoc_entity_type %I.type.1, type [template]
// CHECK:STDOUT: %.2: %.1 = assoc_entity element0, imports.%import_ref.11 [template]
// CHECK:STDOUT: %.3: Core.IntLiteral = int_value 2 [template]
// CHECK:STDOUT: %.3: <witness> = facet_access_witness %.Self [symbolic]
// CHECK:STDOUT: %.4: Core.IntLiteral = int_value 2 [template]
// CHECK:STDOUT: %I.type.2: type = facet_type <@I where TODO> [template]
// CHECK:STDOUT: %X: %I.type.2 = bind_symbolic_name X, 0 [symbolic]
// CHECK:STDOUT: %X.patt: %I.type.2 = symbolic_binding_pattern X, 0 [symbolic]
@@ -528,7 +525,7 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT: %import_ref.2: type = import_ref Main//state_constraints, inst+7, loaded [template = constants.%I.type.1]
// CHECK:STDOUT: %import_ref.3 = import_ref Main//state_constraints, inst+35, unloaded
// CHECK:STDOUT: %import_ref.4 = import_ref Main//state_constraints, inst+57, unloaded
// CHECK:STDOUT: %import_ref.5 = import_ref Main//state_constraints, inst+82, unloaded
// CHECK:STDOUT: %import_ref.5 = import_ref Main//state_constraints, inst+85, unloaded
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .ImplicitAs = %import_ref.12
// CHECK:STDOUT: import Core//prelude
@@ -554,20 +551,22 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %default.import = import <invalid>
// CHECK:STDOUT: %RewriteTypeMismatch.decl: %RewriteTypeMismatch.type = fn_decl @RewriteTypeMismatch [template = constants.%RewriteTypeMismatch] {
// CHECK:STDOUT: %X.patt.loc16_24.1: %I.type.2 = symbolic_binding_pattern X, 0 [symbolic = %X.patt.loc16_24.2 (constants.%X.patt)]
// CHECK:STDOUT: %X.param_patt: %I.type.2 = value_param_pattern %X.patt.loc16_24.1, runtime_param<invalid> [symbolic = %X.patt.loc16_24.2 (constants.%X.patt)]
// CHECK:STDOUT: %X.patt.loc14_24.1: %I.type.2 = symbolic_binding_pattern X, 0 [symbolic = %X.patt.loc14_24.2 (constants.%X.patt)]
// CHECK:STDOUT: %X.param_patt: %I.type.2 = value_param_pattern %X.patt.loc14_24.1, runtime_param<invalid> [symbolic = %X.patt.loc14_24.2 (constants.%X.patt)]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %I.ref: type = name_ref I, imports.%import_ref.2 [template = constants.%I.type.1]
// CHECK:STDOUT: %.Self: %I.type.1 = bind_symbolic_name .Self, 0 [symbolic = constants.%.Self]
// CHECK:STDOUT: %.Self.ref: %I.type.1 = name_ref .Self, %.Self [symbolic = constants.%.Self]
// CHECK:STDOUT: %Member.ref: %.1 = name_ref Member, imports.%import_ref.7 [template = constants.%.2]
// CHECK:STDOUT: %.loc16_46.1: Core.IntLiteral = int_value 2 [template = constants.%.3]
// CHECK:STDOUT: %.loc16_46.2: %.1 = converted %.loc16_46.1, <error> [template = <error>]
// CHECK:STDOUT: %.loc16_30: type = where_expr %.Self [template = constants.%I.type.2] {
// CHECK:STDOUT: requirement_rewrite %Member.ref, <error>
// CHECK:STDOUT: %.loc14_36.1: <witness> = facet_access_witness %.Self.ref [symbolic = constants.%.3]
// CHECK:STDOUT: %.loc14_36.2: type = interface_witness_access %.loc14_36.1, element0
// CHECK:STDOUT: %.loc14_46.1: Core.IntLiteral = int_value 2 [template = constants.%.4]
// CHECK:STDOUT: %.loc14_46.2: type = converted %.loc14_46.1, <error> [template = <error>]
// CHECK:STDOUT: %.loc14_30: type = where_expr %.Self [template = constants.%I.type.2] {
// CHECK:STDOUT: requirement_rewrite %.loc14_36.2, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT: %X.param: %I.type.2 = value_param runtime_param<invalid>
// CHECK:STDOUT: %X.loc16_24.1: %I.type.2 = bind_symbolic_name X, 0, %X.param [symbolic = %X.loc16_24.2 (constants.%X)]
// CHECK:STDOUT: %X.loc14_24.1: %I.type.2 = bind_symbolic_name X, 0, %X.param [symbolic = %X.loc14_24.2 (constants.%X)]
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -579,16 +578,16 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT: witness = (imports.%import_ref.9, imports.%import_ref.10)
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @RewriteTypeMismatch(%X.loc16_24.1: %I.type.2) {
// CHECK:STDOUT: %X.loc16_24.2: %I.type.2 = bind_symbolic_name X, 0 [symbolic = %X.loc16_24.2 (constants.%X)]
// CHECK:STDOUT: %X.patt.loc16_24.2: %I.type.2 = symbolic_binding_pattern X, 0 [symbolic = %X.patt.loc16_24.2 (constants.%X.patt)]
// CHECK:STDOUT: generic fn @RewriteTypeMismatch(%X.loc14_24.1: %I.type.2) {
// CHECK:STDOUT: %X.loc14_24.2: %I.type.2 = bind_symbolic_name X, 0 [symbolic = %X.loc14_24.2 (constants.%X)]
// CHECK:STDOUT: %X.patt.loc14_24.2: %I.type.2 = symbolic_binding_pattern X, 0 [symbolic = %X.patt.loc14_24.2 (constants.%X.patt)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%X.param_patt: %I.type.2);
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @RewriteTypeMismatch(constants.%X) {
// CHECK:STDOUT: %X.loc16_24.2 => constants.%X
// CHECK:STDOUT: %X.patt.loc16_24.2 => constants.%X
// CHECK:STDOUT: %X.loc14_24.2 => constants.%X
// CHECK:STDOUT: %X.patt.loc14_24.2 => constants.%X
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_left_of_impls_non_type.carbon
@@ -786,7 +785,7 @@ let B: type where .Self impls A = D;
// CHECK:STDOUT: %import_ref.2 = import_ref Main//state_constraints, inst+7, unloaded
// CHECK:STDOUT: %import_ref.3 = import_ref Main//state_constraints, inst+35, unloaded
// CHECK:STDOUT: %import_ref.4: %Impls.type = import_ref Main//state_constraints, inst+57, loaded [template = constants.%Impls]
// CHECK:STDOUT: %import_ref.5 = import_ref Main//state_constraints, inst+82, unloaded
// CHECK:STDOUT: %import_ref.5 = import_ref Main//state_constraints, inst+85, unloaded
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .ImplicitAs = %import_ref.7
// CHECK:STDOUT: import Core//prelude
+4 -1
View File
@@ -100,6 +100,7 @@ class D {
// CHECK:STDOUT: %T.patt: %I.type.2 = symbolic_binding_pattern T, 0 [symbolic]
// CHECK:STDOUT: %PeriodSelf.type: type = fn_type @PeriodSelf [template]
// CHECK:STDOUT: %PeriodSelf: %PeriodSelf.type = struct_value () [template]
// CHECK:STDOUT: %.3: <witness> = facet_access_witness %.Self.1 [symbolic]
// CHECK:STDOUT: %I.type.3: type = facet_type <@I where TODO> [template]
// CHECK:STDOUT: %U: %I.type.3 = bind_symbolic_name U, 0 [symbolic]
// CHECK:STDOUT: %U.patt: %I.type.3 = symbolic_binding_pattern U, 0 [symbolic]
@@ -152,9 +153,11 @@ class D {
// CHECK:STDOUT: %.Self: %I.type.1 = bind_symbolic_name .Self, 0 [symbolic = constants.%.Self.1]
// CHECK:STDOUT: %.Self.ref: %I.type.1 = name_ref .Self, %.Self [symbolic = constants.%.Self.1]
// CHECK:STDOUT: %Member.ref: %.1 = name_ref Member, @I.%.loc5 [template = constants.%.2]
// CHECK:STDOUT: %.loc10_29.1: <witness> = facet_access_witness %.Self.ref [symbolic = constants.%.3]
// CHECK:STDOUT: %.loc10_29.2: type = interface_witness_access %.loc10_29.1, element0
// CHECK:STDOUT: %.loc10_41: %empty_tuple.type = tuple_literal ()
// CHECK:STDOUT: %.loc10_23: type = where_expr %.Self [template = constants.%I.type.3] {
// CHECK:STDOUT: requirement_equivalent %Member.ref, %.loc10_41
// CHECK:STDOUT: requirement_equivalent %.loc10_29.2, %.loc10_41
// CHECK:STDOUT: }
// CHECK:STDOUT: %U.param: %I.type.3 = value_param runtime_param<invalid>
// CHECK:STDOUT: %U.loc10_17.1: %I.type.3 = bind_symbolic_name U, 0, %U.param [symbolic = %U.loc10_17.2 (constants.%U)]
+7 -4
View File
@@ -21,10 +21,11 @@ fn NotGenericF(U: I where .T == i32) {}
// CHECK:STDOUT: %.1: type = assoc_entity_type %I.type.1, type [template]
// CHECK:STDOUT: %.2: %.1 = assoc_entity element0, @I.%T [template]
// CHECK:STDOUT: %.Self: %I.type.1 = bind_symbolic_name .Self, 0 [symbolic]
// CHECK:STDOUT: %.3: Core.IntLiteral = int_value 32 [template]
// CHECK:STDOUT: %.3: <witness> = facet_access_witness %.Self [symbolic]
// CHECK:STDOUT: %.4: Core.IntLiteral = int_value 32 [template]
// CHECK:STDOUT: %Int.type: type = fn_type @Int [template]
// CHECK:STDOUT: %Int: %Int.type = struct_value () [template]
// CHECK:STDOUT: %i32: type = int_type signed, %.3 [template]
// CHECK:STDOUT: %i32: type = int_type signed, %.4 [template]
// CHECK:STDOUT: %I.type.2: type = facet_type <@I where TODO> [template]
// CHECK:STDOUT: %NotGenericF.type: type = fn_type @NotGenericF [template]
// CHECK:STDOUT: %NotGenericF: %NotGenericF.type = struct_value () [template]
@@ -54,10 +55,12 @@ fn NotGenericF(U: I where .T == i32) {}
// CHECK:STDOUT: %.Self: %I.type.1 = bind_symbolic_name .Self, 0 [symbolic = constants.%.Self]
// CHECK:STDOUT: %.Self.ref: %I.type.1 = name_ref .Self, %.Self [symbolic = constants.%.Self]
// CHECK:STDOUT: %T.ref: %.1 = name_ref T, @I.%.loc11 [template = constants.%.2]
// CHECK:STDOUT: %.loc14_33: Core.IntLiteral = int_value 32 [template = constants.%.3]
// CHECK:STDOUT: %.loc14_27.1: <witness> = facet_access_witness %.Self.ref [symbolic = constants.%.3]
// CHECK:STDOUT: %.loc14_27.2: type = interface_witness_access %.loc14_27.1, element0
// CHECK:STDOUT: %.loc14_33: Core.IntLiteral = int_value 32 [template = constants.%.4]
// CHECK:STDOUT: %int.make_type_signed: init type = call constants.%Int(%.loc14_33) [template = constants.%i32]
// CHECK:STDOUT: %.loc14_21: type = where_expr %.Self [template = constants.%I.type.2] {
// CHECK:STDOUT: requirement_equivalent %T.ref, %int.make_type_signed
// CHECK:STDOUT: requirement_equivalent %.loc14_27.2, %int.make_type_signed
// CHECK:STDOUT: }
// CHECK:STDOUT: %U.param: %I.type.2 = value_param runtime_param0
// CHECK:STDOUT: %U: %I.type.2 = bind_name U, %U.param
+1
View File
@@ -264,6 +264,7 @@ auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory {
case CompleteTypeWitness::Kind:
case ConstType::Kind:
case FacetAccessType::Kind:
case FacetAccessWitness::Kind:
case FacetType::Kind:
case FacetValue::Kind:
case FloatLiteral::Kind:
+1
View File
@@ -85,6 +85,7 @@ CARBON_SEM_IR_INST_KIND(ConstType)
CARBON_SEM_IR_INST_KIND(Converted)
CARBON_SEM_IR_INST_KIND(Deref)
CARBON_SEM_IR_INST_KIND(FacetAccessType)
CARBON_SEM_IR_INST_KIND(FacetAccessWitness)
CARBON_SEM_IR_INST_KIND(FacetType)
CARBON_SEM_IR_INST_KIND(FacetValue)
CARBON_SEM_IR_INST_KIND(FieldDecl)
+6
View File
@@ -192,6 +192,12 @@ auto StringifyTypeExpr(const SemIR::File& outer_sem_ir, InstId outer_inst_id)
push_inst_id(inst.facet_value_inst_id);
break;
}
case CARBON_KIND(FacetAccessWitness inst): {
out << "<witness for ";
push_string(">");
push_inst_id(inst.facet_value_inst_id);
break;
}
case CARBON_KIND(FacetType inst): {
const FacetTypeInfo& facet_type_info =
sem_ir.facet_types().Get(inst.facet_type_id);
+15 -1
View File
@@ -602,7 +602,21 @@ struct FacetAccessType {
InstId facet_value_inst_id;
};
// TODO: `FacetAccessWitness`
// Represents accessing the `witness` field in a facet value, which is
// notionally a pair of a type and a witness.
struct FacetAccessWitness {
static constexpr auto Kind =
InstKind::FacetAccessWitness.Define<Parse::NodeId>(
{.ir_name = "facet_access_witness",
.is_type = InstIsType::Never,
.constant_kind = InstConstantKind::SymbolicOnly,
.is_lowered = false});
// Always the builtin witness type.
TypeId type_id;
// An instruction that evaluates to a `FacetValue`.
InstId facet_value_inst_id;
};
// A facet type value.
struct FacetType {