Track and resolve the specific callee in a call to a generic function (#4395)

Add a new `specific_function` instruction that represents a generic
function plus its deduced argument list as a callee in a function call.
The new instruction can only appear as the immediate operand of a call
instruction, so we give it a builtin placeholder type.

At the end of each file, require definitions for all specific functions
used in that file. Resolve the generic with the argument list to produce
those specific function definitions as needed, and diagnose if the
generic doesn't have a definition available.

A few tests are updated in cases where they declared and used generic
functions but didn't previously provide a function definition.
This commit is contained in:
Richard Smith
2024-10-10 20:52:46 +00:00
committed by GitHub
parent bb874f21f7
commit 1a1bfd2eb2
35 changed files with 1761 additions and 528 deletions
+141 -62
View File
@@ -12,7 +12,7 @@
library "[[@TEST_NAME]]";
fn ExplicitGenericParam(T:! type) -> T*;
fn ExplicitGenericParam(T:! type) -> T* { return ExplicitGenericParam(T); }
fn CallExplicitGenericParam() -> i32* {
return ExplicitGenericParam(i32);
@@ -46,7 +46,7 @@ fn CallExplicitAndAlsoDeduced(n: i32) -> i32* {
library "[[@TEST_NAME]]";
fn ImplicitGenericParam[T:! type](x: T) -> T*;
fn ImplicitGenericParam[T:! type](x: T) -> T* { return ImplicitGenericParam(x); }
fn CallImplicitGenericParam(n: i32) -> i32* {
return ImplicitGenericParam(n);
@@ -56,7 +56,7 @@ fn CallImplicitGenericParam(n: i32) -> i32* {
library "[[@TEST_NAME]]";
fn TupleParam[T:! type](x: (T, i32));
fn TupleParam[T:! type](x: (T, i32)) {}
fn CallTupleParam() {
TupleParam((1, 2));
@@ -66,15 +66,15 @@ fn CallTupleParam() {
library "[[@TEST_NAME]]";
fn StructParam[T:! type](x: {.a: T, .b: i32});
fn StructParam[T:! type](x: {.a: T, .b: i32}) {}
fn CallStructParam() {
// CHECK:STDERR: fail_todo_deduce_nested_struct.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T`
// CHECK:STDERR: StructParam({.a = 1, .b = 2});
// CHECK:STDERR: ^~~~~~~~~~~~
// CHECK:STDERR: fail_todo_deduce_nested_struct.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here
// CHECK:STDERR: fn StructParam[T:! type](x: {.a: T, .b: i32});
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fn StructParam[T:! type](x: {.a: T, .b: i32}) {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
StructParam({.a = 1, .b = 2});
}
@@ -122,15 +122,18 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %ExplicitGenericParam.type: type = fn_type @ExplicitGenericParam [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %ExplicitGenericParam: %ExplicitGenericParam.type = struct_value () [template]
// CHECK:STDOUT: %.3: <specific function> = specific_function %ExplicitGenericParam, @ExplicitGenericParam(%T) [symbolic]
// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template]
// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template]
// CHECK:STDOUT: %.3: type = ptr_type i32 [template]
// CHECK:STDOUT: %.4: type = ptr_type i32 [template]
// CHECK:STDOUT: %CallExplicitGenericParam.type: type = fn_type @CallExplicitGenericParam [template]
// CHECK:STDOUT: %CallExplicitGenericParam: %CallExplicitGenericParam.type = struct_value () [template]
// CHECK:STDOUT: %.4: type = struct_type {.a: %T} [symbolic]
// CHECK:STDOUT: %.5: type = ptr_type %.4 [symbolic]
// CHECK:STDOUT: %.5: <specific function> = specific_function %ExplicitGenericParam, @ExplicitGenericParam(i32) [template]
// CHECK:STDOUT: %.6: type = struct_type {.a: %T} [symbolic]
// CHECK:STDOUT: %.7: type = ptr_type %.6 [symbolic]
// CHECK:STDOUT: %CallExplicitGenericParamWithGenericArg.type: type = fn_type @CallExplicitGenericParamWithGenericArg [template]
// CHECK:STDOUT: %CallExplicitGenericParamWithGenericArg: %CallExplicitGenericParamWithGenericArg.type = struct_value () [template]
// CHECK:STDOUT: %.8: <specific function> = specific_function %ExplicitGenericParam, @ExplicitGenericParam(%.6) [symbolic]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -161,7 +164,7 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: } {
// CHECK:STDOUT: %T.param: type = param T, runtime_param<invalid>
// CHECK:STDOUT: %T.loc4_25.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc4_25.2 (constants.%T)]
// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc4_25.1 [symbolic = %T.loc4_25.2 (constants.%T)]
// CHECK:STDOUT: %T.ref.loc4_38: type = name_ref T, %T.loc4_25.1 [symbolic = %T.loc4_25.2 (constants.%T)]
// CHECK:STDOUT: %.loc4_39.1: type = ptr_type %T [symbolic = %.loc4_39.2 (constants.%.1)]
// CHECK:STDOUT: %return: ref @ExplicitGenericParam.%.loc4_39.2 (%.1) = var <return slot>
// CHECK:STDOUT: }
@@ -169,8 +172,8 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %int.make_type_32.loc6: init type = call constants.%Int32() [template = i32]
// CHECK:STDOUT: %.loc6_37.1: type = value_of_initializer %int.make_type_32.loc6 [template = i32]
// CHECK:STDOUT: %.loc6_37.2: type = converted %int.make_type_32.loc6, %.loc6_37.1 [template = i32]
// CHECK:STDOUT: %.loc6_37.3: type = ptr_type i32 [template = constants.%.3]
// CHECK:STDOUT: %return: ref %.3 = var <return slot>
// CHECK:STDOUT: %.loc6_37.3: type = ptr_type i32 [template = constants.%.4]
// CHECK:STDOUT: %return: ref %.4 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %CallExplicitGenericParamWithGenericArg.decl: %CallExplicitGenericParamWithGenericArg.type = fn_decl @CallExplicitGenericParamWithGenericArg [template = constants.%CallExplicitGenericParamWithGenericArg] {
// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0
@@ -178,9 +181,9 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %T.param: type = param T, runtime_param<invalid>
// CHECK:STDOUT: %T.loc10_43.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc10_43.2 (constants.%T)]
// CHECK:STDOUT: %T.ref.loc10: type = name_ref T, %T.loc10_43.1 [symbolic = %T.loc10_43.2 (constants.%T)]
// CHECK:STDOUT: %.loc10_62.1: type = struct_type {.a: %T} [symbolic = %.loc10_62.2 (constants.%.4)]
// CHECK:STDOUT: %.loc10_63.1: type = ptr_type %.4 [symbolic = %.loc10_63.2 (constants.%.5)]
// CHECK:STDOUT: %return: ref @CallExplicitGenericParamWithGenericArg.%.loc10_63.2 (%.5) = var <return slot>
// CHECK:STDOUT: %.loc10_62.1: type = struct_type {.a: %T} [symbolic = %.loc10_62.2 (constants.%.6)]
// CHECK:STDOUT: %.loc10_63.1: type = ptr_type %.6 [symbolic = %.loc10_63.2 (constants.%.7)]
// CHECK:STDOUT: %return: ref @CallExplicitGenericParamWithGenericArg.%.loc10_63.2 (%.7) = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -188,38 +191,53 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %T.loc4_25.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_25.2 (constants.%T)]
// CHECK:STDOUT: %.loc4_39.2: type = ptr_type @ExplicitGenericParam.%T.loc4_25.2 (%T) [symbolic = %.loc4_39.2 (constants.%.1)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%T.loc4_25.1: type) -> @ExplicitGenericParam.%.loc4_39.2 (%.1);
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc4_50.2: <specific function> = specific_function constants.%ExplicitGenericParam, @ExplicitGenericParam(%T.loc4_25.2) [symbolic = %.loc4_50.2 (constants.%.3)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%T.loc4_25.1: type) -> @ExplicitGenericParam.%.loc4_39.2 (%.1) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %ExplicitGenericParam.ref: %ExplicitGenericParam.type = name_ref ExplicitGenericParam, file.%ExplicitGenericParam.decl [template = constants.%ExplicitGenericParam]
// CHECK:STDOUT: %T.ref.loc4_71: type = name_ref T, %T.loc4_25.1 [symbolic = %T.loc4_25.2 (constants.%T)]
// CHECK:STDOUT: %.loc4_50.1: <specific function> = specific_function %ExplicitGenericParam.ref, @ExplicitGenericParam(constants.%T) [symbolic = %.loc4_50.2 (constants.%.3)]
// CHECK:STDOUT: %ExplicitGenericParam.call: init @ExplicitGenericParam.%.loc4_39.2 (%.1) = call %.loc4_50.1()
// CHECK:STDOUT: %.loc4_73.1: @ExplicitGenericParam.%.loc4_39.2 (%.1) = value_of_initializer %ExplicitGenericParam.call
// CHECK:STDOUT: %.loc4_73.2: @ExplicitGenericParam.%.loc4_39.2 (%.1) = converted %ExplicitGenericParam.call, %.loc4_73.1
// CHECK:STDOUT: return %.loc4_73.2
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @CallExplicitGenericParam() -> %.3 {
// CHECK:STDOUT: fn @CallExplicitGenericParam() -> %.4 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %ExplicitGenericParam.ref: %ExplicitGenericParam.type = name_ref ExplicitGenericParam, file.%ExplicitGenericParam.decl [template = constants.%ExplicitGenericParam]
// CHECK:STDOUT: %int.make_type_32.loc7: init type = call constants.%Int32() [template = i32]
// CHECK:STDOUT: %.loc7_30.1: type = value_of_initializer %int.make_type_32.loc7 [template = i32]
// CHECK:STDOUT: %.loc7_30.2: type = converted %int.make_type_32.loc7, %.loc7_30.1 [template = i32]
// CHECK:STDOUT: %ExplicitGenericParam.call: init %.3 = call %ExplicitGenericParam.ref()
// CHECK:STDOUT: %.loc7_35.1: %.3 = value_of_initializer %ExplicitGenericParam.call
// CHECK:STDOUT: %.loc7_35.2: %.3 = converted %ExplicitGenericParam.call, %.loc7_35.1
// CHECK:STDOUT: %.loc7_10: <specific function> = specific_function %ExplicitGenericParam.ref, @ExplicitGenericParam(i32) [template = constants.%.5]
// CHECK:STDOUT: %ExplicitGenericParam.call: init %.4 = call %.loc7_10()
// CHECK:STDOUT: %.loc7_35.1: %.4 = value_of_initializer %ExplicitGenericParam.call
// CHECK:STDOUT: %.loc7_35.2: %.4 = converted %ExplicitGenericParam.call, %.loc7_35.1
// CHECK:STDOUT: return %.loc7_35.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @CallExplicitGenericParamWithGenericArg(%T.loc10_43.1: type) {
// CHECK:STDOUT: %T.loc10_43.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc10_43.2 (constants.%T)]
// CHECK:STDOUT: %.loc10_62.2: type = struct_type {.a: @CallExplicitGenericParamWithGenericArg.%T.loc10_43.2 (%T)} [symbolic = %.loc10_62.2 (constants.%.4)]
// CHECK:STDOUT: %.loc10_63.2: type = ptr_type @CallExplicitGenericParamWithGenericArg.%.loc10_62.2 (%.4) [symbolic = %.loc10_63.2 (constants.%.5)]
// CHECK:STDOUT: %.loc10_62.2: type = struct_type {.a: @CallExplicitGenericParamWithGenericArg.%T.loc10_43.2 (%T)} [symbolic = %.loc10_62.2 (constants.%.6)]
// CHECK:STDOUT: %.loc10_63.2: type = ptr_type @CallExplicitGenericParamWithGenericArg.%.loc10_62.2 (%.6) [symbolic = %.loc10_63.2 (constants.%.7)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc11_10.2: <specific function> = specific_function constants.%ExplicitGenericParam, @ExplicitGenericParam(%.loc10_62.2) [symbolic = %.loc11_10.2 (constants.%.8)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%T.loc10_43.1: type) -> @CallExplicitGenericParamWithGenericArg.%.loc10_63.2 (%.5) {
// CHECK:STDOUT: fn(%T.loc10_43.1: type) -> @CallExplicitGenericParamWithGenericArg.%.loc10_63.2 (%.7) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %ExplicitGenericParam.ref: %ExplicitGenericParam.type = name_ref ExplicitGenericParam, file.%ExplicitGenericParam.decl [template = constants.%ExplicitGenericParam]
// CHECK:STDOUT: %T.ref.loc11: type = name_ref T, %T.loc10_43.1 [symbolic = %T.loc10_43.2 (constants.%T)]
// CHECK:STDOUT: %.loc11_37: type = struct_type {.a: %T} [symbolic = %.loc10_62.2 (constants.%.4)]
// CHECK:STDOUT: %ExplicitGenericParam.call: init @CallExplicitGenericParamWithGenericArg.%.loc10_63.2 (%.5) = call %ExplicitGenericParam.ref()
// CHECK:STDOUT: %.loc11_39.1: @CallExplicitGenericParamWithGenericArg.%.loc10_63.2 (%.5) = value_of_initializer %ExplicitGenericParam.call
// CHECK:STDOUT: %.loc11_39.2: @CallExplicitGenericParamWithGenericArg.%.loc10_63.2 (%.5) = converted %ExplicitGenericParam.call, %.loc11_39.1
// CHECK:STDOUT: %.loc11_37: type = struct_type {.a: %T} [symbolic = %.loc10_62.2 (constants.%.6)]
// CHECK:STDOUT: %.loc11_10.1: <specific function> = specific_function %ExplicitGenericParam.ref, @ExplicitGenericParam(constants.%.6) [symbolic = %.loc11_10.2 (constants.%.8)]
// CHECK:STDOUT: %ExplicitGenericParam.call: init @CallExplicitGenericParamWithGenericArg.%.loc10_63.2 (%.7) = call %.loc11_10.1()
// CHECK:STDOUT: %.loc11_39.1: @CallExplicitGenericParamWithGenericArg.%.loc10_63.2 (%.7) = value_of_initializer %ExplicitGenericParam.call
// CHECK:STDOUT: %.loc11_39.2: @CallExplicitGenericParamWithGenericArg.%.loc10_63.2 (%.7) = converted %ExplicitGenericParam.call, %.loc11_39.1
// CHECK:STDOUT: return %.loc11_39.2
// CHECK:STDOUT: }
// CHECK:STDOUT: }
@@ -227,22 +245,41 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: specific @ExplicitGenericParam(constants.%T) {
// CHECK:STDOUT: %T.loc4_25.2 => constants.%T
// CHECK:STDOUT: %.loc4_39.2 => constants.%.1
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc4_50.2 => constants.%.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @ExplicitGenericParam(@ExplicitGenericParam.%T.loc4_25.2) {
// CHECK:STDOUT: %T.loc4_25.2 => constants.%T
// CHECK:STDOUT: %.loc4_39.2 => constants.%.1
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @ExplicitGenericParam(i32) {
// CHECK:STDOUT: %T.loc4_25.2 => i32
// CHECK:STDOUT: %.loc4_39.2 => constants.%.3
// CHECK:STDOUT: %.loc4_39.2 => constants.%.4
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc4_50.2 => constants.%.5
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @CallExplicitGenericParamWithGenericArg(constants.%T) {
// CHECK:STDOUT: %T.loc10_43.2 => constants.%T
// CHECK:STDOUT: %.loc10_62.2 => constants.%.4
// CHECK:STDOUT: %.loc10_63.2 => constants.%.5
// CHECK:STDOUT: %.loc10_62.2 => constants.%.6
// CHECK:STDOUT: %.loc10_63.2 => constants.%.7
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @ExplicitGenericParam(constants.%.4) {
// CHECK:STDOUT: %T.loc4_25.2 => constants.%.4
// CHECK:STDOUT: %.loc4_39.2 => constants.%.5
// CHECK:STDOUT: specific @ExplicitGenericParam(constants.%.6) {
// CHECK:STDOUT: %T.loc4_25.2 => constants.%.6
// CHECK:STDOUT: %.loc4_39.2 => constants.%.7
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc4_50.2 => constants.%.8
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @ExplicitGenericParam(@CallExplicitGenericParamWithGenericArg.%.loc10_62.2) {
// CHECK:STDOUT: %T.loc4_25.2 => constants.%.6
// CHECK:STDOUT: %.loc4_39.2 => constants.%.7
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_explicit_vs_deduced.carbon
@@ -353,11 +390,13 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %ImplicitGenericParam.type: type = fn_type @ImplicitGenericParam [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %ImplicitGenericParam: %ImplicitGenericParam.type = struct_value () [template]
// CHECK:STDOUT: %.3: <specific function> = specific_function %ImplicitGenericParam, @ImplicitGenericParam(%T) [symbolic]
// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template]
// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template]
// CHECK:STDOUT: %.3: type = ptr_type i32 [template]
// CHECK:STDOUT: %.4: type = ptr_type i32 [template]
// CHECK:STDOUT: %CallImplicitGenericParam.type: type = fn_type @CallImplicitGenericParam [template]
// CHECK:STDOUT: %CallImplicitGenericParam: %CallImplicitGenericParam.type = struct_value () [template]
// CHECK:STDOUT: %.5: <specific function> = specific_function %ImplicitGenericParam, @ImplicitGenericParam(i32) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -406,8 +445,8 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %int.make_type_32.loc6_40: init type = call constants.%Int32() [template = i32]
// CHECK:STDOUT: %.loc6_43.1: type = value_of_initializer %int.make_type_32.loc6_40 [template = i32]
// CHECK:STDOUT: %.loc6_43.2: type = converted %int.make_type_32.loc6_40, %.loc6_43.1 [template = i32]
// CHECK:STDOUT: %.loc6_43.3: type = ptr_type i32 [template = constants.%.3]
// CHECK:STDOUT: %return: ref %.3 = var <return slot>
// CHECK:STDOUT: %.loc6_43.3: type = ptr_type i32 [template = constants.%.4]
// CHECK:STDOUT: %return: ref %.4 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -415,29 +454,53 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %T.loc4_25.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_25.2 (constants.%T)]
// CHECK:STDOUT: %.loc4_45.2: type = ptr_type @ImplicitGenericParam.%T.loc4_25.2 (%T) [symbolic = %.loc4_45.2 (constants.%.1)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%T.loc4_25.1: type](%x: @ImplicitGenericParam.%T.loc4_25.2 (%T)) -> @ImplicitGenericParam.%.loc4_45.2 (%.1);
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc4_56.2: <specific function> = specific_function constants.%ImplicitGenericParam, @ImplicitGenericParam(%T.loc4_25.2) [symbolic = %.loc4_56.2 (constants.%.3)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%T.loc4_25.1: type](%x: @ImplicitGenericParam.%T.loc4_25.2 (%T)) -> @ImplicitGenericParam.%.loc4_45.2 (%.1) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %ImplicitGenericParam.ref: %ImplicitGenericParam.type = name_ref ImplicitGenericParam, file.%ImplicitGenericParam.decl [template = constants.%ImplicitGenericParam]
// CHECK:STDOUT: %x.ref: @ImplicitGenericParam.%T.loc4_25.2 (%T) = name_ref x, %x
// CHECK:STDOUT: %.loc4_56.1: <specific function> = specific_function %ImplicitGenericParam.ref, @ImplicitGenericParam(constants.%T) [symbolic = %.loc4_56.2 (constants.%.3)]
// CHECK:STDOUT: %ImplicitGenericParam.call: init @ImplicitGenericParam.%.loc4_45.2 (%.1) = call %.loc4_56.1(%x.ref)
// CHECK:STDOUT: %.loc4_79.1: @ImplicitGenericParam.%.loc4_45.2 (%.1) = value_of_initializer %ImplicitGenericParam.call
// CHECK:STDOUT: %.loc4_79.2: @ImplicitGenericParam.%.loc4_45.2 (%.1) = converted %ImplicitGenericParam.call, %.loc4_79.1
// CHECK:STDOUT: return %.loc4_79.2
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @CallImplicitGenericParam(%n: i32) -> %.3 {
// CHECK:STDOUT: fn @CallImplicitGenericParam(%n: i32) -> %.4 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %ImplicitGenericParam.ref: %ImplicitGenericParam.type = name_ref ImplicitGenericParam, file.%ImplicitGenericParam.decl [template = constants.%ImplicitGenericParam]
// CHECK:STDOUT: %n.ref: i32 = name_ref n, %n
// CHECK:STDOUT: %ImplicitGenericParam.call: init %.3 = call %ImplicitGenericParam.ref(%n.ref)
// CHECK:STDOUT: %.loc7_33.1: %.3 = value_of_initializer %ImplicitGenericParam.call
// CHECK:STDOUT: %.loc7_33.2: %.3 = converted %ImplicitGenericParam.call, %.loc7_33.1
// CHECK:STDOUT: %.loc7_10: <specific function> = specific_function %ImplicitGenericParam.ref, @ImplicitGenericParam(i32) [template = constants.%.5]
// CHECK:STDOUT: %ImplicitGenericParam.call: init %.4 = call %.loc7_10(%n.ref)
// CHECK:STDOUT: %.loc7_33.1: %.4 = value_of_initializer %ImplicitGenericParam.call
// CHECK:STDOUT: %.loc7_33.2: %.4 = converted %ImplicitGenericParam.call, %.loc7_33.1
// CHECK:STDOUT: return %.loc7_33.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @ImplicitGenericParam(constants.%T) {
// CHECK:STDOUT: %T.loc4_25.2 => constants.%T
// CHECK:STDOUT: %.loc4_45.2 => constants.%.1
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc4_56.2 => constants.%.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @ImplicitGenericParam(@ImplicitGenericParam.%T.loc4_25.2) {
// CHECK:STDOUT: %T.loc4_25.2 => constants.%T
// CHECK:STDOUT: %.loc4_45.2 => constants.%.1
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @ImplicitGenericParam(i32) {
// CHECK:STDOUT: %T.loc4_25.2 => i32
// CHECK:STDOUT: %.loc4_45.2 => constants.%.3
// CHECK:STDOUT: %.loc4_45.2 => constants.%.4
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc4_56.2 => constants.%.5
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- deduce_nested_tuple.carbon
@@ -451,13 +514,15 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %.3: type = tuple_type (%T, i32) [symbolic]
// CHECK:STDOUT: %TupleParam.type: type = fn_type @TupleParam [template]
// CHECK:STDOUT: %TupleParam: %TupleParam.type = struct_value () [template]
// CHECK:STDOUT: %.4: type = ptr_type %.3 [symbolic]
// CHECK:STDOUT: %CallTupleParam.type: type = fn_type @CallTupleParam [template]
// CHECK:STDOUT: %CallTupleParam: %CallTupleParam.type = struct_value () [template]
// 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 = ptr_type %.6 [template]
// CHECK:STDOUT: %tuple: %.6 = tuple_value (%.4, %.5) [template]
// CHECK:STDOUT: %.5: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.6: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.7: type = tuple_type (i32, i32) [template]
// CHECK:STDOUT: %.8: <specific function> = specific_function %TupleParam, @TupleParam(i32) [template]
// CHECK:STDOUT: %.9: type = ptr_type %.7 [template]
// CHECK:STDOUT: %tuple: %.7 = tuple_value (%.5, %.6) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -506,18 +571,24 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %T.loc4_15.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_15.2 (constants.%T)]
// CHECK:STDOUT: %.loc4_35.5: type = tuple_type (@TupleParam.%T.loc4_15.2 (%T), i32) [symbolic = %.loc4_35.5 (constants.%.3)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%T.loc4_15.1: type](%x: @TupleParam.%.loc4_35.5 (%.3));
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%T.loc4_15.1: type](%x: @TupleParam.%.loc4_35.5 (%.3)) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @CallTupleParam() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %TupleParam.ref: %TupleParam.type = name_ref TupleParam, file.%TupleParam.decl [template = constants.%TupleParam]
// 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: %.loc7_15: i32 = int_literal 1 [template = constants.%.5]
// CHECK:STDOUT: %.loc7_18: i32 = int_literal 2 [template = constants.%.6]
// CHECK:STDOUT: %.loc7_19: %.7 = tuple_literal (%.loc7_15, %.loc7_18)
// CHECK:STDOUT: %.loc7_3: <specific function> = specific_function %TupleParam.ref, @TupleParam(i32) [template = constants.%.8]
// CHECK:STDOUT: %tuple: %.7 = tuple_value (%.loc7_15, %.loc7_18) [template = constants.%tuple]
// CHECK:STDOUT: %.loc7_13: %.7 = converted %.loc7_19, %tuple [template = constants.%tuple]
// CHECK:STDOUT: %TupleParam.call: init %.1 = call %.loc7_3(%.loc7_13)
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -528,7 +599,9 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT:
// CHECK:STDOUT: specific @TupleParam(i32) {
// CHECK:STDOUT: %T.loc4_15.2 => i32
// CHECK:STDOUT: %.loc4_35.5 => constants.%.6
// CHECK:STDOUT: %.loc4_35.5 => constants.%.7
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_deduce_nested_struct.carbon
@@ -541,11 +614,12 @@ fn CallImplicitNotDeducible() {
// 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: %.3: type = ptr_type %.2 [symbolic]
// 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: %.4: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.5: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.6: type = struct_type {.a: i32, .b: i32} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -593,15 +667,20 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %T.loc4_16.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_16.2 (constants.%T)]
// CHECK:STDOUT: %.loc4_44.2: type = struct_type {.a: @StructParam.%T.loc4_16.2 (%T), .b: i32} [symbolic = %.loc4_44.2 (constants.%.2)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%T.loc4_16.1: type](%x: @StructParam.%.loc4_44.2 (%.2));
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%T.loc4_16.1: type](%x: @StructParam.%.loc4_44.2 (%.2)) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// 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: %.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: %.loc14_21: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc14_29: i32 = int_literal 2 [template = constants.%.5]
// CHECK:STDOUT: %.loc14_30: %.6 = struct_literal (%.loc14_21, %.loc14_29)
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -61,15 +61,18 @@ fn CallSpecific(x: C) -> C {
// CHECK:STDOUT: %Function: %Function.type = struct_value () [template]
// CHECK:STDOUT: %CallGeneric.type: type = fn_type @CallGeneric [template]
// CHECK:STDOUT: %CallGeneric: %CallGeneric.type = struct_value () [template]
// CHECK:STDOUT: %.2: type = ptr_type %T [symbolic]
// CHECK:STDOUT: %.2: <specific function> = specific_function %Function, @Function(%T) [symbolic]
// CHECK:STDOUT: %.3: type = ptr_type %T [symbolic]
// CHECK:STDOUT: %CallGenericPtr.type: type = fn_type @CallGenericPtr [template]
// CHECK:STDOUT: %CallGenericPtr: %CallGenericPtr.type = struct_value () [template]
// CHECK:STDOUT: %.4: <specific function> = specific_function %Function, @Function(%.3) [symbolic]
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.3: type = struct_type {} [template]
// CHECK:STDOUT: %.4: <witness> = complete_type_witness %.3 [template]
// CHECK:STDOUT: %.5: type = struct_type {} [template]
// CHECK:STDOUT: %.6: <witness> = complete_type_witness %.5 [template]
// CHECK:STDOUT: %CallSpecific.type: type = fn_type @CallSpecific [template]
// CHECK:STDOUT: %CallSpecific: %CallSpecific.type = struct_value () [template]
// CHECK:STDOUT: %.5: type = ptr_type %.3 [template]
// CHECK:STDOUT: %.7: type = ptr_type %.5 [template]
// CHECK:STDOUT: %.8: <specific function> = specific_function %Function, @Function(%C) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
@@ -106,17 +109,17 @@ fn CallSpecific(x: C) -> C {
// CHECK:STDOUT: }
// CHECK:STDOUT: %CallGenericPtr.decl: %CallGenericPtr.type = fn_decl @CallGenericPtr [template = constants.%CallGenericPtr] {
// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0
// CHECK:STDOUT: %x.patt: @CallGenericPtr.%.loc12_33.2 (%.2) = binding_pattern x
// CHECK:STDOUT: %x.patt: @CallGenericPtr.%.loc12_33.2 (%.3) = binding_pattern x
// CHECK:STDOUT: } {
// CHECK:STDOUT: %T.param: type = param T, runtime_param<invalid>
// CHECK:STDOUT: %T.loc12_19.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc12_19.2 (constants.%T)]
// CHECK:STDOUT: %T.ref.loc12_32: type = name_ref T, %T.loc12_19.1 [symbolic = %T.loc12_19.2 (constants.%T)]
// CHECK:STDOUT: %.loc12_33.1: type = ptr_type %T [symbolic = %.loc12_33.2 (constants.%.2)]
// CHECK:STDOUT: %x.param: @CallGenericPtr.%.loc12_33.2 (%.2) = param x, runtime_param0
// CHECK:STDOUT: %x: @CallGenericPtr.%.loc12_33.2 (%.2) = bind_name x, %x.param
// CHECK:STDOUT: %.loc12_33.1: type = ptr_type %T [symbolic = %.loc12_33.2 (constants.%.3)]
// CHECK:STDOUT: %x.param: @CallGenericPtr.%.loc12_33.2 (%.3) = param x, runtime_param0
// CHECK:STDOUT: %x: @CallGenericPtr.%.loc12_33.2 (%.3) = bind_name x, %x.param
// CHECK:STDOUT: %T.ref.loc12_39: type = name_ref T, %T.loc12_19.1 [symbolic = %T.loc12_19.2 (constants.%T)]
// CHECK:STDOUT: %.loc12_40: type = ptr_type %T [symbolic = %.loc12_33.2 (constants.%.2)]
// CHECK:STDOUT: %return: ref @CallGenericPtr.%.loc12_33.2 (%.2) = var <return slot>
// CHECK:STDOUT: %.loc12_40: type = ptr_type %T [symbolic = %.loc12_33.2 (constants.%.3)]
// CHECK:STDOUT: %return: ref @CallGenericPtr.%.loc12_33.2 (%.3) = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {}
// CHECK:STDOUT: %CallSpecific.decl: %CallSpecific.type = fn_decl @CallSpecific [template = constants.%CallSpecific] {
@@ -131,7 +134,7 @@ fn CallSpecific(x: C) -> C {
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: %.loc16: <witness> = complete_type_witness %.3 [template = constants.%.4]
// CHECK:STDOUT: %.loc16: <witness> = complete_type_witness %.5 [template = constants.%.6]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%C
@@ -153,13 +156,15 @@ fn CallSpecific(x: C) -> C {
// CHECK:STDOUT: %T.loc8_16.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc8_16.2 (constants.%T)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc9_10.2: <specific function> = specific_function constants.%Function, @Function(%T.loc8_16.2) [symbolic = %.loc9_10.2 (constants.%.2)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%T.loc8_16.1: type, %x: @CallGeneric.%T.loc8_16.2 (%T)) -> @CallGeneric.%T.loc8_16.2 (%T) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Function.ref: %Function.type = name_ref Function, file.%Function.decl [template = constants.%Function]
// CHECK:STDOUT: %T.ref.loc9: type = name_ref T, %T.loc8_16.1 [symbolic = %T.loc8_16.2 (constants.%T)]
// CHECK:STDOUT: %x.ref: @CallGeneric.%T.loc8_16.2 (%T) = name_ref x, %x
// CHECK:STDOUT: %Function.call: init @CallGeneric.%T.loc8_16.2 (%T) = call %Function.ref(%x.ref)
// CHECK:STDOUT: %.loc9_10.1: <specific function> = specific_function %Function.ref, @Function(constants.%T) [symbolic = %.loc9_10.2 (constants.%.2)]
// CHECK:STDOUT: %Function.call: init @CallGeneric.%T.loc8_16.2 (%T) = call %.loc9_10.1(%x.ref)
// CHECK:STDOUT: %.loc9_24.1: @CallGeneric.%T.loc8_16.2 (%T) = value_of_initializer %Function.call
// CHECK:STDOUT: %.loc9_24.2: @CallGeneric.%T.loc8_16.2 (%T) = converted %Function.call, %.loc9_24.1
// CHECK:STDOUT: return %.loc9_24.2
@@ -168,19 +173,21 @@ fn CallSpecific(x: C) -> C {
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @CallGenericPtr(%T.loc12_19.1: type) {
// CHECK:STDOUT: %T.loc12_19.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc12_19.2 (constants.%T)]
// CHECK:STDOUT: %.loc12_33.2: type = ptr_type @CallGenericPtr.%T.loc12_19.2 (%T) [symbolic = %.loc12_33.2 (constants.%.2)]
// CHECK:STDOUT: %.loc12_33.2: type = ptr_type @CallGenericPtr.%T.loc12_19.2 (%T) [symbolic = %.loc12_33.2 (constants.%.3)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc13_10.2: <specific function> = specific_function constants.%Function, @Function(%.loc12_33.2) [symbolic = %.loc13_10.2 (constants.%.4)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%T.loc12_19.1: type, %x: @CallGenericPtr.%.loc12_33.2 (%.2)) -> @CallGenericPtr.%.loc12_33.2 (%.2) {
// CHECK:STDOUT: fn(%T.loc12_19.1: type, %x: @CallGenericPtr.%.loc12_33.2 (%.3)) -> @CallGenericPtr.%.loc12_33.2 (%.3) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Function.ref: %Function.type = name_ref Function, file.%Function.decl [template = constants.%Function]
// CHECK:STDOUT: %T.ref.loc13: type = name_ref T, %T.loc12_19.1 [symbolic = %T.loc12_19.2 (constants.%T)]
// CHECK:STDOUT: %.loc13_20: type = ptr_type %T [symbolic = %.loc12_33.2 (constants.%.2)]
// CHECK:STDOUT: %x.ref: @CallGenericPtr.%.loc12_33.2 (%.2) = name_ref x, %x
// CHECK:STDOUT: %Function.call: init @CallGenericPtr.%.loc12_33.2 (%.2) = call %Function.ref(%x.ref)
// CHECK:STDOUT: %.loc13_25.1: @CallGenericPtr.%.loc12_33.2 (%.2) = value_of_initializer %Function.call
// CHECK:STDOUT: %.loc13_25.2: @CallGenericPtr.%.loc12_33.2 (%.2) = converted %Function.call, %.loc13_25.1
// CHECK:STDOUT: %.loc13_20: type = ptr_type %T [symbolic = %.loc12_33.2 (constants.%.3)]
// CHECK:STDOUT: %x.ref: @CallGenericPtr.%.loc12_33.2 (%.3) = name_ref x, %x
// CHECK:STDOUT: %.loc13_10.1: <specific function> = specific_function %Function.ref, @Function(constants.%.3) [symbolic = %.loc13_10.2 (constants.%.4)]
// CHECK:STDOUT: %Function.call: init @CallGenericPtr.%.loc12_33.2 (%.3) = call %.loc13_10.1(%x.ref)
// CHECK:STDOUT: %.loc13_25.1: @CallGenericPtr.%.loc12_33.2 (%.3) = value_of_initializer %Function.call
// CHECK:STDOUT: %.loc13_25.2: @CallGenericPtr.%.loc12_33.2 (%.3) = converted %Function.call, %.loc13_25.1
// CHECK:STDOUT: return %.loc13_25.2
// CHECK:STDOUT: }
// CHECK:STDOUT: }
@@ -190,30 +197,45 @@ fn CallSpecific(x: C) -> C {
// CHECK:STDOUT: %Function.ref: %Function.type = name_ref Function, file.%Function.decl [template = constants.%Function]
// CHECK:STDOUT: %C.ref.loc19: type = name_ref C, file.%C.decl [template = constants.%C]
// CHECK:STDOUT: %x.ref: %C = name_ref x, %x
// CHECK:STDOUT: %.loc19: <specific function> = specific_function %Function.ref, @Function(constants.%C) [template = constants.%.8]
// CHECK:STDOUT: %.loc18: ref %C = splice_block %return {}
// CHECK:STDOUT: %Function.call: init %C = call %Function.ref(%x.ref) to %.loc18
// CHECK:STDOUT: %Function.call: init %C = call %.loc19(%x.ref) to %.loc18
// CHECK:STDOUT: return %Function.call to %return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Function(constants.%T) {
// CHECK:STDOUT: %T.loc4_13.2 => constants.%T
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @CallGeneric(constants.%T) {
// CHECK:STDOUT: %T.loc8_16.2 => constants.%T
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @CallGenericPtr(constants.%T) {
// CHECK:STDOUT: %T.loc12_19.2 => constants.%T
// CHECK:STDOUT: %.loc12_33.2 => constants.%.2
// CHECK:STDOUT: specific @Function(@CallGeneric.%T.loc8_16.2) {
// CHECK:STDOUT: %T.loc4_13.2 => constants.%T
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Function(constants.%.2) {
// CHECK:STDOUT: %T.loc4_13.2 => constants.%.2
// CHECK:STDOUT: specific @CallGenericPtr(constants.%T) {
// CHECK:STDOUT: %T.loc12_19.2 => constants.%T
// CHECK:STDOUT: %.loc12_33.2 => constants.%.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Function(constants.%.3) {
// CHECK:STDOUT: %T.loc4_13.2 => constants.%.3
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Function(@CallGenericPtr.%.loc12_33.2) {
// CHECK:STDOUT: %T.loc4_13.2 => constants.%.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Function(constants.%C) {
// CHECK:STDOUT: %T.loc4_13.2 => constants.%C
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- deduced.carbon
@@ -225,15 +247,18 @@ fn CallSpecific(x: C) -> C {
// CHECK:STDOUT: %Function: %Function.type = struct_value () [template]
// CHECK:STDOUT: %CallGeneric.type: type = fn_type @CallGeneric [template]
// CHECK:STDOUT: %CallGeneric: %CallGeneric.type = struct_value () [template]
// CHECK:STDOUT: %.2: type = ptr_type %T [symbolic]
// CHECK:STDOUT: %.2: <specific function> = specific_function %Function, @Function(%T) [symbolic]
// CHECK:STDOUT: %.3: type = ptr_type %T [symbolic]
// CHECK:STDOUT: %CallGenericPtr.type: type = fn_type @CallGenericPtr [template]
// CHECK:STDOUT: %CallGenericPtr: %CallGenericPtr.type = struct_value () [template]
// CHECK:STDOUT: %.4: <specific function> = specific_function %Function, @Function(%.3) [symbolic]
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.3: type = struct_type {} [template]
// CHECK:STDOUT: %.4: <witness> = complete_type_witness %.3 [template]
// CHECK:STDOUT: %.5: type = struct_type {} [template]
// CHECK:STDOUT: %.6: <witness> = complete_type_witness %.5 [template]
// CHECK:STDOUT: %CallSpecific.type: type = fn_type @CallSpecific [template]
// CHECK:STDOUT: %CallSpecific: %CallSpecific.type = struct_value () [template]
// CHECK:STDOUT: %.5: type = ptr_type %.3 [template]
// CHECK:STDOUT: %.7: type = ptr_type %.5 [template]
// CHECK:STDOUT: %.8: <specific function> = specific_function %Function, @Function(%C) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
@@ -270,17 +295,17 @@ fn CallSpecific(x: C) -> C {
// CHECK:STDOUT: }
// CHECK:STDOUT: %CallGenericPtr.decl: %CallGenericPtr.type = fn_decl @CallGenericPtr [template = constants.%CallGenericPtr] {
// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0
// CHECK:STDOUT: %x.patt: @CallGenericPtr.%.loc12_33.2 (%.2) = binding_pattern x
// CHECK:STDOUT: %x.patt: @CallGenericPtr.%.loc12_33.2 (%.3) = binding_pattern x
// CHECK:STDOUT: } {
// CHECK:STDOUT: %T.param: type = param T, runtime_param<invalid>
// CHECK:STDOUT: %T.loc12_19.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc12_19.2 (constants.%T)]
// CHECK:STDOUT: %T.ref.loc12_32: type = name_ref T, %T.loc12_19.1 [symbolic = %T.loc12_19.2 (constants.%T)]
// CHECK:STDOUT: %.loc12_33.1: type = ptr_type %T [symbolic = %.loc12_33.2 (constants.%.2)]
// CHECK:STDOUT: %x.param: @CallGenericPtr.%.loc12_33.2 (%.2) = param x, runtime_param0
// CHECK:STDOUT: %x: @CallGenericPtr.%.loc12_33.2 (%.2) = bind_name x, %x.param
// CHECK:STDOUT: %.loc12_33.1: type = ptr_type %T [symbolic = %.loc12_33.2 (constants.%.3)]
// CHECK:STDOUT: %x.param: @CallGenericPtr.%.loc12_33.2 (%.3) = param x, runtime_param0
// CHECK:STDOUT: %x: @CallGenericPtr.%.loc12_33.2 (%.3) = bind_name x, %x.param
// CHECK:STDOUT: %T.ref.loc12_39: type = name_ref T, %T.loc12_19.1 [symbolic = %T.loc12_19.2 (constants.%T)]
// CHECK:STDOUT: %.loc12_40: type = ptr_type %T [symbolic = %.loc12_33.2 (constants.%.2)]
// CHECK:STDOUT: %return: ref @CallGenericPtr.%.loc12_33.2 (%.2) = var <return slot>
// CHECK:STDOUT: %.loc12_40: type = ptr_type %T [symbolic = %.loc12_33.2 (constants.%.3)]
// CHECK:STDOUT: %return: ref @CallGenericPtr.%.loc12_33.2 (%.3) = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {}
// CHECK:STDOUT: %CallSpecific.decl: %CallSpecific.type = fn_decl @CallSpecific [template = constants.%CallSpecific] {
@@ -295,7 +320,7 @@ fn CallSpecific(x: C) -> C {
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: %.loc16: <witness> = complete_type_witness %.3 [template = constants.%.4]
// CHECK:STDOUT: %.loc16: <witness> = complete_type_witness %.5 [template = constants.%.6]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%C
@@ -317,12 +342,14 @@ fn CallSpecific(x: C) -> C {
// CHECK:STDOUT: %T.loc8_16.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc8_16.2 (constants.%T)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc9_10.2: <specific function> = specific_function constants.%Function, @Function(%T.loc8_16.2) [symbolic = %.loc9_10.2 (constants.%.2)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%T.loc8_16.1: type, %x: @CallGeneric.%T.loc8_16.2 (%T)) -> @CallGeneric.%T.loc8_16.2 (%T) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Function.ref: %Function.type = name_ref Function, file.%Function.decl [template = constants.%Function]
// CHECK:STDOUT: %x.ref: @CallGeneric.%T.loc8_16.2 (%T) = name_ref x, %x
// CHECK:STDOUT: %Function.call: init @CallGeneric.%T.loc8_16.2 (%T) = call %Function.ref(%x.ref)
// CHECK:STDOUT: %.loc9_10.1: <specific function> = specific_function %Function.ref, @Function(constants.%T) [symbolic = %.loc9_10.2 (constants.%.2)]
// CHECK:STDOUT: %Function.call: init @CallGeneric.%T.loc8_16.2 (%T) = call %.loc9_10.1(%x.ref)
// CHECK:STDOUT: %.loc9_21.1: @CallGeneric.%T.loc8_16.2 (%T) = value_of_initializer %Function.call
// CHECK:STDOUT: %.loc9_21.2: @CallGeneric.%T.loc8_16.2 (%T) = converted %Function.call, %.loc9_21.1
// CHECK:STDOUT: return %.loc9_21.2
@@ -331,17 +358,19 @@ fn CallSpecific(x: C) -> C {
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @CallGenericPtr(%T.loc12_19.1: type) {
// CHECK:STDOUT: %T.loc12_19.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc12_19.2 (constants.%T)]
// CHECK:STDOUT: %.loc12_33.2: type = ptr_type @CallGenericPtr.%T.loc12_19.2 (%T) [symbolic = %.loc12_33.2 (constants.%.2)]
// CHECK:STDOUT: %.loc12_33.2: type = ptr_type @CallGenericPtr.%T.loc12_19.2 (%T) [symbolic = %.loc12_33.2 (constants.%.3)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc13_10.2: <specific function> = specific_function constants.%Function, @Function(%.loc12_33.2) [symbolic = %.loc13_10.2 (constants.%.4)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%T.loc12_19.1: type, %x: @CallGenericPtr.%.loc12_33.2 (%.2)) -> @CallGenericPtr.%.loc12_33.2 (%.2) {
// CHECK:STDOUT: fn(%T.loc12_19.1: type, %x: @CallGenericPtr.%.loc12_33.2 (%.3)) -> @CallGenericPtr.%.loc12_33.2 (%.3) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Function.ref: %Function.type = name_ref Function, file.%Function.decl [template = constants.%Function]
// CHECK:STDOUT: %x.ref: @CallGenericPtr.%.loc12_33.2 (%.2) = name_ref x, %x
// CHECK:STDOUT: %Function.call: init @CallGenericPtr.%.loc12_33.2 (%.2) = call %Function.ref(%x.ref)
// CHECK:STDOUT: %.loc13_21.1: @CallGenericPtr.%.loc12_33.2 (%.2) = value_of_initializer %Function.call
// CHECK:STDOUT: %.loc13_21.2: @CallGenericPtr.%.loc12_33.2 (%.2) = converted %Function.call, %.loc13_21.1
// CHECK:STDOUT: %x.ref: @CallGenericPtr.%.loc12_33.2 (%.3) = name_ref x, %x
// CHECK:STDOUT: %.loc13_10.1: <specific function> = specific_function %Function.ref, @Function(constants.%.3) [symbolic = %.loc13_10.2 (constants.%.4)]
// CHECK:STDOUT: %Function.call: init @CallGenericPtr.%.loc12_33.2 (%.3) = call %.loc13_10.1(%x.ref)
// CHECK:STDOUT: %.loc13_21.1: @CallGenericPtr.%.loc12_33.2 (%.3) = value_of_initializer %Function.call
// CHECK:STDOUT: %.loc13_21.2: @CallGenericPtr.%.loc12_33.2 (%.3) = converted %Function.call, %.loc13_21.1
// CHECK:STDOUT: return %.loc13_21.2
// CHECK:STDOUT: }
// CHECK:STDOUT: }
@@ -350,29 +379,44 @@ fn CallSpecific(x: C) -> C {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Function.ref: %Function.type = name_ref Function, file.%Function.decl [template = constants.%Function]
// CHECK:STDOUT: %x.ref: %C = name_ref x, %x
// CHECK:STDOUT: %.loc19: <specific function> = specific_function %Function.ref, @Function(constants.%C) [template = constants.%.8]
// CHECK:STDOUT: %.loc18: ref %C = splice_block %return {}
// CHECK:STDOUT: %Function.call: init %C = call %Function.ref(%x.ref) to %.loc18
// CHECK:STDOUT: %Function.call: init %C = call %.loc19(%x.ref) to %.loc18
// CHECK:STDOUT: return %Function.call to %return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Function(constants.%T) {
// CHECK:STDOUT: %T.loc4_13.2 => constants.%T
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @CallGeneric(constants.%T) {
// CHECK:STDOUT: %T.loc8_16.2 => constants.%T
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @CallGenericPtr(constants.%T) {
// CHECK:STDOUT: %T.loc12_19.2 => constants.%T
// CHECK:STDOUT: %.loc12_33.2 => constants.%.2
// CHECK:STDOUT: specific @Function(@CallGeneric.%T.loc8_16.2) {
// CHECK:STDOUT: %T.loc4_13.2 => constants.%T
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Function(constants.%.2) {
// CHECK:STDOUT: %T.loc4_13.2 => constants.%.2
// CHECK:STDOUT: specific @CallGenericPtr(constants.%T) {
// CHECK:STDOUT: %T.loc12_19.2 => constants.%T
// CHECK:STDOUT: %.loc12_33.2 => constants.%.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Function(constants.%.3) {
// CHECK:STDOUT: %T.loc4_13.2 => constants.%.3
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Function(@CallGenericPtr.%.loc12_33.2) {
// CHECK:STDOUT: %T.loc4_13.2 => constants.%.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Function(constants.%C) {
// CHECK:STDOUT: %T.loc4_13.2 => constants.%C
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: }
// CHECK:STDOUT:
+12 -1
View File
@@ -97,6 +97,7 @@ fn F(U:! type, T:! type) -> U* {
// CHECK:STDOUT: %F.type: type = fn_type @F [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %F: %F.type = struct_value () [template]
// CHECK:STDOUT: %.3: <specific function> = specific_function %F, @F(%T) [symbolic]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -143,12 +144,14 @@ fn F(U:! type, T:! type) -> U* {
// CHECK:STDOUT: %.loc4_20.2: type = ptr_type @F.%T.loc4_6.2 (%T) [symbolic = %.loc4_20.2 (constants.%.1)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc7_10.2: <specific function> = specific_function constants.%F, @F(%T.loc4_6.2) [symbolic = %.loc7_10.2 (constants.%.3)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%T.loc6: type) -> %.1 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl.loc4 [template = constants.%F]
// CHECK:STDOUT: %T.ref.loc7: type = name_ref T, %T.loc6 [symbolic = %T.loc4_6.2 (constants.%T)]
// CHECK:STDOUT: %F.call: init @F.%.loc4_20.2 (%.1) = call %F.ref()
// CHECK:STDOUT: %.loc7_10.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %.loc7_10.2 (constants.%.3)]
// CHECK:STDOUT: %F.call: init @F.%.loc4_20.2 (%.1) = call %.loc7_10.1()
// CHECK:STDOUT: %.loc7_14.1: @F.%.loc4_20.2 (%.1) = value_of_initializer %F.call
// CHECK:STDOUT: %.loc7_14.2: @F.%.loc4_20.2 (%.1) = converted %F.call, %.loc7_14.1
// CHECK:STDOUT: return %.loc7_14.2
@@ -158,6 +161,14 @@ fn F(U:! type, T:! type) -> U* {
// CHECK:STDOUT: specific @F(constants.%T) {
// CHECK:STDOUT: %T.loc4_6.2 => constants.%T
// CHECK:STDOUT: %.loc4_20.2 => constants.%.1
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc7_10.2 => constants.%.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @F(@F.%T.loc4_6.2) {
// CHECK:STDOUT: %T.loc4_6.2 => constants.%T
// CHECK:STDOUT: %.loc4_20.2 => constants.%.1
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_different_return_type.carbon
@@ -0,0 +1,127 @@
// 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/function/generic/resolve_used.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/resolve_used.carbon
// --- fail_call_monomorphization_error.carbon
library "[[@TEST_NAME]]";
fn ErrorIfNIsZero(N:! i32) {
// Check that we resolve the definition of a used specific function by
// ensuring we produce an error when doing so. Notionally this error is
// produced as a result of instantiating the `Core.Int` template, although
// that's not how we currently model `Core.Int`.
// CHECK:STDERR: fail_call_monomorphization_error.carbon:[[@LINE+3]]:10: error: integer type width of 0 is not positive
// CHECK:STDERR: var v: Core.Int(N);
// CHECK:STDERR: ^~~~~~~~~
var v: Core.Int(N);
}
fn CallNegative() {
ErrorIfNIsZero(0);
}
// CHECK:STDOUT: --- fail_call_monomorphization_error.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: %ErrorIfNIsZero.type: type = fn_type @ErrorIfNIsZero [template]
// CHECK:STDOUT: %ErrorIfNIsZero: %ErrorIfNIsZero.type = struct_value () [template]
// 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: %CallNegative.type: type = fn_type @CallNegative [template]
// CHECK:STDOUT: %CallNegative: %CallNegative.type = struct_value () [template]
// CHECK:STDOUT: %.3: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.4: <specific function> = specific_function %ErrorIfNIsZero, @ErrorIfNIsZero(%.3) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = 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> = namespace [template] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .ErrorIfNIsZero = %ErrorIfNIsZero.decl
// CHECK:STDOUT: .CallNegative = %CallNegative.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %ErrorIfNIsZero.decl: %ErrorIfNIsZero.type = fn_decl @ErrorIfNIsZero [template = constants.%ErrorIfNIsZero] {
// 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<invalid>
// CHECK:STDOUT: %N.loc4_19.1: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.loc4_19.2 (constants.%N)]
// CHECK:STDOUT: }
// CHECK:STDOUT: %CallNegative.decl: %CallNegative.type = fn_decl @CallNegative [template = constants.%CallNegative] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @ErrorIfNIsZero(%N.loc4_19.1: i32) {
// CHECK:STDOUT: %N.loc4_19.2: i32 = bind_symbolic_name N, 0 [symbolic = %N.loc4_19.2 (constants.%N)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc12_18: type = int_type signed, %N.loc4_19.2 [symbolic = %.loc12_18 (constants.%.2)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%N.loc4_19.1: i32) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Core.ref: <namespace> = 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: i32 = name_ref N, %N.loc4_19.1 [symbolic = %N.loc4_19.2 (constants.%N)]
// CHECK:STDOUT: %int.make_type_signed: init type = call %Int.ref(%N.ref) [symbolic = %.loc12_18 (constants.%.2)]
// CHECK:STDOUT: %.loc12_20.1: type = value_of_initializer %int.make_type_signed [symbolic = %.loc12_18 (constants.%.2)]
// CHECK:STDOUT: %.loc12_20.2: type = converted %int.make_type_signed, %.loc12_20.1 [symbolic = %.loc12_18 (constants.%.2)]
// CHECK:STDOUT: %v.var: ref @ErrorIfNIsZero.%.loc12_18 (%.2) = var v
// CHECK:STDOUT: %v: ref @ErrorIfNIsZero.%.loc12_18 (%.2) = bind_name v, %v.var
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Int(%size: i32) -> type = "int.make_type_signed";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @CallNegative() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %ErrorIfNIsZero.ref: %ErrorIfNIsZero.type = name_ref ErrorIfNIsZero, file.%ErrorIfNIsZero.decl [template = constants.%ErrorIfNIsZero]
// CHECK:STDOUT: %.loc16_18: i32 = int_literal 0 [template = constants.%.3]
// CHECK:STDOUT: %.loc16_3: <specific function> = specific_function %ErrorIfNIsZero.ref, @ErrorIfNIsZero(constants.%.3) [template = constants.%.4]
// CHECK:STDOUT: %ErrorIfNIsZero.call: init %.1 = call %.loc16_3()
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @ErrorIfNIsZero(constants.%N) {
// CHECK:STDOUT: %N.loc4_19.2 => constants.%N
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @ErrorIfNIsZero(constants.%.3) {
// CHECK:STDOUT: %N.loc4_19.2 => constants.%.3
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %.loc12_18 => <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
+77 -24
View File
@@ -9,7 +9,7 @@
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/return_slot.carbon
class Wrap(T:! type) {
fn Make() -> T;
fn Make() -> T { return Make(); }
}
class C { var arr: [i32; 100]; }
@@ -32,29 +32,33 @@ fn G() {
// CHECK:STDOUT: %Make.1: %Make.type.1 = struct_value () [symbolic]
// CHECK:STDOUT: %.2: type = struct_type {} [template]
// CHECK:STDOUT: %.3: <witness> = complete_type_witness %.2 [template]
// CHECK:STDOUT: %.4: <specific function> = specific_function %Make.1, @Make(%T) [symbolic]
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template]
// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template]
// CHECK:STDOUT: %.4: i32 = int_literal 100 [template]
// CHECK:STDOUT: %.5: type = array_type %.4, i32 [template]
// CHECK:STDOUT: %.6: type = ptr_type %.5 [template]
// CHECK:STDOUT: %.7: type = unbound_element_type %C, %.5 [template]
// CHECK:STDOUT: %.8: type = struct_type {.arr: %.5} [template]
// CHECK:STDOUT: %.9: <witness> = complete_type_witness %.8 [template]
// CHECK:STDOUT: %.5: i32 = int_literal 100 [template]
// CHECK:STDOUT: %.6: type = array_type %.5, i32 [template]
// CHECK:STDOUT: %.7: type = ptr_type %.6 [template]
// CHECK:STDOUT: %.8: type = unbound_element_type %C, %.6 [template]
// CHECK:STDOUT: %.9: type = struct_type {.arr: %.6} [template]
// CHECK:STDOUT: %.10: <witness> = complete_type_witness %.9 [template]
// CHECK:STDOUT: %G.type: type = fn_type @G [template]
// CHECK:STDOUT: %G: %G.type = struct_value () [template]
// CHECK:STDOUT: %Wrap.3: type = class_type @Wrap, @Wrap(i32) [template]
// CHECK:STDOUT: %Make.type.2: type = fn_type @Make, @Wrap(i32) [template]
// CHECK:STDOUT: %Make.2: %Make.type.2 = struct_value () [template]
// CHECK:STDOUT: %.10: type = ptr_type %.2 [template]
// CHECK:STDOUT: %.11: type = ptr_type %.2 [template]
// CHECK:STDOUT: %.12: <specific function> = specific_function %Make.2, @Make(i32) [template]
// CHECK:STDOUT: %Wrap.4: type = class_type @Wrap, @Wrap(%.1) [template]
// CHECK:STDOUT: %Make.type.3: type = fn_type @Make, @Wrap(%.1) [template]
// CHECK:STDOUT: %Make.3: %Make.type.3 = struct_value () [template]
// CHECK:STDOUT: %.11: type = struct_type {.arr: %.6} [template]
// CHECK:STDOUT: %.12: type = ptr_type %.8 [template]
// CHECK:STDOUT: %.13: <specific function> = specific_function %Make.3, @Make(%.1) [template]
// CHECK:STDOUT: %.14: type = struct_type {.arr: %.7} [template]
// CHECK:STDOUT: %.15: type = ptr_type %.9 [template]
// CHECK:STDOUT: %Wrap.5: type = class_type @Wrap, @Wrap(%C) [template]
// CHECK:STDOUT: %Make.type.4: type = fn_type @Make, @Wrap(%C) [template]
// CHECK:STDOUT: %Make.4: %Make.type.4 = struct_value () [template]
// CHECK:STDOUT: %.16: <specific function> = specific_function %Make.4, @Make(%C) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -112,12 +116,12 @@ fn G() {
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32]
// CHECK:STDOUT: %.loc15_26: i32 = int_literal 100 [template = constants.%.4]
// CHECK:STDOUT: %.loc15_26: i32 = int_literal 100 [template = constants.%.5]
// CHECK:STDOUT: %.loc15_21.1: type = value_of_initializer %int.make_type_32 [template = i32]
// CHECK:STDOUT: %.loc15_21.2: type = converted %int.make_type_32, %.loc15_21.1 [template = i32]
// CHECK:STDOUT: %.loc15_29: type = array_type %.loc15_26, i32 [template = constants.%.5]
// CHECK:STDOUT: %.loc15_18: %.7 = field_decl arr, element0 [template]
// CHECK:STDOUT: %.loc15_32: <witness> = complete_type_witness %.8 [template = constants.%.9]
// CHECK:STDOUT: %.loc15_29: type = array_type %.loc15_26, i32 [template = constants.%.6]
// CHECK:STDOUT: %.loc15_18: %.8 = field_decl arr, element0 [template]
// CHECK:STDOUT: %.loc15_32: <witness> = complete_type_witness %.9 [template = constants.%.10]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%C
@@ -127,7 +131,21 @@ fn G() {
// CHECK:STDOUT: generic fn @Make(@Wrap.%T.loc11_12.1: type) {
// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn() -> @Make.%T (%T);
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %Make.type: type = fn_type @Make, @Wrap(%T) [symbolic = %Make.type (constants.%Make.type.1)]
// CHECK:STDOUT: %Make: @Make.%Make.type (%Make.type.1) = struct_value () [symbolic = %Make (constants.%Make.1)]
// CHECK:STDOUT: %.loc12_27.3: <specific function> = specific_function %Make, @Make(%T) [symbolic = %.loc12_27.3 (constants.%.4)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn() -> @Make.%T (%T) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc12_27.1: @Make.%Make.type (%Make.type.1) = specific_constant @Wrap.%Make.decl, @Wrap(constants.%T) [symbolic = %Make (constants.%Make.1)]
// CHECK:STDOUT: %Make.ref: @Make.%Make.type (%Make.type.1) = name_ref Make, %.loc12_27.1 [symbolic = %Make (constants.%Make.1)]
// CHECK:STDOUT: %.loc12_27.2: <specific function> = specific_function %Make.ref, @Make(constants.%T) [symbolic = %.loc12_27.3 (constants.%.4)]
// CHECK:STDOUT: %Make.call: init @Make.%T (%T) = call %.loc12_27.2()
// CHECK:STDOUT: %.loc12_33.1: @Make.%T (%T) = value_of_initializer %Make.call
// CHECK:STDOUT: %.loc12_33.2: @Make.%T (%T) = converted %Make.call, %.loc12_33.1
// CHECK:STDOUT: return %.loc12_33.2
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
@@ -144,9 +162,10 @@ fn G() {
// CHECK:STDOUT: %.loc18_20.1: type = value_of_initializer %int.make_type_32.loc18_21 [template = i32]
// CHECK:STDOUT: %.loc18_20.2: type = converted %int.make_type_32.loc18_21, %.loc18_20.1 [template = i32]
// CHECK:STDOUT: %Wrap.loc18: type = class_type @Wrap, @Wrap(i32) [template = constants.%Wrap.3]
// CHECK:STDOUT: %.loc18_25: %Make.type.2 = specific_constant @Wrap.%Make.decl, @Wrap(i32) [template = constants.%Make.2]
// CHECK:STDOUT: %Make.ref.loc18: %Make.type.2 = name_ref Make, %.loc18_25 [template = constants.%Make.2]
// CHECK:STDOUT: %Make.call.loc18: init i32 = call %Make.ref.loc18()
// CHECK:STDOUT: %.loc18_25.1: %Make.type.2 = specific_constant @Wrap.%Make.decl, @Wrap(i32) [template = constants.%Make.2]
// CHECK:STDOUT: %Make.ref.loc18: %Make.type.2 = name_ref Make, %.loc18_25.1 [template = constants.%Make.2]
// CHECK:STDOUT: %.loc18_25.2: <specific function> = specific_function %Make.ref.loc18, @Make(i32) [template = constants.%.12]
// CHECK:STDOUT: %Make.call.loc18: init i32 = call %.loc18_25.2()
// CHECK:STDOUT: assign %a.var, %Make.call.loc18
// CHECK:STDOUT: %.loc19_11.1: %.1 = tuple_literal ()
// CHECK:STDOUT: %.loc19_11.2: type = converted %.loc19_11.1, constants.%.1 [template = constants.%.1]
@@ -156,9 +175,10 @@ fn G() {
// CHECK:STDOUT: %.loc19_21: %.1 = tuple_literal ()
// CHECK:STDOUT: %.loc19_19: type = converted %.loc19_21, constants.%.1 [template = constants.%.1]
// CHECK:STDOUT: %Wrap.loc19: type = class_type @Wrap, @Wrap(constants.%.1) [template = constants.%Wrap.4]
// CHECK:STDOUT: %.loc19_23: %Make.type.3 = specific_constant @Wrap.%Make.decl, @Wrap(constants.%.1) [template = constants.%Make.3]
// CHECK:STDOUT: %Make.ref.loc19: %Make.type.3 = name_ref Make, %.loc19_23 [template = constants.%Make.3]
// CHECK:STDOUT: %Make.call.loc19: init %.1 = call %Make.ref.loc19()
// CHECK:STDOUT: %.loc19_23.1: %Make.type.3 = specific_constant @Wrap.%Make.decl, @Wrap(constants.%.1) [template = constants.%Make.3]
// CHECK:STDOUT: %Make.ref.loc19: %Make.type.3 = name_ref Make, %.loc19_23.1 [template = constants.%Make.3]
// CHECK:STDOUT: %.loc19_23.2: <specific function> = specific_function %Make.ref.loc19, @Make(constants.%.1) [template = constants.%.13]
// CHECK:STDOUT: %Make.call.loc19: init %.1 = call %.loc19_23.2()
// CHECK:STDOUT: assign %b.var, %Make.call.loc19
// CHECK:STDOUT: %C.ref.loc20_10: type = name_ref C, file.%C.decl [template = constants.%C]
// CHECK:STDOUT: %c.var: ref %C = var c
@@ -166,26 +186,44 @@ fn G() {
// CHECK:STDOUT: %Wrap.ref.loc20: %Wrap.type = name_ref Wrap, file.%Wrap.decl [template = constants.%Wrap.1]
// CHECK:STDOUT: %C.ref.loc20_19: type = name_ref C, file.%C.decl [template = constants.%C]
// CHECK:STDOUT: %Wrap.loc20: type = class_type @Wrap, @Wrap(constants.%C) [template = constants.%Wrap.5]
// CHECK:STDOUT: %.loc20_21: %Make.type.4 = specific_constant @Wrap.%Make.decl, @Wrap(constants.%C) [template = constants.%Make.4]
// CHECK:STDOUT: %Make.ref.loc20: %Make.type.4 = name_ref Make, %.loc20_21 [template = constants.%Make.4]
// CHECK:STDOUT: %.loc20_21.1: %Make.type.4 = specific_constant @Wrap.%Make.decl, @Wrap(constants.%C) [template = constants.%Make.4]
// CHECK:STDOUT: %Make.ref.loc20: %Make.type.4 = name_ref Make, %.loc20_21.1 [template = constants.%Make.4]
// CHECK:STDOUT: %.loc20_21.2: <specific function> = specific_function %Make.ref.loc20, @Make(constants.%C) [template = constants.%.16]
// CHECK:STDOUT: %.loc20_7: ref %C = splice_block %c.var {}
// CHECK:STDOUT: %Make.call.loc20: init %C = call %Make.ref.loc20() to %.loc20_7
// CHECK:STDOUT: %Make.call.loc20: init %C = call %.loc20_21.2() to %.loc20_7
// CHECK:STDOUT: assign %c.var, %Make.call.loc20
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Wrap(constants.%T) {
// CHECK:STDOUT: %T.loc11_12.2 => constants.%T
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %Make.type => constants.%Make.type.1
// CHECK:STDOUT: %Make => constants.%Make.1
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Make(constants.%T) {
// CHECK:STDOUT: %T => constants.%T
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %Make.type => constants.%Make.type.1
// CHECK:STDOUT: %Make => constants.%Make.1
// CHECK:STDOUT: %.loc12_27.3 => constants.%.4
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Wrap(@Wrap.%T.loc11_12.2) {
// CHECK:STDOUT: %T.loc11_12.2 => constants.%T
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Wrap(@Make.%T) {
// CHECK:STDOUT: %T.loc11_12.2 => constants.%T
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Make(@Make.%T) {
// CHECK:STDOUT: %T => constants.%T
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Wrap(i32) {
// CHECK:STDOUT: %T.loc11_12.2 => i32
// CHECK:STDOUT:
@@ -196,6 +234,11 @@ fn G() {
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Make(i32) {
// CHECK:STDOUT: %T => i32
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %Make.type => constants.%Make.type.2
// CHECK:STDOUT: %Make => constants.%Make.2
// CHECK:STDOUT: %.loc12_27.3 => constants.%.12
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Wrap(constants.%.1) {
@@ -208,6 +251,11 @@ fn G() {
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Make(constants.%.1) {
// CHECK:STDOUT: %T => constants.%.1
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %Make.type => constants.%Make.type.3
// CHECK:STDOUT: %Make => constants.%Make.3
// CHECK:STDOUT: %.loc12_27.3 => constants.%.13
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Wrap(constants.%C) {
@@ -220,5 +268,10 @@ fn G() {
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Make(constants.%C) {
// CHECK:STDOUT: %T => constants.%C
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %Make.type => constants.%Make.type.4
// CHECK:STDOUT: %Make => constants.%Make.4
// CHECK:STDOUT: %.loc12_27.3 => constants.%.16
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -0,0 +1,332 @@
// 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/function/generic/undefined.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/undefined.carbon
// --- call_defined.carbon
library "[[@TEST_NAME]]";
fn Defined[T:! type](x: T) -> T {
return x;
}
fn CallDefined() -> i32 {
return Defined(0);
}
// --- call_defined_late.carbon
library "[[@TEST_NAME]]";
fn Defined[T:! type](x: T) -> T;
fn CallDefined() -> i32 {
return Defined(0);
}
fn Defined[T:! type](x: T) -> T {
return x;
}
// --- fail_call_undefined.carbon
library "[[@TEST_NAME]]";
fn Undefined[T:! type](x: T) -> T;
fn CallUndefined() -> i32 {
// CHECK:STDERR: fail_call_undefined.carbon:[[@LINE+6]]:10: error: use of undefined generic function
// CHECK:STDERR: return Undefined(0);
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_call_undefined.carbon:[[@LINE-6]]:1: note: generic function declared here
// CHECK:STDERR: fn Undefined[T:! type](x: T) -> T;
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return Undefined(0);
}
// CHECK:STDOUT: --- call_defined.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic]
// CHECK:STDOUT: %Defined.type: type = fn_type @Defined [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %Defined: %Defined.type = struct_value () [template]
// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template]
// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template]
// CHECK:STDOUT: %CallDefined.type: type = fn_type @CallDefined [template]
// CHECK:STDOUT: %CallDefined: %CallDefined.type = struct_value () [template]
// CHECK:STDOUT: %.2: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.3: <specific function> = specific_function %Defined, @Defined(i32) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = 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> = namespace [template] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .Defined = %Defined.decl
// CHECK:STDOUT: .CallDefined = %CallDefined.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %Defined.decl: %Defined.type = fn_decl @Defined [template = constants.%Defined] {
// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0
// CHECK:STDOUT: %x.patt: @Defined.%T.loc4_12.2 (%T) = binding_pattern x
// CHECK:STDOUT: } {
// CHECK:STDOUT: %T.param: type = param T, runtime_param<invalid>
// CHECK:STDOUT: %T.loc4_12.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc4_12.2 (constants.%T)]
// CHECK:STDOUT: %T.ref.loc4_25: type = name_ref T, %T.loc4_12.1 [symbolic = %T.loc4_12.2 (constants.%T)]
// CHECK:STDOUT: %x.param: @Defined.%T.loc4_12.2 (%T) = param x, runtime_param0
// CHECK:STDOUT: %x: @Defined.%T.loc4_12.2 (%T) = bind_name x, %x.param
// CHECK:STDOUT: %T.ref.loc4_31: type = name_ref T, %T.loc4_12.1 [symbolic = %T.loc4_12.2 (constants.%T)]
// CHECK:STDOUT: %return: ref @Defined.%T.loc4_12.2 (%T) = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %CallDefined.decl: %CallDefined.type = fn_decl @CallDefined [template = constants.%CallDefined] {} {
// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32]
// CHECK:STDOUT: %.loc8_21.1: type = value_of_initializer %int.make_type_32 [template = i32]
// CHECK:STDOUT: %.loc8_21.2: type = converted %int.make_type_32, %.loc8_21.1 [template = i32]
// CHECK:STDOUT: %return: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @Defined(%T.loc4_12.1: type) {
// CHECK:STDOUT: %T.loc4_12.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_12.2 (constants.%T)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%T.loc4_12.1: type](%x: @Defined.%T.loc4_12.2 (%T)) -> @Defined.%T.loc4_12.2 (%T) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %x.ref: @Defined.%T.loc4_12.2 (%T) = name_ref x, %x
// CHECK:STDOUT: return %x.ref
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @CallDefined() -> i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Defined.ref: %Defined.type = name_ref Defined, file.%Defined.decl [template = constants.%Defined]
// CHECK:STDOUT: %.loc9_18: i32 = int_literal 0 [template = constants.%.2]
// CHECK:STDOUT: %.loc9_10: <specific function> = specific_function %Defined.ref, @Defined(i32) [template = constants.%.3]
// CHECK:STDOUT: %Defined.call: init i32 = call %.loc9_10(%.loc9_18)
// CHECK:STDOUT: %.loc9_20.1: i32 = value_of_initializer %Defined.call
// CHECK:STDOUT: %.loc9_20.2: i32 = converted %Defined.call, %.loc9_20.1
// CHECK:STDOUT: return %.loc9_20.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Defined(constants.%T) {
// CHECK:STDOUT: %T.loc4_12.2 => constants.%T
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Defined(i32) {
// CHECK:STDOUT: %T.loc4_12.2 => i32
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- call_defined_late.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic]
// CHECK:STDOUT: %Defined.type: type = fn_type @Defined [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %Defined: %Defined.type = struct_value () [template]
// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template]
// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template]
// CHECK:STDOUT: %CallDefined.type: type = fn_type @CallDefined [template]
// CHECK:STDOUT: %CallDefined: %CallDefined.type = struct_value () [template]
// CHECK:STDOUT: %.2: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.3: <specific function> = specific_function %Defined, @Defined(i32) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = 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> = namespace [template] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .Defined = %Defined.decl.loc4
// CHECK:STDOUT: .CallDefined = %CallDefined.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %Defined.decl.loc4: %Defined.type = fn_decl @Defined [template = constants.%Defined] {
// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0
// CHECK:STDOUT: %x.patt: %T = binding_pattern x
// CHECK:STDOUT: } {
// CHECK:STDOUT: %T.param.loc4: type = param T, runtime_param<invalid>
// CHECK:STDOUT: %T.loc4_12.1: type = bind_symbolic_name T, 0, %T.param.loc4 [symbolic = %T.loc4_12.2 (constants.%T)]
// CHECK:STDOUT: %T.ref.loc4_25: type = name_ref T, %T.loc4_12.1 [symbolic = %T.loc4_12.2 (constants.%T)]
// CHECK:STDOUT: %x.param.loc4: @Defined.%T.loc4_12.2 (%T) = param x, runtime_param0
// CHECK:STDOUT: %x.loc4: @Defined.%T.loc4_12.2 (%T) = bind_name x, %x.param.loc4
// CHECK:STDOUT: %T.ref.loc4_31: type = name_ref T, %T.loc4_12.1 [symbolic = %T.loc4_12.2 (constants.%T)]
// CHECK:STDOUT: %return.var.loc4: ref @Defined.%T.loc4_12.2 (%T) = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %CallDefined.decl: %CallDefined.type = fn_decl @CallDefined [template = constants.%CallDefined] {} {
// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32]
// CHECK:STDOUT: %.loc6_21.1: type = value_of_initializer %int.make_type_32 [template = i32]
// CHECK:STDOUT: %.loc6_21.2: type = converted %int.make_type_32, %.loc6_21.1 [template = i32]
// CHECK:STDOUT: %return: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Defined.decl.loc10: %Defined.type = fn_decl @Defined [template = constants.%Defined] {
// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0
// CHECK:STDOUT: %x.patt: %T = binding_pattern x
// CHECK:STDOUT: } {
// CHECK:STDOUT: %T.param.loc10: type = param T, runtime_param<invalid>
// CHECK:STDOUT: %T.loc10: type = bind_symbolic_name T, 0, %T.param.loc10 [symbolic = constants.%T]
// CHECK:STDOUT: %T.ref.loc10_25: type = name_ref T, %T.loc10 [symbolic = constants.%T]
// CHECK:STDOUT: %x.param.loc10: %T = param x, runtime_param0
// CHECK:STDOUT: %x.loc10: %T = bind_name x, %x.param.loc10
// CHECK:STDOUT: %T.ref.loc10_31: type = name_ref T, %T.loc10 [symbolic = constants.%T]
// CHECK:STDOUT: %return: ref %T = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @Defined(%T.loc4_12.1: type) {
// CHECK:STDOUT: %T.loc4_12.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_12.2 (constants.%T)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%T.loc10: type](%x.loc10: %T) -> %T {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %x.ref: @Defined.%T.loc4_12.2 (%T) = name_ref x, %x.loc10
// CHECK:STDOUT: return %x.ref
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @CallDefined() -> i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Defined.ref: %Defined.type = name_ref Defined, file.%Defined.decl.loc4 [template = constants.%Defined]
// CHECK:STDOUT: %.loc7_18: i32 = int_literal 0 [template = constants.%.2]
// CHECK:STDOUT: %.loc7_10: <specific function> = specific_function %Defined.ref, @Defined(i32) [template = constants.%.3]
// CHECK:STDOUT: %Defined.call: init i32 = call %.loc7_10(%.loc7_18)
// CHECK:STDOUT: %.loc7_20.1: i32 = value_of_initializer %Defined.call
// CHECK:STDOUT: %.loc7_20.2: i32 = converted %Defined.call, %.loc7_20.1
// CHECK:STDOUT: return %.loc7_20.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Defined(constants.%T) {
// CHECK:STDOUT: %T.loc4_12.2 => constants.%T
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Defined(i32) {
// CHECK:STDOUT: %T.loc4_12.2 => i32
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_call_undefined.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic]
// CHECK:STDOUT: %Undefined.type: type = fn_type @Undefined [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %Undefined: %Undefined.type = struct_value () [template]
// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template]
// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template]
// CHECK:STDOUT: %CallUndefined.type: type = fn_type @CallUndefined [template]
// CHECK:STDOUT: %CallUndefined: %CallUndefined.type = struct_value () [template]
// CHECK:STDOUT: %.2: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.3: <specific function> = specific_function %Undefined, @Undefined(i32) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = 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> = namespace [template] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .Undefined = %Undefined.decl
// CHECK:STDOUT: .CallUndefined = %CallUndefined.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %Undefined.decl: %Undefined.type = fn_decl @Undefined [template = constants.%Undefined] {
// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0
// CHECK:STDOUT: %x.patt: @Undefined.%T.loc4_14.2 (%T) = binding_pattern x
// CHECK:STDOUT: } {
// CHECK:STDOUT: %T.param: type = param T, runtime_param<invalid>
// CHECK:STDOUT: %T.loc4_14.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc4_14.2 (constants.%T)]
// CHECK:STDOUT: %T.ref.loc4_27: type = name_ref T, %T.loc4_14.1 [symbolic = %T.loc4_14.2 (constants.%T)]
// CHECK:STDOUT: %x.param: @Undefined.%T.loc4_14.2 (%T) = param x, runtime_param0
// CHECK:STDOUT: %x: @Undefined.%T.loc4_14.2 (%T) = bind_name x, %x.param
// CHECK:STDOUT: %T.ref.loc4_33: type = name_ref T, %T.loc4_14.1 [symbolic = %T.loc4_14.2 (constants.%T)]
// CHECK:STDOUT: %return: ref @Undefined.%T.loc4_14.2 (%T) = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %CallUndefined.decl: %CallUndefined.type = fn_decl @CallUndefined [template = constants.%CallUndefined] {} {
// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32]
// CHECK:STDOUT: %.loc6_23.1: type = value_of_initializer %int.make_type_32 [template = i32]
// CHECK:STDOUT: %.loc6_23.2: type = converted %int.make_type_32, %.loc6_23.1 [template = i32]
// CHECK:STDOUT: %return: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @Undefined(%T.loc4_14.1: type) {
// CHECK:STDOUT: %T.loc4_14.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_14.2 (constants.%T)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%T.loc4_14.1: type](%x: @Undefined.%T.loc4_14.2 (%T)) -> @Undefined.%T.loc4_14.2 (%T);
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @CallUndefined() -> i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Undefined.ref: %Undefined.type = name_ref Undefined, file.%Undefined.decl [template = constants.%Undefined]
// CHECK:STDOUT: %.loc13_20: i32 = int_literal 0 [template = constants.%.2]
// CHECK:STDOUT: %.loc13_10: <specific function> = specific_function %Undefined.ref, @Undefined(i32) [template = constants.%.3]
// CHECK:STDOUT: %Undefined.call: init i32 = call %.loc13_10(%.loc13_20)
// CHECK:STDOUT: %.loc13_22.1: i32 = value_of_initializer %Undefined.call
// CHECK:STDOUT: %.loc13_22.2: i32 = converted %Undefined.call, %.loc13_22.1
// CHECK:STDOUT: return %.loc13_22.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Undefined(constants.%T) {
// CHECK:STDOUT: %T.loc4_14.2 => constants.%T
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Undefined(i32) {
// CHECK:STDOUT: %T.loc4_14.2 => i32
// CHECK:STDOUT: }
// CHECK:STDOUT: