diff --git a/xls/dslx/type_system/deduce_expr.cc b/xls/dslx/type_system/deduce_expr.cc index 99ed56c22c..3400ae03ce 100644 --- a/xls/dslx/type_system/deduce_expr.cc +++ b/xls/dslx/type_system/deduce_expr.cc @@ -164,7 +164,7 @@ static absl::StatusOr> DeduceArrayTypeAnnotation( // numbers. This will become more generalized with type inference 2.0. static absl::StatusOr> DeduceArrayInternal( const Array* node, DeduceCtx* ctx) { - VLOG(5) << "DeduceArray; node: " << node->ToString(); + VLOG(5) << "DeduceArrayInternal; node: " << node->ToString(); if (node->members().empty()) { return DeduceEmptyArray(node, ctx); @@ -175,6 +175,7 @@ static absl::StatusOr> DeduceArrayInternal( DeduceArrayTypeAnnotation(node, ctx)); if (annotated != nullptr) { + VLOG(5) << "DeduceArrayInternal; annotated: " << annotated->ToString(); // If the array type is annotated, as a user convenience, we propagate the // element type to bare (unannotated) literal numbers contained in the // array. @@ -206,11 +207,21 @@ static absl::StatusOr> DeduceArrayInternal( } } + std::unique_ptr inferred_element_type = + member_types[0]->CloneToUnique(); + // Check that we're not making an array of types, as arrays cannot hold types. + if (inferred_element_type->IsMeta()) { + return TypeInferenceErrorStatus( + node->span(), inferred_element_type.get(), + "Array element cannot be a metatype because arrays cannot hold types.", + ctx->file_table()); + } + // Check that we're not making a token array, as tokens must not alias, and // arrays obscure their provenance as they are aggregate types. - if (member_types[0]->HasToken()) { + if (inferred_element_type->HasToken()) { return TypeInferenceErrorStatus( - node->span(), member_types[0].get(), + node->span(), inferred_element_type.get(), "Types with tokens cannot be placed in arrays.", ctx->file_table()); } @@ -219,7 +230,7 @@ static absl::StatusOr> DeduceArrayInternal( // Try to infer the array type from the first member. std::unique_ptr inferred = std::make_unique( - member_types[0]->CloneToUnique(), member_types_dim); + std::move(inferred_element_type), member_types_dim); if (annotated == nullptr) { if (node->has_ellipsis()) { diff --git a/xls/dslx/type_system/type.cc b/xls/dslx/type_system/type.cc index 7d3daec657..97d1171e69 100644 --- a/xls/dslx/type_system/type.cc +++ b/xls/dslx/type_system/type.cc @@ -856,6 +856,14 @@ absl::StatusOr TupleType::GetTotalBitCount() const { // -- ArrayType +ArrayType::ArrayType(std::unique_ptr element_type, const TypeDim& size) + : element_type_(std::move(element_type)), size_(size) { + CHECK(!element_type_->IsMeta()) + << "Array element cannot be a metatype because arrays cannot hold types; " + "got: " + << element_type_->ToStringInternal(FullyQualify::kNo, nullptr); +} + absl::StatusOr> ArrayType::MapSize( const std::function(TypeDim)>& f) const { XLS_ASSIGN_OR_RETURN(std::unique_ptr new_element_type, diff --git a/xls/dslx/type_system/type.h b/xls/dslx/type_system/type.h index 356d12c248..91cd44a4e2 100644 --- a/xls/dslx/type_system/type.h +++ b/xls/dslx/type_system/type.h @@ -751,11 +751,7 @@ class TupleType : public Type { // These will nest in the case of multidimensional arrays. class ArrayType : public Type { public: - ArrayType(std::unique_ptr element_type, const TypeDim& size) - : element_type_(std::move(element_type)), size_(size) { - CHECK(!element_type_->IsMeta()) - << element_type_->ToStringInternal(FullyQualify::kNo, nullptr); - } + ArrayType(std::unique_ptr element_type, const TypeDim& size); absl::Status Accept(TypeVisitor& v) const override { return v.HandleArray(*this); diff --git a/xls/dslx/type_system/typecheck_module_test.cc b/xls/dslx/type_system/typecheck_module_test.cc index 3a2b8d5134..84a12dc729 100644 --- a/xls/dslx/type_system/typecheck_module_test.cc +++ b/xls/dslx/type_system/typecheck_module_test.cc @@ -1878,6 +1878,31 @@ fn main() -> u32 { HasSubstr("Cannot pass a type as a function argument."))); } +TEST(TypecheckTest, InvalidParametricTypeConstantArrayContents) { + constexpr std::string_view kImported = R"( +pub struct MyStruct { + a: bits[A], + b: bits[B], +} +)"; + constexpr std::string_view kProgram = R"( +import imported; + +const MY_ARRAY = imported::MyStruct[2]:[ + imported::MyStruct +]; +)"; + auto import_data = CreateImportDataForTest(); + XLS_ASSERT_OK_AND_ASSIGN( + TypecheckedModule module, + ParseAndTypecheck(kImported, "imported.x", "imported", &import_data)); + absl::StatusOr result = + ParseAndTypecheck(kProgram, "fake_main_path.x", "main", &import_data); + EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument, + HasSubstr("Array element cannot be a metatype"))) + << result.status(); +} + TEST(TypecheckErrorTest, ArraySizeOfBitsType) { EXPECT_THAT( Typecheck(R"(