Check for a symbolic value only if normal value lookup fails. (#1326)

This causes compile-time evaluation to give the same result as runtime
evaluation wherever possible. In particular, referencing a generic
parameter at compile time will resolve to the actual value if we're
evaluating a call to the enclosing function so a value for the
parameter is available in the call frame.

Clean up recently-added support for `SymbolicWitness`es using this.
This commit is contained in:
Richard Smith
2022-06-13 14:41:19 -07:00
committed by GitHub
parent bc40bdc279
commit 392182cee1
5 changed files with 52 additions and 16 deletions
+17 -5
View File
@@ -52,11 +52,9 @@ void ActionStack::Initialize(ValueNodeView value_node,
auto ActionStack::ValueOfNode(ValueNodeView value_node,
SourceLocation source_loc) const
-> ErrorOr<Nonnull<const Value*>> {
std::optional<const Value*> value = (phase_ == Phase::CompileTime)
? value_node.symbolic_identity()
: value_node.constant_value();
if (value.has_value()) {
return *value;
std::optional<const Value*> constant_value = value_node.constant_value();
if (constant_value.has_value()) {
return *constant_value;
}
for (const std::unique_ptr<Action>& action : todo_) {
// TODO: have static name resolution identify the scope of value_node
@@ -77,6 +75,20 @@ auto ActionStack::ValueOfNode(ValueNodeView value_node,
return *result;
}
}
// We don't know the value of this node, but at compile time we may still be
// able to form a symbolic value for it. For example, in
//
// fn F[T:! Type](x: T) {}
//
// ... we don't know the value of `T` but can still symbolically evaluate it
// to a `VariableType`. At runtime we need actual values.
if (phase_ == Phase::CompileTime) {
std::optional<const Value*> symbolic_identity =
value_node.symbolic_identity();
if (symbolic_identity.has_value()) {
return *symbolic_identity;
}
}
// TODO: Move these errors to compile time and explain them more clearly.
return RuntimeError(source_loc)
<< "could not find `" << value_node.base() << "`";