mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 13:40:11 +01:00
Type completeness in extend (#6395)
Define rules for `extend` declarations (`extend require`, `extend impl as`, `extend base`, `extend adapt`) that say the target scope they name must be complete at the point of the declaration. Define completeness for a facet type to include all interfaces and named constraints that provide unqualified name lookup through the facet type. --------- Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com> Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
co-authored by
Carbon Infra Bot
Richard Smith
parent
ec8c999bb1
commit
0baa74d96f
@@ -0,0 +1,190 @@
|
||||
# Type completeness in extend
|
||||
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
[Pull request](https://github.com/carbon-language/carbon-lang/pull/6395)
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Abstract](#abstract)
|
||||
- [Problem](#problem)
|
||||
- [Background](#background)
|
||||
- [Proposal](#proposal)
|
||||
- [Details](#details)
|
||||
- [Rationale](#rationale)
|
||||
- [Alternatives considered](#alternatives-considered)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
## Abstract
|
||||
|
||||
Require any target scopes in an `extend` declaration to be complete, since
|
||||
`extend` changes the scopes which are looked in for name lookup to include those
|
||||
named in the declaration.
|
||||
|
||||
## Problem
|
||||
|
||||
Proposal
|
||||
[#5168](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p5168.md)
|
||||
laid out rules for when a facet type needs to be identified or complete. When
|
||||
`require impls X` is written, then `X` must be identified. However it does not
|
||||
specify any rule for `extend require impls X`. And we lack completeness rules
|
||||
for other `extend` declarations, including `extend impl as X`, `extend base: X`,
|
||||
and `extend adapt X`.
|
||||
|
||||
An `extend` declaration always names one or more target entities which will be
|
||||
included in the search for names when looking in the enclosing scope of the
|
||||
`extend` declaration. In order to do name lookup into an entity, it must be
|
||||
complete to avoid poisoning names in the entity.
|
||||
|
||||
## Background
|
||||
|
||||
- Proposal
|
||||
[#5168](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p5168.md):
|
||||
Forward `impl` declaration of an incomplete interface
|
||||
- Proposal
|
||||
[#2760](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p2760.md):
|
||||
Consistent `class` and `interface` syntax
|
||||
- Proposal
|
||||
[#0777](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p0777.md):
|
||||
Inheritance
|
||||
|
||||
## Proposal
|
||||
|
||||
An `extend` declaration declares that the enclosing scope extends the scope
|
||||
associated with any target entity named in the declaration. That is to say name
|
||||
lookups into the enclosing scope will also look into the scopes which are
|
||||
nominated by the `extend` declaration. The `extend` declaration requires that
|
||||
the target scopes named in an `extend` declaration are complete, or if the
|
||||
target is a generic parameter, requires the type of the parameter to be
|
||||
complete.
|
||||
|
||||
The scope of a facet type formed by a `where` declaration extends the scope of
|
||||
its first operand. And the scope of a facet type formed by a `&` operator
|
||||
extends the scopes of both of its operands. In either case, the scope of the
|
||||
facet type is complete if every scope it extends is complete. The facet type
|
||||
`type` is associated with an empty scope and is complete.
|
||||
|
||||
| Facet type | Requirement |
|
||||
| ---------------------------- | ------------------------------------- |
|
||||
| `I` | Requires `I` is complete. |
|
||||
| `I & J` | Requires `I` and `J` are complete. |
|
||||
| `type where U impls J` | Requires `type` is complete. |
|
||||
| `I & (type where U impls J)` | Requires `I` and `type` are complete. |
|
||||
|
||||
## Details
|
||||
|
||||
To `extend` an entity `Y` with another `Z` means that name lookups into `Y` will
|
||||
also look into `Z`. Immediately after the `extend` operation, members of `Z`
|
||||
should also be found when doing name lookup into `Y`, both from outside and from
|
||||
inside the definition of `Y`. In order to be able to perform lookups into `Z`,
|
||||
we require that `extend` operations only target scopes that are complete.
|
||||
|
||||
This requirement functions recursively. Given an interface `B` that extends
|
||||
another interface `A`: By naming `A` in an extend declaration, we require `A` is
|
||||
complete. This provides that its entire definition is known, and thus its
|
||||
`extend` relationship to `B`. The `extend` relationship there also provides that
|
||||
`B` is complete.
|
||||
|
||||
If the target scope of an `extend` declaration is a generic parameter, its type
|
||||
must be complete where the `extend` declaration is written, as name lookups into
|
||||
the extended scope will look into the type of the generic parameter.
|
||||
|
||||
```carbon
|
||||
interface I {
|
||||
fn F();
|
||||
}
|
||||
|
||||
class C(T:! I) {
|
||||
extend base: T;
|
||||
// `F` names `T.F` here, found in `I`.
|
||||
fn G() { F(); }
|
||||
}
|
||||
```
|
||||
|
||||
As any generic parameter in the enclosing scope is replaced by a more specific
|
||||
value, extended scopes that depend on a generic parameter must remain complete.
|
||||
This includes forming a specific for the extended scope involving the parameter
|
||||
in order to surface any monomorphization errors in the resulting specific.
|
||||
|
||||
In the next example, the `extend` declaration in interface `A(N)` names a
|
||||
symbolic facet type which can produce monomorphization errors when a negative
|
||||
value is provided for `N`. When a more specific value for the target `B(N)` is
|
||||
provided, we require the specific value to be complete as well by forming the
|
||||
specific. A diagnostic error would be produced while checking `C(-1)` for
|
||||
completeness, as it requires `A(-1)` to be complete, which requires
|
||||
`B(array(i32, -1))` to be complete, and that contains an invalid type.
|
||||
|
||||
```carbon
|
||||
interface B(T:! type) {}
|
||||
|
||||
interface A(N:! i32) {
|
||||
// Requires `B(N)` to be complete.
|
||||
extend require impls B(array(i32, N)) {}
|
||||
}
|
||||
|
||||
class C(N! i32) {
|
||||
// Requires `A(N)` to be complete, which requires `B(N)` to be complete.
|
||||
extend impl as A(N);
|
||||
}
|
||||
|
||||
fn F() {
|
||||
// Requires `C(-1)` to be complete, which requires `A(-1)` to be complete, which requires `B(array(i32, -1))` to be complete.
|
||||
var c: C(-1);
|
||||
}
|
||||
```
|
||||
|
||||
These rules prohibit an `extend` declaration from naming its enclosing scope,
|
||||
since by being part of the definition of that scope, it is implied that the
|
||||
enclosing scope is not complete. This seems reasonable as all names available
|
||||
inside the enclosing interface or named constraint are already available or
|
||||
would conflict with the ones that are.
|
||||
|
||||
## Rationale
|
||||
|
||||
This is based on the principle of
|
||||
[Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).
|
||||
For code to be easy to write, the rules need to be consistent. Once an `extend`
|
||||
declaration has been written, the names inside should become available through
|
||||
the enclosing scope immediately. If we allow an interface named in an `extend`
|
||||
declaration to be incomplete, then name lookup will fail ambiguously. Those same
|
||||
names may become valid later once the interface is defined.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
We considered not requiring that the scope named in an `extend` declaration be
|
||||
complete where it is written, but only when the enclosing scope is required to
|
||||
be complete. This is more flexible, allowing entities to be defined later in the
|
||||
program. However this does not allow the use of names from the target scope in
|
||||
the `extend` to be used from within the enclosing definition scope. They would
|
||||
not become available until the enclosing definition scope was closed and
|
||||
complete.
|
||||
|
||||
In particular, we want this to work:
|
||||
|
||||
```carbon
|
||||
interface Z {
|
||||
let X:! type;
|
||||
fn F() -> X;
|
||||
}
|
||||
class C {
|
||||
extend impl as Z where .X = () {
|
||||
// Names `X` directly.
|
||||
fn F() -> X;
|
||||
}
|
||||
|
||||
// Names `X` and `F` directly.
|
||||
fn G() -> X { return F(); }
|
||||
}
|
||||
|
||||
// Now `C` is complete, `C.X` and `C.F` are also available.
|
||||
fn H() -> C.X {
|
||||
return C.F();
|
||||
}
|
||||
```
|
||||
+440
-13
@@ -141,6 +141,9 @@ interface J {
|
||||
|
||||
class E {
|
||||
extend impl as J where .U = i32 {
|
||||
// TODO: U should be in scope and usable as soon as we finish the
|
||||
// declaration / enter the definition.
|
||||
//
|
||||
// CHECK:STDERR: fail_todo_use_associated_constant_in_impl.carbon:[[@LINE+14]]:13: error: cannot implicitly convert non-type value of type `<associated entity in J>` to `type` [ConversionFailureNonTypeToFacet]
|
||||
// CHECK:STDERR: fn F(u: U) -> U {
|
||||
// CHECK:STDERR: ^
|
||||
@@ -161,6 +164,61 @@ class E {
|
||||
}
|
||||
}
|
||||
|
||||
// --- fail_todo_call_extend_fn.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface J {
|
||||
fn F() {}
|
||||
}
|
||||
|
||||
class E {
|
||||
extend impl as J {
|
||||
fn F() {}
|
||||
}
|
||||
|
||||
// CHECK:STDERR: fail_todo_call_extend_fn.carbon:[[@LINE+4]]:12: error: value of type `<associated entity in J>` is not callable [CallToNonCallable]
|
||||
// CHECK:STDERR: fn G() { F(); }
|
||||
// CHECK:STDERR: ^~~
|
||||
// CHECK:STDERR:
|
||||
fn G() { F(); }
|
||||
}
|
||||
|
||||
// --- call_extend_method.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface J {
|
||||
fn F[self: Self]() {}
|
||||
}
|
||||
|
||||
class E {
|
||||
extend impl as J {
|
||||
fn F[self: Self]() {}
|
||||
}
|
||||
|
||||
fn G[self: Self]() { self.F(); }
|
||||
}
|
||||
|
||||
// --- fail_todo_use_extend_constant.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface J {
|
||||
let X:! type;
|
||||
}
|
||||
|
||||
class E {
|
||||
extend impl as J where .X = () {}
|
||||
|
||||
// TODO: `X` should be in scope and directly usable.
|
||||
// CHECK:STDERR: fail_todo_use_extend_constant.carbon:[[@LINE+7]]:13: error: cannot implicitly convert non-type value of type `<associated entity in J>` to `type` [ConversionFailureNonTypeToFacet]
|
||||
// CHECK:STDERR: fn G() -> X { return (); }
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR: fail_todo_use_extend_constant.carbon:[[@LINE+4]]:13: note: type `<associated entity in J>` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessNote]
|
||||
// CHECK:STDERR: fn G() -> X { return (); }
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR:
|
||||
fn G() -> X { return (); }
|
||||
}
|
||||
|
||||
// --- fail_todo_self_period_associated_type.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
@@ -2309,11 +2367,11 @@ fn F() {
|
||||
// CHECK:STDOUT: %J.impl_witness: <witness> = impl_witness @E.%J.impl_witness_table [concrete]
|
||||
// CHECK:STDOUT: %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
|
||||
// CHECK:STDOUT: %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.type.3487c0.1: type = fn_type @E.as.J.impl.F.loc24_21.1 [concrete]
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.type.3487c0.1: type = fn_type @E.as.J.impl.F.loc27_21.1 [concrete]
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.1487eb.1: %E.as.J.impl.F.type.3487c0.1 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %J.facet: %J.type = facet_value %E, (%J.impl_witness) [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.7ce: type = pattern_type %i32 [concrete]
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.type.3487c0.2: type = fn_type @E.as.J.impl.F.loc24_21.2 [concrete]
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.type.3487c0.2: type = fn_type @E.as.J.impl.F.loc27_21.2 [concrete]
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.1487eb.2: %E.as.J.impl.F.type.3487c0.2 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
|
||||
// CHECK:STDOUT: %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
|
||||
@@ -2379,24 +2437,24 @@ fn F() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: impl @E.as.J.impl: %Self.ref as %.loc9_20 {
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.decl.loc24_21.1: %E.as.J.impl.F.type.3487c0.1 = fn_decl @E.as.J.impl.F.loc24_21.1 [concrete = constants.%E.as.J.impl.F.1487eb.1] {
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.decl.loc27_21.1: %E.as.J.impl.F.type.3487c0.1 = fn_decl @E.as.J.impl.F.loc27_21.1 [concrete = constants.%E.as.J.impl.F.1487eb.1] {
|
||||
// CHECK:STDOUT: %u.patt: <error> = value_binding_pattern u [concrete]
|
||||
// CHECK:STDOUT: %u.param_patt: <error> = value_param_pattern %u.patt, call_param0 [concrete]
|
||||
// CHECK:STDOUT: %return.patt: <error> = return_slot_pattern [concrete]
|
||||
// CHECK:STDOUT: %return.param_patt: <error> = out_param_pattern %return.patt, call_param1 [concrete]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %U.ref.loc24_19: %J.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0.411]
|
||||
// CHECK:STDOUT: %.loc24_19: type = converted %U.ref.loc24_19, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: %U.ref.loc27_19: %J.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0.411]
|
||||
// CHECK:STDOUT: %.loc27_19: type = converted %U.ref.loc27_19, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: %u.param: <error> = value_param call_param0
|
||||
// CHECK:STDOUT: %.1: <error> = splice_block <error> [concrete = <error>] {
|
||||
// CHECK:STDOUT: %U.ref.loc24_13: %J.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0.411]
|
||||
// CHECK:STDOUT: %.loc24_13: type = converted %U.ref.loc24_13, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: %U.ref.loc27_13: %J.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0.411]
|
||||
// CHECK:STDOUT: %.loc27_13: type = converted %U.ref.loc27_13, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %u: <error> = value_binding u, %u.param
|
||||
// CHECK:STDOUT: %return.param: ref <error> = out_param call_param1
|
||||
// CHECK:STDOUT: %return: ref <error> = return_slot %return.param
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.decl.loc24_21.2: %E.as.J.impl.F.type.3487c0.2 = fn_decl @E.as.J.impl.F.loc24_21.2 [concrete = constants.%E.as.J.impl.F.1487eb.2] {
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.decl.loc27_21.2: %E.as.J.impl.F.type.3487c0.2 = fn_decl @E.as.J.impl.F.loc27_21.2 [concrete = constants.%E.as.J.impl.F.1487eb.2] {
|
||||
// CHECK:STDOUT: %u.patt: %pattern_type.7ce = value_binding_pattern u [concrete]
|
||||
// CHECK:STDOUT: %u.param_patt: %pattern_type.7ce = value_param_pattern %u.patt, call_param0 [concrete]
|
||||
// CHECK:STDOUT: %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]
|
||||
@@ -2410,7 +2468,7 @@ fn F() {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .U = <poisoned>
|
||||
// CHECK:STDOUT: .F = %E.as.J.impl.F.decl.loc24_21.1
|
||||
// CHECK:STDOUT: .F = %E.as.J.impl.F.decl.loc27_21.1
|
||||
// CHECK:STDOUT: witness = @E.%J.impl_witness
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -2431,7 +2489,7 @@ fn F() {
|
||||
// CHECK:STDOUT: requirement_rewrite %impl.elem0, %i32
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant, @E.as.J.impl.%E.as.J.impl.F.decl.loc24_21.2), @E.as.J.impl [concrete]
|
||||
// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant, @E.as.J.impl.%E.as.J.impl.F.decl.loc27_21.2), @E.as.J.impl [concrete]
|
||||
// CHECK:STDOUT: %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness]
|
||||
// CHECK:STDOUT: %impl_witness_assoc_constant: type = impl_witness_assoc_constant constants.%i32 [concrete = constants.%i32]
|
||||
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]
|
||||
@@ -2453,15 +2511,15 @@ fn F() {
|
||||
// CHECK:STDOUT: fn(%u.param: @J.F.%impl.elem0.loc5_11.1 (%impl.elem0.fa9)) -> @J.F.%impl.elem0.loc5_11.1 (%impl.elem0.fa9);
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @E.as.J.impl.F.loc24_21.1(%u.param: <error>) -> <error> {
|
||||
// CHECK:STDOUT: fn @E.as.J.impl.F.loc27_21.1(%u.param: <error>) -> <error> {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %u.ref: <error> = name_ref u, %u
|
||||
// CHECK:STDOUT: return <error> to %return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @E.as.J.impl.F.loc24_21.2(%u.param: %i32) -> %i32 [thunk @E.as.J.impl.%E.as.J.impl.F.decl.loc24_21.1] {
|
||||
// CHECK:STDOUT: fn @E.as.J.impl.F.loc27_21.2(%u.param: %i32) -> %i32 [thunk @E.as.J.impl.%E.as.J.impl.F.decl.loc27_21.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %E.as.J.impl.F.type.3487c0.1 = name_ref F, @E.as.J.impl.%E.as.J.impl.F.decl.loc24_21.1 [concrete = constants.%E.as.J.impl.F.1487eb.1]
|
||||
// CHECK:STDOUT: %F.ref: %E.as.J.impl.F.type.3487c0.1 = name_ref F, @E.as.J.impl.%E.as.J.impl.F.decl.loc27_21.1 [concrete = constants.%E.as.J.impl.F.1487eb.1]
|
||||
// CHECK:STDOUT: %u.ref: %i32 = name_ref u, %u.param
|
||||
// CHECK:STDOUT: %return.ref: ref %i32 = name_ref <return slot>, %return.param
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.call: init <error> = call %F.ref(<error>)
|
||||
@@ -2486,6 +2544,375 @@ fn F() {
|
||||
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.7ce
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_call_extend_fn.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %J.type: type = facet_type <@J> [concrete]
|
||||
// CHECK:STDOUT: %Self: %J.type = symbolic_binding Self, 0 [symbolic]
|
||||
// CHECK:STDOUT: %J.F.type: type = fn_type @J.F [concrete]
|
||||
// CHECK:STDOUT: %J.F: %J.F.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %J.assoc_type: type = assoc_entity_type @J [concrete]
|
||||
// CHECK:STDOUT: %assoc0: %J.assoc_type = assoc_entity element0, @J.%J.F.decl [concrete]
|
||||
// CHECK:STDOUT: %E: type = class_type @E [concrete]
|
||||
// CHECK:STDOUT: %J.impl_witness: <witness> = impl_witness @E.%J.impl_witness_table [concrete]
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.type: type = fn_type @E.as.J.impl.F [concrete]
|
||||
// CHECK:STDOUT: %E.as.J.impl.F: %E.as.J.impl.F.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %J.facet: %J.type = facet_value %E, (%J.impl_witness) [concrete]
|
||||
// CHECK:STDOUT: %E.G.type: type = fn_type @E.G [concrete]
|
||||
// CHECK:STDOUT: %E.G: %E.G.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
|
||||
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [concrete] {
|
||||
// CHECK:STDOUT: import Core//prelude
|
||||
// CHECK:STDOUT: import Core//prelude/...
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
|
||||
// CHECK:STDOUT: .Core = imports.%Core
|
||||
// CHECK:STDOUT: .J = %J.decl
|
||||
// CHECK:STDOUT: .E = %E.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core.import = import Core
|
||||
// CHECK:STDOUT: %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}
|
||||
// CHECK:STDOUT: %E.decl: type = class_decl @E [concrete = constants.%E] {} {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: interface @J {
|
||||
// CHECK:STDOUT: %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
|
||||
// CHECK:STDOUT: %J.F.decl: %J.F.type = fn_decl @J.F [concrete = constants.%J.F] {} {}
|
||||
// CHECK:STDOUT: %assoc0: %J.assoc_type = assoc_entity element0, %J.F.decl [concrete = constants.%assoc0]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = %Self
|
||||
// CHECK:STDOUT: .F = %assoc0
|
||||
// CHECK:STDOUT: witness = (%J.F.decl)
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !requires:
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: impl @E.as.J.impl: %Self.ref as %J.ref {
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.decl: %E.as.J.impl.F.type = fn_decl @E.as.J.impl.F [concrete = constants.%E.as.J.impl.F] {} {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .F = %E.as.J.impl.F.decl
|
||||
// CHECK:STDOUT: witness = @E.%J.impl_witness
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @E {
|
||||
// CHECK:STDOUT: impl_decl @E.as.J.impl [concrete] {} {
|
||||
// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%E [concrete = constants.%E]
|
||||
// CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (@E.as.J.impl.%E.as.J.impl.F.decl), @E.as.J.impl [concrete]
|
||||
// CHECK:STDOUT: %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness]
|
||||
// CHECK:STDOUT: %E.G.decl: %E.G.type = fn_decl @E.G [concrete = constants.%E.G] {} {}
|
||||
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
|
||||
// CHECK:STDOUT: complete_type_witness = %complete_type
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%E
|
||||
// CHECK:STDOUT: .J = <poisoned>
|
||||
// CHECK:STDOUT: .G = %E.G.decl
|
||||
// CHECK:STDOUT: .F = <poisoned>
|
||||
// CHECK:STDOUT: extend @E.as.J.impl.%J.ref
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: generic fn @J.F(@J.%Self: %J.type) {
|
||||
// CHECK:STDOUT: !definition:
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @E.as.J.impl.F() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @E.G() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %J.assoc_type = name_ref F, @J.%assoc0 [concrete = constants.%assoc0]
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @J.F(constants.%Self) {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @J.F(constants.%J.facet) {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- call_extend_method.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %J.type: type = facet_type <@J> [concrete]
|
||||
// CHECK:STDOUT: %Self: %J.type = symbolic_binding Self, 0 [symbolic]
|
||||
// CHECK:STDOUT: %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic]
|
||||
// CHECK:STDOUT: %pattern_type.4c4: type = pattern_type %Self.binding.as_type [symbolic]
|
||||
// CHECK:STDOUT: %J.F.type: type = fn_type @J.F [concrete]
|
||||
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
|
||||
// CHECK:STDOUT: %J.F: %J.F.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %J.assoc_type: type = assoc_entity_type @J [concrete]
|
||||
// CHECK:STDOUT: %assoc0: %J.assoc_type = assoc_entity element0, @J.%J.F.decl [concrete]
|
||||
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type %Self.binding.as_type [symbolic]
|
||||
// CHECK:STDOUT: %E: type = class_type @E [concrete]
|
||||
// CHECK:STDOUT: %J.impl_witness: <witness> = impl_witness @E.%J.impl_witness_table [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.a4a: type = pattern_type %E [concrete]
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.type: type = fn_type @E.as.J.impl.F [concrete]
|
||||
// CHECK:STDOUT: %E.as.J.impl.F: %E.as.J.impl.F.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %J.facet: %J.type = facet_value %E, (%J.impl_witness) [concrete]
|
||||
// CHECK:STDOUT: %E.G.type: type = fn_type @E.G [concrete]
|
||||
// CHECK:STDOUT: %E.G: %E.G.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
|
||||
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
|
||||
// CHECK:STDOUT: %.225: type = fn_type_with_self_type %J.F.type, %J.facet [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [concrete] {
|
||||
// CHECK:STDOUT: import Core//prelude
|
||||
// CHECK:STDOUT: import Core//prelude/...
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
|
||||
// CHECK:STDOUT: .Core = imports.%Core
|
||||
// CHECK:STDOUT: .J = %J.decl
|
||||
// CHECK:STDOUT: .E = %E.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core.import = import Core
|
||||
// CHECK:STDOUT: %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}
|
||||
// CHECK:STDOUT: %E.decl: type = class_decl @E [concrete = constants.%E] {} {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: interface @J {
|
||||
// CHECK:STDOUT: %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
|
||||
// CHECK:STDOUT: %J.F.decl: %J.F.type = fn_decl @J.F [concrete = constants.%J.F] {
|
||||
// CHECK:STDOUT: %self.patt: @J.F.%pattern_type (%pattern_type.4c4) = value_binding_pattern self [concrete]
|
||||
// CHECK:STDOUT: %self.param_patt: @J.F.%pattern_type (%pattern_type.4c4) = value_param_pattern %self.patt, call_param0 [concrete]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %self.param: @J.F.%Self.binding.as_type (%Self.binding.as_type) = value_param call_param0
|
||||
// CHECK:STDOUT: %.loc4_14.1: type = splice_block %.loc4_14.2 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)] {
|
||||
// CHECK:STDOUT: %Self.ref: %J.type = name_ref Self, @J.%Self [symbolic = %Self (constants.%Self)]
|
||||
// CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self.ref [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
|
||||
// CHECK:STDOUT: %.loc4_14.2: type = converted %Self.ref, %Self.as_type [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %self: @J.F.%Self.binding.as_type (%Self.binding.as_type) = value_binding self, %self.param
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %assoc0: %J.assoc_type = assoc_entity element0, %J.F.decl [concrete = constants.%assoc0]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = %Self
|
||||
// CHECK:STDOUT: .F = %assoc0
|
||||
// CHECK:STDOUT: witness = (%J.F.decl)
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !requires:
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: impl @E.as.J.impl: %Self.ref as %J.ref {
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.decl: %E.as.J.impl.F.type = fn_decl @E.as.J.impl.F [concrete = constants.%E.as.J.impl.F] {
|
||||
// CHECK:STDOUT: %self.patt: %pattern_type.a4a = value_binding_pattern self [concrete]
|
||||
// CHECK:STDOUT: %self.param_patt: %pattern_type.a4a = value_param_pattern %self.patt, call_param0 [concrete]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %self.param: %E = value_param call_param0
|
||||
// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%E [concrete = constants.%E]
|
||||
// CHECK:STDOUT: %self: %E = value_binding self, %self.param
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .F = %E.as.J.impl.F.decl
|
||||
// CHECK:STDOUT: witness = @E.%J.impl_witness
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @E {
|
||||
// CHECK:STDOUT: impl_decl @E.as.J.impl [concrete] {} {
|
||||
// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%E [concrete = constants.%E]
|
||||
// CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (@E.as.J.impl.%E.as.J.impl.F.decl), @E.as.J.impl [concrete]
|
||||
// CHECK:STDOUT: %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness]
|
||||
// CHECK:STDOUT: %E.G.decl: %E.G.type = fn_decl @E.G [concrete = constants.%E.G] {
|
||||
// CHECK:STDOUT: %self.patt: %pattern_type.a4a = value_binding_pattern self [concrete]
|
||||
// CHECK:STDOUT: %self.param_patt: %pattern_type.a4a = value_param_pattern %self.patt, call_param0 [concrete]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %self.param: %E = value_param call_param0
|
||||
// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%E [concrete = constants.%E]
|
||||
// CHECK:STDOUT: %self: %E = value_binding self, %self.param
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
|
||||
// CHECK:STDOUT: complete_type_witness = %complete_type
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%E
|
||||
// CHECK:STDOUT: .J = <poisoned>
|
||||
// CHECK:STDOUT: .G = %E.G.decl
|
||||
// CHECK:STDOUT: .F = <poisoned>
|
||||
// CHECK:STDOUT: extend @E.as.J.impl.%J.ref
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: generic fn @J.F(@J.%Self: %J.type) {
|
||||
// CHECK:STDOUT: %Self: %J.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]
|
||||
// CHECK:STDOUT: %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
|
||||
// CHECK:STDOUT: %pattern_type: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.4c4)]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !definition:
|
||||
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type %Self.binding.as_type [symbolic = %require_complete (constants.%require_complete)]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn(%self.param: @J.F.%Self.binding.as_type (%Self.binding.as_type)) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @E.as.J.impl.F(%self.param: %E) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @E.G(%self.param: %E) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %self.ref: %E = name_ref self, %self
|
||||
// CHECK:STDOUT: %F.ref: %J.assoc_type = name_ref F, @J.%assoc0 [concrete = constants.%assoc0]
|
||||
// CHECK:STDOUT: %impl.elem0: %.225 = impl_witness_access constants.%J.impl_witness, element0 [concrete = constants.%E.as.J.impl.F]
|
||||
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %self.ref, %impl.elem0
|
||||
// CHECK:STDOUT: %E.as.J.impl.F.call: init %empty_tuple.type = call %bound_method(%self.ref)
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @J.F(constants.%Self) {
|
||||
// CHECK:STDOUT: %Self => constants.%Self
|
||||
// CHECK:STDOUT: %Self.binding.as_type => constants.%Self.binding.as_type
|
||||
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.4c4
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @J.F(constants.%J.facet) {
|
||||
// CHECK:STDOUT: %Self => constants.%J.facet
|
||||
// CHECK:STDOUT: %Self.binding.as_type => constants.%E
|
||||
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.a4a
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_use_extend_constant.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %J.type: type = facet_type <@J> [concrete]
|
||||
// CHECK:STDOUT: %Self.dc6: %J.type = symbolic_binding Self, 0 [symbolic]
|
||||
// CHECK:STDOUT: %J.assoc_type: type = assoc_entity_type @J [concrete]
|
||||
// CHECK:STDOUT: %assoc0.8fd: %J.assoc_type = assoc_entity element0, @J.%X [concrete]
|
||||
// CHECK:STDOUT: %E: type = class_type @E [concrete]
|
||||
// CHECK:STDOUT: %.Self: %J.type = symbolic_binding .Self [symbolic_self]
|
||||
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
|
||||
// CHECK:STDOUT: %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]
|
||||
// CHECK:STDOUT: %J.lookup_impl_witness: <witness> = lookup_impl_witness %.Self, @J [symbolic_self]
|
||||
// CHECK:STDOUT: %impl.elem0: type = impl_witness_access %J.lookup_impl_witness, element0 [symbolic_self]
|
||||
// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
|
||||
// CHECK:STDOUT: %J_where.type: type = facet_type <@J where %impl.elem0 = %empty_tuple.type> [concrete]
|
||||
// CHECK:STDOUT: %J.impl_witness: <witness> = impl_witness @E.%J.impl_witness_table [concrete]
|
||||
// CHECK:STDOUT: %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
|
||||
// CHECK:STDOUT: %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %E.G.type: type = fn_type @E.G [concrete]
|
||||
// CHECK:STDOUT: %E.G: %E.G.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
|
||||
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [concrete] {
|
||||
// CHECK:STDOUT: .ImplicitAs = %Core.ImplicitAs
|
||||
// CHECK:STDOUT: import Core//prelude
|
||||
// CHECK:STDOUT: import Core//prelude/...
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
|
||||
// CHECK:STDOUT: .Core = imports.%Core
|
||||
// CHECK:STDOUT: .J = %J.decl
|
||||
// CHECK:STDOUT: .E = %E.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core.import = import Core
|
||||
// CHECK:STDOUT: %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}
|
||||
// CHECK:STDOUT: %E.decl: type = class_decl @E [concrete = constants.%E] {} {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: interface @J {
|
||||
// CHECK:STDOUT: %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self.dc6]
|
||||
// CHECK:STDOUT: %X: type = assoc_const_decl @X [concrete] {
|
||||
// CHECK:STDOUT: %assoc0: %J.assoc_type = assoc_entity element0, @J.%X [concrete = constants.%assoc0.8fd]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = %Self
|
||||
// CHECK:STDOUT: .X = @X.%assoc0
|
||||
// CHECK:STDOUT: witness = (%X)
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !requires:
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: generic assoc_const @X(@J.%Self: %J.type) {
|
||||
// CHECK:STDOUT: assoc_const X:! type;
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: impl @E.as.J.impl: %Self.ref as %.loc8_20 {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: witness = @E.%J.impl_witness
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @E {
|
||||
// CHECK:STDOUT: impl_decl @E.as.J.impl [concrete] {} {
|
||||
// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%E [concrete = constants.%E]
|
||||
// CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
|
||||
// CHECK:STDOUT: %.Self: %J.type = symbolic_binding .Self [symbolic_self = constants.%.Self]
|
||||
// CHECK:STDOUT: %.Self.ref: %J.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
|
||||
// CHECK:STDOUT: %X.ref: %J.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0.8fd]
|
||||
// CHECK:STDOUT: %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.binding.as_type]
|
||||
// CHECK:STDOUT: %.loc8_26: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.binding.as_type]
|
||||
// CHECK:STDOUT: %impl.elem0: type = impl_witness_access constants.%J.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
|
||||
// CHECK:STDOUT: %.loc8_32.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
|
||||
// CHECK:STDOUT: %.loc8_32.2: type = converted %.loc8_32.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
|
||||
// CHECK:STDOUT: %.loc8_20: type = where_expr %.Self [concrete = constants.%J_where.type] {
|
||||
// CHECK:STDOUT: requirement_base_facet_type constants.%J.type
|
||||
// CHECK:STDOUT: requirement_rewrite %impl.elem0, %.loc8_32.2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant), @E.as.J.impl [concrete]
|
||||
// CHECK:STDOUT: %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness]
|
||||
// CHECK:STDOUT: %impl_witness_assoc_constant: type = impl_witness_assoc_constant constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
|
||||
// CHECK:STDOUT: %E.G.decl: %E.G.type = fn_decl @E.G [concrete = constants.%E.G] {
|
||||
// CHECK:STDOUT: %return.patt: <error> = return_slot_pattern [concrete]
|
||||
// CHECK:STDOUT: %return.param_patt: <error> = out_param_pattern %return.patt, call_param0 [concrete]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %X.ref: %J.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0.8fd]
|
||||
// CHECK:STDOUT: %.loc18_13: type = converted %X.ref, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: %return.param: ref <error> = out_param call_param0
|
||||
// CHECK:STDOUT: %return: ref <error> = return_slot %return.param
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
|
||||
// CHECK:STDOUT: complete_type_witness = %complete_type
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%E
|
||||
// CHECK:STDOUT: .J = <poisoned>
|
||||
// CHECK:STDOUT: .X = <poisoned>
|
||||
// CHECK:STDOUT: .G = %E.G.decl
|
||||
// CHECK:STDOUT: extend @E.as.J.impl.%.loc8_20
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @E.G() -> <error> {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %.loc18_25: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
|
||||
// CHECK:STDOUT: return <error> to %return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @X(constants.%Self.dc6) {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @X(constants.%.Self) {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_self_period_associated_type.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
|
||||
Reference in New Issue
Block a user