mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 11:21:05 +01:00
Produce a class value when converting {} to class type. (#1265)
Previously we missed this special case because {} results in a
StructType value not a StructValue value.
This commit is contained in:
@@ -494,7 +494,6 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
|
||||
case Value::Kind::FunctionType:
|
||||
case Value::Kind::PointerType:
|
||||
case Value::Kind::AutoType:
|
||||
case Value::Kind::StructType:
|
||||
case Value::Kind::NominalClassType:
|
||||
case Value::Kind::InterfaceType:
|
||||
case Value::Kind::Witness:
|
||||
@@ -548,6 +547,19 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
|
||||
<< *destination_type;
|
||||
}
|
||||
}
|
||||
case Value::Kind::StructType: {
|
||||
// The value `{}` has kind `StructType` not `StructValue`. This value can
|
||||
// be converted to an empty class type.
|
||||
if (auto* destination_class_type =
|
||||
dyn_cast<NominalClassType>(destination_type)) {
|
||||
CARBON_CHECK(cast<StructType>(*value).fields().empty())
|
||||
<< "only an empty struct type value converts to class type";
|
||||
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> inst_dest,
|
||||
InstantiateType(destination_type, source_loc));
|
||||
return arena_->New<NominalClassValue>(inst_dest, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
case Value::Kind::TupleValue: {
|
||||
const auto& tuple = cast<TupleValue>(value);
|
||||
std::vector<Nonnull<const Value*>> destination_element_types;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
namespace Carbon {
|
||||
|
||||
using llvm::cast;
|
||||
using llvm::dyn_cast;
|
||||
|
||||
auto StructValue::FindField(const std::string& name) const
|
||||
-> std::optional<Nonnull<const Value*>> {
|
||||
@@ -72,9 +73,13 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
|
||||
}
|
||||
case Value::Kind::NominalClassValue: {
|
||||
const auto& object = cast<NominalClassValue>(*v);
|
||||
// Look for a field
|
||||
std::optional<Nonnull<const Value*>> field =
|
||||
cast<StructValue>(object.inits()).FindField(f);
|
||||
// Look for a field.
|
||||
// Note that the value representation of an empty class is a
|
||||
// `StructType`, not a `StructValue`.
|
||||
std::optional<Nonnull<const Value*>> field;
|
||||
if (auto* struct_value = dyn_cast<StructValue>(&object.inits())) {
|
||||
field = struct_value->FindField(f);
|
||||
}
|
||||
if (field.has_value()) {
|
||||
return *field;
|
||||
} else {
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// RUN: %{explorer} %s 2>&1 | \
|
||||
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s
|
||||
// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
|
||||
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s
|
||||
// AUTOUPDATE: %{explorer} %s
|
||||
// CHECK: result: 0
|
||||
|
||||
package ExplorerTest api;
|
||||
|
||||
class A { fn F[me: Self]() -> i32 { return 0; } }
|
||||
|
||||
fn Main() -> i32 {
|
||||
// {} is a bit strange; its type is {}. Make sure we can properly convert a
|
||||
// value of type {} to type TypeOfClassType.
|
||||
var a: A = {};
|
||||
return a.F();
|
||||
}
|
||||
Reference in New Issue
Block a user