Skip to content

Commit 114ecda

Browse files
authored
Enable conversions to value-or-ref to use value_of_initializer (#6309)
As a byproduct, the only test that exercised the "address of a temporary object" diagnostic now trigers the "address of a non-reference expression" diagnostic. We could restore it by using a type that doesn't support `value_of_initializer`, but it seems better to remove the diagnostic altogether: not only does it simplify the code, I'd also argue "non-reference expression" is more accurate as a user-facing description of the operand.
1 parent 1324fad commit 114ecda

File tree

5 files changed

+17
-29
lines changed

5 files changed

+17
-29
lines changed

toolchain/check/convert.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,14 +722,16 @@ static auto ConvertDerivedPointerToBasePointer(
722722
}
723723

724724
// Returns whether `category` is a valid expression category to produce as a
725-
// result of a conversion with kind `target_kind`, or at most needs a temporary
726-
// to be materialized.
725+
// result of a conversion with kind `target_kind`.
727726
static auto IsValidExprCategoryForConversionTarget(
728727
SemIR::ExprCategory category, ConversionTarget::Kind target_kind) -> bool {
729728
switch (target_kind) {
730729
case ConversionTarget::Value:
731730
return category == SemIR::ExprCategory::Value;
732731
case ConversionTarget::ValueOrRef:
732+
return category == SemIR::ExprCategory::Value ||
733+
category == SemIR::ExprCategory::DurableRef ||
734+
category == SemIR::ExprCategory::EphemeralRef;
733735
case ConversionTarget::Discarded:
734736
return category == SemIR::ExprCategory::Value ||
735737
category == SemIR::ExprCategory::DurableRef ||
@@ -910,6 +912,12 @@ static auto PerformBuiltinConversion(
910912
context, loc_id, {.type_id = value_type_id, .init_id = value_id});
911913
}
912914

915+
// Materialization is handled as part of the enclosing conversion.
916+
if (value_cat == SemIR::ExprCategory::Initializing &&
917+
target.kind == ConversionTarget::ValueOrRef) {
918+
return value_id;
919+
}
920+
913921
// PerformBuiltinConversion converts each part of a tuple or struct, even
914922
// when the types are the same. This is not done for classes since they have
915923
// to define their conversions as part of their api.

toolchain/check/handle_operator.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,6 @@ auto HandleParseNode(Context& context, Parse::PrefixOperatorAmpId node_id)
252252
case SemIR::ExprCategory::DurableRef:
253253
case SemIR::ExprCategory::Error:
254254
break;
255-
case SemIR::ExprCategory::EphemeralRef:
256-
CARBON_DIAGNOSTIC(AddrOfEphemeralRef, Error,
257-
"cannot take the address of a temporary object");
258-
context.emitter().Emit(LocIdForDiagnostics::TokenOnly(node_id),
259-
AddrOfEphemeralRef);
260-
value_id = SemIR::ErrorInst::InstId;
261-
break;
262255
default:
263256
CARBON_DIAGNOSTIC(AddrOfNonRef, Error,
264257
"cannot take the address of non-reference expression");

toolchain/check/testdata/pointer/fail_address_of_value.carbon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ fn AddressOfOperator() {
5353
// CHECK:STDERR: ^
5454
// CHECK:STDERR:
5555
&(true and false);
56-
// CHECK:STDERR: fail_address_of_value.carbon:[[@LINE+4]]:3: error: cannot take the address of a temporary object [AddrOfEphemeralRef]
56+
// CHECK:STDERR: fail_address_of_value.carbon:[[@LINE+4]]:3: error: cannot take the address of non-reference expression [AddrOfNonRef]
5757
// CHECK:STDERR: &H().a;
5858
// CHECK:STDERR: ^
5959
// CHECK:STDERR:

toolchain/check/testdata/tuple/element_access.carbon

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,6 @@ var b: i32 = a.({.index = 2}.index);
438438
// CHECK:STDOUT:
439439
// CHECK:STDOUT: constants {
440440
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
441-
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
442441
// CHECK:STDOUT: %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]
443442
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete]
444443
// CHECK:STDOUT: %tuple.type.a1c: type = tuple_type (%i32) [concrete]
@@ -455,11 +454,6 @@ var b: i32 = a.({.index = 2}.index);
455454
// CHECK:STDOUT: %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.fb7) [concrete]
456455
// CHECK:STDOUT: %.65f: type = fn_type_with_self_type %Copy.Op.type, %Copy.facet [concrete]
457456
// CHECK:STDOUT: %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.dfd, @Int.as.Copy.impl.Op(%int_32) [concrete]
458-
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
459-
// CHECK:STDOUT: %facet_value: %type_where = facet_value %tuple.type.a1c, () [concrete]
460-
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.49b: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [concrete]
461-
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.c36: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.49b = struct_value () [concrete]
462-
// CHECK:STDOUT: %ptr.0b7: type = ptr_type %tuple.type.a1c [concrete]
463457
// CHECK:STDOUT: }
464458
// CHECK:STDOUT:
465459
// CHECK:STDOUT: imports {
@@ -472,20 +466,14 @@ var b: i32 = a.({.index = 2}.index);
472466
// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
473467
// CHECK:STDOUT: %F.call: init %tuple.type.a1c = call %F.ref()
474468
// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
475-
// CHECK:STDOUT: %.loc7_12.1: ref %tuple.type.a1c = temporary_storage
476-
// CHECK:STDOUT: %.loc7_12.2: ref %tuple.type.a1c = temporary %.loc7_12.1, %F.call
477-
// CHECK:STDOUT: %tuple.elem0: ref %i32 = tuple_access %.loc7_12.2, element0
478-
// CHECK:STDOUT: %.loc7_13: %i32 = acquire_value %tuple.elem0
469+
// CHECK:STDOUT: %.loc7_12.1: %tuple.type.a1c = value_of_initializer %F.call
470+
// CHECK:STDOUT: %.loc7_12.2: %tuple.type.a1c = converted %F.call, %.loc7_12.1
471+
// CHECK:STDOUT: %tuple.elem0: %i32 = tuple_access %.loc7_12.2, element0
479472
// CHECK:STDOUT: %impl.elem0: %.65f = impl_witness_access constants.%Copy.impl_witness.fb7, element0 [concrete = constants.%Int.as.Copy.impl.Op.dfd]
480-
// CHECK:STDOUT: %bound_method.loc7_13.1: <bound method> = bound_method %.loc7_13, %impl.elem0
473+
// CHECK:STDOUT: %bound_method.loc7_13.1: <bound method> = bound_method %tuple.elem0, %impl.elem0
481474
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
482-
// CHECK:STDOUT: %bound_method.loc7_13.2: <bound method> = bound_method %.loc7_13, %specific_fn
483-
// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc7_13.2(%.loc7_13)
484-
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc7_12.2, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.c36
485-
// CHECK:STDOUT: <elided>
486-
// CHECK:STDOUT: %bound_method.loc7_12: <bound method> = bound_method %.loc7_12.2, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn
487-
// CHECK:STDOUT: %addr: %ptr.0b7 = addr_of %.loc7_12.2
488-
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc7_12(%addr)
475+
// CHECK:STDOUT: %bound_method.loc7_13.2: <bound method> = bound_method %tuple.elem0, %specific_fn
476+
// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc7_13.2(%tuple.elem0)
489477
// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call to %return
490478
// CHECK:STDOUT: }
491479
// CHECK:STDOUT:

toolchain/diagnostics/diagnostic_kind.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,6 @@ CARBON_DIAGNOSTIC_KIND(AbstractTypeInFieldDecl)
392392
CARBON_DIAGNOSTIC_KIND(AbstractTypeInFunctionReturnType)
393393
CARBON_DIAGNOSTIC_KIND(AbstractTypeInInit)
394394
CARBON_DIAGNOSTIC_KIND(AbstractTypeInVarPattern)
395-
CARBON_DIAGNOSTIC_KIND(AddrOfEphemeralRef)
396395
CARBON_DIAGNOSTIC_KIND(AddrOfNonRef)
397396
CARBON_DIAGNOSTIC_KIND(AddrOnNonSelfParam)
398397
CARBON_DIAGNOSTIC_KIND(AddrOnNonPointerType)

0 commit comments

Comments
 (0)