Add an interface for initialization of vars without an explicit initializer (#6934)

When a `var` is not explicitly given an initializer, initialize it in
one of two ways:

* If its type implements the new interface `Core.Default`, call
`Core.Default.Op` to initialize it.
* Otherwise, if its type implements `UnformedInit`, leave it in an
unformed state. For now, this is always an uninitialized state, but that
will change in the future.
* If neither of those apply, the `var` declaration is ill-formed.

This is a step towards implementing leads decision #6739 and proposals
#257 and #5913.

Assisted-by: Gemini 3.1 Pro via Antigravity

---------

Co-authored-by: Geoff Romer <gromer@google.com>
This commit is contained in:
Richard Smith
2026-03-19 23:46:06 +00:00
committed by GitHub
co-authored by Geoff Romer
parent fd2d210c63
commit ce50f181f1
146 changed files with 5226 additions and 3535 deletions
+30
View File
@@ -140,6 +140,7 @@ var a: array(1, 1);
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %a.ref: ref %tuple.type = name_ref a, file.%a [concrete = file.%a.var]
// CHECK:STDOUT: %tuple.elem0: ref %empty_tuple.type = tuple_access %a.ref, element0 [concrete = constants.%tuple.elem0]
// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]
@@ -230,15 +231,28 @@ var a: array(1, 1);
// CHECK:STDOUT: %int_3: Core.IntLiteral = int_value 3 [concrete]
// CHECK:STDOUT: %array_type: type = array_type %int_3, %empty_tuple.type [concrete]
// CHECK:STDOUT: %pattern_type.035: type = pattern_type %array_type [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]
// CHECK:STDOUT: %T: type = symbolic_binding T, 0 [symbolic]
// CHECK:STDOUT: %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]
// CHECK:STDOUT: %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]
// CHECK:STDOUT: %DefaultOrUnformed.impl_witness.924: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%array_type) [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.facet.86d: %DefaultOrUnformed.type = facet_value %array_type, (%DefaultOrUnformed.impl_witness.924) [concrete]
// CHECK:STDOUT: %tuple.type: type = tuple_type (%empty_tuple.type, %empty_tuple.type, %empty_tuple.type) [concrete]
// CHECK:STDOUT: %tuple: %tuple.type = tuple_value (%empty_tuple, %empty_tuple, %empty_tuple) [concrete]
// CHECK:STDOUT: %pattern_type.8c1: type = pattern_type %tuple.type [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.impl_witness.032: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%tuple.type) [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.facet.1ea: %DefaultOrUnformed.type = facet_value %tuple.type, (%DefaultOrUnformed.impl_witness.032) [concrete]
// CHECK:STDOUT: %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc8 [concrete]
// CHECK:STDOUT: %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc7 [concrete]
// CHECK:STDOUT: %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\d+_\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]
// CHECK:STDOUT: %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @G() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
@@ -246,6 +260,14 @@ var a: array(1, 1);
// CHECK:STDOUT: %a.var_patt: %pattern_type.035 = var_pattern %a.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a.var: ref %array_type = var %a.var_patt
// CHECK:STDOUT: %DefaultOrUnformed.facet.loc7: %DefaultOrUnformed.type = facet_value constants.%array_type, (constants.%DefaultOrUnformed.impl_witness.924) [concrete = constants.%DefaultOrUnformed.facet.86d]
// CHECK:STDOUT: %.loc7_29.1: %DefaultOrUnformed.type = converted constants.%array_type, %DefaultOrUnformed.facet.loc7 [concrete = constants.%DefaultOrUnformed.facet.86d]
// CHECK:STDOUT: %as_type.loc7: type = facet_access_type %.loc7_29.1 [concrete = constants.%array_type]
// CHECK:STDOUT: %.loc7_29.2: type = converted %.loc7_29.1, %as_type.loc7 [concrete = constants.%array_type]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %.loc7_3: ref %array_type = splice_block %a.var {}
// CHECK:STDOUT: %T.as.DefaultOrUnformed.impl.Op.call.loc7: init %array_type to %.loc7_3 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn.1()
// CHECK:STDOUT: assign %a.var, %T.as.DefaultOrUnformed.impl.Op.call.loc7
// CHECK:STDOUT: %.loc7_28: type = splice_block %array_type [concrete = constants.%array_type] {
// CHECK:STDOUT: %.loc7_24.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
// CHECK:STDOUT: %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]
@@ -258,6 +280,14 @@ var a: array(1, 1);
// CHECK:STDOUT: %b.var_patt: %pattern_type.8c1 = var_pattern %b.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %b.var: ref %tuple.type = var %b.var_patt
// CHECK:STDOUT: %DefaultOrUnformed.facet.loc8: %DefaultOrUnformed.type = facet_value constants.%tuple.type, (constants.%DefaultOrUnformed.impl_witness.032) [concrete = constants.%DefaultOrUnformed.facet.1ea]
// CHECK:STDOUT: %.loc8_29.1: %DefaultOrUnformed.type = converted constants.%tuple.type, %DefaultOrUnformed.facet.loc8 [concrete = constants.%DefaultOrUnformed.facet.1ea]
// CHECK:STDOUT: %as_type.loc8: type = facet_access_type %.loc8_29.1 [concrete = constants.%tuple.type]
// CHECK:STDOUT: %.loc8_29.2: type = converted %.loc8_29.1, %as_type.loc8 [concrete = constants.%tuple.type]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %.loc8_3: ref %tuple.type = splice_block %b.var {}
// CHECK:STDOUT: %T.as.DefaultOrUnformed.impl.Op.call.loc8: init %tuple.type to %.loc8_3 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn.2()
// CHECK:STDOUT: assign %b.var, %T.as.DefaultOrUnformed.impl.Op.call.loc8
// CHECK:STDOUT: %.loc8_28.1: type = splice_block %.loc8_28.6 [concrete = constants.%tuple.type] {
// CHECK:STDOUT: %.loc8_19: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
// CHECK:STDOUT: %.loc8_23: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]