diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index 707e0e86d020..aa2ea18ace01 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -104,7 +104,13 @@ TypeResolution::typesAreCompatible (AST::Type *lhs, AST::Type *rhs, } AST::Type *val = NULL; - return scope.LookupType (lhsTypeStr, &val); + if (!scope.LookupType (lhsTypeStr, &val)) + { + rust_error_at (locus, "Unknown type: %s", lhsTypeStr.c_str ()); + return false; + } + + return true; } bool @@ -395,19 +401,112 @@ TypeResolution::visit (AST::CompoundAssignmentExpr &expr) void TypeResolution::visit (AST::GroupedExpr &expr) {} -// void TypeResolution::visit(ArrayElems& elems) {} + void TypeResolution::visit (AST::ArrayElemsValues &elems) -{} +{ + // we need to generate the AST::ArrayType for this array init_expression + // we can get the size via get_num_values() but we need to ensure each element + // are type compatible + + bool failed = false; + AST::Type *last_inferred_type = nullptr; + elems.iterate ([&] (AST::Expr *expr) mutable -> bool { + size_t before; + before = typeBuffer.size (); + expr->accept_vis (*this); + if (typeBuffer.size () <= before) + { + rust_error_at (expr->get_locus_slow (), + "unable to determine element type"); + return false; + } + + AST::Type *inferedType = typeBuffer.back (); + typeBuffer.pop_back (); + + if (last_inferred_type == nullptr) + last_inferred_type = inferedType; + else + { + if (!typesAreCompatible (last_inferred_type, inferedType, + expr->get_locus_slow ())) + { + failed = true; + return false; + } + } + + return true; + }); + + // nothing to do when its failed + if (failed) + return; + + auto capacity + = new AST::LiteralExpr (std::to_string (elems.get_num_values ()), + AST::Literal::INT, + Linemap::predeclared_location ()); + auto arrayType = new AST::ArrayType (last_inferred_type->clone_type (), + std::unique_ptr (capacity), + Linemap::predeclared_location ()); + typeBuffer.push_back (arrayType); +} + void TypeResolution::visit (AST::ArrayElemsCopied &elems) -{} +{ + printf ("ArrayElemsCopied: %s\n", elems.as_string ().c_str ()); +} + void TypeResolution::visit (AST::ArrayExpr &expr) -{} +{ + auto elements = expr.get_internal_elements (); + elements->accept_vis (*this); +} + void TypeResolution::visit (AST::ArrayIndexExpr &expr) -{} +{ + printf ("ArrayIndexExpr: %s\n", expr.as_string ().c_str ()); + + auto before = typeBuffer.size (); + expr.get_array_expr ()->accept_vis (*this); + if (typeBuffer.size () <= before) + { + rust_error_at (expr.get_locus_slow (), + "unable to determine type for array index expression"); + return; + } + AST::Type *array_expr_type = typeBuffer.back (); + typeBuffer.pop_back (); + + before = typeBuffer.size (); + expr.get_index_expr ()->accept_vis (*this); + if (typeBuffer.size () <= before) + { + rust_error_at (expr.get_index_expr ()->get_locus_slow (), + "unable to determine type for index expression"); + return; + } + + AST::Type *array_index_type = typeBuffer.back (); + typeBuffer.pop_back (); + + printf ("Array expr type %s array index expr type: [%s]\n", + array_expr_type->as_string ().c_str (), + array_index_type->as_string ().c_str ()); + + // the the element type from the array_expr_type and it _must_ be an array + // TODO + + // check the index_type should be an i32 which should really be + // more permissive + // TODO +} + void TypeResolution::visit (AST::TupleExpr &expr) {} @@ -1015,7 +1114,7 @@ TypeResolution::visit (AST::LetStmt &stmt) return; } - AST::Type *inferedType = NULL; + AST::Type *inferedType = nullptr; if (stmt.has_init_expr ()) { auto before = typeBuffer.size (); @@ -1048,6 +1147,51 @@ TypeResolution::visit (AST::LetStmt &stmt) return; } } + else if (stmt.has_type ()) + { + auto before = typeComparisonBuffer.size (); + stmt.type->accept_vis (*this); + if (typeComparisonBuffer.size () <= before) + { + rust_error_at (stmt.locus, "failed to understand type for lhs"); + return; + } + auto typeString = typeComparisonBuffer.back (); + typeComparisonBuffer.pop_back (); + + AST::Type *val = NULL; + if (!scope.LookupType (typeString, &val)) + { + rust_error_at (stmt.locus, "LetStmt has unknown type: %s", + stmt.type->as_string ().c_str ()); + return; + } + } + else if (inferedType != nullptr) + { + auto before = typeComparisonBuffer.size (); + inferedType->accept_vis (*this); + if (typeComparisonBuffer.size () <= before) + { + rust_error_at (stmt.locus, "failed to understand type for lhs"); + return; + } + auto typeString = typeComparisonBuffer.back (); + typeComparisonBuffer.pop_back (); + + AST::Type *val = NULL; + if (!scope.LookupType (typeString, &val)) + { + rust_error_at (stmt.locus, "Inferred unknown type: %s", + inferedType->as_string ().c_str ()); + return; + } + } + else + { + rust_fatal_error (stmt.locus, "Failed to determine any type for LetStmt"); + return; + } // ensure the decl has the type set for compilation later on if (!stmt.has_type ()) @@ -1115,9 +1259,13 @@ TypeResolution::visit (AST::RawPointerType &type) void TypeResolution::visit (AST::ReferenceType &type) {} + void TypeResolution::visit (AST::ArrayType &type) -{} +{ + typeComparisonBuffer.push_back (type.get_element_type ()->as_string ()); +} + void TypeResolution::visit (AST::SliceType &type) {} diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index fd6913f31e2c..d3e7cbdc86ae 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -928,6 +928,17 @@ class ArrayElemsValues : public ArrayElems void accept_vis (ASTVisitor &vis) override; + size_t get_num_values () const { return values.size (); } + + void iterate (std::function cb) + { + for (auto it = values.begin (); it != values.end (); it++) + { + if (!cb ((*it).get ())) + return; + } + } + protected: ArrayElemsValues *clone_array_elems_impl () const override { @@ -1037,6 +1048,8 @@ class ArrayExpr : public ExprWithoutBlock void accept_vis (ASTVisitor &vis) override; + ArrayElems *get_internal_elements () { return internal_elements.get (); }; + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1100,6 +1113,9 @@ class ArrayIndexExpr : public ExprWithoutBlock void accept_vis (ASTVisitor &vis) override; + Expr *get_array_expr () { return array_expr.get (); } + Expr *get_index_expr () { return index_expr.get (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index b396a44edb4a..301b66472db4 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -60,7 +60,7 @@ class ImplTraitType : public Type { // TypeParamBounds type_param_bounds; // inlined form - std::vector> type_param_bounds; + std::vector > type_param_bounds; Location locus; @@ -74,7 +74,7 @@ class ImplTraitType : public Type public: ImplTraitType ( - std::vector> type_param_bounds, + std::vector > type_param_bounds, Location locus) : type_param_bounds (std::move (type_param_bounds)), locus (locus) {} @@ -115,7 +115,7 @@ class TraitObjectType : public Type { bool has_dyn; // TypeParamBounds type_param_bounds; - std::vector> + std::vector > type_param_bounds; // inlined form Location locus; @@ -130,7 +130,7 @@ class TraitObjectType : public Type public: TraitObjectType ( - std::vector> type_param_bounds, + std::vector > type_param_bounds, Location locus, bool is_dyn_dispatch = false) : has_dyn (is_dyn_dispatch), type_param_bounds (std::move (type_param_bounds)), locus (locus) @@ -318,14 +318,14 @@ class TypePath; // definition moved to "rust-path.h" * specific order */ class TupleType : public TypeNoBounds { - std::vector> elems; + std::vector > elems; Location locus; public: // Returns whether the tuple type is the unit type, i.e. has no elements. bool is_unit_type () const { return elems.empty (); } - TupleType (std::vector> elems, Location locus) + TupleType (std::vector > elems, Location locus) : elems (std::move (elems)), locus (locus) {} @@ -574,6 +574,8 @@ class ArrayType : public TypeNoBounds void accept_vis (ASTVisitor &vis) override; + Type *get_element_type () { return elem_type.get (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */