Implement thunking in terms of constant evaluation (#7332)

The bulk of this change is changing most pattern insts to be `Always`
rather than `AlwaysUnique` constants, so that they can be wrapped in
`SpecificConstant`s to perform substitution. That then lets thunking
rely much more on `SpecificConstant` wrappers instead of deep-copying
the inst tree with modified types.

This approach to thunking should scale better, particularly as things
like form generics make function signatures more complex, because we can
leverage the existing support for constant evaluation and substitution.
Unfortunately, applying this approach to binding patterns will require
more work; see the TODO near the top of `thunk.cpp` for details.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
Geoff Romer
2026-06-13 00:22:00 +00:00
committed by GitHub
co-authored by Richard Smith
parent 40d2d8f68c
commit e023f75254
589 changed files with 22583 additions and 11517 deletions
@@ -434,6 +434,8 @@ fn F() {
// CHECK:STDOUT: %S: type = class_type @S [concrete]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %pattern_type.0f5: type = pattern_type %S [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete]
// CHECK:STDOUT: %S.val: %S = struct_value () [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
@@ -463,8 +465,8 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete = constants.%s.patt]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete = constants.%s.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s.var: ref %S = var %s.var_patt
// CHECK:STDOUT: %.loc8_19.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
@@ -496,6 +498,8 @@ fn F() {
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.282 = ref_binding_pattern p [concrete]
// CHECK:STDOUT: %p.var_patt: %pattern_type.282 = var_pattern %p.patt [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
@@ -522,8 +526,8 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %p.patt: %pattern_type.282 = ref_binding_pattern p [concrete]
// CHECK:STDOUT: %p.var_patt: %pattern_type.282 = var_pattern %p.patt [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.282 = ref_binding_pattern p [concrete = constants.%p.patt]
// CHECK:STDOUT: %p.var_patt: %pattern_type.282 = var_pattern %p.patt [concrete = constants.%p.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %p.var: ref %const = var %p.var_patt
// CHECK:STDOUT: %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]
@@ -562,10 +566,14 @@ fn F() {
// CHECK:STDOUT: %S: type = class_type @S [concrete]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %pattern_type.0f5: type = pattern_type %S [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete]
// CHECK:STDOUT: %S.val: %S = struct_value () [concrete]
// CHECK:STDOUT: %ptr.037: type = ptr_type %S [concrete]
// CHECK:STDOUT: %pattern_type.de6: type = pattern_type %ptr.037 [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.de6 = ref_binding_pattern p [concrete]
// CHECK:STDOUT: %p.var_patt: %pattern_type.de6 = var_pattern %p.patt [concrete]
// CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete]
// CHECK:STDOUT: %T.67d: type = symbolic_binding T, 0 [symbolic]
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.type.ff5: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]
@@ -608,8 +616,8 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete = constants.%s.patt]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete = constants.%s.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s.var: ref %S = var %s.var_patt
// CHECK:STDOUT: %.loc8_19.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
@@ -622,8 +630,8 @@ fn F() {
// CHECK:STDOUT: }
// CHECK:STDOUT: %s: ref %S = ref_binding s, %s.var
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %p.patt: %pattern_type.de6 = ref_binding_pattern p [concrete]
// CHECK:STDOUT: %p.var_patt: %pattern_type.de6 = var_pattern %p.patt [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.de6 = ref_binding_pattern p [concrete = constants.%p.patt]
// CHECK:STDOUT: %p.var_patt: %pattern_type.de6 = var_pattern %p.patt [concrete = constants.%p.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %p.var: ref %ptr.037 = var %p.var_patt
// CHECK:STDOUT: %s.ref: ref %S = name_ref s, %s
@@ -663,6 +671,8 @@ fn F() {
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.914 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.914 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %ptr.711: type = ptr_type %const [concrete]
@@ -690,8 +700,8 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type.914 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.914 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.914 = ref_binding_pattern s [concrete = constants.%s.patt]
// CHECK:STDOUT: %s.var_patt: %pattern_type.914 = var_pattern %s.patt [concrete = constants.%s.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s.var: ref %const = var %s.var_patt
// CHECK:STDOUT: %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]
@@ -727,6 +737,8 @@ fn F() {
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %ptr.037: type = ptr_type %S [concrete]
@@ -756,8 +768,8 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete = constants.%s.patt]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete = constants.%s.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s.var: ref %S = var %s.var_patt
// CHECK:STDOUT: %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]
@@ -791,6 +803,8 @@ fn F() {
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.282 = ref_binding_pattern p [concrete]
// CHECK:STDOUT: %p.var_patt: %pattern_type.282 = var_pattern %p.patt [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
@@ -817,8 +831,8 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %p.patt: %pattern_type.282 = ref_binding_pattern p [concrete]
// CHECK:STDOUT: %p.var_patt: %pattern_type.282 = var_pattern %p.patt [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.282 = ref_binding_pattern p [concrete = constants.%p.patt]
// CHECK:STDOUT: %p.var_patt: %pattern_type.282 = var_pattern %p.patt [concrete = constants.%p.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %p.var: ref %const = var %p.var_patt
// CHECK:STDOUT: %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]
@@ -859,6 +873,8 @@ fn F() {
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.de6 = ref_binding_pattern p [concrete]
// CHECK:STDOUT: %p.var_patt: %pattern_type.de6 = var_pattern %p.patt [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
@@ -885,8 +901,8 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %p.patt: %pattern_type.de6 = ref_binding_pattern p [concrete]
// CHECK:STDOUT: %p.var_patt: %pattern_type.de6 = var_pattern %p.patt [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.de6 = ref_binding_pattern p [concrete = constants.%p.patt]
// CHECK:STDOUT: %p.var_patt: %pattern_type.de6 = var_pattern %p.patt [concrete = constants.%p.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %p.var: ref %ptr = var %p.var_patt
// CHECK:STDOUT: %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]
@@ -920,6 +936,8 @@ fn F() {
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.282 = ref_binding_pattern p [concrete]
// CHECK:STDOUT: %p.var_patt: %pattern_type.282 = var_pattern %p.patt [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %OptionalStorage.type: type = facet_type <@OptionalStorage> [concrete]
@@ -1002,15 +1020,15 @@ fn F() {
// CHECK:STDOUT: %ImplicitAs.impl_witness_table.b0d = impl_witness_table (%Core.import_ref.a74), @const.as.ImplicitAs.impl [concrete]
// CHECK:STDOUT: %Core.import_ref.eb9: @U.as_type.as.ImplicitAs.impl.167.%U.as_type.as.ImplicitAs.impl.Convert.type (%U.as_type.as.ImplicitAs.impl.Convert.type.ad5) = import_ref Core//prelude/types/optional, loc{{\d+_\d+}}, loaded [symbolic = @U.as_type.as.ImplicitAs.impl.167.%U.as_type.as.ImplicitAs.impl.Convert (constants.%U.as_type.as.ImplicitAs.impl.Convert.331)]
// CHECK:STDOUT: %ImplicitAs.impl_witness_table.cf7 = impl_witness_table (%Core.import_ref.eb9), @U.as_type.as.ImplicitAs.impl.167 [concrete]
// CHECK:STDOUT: %Core.import_ref.017: @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert.type (%T.as_type.as.OptionalAs.impl.Convert.type.774) = import_ref Core//prelude/types/optional, loc{{\d+_\d+}}, loaded [symbolic = @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert (constants.%T.as_type.as.OptionalAs.impl.Convert.5f9)]
// CHECK:STDOUT: %OptionalAs.impl_witness_table.efa = impl_witness_table (%Core.import_ref.017), @T.as_type.as.OptionalAs.impl [concrete]
// CHECK:STDOUT: %Core.import_ref.017d8: @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert.type (%T.as_type.as.OptionalAs.impl.Convert.type.774) = import_ref Core//prelude/types/optional, loc{{\d+_\d+}}, loaded [symbolic = @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert (constants.%T.as_type.as.OptionalAs.impl.Convert.5f9)]
// CHECK:STDOUT: %OptionalAs.impl_witness_table.efa = impl_witness_table (%Core.import_ref.017d8), @T.as_type.as.OptionalAs.impl [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %p.patt: %pattern_type.282 = ref_binding_pattern p [concrete]
// CHECK:STDOUT: %p.var_patt: %pattern_type.282 = var_pattern %p.patt [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.282 = ref_binding_pattern p [concrete = constants.%p.patt]
// CHECK:STDOUT: %p.var_patt: %pattern_type.282 = var_pattern %p.patt [concrete = constants.%p.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %p.var: ref %const.f96 = var %p.var_patt
// CHECK:STDOUT: %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]
@@ -1073,6 +1091,8 @@ fn F() {
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.de6 = ref_binding_pattern p [concrete]
// CHECK:STDOUT: %p.var_patt: %pattern_type.de6 = var_pattern %p.patt [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %OptionalStorage.type: type = facet_type <@OptionalStorage> [concrete]
@@ -1145,15 +1165,15 @@ fn F() {
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import_ref.eb9: @U.as_type.as.ImplicitAs.impl.167.%U.as_type.as.ImplicitAs.impl.Convert.type (%U.as_type.as.ImplicitAs.impl.Convert.type.ad5) = import_ref Core//prelude/types/optional, loc{{\d+_\d+}}, loaded [symbolic = @U.as_type.as.ImplicitAs.impl.167.%U.as_type.as.ImplicitAs.impl.Convert (constants.%U.as_type.as.ImplicitAs.impl.Convert.331)]
// CHECK:STDOUT: %ImplicitAs.impl_witness_table.cf7 = impl_witness_table (%Core.import_ref.eb9), @U.as_type.as.ImplicitAs.impl.167 [concrete]
// CHECK:STDOUT: %Core.import_ref.017: @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert.type (%T.as_type.as.OptionalAs.impl.Convert.type.774) = import_ref Core//prelude/types/optional, loc{{\d+_\d+}}, loaded [symbolic = @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert (constants.%T.as_type.as.OptionalAs.impl.Convert.5f9)]
// CHECK:STDOUT: %OptionalAs.impl_witness_table.efa = impl_witness_table (%Core.import_ref.017), @T.as_type.as.OptionalAs.impl [concrete]
// CHECK:STDOUT: %Core.import_ref.017d8: @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert.type (%T.as_type.as.OptionalAs.impl.Convert.type.774) = import_ref Core//prelude/types/optional, loc{{\d+_\d+}}, loaded [symbolic = @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert (constants.%T.as_type.as.OptionalAs.impl.Convert.5f9)]
// CHECK:STDOUT: %OptionalAs.impl_witness_table.efa = impl_witness_table (%Core.import_ref.017d8), @T.as_type.as.OptionalAs.impl [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %p.patt: %pattern_type.de6 = ref_binding_pattern p [concrete]
// CHECK:STDOUT: %p.var_patt: %pattern_type.de6 = var_pattern %p.patt [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.de6 = ref_binding_pattern p [concrete = constants.%p.patt]
// CHECK:STDOUT: %p.var_patt: %pattern_type.de6 = var_pattern %p.patt [concrete = constants.%p.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %p.var: ref %ptr.037 = var %p.var_patt
// CHECK:STDOUT: %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]
@@ -1342,6 +1362,8 @@ fn F() {
// CHECK:STDOUT: %S: type = class_type @S [concrete]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %pattern_type.0f5: type = pattern_type %S [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete]
// CHECK:STDOUT: %S.val: %S = struct_value () [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
@@ -1419,15 +1441,15 @@ fn F() {
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import_ref.eb9: @U.as_type.as.ImplicitAs.impl.167.%U.as_type.as.ImplicitAs.impl.Convert.type (%U.as_type.as.ImplicitAs.impl.Convert.type.ad5) = import_ref Core//prelude/types/optional, loc{{\d+_\d+}}, loaded [symbolic = @U.as_type.as.ImplicitAs.impl.167.%U.as_type.as.ImplicitAs.impl.Convert (constants.%U.as_type.as.ImplicitAs.impl.Convert.331)]
// CHECK:STDOUT: %ImplicitAs.impl_witness_table.cf7 = impl_witness_table (%Core.import_ref.eb9), @U.as_type.as.ImplicitAs.impl.167 [concrete]
// CHECK:STDOUT: %Core.import_ref.017: @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert.type (%T.as_type.as.OptionalAs.impl.Convert.type.774) = import_ref Core//prelude/types/optional, loc{{\d+_\d+}}, loaded [symbolic = @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert (constants.%T.as_type.as.OptionalAs.impl.Convert.5f9)]
// CHECK:STDOUT: %OptionalAs.impl_witness_table.efa = impl_witness_table (%Core.import_ref.017), @T.as_type.as.OptionalAs.impl [concrete]
// CHECK:STDOUT: %Core.import_ref.017d8: @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert.type (%T.as_type.as.OptionalAs.impl.Convert.type.774) = import_ref Core//prelude/types/optional, loc{{\d+_\d+}}, loaded [symbolic = @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert (constants.%T.as_type.as.OptionalAs.impl.Convert.5f9)]
// CHECK:STDOUT: %OptionalAs.impl_witness_table.efa = impl_witness_table (%Core.import_ref.017d8), @T.as_type.as.OptionalAs.impl [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete = constants.%s.patt]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete = constants.%s.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s.var: ref %S = var %s.var_patt
// CHECK:STDOUT: %.loc8_19.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
@@ -1599,6 +1621,8 @@ fn F() {
// CHECK:STDOUT: %S: type = class_type @S [concrete]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %pattern_type.0f5: type = pattern_type %S [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete]
// CHECK:STDOUT: %S.val: %S = struct_value () [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
@@ -1678,8 +1702,8 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete = constants.%s.patt]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete = constants.%s.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s.var: ref %S = var %s.var_patt
// CHECK:STDOUT: %.loc8_19.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
@@ -1705,16 +1729,18 @@ fn F() {
// CHECK:STDOUT: %Some.ref: %Optional.Some.type.004 = name_ref Some, %.loc9_32 [concrete = constants.%Optional.Some.9ba]
// CHECK:STDOUT: %s.ref: ref %S = name_ref s, %s
// CHECK:STDOUT: %addr: %ptr.037 = addr_of %s.ref
// CHECK:STDOUT: %OptionalStorage.facet.loc9_40: %OptionalStorage.type = facet_value constants.%ptr.037, (constants.%OptionalStorage.impl_witness.582) [concrete = constants.%OptionalStorage.facet]
// CHECK:STDOUT: %.loc9_40.1: %OptionalStorage.type = converted constants.%ptr.037, %OptionalStorage.facet.loc9_40 [concrete = constants.%OptionalStorage.facet]
// CHECK:STDOUT: %OptionalStorage.facet.loc9_40.1: %OptionalStorage.type = facet_value constants.%ptr.037, (constants.%OptionalStorage.impl_witness.582) [concrete = constants.%OptionalStorage.facet]
// CHECK:STDOUT: %.loc9_40.1: %OptionalStorage.type = converted constants.%ptr.037, %OptionalStorage.facet.loc9_40.1 [concrete = constants.%OptionalStorage.facet]
// CHECK:STDOUT: %OptionalStorage.facet.loc9_40.2: %OptionalStorage.type = facet_value constants.%ptr.037, (constants.%OptionalStorage.impl_witness.582) [concrete = constants.%OptionalStorage.facet]
// CHECK:STDOUT: %.loc9_40.2: %OptionalStorage.type = converted constants.%ptr.037, %OptionalStorage.facet.loc9_40.2 [concrete = constants.%OptionalStorage.facet]
// CHECK:STDOUT: %Optional.Some.specific_fn: <specific function> = specific_function %Some.ref, @Optional.Some(constants.%OptionalStorage.facet) [concrete = constants.%Optional.Some.specific_fn]
// CHECK:STDOUT: %Optional.Some.call: init %Optional.659 = call %Optional.Some.specific_fn(%addr)
// CHECK:STDOUT: %.loc9_40.2: ref %Optional.659 = temporary_storage
// CHECK:STDOUT: %.loc9_40.3: ref %Optional.659 = temporary %.loc9_40.2, %Optional.Some.call
// CHECK:STDOUT: %.loc9_40.4: %Optional.659 = acquire_value %.loc9_40.3
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc9_40.4)
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %.loc9_40.3, constants.%Destroy.Op.1a2547.4
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc9_40.3)
// CHECK:STDOUT: %.loc9_40.3: ref %Optional.659 = temporary_storage
// CHECK:STDOUT: %.loc9_40.4: ref %Optional.659 = temporary %.loc9_40.3, %Optional.Some.call
// CHECK:STDOUT: %.loc9_40.5: %Optional.659 = acquire_value %.loc9_40.4
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc9_40.5)
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %.loc9_40.4, constants.%Destroy.Op.1a2547.4
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc9_40.4)
// CHECK:STDOUT: %S.cpp_destructor.bound: <bound method> = bound_method %s.var, constants.%S.cpp_destructor
// CHECK:STDOUT: %S.cpp_destructor.call: init %empty_tuple.type = call %S.cpp_destructor.bound(%s.var)
// CHECK:STDOUT: <elided>
@@ -1843,10 +1869,13 @@ fn F() {
// CHECK:STDOUT: %S: type = class_type @S [concrete]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %pattern_type.0f5: type = pattern_type %S [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete]
// CHECK:STDOUT: %S.val: %S = struct_value () [concrete]
// CHECK:STDOUT: %ptr.037: type = ptr_type %S [concrete]
// CHECK:STDOUT: %pattern_type.de6: type = pattern_type %ptr.037 [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.de6 = value_binding_pattern p [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
@@ -1873,8 +1902,8 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete = constants.%s.patt]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete = constants.%s.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s.var: ref %S = var %s.var_patt
// CHECK:STDOUT: %.loc8_19.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
@@ -1887,20 +1916,20 @@ fn F() {
// CHECK:STDOUT: }
// CHECK:STDOUT: %s: ref %S = ref_binding s, %s.var
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %p.patt: %pattern_type.de6 = value_binding_pattern p [concrete]
// CHECK:STDOUT: %p.patt: %pattern_type.de6 = value_binding_pattern p [concrete = constants.%p.patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %Cpp.ref.loc13_26: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value]
// CHECK:STDOUT: %s.ref: ref %S = name_ref s, %s
// CHECK:STDOUT: %addr: %ptr.037 = addr_of %s.ref
// CHECK:STDOUT: %foo.call: init %ptr.037 = call imports.%foo.decl(%addr)
// CHECK:STDOUT: %.loc13_36.1: %ptr.037 = value_of_initializer %foo.call
// CHECK:STDOUT: %.loc13_36.2: %ptr.037 = converted %foo.call, %.loc13_36.1
// CHECK:STDOUT: %.loc13_22: type = splice_block %ptr [concrete = constants.%ptr.037] {
// CHECK:STDOUT: %Cpp.ref.loc13_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %S.ref.loc13: type = name_ref S, imports.%S.decl [concrete = constants.%S]
// CHECK:STDOUT: %ptr: type = ptr_type %S.ref.loc13 [concrete = constants.%ptr.037]
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc13_36.1: %ptr.037 = value_of_initializer %foo.call
// CHECK:STDOUT: %.loc13_36.2: %ptr.037 = converted %foo.call, %.loc13_36.1
// CHECK:STDOUT: %p: %ptr.037 = value_binding p, %.loc13_36.2
// CHECK:STDOUT: %S.cpp_destructor.bound: <bound method> = bound_method %s.var, constants.%S.cpp_destructor
// CHECK:STDOUT: %S.cpp_destructor.call: init %empty_tuple.type = call %S.cpp_destructor.bound(%s.var)
@@ -1914,6 +1943,8 @@ fn F() {
// CHECK:STDOUT: %S: type = class_type @S [concrete]
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
// CHECK:STDOUT: %pattern_type.0f5: type = pattern_type %S [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete]
// CHECK:STDOUT: %S.val: %S = struct_value () [concrete]
// CHECK:STDOUT: %Direct.cpp_overload_set.type: type = cpp_overload_set_type @Direct.cpp_overload_set [concrete]
@@ -1962,6 +1993,7 @@ fn F() {
// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.c92: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%Optional.659, %ImplicitAs.facet.21e) [concrete]
// CHECK:STDOUT: %.c09: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.c92, %ImplicitAs.facet.21e [concrete]
// CHECK:STDOUT: %U.as_type.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %U.as_type.as.ImplicitAs.impl.Convert.8f4, @U.as_type.as.ImplicitAs.impl.Convert.2(%OptionalStorage.facet.0ce, %OptionalAs.facet) [concrete]
// CHECK:STDOUT: %a.patt: %pattern_type.9f4 = value_binding_pattern a [concrete]
// CHECK:STDOUT: %Indirect.cpp_overload_set.type: type = cpp_overload_set_type @Indirect.cpp_overload_set [concrete]
// CHECK:STDOUT: %Indirect.cpp_overload_set.value: %Indirect.cpp_overload_set.type = cpp_overload_set_value @Indirect.cpp_overload_set [concrete]
// CHECK:STDOUT: %Indirect__carbon_thunk.type: type = fn_type @Indirect__carbon_thunk [concrete]
@@ -2014,8 +2046,8 @@ fn F() {
// CHECK:STDOUT: %Core.ImplicitAs: %ImplicitAs.type.0ff = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
// CHECK:STDOUT: %Core.import_ref.eb9: @U.as_type.as.ImplicitAs.impl.167.%U.as_type.as.ImplicitAs.impl.Convert.type (%U.as_type.as.ImplicitAs.impl.Convert.type.ad5) = import_ref Core//prelude/types/optional, loc{{\d+_\d+}}, loaded [symbolic = @U.as_type.as.ImplicitAs.impl.167.%U.as_type.as.ImplicitAs.impl.Convert (constants.%U.as_type.as.ImplicitAs.impl.Convert.331)]
// CHECK:STDOUT: %ImplicitAs.impl_witness_table.cf7 = impl_witness_table (%Core.import_ref.eb9), @U.as_type.as.ImplicitAs.impl.167 [concrete]
// CHECK:STDOUT: %Core.import_ref.017: @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert.type (%T.as_type.as.OptionalAs.impl.Convert.type.774) = import_ref Core//prelude/types/optional, loc{{\d+_\d+}}, loaded [symbolic = @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert (constants.%T.as_type.as.OptionalAs.impl.Convert.5f9)]
// CHECK:STDOUT: %OptionalAs.impl_witness_table.efa = impl_witness_table (%Core.import_ref.017), @T.as_type.as.OptionalAs.impl [concrete]
// CHECK:STDOUT: %Core.import_ref.017d8: @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert.type (%T.as_type.as.OptionalAs.impl.Convert.type.774) = import_ref Core//prelude/types/optional, loc{{\d+_\d+}}, loaded [symbolic = @T.as_type.as.OptionalAs.impl.%T.as_type.as.OptionalAs.impl.Convert (constants.%T.as_type.as.OptionalAs.impl.Convert.5f9)]
// CHECK:STDOUT: %OptionalAs.impl_witness_table.efa = impl_witness_table (%Core.import_ref.017d8), @T.as_type.as.OptionalAs.impl [concrete]
// CHECK:STDOUT: %Indirect.cpp_overload_set.value: %Indirect.cpp_overload_set.type = cpp_overload_set_value @Indirect.cpp_overload_set [concrete = constants.%Indirect.cpp_overload_set.value]
// CHECK:STDOUT: %Indirect__carbon_thunk.decl: %Indirect__carbon_thunk.type = fn_decl @Indirect__carbon_thunk [concrete = constants.%Indirect__carbon_thunk] {
// CHECK:STDOUT: <elided>
@@ -2031,8 +2063,8 @@ fn F() {
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type.0f5 = ref_binding_pattern s [concrete = constants.%s.patt]
// CHECK:STDOUT: %s.var_patt: %pattern_type.0f5 = var_pattern %s.patt [concrete = constants.%s.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s.var: ref %S = var %s.var_patt
// CHECK:STDOUT: %.loc10_19.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
@@ -2059,7 +2091,7 @@ fn F() {
// CHECK:STDOUT: %.loc11_14.4: %Optional.659 = acquire_value %.loc11_14.3
// CHECK:STDOUT: %Direct.call: init %Optional.659 = call imports.%Direct.decl(%.loc11_14.4)
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %a.patt: %pattern_type.9f4 = value_binding_pattern a [concrete]
// CHECK:STDOUT: %a.patt: %pattern_type.9f4 = value_binding_pattern a [concrete = constants.%a.patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: %Cpp.ref.loc13_41: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Indirect.ref: %Indirect.cpp_overload_set.type = name_ref Indirect, imports.%Indirect.cpp_overload_set.value [concrete = constants.%Indirect.cpp_overload_set.value]
@@ -2074,6 +2106,9 @@ fn F() {
// CHECK:STDOUT: %.loc13_57.4: ref %S = value_as_ref %.loc13_57.3
// CHECK:STDOUT: %addr.loc13: %ptr.037 = addr_of %.loc13_57.4
// CHECK:STDOUT: %Indirect__carbon_thunk.call: init %Optional.659 = call imports.%Indirect__carbon_thunk.decl(%addr.loc13)
// CHECK:STDOUT: %.loc13_65.1: ref %Optional.659 = temporary_storage
// CHECK:STDOUT: %.loc13_65.2: ref %Optional.659 = temporary %.loc13_65.1, %Indirect__carbon_thunk.call
// CHECK:STDOUT: %.loc13_65.3: %Optional.659 = acquire_value %.loc13_65.2
// CHECK:STDOUT: %.loc13_37.1: type = splice_block %Optional [concrete = constants.%Optional.659] {
// CHECK:STDOUT: %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]
// CHECK:STDOUT: %Optional.ref: %Optional.type = name_ref Optional, imports.%Core.Optional [concrete = constants.%Optional.generic]
@@ -2084,9 +2119,6 @@ fn F() {
// CHECK:STDOUT: %.loc13_37.2: %OptionalStorage.type = converted %ptr, %OptionalStorage.facet [concrete = constants.%OptionalStorage.facet.0ce]
// CHECK:STDOUT: %Optional: type = class_type @Optional, @Optional(constants.%OptionalStorage.facet.0ce) [concrete = constants.%Optional.659]
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc13_65.1: ref %Optional.659 = temporary_storage
// CHECK:STDOUT: %.loc13_65.2: ref %Optional.659 = temporary %.loc13_65.1, %Indirect__carbon_thunk.call
// CHECK:STDOUT: %.loc13_65.3: %Optional.659 = acquire_value %.loc13_65.2
// CHECK:STDOUT: %a: %Optional.659 = value_binding a, %.loc13_65.3
// CHECK:STDOUT: %Destroy.Op.bound.loc13: <bound method> = bound_method %.loc13_65.2, constants.%Destroy.Op.1a2547.4
// CHECK:STDOUT: %Destroy.Op.call.loc13: init %empty_tuple.type = call %Destroy.Op.bound.loc13(%.loc13_65.2)