mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 08:54:47 +01:00
Explorer: Support class subtyping (#2460)
Features: * Adds support for [subtyping](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/classes.md#subtyping) for local variables, and function parameters Changes: * Update function parameter `Deduce` to handle subtyping * Update `InstantiateType` to support `PointerType` * Update `Convert` to support convertion from child class to a base class Relates to #1881 Co-authored-by: Jon Ross-Perkins <jperkins@google.com> Co-authored-by: Geoff Romer <gromer@google.com>
This commit is contained in:
co-authored by
Jon Ross-Perkins
Geoff Romer
parent
8e6d48004b
commit
9299e51511
@@ -641,6 +641,13 @@ auto Interpreter::InstantiateType(Nonnull<const Value*> type,
|
||||
EvalAssociatedConstant(cast<AssociatedConstant>(type), source_loc));
|
||||
return type_value;
|
||||
}
|
||||
case Value::Kind::PointerType: {
|
||||
const auto* ptr = cast<PointerType>(type);
|
||||
CARBON_ASSIGN_OR_RETURN(
|
||||
const auto* actual_type,
|
||||
InstantiateType(&ptr->pointee_type(), source_loc));
|
||||
return arena_->New<PointerType>(actual_type);
|
||||
}
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
@@ -712,7 +719,6 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
|
||||
case Value::Kind::FunctionValue:
|
||||
case Value::Kind::DestructorValue:
|
||||
case Value::Kind::BoundMethodValue:
|
||||
case Value::Kind::PointerValue:
|
||||
case Value::Kind::LValue:
|
||||
case Value::Kind::BoolValue:
|
||||
case Value::Kind::NominalClassValue:
|
||||
@@ -863,6 +869,40 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
|
||||
}
|
||||
return Convert(value, destination_type, source_loc);
|
||||
}
|
||||
case Value::Kind::PointerValue: {
|
||||
if (destination_type->kind() != Value::Kind::PointerType ||
|
||||
cast<PointerType>(destination_type)->pointee_type().kind() !=
|
||||
Value::Kind::NominalClassType) {
|
||||
// No conversion needed.
|
||||
return value;
|
||||
}
|
||||
|
||||
// Get pointee value.
|
||||
const auto* src_ptr = cast<PointerValue>(value);
|
||||
CARBON_ASSIGN_OR_RETURN(const auto* pointee,
|
||||
heap_.Read(src_ptr->address(), source_loc))
|
||||
CARBON_CHECK(pointee->kind() == Value::Kind::NominalClassValue)
|
||||
<< "Unexpected pointer type";
|
||||
|
||||
const auto* dest_ptr = cast<PointerType>(destination_type);
|
||||
std::optional<Nonnull<const NominalClassValue*>> class_subobj =
|
||||
cast<NominalClassValue>(pointee);
|
||||
auto new_addr = src_ptr->address();
|
||||
while (class_subobj) {
|
||||
if (TypeEqual(&(*class_subobj)->type(), &dest_ptr->pointee_type(),
|
||||
std::nullopt)) {
|
||||
return arena_->New<PointerValue>(new_addr);
|
||||
}
|
||||
class_subobj = (*class_subobj)->base();
|
||||
new_addr = new_addr.ElementAddress(
|
||||
arena_->New<BaseElement>(&dest_ptr->pointee_type()));
|
||||
}
|
||||
|
||||
// Unable to resolve, return as-is.
|
||||
// TODO: Produce error instead once we can properly substitute
|
||||
// parameterized types for pointers in function call parameters.
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user