diff --git a/toolchain/check/deduce.cpp b/toolchain/check/deduce.cpp index ad514915fc0f..7052375fb835 100644 --- a/toolchain/check/deduce.cpp +++ b/toolchain/check/deduce.cpp @@ -80,6 +80,28 @@ class DeductionWorklist { AddAll(context_.inst_blocks().Get(params), args, needs_substitution); } + auto AddAll(SemIR::StructTypeFieldsId params, SemIR::StructTypeFieldsId args, + bool needs_substitution) -> void { + const auto& param_fields = context_.struct_type_fields().Get(params); + const auto& arg_fields = context_.struct_type_fields().Get(args); + if (param_fields.size() != arg_fields.size()) { + // TODO: Decide whether to error on this or just treat the parameter list + // as non-deduced. For now we treat it as non-deduced. + return; + } + // Don't do deduction unless the names match in order. + // TODO: Support reordering of names. + for (auto [param, arg] : llvm::zip_equal(param_fields, arg_fields)) { + if (param.name_id != arg.name_id) { + return; + } + } + for (auto [param, arg] : + llvm::reverse(llvm::zip_equal(param_fields, arg_fields))) { + Add(param.type_id, arg.type_id, needs_substitution); + } + } + auto AddAll(SemIR::InstBlockId params, SemIR::InstBlockId args, bool needs_substitution) -> void { AddAll(context_.inst_blocks().Get(params), context_.inst_blocks().Get(args), @@ -107,6 +129,10 @@ class DeductionWorklist { case SemIR::IdKind::For: Add(SemIR::TypeId(param), SemIR::TypeId(arg), needs_substitution); break; + case SemIR::IdKind::For: + AddAll(SemIR::StructTypeFieldsId(param), SemIR::StructTypeFieldsId(arg), + needs_substitution); + break; case SemIR::IdKind::For: AddAll(SemIR::InstBlockId(param), SemIR::InstBlockId(arg), needs_substitution); @@ -378,6 +404,7 @@ auto DeductionContext::Deduce() -> bool { case SemIR::InterfaceType::Kind: case SemIR::IntType::Kind: case SemIR::PointerType::Kind: + case SemIR::StructType::Kind: case SemIR::TupleType::Kind: case SemIR::TupleValue::Kind: { auto arg_inst = context().insts().Get(arg_id); @@ -392,7 +419,6 @@ auto DeductionContext::Deduce() -> bool { continue; } - case SemIR::StructType::Kind: case SemIR::StructValue::Kind: // TODO: Match field name order between param and arg. break; diff --git a/toolchain/check/testdata/function/generic/deduce.carbon b/toolchain/check/testdata/function/generic/deduce.carbon index 5343be3cf332..776f80ede163 100644 --- a/toolchain/check/testdata/function/generic/deduce.carbon +++ b/toolchain/check/testdata/function/generic/deduce.carbon @@ -77,23 +77,84 @@ fn CallTupleParam() { TupleParam((1, 2)); } -// --- fail_todo_deduce_nested_struct.carbon +// --- deduce_nested_struct.carbon library "[[@TEST_NAME]]"; fn StructParam[T:! type](x: {.a: T, .b: i32}) {} fn CallStructParam() { - // CHECK:STDERR: fail_todo_deduce_nested_struct.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T` [DeductionIncomplete] - // CHECK:STDERR: StructParam({.a = 1, .b = 2}); - // CHECK:STDERR: ^~~~~~~~~~~~ - // CHECK:STDERR: fail_todo_deduce_nested_struct.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere] - // CHECK:STDERR: fn StructParam[T:! type](x: {.a: T, .b: i32}) {} - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: StructParam({.a = 1, .b = 2}); } +// --- fail_deduce_bigger_struct.carbon + +library "[[@TEST_NAME]]"; + +fn BigStructParam[T:! type](x: {.c: T, .d: i32, .e: i32}) {} + +fn CallBigStructParam() { + // CHECK:STDERR: fail_deduce_bigger_struct.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T` [DeductionIncomplete] + // CHECK:STDERR: BigStructParam({.c = 3, .d = 4}); + // CHECK:STDERR: ^~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_deduce_bigger_struct.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere] + // CHECK:STDERR: fn BigStructParam[T:! type](x: {.c: T, .d: i32, .e: i32}) {} + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + BigStructParam({.c = 3, .d = 4}); +} + +// --- fail_deduce_smaller_struct.carbon + +library "[[@TEST_NAME]]"; + +fn SmallStructParam[T:! type](x: {.f: T, .g: i32}) {} + +fn CallSmallStructParam() { + // CHECK:STDERR: fail_deduce_smaller_struct.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T` [DeductionIncomplete] + // CHECK:STDERR: SmallStructParam({.f = 5, .g = 6, .h = 7}); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_deduce_smaller_struct.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere] + // CHECK:STDERR: fn SmallStructParam[T:! type](x: {.f: T, .g: i32}) {} + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + SmallStructParam({.f = 5, .g = 6, .h = 7}); +} + +// --- fail_deduce_struct_wrong_name.carbon + +library "[[@TEST_NAME]]"; + +fn WrongNameStructParam[T:! type](x: {.i: T, .different: i32}) {} + +fn CallWrongNameStructParam() { + // CHECK:STDERR: fail_deduce_struct_wrong_name.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T` [DeductionIncomplete] + // CHECK:STDERR: WrongNameStructParam({.i = 8, .j = 9}); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_deduce_struct_wrong_name.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere] + // CHECK:STDERR: fn WrongNameStructParam[T:! type](x: {.i: T, .different: i32}) {} + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + WrongNameStructParam({.i = 8, .j = 9}); +} + +// --- fail_todo_deduce_struct_wrong_order.carbon + +library "[[@TEST_NAME]]"; + +fn WrongOrderStructParam[T:! type](x: {.first: T, .second: i32}) {} + +fn CallWrongOrderStructParam() { + // CHECK:STDERR: fail_todo_deduce_struct_wrong_order.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T` [DeductionIncomplete] + // CHECK:STDERR: WrongOrderStructParam({.second = 11, .first = 10}); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_todo_deduce_struct_wrong_order.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere] + // CHECK:STDERR: fn WrongOrderStructParam[T:! type](x: {.first: T, .second: i32}) {} + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + WrongOrderStructParam({.second = 11, .first = 10}); +} + // --- fail_deduce_incomplete.carbon library "[[@TEST_NAME]]"; @@ -810,7 +871,7 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: !definition: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_deduce_nested_struct.carbon +// CHECK:STDOUT: --- deduce_nested_struct.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] @@ -827,6 +888,9 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: %.4: i32 = int_value 1 [template] // CHECK:STDOUT: %.5: i32 = int_value 2 [template] // CHECK:STDOUT: %.6: type = struct_type {.a: i32, .b: i32} [template] +// CHECK:STDOUT: %.7: = specific_function %StructParam, @StructParam(i32) [template] +// CHECK:STDOUT: %.8: type = ptr_type %.6 [template] +// CHECK:STDOUT: %struct: %.6 = struct_value (%.4, %.5) [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -882,9 +946,13 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: fn @CallStructParam() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %StructParam.ref: %StructParam.type = name_ref StructParam, file.%StructParam.decl [template = constants.%StructParam] -// CHECK:STDOUT: %.loc14_21: i32 = int_value 1 [template = constants.%.4] -// CHECK:STDOUT: %.loc14_29: i32 = int_value 2 [template = constants.%.5] -// CHECK:STDOUT: %.loc14_30: %.6 = struct_literal (%.loc14_21, %.loc14_29) +// CHECK:STDOUT: %.loc7_21: i32 = int_value 1 [template = constants.%.4] +// CHECK:STDOUT: %.loc7_29: i32 = int_value 2 [template = constants.%.5] +// CHECK:STDOUT: %.loc7_30.1: %.6 = struct_literal (%.loc7_21, %.loc7_29) +// CHECK:STDOUT: %.loc7_3: = specific_function %StructParam.ref, @StructParam(i32) [template = constants.%.7] +// CHECK:STDOUT: %struct: %.6 = struct_value (%.loc7_21, %.loc7_29) [template = constants.%struct] +// CHECK:STDOUT: %.loc7_30.2: %.6 = converted %.loc7_30.1, %struct [template = constants.%struct] +// CHECK:STDOUT: %StructParam.call: init %.1 = call %.loc7_3(%.loc7_30.2) // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: @@ -894,6 +962,355 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: %.loc4_44.2 => constants.%.2 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @StructParam(i32) { +// CHECK:STDOUT: %T.loc4_16.2 => i32 +// CHECK:STDOUT: %T.patt.loc4_16.2 => i32 +// CHECK:STDOUT: %.loc4_44.2 => constants.%.6 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_deduce_bigger_struct.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %.2: type = struct_type {.c: %T, .d: i32, .e: i32} [symbolic] +// CHECK:STDOUT: %BigStructParam.type: type = fn_type @BigStructParam [template] +// CHECK:STDOUT: %BigStructParam: %BigStructParam.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.2 [symbolic] +// CHECK:STDOUT: %CallBigStructParam.type: type = fn_type @CallBigStructParam [template] +// CHECK:STDOUT: %CallBigStructParam: %CallBigStructParam.type = struct_value () [template] +// CHECK:STDOUT: %.4: i32 = int_value 3 [template] +// CHECK:STDOUT: %.5: i32 = int_value 4 [template] +// CHECK:STDOUT: %.6: type = struct_type {.c: i32, .d: i32} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .BigStructParam = %BigStructParam.decl +// CHECK:STDOUT: .CallBigStructParam = %CallBigStructParam.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %BigStructParam.decl: %BigStructParam.type = fn_decl @BigStructParam [template = constants.%BigStructParam] { +// CHECK:STDOUT: %T.patt.loc4_19.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_19.2 (constants.%T.patt)] +// CHECK:STDOUT: %T.param_patt: type = value_param_pattern %T.patt.loc4_19.1, runtime_param [symbolic = %T.patt.loc4_19.2 (constants.%T.patt)] +// CHECK:STDOUT: %x.patt: @BigStructParam.%.loc4_56.2 (%.2) = binding_pattern x +// CHECK:STDOUT: %x.param_patt: @BigStructParam.%.loc4_56.2 (%.2) = value_param_pattern %x.patt, runtime_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc4_19.1 [symbolic = %T.loc4_19.2 (constants.%T)] +// CHECK:STDOUT: %int.make_type_32.loc4_44: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc4_44.1: type = value_of_initializer %int.make_type_32.loc4_44 [template = i32] +// CHECK:STDOUT: %.loc4_44.2: type = converted %int.make_type_32.loc4_44, %.loc4_44.1 [template = i32] +// CHECK:STDOUT: %int.make_type_32.loc4_53: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc4_53.1: type = value_of_initializer %int.make_type_32.loc4_53 [template = i32] +// CHECK:STDOUT: %.loc4_53.2: type = converted %int.make_type_32.loc4_53, %.loc4_53.1 [template = i32] +// CHECK:STDOUT: %.loc4_56.1: type = struct_type {.c: %T, .d: i32, .e: i32} [symbolic = %.loc4_56.2 (constants.%.2)] +// CHECK:STDOUT: %T.param: type = value_param runtime_param +// CHECK:STDOUT: %T.loc4_19.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc4_19.2 (constants.%T)] +// CHECK:STDOUT: %x.param: @BigStructParam.%.loc4_56.2 (%.2) = value_param runtime_param0 +// CHECK:STDOUT: %x: @BigStructParam.%.loc4_56.2 (%.2) = bind_name x, %x.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %CallBigStructParam.decl: %CallBigStructParam.type = fn_decl @CallBigStructParam [template = constants.%CallBigStructParam] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @BigStructParam(%T.loc4_19.1: type) { +// CHECK:STDOUT: %T.loc4_19.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_19.2 (constants.%T)] +// CHECK:STDOUT: %T.patt.loc4_19.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_19.2 (constants.%T.patt)] +// CHECK:STDOUT: %.loc4_56.2: type = struct_type {.c: @BigStructParam.%T.loc4_19.2 (%T), .d: i32, .e: i32} [symbolic = %.loc4_56.2 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.param_patt: type](%x.param_patt: @BigStructParam.%.loc4_56.2 (%.2)) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @CallBigStructParam() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %BigStructParam.ref: %BigStructParam.type = name_ref BigStructParam, file.%BigStructParam.decl [template = constants.%BigStructParam] +// CHECK:STDOUT: %.loc14_24: i32 = int_value 3 [template = constants.%.4] +// CHECK:STDOUT: %.loc14_32: i32 = int_value 4 [template = constants.%.5] +// CHECK:STDOUT: %.loc14_33: %.6 = struct_literal (%.loc14_24, %.loc14_32) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @BigStructParam(constants.%T) { +// CHECK:STDOUT: %T.loc4_19.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_19.2 => constants.%T +// CHECK:STDOUT: %.loc4_56.2 => constants.%.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_deduce_smaller_struct.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %.2: type = struct_type {.f: %T, .g: i32} [symbolic] +// CHECK:STDOUT: %SmallStructParam.type: type = fn_type @SmallStructParam [template] +// CHECK:STDOUT: %SmallStructParam: %SmallStructParam.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.2 [symbolic] +// CHECK:STDOUT: %CallSmallStructParam.type: type = fn_type @CallSmallStructParam [template] +// CHECK:STDOUT: %CallSmallStructParam: %CallSmallStructParam.type = struct_value () [template] +// CHECK:STDOUT: %.4: i32 = int_value 5 [template] +// CHECK:STDOUT: %.5: i32 = int_value 6 [template] +// CHECK:STDOUT: %.6: i32 = int_value 7 [template] +// CHECK:STDOUT: %.7: type = struct_type {.f: i32, .g: i32, .h: i32} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .SmallStructParam = %SmallStructParam.decl +// CHECK:STDOUT: .CallSmallStructParam = %CallSmallStructParam.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %SmallStructParam.decl: %SmallStructParam.type = fn_decl @SmallStructParam [template = constants.%SmallStructParam] { +// CHECK:STDOUT: %T.patt.loc4_21.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_21.2 (constants.%T.patt)] +// CHECK:STDOUT: %T.param_patt: type = value_param_pattern %T.patt.loc4_21.1, runtime_param [symbolic = %T.patt.loc4_21.2 (constants.%T.patt)] +// CHECK:STDOUT: %x.patt: @SmallStructParam.%.loc4_49.2 (%.2) = binding_pattern x +// CHECK:STDOUT: %x.param_patt: @SmallStructParam.%.loc4_49.2 (%.2) = value_param_pattern %x.patt, runtime_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc4_21.1 [symbolic = %T.loc4_21.2 (constants.%T)] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc4_46.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc4_46.2: type = converted %int.make_type_32, %.loc4_46.1 [template = i32] +// CHECK:STDOUT: %.loc4_49.1: type = struct_type {.f: %T, .g: i32} [symbolic = %.loc4_49.2 (constants.%.2)] +// CHECK:STDOUT: %T.param: type = value_param runtime_param +// CHECK:STDOUT: %T.loc4_21.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc4_21.2 (constants.%T)] +// CHECK:STDOUT: %x.param: @SmallStructParam.%.loc4_49.2 (%.2) = value_param runtime_param0 +// CHECK:STDOUT: %x: @SmallStructParam.%.loc4_49.2 (%.2) = bind_name x, %x.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %CallSmallStructParam.decl: %CallSmallStructParam.type = fn_decl @CallSmallStructParam [template = constants.%CallSmallStructParam] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @SmallStructParam(%T.loc4_21.1: type) { +// CHECK:STDOUT: %T.loc4_21.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_21.2 (constants.%T)] +// CHECK:STDOUT: %T.patt.loc4_21.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_21.2 (constants.%T.patt)] +// CHECK:STDOUT: %.loc4_49.2: type = struct_type {.f: @SmallStructParam.%T.loc4_21.2 (%T), .g: i32} [symbolic = %.loc4_49.2 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.param_patt: type](%x.param_patt: @SmallStructParam.%.loc4_49.2 (%.2)) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @CallSmallStructParam() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %SmallStructParam.ref: %SmallStructParam.type = name_ref SmallStructParam, file.%SmallStructParam.decl [template = constants.%SmallStructParam] +// CHECK:STDOUT: %.loc14_26: i32 = int_value 5 [template = constants.%.4] +// CHECK:STDOUT: %.loc14_34: i32 = int_value 6 [template = constants.%.5] +// CHECK:STDOUT: %.loc14_42: i32 = int_value 7 [template = constants.%.6] +// CHECK:STDOUT: %.loc14_43: %.7 = struct_literal (%.loc14_26, %.loc14_34, %.loc14_42) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @SmallStructParam(constants.%T) { +// CHECK:STDOUT: %T.loc4_21.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_21.2 => constants.%T +// CHECK:STDOUT: %.loc4_49.2 => constants.%.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_deduce_struct_wrong_name.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %.2: type = struct_type {.i: %T, .different: i32} [symbolic] +// CHECK:STDOUT: %WrongNameStructParam.type: type = fn_type @WrongNameStructParam [template] +// CHECK:STDOUT: %WrongNameStructParam: %WrongNameStructParam.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.2 [symbolic] +// CHECK:STDOUT: %CallWrongNameStructParam.type: type = fn_type @CallWrongNameStructParam [template] +// CHECK:STDOUT: %CallWrongNameStructParam: %CallWrongNameStructParam.type = struct_value () [template] +// CHECK:STDOUT: %.4: i32 = int_value 8 [template] +// CHECK:STDOUT: %.5: i32 = int_value 9 [template] +// CHECK:STDOUT: %.6: type = struct_type {.i: i32, .j: i32} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .WrongNameStructParam = %WrongNameStructParam.decl +// CHECK:STDOUT: .CallWrongNameStructParam = %CallWrongNameStructParam.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %WrongNameStructParam.decl: %WrongNameStructParam.type = fn_decl @WrongNameStructParam [template = constants.%WrongNameStructParam] { +// CHECK:STDOUT: %T.patt.loc4_25.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_25.2 (constants.%T.patt)] +// CHECK:STDOUT: %T.param_patt: type = value_param_pattern %T.patt.loc4_25.1, runtime_param [symbolic = %T.patt.loc4_25.2 (constants.%T.patt)] +// CHECK:STDOUT: %x.patt: @WrongNameStructParam.%.loc4_61.2 (%.2) = binding_pattern x +// CHECK:STDOUT: %x.param_patt: @WrongNameStructParam.%.loc4_61.2 (%.2) = value_param_pattern %x.patt, runtime_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc4_25.1 [symbolic = %T.loc4_25.2 (constants.%T)] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc4_58.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc4_58.2: type = converted %int.make_type_32, %.loc4_58.1 [template = i32] +// CHECK:STDOUT: %.loc4_61.1: type = struct_type {.i: %T, .different: i32} [symbolic = %.loc4_61.2 (constants.%.2)] +// CHECK:STDOUT: %T.param: type = value_param runtime_param +// CHECK:STDOUT: %T.loc4_25.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc4_25.2 (constants.%T)] +// CHECK:STDOUT: %x.param: @WrongNameStructParam.%.loc4_61.2 (%.2) = value_param runtime_param0 +// CHECK:STDOUT: %x: @WrongNameStructParam.%.loc4_61.2 (%.2) = bind_name x, %x.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %CallWrongNameStructParam.decl: %CallWrongNameStructParam.type = fn_decl @CallWrongNameStructParam [template = constants.%CallWrongNameStructParam] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @WrongNameStructParam(%T.loc4_25.1: type) { +// CHECK:STDOUT: %T.loc4_25.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_25.2 (constants.%T)] +// CHECK:STDOUT: %T.patt.loc4_25.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_25.2 (constants.%T.patt)] +// CHECK:STDOUT: %.loc4_61.2: type = struct_type {.i: @WrongNameStructParam.%T.loc4_25.2 (%T), .different: i32} [symbolic = %.loc4_61.2 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.param_patt: type](%x.param_patt: @WrongNameStructParam.%.loc4_61.2 (%.2)) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @CallWrongNameStructParam() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %WrongNameStructParam.ref: %WrongNameStructParam.type = name_ref WrongNameStructParam, file.%WrongNameStructParam.decl [template = constants.%WrongNameStructParam] +// CHECK:STDOUT: %.loc14_30: i32 = int_value 8 [template = constants.%.4] +// CHECK:STDOUT: %.loc14_38: i32 = int_value 9 [template = constants.%.5] +// CHECK:STDOUT: %.loc14_39: %.6 = struct_literal (%.loc14_30, %.loc14_38) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @WrongNameStructParam(constants.%T) { +// CHECK:STDOUT: %T.loc4_25.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_25.2 => constants.%T +// CHECK:STDOUT: %.loc4_61.2 => constants.%.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_deduce_struct_wrong_order.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %.2: type = struct_type {.first: %T, .second: i32} [symbolic] +// CHECK:STDOUT: %WrongOrderStructParam.type: type = fn_type @WrongOrderStructParam [template] +// CHECK:STDOUT: %WrongOrderStructParam: %WrongOrderStructParam.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.2 [symbolic] +// CHECK:STDOUT: %CallWrongOrderStructParam.type: type = fn_type @CallWrongOrderStructParam [template] +// CHECK:STDOUT: %CallWrongOrderStructParam: %CallWrongOrderStructParam.type = struct_value () [template] +// CHECK:STDOUT: %.4: i32 = int_value 11 [template] +// CHECK:STDOUT: %.5: i32 = int_value 10 [template] +// CHECK:STDOUT: %.6: type = struct_type {.second: i32, .first: i32} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .WrongOrderStructParam = %WrongOrderStructParam.decl +// CHECK:STDOUT: .CallWrongOrderStructParam = %CallWrongOrderStructParam.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %WrongOrderStructParam.decl: %WrongOrderStructParam.type = fn_decl @WrongOrderStructParam [template = constants.%WrongOrderStructParam] { +// CHECK:STDOUT: %T.patt.loc4_26.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_26.2 (constants.%T.patt)] +// CHECK:STDOUT: %T.param_patt: type = value_param_pattern %T.patt.loc4_26.1, runtime_param [symbolic = %T.patt.loc4_26.2 (constants.%T.patt)] +// CHECK:STDOUT: %x.patt: @WrongOrderStructParam.%.loc4_63.2 (%.2) = binding_pattern x +// CHECK:STDOUT: %x.param_patt: @WrongOrderStructParam.%.loc4_63.2 (%.2) = value_param_pattern %x.patt, runtime_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc4_26.1 [symbolic = %T.loc4_26.2 (constants.%T)] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc4_60.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc4_60.2: type = converted %int.make_type_32, %.loc4_60.1 [template = i32] +// CHECK:STDOUT: %.loc4_63.1: type = struct_type {.first: %T, .second: i32} [symbolic = %.loc4_63.2 (constants.%.2)] +// CHECK:STDOUT: %T.param: type = value_param runtime_param +// CHECK:STDOUT: %T.loc4_26.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc4_26.2 (constants.%T)] +// CHECK:STDOUT: %x.param: @WrongOrderStructParam.%.loc4_63.2 (%.2) = value_param runtime_param0 +// CHECK:STDOUT: %x: @WrongOrderStructParam.%.loc4_63.2 (%.2) = bind_name x, %x.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %CallWrongOrderStructParam.decl: %CallWrongOrderStructParam.type = fn_decl @CallWrongOrderStructParam [template = constants.%CallWrongOrderStructParam] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @WrongOrderStructParam(%T.loc4_26.1: type) { +// CHECK:STDOUT: %T.loc4_26.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_26.2 (constants.%T)] +// CHECK:STDOUT: %T.patt.loc4_26.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_26.2 (constants.%T.patt)] +// CHECK:STDOUT: %.loc4_63.2: type = struct_type {.first: @WrongOrderStructParam.%T.loc4_26.2 (%T), .second: i32} [symbolic = %.loc4_63.2 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.param_patt: type](%x.param_patt: @WrongOrderStructParam.%.loc4_63.2 (%.2)) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @CallWrongOrderStructParam() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %WrongOrderStructParam.ref: %WrongOrderStructParam.type = name_ref WrongOrderStructParam, file.%WrongOrderStructParam.decl [template = constants.%WrongOrderStructParam] +// CHECK:STDOUT: %.loc14_36: i32 = int_value 11 [template = constants.%.4] +// CHECK:STDOUT: %.loc14_49: i32 = int_value 10 [template = constants.%.5] +// CHECK:STDOUT: %.loc14_51: %.6 = struct_literal (%.loc14_36, %.loc14_49) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @WrongOrderStructParam(constants.%T) { +// CHECK:STDOUT: %T.loc4_26.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_26.2 => constants.%T +// CHECK:STDOUT: %.loc4_63.2 => constants.%.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_deduce_incomplete.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants {