Make type contexts expect a value of type Type. (#2357)

In particular, this means that a type can implement `ImplicitAs(Type)` and have values of that type behave like types.

This implies that `()` and `{}` are no longer types. They are now values whose type is the result of converting `()` or `{}` to type `Type`, as has been discussed recently and seems to be the supported direction. This fixes various cases where these types were previously mishandled.
This commit is contained in:
Richard Smith
2022-10-28 08:20:49 -07:00
committed by GitHub
parent f46eaf49a2
commit 0219218b01
40 changed files with 674 additions and 319 deletions
+19 -14
View File
@@ -21,6 +21,7 @@ namespace Carbon {
using llvm::cast;
using llvm::dyn_cast;
using llvm::dyn_cast_or_null;
using llvm::isa;
auto StructValue::FindField(std::string_view name) const
-> std::optional<Nonnull<const Value*>> {
@@ -87,13 +88,8 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
case Value::Kind::NominalClassValue: {
const auto& object = cast<NominalClassValue>(*v);
// 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 (const auto* struct_value = dyn_cast<StructValue>(&object.inits())) {
field = struct_value->FindField(f);
}
if (field.has_value()) {
if (std::optional<Nonnull<const Value*>> field =
cast<StructValue>(object.inits()).FindField(f)) {
return *field;
} else {
// Look for a method in the object's class
@@ -185,9 +181,10 @@ static auto SetFieldImpl(
path_end, field_value, source_loc));
return arena->New<NominalClassValue>(&object.type(), inits);
}
case Value::Kind::TupleType:
case Value::Kind::TupleValue: {
std::vector<Nonnull<const Value*>> elements =
cast<TupleValue>(*value).elements();
cast<TupleValueBase>(*value).elements();
// TODO(geoffromer): update FieldPath to hold integers as well as strings.
int index = std::stoi(std::string((*path_begin).name()));
if (index < 0 || static_cast<size_t>(index) >= elements.size()) {
@@ -197,7 +194,11 @@ static auto SetFieldImpl(
CARBON_ASSIGN_OR_RETURN(
elements[index], SetFieldImpl(arena, elements[index], path_begin + 1,
path_end, field_value, source_loc));
return arena->New<TupleValue>(elements);
if (isa<TupleType>(value)) {
return arena->New<TupleType>(elements);
} else {
return arena->New<TupleValue>(elements);
}
}
default:
CARBON_FATAL() << "field access not allowed for value " << *value;
@@ -272,10 +273,12 @@ void Value::Print(llvm::raw_ostream& out) const {
out << cast<NominalClassType>(s.type()).declaration().name() << s.inits();
break;
}
case Value::Kind::TupleType:
case Value::Kind::TupleValue: {
out << "(";
llvm::ListSeparator sep;
for (Nonnull<const Value*> element : cast<TupleValue>(*this).elements()) {
for (Nonnull<const Value*> element :
cast<TupleValueBase>(*this).elements()) {
out << sep << *element;
}
out << ")";
@@ -705,9 +708,10 @@ auto TypeEqual(Nonnull<const Value*> t1, Nonnull<const Value*> t2,
}
case Value::Kind::ChoiceType:
return cast<ChoiceType>(*t1).name() == cast<ChoiceType>(*t2).name();
case Value::Kind::TupleType:
case Value::Kind::TupleValue: {
const auto& tup1 = cast<TupleValue>(*t1);
const auto& tup2 = cast<TupleValue>(*t2);
const auto& tup1 = cast<TupleValueBase>(*t1);
const auto& tup2 = cast<TupleValueBase>(*t2);
if (tup1.elements().size() != tup2.elements().size()) {
return false;
}
@@ -806,11 +810,12 @@ auto ValueStructurallyEqual(
body1.has_value() == body2.has_value() &&
(!body1.has_value() || *body1 == *body2);
}
case Value::Kind::TupleType:
case Value::Kind::TupleValue: {
const std::vector<Nonnull<const Value*>>& elements1 =
cast<TupleValue>(*v1).elements();
cast<TupleValueBase>(*v1).elements();
const std::vector<Nonnull<const Value*>>& elements2 =
cast<TupleValue>(*v2).elements();
cast<TupleValueBase>(*v2).elements();
if (elements1.size() != elements2.size()) {
return false;
}