Repository: carbon-language/carbon-lang
File: toolchain/check/eval.cpp (C++)

Code before:
  }
  auto const_id = eval_context.GetConstantValue(inst_id);
  *phase =
      LatestPhase(*phase, GetPhase(eval_context.constant_values(), const_id));
  return eval_context.constant_values().GetInstId(const_id);
}

// Gets a constant value for an `inst_id`, diagnosing when the input is not a
// constant value.
static auto RequireConstantValue(EvalContext& eval_context,
                                 SemIR::InstId inst_id, Phase* phase)
    -> SemIR::InstId {
  if (!inst_id.has_value()) {
    return SemIR::InstId::None;
  }
  auto const_id = eval_context.GetConstantValue(inst_id);
  *phase =
      LatestPhase(*phase, GetPhase(eval_context.constant_values(), const_id));
  if (const_id.is_constant()) {
    return eval_context.constant_values().GetInstId(const_id);
  }

  if (inst_id != SemIR::ErrorInst::InstId) {
    CARBON_DIAGNOSTIC(
        EvalRequiresConstantValue, Error,
        "found runtime value where a compile-time value was expected");
    eval_context.emitter().Emit(eval_context.GetDiagnosticLoc({inst_id}),
                                EvalRequiresConstantValue);
  }
  *phase = Phase::UnknownDueToError;
  return SemIR::ErrorInst::InstId;
}

// If the given instruction is constant, returns its constant value. Otherwise,
// produces an error diagnostic. When determining the phase of the result,
// ignore any dependence on `.Self`.
//
// This is used when evaluating facet types, for which `where` expressions using
// `.Self` should not be considered symbolic
// - `Interface where .Self impls I and .A = bool` -> concrete
// - `T:! type` ... `Interface where .A = T` -> symbolic, since uses `T` which
//   is symbolic and not due to `.Self`.
static auto RequireConstantValueIgnoringPeriodSelf(EvalContext& eval_context,
                                                   SemIR::InstId inst_id,
                                                   Phase* phase)
    -> SemIR::InstId {
  if (!inst_id.has_value()) {
    return SemIR::InstId::None;
  }
  Phase constant_phase = *phase;
  auto const_inst_id =

Review comment (suggestion):
This seems kind of borderline for diagnostic phrasing since it's stating the expectation (versus [diagnostic messaging](https://github.com/carbon-language/carbon-lang/blob/trunk/toolchain/docs/diagnostics.md#diagnostic-message-style-guide), "Diagnostics should describe the situation the toolchain observed. The language rule violated can be mentioned if it wouldn't otherwise be clear.")

At least I'd suggest something that drops things like "a" and "was", e.g.:

```suggestion
        "expression is runtime");
````

```suggestion
        "expression is runtime; expected constant");
````

Note partly avoiding compile-time, per https://github.com/carbon-language/carbon-lang/pull/2964

But, not really strongly opinionated here -- I think we're going to have to go back and rephrase diagnostics in general

Code after:
    return SemIR::InstId::None;
  }
  auto const_id = eval_context.GetConstantValue(inst_id);
  *phase =
      LatestPhase(*phase, GetPhase(eval_context.constant_values(), const_id));
  return eval_context.constant_values().GetInstId(const_id);
}

// Gets a constant value for an `inst_id`, diagnosing when the input is not a
// constant value.
static auto RequireConstantValue(EvalContext& eval_context,
                                 SemIR::InstId inst_id, Phase* phase)
    -> SemIR::InstId {
  if (!inst_id.has_value()) {
    return SemIR::InstId::None;
  }
  auto const_id = eval_context.GetConstantValue(inst_id);
  *phase =
      LatestPhase(*phase, GetPhase(eval_context.constant_values(), const_id));
  if (const_id.is_constant()) {
    return eval_context.constant_values().GetInstId(const_id);
  }

  if (inst_id != SemIR::ErrorInst::InstId) {
    CARBON_DIAGNOSTIC(EvalRequiresConstantValue, Error,
                      "expression is runtime; expected constant");
    eval_context.emitter().Emit(eval_context.GetDiagnosticLoc({inst_id}),
                                EvalRequiresConstantValue);
  }
  *phase = Phase::UnknownDueToError;
  return SemIR::ErrorInst::InstId;
}

// If the given instruction is constant, returns its constant value. Otherwise,
// produces an error diagnostic. When determining the phase of the result,
// ignore any dependence on `.Self`.
//
// This is used when evaluating facet types, for which `where` expressions using
// `.Self` should not be considered symbolic
// - `Interface where .Self impls I and .A = bool` -> concrete
// - `T:! type` ... `Interface where .A = T` -> symbolic, since uses `T` which
//   is symbolic and not due to `.Self`.
static auto RequireConstantValueIgnoringPeriodSelf(EvalContext& eval_context,
                                                   SemIR::InstId inst_id,
                                                   Phase* phase)
    -> SemIR::InstId {
  if (!inst_id.has_value()) {
    return SemIR::InstId::None;
  }
  Phase constant_phase = *phase;
  auto const_inst_id =