Skip to content

Commit dcc74e9

Browse files
committed
Avoid crashing during associated constant lookup on a runtime facet value
Perhaps we will disallow member lookup on and conversion of runtime facet values. For now, leave a TODO and produce a TODO diagnostic instead of crashing. Related to carbon-language#5241.
1 parent 164310c commit dcc74e9

File tree

2 files changed

+206
-0
lines changed

2 files changed

+206
-0
lines changed

toolchain/check/member_access.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,13 @@ static auto GetAssociatedValueImpl(Context& context, SemIR::LocId loc_id,
607607
context, SemIR::InstId::None,
608608
SemIR::FacetAccessType{.type_id = SemIR::TypeType::SingletonTypeId,
609609
.facet_value_inst_id = facet_inst_id});
610+
// TODO: We should be able to lookup constant associated values from runtime
611+
// facet values by using their FacetType only, but we assume constant values
612+
// for impl lookup at the moment.
613+
if (!self_type_const_id.is_constant()) {
614+
context.TODO(loc_id, "associated value lookup on runtime facet value");
615+
return SemIR::ErrorInst::SingletonInstId;
616+
}
610617
auto self_type_id =
611618
context.types().GetTypeIdForTypeConstantId(self_type_const_id);
612619
auto witness_id =

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

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,24 @@ fn F(c: C) {
4646
let a: I = c.ij;
4747
}
4848

