mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Make the constant value of AsCompatible match its type (#4881)
AsCompatible changes a source instruction's type to a compatible type, so it also needs its constant value to take on the compatible type. Otherwise the type of the instruction and its constant value will differ, which makes moving to the constant value into a lossy transformation. Part of #4868
This commit is contained in:
@@ -1512,6 +1512,10 @@ static auto MakeFacetTypeResult(Context& context,
|
||||
}
|
||||
|
||||
// Implementation for `TryEvalInst`, wrapping `Context` with `EvalContext`.
|
||||
//
|
||||
// Tail call should not be diagnosed as recursion.
|
||||
// https://github.com/llvm/llvm-project/issues/125724
|
||||
// NOLINTNEXTLINE(misc-no-recursion): Tail call.
|
||||
static auto TryEvalInstInContext(EvalContext& eval_context,
|
||||
SemIR::InstId inst_id, SemIR::Inst inst)
|
||||
-> SemIR::ConstantId {
|
||||
@@ -1898,10 +1902,43 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
|
||||
return MakeConstantResult(eval_context.context(), bind, phase);
|
||||
}
|
||||
|
||||
// These semantic wrappers don't change the constant value.
|
||||
// AsCompatible changes the type of the source instruction; its constant
|
||||
// value, if there is one, needs to be modified to be of the same type.
|
||||
case CARBON_KIND(SemIR::AsCompatible inst): {
|
||||
return eval_context.GetConstantValue(inst.source_id);
|
||||
auto value = eval_context.GetConstantValue(inst.source_id);
|
||||
if (!value.is_constant()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
auto from_phase = Phase::Template;
|
||||
auto value_inst_id =
|
||||
GetConstantValue(eval_context, inst.source_id, &from_phase);
|
||||
|
||||
auto to_phase = Phase::Template;
|
||||
auto type_id = GetConstantValue(eval_context, inst.type_id, &to_phase);
|
||||
|
||||
auto value_inst = eval_context.insts().Get(value_inst_id);
|
||||
value_inst.SetType(type_id);
|
||||
|
||||
if (to_phase >= from_phase) {
|
||||
// If moving from a template constant value to a symbolic type, the new
|
||||
// constant value takes on the phase of the new type. We're adding the
|
||||
// symbolic bit to the new constant value due to the presence of a
|
||||
// symbolic type.
|
||||
return MakeConstantResult(eval_context.context(), value_inst, to_phase);
|
||||
} else {
|
||||
// If moving from a symbolic constant value to a template type, the new
|
||||
// constant value has a phase that depends on what is in the value. If
|
||||
// there is anything symbolic within the value, then it's symbolic. We
|
||||
// can't easily determine that here without evaluating a new constant
|
||||
// value. See
|
||||
// https://github.com/carbon-language/carbon-lang/pull/4881#discussion_r1939961372
|
||||
[[clang::musttail]] return TryEvalInstInContext(
|
||||
eval_context, SemIR::InstId::None, value_inst);
|
||||
}
|
||||
}
|
||||
|
||||
// These semantic wrappers don't change the constant value.
|
||||
case CARBON_KIND(SemIR::BindAlias typed_inst): {
|
||||
return eval_context.GetConstantValue(typed_inst.value_id);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user