mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 21:11:27 +01:00
A query facet type may contain multiple required interfaces, in which case impl lookup should return an ImplWitness for an impl that is used for each interface in the query. We bundle these together into an instruction block and return that from impl lookup. The witnesses are in the same order as the interfaces in the `CompleteFacetType::required_interfaces`. This allows walking the `required_interfaces` to find an interface to give an index that can also be used to grab a witness from this set, or from FacetValue. FacetValue now has an InstBlockId for the set of witnesses of the FacetType, instead of a single ImplWitness instruction id. FacetAccessWitness includes the index of the witness (determined from the position in `required_interfaces`) of the witness it's accessing from the FacetType. The toolchain/check/testdata/facet/no_prelude/fail_todo_call_combined_impl_witness.carbon test demonstrates the fix in the resulting SemIR. We can see the calls to methods on a multi-interface FacetType result in a FacetAccessWitness with an index of the correct interface, and this results in a witness that leads to the correct impl's function. There is a TODO in member access, where it does not have a `CompleteFacetType` yet, so it uses the index in `FacetTypeInfo::impls_constraints` instead, but this can be incorrect in the presence of named constraints, which when completed can add more interfaces to the `CompleteFacetType` and which are sorted into an arbitrary order with the rest there. --------- Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
375 lines
21 KiB
Plaintext
375 lines
21 KiB
Plaintext
// 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/if_expr/constant_condition.carbon
|
|
// TIP: To dump output, run:
|
|
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/if_expr/constant_condition.carbon
|
|
|
|
fn A() -> i32 { return 1; }
|
|
fn B() -> i32 { return 2; }
|
|
|
|
fn F() -> i32 {
|
|
return if true then A() else B();
|
|
}
|
|
|
|
fn G() -> i32 {
|
|
return if false then A() else B();
|
|
}
|
|
|
|
fn Constant() -> i32 {
|
|
var v: if true then i32 else i32* = 1;
|
|
var w: if false then i32 else i32* = &v;
|
|
return *w;
|
|
}
|
|
|
|
fn PartiallyConstant(t: type) -> i32 {
|
|
var v: if true then i32 else t = 1;
|
|
var w: if false then t else i32* = &v;
|
|
return *w;
|
|
}
|
|
|
|
// CHECK:STDOUT: --- constant_condition.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: constants {
|
|
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
|
|
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete]
|
|
// CHECK:STDOUT: %A.type: type = fn_type @A [concrete]
|
|
// CHECK:STDOUT: %A: %A.type = struct_value () [concrete]
|
|
// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]
|
|
// CHECK:STDOUT: %ImplicitAs.type.205: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]
|
|
// CHECK:STDOUT: %Convert.type.1b6: type = fn_type @Convert.1, @ImplicitAs(%i32) [concrete]
|
|
// CHECK:STDOUT: %impl_witness.d39: <witness> = impl_witness (imports.%Core.import_ref.a5b), @impl.4f9(%int_32) [concrete]
|
|
// CHECK:STDOUT: %Convert.type.035: type = fn_type @Convert.2, @impl.4f9(%int_32) [concrete]
|
|
// CHECK:STDOUT: %Convert.956: %Convert.type.035 = struct_value () [concrete]
|
|
// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.205 = facet_value Core.IntLiteral, (%impl_witness.d39) [concrete]
|
|
// CHECK:STDOUT: %.be7: type = fn_type_with_self_type %Convert.type.1b6, %ImplicitAs.facet [concrete]
|
|
// CHECK:STDOUT: %Convert.bound.ab5: <bound method> = bound_method %int_1.5b8, %Convert.956 [concrete]
|
|
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.2(%int_32) [concrete]
|
|
// CHECK:STDOUT: %bound_method.9a1: <bound method> = bound_method %int_1.5b8, %Convert.specific_fn [concrete]
|
|
// CHECK:STDOUT: %int_1.5d2: %i32 = int_value 1 [concrete]
|
|
// CHECK:STDOUT: %B.type: type = fn_type @B [concrete]
|
|
// CHECK:STDOUT: %B: %B.type = struct_value () [concrete]
|
|
// CHECK:STDOUT: %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]
|
|
// CHECK:STDOUT: %Convert.bound.ef9: <bound method> = bound_method %int_2.ecc, %Convert.956 [concrete]
|
|
// CHECK:STDOUT: %bound_method.b92: <bound method> = bound_method %int_2.ecc, %Convert.specific_fn [concrete]
|
|
// CHECK:STDOUT: %int_2.ef8: %i32 = int_value 2 [concrete]
|
|
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
|
|
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
|
|
// CHECK:STDOUT: %true: bool = bool_literal true [concrete]
|
|
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
|
|
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
|
|
// CHECK:STDOUT: %false: bool = bool_literal false [concrete]
|
|
// CHECK:STDOUT: %Constant.type: type = fn_type @Constant [concrete]
|
|
// CHECK:STDOUT: %Constant: %Constant.type = struct_value () [concrete]
|
|
// CHECK:STDOUT: %ptr: type = ptr_type %i32 [concrete]
|
|
// CHECK:STDOUT: %PartiallyConstant.type: type = fn_type @PartiallyConstant [concrete]
|
|
// CHECK:STDOUT: %PartiallyConstant: %PartiallyConstant.type = struct_value () [concrete]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: imports {
|
|
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [concrete] {
|
|
// CHECK:STDOUT: .Int = %Core.Int
|
|
// CHECK:STDOUT: .ImplicitAs = %Core.ImplicitAs
|
|
// CHECK:STDOUT: import Core//prelude
|
|
// CHECK:STDOUT: import Core//prelude/...
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: file {
|
|
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
|
|
// CHECK:STDOUT: .Core = imports.%Core
|
|
// CHECK:STDOUT: .A = %A.decl
|
|
// CHECK:STDOUT: .B = %B.decl
|
|
// CHECK:STDOUT: .F = %F.decl
|
|
// CHECK:STDOUT: .G = %G.decl
|
|
// CHECK:STDOUT: .Constant = %Constant.decl
|
|
// CHECK:STDOUT: .PartiallyConstant = %PartiallyConstant.decl
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %Core.import = import Core
|
|
// CHECK:STDOUT: %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {
|
|
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
|
|
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, call_param0
|
|
// CHECK:STDOUT: } {
|
|
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
|
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
|
|
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param0
|
|
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {
|
|
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
|
|
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, call_param0
|
|
// CHECK:STDOUT: } {
|
|
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
|
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
|
|
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param0
|
|
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
|
|
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
|
|
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, call_param0
|
|
// CHECK:STDOUT: } {
|
|
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
|
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
|
|
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param0
|
|
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {
|
|
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
|
|
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, call_param0
|
|
// CHECK:STDOUT: } {
|
|
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
|
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
|
|
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param0
|
|
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %Constant.decl: %Constant.type = fn_decl @Constant [concrete = constants.%Constant] {
|
|
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
|
|
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, call_param0
|
|
// CHECK:STDOUT: } {
|
|
// CHECK:STDOUT: %int_32.loc22: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
|
// CHECK:STDOUT: %i32.loc22: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
|
|
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param0
|
|
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %PartiallyConstant.decl: %PartiallyConstant.type = fn_decl @PartiallyConstant [concrete = constants.%PartiallyConstant] {
|
|
// CHECK:STDOUT: %t.patt: type = binding_pattern t
|
|
// CHECK:STDOUT: %t.param_patt: type = value_param_pattern %t.patt, call_param0
|
|
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
|
|
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, call_param1
|
|
// CHECK:STDOUT: } {
|
|
// CHECK:STDOUT: %int_32.loc28: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
|
// CHECK:STDOUT: %i32.loc28: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
|
|
// CHECK:STDOUT: %t.param: type = value_param call_param0
|
|
// CHECK:STDOUT: %t: type = bind_name t, %t.param
|
|
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param1
|
|
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @A() -> %i32 {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
|
|
// CHECK:STDOUT: %impl.elem0: %.be7 = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956]
|
|
// CHECK:STDOUT: %bound_method.loc11_25.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Convert.bound.ab5]
|
|
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
|
|
// CHECK:STDOUT: %bound_method.loc11_25.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method.9a1]
|
|
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %bound_method.loc11_25.2(%int_1) [concrete = constants.%int_1.5d2]
|
|
// CHECK:STDOUT: %.loc11_25.1: %i32 = value_of_initializer %int.convert_checked [concrete = constants.%int_1.5d2]
|
|
// CHECK:STDOUT: %.loc11_25.2: %i32 = converted %int_1, %.loc11_25.1 [concrete = constants.%int_1.5d2]
|
|
// CHECK:STDOUT: return %.loc11_25.2
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @B() -> %i32 {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]
|
|
// CHECK:STDOUT: %impl.elem0: %.be7 = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956]
|
|
// CHECK:STDOUT: %bound_method.loc12_25.1: <bound method> = bound_method %int_2, %impl.elem0 [concrete = constants.%Convert.bound.ef9]
|
|
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
|
|
// CHECK:STDOUT: %bound_method.loc12_25.2: <bound method> = bound_method %int_2, %specific_fn [concrete = constants.%bound_method.b92]
|
|
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %bound_method.loc12_25.2(%int_2) [concrete = constants.%int_2.ef8]
|
|
// CHECK:STDOUT: %.loc12_25.1: %i32 = value_of_initializer %int.convert_checked [concrete = constants.%int_2.ef8]
|
|
// CHECK:STDOUT: %.loc12_25.2: %i32 = converted %int_2, %.loc12_25.1 [concrete = constants.%int_2.ef8]
|
|
// CHECK:STDOUT: return %.loc12_25.2
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @F() -> %i32 {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: %true: bool = bool_literal true [concrete = constants.%true]
|
|
// CHECK:STDOUT: if %true br !if.expr.then else br !if.expr.else
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.then:
|
|
// CHECK:STDOUT: %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]
|
|
// CHECK:STDOUT: %A.call: init %i32 = call %A.ref()
|
|
// CHECK:STDOUT: %.loc15_25.1: %i32 = value_of_initializer %A.call
|
|
// CHECK:STDOUT: %.loc15_25.2: %i32 = converted %A.call, %.loc15_25.1
|
|
// CHECK:STDOUT: br !if.expr.result(%.loc15_25.2)
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.else:
|
|
// CHECK:STDOUT: %B.ref: %B.type = name_ref B, file.%B.decl [concrete = constants.%B]
|
|
// CHECK:STDOUT: %B.call: init %i32 = call %B.ref()
|
|
// CHECK:STDOUT: %.loc15_27.1: %i32 = value_of_initializer %B.call
|
|
// CHECK:STDOUT: %.loc15_27.2: %i32 = converted %B.call, %.loc15_27.1
|
|
// CHECK:STDOUT: br !if.expr.result(%.loc15_27.2)
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.result:
|
|
// CHECK:STDOUT: %.loc15_10: %i32 = block_arg !if.expr.result
|
|
// CHECK:STDOUT: return %.loc15_10
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @G() -> %i32 {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: %false: bool = bool_literal false [concrete = constants.%false]
|
|
// CHECK:STDOUT: if %false br !if.expr.then else br !if.expr.else
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.then:
|
|
// CHECK:STDOUT: %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]
|
|
// CHECK:STDOUT: %A.call: init %i32 = call %A.ref()
|
|
// CHECK:STDOUT: %.loc19_26.1: %i32 = value_of_initializer %A.call
|
|
// CHECK:STDOUT: %.loc19_26.2: %i32 = converted %A.call, %.loc19_26.1
|
|
// CHECK:STDOUT: br !if.expr.result(%.loc19_26.2)
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.else:
|
|
// CHECK:STDOUT: %B.ref: %B.type = name_ref B, file.%B.decl [concrete = constants.%B]
|
|
// CHECK:STDOUT: %B.call: init %i32 = call %B.ref()
|
|
// CHECK:STDOUT: %.loc19_28.1: %i32 = value_of_initializer %B.call
|
|
// CHECK:STDOUT: %.loc19_28.2: %i32 = converted %B.call, %.loc19_28.1
|
|
// CHECK:STDOUT: br !if.expr.result(%.loc19_28.2)
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.result:
|
|
// CHECK:STDOUT: %.loc19_10: %i32 = block_arg !if.expr.result
|
|
// CHECK:STDOUT: return %.loc19_10
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @Constant() -> %i32 {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: name_binding_decl {
|
|
// CHECK:STDOUT: %v.patt: %i32 = binding_pattern v
|
|
// CHECK:STDOUT: %.loc23_3.1: %i32 = var_pattern %v.patt
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %v.var: ref %i32 = var v
|
|
// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
|
|
// CHECK:STDOUT: %impl.elem0: %.be7 = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956]
|
|
// CHECK:STDOUT: %bound_method.loc23_3.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Convert.bound.ab5]
|
|
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
|
|
// CHECK:STDOUT: %bound_method.loc23_3.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method.9a1]
|
|
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %bound_method.loc23_3.2(%int_1) [concrete = constants.%int_1.5d2]
|
|
// CHECK:STDOUT: %.loc23_3.2: init %i32 = converted %int_1, %int.convert_checked [concrete = constants.%int_1.5d2]
|
|
// CHECK:STDOUT: assign %v.var, %.loc23_3.2
|
|
// CHECK:STDOUT: br !.loc23_13
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !.loc23_13:
|
|
// CHECK:STDOUT: %true: bool = bool_literal true [concrete = constants.%true]
|
|
// CHECK:STDOUT: if %true br !if.expr.then.loc23 else br !if.expr.else.loc23
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.then.loc23:
|
|
// CHECK:STDOUT: %int_32.loc23_23: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
|
// CHECK:STDOUT: %i32.loc23_23: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
|
|
// CHECK:STDOUT: br !if.expr.result.loc23(%i32.loc23_23)
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.else.loc23:
|
|
// CHECK:STDOUT: %int_32.loc23_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
|
// CHECK:STDOUT: %i32.loc23_32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
|
|
// CHECK:STDOUT: %ptr.loc23: type = ptr_type %i32 [concrete = constants.%ptr]
|
|
// CHECK:STDOUT: br !if.expr.result.loc23(%ptr.loc23)
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.result.loc23:
|
|
// CHECK:STDOUT: %.loc23_10: type = block_arg !if.expr.result.loc23 [concrete = constants.%i32]
|
|
// CHECK:STDOUT: br !.loc23_7
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !.loc23_7:
|
|
// CHECK:STDOUT: %v: ref %i32 = bind_name v, %v.var
|
|
// CHECK:STDOUT: name_binding_decl {
|
|
// CHECK:STDOUT: %w.patt: %ptr = binding_pattern w
|
|
// CHECK:STDOUT: %.loc24_3: %ptr = var_pattern %w.patt
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %w.var: ref %ptr = var w
|
|
// CHECK:STDOUT: %v.ref: ref %i32 = name_ref v, %v
|
|
// CHECK:STDOUT: %addr: %ptr = addr_of %v.ref
|
|
// CHECK:STDOUT: assign %w.var, %addr
|
|
// CHECK:STDOUT: br !.loc24_13
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !.loc24_13:
|
|
// CHECK:STDOUT: %false: bool = bool_literal false [concrete = constants.%false]
|
|
// CHECK:STDOUT: if %false br !if.expr.then.loc24 else br !if.expr.else.loc24
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.then.loc24:
|
|
// CHECK:STDOUT: %int_32.loc24_24: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
|
// CHECK:STDOUT: %i32.loc24_24: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
|
|
// CHECK:STDOUT: br !if.expr.result.loc24(%i32.loc24_24)
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.else.loc24:
|
|
// CHECK:STDOUT: %int_32.loc24_33: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
|
// CHECK:STDOUT: %i32.loc24_33: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
|
|
// CHECK:STDOUT: %ptr.loc24: type = ptr_type %i32 [concrete = constants.%ptr]
|
|
// CHECK:STDOUT: br !if.expr.result.loc24(%ptr.loc24)
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.result.loc24:
|
|
// CHECK:STDOUT: %.loc24_10: type = block_arg !if.expr.result.loc24 [concrete = constants.%ptr]
|
|
// CHECK:STDOUT: br !.loc24_7
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !.loc24_7:
|
|
// CHECK:STDOUT: %w: ref %ptr = bind_name w, %w.var
|
|
// CHECK:STDOUT: %w.ref: ref %ptr = name_ref w, %w
|
|
// CHECK:STDOUT: %.loc25_11: %ptr = bind_value %w.ref
|
|
// CHECK:STDOUT: %.loc25_10.1: ref %i32 = deref %.loc25_11
|
|
// CHECK:STDOUT: %.loc25_10.2: %i32 = bind_value %.loc25_10.1
|
|
// CHECK:STDOUT: return %.loc25_10.2
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @PartiallyConstant(%t.param_patt: type) -> %i32 {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: name_binding_decl {
|
|
// CHECK:STDOUT: %v.patt: %i32 = binding_pattern v
|
|
// CHECK:STDOUT: %.loc29_3.1: %i32 = var_pattern %v.patt
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %v.var: ref %i32 = var v
|
|
// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
|
|
// CHECK:STDOUT: %impl.elem0: %.be7 = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956]
|
|
// CHECK:STDOUT: %bound_method.loc29_3.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Convert.bound.ab5]
|
|
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
|
|
// CHECK:STDOUT: %bound_method.loc29_3.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method.9a1]
|
|
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %bound_method.loc29_3.2(%int_1) [concrete = constants.%int_1.5d2]
|
|
// CHECK:STDOUT: %.loc29_3.2: init %i32 = converted %int_1, %int.convert_checked [concrete = constants.%int_1.5d2]
|
|
// CHECK:STDOUT: assign %v.var, %.loc29_3.2
|
|
// CHECK:STDOUT: br !.loc29_13
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !.loc29_13:
|
|
// CHECK:STDOUT: %true: bool = bool_literal true [concrete = constants.%true]
|
|
// CHECK:STDOUT: if %true br !if.expr.then.loc29 else br !if.expr.else.loc29
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.then.loc29:
|
|
// CHECK:STDOUT: %int_32.loc29: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
|
// CHECK:STDOUT: %i32.loc29: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
|
|
// CHECK:STDOUT: br !if.expr.result.loc29(%i32.loc29)
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.else.loc29:
|
|
// CHECK:STDOUT: %t.ref.loc29: type = name_ref t, %t
|
|
// CHECK:STDOUT: br !if.expr.result.loc29(%t.ref.loc29)
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.result.loc29:
|
|
// CHECK:STDOUT: %.loc29_10: type = block_arg !if.expr.result.loc29 [concrete = constants.%i32]
|
|
// CHECK:STDOUT: br !.loc29_7
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !.loc29_7:
|
|
// CHECK:STDOUT: %v: ref %i32 = bind_name v, %v.var
|
|
// CHECK:STDOUT: name_binding_decl {
|
|
// CHECK:STDOUT: %w.patt: %ptr = binding_pattern w
|
|
// CHECK:STDOUT: %.loc30_3: %ptr = var_pattern %w.patt
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT: %w.var: ref %ptr = var w
|
|
// CHECK:STDOUT: %v.ref: ref %i32 = name_ref v, %v
|
|
// CHECK:STDOUT: %addr: %ptr = addr_of %v.ref
|
|
// CHECK:STDOUT: assign %w.var, %addr
|
|
// CHECK:STDOUT: br !.loc30_13
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !.loc30_13:
|
|
// CHECK:STDOUT: %false: bool = bool_literal false [concrete = constants.%false]
|
|
// CHECK:STDOUT: if %false br !if.expr.then.loc30 else br !if.expr.else.loc30
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.then.loc30:
|
|
// CHECK:STDOUT: %t.ref.loc30: type = name_ref t, %t
|
|
// CHECK:STDOUT: br !if.expr.result.loc30(%t.ref.loc30)
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.else.loc30:
|
|
// CHECK:STDOUT: %int_32.loc30: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
|
// CHECK:STDOUT: %i32.loc30: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
|
|
// CHECK:STDOUT: %ptr: type = ptr_type %i32 [concrete = constants.%ptr]
|
|
// CHECK:STDOUT: br !if.expr.result.loc30(%ptr)
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !if.expr.result.loc30:
|
|
// CHECK:STDOUT: %.loc30_10: type = block_arg !if.expr.result.loc30 [concrete = constants.%ptr]
|
|
// CHECK:STDOUT: br !.loc30_7
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: !.loc30_7:
|
|
// CHECK:STDOUT: %w: ref %ptr = bind_name w, %w.var
|
|
// CHECK:STDOUT: %w.ref: ref %ptr = name_ref w, %w
|
|
// CHECK:STDOUT: %.loc31_11: %ptr = bind_value %w.ref
|
|
// CHECK:STDOUT: %.loc31_10.1: ref %i32 = deref %.loc31_11
|
|
// CHECK:STDOUT: %.loc31_10.2: %i32 = bind_value %.loc31_10.1
|
|
// CHECK:STDOUT: return %.loc31_10.2
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|