Skip to content

Commit 164310c

Browse files
authored
Facet values (like type values) can be copied around at runtime (carbon-language#5242)
Give them a value representation of copy, and allow conversions between two facet values of the same type to work. Convert was assuming that facet values are compile time constants, but thye can also be runtime values. In that case, we have no support for converting to a different facet value of a different facet type. But if the types are equal then it's all fine. In theory it seems that we should be able to convert if the target facet type can be found through the source value's FacetType. But currently that happens through impl lookup and it requires constant values. Adding a test for this. Related to carbon-language#5241
1 parent c33adfa commit 164310c

31 files changed

+689
-58
lines changed

toolchain/check/convert.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1015,13 +1015,20 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id,
10151015
}
10161016
}
10171017

1018-
if (sem_ir.types().Is<SemIR::FacetType>(target.type_id) &&
1018+
if (target.type_id != value_type_id &&
1019+
sem_ir.types().Is<SemIR::FacetType>(target.type_id) &&
10191020
(sem_ir.types().Is<SemIR::TypeType>(value_type_id) ||
10201021
sem_ir.types().Is<SemIR::FacetType>(value_type_id))) {
10211022
// The value is a type or facet value, so it has a constant value. We get
10221023
// that to unwrap things like NameRef and get to the underlying type or
10231024
// facet value instruction so that we can use `TryGetAs`.
10241025
auto const_value_id = sem_ir.constant_values().GetConstantInstId(value_id);
1026+
// TODO: Runtime facet values should be allowed to convert based on their
1027+
// FacetTypes, but we assume constant values for impl lookup at the moment.
1028+
if (!const_value_id.has_value()) {
1029+
context.TODO(loc_id, "conversion of runtime facet value");
1030+
const_value_id = SemIR::ErrorInst::SingletonInstId;
1031+
}
10251032

10261033
if (auto facet_access_type_inst =
10271034
sem_ir.insts().TryGetAs<SemIR::FacetAccessType>(const_value_id)) {

toolchain/check/testdata/facet/min_prelude/convert_class_type_to_facet_type.carbon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ fn F() {
3030
// CHECK:STDOUT: %Goat: type = class_type @Goat [concrete]
3131
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
3232
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
33-
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
3433
// CHECK:STDOUT: %impl_witness: <witness> = impl_witness () [concrete]
3534
// CHECK:STDOUT: %A: %Animal.type = bind_symbolic_name A, 0 [symbolic]
3635
// CHECK:STDOUT: %A.patt: %Animal.type = symbolic_binding_pattern A, 0 [symbolic]
3736
// CHECK:STDOUT: %WalkAnimal.type: type = fn_type @WalkAnimal [concrete]
37+
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
3838
// CHECK:STDOUT: %WalkAnimal: %WalkAnimal.type = struct_value () [concrete]
3939
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
4040
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]

toolchain/check/testdata/facet/min_prelude/convert_facet_value_as_type_knows_original_type.carbon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ fn F() {
6868
// CHECK:STDOUT: %Goat: type = class_type @Goat [concrete]
6969
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
7070
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
71-
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
7271
// CHECK:STDOUT: %impl_witness: <witness> = impl_witness () [concrete]
7372
// CHECK:STDOUT: %e: %Eats.type = bind_symbolic_name e, 0 [symbolic]
7473
// CHECK:STDOUT: %e.patt: %Eats.type = symbolic_binding_pattern e, 0 [symbolic]
7574
// CHECK:STDOUT: %Feed.type: type = fn_type @Feed [concrete]
75+
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
7676
// CHECK:STDOUT: %Feed: %Feed.type = struct_value () [concrete]
7777
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
7878
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]

toolchain/check/testdata/facet/min_prelude/convert_facet_value_to_narrowed_facet_type.carbon

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,10 +383,10 @@ fn CallsWithTypeExplicit(U:! type) {
383383
// CHECK:STDOUT: %Self.7ee: %Tame.type = bind_symbolic_name Self, 0 [symbolic]
384384
// CHECK:STDOUT: %BitAnd.type: type = facet_type <@BitAnd> [concrete]
385385
// CHECK:STDOUT: %Self.25f: %BitAnd.type = bind_symbolic_name Self, 0 [symbolic]
386-
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
387386
// CHECK:STDOUT: %BitAnd.assoc_type: type = assoc_entity_type %BitAnd.type [concrete]
388387
// CHECK:STDOUT: %assoc0: %BitAnd.assoc_type = assoc_entity element0, imports.%Core.import_ref.a93 [concrete]
389388
// CHECK:STDOUT: %Op.type.27a: type = fn_type @Op.1 [concrete]
389+
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
390390
// CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self.25f [symbolic]
391391
// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic]
392392
// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic]
@@ -694,13 +694,13 @@ fn CallsWithTypeExplicit(U:! type) {
694694
// CHECK:STDOUT: %A: %Animal.type = bind_symbolic_name A, 0 [symbolic]
695695
// CHECK:STDOUT: %A.patt: %Animal.type = symbolic_binding_pattern A, 0 [symbolic]
696696
// CHECK:STDOUT: %A.as_type: type = facet_access_type %A [symbolic]
697-
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
698697
// CHECK:STDOUT: %impl_witness.110: <witness> = impl_witness (), @impl.e7b(%A) [symbolic]
699698
// CHECK:STDOUT: %BitAnd.type: type = facet_type <@BitAnd> [concrete]
700699
// CHECK:STDOUT: %Self.25f: %BitAnd.type = bind_symbolic_name Self, 0 [symbolic]
701700
// CHECK:STDOUT: %BitAnd.assoc_type: type = assoc_entity_type %BitAnd.type [concrete]
702701
// CHECK:STDOUT: %assoc0: %BitAnd.assoc_type = assoc_entity element0, imports.%Core.import_ref.a93 [concrete]
703702
// CHECK:STDOUT: %Op.type.27a: type = fn_type @Op.1 [concrete]
703+
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
704704
// CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self.25f [symbolic]
705705
// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic]
706706
// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic]

toolchain/check/testdata/facet/min_prelude/convert_facet_value_value_to_blanket_impl.carbon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ fn HandleAnimal[T:! Animal](a: T) { Feed(a); }
3030
// CHECK:STDOUT: %A: %Animal.type = bind_symbolic_name A, 0 [symbolic]
3131
// CHECK:STDOUT: %A.patt: %Animal.type = symbolic_binding_pattern A, 0 [symbolic]
3232
// CHECK:STDOUT: %A.as_type: type = facet_access_type %A [symbolic]
33-
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
3433
// CHECK:STDOUT: %impl_witness.11010a.1: <witness> = impl_witness (), @impl(%A) [symbolic]
3534
// CHECK:STDOUT: %T.1b5: %Eats.type = bind_symbolic_name T, 0 [symbolic]
3635
// CHECK:STDOUT: %T.patt.6be: %Eats.type = symbolic_binding_pattern T, 0 [symbolic]
3736
// CHECK:STDOUT: %T.as_type.27d: type = facet_access_type %T.1b5 [symbolic]
3837
// CHECK:STDOUT: %Feed.type: type = fn_type @Feed [concrete]
38+
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
3939
// CHECK:STDOUT: %Feed: %Feed.type = struct_value () [concrete]
4040
// CHECK:STDOUT: %require_complete.c75: <witness> = require_complete_type %T.as_type.27d [symbolic]
4141
// CHECK:STDOUT: %T.fd4: %Animal.type = bind_symbolic_name T, 0 [symbolic]

toolchain/check/testdata/facet/min_prelude/convert_facet_value_value_to_generic_facet_value_value.carbon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ fn F() {
4242
// CHECK:STDOUT: %Grass: type = class_type @Grass [concrete]
4343
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
4444
// CHECK:STDOUT: %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
45-
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
4645
// CHECK:STDOUT: %impl_witness.1bc: <witness> = impl_witness () [concrete]
4746
// CHECK:STDOUT: %Animal.type: type = facet_type <@Animal> [concrete]
4847
// CHECK:STDOUT: %Self.fd4: %Animal.type = bind_symbolic_name Self, 0 [symbolic]
4948
// CHECK:STDOUT: %Food.8b3: type = bind_symbolic_name Food, 0 [symbolic]
5049
// CHECK:STDOUT: %Food.patt.e01: type = symbolic_binding_pattern Food, 0 [symbolic]
5150
// CHECK:STDOUT: %Eats.type.ba2: type = generic_interface_type @Eats [concrete]
51+
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
5252
// CHECK:STDOUT: %Eats.generic: %Eats.type.ba2 = struct_value () [concrete]
5353
// CHECK:STDOUT: %Eats.type.6c0: type = facet_type <@Eats, @Eats(%Food.8b3)> [symbolic]
5454
// CHECK:STDOUT: %Self.4eb: %Eats.type.6c0 = bind_symbolic_name Self, 1 [symbolic]

toolchain/check/testdata/facet/min_prelude/convert_interface.carbon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ fn G() { F(Animal); }
2828
// CHECK:STDOUT: %Self.1b5: %Eats.type = bind_symbolic_name Self, 0 [symbolic]
2929
// CHECK:STDOUT: %Animal.type: type = facet_type <@Animal> [concrete]
3030
// CHECK:STDOUT: %Self.fd4: %Animal.type = bind_symbolic_name Self, 0 [symbolic]
31-
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
3231
// CHECK:STDOUT: %impl_witness: <witness> = impl_witness () [concrete]
3332
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
33+
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
3434
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
3535
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
3636
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]

0 commit comments

Comments
 (0)