49+
// --- fail_todo_member_lookup_in_runtime_value.carbon
50+
51+
interface Z(T:! type) {
52+
let X:! type;
53+
}
54+
55+
class C {}
56+
57+
final impl forall [T:! type] T as Z(C) where .X = () {}
58+
59+
// CHECK:STDERR: fail_todo_member_lookup_in_runtime_value.carbon:[[@LINE+4]]:18: error: semantics TODO: `associated value lookup on runtime facet value` [SemanticsTodo]
60+
// CHECK:STDERR: fn F(T: Z(C)) -> T.(Z(C).X) {
61+
// CHECK:STDERR: ^~~~~~~~~~
62+
// CHECK:STDERR:
63+
fn F(T: Z(C)) -> T.(Z(C).X) {
64+
return ();
65+
}
66+
4967
// CHECK:STDOUT: --- facet_value_copy_from_reference.carbon
5068
// CHECK:STDOUT:
5169
// CHECK:STDOUT: constants {
@@ -311,6 +329,187 @@ fn F(c: C) {
311329
// CHECK:STDOUT: !definition:
312330
// CHECK:STDOUT: }
313331
// CHECK:STDOUT:
332+
// CHECK:STDOUT: --- fail_todo_member_lookup_in_runtime_value.carbon
333+
// CHECK:STDOUT:
334+
// CHECK:STDOUT: constants {
335+
// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic]
336+
// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic]
337+
// CHECK:STDOUT: %Z.type.9fb: type = generic_interface_type @Z [concrete]
338+
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
339+
// CHECK:STDOUT: %Z.generic: %Z.type.9fb = struct_value () [concrete]
340+
// CHECK:STDOUT: %Z.type.a61: type = facet_type <@Z, @Z(%T)> [symbolic]
341+
// CHECK:STDOUT: %Self.2bc: %Z.type.a61 = bind_symbolic_name Self, 1 [symbolic]
342+
// CHECK:STDOUT: %Z.assoc_type.40c: type = assoc_entity_type %Z.type.a61 [symbolic]
343+
// CHECK:STDOUT: %assoc0.3aa: %Z.assoc_type.40c = assoc_entity element0, @Z.%X [symbolic]
344+
// CHECK:STDOUT: %C: type = class_type @C [concrete]
345+
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
346+
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
347+
// CHECK:STDOUT: %Z.type.049: type = facet_type <@Z, @Z(%C)> [concrete]
348+
// CHECK:STDOUT: %.Self: %Z.type.049 = bind_symbolic_name .Self [symbolic_self]
349+
// CHECK:STDOUT: %Self.a38: %Z.type.049 = bind_symbolic_name Self, 1 [symbolic]
350+
// CHECK:STDOUT: %Z.assoc_type.444: type = assoc_entity_type %Z.type.049 [concrete]
351+
// CHECK:STDOUT: %assoc0.1c8: %Z.assoc_type.444 = assoc_entity element0, @Z.%X [concrete]
352+
// CHECK:STDOUT: %.Self.as_type: type = facet_access_type %.Self [symbolic_self]
353+
// CHECK:STDOUT: %.Self.as_wit.iface0: <witness> = facet_access_witness %.Self, element0 [symbolic_self]
354+
// CHECK:STDOUT: %Z.facet: %Z.type.049 = facet_value %.Self.as_type, (%.Self.as_wit.iface0) [symbolic_self]
355+
// CHECK:STDOUT: %impl.elem0: type = impl_witness_access %.Self.as_wit.iface0, element0 [symbolic_self]
356+
// CHECK:STDOUT: %Z_where.type: type = facet_type <@Z, @Z(%C) where %impl.elem0 = %empty_tuple.type> [concrete]
357+
// CHECK:STDOUT: %impl_witness: <witness> = impl_witness (%empty_tuple.type), @impl(%T) [symbolic]
358+
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
359+
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
360+
// CHECK:STDOUT: }
361+
// CHECK:STDOUT:
362+
// CHECK:STDOUT: imports {
363+
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [concrete] {
364+
// CHECK:STDOUT: import Core//prelude
365+
// CHECK:STDOUT: }
366+
// CHECK:STDOUT: }
367+
// CHECK:STDOUT:
368+
// CHECK:STDOUT: file {
369+
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
370+
// CHECK:STDOUT: .Core = imports.%Core
371+
// CHECK:STDOUT: .Z = %Z.decl
372+
// CHECK:STDOUT: .C = %C.decl
373+
// CHECK:STDOUT: .F = %F.decl
374+
// CHECK:STDOUT: }
375+
// CHECK:STDOUT: %Core.import = import Core
376+
// CHECK:STDOUT: %Z.decl: %Z.type.9fb = interface_decl @Z [concrete = constants.%Z.generic] {
377+
// CHECK:STDOUT: %T.patt.loc2_13.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc2_13.2 (constants.%T.patt)]
378+
// CHECK:STDOUT: } {
379+
// CHECK:STDOUT: %T.loc2_13.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc2_13.2 (constants.%T)]
380+
// CHECK:STDOUT: }
381+
// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
382+
// CHECK:STDOUT: impl_decl @impl [concrete] {
383+
// CHECK:STDOUT: %T.patt.loc8_20.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc8_20.2 (constants.%T.patt)]
384+
// CHECK:STDOUT: } {
385+
// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc8_20.1 [symbolic = %T.loc8_20.2 (constants.%T)]
386+
// CHECK:STDOUT: %Z.ref: %Z.type.9fb = name_ref Z, file.%Z.decl [concrete = constants.%Z.generic]
387+
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
388+
// CHECK:STDOUT: %Z.type: type = facet_type <@Z, @Z(constants.%C)> [concrete = constants.%Z.type.049]
389+
// CHECK:STDOUT: %.Self: %Z.type.049 = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
390+
// CHECK:STDOUT: %.Self.ref: %Z.type.049 = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
391+
// CHECK:STDOUT: %.loc8_46.1: %Z.assoc_type.444 = specific_constant @X.%assoc0, @Z(constants.%C) [concrete = constants.%assoc0.1c8]
392+
// CHECK:STDOUT: %X.ref: %Z.assoc_type.444 = name_ref X, %.loc8_46.1 [concrete = constants.%assoc0.1c8]
393+
// CHECK:STDOUT: %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
394+
// CHECK:STDOUT: %.loc8_46.2: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
395+
// CHECK:STDOUT: %.Self.as_wit.iface0: <witness> = facet_access_witness %.Self.ref, element0 [symbolic_self = constants.%.Self.as_wit.iface0]
396+
// CHECK:STDOUT: %impl.elem0: type = impl_witness_access %.Self.as_wit.iface0, element0 [symbolic_self = constants.%impl.elem0]
397+
// CHECK:STDOUT: %.loc8_52.1: %empty_tuple.type = tuple_literal ()
398+
// CHECK:STDOUT: %.loc8_52.2: type = converted %.loc8_52.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
399+
// CHECK:STDOUT: %.loc8_40: type = where_expr %.Self [concrete = constants.%Z_where.type] {
400+
// CHECK:STDOUT: requirement_rewrite %impl.elem0, %.loc8_52.2
401+
// CHECK:STDOUT: }
402+
// CHECK:STDOUT: %T.loc8_20.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc8_20.2 (constants.%T)]
403+
// CHECK:STDOUT: }
404+
// CHECK:STDOUT: %impl_witness: <witness> = impl_witness (constants.%empty_tuple.type), @impl(constants.%T) [symbolic = @impl.%impl_witness (constants.%impl_witness)]
405+
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
406+
// CHECK:STDOUT: %T.patt: %Z.type.049 = binding_pattern T
407+
// CHECK:STDOUT: %T.param_patt: %Z.type.049 = value_param_pattern %T.patt, call_param0
408+
// CHECK:STDOUT: %return.patt: <error> = return_slot_pattern
409+
// CHECK:STDOUT: %return.param_patt: <error> = out_param_pattern %return.patt, call_param1
410+
// CHECK:STDOUT: } {
411+
// CHECK:STDOUT: %T.ref: %Z.type.049 = name_ref T, %T
412+
// CHECK:STDOUT: %Z.ref.loc14_21: %Z.type.9fb = name_ref Z, file.%Z.decl [concrete = constants.%Z.generic]
413+
// CHECK:STDOUT: %C.ref.loc14_23: type = name_ref C, file.%C.decl [concrete = constants.%C]
414+
// CHECK:STDOUT: %Z.type.loc14_24: type = facet_type <@Z, @Z(constants.%C)> [concrete = constants.%Z.type.049]
415+
// CHECK:STDOUT: %.loc14_25: %Z.assoc_type.444 = specific_constant @X.%assoc0, @Z(constants.%C) [concrete = constants.%assoc0.1c8]
416+
// CHECK:STDOUT: %X.ref: %Z.assoc_type.444 = name_ref X, %.loc14_25 [concrete = constants.%assoc0.1c8]
417+
// CHECK:STDOUT: %T.param: %Z.type.049 = value_param call_param0
418+
// CHECK:STDOUT: %.loc14_12: type = splice_block %Z.type.loc14_12 [concrete = constants.%Z.type.049] {
419+
// CHECK:STDOUT: %Z.ref.loc14_9: %Z.type.9fb = name_ref Z, file.%Z.decl [concrete = constants.%Z.generic]
420+
// CHECK:STDOUT: %C.ref.loc14_11: type = name_ref C, file.%C.decl [concrete = constants.%C]
421+
// CHECK:STDOUT: %Z.type.loc14_12: type = facet_type <@Z, @Z(constants.%C)> [concrete = constants.%Z.type.049]
422+
// CHECK:STDOUT: }
423+
// CHECK:STDOUT: %T: %Z.type.049 = bind_name T, %T.param
424+
// CHECK:STDOUT: %return.param: ref <error> = out_param call_param1
425+
// CHECK:STDOUT: %return: ref <error> = return_slot %return.param
426+
// CHECK:STDOUT: }
427+
// CHECK:STDOUT: }
428+
// CHECK:STDOUT:
429+
// CHECK:STDOUT: generic interface @Z(%T.loc2_13.1: type) {
430+
// CHECK:STDOUT: %T.loc2_13.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc2_13.2 (constants.%T)]
431+
// CHECK:STDOUT: %T.patt.loc2_13.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc2_13.2 (constants.%T.patt)]
432+
// CHECK:STDOUT:
433+
// CHECK:STDOUT: !definition:
434+
// CHECK:STDOUT: %Z.type: type = facet_type <@Z, @Z(%T.loc2_13.2)> [symbolic = %Z.type (constants.%Z.type.a61)]
435+
// CHECK:STDOUT: %Self.2: @Z.%Z.type (%Z.type.a61) = bind_symbolic_name Self, 1 [symbolic = %Self.2 (constants.%Self.2bc)]
436+
// CHECK:STDOUT: %Z.assoc_type: type = assoc_entity_type @Z.%Z.type (%Z.type.a61) [symbolic = %Z.assoc_type (constants.%Z.assoc_type.40c)]
437+
// CHECK:STDOUT: %assoc0: @Z.%Z.assoc_type (%Z.assoc_type.40c) = assoc_entity element0, %X [symbolic = %assoc0 (constants.%assoc0.3aa)]
438+
// CHECK:STDOUT:
439+
// CHECK:STDOUT: interface {
440+
// CHECK:STDOUT: %Self.1: @Z.%Z.type (%Z.type.a61) = bind_symbolic_name Self, 1 [symbolic = %Self.2 (constants.%Self.2bc)]
441+
// CHECK:STDOUT: %X: type = assoc_const_decl @X [concrete] {
442+
// CHECK:STDOUT: %assoc0: @Z.%Z.assoc_type (%Z.assoc_type.40c) = assoc_entity element0, @Z.%X [symbolic = @Z.%assoc0 (constants.%assoc0.3aa)]
443+
// CHECK:STDOUT: }
444+
// CHECK:STDOUT:
445+
// CHECK:STDOUT: !members:
446+
// CHECK:STDOUT: .Self = %Self.1
447+
// CHECK:STDOUT: .X = @X.%assoc0
448+
// CHECK:STDOUT: witness = (%X)
449+
// CHECK:STDOUT: }
450+
// CHECK:STDOUT: }
451+
// CHECK:STDOUT:
452+
// CHECK:STDOUT: generic assoc_const @X(@Z.%T.loc2_13.1: type, @Z.%Self.1: @Z.%Z.type (%Z.type.a61)) {
453+
// CHECK:STDOUT: assoc_const X:! type;
454+
// CHECK:STDOUT: }
455+
// CHECK:STDOUT:
456+
// CHECK:STDOUT: generic impl @impl(%T.loc8_20.1: type) {
457+
// CHECK:STDOUT: %T.loc8_20.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc8_20.2 (constants.%T)]
458+
// CHECK:STDOUT: %T.patt.loc8_20.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc8_20.2 (constants.%T.patt)]
459+
// CHECK:STDOUT: %impl_witness: <witness> = impl_witness (constants.%empty_tuple.type), @impl(%T.loc8_20.2) [symbolic = %impl_witness (constants.%impl_witness)]
460+
// CHECK:STDOUT:
461+
// CHECK:STDOUT: !definition:
462+
// CHECK:STDOUT:
463+
// CHECK:STDOUT: impl: %T.ref as %.loc8_40 {
464+
// CHECK:STDOUT: !members:
465+
// CHECK:STDOUT: witness = file.%impl_witness
466+
// CHECK:STDOUT: }
467+
// CHECK:STDOUT: }
468+
// CHECK:STDOUT:
469+
// CHECK:STDOUT: class @C {
470+
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
471+
// CHECK:STDOUT: complete_type_witness = %complete_type
472+
// CHECK:STDOUT:
473+
// CHECK:STDOUT: !members:
474+
// CHECK:STDOUT: .Self = constants.%C
475+
// CHECK:STDOUT: }
476+
// CHECK:STDOUT:
477+
// CHECK:STDOUT: fn @F(%T.param_patt: %Z.type.049) -> <error> {
478+
// CHECK:STDOUT: !entry:
479+
// CHECK:STDOUT: %.loc15: %empty_tuple.type = tuple_literal ()
480+
// CHECK:STDOUT: return <error>
481+
// CHECK:STDOUT: }
482+
// CHECK:STDOUT:
483+
// CHECK:STDOUT: specific @Z(constants.%T) {
484+
// CHECK:STDOUT: %T.loc2_13.2 => constants.%T
485+
// CHECK:STDOUT: %T.patt.loc2_13.2 => constants.%T.patt
486+
// CHECK:STDOUT: }
487+
// CHECK:STDOUT:
488+
// CHECK:STDOUT: specific @X(constants.%T, constants.%Self.2bc) {}
489+
// CHECK:STDOUT:
490+
// CHECK:STDOUT: specific @Z(%T.loc2_13.2) {}
491+
// CHECK:STDOUT:
492+
// CHECK:STDOUT: specific @Z(constants.%C) {
493+
// CHECK:STDOUT: %T.loc2_13.2 => constants.%C
494+
// CHECK:STDOUT: %T.patt.loc2_13.2 => constants.%T.patt
495+
// CHECK:STDOUT:
496+
// CHECK:STDOUT: !definition:
497+
// CHECK:STDOUT: %Z.type => constants.%Z.type.049
498+
// CHECK:STDOUT: %Self.2 => constants.%Self.a38
499+
// CHECK:STDOUT: %Z.assoc_type => constants.%Z.assoc_type.444
500+
// CHECK:STDOUT: %assoc0 => constants.%assoc0.1c8
501+
// CHECK:STDOUT: }
502+
// CHECK:STDOUT:
503+
// CHECK:STDOUT: specific @X(constants.%C, constants.%Z.facet) {}
504+
// CHECK:STDOUT:
505+
// CHECK:STDOUT: specific @impl(constants.%T) {
506+
// CHECK:STDOUT: %T.loc8_20.2 => constants.%T
507+
// CHECK:STDOUT: %T.patt.loc8_20.2 => constants.%T.patt
508+
// CHECK:STDOUT: %impl_witness => constants.%impl_witness
509+
// CHECK:STDOUT: }
510+
// CHECK:STDOUT:
511+
// CHECK:STDOUT: specific @impl(%T.loc8_20.2) {}
512+
// CHECK:STDOUT:
314513
// CHECK:STDOUT: --- include_files/facet_types.carbon
315514
// CHECK:STDOUT:
316515
// CHECK:STDOUT: constants {

0 commit comments

Comments
 (0)