diff --git a/toolchain/check/deduce.cpp b/toolchain/check/deduce.cpp index de9b746da5451..e4035ba3c2112 100644 --- a/toolchain/check/deduce.cpp +++ b/toolchain/check/deduce.cpp @@ -39,11 +39,31 @@ class DeductionWorklist { {.param = param, .arg = arg, .needs_substitution = needs_substitution}); } + // Adds a single (param, arg) type deduction. + auto Add(SemIR::TypeId param, SemIR::TypeId arg, bool needs_substitution) + -> void { + Add(context_.types().GetInstId(param), context_.types().GetInstId(arg), + needs_substitution); + } + + // Adds a single (param, arg) deduction of a specific. + auto Add(SemIR::SpecificId param, SemIR::SpecificId arg, + bool needs_substitution) -> void { + auto& param_specific = context_.specifics().Get(param); + auto& arg_specific = context_.specifics().Get(arg); + if (param_specific.generic_id != arg_specific.generic_id) { + // TODO: Decide whether to error on this or just treat the specific as + // non-deduced. For now we treat it as non-deduced. + return; + } + AddAll(param_specific.args_id, arg_specific.args_id, needs_substitution); + } + // Adds a list of (param, arg) deductions. These are added in reverse order so // they are popped in forward order. - auto AddAll(llvm::ArrayRef params, - llvm::ArrayRef args, bool needs_substitution) - -> void { + template + auto AddAll(llvm::ArrayRef params, llvm::ArrayRef args, + bool needs_substitution) -> void { if (params.size() != args.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. @@ -65,6 +85,44 @@ class DeductionWorklist { needs_substitution); } + auto AddAll(SemIR::TypeBlockId params, SemIR::TypeBlockId args, + bool needs_substitution) -> void { + AddAll(context_.type_blocks().Get(params), context_.type_blocks().Get(args), + needs_substitution); + } + + // Adds a (param, arg) pair for an instruction argument, given its kind. + auto AddInstArg(SemIR::IdKind kind, int32_t param, int32_t arg, + bool needs_substitution) -> void { + switch (kind) { + case SemIR::IdKind::None: + case SemIR::IdKind::For: + case SemIR::IdKind::For: + case SemIR::IdKind::For: + break; + case SemIR::IdKind::For: + Add(SemIR::InstId(param), SemIR::InstId(arg), needs_substitution); + break; + case SemIR::IdKind::For: + Add(SemIR::TypeId(param), SemIR::TypeId(arg), needs_substitution); + break; + case SemIR::IdKind::For: + AddAll(SemIR::InstBlockId(param), SemIR::InstBlockId(arg), + needs_substitution); + break; + case SemIR::IdKind::For: + AddAll(SemIR::TypeBlockId(param), SemIR::TypeBlockId(arg), + needs_substitution); + break; + case SemIR::IdKind::For: + Add(SemIR::SpecificId(param), SemIR::SpecificId(arg), + needs_substitution); + break; + default: + CARBON_FATAL("unexpected argument kind"); + } + } + // Returns whether we have completed all deductions. auto Done() -> bool { return deductions_.empty(); } @@ -208,65 +266,99 @@ auto DeductionContext::Deduce() -> bool { } } - // If the parameter is a symbolic constant, deduce against it. + // If the parameter is a symbolic constant, deduce against it. Otherwise, we + // assume there is nothing to deduce. + // TODO: This won't do the right thing in a template deduction. auto param_const_id = context().constant_values().Get(param_id); if (!param_const_id.is_valid() || !param_const_id.is_symbolic()) { continue; } - // If we've not yet substituted into the parameter, do so now. - if (needs_substitution) { - param_const_id = SubstConstant(context(), param_const_id, substitutions_); - if (!param_const_id.is_valid() || !param_const_id.is_symbolic()) { - continue; - } - needs_substitution = false; - } - - CARBON_KIND_SWITCH(context().insts().Get( - context().constant_values().GetInstId( - param_const_id))) { + // Attempt to match `param_inst` against `arg_id`. If the match succeeds, + // this should `continue` the outer loop. On `break`, we will try to desugar + // the parameter to continue looking for a match. + auto param_inst = context().insts().Get( + context().constant_values().GetInstId(param_const_id)); + CARBON_KIND_SWITCH(param_inst) { // Deducing a symbolic binding from an argument with a constant value // deduces the binding as having that constant value. case CARBON_KIND(SemIR::BindSymbolicName bind): { auto& entity_name = context().entity_names().Get(bind.entity_name_id); auto index = entity_name.bind_index; - if (index.is_valid() && index >= first_deduced_index_) { - CARBON_CHECK( - static_cast(index.index) < result_arg_ids_.size(), - "Deduced value for unexpected index {0}; expected to " - "deduce {1} arguments.", - index, result_arg_ids_.size()); - auto arg_const_inst_id = - context().constant_values().GetConstantInstId(arg_id); - if (arg_const_inst_id.is_valid()) { - if (result_arg_ids_[index.index].is_valid() && - result_arg_ids_[index.index] != arg_const_inst_id) { - if (diagnose_) { - // TODO: Include the two different deduced values. - CARBON_DIAGNOSTIC( - DeductionInconsistent, Error, - "inconsistent deductions for value of generic " - "parameter `{0}`", - SemIR::NameId); - auto diag = context().emitter().Build( - loc_id_, DeductionInconsistent, entity_name.name_id); - NoteGenericHere(context(), generic_id_, diag); - diag.Emit(); - } - return false; + if (!index.is_valid() || index < first_deduced_index_) { + break; + } + + CARBON_CHECK(static_cast(index.index) < result_arg_ids_.size(), + "Deduced value for unexpected index {0}; expected to " + "deduce {1} arguments.", + index, result_arg_ids_.size()); + auto arg_const_inst_id = + context().constant_values().GetConstantInstId(arg_id); + if (arg_const_inst_id.is_valid()) { + if (result_arg_ids_[index.index].is_valid() && + result_arg_ids_[index.index] != arg_const_inst_id) { + if (diagnose_) { + // TODO: Include the two different deduced values. + CARBON_DIAGNOSTIC(DeductionInconsistent, Error, + "inconsistent deductions for value of generic " + "parameter `{0}`", + SemIR::NameId); + auto diag = context().emitter().Build( + loc_id_, DeductionInconsistent, entity_name.name_id); + NoteGenericHere(context(), generic_id_, diag); + diag.Emit(); } - result_arg_ids_[index.index] = arg_const_inst_id; + return false; } + result_arg_ids_[index.index] = arg_const_inst_id; } - break; + continue; } + // Various kinds of parameter should match an argument of the same form, + // if the operands all match. + case SemIR::ArrayType::Kind: + case SemIR::ClassType::Kind: + case SemIR::ConstType::Kind: + case SemIR::FloatType::Kind: + case SemIR::InterfaceType::Kind: + case SemIR::IntType::Kind: + case SemIR::PointerType::Kind: + case SemIR::TupleType::Kind: + case SemIR::TupleValue::Kind: { + auto arg_inst = context().insts().Get(arg_id); + if (arg_inst.kind() != param_inst.kind()) { + break; + } + auto [kind0, kind1] = param_inst.ArgKinds(); + worklist_.AddInstArg(kind0, param_inst.arg0(), arg_inst.arg0(), + needs_substitution); + worklist_.AddInstArg(kind1, param_inst.arg1(), arg_inst.arg1(), + needs_substitution); + continue; + } + + case SemIR::StructType::Kind: + case SemIR::StructValue::Kind: + // TODO: Match field name order between param and arg. + break; + // TODO: Handle more cases. default: break; } + + // If we've not yet substituted into the parameter, do so now and try again. + if (needs_substitution) { + param_const_id = SubstConstant(context(), param_const_id, substitutions_); + if (!param_const_id.is_valid() || !param_const_id.is_symbolic()) { + continue; + } + Add(context().constant_values().GetInstId(param_const_id), arg_id, + /*needs_substitution=*/false); + } } return true; diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index 816fab59ed759..2ca131bc33be9 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -1433,15 +1433,14 @@ static auto TryEvalInstInContext(EvalContext& eval_context, // `const (const T)` evaluates to `const T`. Otherwise, `const T` evaluates // to itself. case CARBON_KIND(SemIR::ConstType typed_inst): { - auto inner_id = eval_context.GetConstantValue(typed_inst.inner_id); - if (inner_id.is_constant() && - eval_context.insts() - .Get(eval_context.constant_values().GetInstId(inner_id)) - .Is()) { - return inner_id; + auto phase = Phase::Template; + auto inner_id = + GetConstantValue(eval_context, typed_inst.inner_id, &phase); + if (eval_context.context().types().Is(inner_id)) { + return eval_context.context().types().GetConstantId(inner_id); } - return MakeConstantResult(eval_context.context(), inst, - GetPhase(inner_id)); + typed_inst.inner_id = inner_id; + return MakeConstantResult(eval_context.context(), typed_inst, phase); } // These cases are either not expressions or not constant. diff --git a/toolchain/check/testdata/deduce/array.carbon b/toolchain/check/testdata/deduce/array.carbon new file mode 100644 index 0000000000000..c6f0050635200 --- /dev/null +++ b/toolchain/check/testdata/deduce/array.carbon @@ -0,0 +1,857 @@ +// 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 +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/array.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/array.carbon + +// --- type_only.carbon + +library "[[@TEST_NAME]]"; + +class C {} + +fn F[T:! type](a: [T; 3]) -> T { return a[0]; } + +fn G() -> C { + var a: [C; 3] = ({}, {}, {}); + return F(a); +} + +// --- fail_todo_bound_only.carbon + +library "[[@TEST_NAME]]"; + +class C {} + +// CHECK:STDERR: fail_todo_bound_only.carbon:[[@LINE+4]]:22: error: semantics TODO: `symbolic array bound` +// CHECK:STDERR: fn F[N:! i32](a: [C; N]) -> i32 { return N; } +// CHECK:STDERR: ^ +// CHECK:STDERR: +fn F[N:! i32](a: [C; N]) -> i32 { return N; } + +fn G() -> C { + var a: [C; 3] = ({}, {}, {}); + return F(a); +} + +// --- fail_todo_type_and_bound.carbon + +library "[[@TEST_NAME]]"; + +class C {} + +// CHECK:STDERR: fail_todo_type_and_bound.carbon:[[@LINE+4]]:32: error: semantics TODO: `symbolic array bound` +// CHECK:STDERR: fn F[T:! type, N:! i32](a: [T; N]) -> T; +// CHECK:STDERR: ^ +// CHECK:STDERR: +fn F[T:! type, N:! i32](a: [T; N]) -> T; + +fn G() -> C { + var a: [C; 3] = ({}, {}, {}); + return F(a); +} + +// --- fail_bound_mismatch.carbon + +library "[[@TEST_NAME]]"; + +class C {} + +fn F[T:! type](a: [T; 2]) -> T { return a[0]; } + +fn G() -> C { + // TODO: We succeed at deducing T here but fail to convert. Is this the right behavior? + var a: [C; 3] = ({}, {}, {}); + // CHECK:STDERR: fail_bound_mismatch.carbon:[[@LINE+10]]:10: error: cannot implicitly convert from `[C; 3]` to `[C; 2]` + // CHECK:STDERR: return F(a); + // CHECK:STDERR: ^~ + // CHECK:STDERR: fail_bound_mismatch.carbon:[[@LINE+7]]:10: note: type `[C; 3]` does not implement interface `ImplicitAs` + // CHECK:STDERR: return F(a); + // CHECK:STDERR: ^~ + // CHECK:STDERR: fail_bound_mismatch.carbon:[[@LINE-11]]:1: note: initializing parameter 1 of function declared here + // CHECK:STDERR: fn F[T:! type](a: [T; 2]) -> T { return a[0]; } + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + return F(a); +} + +// --- fail_type_mismatch.carbon + +library "[[@TEST_NAME]]"; + +class C {} +class D {} + +// CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE+3]]:22: error: semantics TODO: `symbolic array bound` +// CHECK:STDERR: fn F[N:! i32](a: [C; N]) -> i32 { return N; } +// CHECK:STDERR: ^ +fn F[N:! i32](a: [C; N]) -> i32 { return N; } + +fn G() -> C { + var a: [D; 3] = ({}, {}, {}); + return F(a); +} + + +// CHECK:STDOUT: --- type_only.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %.3: i32 = int_literal 3 [template] +// CHECK:STDOUT: %.4: type = array_type %.3, %T [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.5: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.6: type = ptr_type %.4 [symbolic] +// CHECK:STDOUT: %.7: i32 = int_literal 0 [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %.1 [template] +// CHECK:STDOUT: %.9: type = array_type %.3, %C [template] +// CHECK:STDOUT: %.10: type = ptr_type %.9 [template] +// CHECK:STDOUT: %.11: type = tuple_type (%.1, %.1, %.1) [template] +// CHECK:STDOUT: %struct: %C = struct_value () [template] +// CHECK:STDOUT: %.12: i32 = int_literal 1 [template] +// CHECK:STDOUT: %.13: i32 = int_literal 2 [template] +// CHECK:STDOUT: %array: %.9 = tuple_value (%struct, %struct, %struct) [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: %a.patt: @F.%.1 (%.4) = binding_pattern a +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc6: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc6_20: type = name_ref T, %T.loc6 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc6_23: i32 = int_literal 3 [template = constants.%.3] +// CHECK:STDOUT: %.loc6_24: type = array_type %.loc6_23, %T [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: %a.param: @F.%.1 (%.4) = param a, runtime_param0 +// CHECK:STDOUT: %a: @F.%.1 (%.4) = bind_name a, %a.param +// CHECK:STDOUT: %T.ref.loc6_30: type = name_ref T, %T.loc6 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %return: ref @F.%T.1 (%T) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] {} { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return: ref %C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%T.loc6: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.1: type = array_type constants.%.3, @F.%T.1 (%T) [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.loc6: type](%a: @F.%.1 (%.4)) -> @F.%T.1 (%T) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: @F.%.1 (%.4) = name_ref a, %a +// CHECK:STDOUT: %.loc6_43: i32 = int_literal 0 [template = constants.%.7] +// CHECK:STDOUT: %.loc6_44.1: ref @F.%.1 (%.4) = value_as_ref %a.ref +// CHECK:STDOUT: %.loc6_44.2: ref @F.%T.1 (%T) = array_index %.loc6_44.1, %.loc6_43 +// CHECK:STDOUT: %.loc6_44.3: @F.%T.1 (%T) = bind_value %.loc6_44.2 +// CHECK:STDOUT: return %.loc6_44.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G() -> %return: %C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %C.ref.loc9: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc9_14: i32 = int_literal 3 [template = constants.%.3] +// CHECK:STDOUT: %.loc9_15: type = array_type %.loc9_14, %C [template = constants.%.9] +// CHECK:STDOUT: %a.var: ref %.9 = var a +// CHECK:STDOUT: %a: ref %.9 = bind_name a, %a.var +// CHECK:STDOUT: %.loc9_21.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc9_25.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc9_29.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc9_30.1: %.11 = tuple_literal (%.loc9_21.1, %.loc9_25.1, %.loc9_29.1) +// CHECK:STDOUT: %.loc9_30.2: i32 = int_literal 0 [template = constants.%.7] +// CHECK:STDOUT: %.loc9_30.3: ref %C = array_index %a.var, %.loc9_30.2 +// CHECK:STDOUT: %.loc9_21.2: init %C = class_init (), %.loc9_30.3 [template = constants.%struct] +// CHECK:STDOUT: %.loc9_30.4: init %C = converted %.loc9_21.1, %.loc9_21.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc9_30.5: i32 = int_literal 1 [template = constants.%.12] +// CHECK:STDOUT: %.loc9_30.6: ref %C = array_index %a.var, %.loc9_30.5 +// CHECK:STDOUT: %.loc9_25.2: init %C = class_init (), %.loc9_30.6 [template = constants.%struct] +// CHECK:STDOUT: %.loc9_30.7: init %C = converted %.loc9_25.1, %.loc9_25.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc9_30.8: i32 = int_literal 2 [template = constants.%.13] +// CHECK:STDOUT: %.loc9_30.9: ref %C = array_index %a.var, %.loc9_30.8 +// CHECK:STDOUT: %.loc9_29.2: init %C = class_init (), %.loc9_30.9 [template = constants.%struct] +// CHECK:STDOUT: %.loc9_30.10: init %C = converted %.loc9_29.1, %.loc9_29.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc9_30.11: init %.9 = array_init (%.loc9_30.4, %.loc9_30.7, %.loc9_30.10) to %a.var [template = constants.%array] +// CHECK:STDOUT: %.loc9_31: init %.9 = converted %.loc9_30.1, %.loc9_30.11 [template = constants.%array] +// CHECK:STDOUT: assign %a.var, %.loc9_31 +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %a.ref: ref %.9 = name_ref a, %a +// CHECK:STDOUT: %.loc8: ref %C = splice_block %return {} +// CHECK:STDOUT: %.loc10: %.9 = bind_value %a.ref +// CHECK:STDOUT: %F.call: init %C = call %F.ref(%.loc10) to %.loc8 +// CHECK:STDOUT: return %F.call to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %.1 => constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%C) { +// CHECK:STDOUT: %T.1 => constants.%C +// CHECK:STDOUT: %.1 => constants.%.9 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_bound_only.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %N: i32 = bind_symbolic_name N, 0 [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type %.1 [template] +// CHECK:STDOUT: %.5: i32 = int_literal 3 [template] +// CHECK:STDOUT: %.6: type = array_type %.5, %C [template] +// CHECK:STDOUT: %.7: type = ptr_type %.6 [template] +// CHECK:STDOUT: %.8: type = tuple_type (%.1, %.1, %.1) [template] +// CHECK:STDOUT: %.9: i32 = int_literal 0 [template] +// CHECK:STDOUT: %struct: %C = struct_value () [template] +// CHECK:STDOUT: %.10: i32 = int_literal 1 [template] +// CHECK:STDOUT: %.11: i32 = int_literal 2 [template] +// CHECK:STDOUT: %array: %.6 = tuple_value (%struct, %struct, %struct) [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/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %N.patt: i32 = symbolic_binding_pattern N, 0 +// CHECK:STDOUT: %a.patt: = binding_pattern a +// CHECK:STDOUT: } { +// CHECK:STDOUT: %int.make_type_32.loc10_10: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc10_10.1: type = value_of_initializer %int.make_type_32.loc10_10 [template = i32] +// CHECK:STDOUT: %.loc10_10.2: type = converted %int.make_type_32.loc10_10, %.loc10_10.1 [template = i32] +// CHECK:STDOUT: %N.param: i32 = param N, runtime_param +// CHECK:STDOUT: %N.loc10: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %N.ref.loc10_22: i32 = name_ref N, %N.loc10 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %.loc10_23: type = array_type %N.ref.loc10_22, %C [template = ] +// CHECK:STDOUT: %a.param: = param a, runtime_param0 +// CHECK:STDOUT: %a: = bind_name a, %a.param +// CHECK:STDOUT: %int.make_type_32.loc10_29: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc10_29.1: type = value_of_initializer %int.make_type_32.loc10_29 [template = i32] +// CHECK:STDOUT: %.loc10_29.2: type = converted %int.make_type_32.loc10_29, %.loc10_29.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] {} { +// CHECK:STDOUT: %C.ref.loc12: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return: ref %C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%N.loc10: i32) { +// CHECK:STDOUT: %N.1: i32 = bind_symbolic_name N, 0 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%N.loc10: i32](%a: ) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %N.ref.loc10_42: i32 = name_ref N, %N.loc10 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: return %N.ref.loc10_42 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G() -> %return: %C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc13_14: i32 = int_literal 3 [template = constants.%.5] +// CHECK:STDOUT: %.loc13_15: type = array_type %.loc13_14, %C [template = constants.%.6] +// CHECK:STDOUT: %a.var: ref %.6 = var a +// CHECK:STDOUT: %a: ref %.6 = bind_name a, %a.var +// CHECK:STDOUT: %.loc13_21.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc13_25.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc13_29.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc13_30.1: %.8 = tuple_literal (%.loc13_21.1, %.loc13_25.1, %.loc13_29.1) +// CHECK:STDOUT: %.loc13_30.2: i32 = int_literal 0 [template = constants.%.9] +// CHECK:STDOUT: %.loc13_30.3: ref %C = array_index %a.var, %.loc13_30.2 +// CHECK:STDOUT: %.loc13_21.2: init %C = class_init (), %.loc13_30.3 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.4: init %C = converted %.loc13_21.1, %.loc13_21.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.5: i32 = int_literal 1 [template = constants.%.10] +// CHECK:STDOUT: %.loc13_30.6: ref %C = array_index %a.var, %.loc13_30.5 +// CHECK:STDOUT: %.loc13_25.2: init %C = class_init (), %.loc13_30.6 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.7: init %C = converted %.loc13_25.1, %.loc13_25.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.8: i32 = int_literal 2 [template = constants.%.11] +// CHECK:STDOUT: %.loc13_30.9: ref %C = array_index %a.var, %.loc13_30.8 +// CHECK:STDOUT: %.loc13_29.2: init %C = class_init (), %.loc13_30.9 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.10: init %C = converted %.loc13_29.1, %.loc13_29.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.11: init %.6 = array_init (%.loc13_30.4, %.loc13_30.7, %.loc13_30.10) to %a.var [template = constants.%array] +// CHECK:STDOUT: %.loc13_31: init %.6 = converted %.loc13_30.1, %.loc13_30.11 [template = constants.%array] +// CHECK:STDOUT: assign %a.var, %.loc13_31 +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %a.ref: ref %.6 = name_ref a, %a +// CHECK:STDOUT: return to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%N) { +// CHECK:STDOUT: %N.1 => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_type_and_bound.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %N: i32 = bind_symbolic_name N, 1 [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type %.1 [template] +// CHECK:STDOUT: %.5: i32 = int_literal 3 [template] +// CHECK:STDOUT: %.6: type = array_type %.5, %C [template] +// CHECK:STDOUT: %.7: type = ptr_type %.6 [template] +// CHECK:STDOUT: %.8: type = tuple_type (%.1, %.1, %.1) [template] +// CHECK:STDOUT: %.9: i32 = int_literal 0 [template] +// CHECK:STDOUT: %struct: %C = struct_value () [template] +// CHECK:STDOUT: %.10: i32 = int_literal 1 [template] +// CHECK:STDOUT: %.11: i32 = int_literal 2 [template] +// CHECK:STDOUT: %array: %.6 = tuple_value (%struct, %struct, %struct) [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/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: %N.patt: i32 = symbolic_binding_pattern N, 1 +// CHECK:STDOUT: %a.patt: = binding_pattern a +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc10: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc10_20.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc10_20.2: type = converted %int.make_type_32, %.loc10_20.1 [template = i32] +// CHECK:STDOUT: %N.param: i32 = param N, runtime_param +// CHECK:STDOUT: %N.loc10: i32 = bind_symbolic_name N, 1, %N.param [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %T.ref.loc10_29: type = name_ref T, %T.loc10 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %N.ref: i32 = name_ref N, %N.loc10 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %.loc10_33: type = array_type %N.ref, %T [template = ] +// CHECK:STDOUT: %a.param: = param a, runtime_param0 +// CHECK:STDOUT: %a: = bind_name a, %a.param +// CHECK:STDOUT: %T.ref.loc10_39: type = name_ref T, %T.loc10 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %return: ref @F.%T.1 (%T) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] {} { +// CHECK:STDOUT: %C.ref.loc12: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return: ref %C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%T.loc10: type, %N.loc10: i32) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %N.1: i32 = bind_symbolic_name N, 1 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.loc10: type, %N.loc10: i32](%a: ) -> @F.%T.1 (%T); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G() -> %return: %C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc13_14: i32 = int_literal 3 [template = constants.%.5] +// CHECK:STDOUT: %.loc13_15: type = array_type %.loc13_14, %C [template = constants.%.6] +// CHECK:STDOUT: %a.var: ref %.6 = var a +// CHECK:STDOUT: %a: ref %.6 = bind_name a, %a.var +// CHECK:STDOUT: %.loc13_21.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc13_25.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc13_29.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc13_30.1: %.8 = tuple_literal (%.loc13_21.1, %.loc13_25.1, %.loc13_29.1) +// CHECK:STDOUT: %.loc13_30.2: i32 = int_literal 0 [template = constants.%.9] +// CHECK:STDOUT: %.loc13_30.3: ref %C = array_index %a.var, %.loc13_30.2 +// CHECK:STDOUT: %.loc13_21.2: init %C = class_init (), %.loc13_30.3 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.4: init %C = converted %.loc13_21.1, %.loc13_21.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.5: i32 = int_literal 1 [template = constants.%.10] +// CHECK:STDOUT: %.loc13_30.6: ref %C = array_index %a.var, %.loc13_30.5 +// CHECK:STDOUT: %.loc13_25.2: init %C = class_init (), %.loc13_30.6 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.7: init %C = converted %.loc13_25.1, %.loc13_25.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.8: i32 = int_literal 2 [template = constants.%.11] +// CHECK:STDOUT: %.loc13_30.9: ref %C = array_index %a.var, %.loc13_30.8 +// CHECK:STDOUT: %.loc13_29.2: init %C = class_init (), %.loc13_30.9 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.10: init %C = converted %.loc13_29.1, %.loc13_29.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.11: init %.6 = array_init (%.loc13_30.4, %.loc13_30.7, %.loc13_30.10) to %a.var [template = constants.%array] +// CHECK:STDOUT: %.loc13_31: init %.6 = converted %.loc13_30.1, %.loc13_30.11 [template = constants.%array] +// CHECK:STDOUT: assign %a.var, %.loc13_31 +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %a.ref: ref %.6 = name_ref a, %a +// CHECK:STDOUT: return to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%T, constants.%N) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %N.1 => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_bound_mismatch.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %.3: i32 = int_literal 2 [template] +// CHECK:STDOUT: %.4: type = array_type %.3, %T [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.5: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.6: type = ptr_type %.4 [symbolic] +// CHECK:STDOUT: %.7: i32 = int_literal 0 [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %.1 [template] +// CHECK:STDOUT: %.9: i32 = int_literal 3 [template] +// CHECK:STDOUT: %.10: type = array_type %.9, %C [template] +// CHECK:STDOUT: %.11: type = ptr_type %.10 [template] +// CHECK:STDOUT: %.12: type = tuple_type (%.1, %.1, %.1) [template] +// CHECK:STDOUT: %struct: %C = struct_value () [template] +// CHECK:STDOUT: %.13: i32 = int_literal 1 [template] +// CHECK:STDOUT: %array: %.10 = tuple_value (%struct, %struct, %struct) [template] +// CHECK:STDOUT: %.14: type = array_type %.3, %C [template] +// CHECK:STDOUT: %.15: type = ptr_type %.14 [template] +// CHECK:STDOUT: %ImplicitAs.type.1: type = generic_interface_type @ImplicitAs [template] +// CHECK:STDOUT: %ImplicitAs: %ImplicitAs.type.1 = struct_value () [template] +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic] +// CHECK:STDOUT: %ImplicitAs.type.2: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic] +// CHECK:STDOUT: %Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2) = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %Self.2: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %Convert.type.1: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic] +// CHECK:STDOUT: %Convert.1: %Convert.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.16: type = assoc_entity_type %ImplicitAs.type.2, %Convert.type.1 [symbolic] +// CHECK:STDOUT: %.17: %.16 = assoc_entity element0, imports.%import_ref.5 [symbolic] +// CHECK:STDOUT: %ImplicitAs.type.3: type = interface_type @ImplicitAs, @ImplicitAs(%.14) [template] +// CHECK:STDOUT: %Convert.type.2: type = fn_type @Convert, @ImplicitAs(%.14) [template] +// CHECK:STDOUT: %Convert.2: %Convert.type.2 = struct_value () [template] +// CHECK:STDOUT: %.18: type = assoc_entity_type %ImplicitAs.type.3, %Convert.type.2 [template] +// CHECK:STDOUT: %.19: %.18 = assoc_entity element0, imports.%import_ref.5 [template] +// CHECK:STDOUT: %.20: %.16 = assoc_entity element0, imports.%import_ref.6 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .ImplicitAs = %import_ref.1 +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: %ImplicitAs.type.1 = import_ref Core//prelude/operators/as, inst+40, loaded [template = constants.%ImplicitAs] +// CHECK:STDOUT: %import_ref.2 = import_ref Core//prelude/operators/as, inst+45, unloaded +// CHECK:STDOUT: %import_ref.3: @ImplicitAs.%.1 (%.16) = import_ref Core//prelude/operators/as, inst+63, loaded [symbolic = @ImplicitAs.%.2 (constants.%.20)] +// CHECK:STDOUT: %import_ref.4 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: %a.patt: @F.%.1 (%.4) = binding_pattern a +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc6: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc6_20: type = name_ref T, %T.loc6 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc6_23: i32 = int_literal 2 [template = constants.%.3] +// CHECK:STDOUT: %.loc6_24: type = array_type %.loc6_23, %T [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: %a.param: @F.%.1 (%.4) = param a, runtime_param0 +// CHECK:STDOUT: %a: @F.%.1 (%.4) = bind_name a, %a.param +// CHECK:STDOUT: %T.ref.loc6_30: type = name_ref T, %T.loc6 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %return: ref @F.%T.1 (%T) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] {} { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return: ref %C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @ImplicitAs(constants.%Dest: type) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)] +// CHECK:STDOUT: %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %Convert.type: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic = %Convert.type (constants.%Convert.type.1)] +// CHECK:STDOUT: %Convert: @ImplicitAs.%Convert.type (%Convert.type.1) = struct_value () [symbolic = %Convert (constants.%Convert.1)] +// CHECK:STDOUT: %.1: type = assoc_entity_type @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2), @ImplicitAs.%Convert.type (%Convert.type.1) [symbolic = %.1 (constants.%.16)] +// CHECK:STDOUT: %.2: @ImplicitAs.%.1 (%.16) = assoc_entity element0, imports.%import_ref.5 [symbolic = %.2 (constants.%.17)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.2 +// CHECK:STDOUT: .Convert = imports.%import_ref.3 +// CHECK:STDOUT: witness = (imports.%import_ref.4) +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%T.loc6: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.1: type = array_type constants.%.3, @F.%T.1 (%T) [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.loc6: type](%a: @F.%.1 (%.4)) -> @F.%T.1 (%T) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: @F.%.1 (%.4) = name_ref a, %a +// CHECK:STDOUT: %.loc6_43: i32 = int_literal 0 [template = constants.%.7] +// CHECK:STDOUT: %.loc6_44.1: ref @F.%.1 (%.4) = value_as_ref %a.ref +// CHECK:STDOUT: %.loc6_44.2: ref @F.%T.1 (%T) = array_index %.loc6_44.1, %.loc6_43 +// CHECK:STDOUT: %.loc6_44.3: @F.%T.1 (%T) = bind_value %.loc6_44.2 +// CHECK:STDOUT: return %.loc6_44.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G() -> %return: %C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %C.ref.loc10: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc10_14: i32 = int_literal 3 [template = constants.%.9] +// CHECK:STDOUT: %.loc10_15: type = array_type %.loc10_14, %C [template = constants.%.10] +// CHECK:STDOUT: %a.var: ref %.10 = var a +// CHECK:STDOUT: %a: ref %.10 = bind_name a, %a.var +// CHECK:STDOUT: %.loc10_21.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc10_25.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc10_29.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc10_30.1: %.12 = tuple_literal (%.loc10_21.1, %.loc10_25.1, %.loc10_29.1) +// CHECK:STDOUT: %.loc10_30.2: i32 = int_literal 0 [template = constants.%.7] +// CHECK:STDOUT: %.loc10_30.3: ref %C = array_index %a.var, %.loc10_30.2 +// CHECK:STDOUT: %.loc10_21.2: init %C = class_init (), %.loc10_30.3 [template = constants.%struct] +// CHECK:STDOUT: %.loc10_30.4: init %C = converted %.loc10_21.1, %.loc10_21.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc10_30.5: i32 = int_literal 1 [template = constants.%.13] +// CHECK:STDOUT: %.loc10_30.6: ref %C = array_index %a.var, %.loc10_30.5 +// CHECK:STDOUT: %.loc10_25.2: init %C = class_init (), %.loc10_30.6 [template = constants.%struct] +// CHECK:STDOUT: %.loc10_30.7: init %C = converted %.loc10_25.1, %.loc10_25.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc10_30.8: i32 = int_literal 2 [template = constants.%.3] +// CHECK:STDOUT: %.loc10_30.9: ref %C = array_index %a.var, %.loc10_30.8 +// CHECK:STDOUT: %.loc10_29.2: init %C = class_init (), %.loc10_30.9 [template = constants.%struct] +// CHECK:STDOUT: %.loc10_30.10: init %C = converted %.loc10_29.1, %.loc10_29.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc10_30.11: init %.10 = array_init (%.loc10_30.4, %.loc10_30.7, %.loc10_30.10) to %a.var [template = constants.%array] +// CHECK:STDOUT: %.loc10_31: init %.10 = converted %.loc10_30.1, %.loc10_30.11 [template = constants.%array] +// CHECK:STDOUT: assign %a.var, %.loc10_31 +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %a.ref: ref %.10 = name_ref a, %a +// CHECK:STDOUT: %.loc21_11.1: ref %C = temporary_storage +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(constants.%.14) [template = constants.%ImplicitAs.type.3] +// CHECK:STDOUT: %.loc21_11.2: %.18 = specific_constant imports.%import_ref.3, @ImplicitAs(constants.%.14) [template = constants.%.19] +// CHECK:STDOUT: %Convert.ref: %.18 = name_ref Convert, %.loc21_11.2 [template = constants.%.19] +// CHECK:STDOUT: %.loc21_11.3: %.14 = converted %a.ref, [template = ] +// CHECK:STDOUT: %F.call: init %C = call %F.ref() [template = ] +// CHECK:STDOUT: return %F.call to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Convert(constants.%Dest: type, constants.%Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2)) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)] +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)] +// CHECK:STDOUT: %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: @Convert.%Self (%Self.2)]() -> @Convert.%Dest (%Dest); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %.1 => constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%C) { +// CHECK:STDOUT: %T.1 => constants.%C +// CHECK:STDOUT: %.1 => constants.%.14 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(constants.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(@ImplicitAs.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(@Convert.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Convert(constants.%Dest, constants.%Self.1) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.2 +// CHECK:STDOUT: %Self => constants.%Self.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(constants.%.14) { +// CHECK:STDOUT: %Dest => constants.%.14 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.3 +// CHECK:STDOUT: %Self => constants.%Self.2 +// CHECK:STDOUT: %Convert.type => constants.%Convert.type.2 +// CHECK:STDOUT: %Convert => constants.%Convert.2 +// CHECK:STDOUT: %.1 => constants.%.18 +// CHECK:STDOUT: %.2 => constants.%.19 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_type_mismatch.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %D: type = class_type @D [template] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %N: i32 = bind_symbolic_name N, 0 [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type %.1 [template] +// CHECK:STDOUT: %.5: i32 = int_literal 3 [template] +// CHECK:STDOUT: %.6: type = array_type %.5, %D [template] +// CHECK:STDOUT: %.7: type = ptr_type %.6 [template] +// CHECK:STDOUT: %.8: type = tuple_type (%.1, %.1, %.1) [template] +// CHECK:STDOUT: %.9: i32 = int_literal 0 [template] +// CHECK:STDOUT: %struct: %D = struct_value () [template] +// CHECK:STDOUT: %.10: i32 = int_literal 1 [template] +// CHECK:STDOUT: %.11: i32 = int_literal 2 [template] +// CHECK:STDOUT: %array: %.6 = tuple_value (%struct, %struct, %struct) [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/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %D.decl: type = class_decl @D [template = constants.%D] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %N.patt: i32 = symbolic_binding_pattern N, 0 +// CHECK:STDOUT: %a.patt: = binding_pattern a +// CHECK:STDOUT: } { +// CHECK:STDOUT: %int.make_type_32.loc10_10: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc10_10.1: type = value_of_initializer %int.make_type_32.loc10_10 [template = i32] +// CHECK:STDOUT: %.loc10_10.2: type = converted %int.make_type_32.loc10_10, %.loc10_10.1 [template = i32] +// CHECK:STDOUT: %N.param: i32 = param N, runtime_param +// CHECK:STDOUT: %N.loc10: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %N.ref.loc10_22: i32 = name_ref N, %N.loc10 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %.loc10_23: type = array_type %N.ref.loc10_22, %C [template = ] +// CHECK:STDOUT: %a.param: = param a, runtime_param0 +// CHECK:STDOUT: %a: = bind_name a, %a.param +// CHECK:STDOUT: %int.make_type_32.loc10_29: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc10_29.1: type = value_of_initializer %int.make_type_32.loc10_29 [template = i32] +// CHECK:STDOUT: %.loc10_29.2: type = converted %int.make_type_32.loc10_29, %.loc10_29.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] {} { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return: ref %C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @D { +// CHECK:STDOUT: %.loc5: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%D +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%N.loc10: i32) { +// CHECK:STDOUT: %N.1: i32 = bind_symbolic_name N, 0 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%N.loc10: i32](%a: ) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %N.ref.loc10_42: i32 = name_ref N, %N.loc10 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: return %N.ref.loc10_42 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G() -> %return: %C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %D.ref: type = name_ref D, file.%D.decl [template = constants.%D] +// CHECK:STDOUT: %.loc13_14: i32 = int_literal 3 [template = constants.%.5] +// CHECK:STDOUT: %.loc13_15: type = array_type %.loc13_14, %D [template = constants.%.6] +// CHECK:STDOUT: %a.var: ref %.6 = var a +// CHECK:STDOUT: %a: ref %.6 = bind_name a, %a.var +// CHECK:STDOUT: %.loc13_21.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc13_25.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc13_29.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc13_30.1: %.8 = tuple_literal (%.loc13_21.1, %.loc13_25.1, %.loc13_29.1) +// CHECK:STDOUT: %.loc13_30.2: i32 = int_literal 0 [template = constants.%.9] +// CHECK:STDOUT: %.loc13_30.3: ref %D = array_index %a.var, %.loc13_30.2 +// CHECK:STDOUT: %.loc13_21.2: init %D = class_init (), %.loc13_30.3 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.4: init %D = converted %.loc13_21.1, %.loc13_21.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.5: i32 = int_literal 1 [template = constants.%.10] +// CHECK:STDOUT: %.loc13_30.6: ref %D = array_index %a.var, %.loc13_30.5 +// CHECK:STDOUT: %.loc13_25.2: init %D = class_init (), %.loc13_30.6 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.7: init %D = converted %.loc13_25.1, %.loc13_25.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.8: i32 = int_literal 2 [template = constants.%.11] +// CHECK:STDOUT: %.loc13_30.9: ref %D = array_index %a.var, %.loc13_30.8 +// CHECK:STDOUT: %.loc13_29.2: init %D = class_init (), %.loc13_30.9 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.10: init %D = converted %.loc13_29.1, %.loc13_29.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc13_30.11: init %.6 = array_init (%.loc13_30.4, %.loc13_30.7, %.loc13_30.10) to %a.var [template = constants.%array] +// CHECK:STDOUT: %.loc13_31: init %.6 = converted %.loc13_30.1, %.loc13_30.11 [template = constants.%array] +// CHECK:STDOUT: assign %a.var, %.loc13_31 +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %a.ref: ref %.6 = name_ref a, %a +// CHECK:STDOUT: return to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%N) { +// CHECK:STDOUT: %N.1 => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/deduce/generic_type.carbon b/toolchain/check/testdata/deduce/generic_type.carbon new file mode 100644 index 0000000000000..a225e97e09d2b --- /dev/null +++ b/toolchain/check/testdata/deduce/generic_type.carbon @@ -0,0 +1,725 @@ +// 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 +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/generic_type.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/generic_type.carbon + +// --- class.carbon + +library "[[@TEST_NAME]]"; + +class C(T:! type) {} +class D {} + +fn F[T:! type](p: C(T)) -> T; + +fn G(p: C(D)) -> D { + return F(p); +} + +// --- interface.carbon + +library "[[@TEST_NAME]]"; + +class I(T:! type) {} +class C {} + +fn F[T:! type](p: I(T)) -> C; + +fn G(p: I(C)) -> C { + return F(p); +} + +// --- nested.carbon + +library "[[@TEST_NAME]]"; + +class Outer(T:! type) { + class Inner(U:! type) {} +} + +class C {} +class D {} + +// C++ doesn't permit deducing `T` here because `Outer` might be specialized. +// But that's not possible in Carbon, so we can deduce `T`. +fn F[T:! type, U:! type](p: Outer(T).Inner(U)) -> (T, U); + +fn G(p: Outer(C).Inner(D)) -> (C, D) { + return F(p); +} + +// --- nontype.carbon + +library "[[@TEST_NAME]]"; + +class WithNontype(N:! i32) {} + +fn F[N:! i32](x: WithNontype(N)) -> i32 { return N; } + +fn G() -> i32 { + return F({} as WithNontype(0)); +} + +// CHECK:STDOUT: --- class.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %C.type: type = generic_class_type @C [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %C.1: %C.type = struct_value () [template] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%T) [symbolic] +// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %.3: = complete_type_witness %.2 [template] +// CHECK:STDOUT: %D: type = class_type @D [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%D) [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type %.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %C.decl: %C.type = class_decl @C [template = constants.%C.1] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc4: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %D.decl: type = class_decl @D [template = constants.%D] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: %p.patt: @F.%C.1 (%C.2) = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc7: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %C.ref: %C.type = name_ref C, file.%C.decl [template = constants.%C.1] +// CHECK:STDOUT: %T.ref.loc7_21: type = name_ref T, %T.loc7 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %C.loc7: type = class_type @C, @C(constants.%T) [symbolic = %C.1 (constants.%C.2)] +// CHECK:STDOUT: %p.param: @F.%C.1 (%C.2) = param p, runtime_param0 +// CHECK:STDOUT: %p: @F.%C.1 (%C.2) = bind_name p, %p.param +// CHECK:STDOUT: %T.ref.loc7_28: type = name_ref T, %T.loc7 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %return: ref @F.%T.1 (%T) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %p.patt: %C.3 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %C.ref: %C.type = name_ref C, file.%C.decl [template = constants.%C.1] +// CHECK:STDOUT: %D.ref.loc9_11: type = name_ref D, file.%D.decl [template = constants.%D] +// CHECK:STDOUT: %C: type = class_type @C, @C(constants.%D) [template = constants.%C.3] +// CHECK:STDOUT: %p.param: %C.3 = param p, runtime_param0 +// CHECK:STDOUT: %p: %C.3 = bind_name p, %p.param +// CHECK:STDOUT: %D.ref.loc9_18: type = name_ref D, file.%D.decl [template = constants.%D] +// CHECK:STDOUT: %return: ref %D = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @C(%T.loc4: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.2 [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @D { +// CHECK:STDOUT: %.loc5: = complete_type_witness %.2 [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%D +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%T.loc7: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %C.1: type = class_type @C, @C(%T.1) [symbolic = %C.1 (constants.%C.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.loc7: type](%p: @F.%C.1 (%C.2)) -> @F.%T.1 (%T); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%p: %C.3) -> %return: %D { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %p.ref: %C.3 = name_ref p, %p +// CHECK:STDOUT: %.loc9: ref %D = splice_block %return {} +// CHECK:STDOUT: %F.call: init %D = call %F.ref(%p.ref) to %.loc9 +// CHECK:STDOUT: return %F.call to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(@F.%T.1) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %C.1 => constants.%C.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%D) { +// CHECK:STDOUT: %T.1 => constants.%D +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%D) { +// CHECK:STDOUT: %T.1 => constants.%D +// CHECK:STDOUT: %C.1 => constants.%C.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- interface.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %I.type: type = generic_class_type @I [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %I.1: %I.type = struct_value () [template] +// CHECK:STDOUT: %I.2: type = class_type @I, @I(%T) [symbolic] +// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %.3: = complete_type_witness %.2 [template] +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %I.3: type = class_type @I, @I(%C) [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type %.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %I.decl: %I.type = class_decl @I [template = constants.%I.1] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc4: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: %p.patt: @F.%I.1 (%I.2) = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc7: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %I.ref: %I.type = name_ref I, file.%I.decl [template = constants.%I.1] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc7 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %I.loc7: type = class_type @I, @I(constants.%T) [symbolic = %I.1 (constants.%I.2)] +// CHECK:STDOUT: %p.param: @F.%I.1 (%I.2) = param p, runtime_param0 +// CHECK:STDOUT: %p: @F.%I.1 (%I.2) = bind_name p, %p.param +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return: ref %C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %p.patt: %I.3 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %I.ref: %I.type = name_ref I, file.%I.decl [template = constants.%I.1] +// CHECK:STDOUT: %C.ref.loc9_11: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %I: type = class_type @I, @I(constants.%C) [template = constants.%I.3] +// CHECK:STDOUT: %p.param: %I.3 = param p, runtime_param0 +// CHECK:STDOUT: %p: %I.3 = bind_name p, %p.param +// CHECK:STDOUT: %C.ref.loc9_18: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return: ref %C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @I(%T.loc4: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.2 [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%I.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc5: = complete_type_witness %.2 [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%T.loc7: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %I.1: type = class_type @I, @I(%T.1) [symbolic = %I.1 (constants.%I.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.loc7: type](%p: @F.%I.1 (%I.2)) -> %C; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%p: %I.3) -> %return: %C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %p.ref: %I.3 = name_ref p, %p +// CHECK:STDOUT: %.loc9: ref %C = splice_block %return {} +// CHECK:STDOUT: %F.call: init %C = call %F.ref(%p.ref) to %.loc9 +// CHECK:STDOUT: return %F.call to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@F.%T.1) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %I.1 => constants.%I.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%C) { +// CHECK:STDOUT: %T.1 => constants.%C +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%C) { +// CHECK:STDOUT: %T.1 => constants.%C +// CHECK:STDOUT: %I.1 => constants.%I.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- nested.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %Outer.type: type = generic_class_type @Outer [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Outer.1: %Outer.type = struct_value () [template] +// CHECK:STDOUT: %Outer.2: type = class_type @Outer, @Outer(%T) [symbolic] +// CHECK:STDOUT: %U: type = bind_symbolic_name U, 1 [symbolic] +// CHECK:STDOUT: %Inner.type.1: type = generic_class_type @Inner, @Outer(%T) [symbolic] +// CHECK:STDOUT: %Inner.1: %Inner.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %Inner.2: type = class_type @Inner, @Inner(%T, %U) [symbolic] +// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %.3: = complete_type_witness %.2 [template] +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %D: type = class_type @D [template] +// CHECK:STDOUT: %.4: type = ptr_type %.2 [template] +// CHECK:STDOUT: %.5: type = tuple_type (type, type) [template] +// CHECK:STDOUT: %.6: type = tuple_type (%T, %U) [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %Outer.3: type = class_type @Outer, @Outer(%C) [template] +// CHECK:STDOUT: %Inner.type.2: type = generic_class_type @Inner, @Outer(%C) [template] +// CHECK:STDOUT: %Inner.3: %Inner.type.2 = struct_value () [template] +// CHECK:STDOUT: %Inner.4: type = class_type @Inner, @Inner(%C, %D) [template] +// CHECK:STDOUT: %.7: type = tuple_type (%C, %D) [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.8: type = tuple_type (%.4, %.4) [template] +// CHECK:STDOUT: %.9: type = ptr_type %.8 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .Outer = %Outer.decl +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %Outer.decl: %Outer.type = class_decl @Outer [template = constants.%Outer.1] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc4: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %D.decl: type = class_decl @D [template = constants.%D] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: %U.patt: type = symbolic_binding_pattern U, 1 +// CHECK:STDOUT: %p.patt: @F.%Inner.2 (%Inner.2) = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc13: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %U.param: type = param U, runtime_param +// CHECK:STDOUT: %U.loc13: type = bind_symbolic_name U, 1, %U.param [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: %Outer.ref: %Outer.type = name_ref Outer, file.%Outer.decl [template = constants.%Outer.1] +// CHECK:STDOUT: %T.ref.loc13_35: type = name_ref T, %T.loc13 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %Outer.loc13: type = class_type @Outer, @Outer(constants.%T) [symbolic = %Outer.1 (constants.%Outer.2)] +// CHECK:STDOUT: %.loc13_37: @F.%Inner.type (%Inner.type.1) = specific_constant @Outer.%Inner.decl, @Outer(constants.%T) [symbolic = %Inner.1 (constants.%Inner.1)] +// CHECK:STDOUT: %Inner.ref: @F.%Inner.type (%Inner.type.1) = name_ref Inner, %.loc13_37 [symbolic = %Inner.1 (constants.%Inner.1)] +// CHECK:STDOUT: %U.ref.loc13_44: type = name_ref U, %U.loc13 [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: %Inner.loc13: type = class_type @Inner, @Inner(constants.%T, constants.%U) [symbolic = %Inner.2 (constants.%Inner.2)] +// CHECK:STDOUT: %p.param: @F.%Inner.2 (%Inner.2) = param p, runtime_param0 +// CHECK:STDOUT: %p: @F.%Inner.2 (%Inner.2) = bind_name p, %p.param +// CHECK:STDOUT: %T.ref.loc13_52: type = name_ref T, %T.loc13 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %U.ref.loc13_55: type = name_ref U, %U.loc13 [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: %.loc13_56.1: %.5 = tuple_literal (%T.ref.loc13_52, %U.ref.loc13_55) +// CHECK:STDOUT: %.loc13_56.2: type = converted %.loc13_56.1, constants.%.6 [symbolic = %.1 (constants.%.6)] +// CHECK:STDOUT: %return: ref @F.%.1 (%.6) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %p.patt: %Inner.4 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %Outer.ref: %Outer.type = name_ref Outer, file.%Outer.decl [template = constants.%Outer.1] +// CHECK:STDOUT: %C.ref.loc15_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %Outer: type = class_type @Outer, @Outer(constants.%C) [template = constants.%Outer.3] +// CHECK:STDOUT: %.loc15_17: %Inner.type.2 = specific_constant @Outer.%Inner.decl, @Outer(constants.%C) [template = constants.%Inner.3] +// CHECK:STDOUT: %Inner.ref: %Inner.type.2 = name_ref Inner, %.loc15_17 [template = constants.%Inner.3] +// CHECK:STDOUT: %D.ref.loc15_24: type = name_ref D, file.%D.decl [template = constants.%D] +// CHECK:STDOUT: %Inner: type = class_type @Inner, @Inner(constants.%C, constants.%D) [template = constants.%Inner.4] +// CHECK:STDOUT: %p.param: %Inner.4 = param p, runtime_param0 +// CHECK:STDOUT: %p: %Inner.4 = bind_name p, %p.param +// CHECK:STDOUT: %C.ref.loc15_32: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %D.ref.loc15_35: type = name_ref D, file.%D.decl [template = constants.%D] +// CHECK:STDOUT: %.loc15_36.1: %.5 = tuple_literal (%C.ref.loc15_32, %D.ref.loc15_35) +// CHECK:STDOUT: %.loc15_36.2: type = converted %.loc15_36.1, constants.%.7 [template = constants.%.7] +// CHECK:STDOUT: %return: ref %.7 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @Outer(%T.loc4: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Inner.type: type = generic_class_type @Inner, @Outer(%T.1) [symbolic = %Inner.type (constants.%Inner.type.1)] +// CHECK:STDOUT: %Inner: @Outer.%Inner.type (%Inner.type.1) = struct_value () [symbolic = %Inner (constants.%Inner.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %Inner.decl: @Outer.%Inner.type (%Inner.type.1) = class_decl @Inner [symbolic = @Outer.%Inner (constants.%Inner.1)] { +// CHECK:STDOUT: %U.patt: type = symbolic_binding_pattern U, 1 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %U.param: type = param U, runtime_param +// CHECK:STDOUT: %U.loc5: type = bind_symbolic_name U, 1, %U.param [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc6: = complete_type_witness %.2 [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Outer.2 +// CHECK:STDOUT: .Inner = %Inner.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @Inner(@Outer.%T.loc4: type, %U.loc5: type) { +// CHECK:STDOUT: %U.1: type = bind_symbolic_name U, 1 [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %.loc5: = complete_type_witness %.2 [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Inner.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc8: = complete_type_witness %.2 [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @D { +// CHECK:STDOUT: %.loc9: = complete_type_witness %.2 [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%D +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%T.loc13: type, %U.loc13: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %U.1: type = bind_symbolic_name U, 1 [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: %Outer.1: type = class_type @Outer, @Outer(%T.1) [symbolic = %Outer.1 (constants.%Outer.2)] +// CHECK:STDOUT: %Inner.type: type = generic_class_type @Inner, @Outer(%T.1) [symbolic = %Inner.type (constants.%Inner.type.1)] +// CHECK:STDOUT: %Inner.1: @F.%Inner.type (%Inner.type.1) = struct_value () [symbolic = %Inner.1 (constants.%Inner.1)] +// CHECK:STDOUT: %Inner.2: type = class_type @Inner, @Inner(%T.1, %U.1) [symbolic = %Inner.2 (constants.%Inner.2)] +// CHECK:STDOUT: %.1: type = tuple_type (@F.%T.1 (%T), @F.%U.1 (%U)) [symbolic = %.1 (constants.%.6)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.loc13: type, %U.loc13: type](%p: @F.%Inner.2 (%Inner.2)) -> @F.%.1 (%.6); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%p: %Inner.4) -> %return: %.7 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %p.ref: %Inner.4 = name_ref p, %p +// CHECK:STDOUT: %.loc15_28: ref %.7 = splice_block %return {} +// CHECK:STDOUT: %F.call: init %.7 = call %F.ref(%p.ref) to %.loc15_28 +// CHECK:STDOUT: return %F.call to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Outer(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Inner.type => constants.%Inner.type.1 +// CHECK:STDOUT: %Inner => constants.%Inner.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Inner(constants.%T, constants.%U) { +// CHECK:STDOUT: %U.1 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Outer(@Outer.%T.1) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Outer(@F.%T.1) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Inner(@F.%T.1, @F.%U.1) { +// CHECK:STDOUT: %U.1 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%T, constants.%U) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %U.1 => constants.%U +// CHECK:STDOUT: %Outer.1 => constants.%Outer.2 +// CHECK:STDOUT: %Inner.type => constants.%Inner.type.1 +// CHECK:STDOUT: %Inner.1 => constants.%Inner.1 +// CHECK:STDOUT: %Inner.2 => constants.%Inner.2 +// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Outer(constants.%C) { +// CHECK:STDOUT: %T.1 => constants.%C +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Inner.type => constants.%Inner.type.2 +// CHECK:STDOUT: %Inner => constants.%Inner.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Inner(constants.%C, constants.%D) { +// CHECK:STDOUT: %U.1 => constants.%D +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%C, constants.%D) { +// CHECK:STDOUT: %T.1 => constants.%C +// CHECK:STDOUT: %U.1 => constants.%D +// CHECK:STDOUT: %Outer.1 => constants.%Outer.3 +// CHECK:STDOUT: %Inner.type => constants.%Inner.type.2 +// CHECK:STDOUT: %Inner.1 => constants.%Inner.3 +// CHECK:STDOUT: %Inner.2 => constants.%Inner.4 +// CHECK:STDOUT: %.1 => constants.%.7 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- nontype.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// 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: %N: i32 = bind_symbolic_name N, 0 [symbolic] +// CHECK:STDOUT: %WithNontype.type: type = generic_class_type @WithNontype [template] +// CHECK:STDOUT: %WithNontype.1: %WithNontype.type = struct_value () [template] +// CHECK:STDOUT: %WithNontype.2: type = class_type @WithNontype, @WithNontype(%N) [symbolic] +// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %.3: = complete_type_witness %.2 [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type %.2 [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.5: i32 = int_literal 0 [template] +// CHECK:STDOUT: %WithNontype.3: type = class_type @WithNontype, @WithNontype(%.5) [template] +// CHECK:STDOUT: %struct: %WithNontype.3 = struct_value () [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/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .WithNontype = %WithNontype.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %WithNontype.decl: %WithNontype.type = class_decl @WithNontype [template = constants.%WithNontype.1] { +// CHECK:STDOUT: %N.patt: i32 = symbolic_binding_pattern N, 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc4_23.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc4_23.2: type = converted %int.make_type_32, %.loc4_23.1 [template = i32] +// CHECK:STDOUT: %N.param: i32 = param N, runtime_param +// CHECK:STDOUT: %N.loc4: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %N.patt: i32 = symbolic_binding_pattern N, 0 +// CHECK:STDOUT: %x.patt: @F.%WithNontype.1 (%WithNontype.2) = binding_pattern x +// CHECK:STDOUT: } { +// CHECK:STDOUT: %int.make_type_32.loc6_10: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc6_10.1: type = value_of_initializer %int.make_type_32.loc6_10 [template = i32] +// CHECK:STDOUT: %.loc6_10.2: type = converted %int.make_type_32.loc6_10, %.loc6_10.1 [template = i32] +// CHECK:STDOUT: %N.param: i32 = param N, runtime_param +// CHECK:STDOUT: %N.loc6: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %WithNontype.ref: %WithNontype.type = name_ref WithNontype, file.%WithNontype.decl [template = constants.%WithNontype.1] +// CHECK:STDOUT: %N.ref.loc6_30: i32 = name_ref N, %N.loc6 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %WithNontype.loc6: type = class_type @WithNontype, @WithNontype(constants.%N) [symbolic = %WithNontype.1 (constants.%WithNontype.2)] +// CHECK:STDOUT: %x.param: @F.%WithNontype.1 (%WithNontype.2) = param x, runtime_param0 +// CHECK:STDOUT: %x: @F.%WithNontype.1 (%WithNontype.2) = bind_name x, %x.param +// CHECK:STDOUT: %int.make_type_32.loc6_37: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc6_37.1: type = value_of_initializer %int.make_type_32.loc6_37 [template = i32] +// CHECK:STDOUT: %.loc6_37.2: type = converted %int.make_type_32.loc6_37, %.loc6_37.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] {} { +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc8_11.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc8_11.2: type = converted %int.make_type_32, %.loc8_11.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @WithNontype(%N.loc4: i32) { +// CHECK:STDOUT: %N.1: i32 = bind_symbolic_name N, 0 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %.loc4_29: = complete_type_witness %.2 [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%WithNontype.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%N.loc6: i32) { +// CHECK:STDOUT: %N.1: i32 = bind_symbolic_name N, 0 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %WithNontype.1: type = class_type @WithNontype, @WithNontype(%N.1) [symbolic = %WithNontype.1 (constants.%WithNontype.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%N.loc6: i32](%x: @F.%WithNontype.1 (%WithNontype.2)) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %N.ref.loc6_50: i32 = name_ref N, %N.loc6 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: return %N.ref.loc6_50 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G() -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %.loc9_13.1: %.2 = struct_literal () +// CHECK:STDOUT: %WithNontype.ref: %WithNontype.type = name_ref WithNontype, file.%WithNontype.decl [template = constants.%WithNontype.1] +// CHECK:STDOUT: %.loc9_30: i32 = int_literal 0 [template = constants.%.5] +// CHECK:STDOUT: %WithNontype: type = class_type @WithNontype, @WithNontype(constants.%.5) [template = constants.%WithNontype.3] +// CHECK:STDOUT: %.loc9_13.2: ref %WithNontype.3 = temporary_storage +// CHECK:STDOUT: %.loc9_13.3: init %WithNontype.3 = class_init (), %.loc9_13.2 [template = constants.%struct] +// CHECK:STDOUT: %.loc9_13.4: ref %WithNontype.3 = temporary %.loc9_13.2, %.loc9_13.3 +// CHECK:STDOUT: %.loc9_15.1: ref %WithNontype.3 = converted %.loc9_13.1, %.loc9_13.4 +// CHECK:STDOUT: %.loc9_15.2: %WithNontype.3 = bind_value %.loc9_15.1 +// CHECK:STDOUT: %F.call: init i32 = call %F.ref(%.loc9_15.2) +// CHECK:STDOUT: %.loc9_33.1: i32 = value_of_initializer %F.call +// CHECK:STDOUT: %.loc9_33.2: i32 = converted %F.call, %.loc9_33.1 +// CHECK:STDOUT: return %.loc9_33.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @WithNontype(constants.%N) { +// CHECK:STDOUT: %N.1 => constants.%N +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @WithNontype(@F.%N.1) { +// CHECK:STDOUT: %N.1 => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%N) { +// CHECK:STDOUT: %N.1 => constants.%N +// CHECK:STDOUT: %WithNontype.1 => constants.%WithNontype.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @WithNontype(constants.%.5) { +// CHECK:STDOUT: %N.1 => constants.%.5 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%.5) { +// CHECK:STDOUT: %N.1 => constants.%.5 +// CHECK:STDOUT: %WithNontype.1 => constants.%WithNontype.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/deduce/int_float.carbon b/toolchain/check/testdata/deduce/int_float.carbon new file mode 100644 index 0000000000000..164b86de28be8 --- /dev/null +++ b/toolchain/check/testdata/deduce/int_float.carbon @@ -0,0 +1,260 @@ +// 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 +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/int_float.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/int_float.carbon + +// --- int.carbon + +library "[[@TEST_NAME]]"; + +fn F[N:! i32](n: Core.Int(N)) -> i32 { + return N; +} + +fn G(a: i64) -> i32 { + return F(a); +} + +// --- fail_todo_float.carbon + +library "[[@TEST_NAME]]"; + +// TODO: This should pass once we accept symbolic widths for Core.Float. +// CHECK:STDERR: fail_todo_float.carbon:[[@LINE+3]]:18: error: cannot evaluate type expression +// CHECK:STDERR: fn F[N:! i32](n: Core.Float(N)) -> i32 { +// CHECK:STDERR: ^~~~~~~~~~~~~ +fn F[N:! i32](n: Core.Float(N)) -> i32 { + return N; +} + +fn G(a: f64) -> i32 { + return F(a); +} + +// CHECK:STDOUT: --- int.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// 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: %N: i32 = bind_symbolic_name N, 0 [symbolic] +// CHECK:STDOUT: %Int.type: type = fn_type @Int [template] +// CHECK:STDOUT: %Int: %Int.type = struct_value () [template] +// CHECK:STDOUT: %.2: type = int_type signed, %N [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.3: i32 = int_literal 64 [template] +// CHECK:STDOUT: %.4: type = int_type signed, %.3 [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref.1 +// CHECK:STDOUT: .Int = %import_ref.2 +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: %import_ref.2: %Int.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %N.patt: i32 = symbolic_binding_pattern N, 0 +// CHECK:STDOUT: %n.patt: @F.%.1 (%.2) = binding_pattern n +// CHECK:STDOUT: } { +// CHECK:STDOUT: %int.make_type_32.loc4_10: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc4_10.1: type = value_of_initializer %int.make_type_32.loc4_10 [template = i32] +// CHECK:STDOUT: %.loc4_10.2: type = converted %int.make_type_32.loc4_10, %.loc4_10.1 [template = i32] +// CHECK:STDOUT: %N.param: i32 = param N, runtime_param +// CHECK:STDOUT: %N.loc4: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %Core.ref: = name_ref Core, imports.%Core [template = imports.%Core] +// CHECK:STDOUT: %Int.ref: %Int.type = name_ref Int, imports.%import_ref.2 [template = constants.%Int] +// CHECK:STDOUT: %N.ref.loc4: i32 = name_ref N, %N.loc4 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %int.make_type_signed: init type = call %Int.ref(%N.ref.loc4) [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: %.loc4_28.1: type = value_of_initializer %int.make_type_signed [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: %.loc4_28.2: type = converted %int.make_type_signed, %.loc4_28.1 [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: %n.param: @F.%.1 (%.2) = param n, runtime_param0 +// CHECK:STDOUT: %n: @F.%.1 (%.2) = bind_name n, %n.param +// CHECK:STDOUT: %int.make_type_32.loc4_34: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc4_34.1: type = value_of_initializer %int.make_type_32.loc4_34 [template = i32] +// CHECK:STDOUT: %.loc4_34.2: type = converted %int.make_type_32.loc4_34, %.loc4_34.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %a.patt: %.4 = binding_pattern a +// CHECK:STDOUT: } { +// CHECK:STDOUT: %.loc8_9.1: i32 = int_literal 64 [template = constants.%.3] +// CHECK:STDOUT: %int.make_type_signed: init type = call constants.%Int(%.loc8_9.1) [template = constants.%.4] +// CHECK:STDOUT: %.loc8_9.2: type = value_of_initializer %int.make_type_signed [template = constants.%.4] +// CHECK:STDOUT: %.loc8_9.3: type = converted %int.make_type_signed, %.loc8_9.2 [template = constants.%.4] +// CHECK:STDOUT: %a.param: %.4 = param a, runtime_param0 +// CHECK:STDOUT: %a: %.4 = bind_name a, %a.param +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc8_17.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc8_17.2: type = converted %int.make_type_32, %.loc8_17.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int(%size: i32) -> type = "int.make_type_signed"; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%N.loc4: i32) { +// CHECK:STDOUT: %N.1: i32 = bind_symbolic_name N, 0 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %.1: type = int_type signed, %N.1 [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%N.loc4: i32](%n: @F.%.1 (%.2)) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %N.ref.loc5: i32 = name_ref N, %N.loc4 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: return %N.ref.loc5 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%a: %.4) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %a.ref: %.4 = name_ref a, %a +// CHECK:STDOUT: %F.call: init i32 = call %F.ref(%a.ref) +// CHECK:STDOUT: %.loc9_14.1: i32 = value_of_initializer %F.call +// CHECK:STDOUT: %.loc9_14.2: i32 = converted %F.call, %.loc9_14.1 +// CHECK:STDOUT: return %.loc9_14.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%N) { +// CHECK:STDOUT: %N.1 => constants.%N +// CHECK:STDOUT: %.1 => constants.%.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%.3) { +// CHECK:STDOUT: %N.1 => constants.%.3 +// CHECK:STDOUT: %.1 => constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_float.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// 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: %N: i32 = bind_symbolic_name N, 0 [symbolic] +// CHECK:STDOUT: %Float.type: type = fn_type @Float [template] +// CHECK:STDOUT: %Float: %Float.type = struct_value () [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.2: i32 = int_literal 64 [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref.1 +// CHECK:STDOUT: .Float = %import_ref.2 +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: %import_ref.2: %Float.type = import_ref Core//prelude/types, inst+35, loaded [template = constants.%Float] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %N.patt: i32 = symbolic_binding_pattern N, 0 +// CHECK:STDOUT: %n.patt: = binding_pattern n +// CHECK:STDOUT: } { +// CHECK:STDOUT: %int.make_type_32.loc8_10: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc8_10.1: type = value_of_initializer %int.make_type_32.loc8_10 [template = i32] +// CHECK:STDOUT: %.loc8_10.2: type = converted %int.make_type_32.loc8_10, %.loc8_10.1 [template = i32] +// CHECK:STDOUT: %N.param: i32 = param N, runtime_param +// CHECK:STDOUT: %N.loc8: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %Core.ref: = name_ref Core, imports.%Core [template = imports.%Core] +// CHECK:STDOUT: %Float.ref: %Float.type = name_ref Float, imports.%import_ref.2 [template = constants.%Float] +// CHECK:STDOUT: %N.ref.loc8: i32 = name_ref N, %N.loc8 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: %float.make_type: init type = call %Float.ref(%N.ref.loc8) +// CHECK:STDOUT: %.loc8_30.1: type = value_of_initializer %float.make_type +// CHECK:STDOUT: %.loc8_30.2: type = converted %float.make_type, %.loc8_30.1 +// CHECK:STDOUT: %n.param: = param n, runtime_param0 +// CHECK:STDOUT: %n: = bind_name n, %n.param +// CHECK:STDOUT: %int.make_type_32.loc8_36: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc8_36.1: type = value_of_initializer %int.make_type_32.loc8_36 [template = i32] +// CHECK:STDOUT: %.loc8_36.2: type = converted %int.make_type_32.loc8_36, %.loc8_36.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %a.patt: f64 = binding_pattern a +// CHECK:STDOUT: } { +// CHECK:STDOUT: %.loc12_9.1: i32 = int_literal 64 [template = constants.%.2] +// CHECK:STDOUT: %float.make_type: init type = call constants.%Float(%.loc12_9.1) [template = f64] +// CHECK:STDOUT: %.loc12_9.2: type = value_of_initializer %float.make_type [template = f64] +// CHECK:STDOUT: %.loc12_9.3: type = converted %float.make_type, %.loc12_9.2 [template = f64] +// CHECK:STDOUT: %a.param: f64 = param a, runtime_param0 +// CHECK:STDOUT: %a: f64 = bind_name a, %a.param +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc12_17.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc12_17.2: type = converted %int.make_type_32, %.loc12_17.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Float(%size: i32) -> type = "float.make_type"; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%N.loc8: i32) { +// CHECK:STDOUT: %N.1: i32 = bind_symbolic_name N, 0 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%N.loc8: i32](%n: ) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %N.ref.loc9: i32 = name_ref N, %N.loc8 [symbolic = %N.1 (constants.%N)] +// CHECK:STDOUT: return %N.ref.loc9 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%a: f64) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %a.ref: f64 = name_ref a, %a +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%N) { +// CHECK:STDOUT: %N.1 => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/deduce/tuple.carbon b/toolchain/check/testdata/deduce/tuple.carbon new file mode 100644 index 0000000000000..9e9b7fb88d23b --- /dev/null +++ b/toolchain/check/testdata/deduce/tuple.carbon @@ -0,0 +1,471 @@ +// 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 +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/tuple.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/tuple.carbon + +// --- tuple_type.carbon + +library "[[@TEST_NAME]]"; + +class C {} +class D {} + +fn F[T:! type, U:! type](pair: (T, U)) -> U; + +fn G(pair: (C, D)) -> D { + return F(pair); +} + +// --- tuple_value.carbon + +library "[[@TEST_NAME]]"; + +class HasPair(Pair:! (i32, i32)) {} + +fn F[A:! i32, B:! i32](h: HasPair((A, B))) -> i32 { return B; } + +fn G(h: HasPair((1, 2))) -> i32 { + return F(h); +} + +// --- fail_inconsistent.carbon + +library "[[@TEST_NAME]]"; + +class C {} +class D {} + +fn F[T:! type](pair: (T, T)) -> T; + +fn G(pair: (C, D)) -> D { + // CHECK:STDERR: fail_inconsistent.carbon:[[@LINE+6]]:10: error: inconsistent deductions for value of generic parameter `T` + // CHECK:STDERR: return F(pair); + // CHECK:STDERR: ^~ + // CHECK:STDERR: fail_inconsistent.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here + // CHECK:STDERR: fn F[T:! type](pair: (T, T)) -> T; + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + return F(pair); +} + +// CHECK:STDOUT: --- tuple_type.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %D: type = class_type @D [template] +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %U: type = bind_symbolic_name U, 1 [symbolic] +// CHECK:STDOUT: %.3: type = tuple_type (type, type) [template] +// CHECK:STDOUT: %.4: type = tuple_type (%T, %U) [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.5: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.6: type = tuple_type (%C, %D) [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.7: type = ptr_type %.1 [template] +// CHECK:STDOUT: %.8: type = tuple_type (%.7, %.7) [template] +// CHECK:STDOUT: %.9: type = ptr_type %.8 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %D.decl: type = class_decl @D [template = constants.%D] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: %U.patt: type = symbolic_binding_pattern U, 1 +// CHECK:STDOUT: %pair.patt: @F.%.1 (%.4) = binding_pattern pair +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc7: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %U.param: type = param U, runtime_param +// CHECK:STDOUT: %U.loc7: type = bind_symbolic_name U, 1, %U.param [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc7 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %U.ref.loc7_36: type = name_ref U, %U.loc7 [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: %.loc7_37.1: %.3 = tuple_literal (%T.ref, %U.ref.loc7_36) +// CHECK:STDOUT: %.loc7_37.2: type = converted %.loc7_37.1, constants.%.4 [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: %pair.param: @F.%.1 (%.4) = param pair, runtime_param0 +// CHECK:STDOUT: %pair: @F.%.1 (%.4) = bind_name pair, %pair.param +// CHECK:STDOUT: %U.ref.loc7_43: type = name_ref U, %U.loc7 [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: %return: ref @F.%U.1 (%U) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %pair.patt: %.6 = binding_pattern pair +// CHECK:STDOUT: } { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %D.ref.loc9_16: type = name_ref D, file.%D.decl [template = constants.%D] +// CHECK:STDOUT: %.loc9_17.1: %.3 = tuple_literal (%C.ref, %D.ref.loc9_16) +// CHECK:STDOUT: %.loc9_17.2: type = converted %.loc9_17.1, constants.%.6 [template = constants.%.6] +// CHECK:STDOUT: %pair.param: %.6 = param pair, runtime_param0 +// CHECK:STDOUT: %pair: %.6 = bind_name pair, %pair.param +// CHECK:STDOUT: %D.ref.loc9_23: type = name_ref D, file.%D.decl [template = constants.%D] +// CHECK:STDOUT: %return: ref %D = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @D { +// CHECK:STDOUT: %.loc5: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%D +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%T.loc7: type, %U.loc7: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %U.1: type = bind_symbolic_name U, 1 [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: %.1: type = tuple_type (@F.%T.1 (%T), @F.%U.1 (%U)) [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.loc7: type, %U.loc7: type](%pair: @F.%.1 (%.4)) -> @F.%U.1 (%U); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%pair: %.6) -> %return: %D { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %pair.ref: %.6 = name_ref pair, %pair +// CHECK:STDOUT: %.loc9_20: ref %D = splice_block %return {} +// CHECK:STDOUT: %F.call: init %D = call %F.ref(%pair.ref) to %.loc9_20 +// CHECK:STDOUT: return %F.call to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%T, constants.%U) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %U.1 => constants.%U +// CHECK:STDOUT: %.1 => constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%C, constants.%D) { +// CHECK:STDOUT: %T.1 => constants.%C +// CHECK:STDOUT: %U.1 => constants.%D +// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- tuple_value.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// 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 = tuple_type (type, type) [template] +// CHECK:STDOUT: %.3: type = tuple_type (i32, i32) [template] +// CHECK:STDOUT: %Pair: %.3 = bind_symbolic_name Pair, 0 [symbolic] +// CHECK:STDOUT: %HasPair.type: type = generic_class_type @HasPair [template] +// CHECK:STDOUT: %HasPair.1: %HasPair.type = struct_value () [template] +// CHECK:STDOUT: %HasPair.2: type = class_type @HasPair, @HasPair(%Pair) [symbolic] +// CHECK:STDOUT: %.4: type = struct_type {} [template] +// CHECK:STDOUT: %.5: = complete_type_witness %.4 [template] +// CHECK:STDOUT: %A: i32 = bind_symbolic_name A, 0 [symbolic] +// CHECK:STDOUT: %B: i32 = bind_symbolic_name B, 1 [symbolic] +// CHECK:STDOUT: %.6: type = ptr_type %.3 [template] +// CHECK:STDOUT: %tuple.1: %.3 = tuple_value (%A, %B) [symbolic] +// CHECK:STDOUT: %HasPair.3: type = class_type @HasPair, @HasPair(%tuple.1) [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.7: type = ptr_type %.4 [template] +// CHECK:STDOUT: %.8: i32 = int_literal 1 [template] +// CHECK:STDOUT: %.9: i32 = int_literal 2 [template] +// CHECK:STDOUT: %tuple.2: %.3 = tuple_value (%.8, %.9) [template] +// CHECK:STDOUT: %HasPair.4: type = class_type @HasPair, @HasPair(%tuple.2) [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [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/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .HasPair = %HasPair.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %HasPair.decl: %HasPair.type = class_decl @HasPair [template = constants.%HasPair.1] { +// CHECK:STDOUT: %Pair.patt: %.3 = symbolic_binding_pattern Pair, 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %int.make_type_32.loc4_23: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %int.make_type_32.loc4_28: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc4_31.1: %.2 = tuple_literal (%int.make_type_32.loc4_23, %int.make_type_32.loc4_28) +// CHECK:STDOUT: %.loc4_31.2: type = value_of_initializer %int.make_type_32.loc4_23 [template = i32] +// CHECK:STDOUT: %.loc4_31.3: type = converted %int.make_type_32.loc4_23, %.loc4_31.2 [template = i32] +// CHECK:STDOUT: %.loc4_31.4: type = value_of_initializer %int.make_type_32.loc4_28 [template = i32] +// CHECK:STDOUT: %.loc4_31.5: type = converted %int.make_type_32.loc4_28, %.loc4_31.4 [template = i32] +// CHECK:STDOUT: %.loc4_31.6: type = converted %.loc4_31.1, constants.%.3 [template = constants.%.3] +// CHECK:STDOUT: %Pair.param: %.3 = param Pair, runtime_param +// CHECK:STDOUT: %Pair.loc4: %.3 = bind_symbolic_name Pair, 0, %Pair.param [symbolic = %Pair.1 (constants.%Pair)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %A.patt: i32 = symbolic_binding_pattern A, 0 +// CHECK:STDOUT: %B.patt: i32 = symbolic_binding_pattern B, 1 +// CHECK:STDOUT: %h.patt: @F.%HasPair.1 (%HasPair.3) = binding_pattern h +// CHECK:STDOUT: } { +// CHECK:STDOUT: %int.make_type_32.loc6_10: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc6_10.1: type = value_of_initializer %int.make_type_32.loc6_10 [template = i32] +// CHECK:STDOUT: %.loc6_10.2: type = converted %int.make_type_32.loc6_10, %.loc6_10.1 [template = i32] +// CHECK:STDOUT: %A.param: i32 = param A, runtime_param +// CHECK:STDOUT: %A.loc6: i32 = bind_symbolic_name A, 0, %A.param [symbolic = %A.1 (constants.%A)] +// CHECK:STDOUT: %int.make_type_32.loc6_19: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc6_19.1: type = value_of_initializer %int.make_type_32.loc6_19 [template = i32] +// CHECK:STDOUT: %.loc6_19.2: type = converted %int.make_type_32.loc6_19, %.loc6_19.1 [template = i32] +// CHECK:STDOUT: %B.param: i32 = param B, runtime_param +// CHECK:STDOUT: %B.loc6: i32 = bind_symbolic_name B, 1, %B.param [symbolic = %B.1 (constants.%B)] +// CHECK:STDOUT: %HasPair.ref: %HasPair.type = name_ref HasPair, file.%HasPair.decl [template = constants.%HasPair.1] +// CHECK:STDOUT: %A.ref: i32 = name_ref A, %A.loc6 [symbolic = %A.1 (constants.%A)] +// CHECK:STDOUT: %B.ref.loc6_39: i32 = name_ref B, %B.loc6 [symbolic = %B.1 (constants.%B)] +// CHECK:STDOUT: %.loc6_40: %.3 = tuple_literal (%A.ref, %B.ref.loc6_39) +// CHECK:STDOUT: %tuple.loc6: %.3 = tuple_value (%A.ref, %B.ref.loc6_39) [symbolic = %tuple.1 (constants.%tuple.1)] +// CHECK:STDOUT: %.loc6_34: %.3 = converted %.loc6_40, %tuple.loc6 [symbolic = %tuple.1 (constants.%tuple.1)] +// CHECK:STDOUT: %HasPair.loc6: type = class_type @HasPair, @HasPair(constants.%tuple.1) [symbolic = %HasPair.1 (constants.%HasPair.3)] +// CHECK:STDOUT: %h.param: @F.%HasPair.1 (%HasPair.3) = param h, runtime_param0 +// CHECK:STDOUT: %h: @F.%HasPair.1 (%HasPair.3) = bind_name h, %h.param +// CHECK:STDOUT: %int.make_type_32.loc6_47: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc6_47.1: type = value_of_initializer %int.make_type_32.loc6_47 [template = i32] +// CHECK:STDOUT: %.loc6_47.2: type = converted %int.make_type_32.loc6_47, %.loc6_47.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %h.patt: %HasPair.4 = binding_pattern h +// CHECK:STDOUT: } { +// CHECK:STDOUT: %HasPair.ref: %HasPair.type = name_ref HasPair, file.%HasPair.decl [template = constants.%HasPair.1] +// CHECK:STDOUT: %.loc8_18: i32 = int_literal 1 [template = constants.%.8] +// CHECK:STDOUT: %.loc8_21: i32 = int_literal 2 [template = constants.%.9] +// CHECK:STDOUT: %.loc8_22: %.3 = tuple_literal (%.loc8_18, %.loc8_21) +// CHECK:STDOUT: %tuple: %.3 = tuple_value (%.loc8_18, %.loc8_21) [template = constants.%tuple.2] +// CHECK:STDOUT: %.loc8_16: %.3 = converted %.loc8_22, %tuple [template = constants.%tuple.2] +// CHECK:STDOUT: %HasPair: type = class_type @HasPair, @HasPair(constants.%tuple.2) [template = constants.%HasPair.4] +// CHECK:STDOUT: %h.param: %HasPair.4 = param h, runtime_param0 +// CHECK:STDOUT: %h: %HasPair.4 = bind_name h, %h.param +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc8_29.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc8_29.2: type = converted %int.make_type_32, %.loc8_29.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @HasPair(%Pair.loc4: %.3) { +// CHECK:STDOUT: %Pair.1: %.3 = bind_symbolic_name Pair, 0 [symbolic = %Pair.1 (constants.%Pair)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %.loc4_35: = complete_type_witness %.4 [template = constants.%.5] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%HasPair.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%A.loc6: i32, %B.loc6: i32) { +// CHECK:STDOUT: %A.1: i32 = bind_symbolic_name A, 0 [symbolic = %A.1 (constants.%A)] +// CHECK:STDOUT: %B.1: i32 = bind_symbolic_name B, 1 [symbolic = %B.1 (constants.%B)] +// CHECK:STDOUT: %tuple.1: %.3 = tuple_value (%A.1, %B.1) [symbolic = %tuple.1 (constants.%tuple.1)] +// CHECK:STDOUT: %HasPair.1: type = class_type @HasPair, @HasPair(%tuple.1) [symbolic = %HasPair.1 (constants.%HasPair.3)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%A.loc6: i32, %B.loc6: i32](%h: @F.%HasPair.1 (%HasPair.3)) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %B.ref.loc6_60: i32 = name_ref B, %B.loc6 [symbolic = %B.1 (constants.%B)] +// CHECK:STDOUT: return %B.ref.loc6_60 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%h: %HasPair.4) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %h.ref: %HasPair.4 = name_ref h, %h +// CHECK:STDOUT: %F.call: init i32 = call %F.ref(%h.ref) +// CHECK:STDOUT: %.loc9_14.1: i32 = value_of_initializer %F.call +// CHECK:STDOUT: %.loc9_14.2: i32 = converted %F.call, %.loc9_14.1 +// CHECK:STDOUT: return %.loc9_14.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @HasPair(constants.%Pair) { +// CHECK:STDOUT: %Pair.1 => constants.%Pair +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @HasPair(constants.%tuple.1) { +// CHECK:STDOUT: %Pair.1 => constants.%tuple.1 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @HasPair(@F.%tuple.1) { +// CHECK:STDOUT: %Pair.1 => constants.%tuple.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%A, constants.%B) { +// CHECK:STDOUT: %A.1 => constants.%A +// CHECK:STDOUT: %B.1 => constants.%B +// CHECK:STDOUT: %tuple.1 => constants.%tuple.1 +// CHECK:STDOUT: %HasPair.1 => constants.%HasPair.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @HasPair(constants.%tuple.2) { +// CHECK:STDOUT: %Pair.1 => constants.%tuple.2 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%.8, constants.%.9) { +// CHECK:STDOUT: %A.1 => constants.%.8 +// CHECK:STDOUT: %B.1 => constants.%.9 +// CHECK:STDOUT: %tuple.1 => constants.%tuple.2 +// CHECK:STDOUT: %HasPair.1 => constants.%HasPair.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_inconsistent.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %D: type = class_type @D [template] +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %.3: type = tuple_type (type, type) [template] +// CHECK:STDOUT: %.4: type = tuple_type (%T, %T) [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.5: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.6: type = tuple_type (%C, %D) [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.7: type = ptr_type %.1 [template] +// CHECK:STDOUT: %.8: type = tuple_type (%.7, %.7) [template] +// CHECK:STDOUT: %.9: type = ptr_type %.8 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %D.decl: type = class_decl @D [template = constants.%D] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: %pair.patt: @F.%.1 (%.4) = binding_pattern pair +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc7: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc7_23: type = name_ref T, %T.loc7 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc7_26: type = name_ref T, %T.loc7 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc7_27.1: %.3 = tuple_literal (%T.ref.loc7_23, %T.ref.loc7_26) +// CHECK:STDOUT: %.loc7_27.2: type = converted %.loc7_27.1, constants.%.4 [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: %pair.param: @F.%.1 (%.4) = param pair, runtime_param0 +// CHECK:STDOUT: %pair: @F.%.1 (%.4) = bind_name pair, %pair.param +// CHECK:STDOUT: %T.ref.loc7_33: type = name_ref T, %T.loc7 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %return: ref @F.%T.1 (%T) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %pair.patt: %.6 = binding_pattern pair +// CHECK:STDOUT: } { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %D.ref.loc9_16: type = name_ref D, file.%D.decl [template = constants.%D] +// CHECK:STDOUT: %.loc9_17.1: %.3 = tuple_literal (%C.ref, %D.ref.loc9_16) +// CHECK:STDOUT: %.loc9_17.2: type = converted %.loc9_17.1, constants.%.6 [template = constants.%.6] +// CHECK:STDOUT: %pair.param: %.6 = param pair, runtime_param0 +// CHECK:STDOUT: %pair: %.6 = bind_name pair, %pair.param +// CHECK:STDOUT: %D.ref.loc9_23: type = name_ref D, file.%D.decl [template = constants.%D] +// CHECK:STDOUT: %return: ref %D = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @D { +// CHECK:STDOUT: %.loc5: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%D +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%T.loc7: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.1: type = tuple_type (@F.%T.1 (%T), @F.%T.1 (%T)) [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.loc7: type](%pair: @F.%.1 (%.4)) -> @F.%T.1 (%T); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%pair: %.6) -> %return: %D { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %pair.ref: %.6 = name_ref pair, %pair +// CHECK:STDOUT: return to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %.1 => constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/deduce/type_operator.carbon b/toolchain/check/testdata/deduce/type_operator.carbon new file mode 100644 index 0000000000000..d44aedd188b15 --- /dev/null +++ b/toolchain/check/testdata/deduce/type_operator.carbon @@ -0,0 +1,461 @@ +// 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 +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/type_operator.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/type_operator.carbon + +// --- pointer.carbon + +library "[[@TEST_NAME]]"; + +class C {} + +fn F[T:! type](p: T*) -> T; + +fn G(p: C*) -> C { + return F(p); +} + +// --- const.carbon + +library "[[@TEST_NAME]]"; + +class C {} + +fn F[T:! type](p: const T*) -> T; + +fn G(p: const C*) -> C { + return F(p); +} + +// --- nonconst_from_const.carbon + +library "[[@TEST_NAME]]"; + +class C {} + +fn F[T:! type](p: T*) -> T; + +fn G(p: const C*) -> const C { + return F(p); +} + +// --- fail_const_from_nonconst.carbon + +library "[[@TEST_NAME]]"; + +class C {} + +fn F[T:! type](p: const T*) -> T; + +fn G(p: C*) -> const C { + // CHECK:STDERR: fail_const_from_nonconst.carbon:[[@LINE+6]]:10: error: cannot deduce value for generic parameter `T` + // CHECK:STDERR: return F(p); + // CHECK:STDERR: ^~ + // CHECK:STDERR: fail_const_from_nonconst.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here + // CHECK:STDERR: fn F[T:! type](p: const T*) -> T; + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + return F(p); +} + +// CHECK:STDOUT: --- pointer.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %.3: type = ptr_type %T [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.4: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.5: type = ptr_type %C [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.6: type = ptr_type %.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: %p.patt: @F.%.1 (%.3) = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc6: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc6_19: type = name_ref T, %T.loc6 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc6: type = ptr_type %T [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %p.param: @F.%.1 (%.3) = param p, runtime_param0 +// CHECK:STDOUT: %p: @F.%.1 (%.3) = bind_name p, %p.param +// CHECK:STDOUT: %T.ref.loc6_26: type = name_ref T, %T.loc6 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %return: ref @F.%T.1 (%T) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %p.patt: %.5 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %C.ref.loc8_9: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc8_10: type = ptr_type %C [template = constants.%.5] +// CHECK:STDOUT: %p.param: %.5 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.5 = bind_name p, %p.param +// CHECK:STDOUT: %C.ref.loc8_16: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return: ref %C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%T.loc6: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.1: type = ptr_type @F.%T.1 (%T) [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.loc6: type](%p: @F.%.1 (%.3)) -> @F.%T.1 (%T); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%p: %.5) -> %return: %C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %p.ref: %.5 = name_ref p, %p +// CHECK:STDOUT: %.loc8_13: ref %C = splice_block %return {} +// CHECK:STDOUT: %F.call: init %C = call %F.ref(%p.ref) to %.loc8_13 +// CHECK:STDOUT: return %F.call to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %.1 => constants.%.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%C) { +// CHECK:STDOUT: %T.1 => constants.%C +// CHECK:STDOUT: %.1 => constants.%.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- const.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %.3: type = const_type %T [symbolic] +// CHECK:STDOUT: %.4: type = ptr_type %.3 [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.5: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.6: type = const_type %C [template] +// CHECK:STDOUT: %.7: type = ptr_type %.6 [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: %p.patt: @F.%.2 (%.4) = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc6: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc6_25: type = name_ref T, %T.loc6 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc6_19: type = const_type %T [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %.loc6_26: type = ptr_type %.3 [symbolic = %.2 (constants.%.4)] +// CHECK:STDOUT: %p.param: @F.%.2 (%.4) = param p, runtime_param0 +// CHECK:STDOUT: %p: @F.%.2 (%.4) = bind_name p, %p.param +// CHECK:STDOUT: %T.ref.loc6_32: type = name_ref T, %T.loc6 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %return: ref @F.%T.1 (%T) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %p.patt: %.7 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %C.ref.loc8_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc8_9: type = const_type %C [template = constants.%.6] +// CHECK:STDOUT: %.loc8_16: type = ptr_type %.6 [template = constants.%.7] +// CHECK:STDOUT: %p.param: %.7 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.7 = bind_name p, %p.param +// CHECK:STDOUT: %C.ref.loc8_22: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return: ref %C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%T.loc6: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.1: type = const_type @F.%T.1 (%T) [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %.2: type = ptr_type @F.%.1 (%.3) [symbolic = %.2 (constants.%.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.loc6: type](%p: @F.%.2 (%.4)) -> @F.%T.1 (%T); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%p: %.7) -> %return: %C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %p.ref: %.7 = name_ref p, %p +// CHECK:STDOUT: %.loc8_19: ref %C = splice_block %return {} +// CHECK:STDOUT: %F.call: init %C = call %F.ref(%p.ref) to %.loc8_19 +// CHECK:STDOUT: return %F.call to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %.1 => constants.%.3 +// CHECK:STDOUT: %.2 => constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%C) { +// CHECK:STDOUT: %T.1 => constants.%C +// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: %.2 => constants.%.7 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- nonconst_from_const.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %.3: type = ptr_type %T [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.4: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.5: type = const_type %C [template] +// CHECK:STDOUT: %.6: type = ptr_type %.5 [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.7: type = ptr_type %.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: %p.patt: @F.%.1 (%.3) = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc6: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc6_19: type = name_ref T, %T.loc6 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc6: type = ptr_type %T [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %p.param: @F.%.1 (%.3) = param p, runtime_param0 +// CHECK:STDOUT: %p: @F.%.1 (%.3) = bind_name p, %p.param +// CHECK:STDOUT: %T.ref.loc6_26: type = name_ref T, %T.loc6 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %return: ref @F.%T.1 (%T) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %p.patt: %.6 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %C.ref.loc8_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc8_9: type = const_type %C [template = constants.%.5] +// CHECK:STDOUT: %.loc8_16: type = ptr_type %.5 [template = constants.%.6] +// CHECK:STDOUT: %p.param: %.6 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.6 = bind_name p, %p.param +// CHECK:STDOUT: %C.ref.loc8_28: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc8_22: type = const_type %C [template = constants.%.5] +// CHECK:STDOUT: %return: ref %.5 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%T.loc6: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.1: type = ptr_type @F.%T.1 (%T) [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.loc6: type](%p: @F.%.1 (%.3)) -> @F.%T.1 (%T); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%p: %.6) -> %return: %.5 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %p.ref: %.6 = name_ref p, %p +// CHECK:STDOUT: %.loc8_19: ref %.5 = splice_block %return {} +// CHECK:STDOUT: %F.call: init %.5 = call %F.ref(%p.ref) to %.loc8_19 +// CHECK:STDOUT: return %F.call to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %.1 => constants.%.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%.5) { +// CHECK:STDOUT: %T.1 => constants.%.5 +// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_const_from_nonconst.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %.3: type = const_type %T [symbolic] +// CHECK:STDOUT: %.4: type = ptr_type %.3 [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.5: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.6: type = ptr_type %C [template] +// CHECK:STDOUT: %.7: type = const_type %C [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: %p.patt: @F.%.2 (%.4) = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc6: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc6_25: type = name_ref T, %T.loc6 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc6_19: type = const_type %T [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %.loc6_26: type = ptr_type %.3 [symbolic = %.2 (constants.%.4)] +// CHECK:STDOUT: %p.param: @F.%.2 (%.4) = param p, runtime_param0 +// CHECK:STDOUT: %p: @F.%.2 (%.4) = bind_name p, %p.param +// CHECK:STDOUT: %T.ref.loc6_32: type = name_ref T, %T.loc6 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %return: ref @F.%T.1 (%T) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %p.patt: %.6 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %C.ref.loc8_9: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc8_10: type = ptr_type %C [template = constants.%.6] +// CHECK:STDOUT: %p.param: %.6 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.6 = bind_name p, %p.param +// CHECK:STDOUT: %C.ref.loc8_22: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc8_16: type = const_type %C [template = constants.%.7] +// CHECK:STDOUT: %return: ref %.7 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%T.loc6: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.1: type = const_type @F.%T.1 (%T) [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %.2: type = ptr_type @F.%.1 (%.3) [symbolic = %.2 (constants.%.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%T.loc6: type](%p: @F.%.2 (%.4)) -> @F.%T.1 (%T); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%p: %.6) -> %return: %.7 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] +// CHECK:STDOUT: %p.ref: %.6 = name_ref p, %p +// CHECK:STDOUT: return to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %.1 => constants.%.3 +// CHECK:STDOUT: %.2 => constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/generic/deduce.carbon b/toolchain/check/testdata/function/generic/deduce.carbon index 9418f5d0914e5..8bf08054fed7d 100644 --- a/toolchain/check/testdata/function/generic/deduce.carbon +++ b/toolchain/check/testdata/function/generic/deduce.carbon @@ -52,30 +52,27 @@ fn CallImplicitGenericParam(n: i32) -> i32* { return ImplicitGenericParam(n); } -// --- fail_todo_deduce_nested.carbon +// --- deduce_nested_tuple.carbon library "[[@TEST_NAME]]"; fn TupleParam[T:! type](x: (T, i32)); fn CallTupleParam() { - // CHECK:STDERR: fail_todo_deduce_nested.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T` - // CHECK:STDERR: TupleParam((1, 2)); - // CHECK:STDERR: ^~~~~~~~~~~ - // CHECK:STDERR: fail_todo_deduce_nested.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here - // CHECK:STDERR: fn TupleParam[T:! type](x: (T, i32)); - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: TupleParam((1, 2)); } +// --- fail_todo_deduce_nested_struct.carbon + +library "[[@TEST_NAME]]"; + fn StructParam[T:! type](x: {.a: T, .b: i32}); fn CallStructParam() { - // CHECK:STDERR: fail_todo_deduce_nested.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T` + // CHECK:STDERR: fail_todo_deduce_nested_struct.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T` // CHECK:STDERR: StructParam({.a = 1, .b = 2}); // CHECK:STDERR: ^~~~~~~~~~~~ - // CHECK:STDERR: fail_todo_deduce_nested.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here + // CHECK:STDERR: fail_todo_deduce_nested_struct.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here // CHECK:STDERR: fn StructParam[T:! type](x: {.a: T, .b: i32}); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -443,7 +440,7 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: %.1 => constants.%.3 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_deduce_nested.carbon +// CHECK:STDOUT: --- deduce_nested_tuple.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] @@ -459,12 +456,8 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: %.4: i32 = int_literal 1 [template] // CHECK:STDOUT: %.5: i32 = int_literal 2 [template] // CHECK:STDOUT: %.6: type = tuple_type (i32, i32) [template] -// CHECK:STDOUT: %.7: type = struct_type {.a: %T, .b: i32} [symbolic] -// CHECK:STDOUT: %StructParam.type: type = fn_type @StructParam [template] -// CHECK:STDOUT: %StructParam: %StructParam.type = struct_value () [template] -// CHECK:STDOUT: %CallStructParam.type: type = fn_type @CallStructParam [template] -// CHECK:STDOUT: %CallStructParam: %CallStructParam.type = struct_value () [template] -// CHECK:STDOUT: %.8: type = struct_type {.a: i32, .b: i32} [template] +// CHECK:STDOUT: %.7: type = ptr_type %.6 [template] +// CHECK:STDOUT: %tuple: %.6 = tuple_value (%.4, %.5) [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -487,8 +480,6 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .TupleParam = %TupleParam.decl // CHECK:STDOUT: .CallTupleParam = %CallTupleParam.decl -// CHECK:STDOUT: .StructParam = %StructParam.decl -// CHECK:STDOUT: .CallStructParam = %CallStructParam.decl // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %TupleParam.decl: %TupleParam.type = fn_decl @TupleParam [template = constants.%TupleParam] { @@ -507,21 +498,6 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: %x: @TupleParam.%.1 (%.3) = bind_name x, %x.param // CHECK:STDOUT: } // CHECK:STDOUT: %CallTupleParam.decl: %CallTupleParam.type = fn_decl @CallTupleParam [template = constants.%CallTupleParam] {} {} -// CHECK:STDOUT: %StructParam.decl: %StructParam.type = fn_decl @StructParam [template = constants.%StructParam] { -// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 -// CHECK:STDOUT: %x.patt: @StructParam.%.1 (%.7) = binding_pattern x -// CHECK:STDOUT: } { -// CHECK:STDOUT: %T.param: type = param T, runtime_param -// CHECK:STDOUT: %T.loc17: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] -// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc17 [symbolic = %T.1 (constants.%T)] -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc17_41.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc17_41.2: type = converted %int.make_type_32, %.loc17_41.1 [template = i32] -// CHECK:STDOUT: %.loc17_44: type = struct_type {.a: %T, .b: i32} [symbolic = %.1 (constants.%.7)] -// CHECK:STDOUT: %x.param: @StructParam.%.1 (%.7) = param x, runtime_param0 -// CHECK:STDOUT: %x: @StructParam.%.1 (%.7) = bind_name x, %x.param -// CHECK:STDOUT: } -// CHECK:STDOUT: %CallStructParam.decl: %CallStructParam.type = fn_decl @CallStructParam [template = constants.%CallStructParam] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; @@ -536,36 +512,102 @@ fn CallImplicitNotDeducible() { // CHECK:STDOUT: fn @CallTupleParam() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %TupleParam.ref: %TupleParam.type = name_ref TupleParam, file.%TupleParam.decl [template = constants.%TupleParam] -// CHECK:STDOUT: %.loc14_15: i32 = int_literal 1 [template = constants.%.4] -// CHECK:STDOUT: %.loc14_18: i32 = int_literal 2 [template = constants.%.5] -// CHECK:STDOUT: %.loc14_19: %.6 = tuple_literal (%.loc14_15, %.loc14_18) +// CHECK:STDOUT: %.loc7_15: i32 = int_literal 1 [template = constants.%.4] +// CHECK:STDOUT: %.loc7_18: i32 = int_literal 2 [template = constants.%.5] +// CHECK:STDOUT: %.loc7_19: %.6 = tuple_literal (%.loc7_15, %.loc7_18) +// CHECK:STDOUT: %tuple: %.6 = tuple_value (%.loc7_15, %.loc7_18) [template = constants.%tuple] +// CHECK:STDOUT: %.loc7_13: %.6 = converted %.loc7_19, %tuple [template = constants.%tuple] +// CHECK:STDOUT: %TupleParam.call: init %.1 = call %TupleParam.ref(%.loc7_13) // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic fn @StructParam(%T.loc17: type) { +// CHECK:STDOUT: specific @TupleParam(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %.1 => constants.%.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @TupleParam(i32) { +// CHECK:STDOUT: %T.1 => i32 +// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_deduce_nested_struct.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name 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 {.a: %T, .b: i32} [symbolic] +// CHECK:STDOUT: %StructParam.type: type = fn_type @StructParam [template] +// CHECK:STDOUT: %StructParam: %StructParam.type = struct_value () [template] +// CHECK:STDOUT: %CallStructParam.type: type = fn_type @CallStructParam [template] +// CHECK:STDOUT: %CallStructParam: %CallStructParam.type = struct_value () [template] +// CHECK:STDOUT: %.3: i32 = int_literal 1 [template] +// CHECK:STDOUT: %.4: i32 = int_literal 2 [template] +// CHECK:STDOUT: %.5: type = struct_type {.a: i32, .b: 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/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .StructParam = %StructParam.decl +// CHECK:STDOUT: .CallStructParam = %CallStructParam.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %StructParam.decl: %StructParam.type = fn_decl @StructParam [template = constants.%StructParam] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 +// CHECK:STDOUT: %x.patt: @StructParam.%.1 (%.2) = binding_pattern x +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc4: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc4 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc4_41.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc4_41.2: type = converted %int.make_type_32, %.loc4_41.1 [template = i32] +// CHECK:STDOUT: %.loc4_44: type = struct_type {.a: %T, .b: i32} [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: %x.param: @StructParam.%.1 (%.2) = param x, runtime_param0 +// CHECK:STDOUT: %x: @StructParam.%.1 (%.2) = bind_name x, %x.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %CallStructParam.decl: %CallStructParam.type = fn_decl @CallStructParam [template = constants.%CallStructParam] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @StructParam(%T.loc4: type) { // CHECK:STDOUT: %T.1: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)] -// CHECK:STDOUT: %.1: type = struct_type {.a: @StructParam.%T.1 (%T), .b: i32} [symbolic = %.1 (constants.%.7)] +// CHECK:STDOUT: %.1: type = struct_type {.a: @StructParam.%T.1 (%T), .b: i32} [symbolic = %.1 (constants.%.2)] // CHECK:STDOUT: -// CHECK:STDOUT: fn[%T.loc17: type](%x: @StructParam.%.1 (%.7)); +// CHECK:STDOUT: fn[%T.loc4: type](%x: @StructParam.%.1 (%.2)); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @CallStructParam() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %StructParam.ref: %StructParam.type = name_ref StructParam, file.%StructParam.decl [template = constants.%StructParam] -// CHECK:STDOUT: %.loc27_21: i32 = int_literal 1 [template = constants.%.4] -// CHECK:STDOUT: %.loc27_29: i32 = int_literal 2 [template = constants.%.5] -// CHECK:STDOUT: %.loc27_30: %.8 = struct_literal (%.loc27_21, %.loc27_29) +// CHECK:STDOUT: %.loc14_21: i32 = int_literal 1 [template = constants.%.3] +// CHECK:STDOUT: %.loc14_29: i32 = int_literal 2 [template = constants.%.4] +// CHECK:STDOUT: %.loc14_30: %.5 = struct_literal (%.loc14_21, %.loc14_29) // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @TupleParam(constants.%T) { -// CHECK:STDOUT: %T.1 => constants.%T -// CHECK:STDOUT: %.1 => constants.%.3 -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: specific @StructParam(constants.%T) { // CHECK:STDOUT: %T.1 => constants.%T -// CHECK:STDOUT: %.1 => constants.%.7 +// CHECK:STDOUT: %.1 => constants.%.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_deduce_incomplete.carbon diff --git a/toolchain/check/testdata/impl/lookup/generic.carbon b/toolchain/check/testdata/impl/lookup/generic.carbon index 333a5667158f1..36e55cecee2dc 100644 --- a/toolchain/check/testdata/impl/lookup/generic.carbon +++ b/toolchain/check/testdata/impl/lookup/generic.carbon @@ -40,7 +40,7 @@ fn G(x: {}) -> {} { return x.(HasF.F)(); } -// --- fail_todo_deduced_type_argument.carbon +// --- deduced_type_argument.carbon library "[[@TEST_NAME]]"; @@ -55,15 +55,10 @@ impl forall [T:! type] C(T) as HasF { } fn G(x: C({})) { - // TODO: Implement support for deducing T in C(T). - // CHECK:STDERR: fail_todo_deduced_type_argument.carbon:[[@LINE+4]]:3: error: cannot access member of interface `HasF` in type `C` that does not implement that interface - // CHECK:STDERR: x.(HasF.F)(); - // CHECK:STDERR: ^~~~~~~~~~ - // CHECK:STDERR: x.(HasF.F)(); } -// --- fail_todo_deduced_interface_argument.carbon +// --- deduced_interface_argument.carbon library "[[@TEST_NAME]]"; @@ -76,11 +71,6 @@ impl forall [T:! type] {} as HasF(T) { } fn G(x: {}) { - // TODO: Implement support for deducing T in HasF(T). - // CHECK:STDERR: fail_todo_deduced_interface_argument.carbon:[[@LINE+4]]:3: error: cannot access member of interface `HasF` in type `{}` that does not implement that interface - // CHECK:STDERR: x.(HasF({}).F)(); - // CHECK:STDERR: ^~~~~~~~~~~~~~ - // CHECK:STDERR: x.(HasF({}).F)(); } @@ -460,7 +450,7 @@ fn G(x: A) { // CHECK:STDOUT: %T => constants.%.5 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_deduced_type_argument.carbon +// CHECK:STDOUT: --- deduced_type_argument.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %HasF.type: type = interface_type @HasF [template] @@ -483,6 +473,9 @@ fn G(x: A) { // CHECK:STDOUT: %G.type: type = fn_type @G [template] // CHECK:STDOUT: %G: %G.type = struct_value () [template] // CHECK:STDOUT: %.7: type = ptr_type %.4 [template] +// CHECK:STDOUT: %F.type.3: type = fn_type @F.2, @impl(%.4) [template] +// CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [template] +// CHECK:STDOUT: %.8: = interface_witness (%F.3) [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -597,6 +590,8 @@ fn G(x: A) { // CHECK:STDOUT: %x.ref: %C.3 = name_ref x, %x // CHECK:STDOUT: %HasF.ref: type = name_ref HasF, file.%HasF.decl [template = constants.%HasF.type] // CHECK:STDOUT: %F.ref: %.2 = name_ref F, @HasF.%.loc5 [template = constants.%.3] +// CHECK:STDOUT: %.loc15: %F.type.1 = interface_witness_access constants.%.8, element0 [template = constants.%F.3] +// CHECK:STDOUT: %F.call: init %.1 = call %.loc15() // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: @@ -635,7 +630,19 @@ fn G(x: A) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_deduced_interface_argument.carbon +// CHECK:STDOUT: specific @impl(constants.%.4) { +// CHECK:STDOUT: %T.1 => constants.%.4 +// CHECK:STDOUT: %C.1 => constants.%C.3 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %F.type => constants.%F.type.3 +// CHECK:STDOUT: %F => constants.%F.3 +// CHECK:STDOUT: %.1 => constants.%.8 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.2(constants.%.4) {} +// CHECK:STDOUT: +// CHECK:STDOUT: --- deduced_interface_argument.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] @@ -659,6 +666,9 @@ fn G(x: A) { // CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [template] // CHECK:STDOUT: %.6: type = assoc_entity_type %HasF.type.3, %F.type.3 [template] // CHECK:STDOUT: %.7: %.6 = assoc_entity element0, @HasF.%F.decl [template] +// CHECK:STDOUT: %F.type.4: type = fn_type @F.2, @impl(%.4) [template] +// CHECK:STDOUT: %F.4: %F.type.4 = struct_value () [template] +// CHECK:STDOUT: %.8: = interface_witness (%F.4) [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -768,11 +778,13 @@ fn G(x: A) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %x.ref: %.4 = name_ref x, %x // CHECK:STDOUT: %HasF.ref: %HasF.type.1 = name_ref HasF, file.%HasF.decl [template = constants.%HasF] -// CHECK:STDOUT: %.loc18_12: %.4 = struct_literal () -// CHECK:STDOUT: %.loc18_10: type = converted %.loc18_12, constants.%.4 [template = constants.%.4] +// CHECK:STDOUT: %.loc13_12: %.4 = struct_literal () +// CHECK:STDOUT: %.loc13_10: type = converted %.loc13_12, constants.%.4 [template = constants.%.4] // CHECK:STDOUT: %HasF.type: type = interface_type @HasF, @HasF(constants.%.4) [template = constants.%HasF.type.3] -// CHECK:STDOUT: %.loc18_14: %.6 = specific_constant @HasF.%.loc5, @HasF(constants.%.4) [template = constants.%.7] -// CHECK:STDOUT: %F.ref: %.6 = name_ref F, %.loc18_14 [template = constants.%.7] +// CHECK:STDOUT: %.loc13_14: %.6 = specific_constant @HasF.%.loc5, @HasF(constants.%.4) [template = constants.%.7] +// CHECK:STDOUT: %F.ref: %.6 = name_ref F, %.loc13_14 [template = constants.%.7] +// CHECK:STDOUT: %.loc13_4: %F.type.3 = interface_witness_access constants.%.8, element0 [template = constants.%F.4] +// CHECK:STDOUT: %F.call: init %.1 = call %.loc13_4() // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: @@ -829,6 +841,18 @@ fn G(x: A) { // CHECK:STDOUT: %.2 => constants.%.7 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @impl(constants.%.4) { +// CHECK:STDOUT: %T.1 => constants.%.4 +// CHECK:STDOUT: %HasF.type.1 => constants.%HasF.type.3 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %F.type => constants.%F.type.4 +// CHECK:STDOUT: %F => constants.%F.4 +// CHECK:STDOUT: %.1 => constants.%.8 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.2(constants.%.4) {} +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_incomplete_deduction.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -992,7 +1016,6 @@ fn G(x: A) { // CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [template] // CHECK:STDOUT: %.8: type = assoc_entity_type %HasF.type.3, %F.type.3 [template] // CHECK:STDOUT: %.9: %.8 = assoc_entity element0, @HasF.%F.decl [template] -// CHECK:STDOUT: %HasF.type.4: type = interface_type @HasF, @HasF(%A) [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -1178,12 +1201,3 @@ fn G(x: A) { // CHECK:STDOUT: %.2 => constants.%.9 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @impl(constants.%A) { -// CHECK:STDOUT: %T.1 => constants.%A -// CHECK:STDOUT: %HasF.type.1 => constants.%HasF.type.4 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: specific @HasF(constants.%A) { -// CHECK:STDOUT: %T.1 => constants.%A -// CHECK:STDOUT: } -// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/lookup/no_prelude/impl_forall.carbon b/toolchain/check/testdata/impl/lookup/no_prelude/impl_forall.carbon index 61917ab902885..76aa904e0f729 100644 --- a/toolchain/check/testdata/impl/lookup/no_prelude/impl_forall.carbon +++ b/toolchain/check/testdata/impl/lookup/no_prelude/impl_forall.carbon @@ -8,7 +8,7 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/lookup/no_prelude/impl_forall.carbon -// --- fail_todo_impl_forall.carbon +// --- impl_forall.carbon class A(T:! type) { var n: T; @@ -25,21 +25,14 @@ impl forall [V:! type] A(V) as I(V) { } fn TestGeneric[W:! type](a: A(W)) -> W { - // CHECK:STDERR: fail_todo_impl_forall.carbon:[[@LINE+4]]:10: error: cannot access member of interface `I` in type `A` that does not implement that interface - // CHECK:STDERR: return a.(I(W).F)(); - // CHECK:STDERR: ^~~~~~~~~~ - // CHECK:STDERR: return a.(I(W).F)(); } fn TestSpecific(a: A({})) -> {} { - // CHECK:STDERR: fail_todo_impl_forall.carbon:[[@LINE+3]]:10: error: cannot access member of interface `I` in type `A` that does not implement that interface - // CHECK:STDERR: return a.(I({}).F)(); - // CHECK:STDERR: ^~~~~~~~~~~ return a.(I({}).F)(); } -// CHECK:STDOUT: --- fail_todo_impl_forall.carbon +// CHECK:STDOUT: --- impl_forall.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] @@ -86,20 +79,27 @@ fn TestSpecific(a: A({})) -> {} { // CHECK:STDOUT: %F.4: %F.type.4 = struct_value () [symbolic] // CHECK:STDOUT: %.18: type = assoc_entity_type %I.type.4, %F.type.4 [symbolic] // CHECK:STDOUT: %.19: %.18 = assoc_entity element0, @I.%F.decl [symbolic] -// CHECK:STDOUT: %.20: type = struct_type {} [template] -// CHECK:STDOUT: %A.5: type = class_type @A, @A(%.20) [template] +// CHECK:STDOUT: %F.type.5: type = fn_type @F.2, @impl(%W) [symbolic] +// CHECK:STDOUT: %F.5: %F.type.5 = struct_value () [symbolic] +// CHECK:STDOUT: %.20: = interface_witness (%F.5) [symbolic] +// CHECK:STDOUT: %.21: type = struct_type {} [template] +// CHECK:STDOUT: %A.5: type = class_type @A, @A(%.21) [template] // CHECK:STDOUT: %TestSpecific.type: type = fn_type @TestSpecific [template] // CHECK:STDOUT: %TestSpecific: %TestSpecific.type = struct_value () [template] -// CHECK:STDOUT: %.21: type = unbound_element_type %A.5, %.20 [template] -// CHECK:STDOUT: %.22: type = struct_type {.n: %.20} [template] -// CHECK:STDOUT: %.23: = complete_type_witness %.22 [template] -// CHECK:STDOUT: %.24: type = struct_type {.n: %.1} [template] -// CHECK:STDOUT: %.25: type = ptr_type %.22 [template] -// CHECK:STDOUT: %I.type.5: type = interface_type @I, @I(%.20) [template] -// CHECK:STDOUT: %F.type.5: type = fn_type @F.1, @I(%.20) [template] -// CHECK:STDOUT: %F.5: %F.type.5 = struct_value () [template] -// CHECK:STDOUT: %.26: type = assoc_entity_type %I.type.5, %F.type.5 [template] -// CHECK:STDOUT: %.27: %.26 = assoc_entity element0, @I.%F.decl [template] +// CHECK:STDOUT: %.22: type = unbound_element_type %A.5, %.21 [template] +// CHECK:STDOUT: %.23: type = struct_type {.n: %.21} [template] +// CHECK:STDOUT: %.24: = complete_type_witness %.23 [template] +// CHECK:STDOUT: %.25: type = struct_type {.n: %.1} [template] +// CHECK:STDOUT: %.26: type = ptr_type %.23 [template] +// CHECK:STDOUT: %I.type.5: type = interface_type @I, @I(%.21) [template] +// CHECK:STDOUT: %F.type.6: type = fn_type @F.1, @I(%.21) [template] +// CHECK:STDOUT: %F.6: %F.type.6 = struct_value () [template] +// CHECK:STDOUT: %.27: type = assoc_entity_type %I.type.5, %F.type.6 [template] +// CHECK:STDOUT: %.28: %.27 = assoc_entity element0, @I.%F.decl [template] +// CHECK:STDOUT: %F.type.7: type = fn_type @F.2, @impl(%.21) [template] +// CHECK:STDOUT: %F.7: %F.type.7 = struct_value () [template] +// CHECK:STDOUT: %.29: = interface_witness (%F.7) [template] +// CHECK:STDOUT: %struct: %.21 = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -151,14 +151,14 @@ fn TestSpecific(a: A({})) -> {} { // CHECK:STDOUT: %a.patt: %A.5 = binding_pattern a // CHECK:STDOUT: } { // CHECK:STDOUT: %A.ref: %A.type = name_ref A, file.%A.decl [template = constants.%A.1] -// CHECK:STDOUT: %.loc24_23: %.20 = struct_literal () -// CHECK:STDOUT: %.loc24_21: type = converted %.loc24_23, constants.%.20 [template = constants.%.20] -// CHECK:STDOUT: %A: type = class_type @A, @A(constants.%.20) [template = constants.%A.5] +// CHECK:STDOUT: %.loc20_23: %.21 = struct_literal () +// CHECK:STDOUT: %.loc20_21: type = converted %.loc20_23, constants.%.21 [template = constants.%.21] +// CHECK:STDOUT: %A: type = class_type @A, @A(constants.%.21) [template = constants.%A.5] // CHECK:STDOUT: %a.param: %A.5 = param a, runtime_param0 // CHECK:STDOUT: %a: %A.5 = bind_name a, %a.param -// CHECK:STDOUT: %.loc24_31.1: %.20 = struct_literal () -// CHECK:STDOUT: %.loc24_31.2: type = converted %.loc24_31.1, constants.%.20 [template = constants.%.20] -// CHECK:STDOUT: %return: ref %.20 = var +// CHECK:STDOUT: %.loc20_31.1: %.21 = struct_literal () +// CHECK:STDOUT: %.loc20_31.2: type = converted %.loc20_31.1, constants.%.21 [template = constants.%.21] +// CHECK:STDOUT: %return: ref %.21 = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -275,32 +275,46 @@ fn TestSpecific(a: A({})) -> {} { // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: %I.type.1: type = interface_type @I, @I(%W.1) [symbolic = %I.type.1 (constants.%I.type.4)] -// CHECK:STDOUT: %F.type: type = fn_type @F.1, @I(%W.1) [symbolic = %F.type (constants.%F.type.4)] -// CHECK:STDOUT: %.1: type = assoc_entity_type @TestGeneric.%I.type.1 (%I.type.4), @TestGeneric.%F.type (%F.type.4) [symbolic = %.1 (constants.%.18)] +// CHECK:STDOUT: %F.type.1: type = fn_type @F.1, @I(%W.1) [symbolic = %F.type.1 (constants.%F.type.4)] +// CHECK:STDOUT: %.1: type = assoc_entity_type @TestGeneric.%I.type.1 (%I.type.4), @TestGeneric.%F.type.1 (%F.type.4) [symbolic = %.1 (constants.%.18)] // CHECK:STDOUT: %.2: @TestGeneric.%.1 (%.18) = assoc_entity element0, @I.%F.decl [symbolic = %.2 (constants.%.19)] +// CHECK:STDOUT: %F.type.2: type = fn_type @F.2, @impl(%W.1) [symbolic = %F.type.2 (constants.%F.type.5)] +// CHECK:STDOUT: %F: @TestGeneric.%F.type.2 (%F.type.5) = struct_value () [symbolic = %F (constants.%F.5)] // CHECK:STDOUT: // CHECK:STDOUT: fn[%W.loc16: type](%a: @TestGeneric.%A.1 (%A.4)) -> @TestGeneric.%W.1 (%W) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %a.ref: @TestGeneric.%A.1 (%A.4) = name_ref a, %a // CHECK:STDOUT: %I.ref: %I.type.1 = name_ref I, file.%I.decl [template = constants.%I] -// CHECK:STDOUT: %W.ref.loc21: type = name_ref W, %W.loc16 [symbolic = %W.1 (constants.%W)] -// CHECK:STDOUT: %I.type.loc21: type = interface_type @I, @I(constants.%W) [symbolic = %I.type.1 (constants.%I.type.4)] -// CHECK:STDOUT: %.loc21: @TestGeneric.%.1 (%.18) = specific_constant @I.%.loc7, @I(constants.%W) [symbolic = %.2 (constants.%.19)] -// CHECK:STDOUT: %F.ref: @TestGeneric.%.1 (%.18) = name_ref F, %.loc21 [symbolic = %.2 (constants.%.19)] -// CHECK:STDOUT: return +// CHECK:STDOUT: %W.ref.loc17: type = name_ref W, %W.loc16 [symbolic = %W.1 (constants.%W)] +// CHECK:STDOUT: %I.type.loc17: type = interface_type @I, @I(constants.%W) [symbolic = %I.type.1 (constants.%I.type.4)] +// CHECK:STDOUT: %.loc17_17: @TestGeneric.%.1 (%.18) = specific_constant @I.%.loc7, @I(constants.%W) [symbolic = %.2 (constants.%.19)] +// CHECK:STDOUT: %F.ref: @TestGeneric.%.1 (%.18) = name_ref F, %.loc17_17 [symbolic = %.2 (constants.%.19)] +// CHECK:STDOUT: %.loc17_11.1: @TestGeneric.%F.type.1 (%F.type.4) = interface_witness_access constants.%.20, element0 [symbolic = %F (constants.%F.5)] +// CHECK:STDOUT: %.loc17_11.2: = bound_method %a.ref, %.loc17_11.1 +// CHECK:STDOUT: %F.call: init @TestGeneric.%W.1 (%W) = call %.loc17_11.2(%a.ref) +// CHECK:STDOUT: %.loc17_22.1: @TestGeneric.%W.1 (%W) = value_of_initializer %F.call +// CHECK:STDOUT: %.loc17_22.2: @TestGeneric.%W.1 (%W) = converted %F.call, %.loc17_22.1 +// CHECK:STDOUT: return %.loc17_22.2 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @TestSpecific(%a: %A.5) -> %.20 { +// CHECK:STDOUT: fn @TestSpecific(%a: %A.5) -> %.21 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %a.ref: %A.5 = name_ref a, %a // CHECK:STDOUT: %I.ref: %I.type.1 = name_ref I, file.%I.decl [template = constants.%I] -// CHECK:STDOUT: %.loc28_16: %.20 = struct_literal () -// CHECK:STDOUT: %.loc28_14: type = converted %.loc28_16, constants.%.20 [template = constants.%.20] -// CHECK:STDOUT: %I.type: type = interface_type @I, @I(constants.%.20) [template = constants.%I.type.5] -// CHECK:STDOUT: %.loc28_18: %.26 = specific_constant @I.%.loc7, @I(constants.%.20) [template = constants.%.27] -// CHECK:STDOUT: %F.ref: %.26 = name_ref F, %.loc28_18 [template = constants.%.27] -// CHECK:STDOUT: return +// CHECK:STDOUT: %.loc21_16: %.21 = struct_literal () +// CHECK:STDOUT: %.loc21_14: type = converted %.loc21_16, constants.%.21 [template = constants.%.21] +// CHECK:STDOUT: %I.type: type = interface_type @I, @I(constants.%.21) [template = constants.%I.type.5] +// CHECK:STDOUT: %.loc21_18: %.27 = specific_constant @I.%.loc7, @I(constants.%.21) [template = constants.%.28] +// CHECK:STDOUT: %F.ref: %.27 = name_ref F, %.loc21_18 [template = constants.%.28] +// CHECK:STDOUT: %.loc21_11.1: %F.type.6 = interface_witness_access constants.%.29, element0 [template = constants.%F.7] +// CHECK:STDOUT: %.loc21_11.2: = bound_method %a.ref, %.loc21_11.1 +// CHECK:STDOUT: %F.call: init %.21 = call %.loc21_11.2(%a.ref) +// CHECK:STDOUT: %.loc21_21.1: ref %.21 = temporary_storage +// CHECK:STDOUT: %.loc21_21.2: ref %.21 = temporary %.loc21_21.1, %F.call +// CHECK:STDOUT: %struct: %.21 = struct_value () [template = constants.%struct] +// CHECK:STDOUT: %.loc21_23: %.21 = converted %F.call, %struct [template = constants.%struct] +// CHECK:STDOUT: return %.loc21_23 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @A(constants.%T) { @@ -422,29 +436,67 @@ fn TestSpecific(a: A({})) -> {} { // CHECK:STDOUT: %.2 => constants.%.19 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @impl(constants.%W) { +// CHECK:STDOUT: %V.1 => constants.%W +// CHECK:STDOUT: %A.1 => constants.%A.4 +// CHECK:STDOUT: %I.type.1 => constants.%I.type.4 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %F.type => constants.%F.type.5 +// CHECK:STDOUT: %F => constants.%F.5 +// CHECK:STDOUT: %.1 => constants.%.20 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.2(constants.%W) { +// CHECK:STDOUT: %V => constants.%W +// CHECK:STDOUT: %A => constants.%A.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @I(@TestGeneric.%W.1) { // CHECK:STDOUT: %U.1 => constants.%W // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @A(constants.%.20) { -// CHECK:STDOUT: %T.1 => constants.%.20 +// CHECK:STDOUT: specific @impl(@TestGeneric.%W.1) { +// CHECK:STDOUT: %V.1 => constants.%W +// CHECK:STDOUT: %A.1 => constants.%A.4 +// CHECK:STDOUT: %I.type.1 => constants.%I.type.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @A(constants.%.21) { +// CHECK:STDOUT: %T.1 => constants.%.21 // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: %A => constants.%A.5 -// CHECK:STDOUT: %.1 => constants.%.21 -// CHECK:STDOUT: %.2 => constants.%.22 -// CHECK:STDOUT: %.3 => constants.%.23 +// CHECK:STDOUT: %.1 => constants.%.22 +// CHECK:STDOUT: %.2 => constants.%.23 +// CHECK:STDOUT: %.3 => constants.%.24 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @I(constants.%.20) { -// CHECK:STDOUT: %U.1 => constants.%.20 +// CHECK:STDOUT: specific @I(constants.%.21) { +// CHECK:STDOUT: %U.1 => constants.%.21 // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: %I.type => constants.%I.type.5 // CHECK:STDOUT: %Self.2 => constants.%Self -// CHECK:STDOUT: %F.type => constants.%F.type.5 -// CHECK:STDOUT: %F => constants.%F.5 -// CHECK:STDOUT: %.1 => constants.%.26 -// CHECK:STDOUT: %.2 => constants.%.27 +// CHECK:STDOUT: %F.type => constants.%F.type.6 +// CHECK:STDOUT: %F => constants.%F.6 +// CHECK:STDOUT: %.1 => constants.%.27 +// CHECK:STDOUT: %.2 => constants.%.28 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl(constants.%.21) { +// CHECK:STDOUT: %V.1 => constants.%.21 +// CHECK:STDOUT: %A.1 => constants.%A.5 +// CHECK:STDOUT: %I.type.1 => constants.%I.type.5 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %F.type => constants.%F.type.7 +// CHECK:STDOUT: %F => constants.%F.7 +// CHECK:STDOUT: %.1 => constants.%.29 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.2(constants.%.21) { +// CHECK:STDOUT: %V => constants.%.21 +// CHECK:STDOUT: %A => constants.%A.5 // CHECK:STDOUT: } // CHECK:STDOUT: