|
|
@@ -32,7 +32,9 @@
|
|
|
#include "explorer/interpreter/impl_scope.h"
|
|
|
#include "explorer/interpreter/interpreter.h"
|
|
|
#include "explorer/interpreter/pattern_analysis.h"
|
|
|
+#include "explorer/interpreter/pattern_match.h"
|
|
|
#include "explorer/interpreter/type_structure.h"
|
|
|
+#include "explorer/interpreter/type_utils.h"
|
|
|
#include "llvm/ADT/DenseSet.h"
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
#include "llvm/ADT/ScopeExit.h"
|
|
|
@@ -81,134 +83,6 @@ static auto ExpectPointerType(SourceLocation source_loc,
|
|
|
return Success();
|
|
|
}
|
|
|
|
|
|
-// Returns whether the value is a type whose values are themselves known to be
|
|
|
-// types.
|
|
|
-static auto IsTypeOfType(Nonnull<const Value*> value) -> bool {
|
|
|
- switch (value->kind()) {
|
|
|
- case Value::Kind::IntValue:
|
|
|
- case Value::Kind::DestructorValue:
|
|
|
- case Value::Kind::FunctionValue:
|
|
|
- case Value::Kind::BoundMethodValue:
|
|
|
- case Value::Kind::PointerValue:
|
|
|
- case Value::Kind::LocationValue:
|
|
|
- case Value::Kind::ReferenceExpressionValue:
|
|
|
- case Value::Kind::BoolValue:
|
|
|
- case Value::Kind::TupleValue:
|
|
|
- case Value::Kind::StructValue:
|
|
|
- case Value::Kind::NominalClassValue:
|
|
|
- case Value::Kind::AlternativeValue:
|
|
|
- case Value::Kind::BindingPlaceholderValue:
|
|
|
- case Value::Kind::AddrValue:
|
|
|
- case Value::Kind::AlternativeConstructorValue:
|
|
|
- case Value::Kind::StringValue:
|
|
|
- case Value::Kind::UninitializedValue:
|
|
|
- case Value::Kind::ImplWitness:
|
|
|
- case Value::Kind::BindingWitness:
|
|
|
- case Value::Kind::ConstraintWitness:
|
|
|
- case Value::Kind::ConstraintImplWitness:
|
|
|
- case Value::Kind::ParameterizedEntityName:
|
|
|
- case Value::Kind::MemberName:
|
|
|
- // These are values, not types.
|
|
|
- return false;
|
|
|
- case Value::Kind::IntType:
|
|
|
- case Value::Kind::BoolType:
|
|
|
- case Value::Kind::FunctionType:
|
|
|
- case Value::Kind::PointerType:
|
|
|
- case Value::Kind::StructType:
|
|
|
- case Value::Kind::NominalClassType:
|
|
|
- case Value::Kind::MixinPseudoType:
|
|
|
- case Value::Kind::ChoiceType:
|
|
|
- case Value::Kind::StringType:
|
|
|
- case Value::Kind::StaticArrayType:
|
|
|
- case Value::Kind::TupleType:
|
|
|
- case Value::Kind::TypeOfMixinPseudoType:
|
|
|
- case Value::Kind::TypeOfParameterizedEntityName:
|
|
|
- case Value::Kind::TypeOfMemberName:
|
|
|
- case Value::Kind::TypeOfNamespaceName:
|
|
|
- // These are types whose values are not types.
|
|
|
- return false;
|
|
|
- case Value::Kind::AutoType:
|
|
|
- case Value::Kind::VariableType:
|
|
|
- case Value::Kind::AssociatedConstant:
|
|
|
- // A value of one of these types could be a type, but isn't known to be.
|
|
|
- return false;
|
|
|
- case Value::Kind::TypeType:
|
|
|
- case Value::Kind::InterfaceType:
|
|
|
- case Value::Kind::NamedConstraintType:
|
|
|
- case Value::Kind::ConstraintType:
|
|
|
- // A value of one of these types is itself always a type.
|
|
|
- return true;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// Returns whether the value is a type value, such as might be a valid type for
|
|
|
-// a syntactic pattern. This includes types involving `auto`. Use
|
|
|
-// `TypeContainsAuto` to determine if a type involves `auto`.
|
|
|
-static auto IsType(Nonnull<const Value*> value) -> bool {
|
|
|
- switch (value->kind()) {
|
|
|
- case Value::Kind::IntValue:
|
|
|
- case Value::Kind::FunctionValue:
|
|
|
- case Value::Kind::DestructorValue:
|
|
|
- case Value::Kind::BoundMethodValue:
|
|
|
- case Value::Kind::PointerValue:
|
|
|
- case Value::Kind::LocationValue:
|
|
|
- case Value::Kind::ReferenceExpressionValue:
|
|
|
- case Value::Kind::BoolValue:
|
|
|
- case Value::Kind::TupleValue:
|
|
|
- case Value::Kind::StructValue:
|
|
|
- case Value::Kind::NominalClassValue:
|
|
|
- case Value::Kind::AlternativeValue:
|
|
|
- case Value::Kind::BindingPlaceholderValue:
|
|
|
- case Value::Kind::AddrValue:
|
|
|
- case Value::Kind::AlternativeConstructorValue:
|
|
|
- case Value::Kind::StringValue:
|
|
|
- case Value::Kind::UninitializedValue:
|
|
|
- case Value::Kind::ImplWitness:
|
|
|
- case Value::Kind::BindingWitness:
|
|
|
- case Value::Kind::ConstraintWitness:
|
|
|
- case Value::Kind::ConstraintImplWitness:
|
|
|
- case Value::Kind::ParameterizedEntityName:
|
|
|
- case Value::Kind::MemberName:
|
|
|
- return false;
|
|
|
- case Value::Kind::IntType:
|
|
|
- case Value::Kind::BoolType:
|
|
|
- case Value::Kind::TypeType:
|
|
|
- case Value::Kind::PointerType:
|
|
|
- case Value::Kind::FunctionType:
|
|
|
- case Value::Kind::StructType:
|
|
|
- case Value::Kind::TupleType:
|
|
|
- case Value::Kind::NominalClassType:
|
|
|
- case Value::Kind::InterfaceType:
|
|
|
- case Value::Kind::NamedConstraintType:
|
|
|
- case Value::Kind::ConstraintType:
|
|
|
- case Value::Kind::ChoiceType:
|
|
|
- case Value::Kind::VariableType:
|
|
|
- case Value::Kind::StringType:
|
|
|
- case Value::Kind::StaticArrayType:
|
|
|
- case Value::Kind::AutoType:
|
|
|
- return true;
|
|
|
- case Value::Kind::TypeOfParameterizedEntityName:
|
|
|
- case Value::Kind::TypeOfMemberName:
|
|
|
- case Value::Kind::TypeOfMixinPseudoType:
|
|
|
- case Value::Kind::TypeOfNamespaceName:
|
|
|
- // These aren't first-class types, but they are still types.
|
|
|
- return true;
|
|
|
- case Value::Kind::AssociatedConstant: {
|
|
|
- // An associated type is an associated constant whose type is a
|
|
|
- // type-of-type.
|
|
|
- const auto& assoc = cast<AssociatedConstant>(*value);
|
|
|
- // TODO: Should we substitute in the arguments? Given
|
|
|
- // interface I(T:! type) { let V:! T; }
|
|
|
- // ... is T.(I(type).V) considered to be a type?
|
|
|
- return IsTypeOfType(&assoc.constant().static_type());
|
|
|
- }
|
|
|
- case Value::Kind::MixinPseudoType:
|
|
|
- // Mixin type is a second-class type that cannot be used
|
|
|
- // within a type annotation expression.
|
|
|
- return false;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
// Expect that a type is complete. Issue a diagnostic if not.
|
|
|
static auto ExpectCompleteType(SourceLocation source_loc,
|
|
|
std::string_view context,
|
|
|
@@ -323,76 +197,6 @@ static auto ExpectConcreteType(SourceLocation source_loc,
|
|
|
return Success();
|
|
|
}
|
|
|
|
|
|
-// Returns whether *value represents the type of a Carbon value, as
|
|
|
-// opposed to a type pattern or a non-type value.
|
|
|
-static auto TypeIsDeduceable(Nonnull<const Value*> type) -> bool {
|
|
|
- CARBON_CHECK(IsType(type)) << "expected a type, but found " << *type;
|
|
|
-
|
|
|
- switch (type->kind()) {
|
|
|
- case Value::Kind::IntValue:
|
|
|
- case Value::Kind::FunctionValue:
|
|
|
- case Value::Kind::DestructorValue:
|
|
|
- case Value::Kind::BoundMethodValue:
|
|
|
- case Value::Kind::PointerValue:
|
|
|
- case Value::Kind::LocationValue:
|
|
|
- case Value::Kind::ReferenceExpressionValue:
|
|
|
- case Value::Kind::BoolValue:
|
|
|
- case Value::Kind::TupleValue:
|
|
|
- case Value::Kind::StructValue:
|
|
|
- case Value::Kind::NominalClassValue:
|
|
|
- case Value::Kind::AlternativeValue:
|
|
|
- case Value::Kind::BindingPlaceholderValue:
|
|
|
- case Value::Kind::AddrValue:
|
|
|
- case Value::Kind::AlternativeConstructorValue:
|
|
|
- case Value::Kind::StringValue:
|
|
|
- case Value::Kind::UninitializedValue:
|
|
|
- case Value::Kind::ImplWitness:
|
|
|
- case Value::Kind::BindingWitness:
|
|
|
- case Value::Kind::ConstraintWitness:
|
|
|
- case Value::Kind::ConstraintImplWitness:
|
|
|
- case Value::Kind::ParameterizedEntityName:
|
|
|
- case Value::Kind::MemberName:
|
|
|
- case Value::Kind::MixinPseudoType:
|
|
|
- CARBON_FATAL() << "non-type value";
|
|
|
- case Value::Kind::IntType:
|
|
|
- case Value::Kind::BoolType:
|
|
|
- case Value::Kind::TypeType:
|
|
|
- case Value::Kind::VariableType:
|
|
|
- case Value::Kind::StringType:
|
|
|
- case Value::Kind::TypeOfMixinPseudoType:
|
|
|
- case Value::Kind::TypeOfParameterizedEntityName:
|
|
|
- case Value::Kind::TypeOfMemberName:
|
|
|
- case Value::Kind::TypeOfNamespaceName:
|
|
|
- // These types do not contain other types.
|
|
|
- return false;
|
|
|
- case Value::Kind::FunctionType:
|
|
|
- case Value::Kind::NominalClassType:
|
|
|
- case Value::Kind::InterfaceType:
|
|
|
- case Value::Kind::NamedConstraintType:
|
|
|
- case Value::Kind::ConstraintType:
|
|
|
- case Value::Kind::ChoiceType:
|
|
|
- case Value::Kind::AssociatedConstant:
|
|
|
- // These types can contain other types, but those types can't involve
|
|
|
- // `auto`.
|
|
|
- return false;
|
|
|
- case Value::Kind::AutoType:
|
|
|
- return true;
|
|
|
- case Value::Kind::StructType:
|
|
|
- return llvm::any_of(
|
|
|
- llvm::map_range(cast<StructType>(type)->fields(),
|
|
|
- [](const NamedValue& v) { return v.value; }),
|
|
|
- TypeIsDeduceable);
|
|
|
- case Value::Kind::TupleType:
|
|
|
- return llvm::any_of(cast<TupleType>(type)->elements(), TypeIsDeduceable);
|
|
|
- case Value::Kind::PointerType:
|
|
|
- return TypeIsDeduceable(&cast<PointerType>(type)->pointee_type());
|
|
|
- case Value::Kind::StaticArrayType:
|
|
|
- const auto* array_type = cast<StaticArrayType>(type);
|
|
|
- return !array_type->has_size() ||
|
|
|
- TypeIsDeduceable(&array_type->element_type());
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
// Returns whether `type` is a placeholder type, which is a second-class type
|
|
|
// that cannot be the type of a binding but can be the type of an expression.
|
|
|
static auto IsPlaceholderType(Nonnull<const Value*> type) -> bool {
|
|
|
@@ -401,12 +205,6 @@ static auto IsPlaceholderType(Nonnull<const Value*> type) -> bool {
|
|
|
TypeOfMixinPseudoType, TypeOfNamespaceName>(type);
|
|
|
}
|
|
|
|
|
|
-// Returns whether `value` is a concrete type, which would be valid as the
|
|
|
-// static type of an expression. This is currently any type other than `auto`.
|
|
|
-static auto IsNonDeduceableType(Nonnull<const Value*> value) -> bool {
|
|
|
- return IsType(value) && !TypeIsDeduceable(value);
|
|
|
-}
|
|
|
-
|
|
|
static auto ExpectResolvedBindingType(const BindingPattern& binding,
|
|
|
Nonnull<const Value*> type)
|
|
|
-> ErrorOr<Success> {
|
|
|
@@ -4459,24 +4257,6 @@ auto TypeChecker::TypeCheckWhereClause(Nonnull<WhereClause*> clause,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// Returns the list size for type deduction.
|
|
|
-static auto GetSize(Nonnull<const Value*> from) -> size_t {
|
|
|
- switch (from->kind()) {
|
|
|
- case Value::Kind::TupleType:
|
|
|
- case Value::Kind::TupleValue: {
|
|
|
- const auto& from_tup = cast<TupleValueBase>(*from);
|
|
|
- return from_tup.elements().size();
|
|
|
- }
|
|
|
- case Value::Kind::StaticArrayType: {
|
|
|
- const auto& from_arr = cast<StaticArrayType>(*from);
|
|
|
- CARBON_CHECK(from_arr.has_size());
|
|
|
- return from_arr.size();
|
|
|
- }
|
|
|
- default:
|
|
|
- return 0;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
auto TypeChecker::TypeCheckPattern(
|
|
|
Nonnull<Pattern*> p, PatternRequirements requirements,
|
|
|
std::optional<Nonnull<const Value*>> expected, ImplScope& impl_scope,
|