Add an interface-with-self generic to each interface and same for constraints (#6667)

Currently each interface has a `Self` facet internally that becomes a
binding to every entity inside the interface: associated constants,
functions, and require decls. Each of these has to be independently
generic as a result. This makes is challenging in extended name lookup
to move into an extended scope of an interface, as we have a specific
for the interface, but the names within require a different specific
that includes a `Self` facet value.

We generalize this relationship by adding a second generic to Interface,
called `generic_with_self`. When we want to work with entities inside
the interface, we move from the interface-without-specific to the
interface-with-self specific by adding a Self to the specific. This is
done independently of any particular entity inside the Interface, as
those entities are now all members of the interface-with-self generic.

Associated constants no longer need a generic of their own, as they do
not have separate generic bindings. Functions retain a generic, but if
the function has no generic arguments, it will have no bindings of its
own now.

Require decls retain a generic so that their specific can be
instantiated separately from the interface. Requiring the interface to
be complete does not require the types in a require decl to be complete
unless it is modified by `extend`. So we allow them to be completed
later by keeping them in a separate generic.

Named constraints look like interfaces and gain the additional inner
generic-with-self, with the same relationship to require decls.

This removes the need for name lookup to perform Substitution of a Self
facet into the extended scope instruction. Instead, the
`SpecificConstant` instruction inserted by a `require` decl is part of
the interface-with-self generic. When looking through a FacetType for
extended scopes, for each interface, we push the scope with the specific
for the interface-with-self. Then the constant value of the
`SpecificConstant` is correctly modified by the provided self
automatically through applying that specific.
This commit is contained in:
Dana Jansens
2026-02-19 16:24:07 +00:00
committed by GitHub
parent e5b094fdad
commit 917a6ea971
419 changed files with 18175 additions and 11940 deletions
@@ -88,7 +88,6 @@ fn F() {
// CHECK:STDOUT: %TakesArray.cpp_overload_set.value: %TakesArray.cpp_overload_set.type = cpp_overload_set_value @TakesArray.cpp_overload_set [concrete]
// CHECK:STDOUT: %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]
// CHECK:STDOUT: %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]
// CHECK:STDOUT: %ImplicitAs.Convert.type.1b6: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%i32) [concrete]
// CHECK:STDOUT: %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]
@@ -97,7 +96,8 @@ fn F() {
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]
// CHECK:STDOUT: %ImplicitAs.facet.b94: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]
// CHECK:STDOUT: %.863: type = fn_type_with_self_type %ImplicitAs.Convert.type.1b6, %ImplicitAs.facet.b94 [concrete]
// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs(%i32, %ImplicitAs.facet.b94) [concrete]
// CHECK:STDOUT: %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet.b94 [concrete]
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]
// CHECK:STDOUT: %bound_method.d2e: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
@@ -120,7 +120,6 @@ fn F() {
// CHECK:STDOUT: %TakesArray.type: type = fn_type @TakesArray [concrete]
// CHECK:STDOUT: %TakesArray: %TakesArray.type = struct_value () [concrete]
// CHECK:STDOUT: %ImplicitAs.type.121: type = facet_type <@ImplicitAs, @ImplicitAs(%Optional.75d)> [concrete]
// CHECK:STDOUT: %ImplicitAs.Convert.type.761: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%Optional.75d) [concrete]
// CHECK:STDOUT: %OptionalAs.type.ea5: type = facet_type <@OptionalAs, @OptionalAs(%T.542)> [symbolic]
// CHECK:STDOUT: %U.2d2: %OptionalAs.type.ea5 = symbolic_binding U, 1 [symbolic]
// CHECK:STDOUT: %U.binding.as_type.as.ImplicitAs.impl.Convert.type.4c5: type = fn_type @U.binding.as_type.as.ImplicitAs.impl.Convert.2, @U.binding.as_type.as.ImplicitAs.impl.71c(%T.542, %U.2d2) [symbolic]
@@ -134,7 +133,8 @@ fn F() {
// CHECK:STDOUT: %U.binding.as_type.as.ImplicitAs.impl.Convert.type.cc7: type = fn_type @U.binding.as_type.as.ImplicitAs.impl.Convert.2, @U.binding.as_type.as.ImplicitAs.impl.71c(%OptionalStorage.facet.6bd, %OptionalAs.facet) [concrete]
// CHECK:STDOUT: %U.binding.as_type.as.ImplicitAs.impl.Convert.37e: %U.binding.as_type.as.ImplicitAs.impl.Convert.type.cc7 = struct_value () [concrete]
// CHECK:STDOUT: %ImplicitAs.facet.8cd: %ImplicitAs.type.121 = facet_value %ptr.235, (%ImplicitAs.impl_witness.2c0) [concrete]
// CHECK:STDOUT: %.07d: type = fn_type_with_self_type %ImplicitAs.Convert.type.761, %ImplicitAs.facet.8cd [concrete]
// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.944: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs(%Optional.75d, %ImplicitAs.facet.8cd) [concrete]
// CHECK:STDOUT: %.c75: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.944, %ImplicitAs.facet.8cd [concrete]
// CHECK:STDOUT: %U.binding.as_type.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %U.binding.as_type.as.ImplicitAs.impl.Convert.37e, @U.binding.as_type.as.ImplicitAs.impl.Convert.2(%OptionalStorage.facet.6bd, %OptionalAs.facet) [concrete]
// CHECK:STDOUT: %Cpp.nullptr_t: type = class_type @NullptrT [concrete]
// CHECK:STDOUT: %uninit: %Cpp.nullptr_t = uninitialized_value [concrete]
@@ -144,7 +144,8 @@ fn F() {
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.type.9ab: type = fn_type @Cpp.nullptr_t.as.ImplicitAs.impl.Convert, @Cpp.nullptr_t.as.ImplicitAs.impl(%i32) [concrete]
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.a00: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.type.9ab = struct_value () [concrete]
// CHECK:STDOUT: %ImplicitAs.facet.cf9: %ImplicitAs.type.121 = facet_value %Cpp.nullptr_t, (%ImplicitAs.impl_witness.aac) [concrete]
// CHECK:STDOUT: %.99d: type = fn_type_with_self_type %ImplicitAs.Convert.type.761, %ImplicitAs.facet.cf9 [concrete]
// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.4aa: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs(%Optional.75d, %ImplicitAs.facet.cf9) [concrete]
// CHECK:STDOUT: %.153: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.4aa, %ImplicitAs.facet.cf9 [concrete]
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %uninit, %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.a00 [concrete]
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.a00, @Cpp.nullptr_t.as.ImplicitAs.impl.Convert(%i32) [concrete]
// CHECK:STDOUT: %bound_method.3ee: <bound method> = bound_method %uninit, %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.specific_fn [concrete]
@@ -209,7 +210,7 @@ fn F() {
// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
// CHECK:STDOUT: %int_32.loc11: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc11: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %impl.elem0.loc11_21: %.863 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]
// CHECK:STDOUT: %impl.elem0.loc11_21: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]
// CHECK:STDOUT: %bound_method.loc11_21.1: <bound method> = bound_method %int_0, %impl.elem0.loc11_21 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]
// CHECK:STDOUT: %specific_fn.loc11_21: <specific function> = specific_function %impl.elem0.loc11_21, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc11_21.2: <bound method> = bound_method %int_0, %specific_fn.loc11_21 [concrete = constants.%bound_method.d2e]
@@ -218,7 +219,7 @@ fn F() {
// CHECK:STDOUT: %.loc11_21.2: %i32 = converted %int_0, %.loc11_21.1 [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %.loc11_22: ref %i32 = array_index %n.ref, %.loc11_21.2
// CHECK:STDOUT: %addr: %ptr.235 = addr_of %.loc11_22
// CHECK:STDOUT: %impl.elem0.loc11_18: %.07d = impl_witness_access constants.%ImplicitAs.impl_witness.2c0, element0 [concrete = constants.%U.binding.as_type.as.ImplicitAs.impl.Convert.37e]
// CHECK:STDOUT: %impl.elem0.loc11_18: %.c75 = impl_witness_access constants.%ImplicitAs.impl_witness.2c0, element0 [concrete = constants.%U.binding.as_type.as.ImplicitAs.impl.Convert.37e]
// CHECK:STDOUT: %bound_method.loc11_18.1: <bound method> = bound_method %addr, %impl.elem0.loc11_18
// CHECK:STDOUT: %specific_fn.loc11_18: <specific function> = specific_function %impl.elem0.loc11_18, @U.binding.as_type.as.ImplicitAs.impl.Convert.2(constants.%OptionalStorage.facet.6bd, constants.%OptionalAs.facet) [concrete = constants.%U.binding.as_type.as.ImplicitAs.impl.Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc11_18.2: <bound method> = bound_method %addr, %specific_fn.loc11_18
@@ -233,7 +234,7 @@ fn F() {
// CHECK:STDOUT: %Cpp.ref.loc13_18: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %nullptr.ref: %Cpp.nullptr_t = name_ref nullptr, %uninit [concrete = constants.%uninit]
// CHECK:STDOUT: %impl.elem0.loc13: %.99d = impl_witness_access constants.%ImplicitAs.impl_witness.aac, element0 [concrete = constants.%Cpp.nullptr_t.as.ImplicitAs.impl.Convert.a00]
// CHECK:STDOUT: %impl.elem0.loc13: %.153 = impl_witness_access constants.%ImplicitAs.impl_witness.aac, element0 [concrete = constants.%Cpp.nullptr_t.as.ImplicitAs.impl.Convert.a00]
// CHECK:STDOUT: %bound_method.loc13_21.1: <bound method> = bound_method %nullptr.ref, %impl.elem0.loc13 [concrete = constants.%Cpp.nullptr_t.as.ImplicitAs.impl.Convert.bound]
// CHECK:STDOUT: %specific_fn.loc13: <specific function> = specific_function %impl.elem0.loc13, @Cpp.nullptr_t.as.ImplicitAs.impl.Convert(constants.%i32) [concrete = constants.%Cpp.nullptr_t.as.ImplicitAs.impl.Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc13_21.2: <bound method> = bound_method %nullptr.ref, %specific_fn.loc13 [concrete = constants.%bound_method.3ee]
@@ -273,7 +274,6 @@ fn F() {
// CHECK:STDOUT: %pattern_type.b6e: type = pattern_type %array_type [concrete]
// CHECK:STDOUT: %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]
// CHECK:STDOUT: %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]
// CHECK:STDOUT: %ImplicitAs.Convert.type.1b6: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%i32) [concrete]
// CHECK:STDOUT: %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]
@@ -281,7 +281,8 @@ fn F() {
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]
// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]
// CHECK:STDOUT: %.863: type = fn_type_with_self_type %ImplicitAs.Convert.type.1b6, %ImplicitAs.facet [concrete]
// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs(%i32, %ImplicitAs.facet) [concrete]
// CHECK:STDOUT: %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
@@ -333,7 +334,7 @@ fn F() {
// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
// CHECK:STDOUT: %int_32.loc31: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc31: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %impl.elem0: %.863 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]
// CHECK:STDOUT: %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]
// CHECK:STDOUT: %bound_method.loc31_24.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc31_24.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]