From a00d2c2c2150f88f17b3df24fff6ce586ca98b5c Mon Sep 17 00:00:00 2001 From: Rich McKeever Date: Fri, 10 Jan 2025 16:14:07 -0800 Subject: [PATCH] Fix the type info for elements of arrays and tuples in type_system_v2. In a case like `const X: u32[3] = [1, 2, 3]`, we were previously allowing the literals in the array to just assume the unified RHS element type of u2, only factoring the LHS into the overall type of [1, 2, 3]. PiperOrigin-RevId: 714263472 --- xls/dslx/type_system_v2/BUILD | 1 + .../inference_table_to_type_info.cc | 116 +- .../type_system_v2/typecheck_module_v2.cc | 45 +- .../typecheck_module_v2_test.cc | 1034 ++++++++--------- 4 files changed, 576 insertions(+), 620 deletions(-) diff --git a/xls/dslx/type_system_v2/BUILD b/xls/dslx/type_system_v2/BUILD index 4aade3baaf..7b8f56e405 100644 --- a/xls/dslx/type_system_v2/BUILD +++ b/xls/dslx/type_system_v2/BUILD @@ -71,6 +71,7 @@ cc_library( "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", + "@com_google_absl//absl/functional:function_ref", "@com_google_absl//absl/log", "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", diff --git a/xls/dslx/type_system_v2/inference_table_to_type_info.cc b/xls/dslx/type_system_v2/inference_table_to_type_info.cc index dab3e615d1..d381295f93 100644 --- a/xls/dslx/type_system_v2/inference_table_to_type_info.cc +++ b/xls/dslx/type_system_v2/inference_table_to_type_info.cc @@ -29,6 +29,7 @@ #include "absl/algorithm/container.h" #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" +#include "absl/functional/function_ref.h" #include "absl/log/check.h" #include "absl/log/log.h" #include "absl/status/status.h" @@ -593,20 +594,22 @@ class InferenceTableConverter { XLS_ASSIGN_OR_RETURN( std::vector actual_arg_annotations, table_.GetTypeAnnotationsForTypeVariable(*actual_arg_type_var)); - XLS_RETURN_IF_ERROR( - ResolveVariableTypeAnnotations(invocation, actual_arg_annotations)); TypeInfo* actual_arg_ti = base_type_info_; if (invocation->caller_invocation().has_value()) { actual_arg_ti = invocation_type_info_.at(*invocation->caller_invocation()); } + // The type variable for the actual argument should have at least one // annotation associated with it that came from the formal argument and is // therefore dependent on the parametric we are solving for. Let's unify // just the independent annotations(s) for the purposes of solving for the // variable. - RemoveAnnotationsReferringToNamesWithoutTypeInfo(actual_arg_ti, - actual_arg_annotations); + auto accept_predicate = [&](const TypeAnnotation* annotation) { + return !HasAnyReferencesWithMissingTypeInfo(actual_arg_ti, annotation); + }; + XLS_RETURN_IF_ERROR(ResolveVariableTypeAnnotations( + invocation, actual_arg_annotations, accept_predicate)); if (actual_arg_annotations.empty()) { VLOG(5) << "The actual argument type variable: " << (*actual_arg_type_var)->ToString() @@ -693,15 +696,21 @@ class InferenceTableConverter { // type annotations that have been associated with the given type variable. If // the information has unreconcilable conflicts, returns an error. The given // `parametric_invocation` argument is used as a context for the evaluation of - // any expressions inside the type annotations. + // any expressions inside the type annotations. If an `accept_predicate` is + // specified, then annotations not accepted by the predicate are ignored. absl::StatusOr UnifyTypeAnnotations( std::optional parametric_invocation, - const NameRef* type_variable, const Span& span) { + const NameRef* type_variable, const Span& span, + std::optional> + accept_predicate = std::nullopt) { VLOG(5) << "Unifying type annotations for variable " << type_variable->ToString(); XLS_ASSIGN_OR_RETURN( std::vector annotations, table_.GetTypeAnnotationsForTypeVariable(type_variable)); + if (accept_predicate.has_value()) { + FilterAnnotations(annotations, *accept_predicate); + } XLS_ASSIGN_OR_RETURN( const TypeAnnotation* result, UnifyTypeAnnotations(parametric_invocation, annotations, span)); @@ -913,10 +922,14 @@ class InferenceTableConverter { // Returns `annotation` with any `TypeVariableTypeAnnotation`s replaced with // the unifications of the corresponding variables. The original `annotation` // is returned if there is nothing to replace, preserving the ability to look - // it up in `auto_literal_annotations_`. + // it up in `auto_literal_annotations_`. If `accept_predicate` is specified, + // then it is used to filter the annotations associated with encountered type + // variables (the predicate is not applied to the input `annotation` itself). absl::StatusOr ResolveVariableTypeAnnotations( std::optional parametric_invocation, - const TypeAnnotation* annotation) { + const TypeAnnotation* annotation, + std::optional> + accept_predicate = std::nullopt) { bool replaced_anything = false; XLS_ASSIGN_OR_RETURN( AstNode * clone, @@ -931,7 +944,7 @@ class InferenceTableConverter { UnifyTypeAnnotations( parametric_invocation, variable_type_annotation->type_variable(), - annotation->span())); + annotation->span(), accept_predicate)); replaced_anything = true; return const_cast(unified); } @@ -946,15 +959,25 @@ class InferenceTableConverter { } // Variant that deeply resolves all `TypeVariableTypeAnnotation`s within a - // vector of annotations. + // vector of annotations. If `accept_predicate` is specified, then any + // annotations not accepted by the predicate are filtered from both + // `annotations` and the expansions of any encountered type variables. absl::Status ResolveVariableTypeAnnotations( std::optional parametric_invocation, - std::vector& annotations) { - for (int i = 0; i < annotations.size(); i++) { - XLS_ASSIGN_OR_RETURN(annotations[i], - ResolveVariableTypeAnnotations(parametric_invocation, - annotations[i])); + std::vector& annotations, + std::optional> + accept_predicate = std::nullopt) { + std::vector result; + for (const TypeAnnotation* annotation : annotations) { + if (!accept_predicate.has_value() || (*accept_predicate)(annotation)) { + XLS_ASSIGN_OR_RETURN( + const TypeAnnotation* resolved_annotation, + ResolveVariableTypeAnnotations(parametric_invocation, annotation, + accept_predicate)); + result.push_back(resolved_annotation); + } } + annotations = std::move(result); return absl::OkStatus(); } @@ -1095,36 +1118,39 @@ class InferenceTableConverter { return context_invocation; } - // Removes any annotations in the given vector that contain any `NameRef` - // whose type info has not (yet) been generated. The effective `TypeInfo` for - // each annotation is either `default_ti`; or, for invocation-scoped - // annotations, the `TypeInfo` for the relevant parametric invocation. - void RemoveAnnotationsReferringToNamesWithoutTypeInfo( - TypeInfo* default_ti, std::vector& annotations) { - annotations.erase( - std::remove_if( - annotations.begin(), annotations.end(), - [&](const TypeAnnotation* annotation) { - TypeInfo* ti = default_ti; - const auto it = - invocation_scoped_type_annotations_.find(annotation); - if (it != invocation_scoped_type_annotations_.end()) { - ti = invocation_type_info_.at(it->second); - } - FreeVariables vars = - GetFreeVariablesByLambda(annotation, [&](const NameRef& ref) { - if (!std::holds_alternative( - ref.name_def())) { - return false; - } - const NameDef* name_def = - std::get(ref.name_def()); - return !ti->GetItem(name_def).has_value() && - !ti->IsKnownConstExpr(name_def); - }); - return vars.GetFreeVariableCount() > 0; - }), - annotations.end()); + // Removes any annotations in the given vector for which `accept_predicate` + // returns false. + void FilterAnnotations( + std::vector& annotations, + absl::FunctionRef accept_predicate) { + annotations.erase(std::remove_if(annotations.begin(), annotations.end(), + [&](const TypeAnnotation* annotation) { + return !accept_predicate(annotation); + }), + annotations.end()); + } + + // Returns true if `annotation` contains any `NameRef` whose type info has not + // (yet) been generated. The effective `TypeInfo` is either `default_ti`; or, + // for invocation-scoped annotations, the `TypeInfo` for the relevant + // parametric invocation. + bool HasAnyReferencesWithMissingTypeInfo(TypeInfo* default_ti, + const TypeAnnotation* annotation) { + TypeInfo* ti = default_ti; + const auto it = invocation_scoped_type_annotations_.find(annotation); + if (it != invocation_scoped_type_annotations_.end()) { + ti = invocation_type_info_.at(it->second); + } + FreeVariables vars = + GetFreeVariablesByLambda(annotation, [&](const NameRef& ref) { + if (!std::holds_alternative(ref.name_def())) { + return false; + } + const NameDef* name_def = std::get(ref.name_def()); + return !ti->GetItem(name_def).has_value() && + !ti->IsKnownConstExpr(name_def); + }); + return vars.GetFreeVariableCount() > 0; } // Returns a `SignednessAndSize` that agrees with the two given diff --git a/xls/dslx/type_system_v2/typecheck_module_v2.cc b/xls/dslx/type_system_v2/typecheck_module_v2.cc index aee72d9688..72e04b925a 100644 --- a/xls/dslx/type_system_v2/typecheck_module_v2.cc +++ b/xls/dslx/type_system_v2/typecheck_module_v2.cc @@ -171,14 +171,18 @@ class PopulateInferenceTableVisitor : public AstNodeVisitorWithDefault { // ----------------------------------------------- // FOO (u32, (s8, u32)) T0 // (4, (-2, 5)) (var:M0, var:M1) T0 - // 4 M0 - // (-2, 5) M1 + // 4 u32 M0 + // (-2, 5) (s8, u32) M1 // // Recursive descent will ultimately put auto annotations for the literals // in the table. Upon conversion of the table to type info, unification of // the LHS annotation with the variable-based RHS annotation will be // attempted. + XLS_ASSIGN_OR_RETURN( + std::optional tuple_annotation, + GetDeclarationTypeAnnotation(node)); + // Create the M0, M1, ... variables and apply them to the members. std::vector member_types; member_types.reserve(node->members().size()); @@ -189,6 +193,10 @@ class PopulateInferenceTableVisitor : public AstNodeVisitorWithDefault { InferenceVariableKind::kType, member, GenerateInternalTypeVariableName(member))); XLS_RETURN_IF_ERROR(table_.SetTypeVariable(member, member_variable)); + if (tuple_annotation.has_value()) { + XLS_RETURN_IF_ERROR(table_.SetTypeAnnotation( + member, (*tuple_annotation)->members()[i])); + } member_types.push_back( module_.Make(member_variable)); } @@ -272,6 +280,10 @@ class PopulateInferenceTableVisitor : public AstNodeVisitorWithDefault { // this unification will fail if the array is inadequately annotated (e.g. // no explicit annotation on a zero-size or elliptical array). + XLS_ASSIGN_OR_RETURN( + std::optional array_annotation, + GetDeclarationTypeAnnotation(node)); + // An empty array can't end with an ellipsis, even if unification is // possible. if (node->has_ellipsis() && node->members().empty()) { @@ -298,6 +310,10 @@ class PopulateInferenceTableVisitor : public AstNodeVisitorWithDefault { for (Expr* member : node->members()) { XLS_RETURN_IF_ERROR( table_.SetTypeVariable(member, element_type_variable)); + if (array_annotation.has_value()) { + XLS_RETURN_IF_ERROR(table_.SetTypeAnnotation( + member, (*array_annotation)->element_type())); + } } Expr* element_count = module_.Make( node->span(), absl::StrCat(node->members().size()), NumberKind::kOther, @@ -790,6 +806,31 @@ class PopulateInferenceTableVisitor : public AstNodeVisitorWithDefault { return absl::OkStatus(); } + // Gets the explicit type annotation (of type `T`) for a node by querying the + // type variable that it shares with a declaration, if any. This must be done + // before imposing any synthetic type annotation on the value. + template + absl::StatusOr> GetDeclarationTypeAnnotation( + const AstNode* node) { + std::optional type_variable = table_.GetTypeVariable(node); + if (!type_variable.has_value()) { + return std::nullopt; + } + XLS_ASSIGN_OR_RETURN( + std::vector annotations, + table_.GetTypeAnnotationsForTypeVariable(*type_variable)); + if (annotations.empty()) { + return std::nullopt; + } + // If > 1, the caller is ignoring the "before imposing an annotation on the + // RHS" precondition. + CHECK_EQ(annotations.size(), 1); + if (const auto* result = dynamic_cast(annotations[0])) { + return result; + } + return std::nullopt; + } + Module& module_; InferenceTable& table_; const FileTable& file_table_; diff --git a/xls/dslx/type_system_v2/typecheck_module_v2_test.cc b/xls/dslx/type_system_v2/typecheck_module_v2_test.cc index 09a42a017a..5036397d8d 100644 --- a/xls/dslx/type_system_v2/typecheck_module_v2_test.cc +++ b/xls/dslx/type_system_v2/typecheck_module_v2_test.cc @@ -39,6 +39,14 @@ absl::StatusOr TypecheckV2(std::string_view program) { return Typecheck(absl::StrCat("#![feature(type_inference_v2)]\n\n", program)); } +// Verifies that a type info string contains the given node string and type +// string combo. +MATCHER_P2(HasNodeWithType, node, type, "") { + return ExplainMatchResult( + HasSubstr(absl::Substitute("node: `$0`, type: $1", node, type)), arg, + result_listener); +} + // Verifies the type produced by `TypecheckV2`, for the topmost node only, in a // simple AST (typically a one-liner). The `arg` is the DSLX code and `expected` // is the type string. @@ -55,9 +63,8 @@ MATCHER_P(TopNodeHasType, expected, "") { << type_info_string.status(); return false; } - bool matched = ExplainMatchResult( - HasSubstr(absl::Substitute("node: `$0`, type: $1", arg, expected)), - *type_info_string, result_listener); + bool matched = ExplainMatchResult(HasNodeWithType(arg, expected), + *type_info_string, result_listener); if (!matched) { *result_listener << "Type info: " << *type_info_string; } @@ -112,6 +119,29 @@ MATCHER_P(TypecheckFails, matcher, "") { result_listener); } +// Verifies that `TypecheckV2` succeeds for the given DSLX code and the +// resulting type info string satisfies the given `matcher`. +MATCHER_P(TypecheckSucceeds, matcher, "") { + absl::StatusOr result = TypecheckV2(arg); + if (!result.ok()) { + *result_listener << "Failed to typecheck: `" << arg + << "`; status: " << result.status(); + return false; + } + absl::StatusOr type_info_string = TypeInfoToString(result->tm); + if (!type_info_string.ok()) { + *result_listener << "Failed to convert type info to string; status: " + << type_info_string.status(); + return false; + } + bool matched = + ExplainMatchResult(matcher, *type_info_string, result_listener); + if (!matched) { + *result_listener << "Type info: " << *type_info_string; + } + return matched; +} + TEST(TypecheckV2Test, GlobalIntegerConstantWithNoTypeAnnotations) { EXPECT_THAT("const X = 3;", TypecheckFails(AllOf(HasSubstr("A variable or constant cannot be " @@ -144,15 +174,13 @@ TEST(TypecheckV2Test, GlobalIntegerConstantWithSignednessConflictFails) { } TEST(TypecheckV2Test, GlobalIntegerConstantEqualsAnotherConstant) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( const X = u2:3; const Y = X; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `const X = u2:3;`, type: uN[2]"), - HasSubstr("node: `const Y = X;`, type: uN[2]"))); +)", + TypecheckSucceeds(AllOf(HasNodeWithType("const X = u2:3;", "uN[2]"), + HasNodeWithType("const Y = X;", "uN[2]")))); } TEST(TypecheckV2Test, GlobalIntegerConstantEqualsSumOfLiterals) { @@ -176,54 +204,44 @@ TEST(TypecheckV2Test, } TEST(TypecheckV2Test, GlobalIntegerConstantEqualsSumOfConstantsAndLiterals) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = u32:3; const Y: u32 = 4; const Z = X + 1 + Y + 2; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = u32:3;`, type: uN[32]"), - HasSubstr("node: `const Y: u32 = 4;`, type: uN[32]"), - HasSubstr("node: `const Z = X + 1 + Y + 2;`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = u32:3;", "uN[32]"), + HasNodeWithType("const Y: u32 = 4;", "uN[32]"), + HasNodeWithType("const Z = X + 1 + Y + 2;", "uN[32]")))); } TEST(TypecheckV2Test, GlobalIntegerConstantEqualsSumOfAscendingAutoSizes) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = u32:1; const Z = 1 + 2 + 3 + 4 + X; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = u32:1;`, type: uN[32]"), - HasSubstr("node: `const Z = 1 + 2 + 3 + 4 + X;`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = u32:1;", "uN[32]"), + HasNodeWithType("const Z = 1 + 2 + 3 + 4 + X;", "uN[32]")))); } TEST(TypecheckV2Test, GlobalIntegerConstantWithCoercionOfAutoToSigned) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const Z = 1 + s2:1; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, AllOf(HasSubstr("node: `1`, type: sN[2]"), - HasSubstr("node: `Z`, type: sN[2]"))); +)", + TypecheckSucceeds(AllOf(HasNodeWithType("1", "sN[2]"), + HasNodeWithType("Z", "sN[2]")))); } TEST(TypecheckV2Test, GlobalIntegerConstantWithCoercionOfByAnotherAuto) { // Promote [auto u2, auto s2] to auto s3 due to the extra bit needed to fit // `2` in a signed value. The `s3:0` term then just avoids the prohibition on // a constant defined with a completely implicit type. - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const Z = 2 + -1 + s3:0; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, AllOf(HasSubstr("node: `2`, type: sN[3]"), - HasSubstr("node: `Z`, type: sN[3]"))); +)", + TypecheckSucceeds(AllOf(HasNodeWithType("2", "sN[3]"), + HasNodeWithType("Z", "sN[3]")))); } TEST(TypecheckV2Test, @@ -257,113 +275,92 @@ TEST(TypecheckV2Test, GlobalIntegerConstantWithTupleAnnotationOnLiteral) { TEST(TypecheckV2Test, GlobalIntegerConstantEqualsDifferenceOfConstantsAndLiterals) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = u32:3; const Y: u32 = 4; const Z = X - 1 - Y - 2; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = u32:3;`, type: uN[32]"), - HasSubstr("node: `const Y: u32 = 4;`, type: uN[32]"), - HasSubstr("node: `const Z = X - 1 - Y - 2;`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = u32:3;", "uN[32]"), + HasNodeWithType("const Y: u32 = 4;", "uN[32]"), + HasNodeWithType("const Z = X - 1 - Y - 2;", "uN[32]")))); } TEST(TypecheckV2Test, GlobalIntegerConstantEqualsProductOfConstantsAndLiterals) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = u32:3; const Y: u32 = 4; const Z = X * 1 * Y * 2; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = u32:3;`, type: uN[32]"), - HasSubstr("node: `const Y: u32 = 4;`, type: uN[32]"), - HasSubstr("node: `const Z = X * 1 * Y * 2;`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = u32:3;", "uN[32]"), + HasNodeWithType("const Y: u32 = 4;", "uN[32]"), + HasNodeWithType("const Z = X * 1 * Y * 2;", "uN[32]")))); } TEST(TypecheckV2Test, GlobalIntegerConstantEqualsQuotientOfConstantsAndLiterals) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = u32:3; const Y: u32 = 4; const Z = X / 1 / Y / 2; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = u32:3;`, type: uN[32]"), - HasSubstr("node: `const Y: u32 = 4;`, type: uN[32]"), - HasSubstr("node: `const Z = X / 1 / Y / 2;`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = u32:3;", "uN[32]"), + HasNodeWithType("const Y: u32 = 4;", "uN[32]"), + HasNodeWithType("const Z = X / 1 / Y / 2;", "uN[32]")))); } TEST(TypecheckV2Test, GlobalIntegerConstantEqualsBitwiseAndOfConstantsAndLiterals) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = u32:3; const Y: u32 = 4; const Z = X & 1 & Y & 2; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = u32:3;`, type: uN[32]"), - HasSubstr("node: `const Y: u32 = 4;`, type: uN[32]"), - HasSubstr("node: `const Z = X & 1 & Y & 2;`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = u32:3;", "uN[32]"), + HasNodeWithType("const Y: u32 = 4;", "uN[32]"), + HasNodeWithType("const Z = X & 1 & Y & 2;", "uN[32]")))); } TEST(TypecheckV2Test, GlobalIntegerConstantEqualsBitwiseOrOfConstantsAndLiterals) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = u32:3; const Y: u32 = 4; const Z = X | 1 | Y | 2; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = u32:3;`, type: uN[32]"), - HasSubstr("node: `const Y: u32 = 4;`, type: uN[32]"), - HasSubstr("node: `const Z = X | 1 | Y | 2;`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = u32:3;", "uN[32]"), + HasNodeWithType("const Y: u32 = 4;", "uN[32]"), + HasNodeWithType("const Z = X | 1 | Y | 2;", "uN[32]")))); } TEST(TypecheckV2Test, GlobalIntegerConstantEqualsBitwiseXorOfConstantsAndLiterals) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = u32:3; const Y: u32 = 4; const Z = X ^ 1 ^ Y ^ 2; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = u32:3;`, type: uN[32]"), - HasSubstr("node: `const Y: u32 = 4;`, type: uN[32]"), - HasSubstr("node: `const Z = X ^ 1 ^ Y ^ 2;`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = u32:3;", "uN[32]"), + HasNodeWithType("const Y: u32 = 4;", "uN[32]"), + HasNodeWithType("const Z = X ^ 1 ^ Y ^ 2;", "uN[32]")))); } TEST(TypecheckV2Test, GlobalIntegerConstantEqualsModOfConstantsAndLiterals) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = u32:3; const Y: u32 = 4; const Z = X % 1 % Y % 2; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = u32:3;`, type: uN[32]"), - HasSubstr("node: `const Y: u32 = 4;`, type: uN[32]"), - HasSubstr("node: `const Z = X % 1 % Y % 2;`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = u32:3;", "uN[32]"), + HasNodeWithType("const Y: u32 = 4;", "uN[32]"), + HasNodeWithType("const Z = X % 1 % Y % 2;", "uN[32]")))); } TEST(TypecheckV2Test, GlobalBoolConstantEqualsComparisonOfUntypedLiterals) { @@ -379,65 +376,53 @@ TEST(TypecheckV2Test, GlobalBoolConstantEqualsComparisonOfLiteralsWithOneType) { } TEST(TypecheckV2Test, GlobalBoolConstantEqualsComparisonOfVariables) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = u32:3; const Y = u32:4; const Z = Y >= X; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, HasSubstr("node: `Z`, type: uN[1]")); +)", + TypecheckSucceeds(HasNodeWithType("Z", "uN[1]"))); } TEST(TypecheckV2Test, GlobalBoolConstantEqualsComparisonOfExprs) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = s24:3; const Y = s24:4; const Z = (Y + X * 2) == (1 - Y); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `(Y + X * 2)`, type: sN[24]"), - HasSubstr("node: `(1 - Y)`, type: sN[24]"), - HasSubstr("node: `Z`, type: uN[1]"))); +)", + TypecheckSucceeds(AllOf(HasNodeWithType("(Y + X * 2)", "sN[24]"), + HasNodeWithType("(1 - Y)", "sN[24]"), + HasNodeWithType("Z", "uN[1]")))); } TEST(TypecheckV2Test, ComparisonAsFunctionArgument) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: bool) -> bool { a } const Y = foo(1 != 2); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, AllOf(HasSubstr("node: `1 != 2`, type: uN[1]"), - HasSubstr("node: `1`, type: uN[2]"), - HasSubstr("node: `2`, type: uN[2]"))); +)", + TypecheckSucceeds(AllOf(HasNodeWithType("1 != 2", "uN[1]"), + HasNodeWithType("1", "uN[2]"), + HasNodeWithType("2", "uN[2]")))); } TEST(TypecheckV2Test, ComparisonOfReturnValues) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: u32) -> u32 { a } const Y = foo(1) > foo(2); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `Y`, type: uN[1]"), - HasSubstr("node: `foo(1)`, type: uN[32]"), - HasSubstr("node: `foo(2)`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf(HasNodeWithType("Y", "uN[1]"), + HasNodeWithType("foo(1)", "uN[32]"), + HasNodeWithType("foo(2)", "uN[32]")))); } TEST(TypecheckV2Test, ComparisonAsParametricArgument) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: xN[S][32]) -> xN[S][32] { a } const Y = foo<{2 > 1}>(s32:5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, AllOf(HasSubstr("node: `Y`, type: sN[32]"), - HasSubstr("node: `2`, type: uN[2]"), - HasSubstr("node: `1`, type: uN[2]"))); +)", + TypecheckSucceeds(AllOf(HasNodeWithType("Y", "sN[32]"), + HasNodeWithType("2", "uN[2]"), + HasNodeWithType("1", "uN[2]")))); } TEST(TypecheckV2Test, ComparisonAsParametricArgumentWithConflictFails) { @@ -485,15 +470,13 @@ TEST(TypecheckV2Test, TEST(TypecheckV2Test, GlobalIntegerConstantEqualsAnotherConstantWithAnnotationOnName) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( const X: u32 = 3; const Y = X; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `const X: u32 = 3;`, type: uN[32]"), - HasSubstr("node: `const Y = X;`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf(HasNodeWithType("const X: u32 = 3;", "uN[32]"), + HasNodeWithType("const Y = X;", "uN[32]")))); } TEST(TypecheckV2Test, GlobalIntegerConstantRefWithSignednessConflictFails) { @@ -505,17 +488,15 @@ const Y:s32 = X; } TEST(TypecheckV2Test, GlobalIntegerConstantWithTwoLevelsOfReferences) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( const X: s20 = 3; const Y = X; const Z = Y; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `const X: s20 = 3;`, type: sN[20]"), - HasSubstr("node: `const Y = X;`, type: sN[20]"), - HasSubstr("node: `const Z = Y;`, type: sN[20]"))); +)", + TypecheckSucceeds(AllOf(HasNodeWithType("const X: s20 = 3;", "sN[20]"), + HasNodeWithType("const Y = X;", "sN[20]"), + HasNodeWithType("const Z = Y;", "sN[20]")))); } TEST(TypecheckV2Test, GlobalBoolConstantWithNoTypeAnnotations) { @@ -551,15 +532,13 @@ TEST(TypecheckV2Test, GlobalBoolConstantWithBitCountConflictFails) { } TEST(TypecheckV2Test, GlobalBoolConstantEqualsAnotherConstant) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( const X = true; const Y = X; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `const X = true;`, type: uN[1]"), - HasSubstr("node: `const Y = X;`, type: uN[1]"))); +)", + TypecheckSucceeds(AllOf(HasNodeWithType("const X = true;", "uN[1]"), + HasNodeWithType("const Y = X;", "uN[1]")))); } TEST(TypecheckV2Test, GlobalIntegerConstantEqualsBoolConstantFails) { @@ -593,7 +572,9 @@ TEST(TypecheckV2Test, GlobalTupleConstantWithAnnotatedIntegerLiterals) { TEST(TypecheckV2Test, GlobalTupleConstantAnnotatedWithBareIntegerLiterals) { EXPECT_THAT("const X: (u32, u32) = (1, 2);", - TopNodeHasType("(uN[32], uN[32])")); + TypecheckSucceeds(AllOf(HasNodeWithType("X", "(uN[32], uN[32])"), + HasNodeWithType("1", "uN[32]"), + HasNodeWithType("2", "uN[32]")))); } TEST(TypecheckV2Test, GlobalTupleConstantWithIntegerAnnotationFails) { @@ -602,8 +583,13 @@ TEST(TypecheckV2Test, GlobalTupleConstantWithIntegerAnnotationFails) { } TEST(TypecheckV2Test, GlobalTupleConstantWithNestedTuple) { - EXPECT_THAT("const X: (u32, (s24, u32)) = (1, (-3, 2));", - TopNodeHasType("(uN[32], (sN[24], uN[32])")); + EXPECT_THAT( + "const X: (u32, (s24, u32)) = (1, (-3, 2));", + TypecheckSucceeds(AllOf(HasNodeWithType("X", "(uN[32], (sN[24], uN[32])"), + HasNodeWithType("1", "uN[32]"), + HasNodeWithType("(-3, 2)", "(sN[24], uN[32])"), + HasNodeWithType("-3", "sN[24]"), + HasNodeWithType("2", "uN[32]")))); } TEST(TypecheckV2Test, GlobalTupleConstantWithNestedTupleAndTypeViolationFails) { @@ -617,28 +603,21 @@ TEST(TypecheckV2Test, GlobalTupleConstantWithNestedTupleAndTypeConflict) { } TEST(TypecheckV2Test, GlobalTupleConstantReferencingIntegerConstant) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X: u32 = 3; const Y = (X, s24:-1); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - HasSubstr("node: `const Y = (X, s24:-1);`, type: (uN[32], sN[24])")); +)", + TypecheckSucceeds(HasNodeWithType("const Y = (X, s24:-1);", + "(uN[32], sN[24])"))); } TEST(TypecheckV2Test, GlobalTupleConstantReferencingTupleConstant) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = (u32:3, s24:-1); const Y = (X, u32:4); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - HasSubstr( - "node: `const Y = (X, u32:4);`, type: ((uN[32], sN[24]), uN[32])")); +)", + TypecheckSucceeds(HasNodeWithType("const Y = (X, u32:4);", + "((uN[32], sN[24]), uN[32])"))); } TEST(TypecheckV2Test, GlobalTupleConstantWithArrays) { @@ -647,11 +626,17 @@ TEST(TypecheckV2Test, GlobalTupleConstantWithArrays) { } TEST(TypecheckV2Test, GlobalArrayConstantWithAnnotatedIntegerLiterals) { - EXPECT_THAT("const X = [u32:1, u32:2];", TopNodeHasType("uN[32][2]")); + EXPECT_THAT("const X = [u32:1, u32:2];", + TypecheckSucceeds(AllOf(HasNodeWithType("X", "uN[32][2]"), + HasNodeWithType("u32:1", "uN[32]"), + HasNodeWithType("u32:2", "uN[32]")))); } TEST(TypecheckV2Test, GlobalArrayConstantAnnotatedWithBareIntegerLiterals) { - EXPECT_THAT("const X: u32[2] = [1, 2];", TopNodeHasType("uN[32][2]")); + EXPECT_THAT("const X: u32[2] = [1, 3];", + TypecheckSucceeds(AllOf(HasNodeWithType("X", "uN[32][2]"), + HasNodeWithType("1", "uN[32]"), + HasNodeWithType("3", "uN[32]")))); } TEST(TypecheckV2Test, GlobalArrayConstantWithTuples) { @@ -661,7 +646,7 @@ TEST(TypecheckV2Test, GlobalArrayConstantWithTuples) { TEST(TypecheckV2Test, GlobalArrayConstantAnnotatedWithTooSmallSizeFails) { EXPECT_THAT("const X: u32[2] = [1, 2, 3];", - TypecheckFails(HasTypeMismatch("uN[2][3]", "u32[2]"))); + TypecheckFails(HasTypeMismatch("uN[32][3]", "u32[2]"))); } TEST(TypecheckV2Test, GlobalArrayConstantWithIntegerAnnotationFails) { @@ -676,29 +661,25 @@ TEST(TypecheckV2Test, GlobalArrayConstantWithTypeViolation) { TEST(TypecheckV2Test, GlobalArrayConstantWithTypeConflict) { EXPECT_THAT("const X: u32[2] = [s24:1, s24:2];", - TypecheckFails(HasSizeMismatch("sN[24]", "u32"))); + TypecheckFails(HasSizeMismatch("s24", "u32"))); } TEST(TypecheckV2Test, GlobalArrayConstantReferencingIntegerConstant) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( const X: u32 = 3; const Y = [X, X]; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const Y = [X, X];`, type: uN[32][2]")); +)", + TypecheckSucceeds(HasNodeWithType("const Y = [X, X];", "uN[32][2]"))); } TEST(TypecheckV2Test, GlobalArrayConstantReferencingArrayConstant) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( const X = [u32:3, u32:4]; const Y = [X, X]; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const Y = [X, X];`, type: uN[32][2][2]")); +)", + TypecheckSucceeds(HasNodeWithType("const Y = [X, X];", "uN[32][2][2]"))); } TEST(TypecheckV2Test, GlobalArrayConstantCombiningArrayAndIntegerFails) { @@ -707,12 +688,16 @@ TEST(TypecheckV2Test, GlobalArrayConstantCombiningArrayAndIntegerFails) { } TEST(TypecheckV2Test, GlobalArrayConstantWithEllipsis) { - EXPECT_THAT("const X: u32[5] = [3, 4, ...];", TopNodeHasType("uN[32][5]")); + EXPECT_THAT("const X: u32[5] = [3, 4, ...];", + TypecheckSucceeds(AllOf(HasNodeWithType("X", "uN[32][5]"), + HasNodeWithType("3", "uN[32]"), + HasNodeWithType("4", "uN[32]")))); } TEST(TypecheckV2Test, GlobalArrayConstantWithNestedEllipsis) { EXPECT_THAT("const X: u32[5][2] = [[5, ...], ...];", - TopNodeHasType("uN[32][5][2]")); + TypecheckSucceeds(AllOf(HasNodeWithType("X", "uN[32][5][2]"), + HasNodeWithType("5", "uN[32]")))); } TEST(TypecheckV2Test, GlobalArrayConstantWithEllipsisAndTooSmallSizeFails) { @@ -739,44 +724,39 @@ TEST(TypecheckV2Test, GlobalArrayConstantEmptyWithAnnotation) { } TEST(TypecheckV2Test, GlobalEmptyStructConstant) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( struct S {} const X = S { }; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, HasSubstr("node: `X`, type: S {}")); +)", + TypecheckSucceeds(HasNodeWithType("X", "S {}"))); } TEST(TypecheckV2Test, GlobalStructConstantWithIntegerMember) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( struct S { field: u32 } const X = S { field: 5 }; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `5`, type: uN[32]"), - HasSubstr("node: `X`, type: S { field: uN[32] }"))); +)", + TypecheckSucceeds(AllOf(HasNodeWithType("5", "uN[32]"), + HasNodeWithType("X", "S { field: uN[32] }")))); } TEST(TypecheckV2Test, GlobalStructConstantWithMultipleMembers) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( struct S { foo: u32, bar: sN[4][3], baz: (s24, bool) } const X = S { baz: (1, false), foo: 5, bar: [1, 2, 3] }; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `(1, false)`, type: (sN[24], uN[1])"), - HasSubstr("node: `5`, type: uN[32]"), - HasSubstr("node: `[1, 2, 3]`, type: sN[4][3]"), - HasSubstr("node: `X`, type: S { foo: uN[32], bar: " - "sN[4][3], baz: (sN[24], uN[1]) }"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("(1, false)", "(sN[24], uN[1])"), + HasNodeWithType("5", "uN[32]"), + HasNodeWithType("[1, 2, 3]", "sN[4][3]"), + HasNodeWithType( + "X", "S { foo: uN[32], bar: sN[4][3], baz: (sN[24], uN[1]) }")))); } TEST(TypecheckV2Test, @@ -834,16 +814,37 @@ const X = S { x: 1, y: u32:2}; } TEST(TypecheckV2Test, GlobalStructInstancePropagation) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( struct S { field: u32 } const X = S { field: 5 }; const Y = X; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `5`, type: uN[32]"), - HasSubstr("node: `Y`, type: S { field: uN[32] }"))); +)", + TypecheckSucceeds(AllOf(HasNodeWithType("5", "uN[32]"), + HasNodeWithType("Y", "S { field: uN[32] }")))); +} + +TEST(TypecheckV2Test, GlobalStructInstanceContainingStructInstance) { + EXPECT_THAT(R"( +struct S { field: u32 } +struct T { s: S } +const X = T { s: S { field: 5 } }; +)", + TypecheckSucceeds( + AllOf(HasNodeWithType("X", "T { s: S { field: uN[32] } }"), + HasNodeWithType("5", "uN[32]")))); +} + +TEST(TypecheckV2Test, GlobalStructInstanceContainingArray) { + EXPECT_THAT( + R"( +struct S { arr: u24[3] } +const X = S { arr: [10, 11, 12] }; +)", + TypecheckSucceeds(AllOf(HasNodeWithType("X", "S { arr: uN[24][3] }"), + HasNodeWithType("10", "uN[24]"), + HasNodeWithType("11", "uN[24]"), + HasNodeWithType("12", "uN[24]")))); } TEST(TypecheckV2Test, @@ -879,34 +880,28 @@ const X: S = u32:1; } TEST(TypecheckV2Test, StructFunctionArgument) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( struct S { field: u32 } fn f(s: S) {} fn g() { f(S { field: 2 }) } -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `2`, type: uN[32]"), - HasSubstr("node: `S { field: 2 }`, type: S { field: uN[32] }"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("2", "uN[32]"), + HasNodeWithType("S { field: 2 }", "S { field: uN[32] }")))); } TEST(TypecheckV2Test, StructFunctionReturnValue) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( struct S { field: u32 } fn f(value: u32) -> S { S { field: value } } const X = f(2); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = f(2);`, type: S { field: uN[32] }"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = f(2);", "S { field: uN[32] }")))); } TEST(TypecheckV2Test, InstantiationOfNonStruct) { @@ -917,91 +912,76 @@ TEST(TypecheckV2Test, InstantiationOfNonStruct) { } TEST(TypecheckV2Test, FunctionCallReturningNothing) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo() { () } const Y = foo(); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasOneLineBlockWithType("()", "()"), - HasSubstr("node: `const Y = foo();`, type: ()"))); +)", + TypecheckSucceeds(AllOf(HasOneLineBlockWithType("()", "()"), + HasNodeWithType("const Y = foo();", "()")))); } TEST(TypecheckV2Test, FunctionCallReturningUnitTupleExplicitly) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo() -> () { () } const Y = foo(); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasOneLineBlockWithType("()", "()"), - HasSubstr("node: `const Y = foo();`, type: ()"))); +)", + TypecheckSucceeds(AllOf(HasOneLineBlockWithType("()", "()"), + HasNodeWithType("const Y = foo();", "()")))); } TEST(TypecheckV2Test, FunctionCallReturningInteger) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo() -> u32 { 3 } const Y = foo(); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasOneLineBlockWithType("3", "uN[32]"), - HasSubstr("node: `const Y = foo();`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf(HasOneLineBlockWithType("3", "uN[32]"), + HasNodeWithType("const Y = foo();", "uN[32]")))); } TEST(TypecheckV2Test, FunctionCallReturningBool) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo() -> bool { true } const Y = foo(); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasOneLineBlockWithType("true", "uN[1]"), - HasSubstr("node: `const Y = foo();`, type: uN[1]"))); +)", + TypecheckSucceeds(AllOf(HasOneLineBlockWithType("true", "uN[1]"), + HasNodeWithType("const Y = foo();", "uN[1]")))); } TEST(TypecheckV2Test, FunctionCallReturningArray) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo() -> s8[3] { [1, 2, 3] } const Y = foo(); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasOneLineBlockWithType("[1, 2, 3]", "sN[8][3]"), - HasSubstr("node: `const Y = foo();`, type: sN[8][3]"))); +)", + TypecheckSucceeds( + AllOf(HasOneLineBlockWithType("[1, 2, 3]", "sN[8][3]"), + HasNodeWithType("const Y = foo();", "sN[8][3]")))); } TEST(TypecheckV2Test, FunctionCallReturningTuple) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo() -> (s8, (u32, u24)) { (1, (2, 3)) } const Y = foo(); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasOneLineBlockWithType("(1, (2, 3))", "(sN[8], (uN[32], uN[24]))"), - HasSubstr( - "node: `const Y = foo();`, type: (sN[8], (uN[32], uN[24]))"))); +)", + TypecheckSucceeds(AllOf( + HasOneLineBlockWithType("(1, (2, 3))", "(sN[8], (uN[32], uN[24]))"), + HasNodeWithType("const Y = foo();", "(sN[8], (uN[32], uN[24]))")))); } TEST(TypecheckV2Test, FunctionCallReturningFunctionCall) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn bar() -> s32 { 123 } fn foo() -> s32 { bar() } const Y = foo(); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasOneLineBlockWithType("123", "sN[32]"), - HasOneLineBlockWithType("bar()", "sN[32]"), - HasSubstr("node: `const Y = foo();`, type: sN[32]"))); +)", + TypecheckSucceeds(AllOf(HasOneLineBlockWithType("123", "sN[32]"), + HasOneLineBlockWithType("bar()", "sN[32]"), + HasNodeWithType("const Y = foo();", "sN[32]")))); } TEST(TypecheckV2Test, FunctionReturningMismatchingIntegerAutoTypeFails) { @@ -1040,82 +1020,67 @@ const Y = foo(); } TEST(TypecheckV2Test, FunctionCallReturningPassedInInteger) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo(a: u32) -> u32 { a } const Y = foo(4); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasOneLineBlockWithType("a", "uN[32]"), - HasSubstr("node: `const Y = foo(4);`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf(HasOneLineBlockWithType("a", "uN[32]"), + HasNodeWithType("const Y = foo(4);", "uN[32]")))); } TEST(TypecheckV2Test, FunctionCallReturningPassedInTuple) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo(a: (u32, s4)) -> (u32, s4) { a } const Y = foo((4, -1)); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf( +)", + TypecheckSucceeds(AllOf( HasOneLineBlockWithType("a", "(uN[32], sN[4])"), - HasSubstr("node: `const Y = foo((4, -1));`, type: (uN[32], sN[4])"))); + HasNodeWithType("const Y = foo((4, -1));", "(uN[32], sN[4])")))); } TEST(TypecheckV2Test, FunctionCallReturningPassedInArray) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: u32[2]) -> u32[2] { a } const Y = foo([4, 5]); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasOneLineBlockWithType("a", "uN[32][2]"), - HasSubstr("node: `const Y = foo([4, 5]);`, type: uN[32][2]"))); +)", + TypecheckSucceeds(AllOf( + HasOneLineBlockWithType("a", "uN[32][2]"), + HasNodeWithType("const Y = foo([4, 5]);", "uN[32][2]")))); } TEST(TypecheckV2Test, FunctionCallReturningSumOfPassedInIntegers) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: u32, b: u32) -> u32 { a + b } const Y = foo(4, 5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasOneLineBlockWithType("a + b", "uN[32]"), - HasSubstr("node: `const Y = foo(4, 5);`, type: uN[32]"))); +)", + TypecheckSucceeds( + AllOf(HasOneLineBlockWithType("a + b", "uN[32]"), + HasNodeWithType("const Y = foo(4, 5);", "uN[32]")))); } TEST(TypecheckV2Test, FunctionCallPassingInFunctionCalls) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo(a: u32, b: u32) -> u32 { a + b } const Y = foo(foo(3, 2), foo(4, 5)); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasOneLineBlockWithType("a + b", "uN[32]"), - HasSubstr( - "node: `const Y = foo(foo(3, 2), foo(4, 5));`, type: uN[32]"))); +)", + TypecheckSucceeds(AllOf( + HasOneLineBlockWithType("a + b", "uN[32]"), + HasNodeWithType("const Y = foo(foo(3, 2), foo(4, 5));", "uN[32]")))); } TEST(TypecheckV2Test, FunctionCallPassingInSum) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X: u32 = 4; const Z: u32 = 5; fn foo(a: u32) -> u32 { a } const Y = foo(X + Z); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasOneLineBlockWithType("a", "uN[32]"), - HasSubstr("node: `const Y = foo(X + Z);`, type: uN[32]"))); +)", + TypecheckSucceeds( + AllOf(HasOneLineBlockWithType("a", "uN[32]"), + HasNodeWithType("const Y = foo(X + Z);", "uN[32]")))); } TEST(TypecheckV2Test, FunctionCallPassingInTooManyArgumentsFails) { @@ -1193,83 +1158,69 @@ const X = foo<3, 4>(); } TEST(TypecheckV2Test, ParametricFunctionReturningIntegerParameter) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo() -> u32 { N } const X = foo<3>(); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `const X = foo<3>();`, type: uN[32]"))); +)", + TypecheckSucceeds( + AllOf(HasNodeWithType("const X = foo<3>();", "uN[32]")))); } TEST(TypecheckV2Test, ParametricFunctionReturningIntegerOfParameterSize) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo() -> uN[N] { 5 } const X = foo<16>(); const Y = foo<17>(); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `const X = foo<16>();`, type: uN[16]"), - HasSubstr("node: `const Y = foo<17>();`, type: uN[17]"))); +)", + TypecheckSucceeds( + AllOf(HasNodeWithType("const X = foo<16>();", "uN[16]"), + HasNodeWithType("const Y = foo<17>();", "uN[17]")))); } TEST(TypecheckV2Test, ParametricFunctionReturningIntegerOfParameterSignedness) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo() -> xN[S][32] { 5 } const X = foo(); const Y = foo(); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `const X = foo();`, type: uN[32]"), - HasSubstr("node: `const Y = foo();`, type: sN[32]"))); +)", + TypecheckSucceeds( + AllOf(HasNodeWithType("const X = foo();", "uN[32]"), + HasNodeWithType("const Y = foo();", "sN[32]")))); } TEST(TypecheckV2Test, ParametricFunctionReturningIntegerOfParameterSignednessAndSize) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo() -> xN[S][N] { 5 } const X = foo(); const Y = foo(); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = foo();`, type: uN[10]"), - HasSubstr("node: `const Y = foo();`, type: sN[11]"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = foo();", "uN[10]"), + HasNodeWithType("const Y = foo();", "sN[11]")))); } TEST(TypecheckV2Test, ParametricFunctionTakingIntegerOfParameterizedSize) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: uN[N]) -> uN[N] { a } const X = foo<10>(u10:5); const Y = foo<11>(u11:5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = foo<10>(u10:5);`, type: uN[10]"), - HasSubstr("node: `const Y = foo<11>(u11:5);`, type: uN[11]"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = foo<10>(u10:5);", "uN[10]"), + HasNodeWithType("const Y = foo<11>(u11:5);", "uN[11]")))); } TEST(TypecheckV2Test, ParametricFunctionTakingIntegerOfImplicitParameterizedSize) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: uN[N]) -> uN[N] { a } const X = foo(u10:5); const Y = foo(u11:5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `const X = foo(u10:5);`, type: uN[10]"), - HasSubstr("node: `const Y = foo(u11:5);`, type: uN[11]"))); +)", + TypecheckSucceeds( + AllOf(HasNodeWithType("const X = foo(u10:5);", "uN[10]"), + HasNodeWithType("const Y = foo(u11:5);", "uN[11]")))); } TEST(TypecheckV2Test, ParametricFunctionWithNonInferrableParametric) { @@ -1282,97 +1233,81 @@ const X = foo(u10:5); TEST(TypecheckV2Test, ParametricFunctionTakingIntegerOfParameterizedSignedness) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: xN[S][32]) -> xN[S][32] { a } const X = foo(u32:5); const Y = foo(s32:5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = foo(u32:5);`, type: uN[32]"), - HasSubstr("node: `const Y = foo(s32:5);`, type: sN[32]"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = foo(u32:5);", "uN[32]"), + HasNodeWithType("const Y = foo(s32:5);", "sN[32]")))); } TEST(TypecheckV2Test, ParametricFunctionTakingIntegerOfImplicitParameterizedSignedness) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: xN[S][32]) -> xN[S][32] { a } const X = foo(u32:5); const Y = foo(s32:5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `const X = foo(u32:5);`, type: uN[32]"), - HasSubstr("node: `const Y = foo(s32:5);`, type: sN[32]"))); +)", + TypecheckSucceeds( + AllOf(HasNodeWithType("const X = foo(u32:5);", "uN[32]"), + HasNodeWithType("const Y = foo(s32:5);", "sN[32]")))); } TEST(TypecheckV2Test, ParametricFunctionTakingIntegerOfParameterizedSignednessAndSize) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo(a: xN[S][N]) -> xN[S][N] { a } const X = foo(u10:5); const Y = foo(s11:5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf( - HasSubstr("node: `const X = foo(u10:5);`, type: uN[10]"), - HasSubstr("node: `const Y = foo(s11:5);`, type: sN[11]"))); +)", + TypecheckSucceeds( + AllOf(HasNodeWithType("const X = foo(u10:5);", "uN[10]"), + HasNodeWithType("const Y = foo(s11:5);", "sN[11]")))); } TEST(TypecheckV2Test, ParametricFunctionTakingIntegerOfImplicitParameterizedSignednessAndSize) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: xN[S][N]) -> xN[S][N] { a } const X = foo(u10:5); const Y = foo(s11:5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - AllOf(HasSubstr("node: `const X = foo(u10:5);`, type: uN[10]"), - HasSubstr("node: `const Y = foo(s11:5);`, type: sN[11]"))); +)", + TypecheckSucceeds( + AllOf(HasNodeWithType("const X = foo(u10:5);", "uN[10]"), + HasNodeWithType("const Y = foo(s11:5);", "sN[11]")))); } TEST(TypecheckV2Test, ParametricFunctionTakingIntegerOfDefaultParameterizedSize) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo(a: uN[N]) -> uN[N] { a } const X = foo(u10:5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const X = foo(u10:5);`, type: uN[10]")); +)", + TypecheckSucceeds(HasNodeWithType("const X = foo(u10:5);", "uN[10]"))); } TEST(TypecheckV2Test, ParametricFunctionTakingIntegerOfOverriddenDefaultParameterizedSize) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: uN[N]) -> uN[N] { a } const X = foo<11>(u11:5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const X = foo<11>(u11:5);`, type: uN[11]")); +)", + TypecheckSucceeds( + HasNodeWithType("const X = foo<11>(u11:5);", "uN[11]"))); } TEST(TypecheckV2Test, ParametricFunctionTakingIntegerWithDependentDefaultParametric) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: uN[N]) -> uN[N] { a } const X = foo<11>(u12:5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const X = foo<11>(u12:5);`, type: uN[12]")); +)", + TypecheckSucceeds( + HasNodeWithType("const X = foo<11>(u12:5);", "uN[12]"))); } TEST(TypecheckV2Test, ParametricFunctionWithDefaultImplicitlyOverriddenFails) { @@ -1387,91 +1322,83 @@ const X = foo<11>(u20:5); TEST(TypecheckV2Test, ParametricFunctionWithDefaultDependingOnInferredParametric) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo(a: uN[M]) -> uN[M] { a } const X = foo(u10:5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const X = foo(u10:5);`, type: uN[10]")); +)", + TypecheckSucceeds(HasNodeWithType("const X = foo(u10:5);", "uN[10]"))); } TEST(TypecheckV2Test, ParametricFunctionWithInferredThenDefaultThenInferredParametric) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo(x: uN[A], y: uN[C][B]) -> uN[A] { x } const X = foo(u3:1, [u24:6, u24:7, u24:8, u24:9]); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const X = foo(u3:1, [u24:6, u24:7, u24:8, " - "u24:9]);`, type: uN[3]")); +)", + TypecheckSucceeds(HasNodeWithType( + "const X = foo(u3:1, [u24:6, u24:7, u24:8, u24:9]);", "uN[3]"))); } TEST(TypecheckV2Test, ParametricFunctionTakingIntegerOfParameterizedSignednessAndSizeWithSum) { // The point here is to make sure that the uN[N] type annotation being // propagated onto a complex subtree in global scope is correctly dealt with. - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = u32:3; const Y = u32:4; fn foo(a: uN[N]) -> uN[N] { a } const Z = foo<32>(X + Y + X + 50); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - HasSubstr("node: `const Z = foo<32>(X + Y + X + 50);`, type: uN[32]")); +)", + TypecheckSucceeds(HasNodeWithType( + "const Z = foo<32>(X + Y + X + 50);", "uN[32]"))); } TEST(TypecheckV2Test, ParametricFunctionTakingIntegerOfImplicitSignednessAndSizeWithSum) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = u32:3; const Y = u32:4; fn foo(a: uN[N]) -> uN[N] { a } const Z = foo(X + Y + X + 50); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - HasSubstr("node: `const Z = foo(X + Y + X + 50);`, type: uN[32]")); +)", + TypecheckSucceeds( + HasNodeWithType("const Z = foo(X + Y + X + 50);", "uN[32]"))); } TEST(TypecheckV2Test, ParametricFunctionTakingArrayOfParameterizedSize) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( -fn foo(a: u32[N]) -> u32[N] { a } -const X = foo<3>([1, 2, 3]); -const Y = foo<4>([1, 2, 3, 4]); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = foo<3>([1, 2, 3]);`, type: uN[32][3]"), - HasSubstr( - "node: `const Y = foo<4>([1, 2, 3, 4]);`, type: uN[32][4]"))); + R"( +fn foo(a: u32[N]) -> u32[N] { a } +const X = foo<3>([5, 6, 7]); +const Y = foo<4>([8, 9, 10, 11]); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = foo<3>([5, 6, 7]);", "uN[32][3]"), + HasNodeWithType("const Y = foo<4>([8, 9, 10, 11]);", "uN[32][4]"), + HasNodeWithType("5", "uN[32]"), HasNodeWithType("6", "uN[32]"), + HasNodeWithType("7", "uN[32]"), HasNodeWithType("8", "uN[32]"), + HasNodeWithType("9", "uN[32]"), HasNodeWithType("10", "uN[32]"), + HasNodeWithType("11", "uN[32]")))); } TEST(TypecheckV2Test, ParametricFunctionTakingArrayOfImplicitSize) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo(a: u32[N]) -> u32[N] { a } const X = foo([1, 2, 3]); -const Y = foo([1, 2, 3, 4]); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf( - HasSubstr("node: `const X = foo([1, 2, 3]);`, type: uN[32][3]"), - HasSubstr("node: `const Y = foo([1, 2, 3, 4]);`, type: uN[32][4]"))); +const Y = foo([4, 5, 6, 7]); +)", + TypecheckSucceeds( + AllOf(HasNodeWithType("const X = foo([1, 2, 3]);", "uN[32][3]"), + HasNodeWithType("const Y = foo([4, 5, 6, 7]);", "uN[32][4]"), + HasNodeWithType("1", "uN[32]"), HasNodeWithType("2", "uN[32]"), + HasNodeWithType("3", "uN[32]"), HasNodeWithType("4", "uN[32]"), + HasNodeWithType("5", "uN[32]"), HasNodeWithType("6", "uN[32]"), + HasNodeWithType("7", "uN[32]")))); } TEST(TypecheckV2Test, @@ -1501,187 +1428,148 @@ const X = foo<3>([u32:1, u32:2, u32:3, u32:4]); } TEST(TypecheckV2Test, ParametricFunctionCallingAnotherParametricFunction) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn bar(a: uN[A]) -> uN[A] { a + 1 } fn foo(a: uN[A]) -> uN[B] { bar(2) } const X = foo<24, 23>(4); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const X = foo<24, 23>(4);`, type: uN[23]")); +)", + TypecheckSucceeds( + HasNodeWithType("const X = foo<24, 23>(4);", "uN[23]"))); } TEST(TypecheckV2Test, ParametricFunctionImplicitParameterPropagation) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn bar(a: uN[A], b: uN[B]) -> uN[A] { a + 1 } fn foo(a: uN[A], b: uN[B]) -> uN[B] { bar(b, a) } const X = foo(u23:4, u17:5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const X = foo(u23:4, u17:5);`, type: uN[17]")); +)", + TypecheckSucceeds( + HasNodeWithType("const X = foo(u23:4, u17:5);", "uN[17]"))); } TEST(TypecheckV2Test, ParametricFunctionImplicitParameterExplicitPropagation) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn bar(a: uN[A], b: uN[B]) -> uN[A] { a + 1 } fn foo(a: uN[A], b: uN[B]) -> uN[B] { bar(b, a) } const X = foo(u23:4, u17:5); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const X = foo(u23:4, u17:5);`, type: uN[17]")); +)", + TypecheckSucceeds( + HasNodeWithType("const X = foo(u23:4, u17:5);", "uN[17]"))); } TEST(TypecheckV2Test, ParametricFunctionInvocationNesting) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: uN[N]) -> uN[N] { a + 1 } const X = foo<24>(foo<24>(4) + foo<24>(5)); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - HasSubstr( - "node: `const X = foo<24>(foo<24>(4) + foo<24>(5));`, type: uN[24]")); +)", + TypecheckSucceeds(HasNodeWithType( + "const X = foo<24>(foo<24>(4) + foo<24>(5));", "uN[24]"))); } TEST(TypecheckV2Test, ParametricFunctionImplicitInvocationNesting) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: uN[N]) -> uN[N] { a + 1 } const X = foo(foo(u24:4) + foo(u24:5)); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - HasSubstr( - "node: `const X = foo(foo(u24:4) + foo(u24:5));`, type: uN[24]")); +)", + TypecheckSucceeds(HasNodeWithType( + "const X = foo(foo(u24:4) + foo(u24:5));", "uN[24]"))); } TEST(TypecheckV2Test, ParametricFunctionImplicitInvocationNestingWithExplicitOuter) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: uN[N]) -> uN[N] { a + 1 } const X = foo<24>(foo(u24:4 + foo(u24:6)) + foo(u24:5)); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const X = foo<24>(foo(u24:4 + foo(u24:6)) + " - "foo(u24:5));`, type: uN[24]")); +)", + TypecheckSucceeds(HasNodeWithType( + "const X = foo<24>(foo(u24:4 + foo(u24:6)) + foo(u24:5));", + "uN[24]"))); } TEST(TypecheckV2Test, ParametricFunctionImplicitInvocationNestingWithExplicitInner) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: uN[N]) -> uN[N] { a + 1 } const X = foo(foo<24>(4) + foo<24>(5)); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - HasSubstr( - "node: `const X = foo(foo<24>(4) + foo<24>(5));`, type: uN[24]")); +)", + TypecheckSucceeds(HasNodeWithType( + "const X = foo(foo<24>(4) + foo<24>(5));", "uN[24]"))); } TEST(TypecheckV2Test, ParametricFunctionUsingGlobalConstantInParametricDefault) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( const X = u32:3; fn foo(a: uN[N]) -> uN[N] { a } const Z = foo<12>(u15:1); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const Z = foo<12>(u15:1);`, type: uN[15]")); +)", + TypecheckSucceeds( + HasNodeWithType("const Z = foo<12>(u15:1);", "uN[15]"))); } TEST(TypecheckV2Test, ParametricFunctionCallUsingGlobalConstantInParametricArgument) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT( + R"( fn foo(a: uN[N]) -> uN[N] { a } const X = u32:3; const Z = foo(u3:1); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const Z = foo(u3:1);`, type: uN[3]")); +)", + TypecheckSucceeds(HasNodeWithType("const Z = foo(u3:1);", "uN[3]"))); } TEST(TypecheckV2Test, ParametricFunctionCallUsingGlobalConstantInImplicitParametricArgument) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: uN[N]) -> uN[N] { a } const X = u3:1; const Z = foo(X); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const Z = foo(X);`, type: uN[3]")); +)", + TypecheckSucceeds(HasNodeWithType("const Z = foo(X);", "uN[3]"))); } TEST(TypecheckV2Test, ParametricFunctionCallFollowedByTypePropagation) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: uN[N]) -> uN[N] { a } const Y = foo<15>(u15:1); const Z = Y + 1; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const Z = Y + 1;`, type: uN[15]")); +)", + TypecheckSucceeds(HasNodeWithType("const Z = Y + 1;", "uN[15]"))); } TEST(TypecheckV2Test, ParametricFunctionCallWithImplicitParameterFollowedByTypePropagation) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: uN[N]) -> uN[N] { a } const Y = foo(u15:1); const Z = Y + 1; -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT(type_info_string, - HasSubstr("node: `const Z = Y + 1;`, type: uN[15]")); +)", + TypecheckSucceeds(HasNodeWithType("const Z = Y + 1;", "uN[15]"))); } TEST(TypecheckV2Test, GlobalConstantUsingParametricFunction) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: uN[N]) -> uN[N] { a } const X = foo<32>(u32:3); const Y = foo(u3:1); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = foo<32>(u32:3);`, type: uN[32]"), - HasSubstr("node: `const Y = foo(u3:1);`, type: uN[3]"))); +)", + TypecheckSucceeds( + AllOf(HasNodeWithType("const X = foo<32>(u32:3);", "uN[32]"), + HasNodeWithType("const Y = foo(u3:1);", "uN[3]")))); } TEST(TypecheckV2Test, GlobalConstantUsingAndUsedByParametricFunction) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( + EXPECT_THAT(R"( fn foo(a: uN[N]) -> uN[N] { a } const X = foo<32>(u32:3); const Y = foo(u3:1); fn bar(a: uN[N]) -> uN[N] { a + Y + foo<3>(Y) } const Z = bar(u3:1 + Y); -)")); - XLS_ASSERT_OK_AND_ASSIGN(std::string type_info_string, - TypeInfoToString(result.tm)); - EXPECT_THAT( - type_info_string, - AllOf(HasSubstr("node: `const X = foo<32>(u32:3);`, type: uN[32]"), - HasSubstr("node: `const Y = foo(u3:1);`, type: uN[3]"), - HasSubstr("node: `const Z = bar(u3:1 + Y);`, type: uN[3]"))); +)", + TypecheckSucceeds(AllOf( + HasNodeWithType("const X = foo<32>(u32:3);", "uN[32]"), + HasNodeWithType("const Y = foo(u3:1);", "uN[3]"), + HasNodeWithType("const Z = bar(u3:1 + Y);", "uN[3]")))); } } // namespace